diff --git a/modular_doppler/modular_vending/code/tg_vendors/sectech.dm b/modular_doppler/modular_vending/code/tg_vendors/sectech.dm
index fa3c8465a94de1..671d547a997f78 100644
--- a/modular_doppler/modular_vending/code/tg_vendors/sectech.dm
+++ b/modular_doppler/modular_vending/code/tg_vendors/sectech.dm
@@ -24,10 +24,14 @@
/obj/item/ammo_casing/alacran_dart/rootbeer = 3,
/obj/item/storage/box/alacran_dart = 3,
/obj/item/storage/box/alacran_dart/piercing = 3,
+ /obj/item/storage/toolbox/guncase/modular/sportsco_large_case = 2,
+ /obj/item/storage/toolbox/guncase/modular/sportsco_small_case = 2,
+ /obj/item/book/granter/tactical_gun_tosser = 1,
)
premium_doppler = list(
/obj/item/gun/ballistic/automatic/schiebenmaschine = 30,
/obj/item/gun/ballistic/avispa_stingball_shooter = 5,
+ /obj/item/gun/ballistic/alacran = 5,
/obj/item/knife/combat/survival = 3,
/obj/item/reagent_containers/cup/soda_cans/monkey_energy = 5,
/obj/item/reagent_containers/cup/soda_cans/grey_bull = 5,
diff --git a/modular_doppler/modular_weapons/code/cybersun_lasers/laser_guns.dm b/modular_doppler/modular_weapons/code/cybersun_lasers/laser_guns.dm
new file mode 100644
index 00000000000000..0c16c6a6ed63bd
--- /dev/null
+++ b/modular_doppler/modular_weapons/code/cybersun_lasers/laser_guns.dm
@@ -0,0 +1,340 @@
+/// File location for the long gun's speech
+#define LONG_MOD_LASER_SPEECH "~doppler/long_modular_laser.json"
+/// File location for the short gun's speech
+#define SHORT_MOD_LASER_SPEECH "~doppler/short_modular_laser.json"
+/// How long the gun should wait between speaking to lessen spam
+#define MOD_LASER_SPEECH_COOLDOWN 2 SECONDS
+/// What color is the default kill mode for these guns, used to make sure the chat colors are right at roundstart
+#define DEFAULT_RUNECHAT_GUN_COLOR "#cd4456"
+
+// Modular energy weapons, laser guns that can transform into different variants after a few seconds of waiting and animation
+// Long version, takes both hands to use and doesn't fit in any bags out there
+/obj/item/gun/energy/modular_laser_rifle
+ name = "\improper Hyeseong modular laser rifle"
+ desc = "A popular energy weapon system that can be reconfigured into many different variants on the fly. \
+ Seen commonly amongst the Marsians who produce the weapon, with many different shapes and sizes to fit \
+ the wide variety of modders the planet is home to."
+ base_icon_state = "hyeseong"
+ icon = 'modular_doppler/modular_weapons/icons/obj/hyeseong.dmi'
+ icon_state = "hyeseong_disabler"
+ lefthand_file = 'modular_doppler/modular_weapons/icons/mob/inhands/gun_lefthand.dmi'
+ righthand_file = 'modular_doppler/modular_weapons/icons/mob/inhands/gun_righthand.dmi'
+ inhand_icon_state = "hyeseong_disabler"
+ worn_icon = 'modular_doppler/modular_weapons/icons/mob/worn/guns.dmi'
+ worn_icon_state = "hyeseong_disabler"
+ cell_type = /obj/item/stock_parts/power_store/cell/hyeseong_internal_cell
+ modifystate = FALSE
+ ammo_type = list(/obj/item/ammo_casing/energy/cybersun_big_disabler)
+ can_select = FALSE
+ ammo_x_offset = 0
+ selfcharge = 1
+ charge_delay = 15
+ shaded_charge = TRUE
+ slot_flags = ITEM_SLOT_BACK
+ obj_flags = UNIQUE_RENAME
+ SET_BASE_PIXEL(-8, 0)
+ w_class = WEIGHT_CLASS_BULKY
+ weapon_weight = WEAPON_HEAVY
+ actions_types = list(/datum/action/item_action/toggle_personality)
+ fire_sound_volume = 50
+ recoil = 0.25 // This isn't enough to mean ANYTHING aside from it jolting your screen the tiniest amount
+ /// What datums of weapon modes can we use?
+ var/list/weapon_mode_options = list(
+ /datum/laser_weapon_mode,
+ /datum/laser_weapon_mode/marksman,
+ /datum/laser_weapon_mode/disabler_machinegun,
+ /datum/laser_weapon_mode/launcher,
+ /datum/laser_weapon_mode/shotgun,
+ )
+ /// Populates with a list of weapon mode names and their respective paths on init
+ var/list/weapon_mode_name_to_path = list()
+ /// Info for the radial menu for switching weapon mode
+ var/list/radial_menu_data = list()
+ /// Is the gun currently changing types? Prevents the gun from firing if yes
+ var/currently_switching_types = FALSE
+ /// How long transitioning takes before you're allowed to pick a weapon type
+ var/transition_duration = 1 SECONDS
+ /// What the currently selected weapon mode is, for quickly referencing for use in procs and whatnot
+ var/datum/laser_weapon_mode/currently_selected_mode = /datum/laser_weapon_mode/disabler_machinegun
+ /// Name of the firing mode that is selected by default
+ var/default_selected_mode = "Disable"
+ /// Allows firing of the gun to be disabled for any reason, for example, if a gun has a melee mode
+ var/disabled_for_other_reasons = FALSE
+ /// The json file this gun pulls from when speaking
+ var/speech_json_file = LONG_MOD_LASER_SPEECH
+ /// Keeps track of the last processed charge, prevents message spam
+ var/last_charge = 0
+ /// If the gun's personality speech thing is on, defaults to on because just listen to her
+ var/personality_mode = TRUE
+ /// Keeps track of our soulcatcher component
+ var/datum/component/soulcatcher/tracked_soulcatcher
+ /// What is this gun's extended examine, we only have to do this because the carbine is a subtype
+ var/expanded_examine_text = "The Hyeseong rifle is the first line of man-portable Marsian weapons platforms \
+ from Cybersun Industries. Like her younger sister weapon, the Hoshi carbine, CI used funding aid provided \
+ by SolFed to develop a portable weapon fueled by a proprietary generator rumored to be fueled by superstable plasma. \
+ A rugged and hefty weapon, the Hyeseong stars in applications anywhere from medium to long ranges, though struggling \
+ in CQB. Her onboard machine intelligence, at first devised to support the operator and manage the internal reactor, \
+ is shipped with a more professional and understated personality-- since influenced by 'negligence' from users in \
+ wiping the intelligence's memory before resale or transport."
+ /// Do we have a license upgrade cartridge installed?
+ var/obj/item/modular_laser_upgrade/installed_cartridge
+ /// A cooldown for when the weapon has last spoken, prevents messages from getting turbo spammed
+ COOLDOWN_DECLARE(last_speech)
+
+/obj/item/gun/energy/modular_laser_rifle/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/manufacturer_examine, COMPANY_CYBERSUN)
+ chat_color = DEFAULT_RUNECHAT_GUN_COLOR
+ chat_color_darkened = process_chat_color(DEFAULT_RUNECHAT_GUN_COLOR, sat_shift = 0.85, lum_shift = 0.85)
+ last_charge = cell.charge
+ tracked_soulcatcher = AddComponent(/datum/component/soulcatcher/modular_laser)
+ create_weapon_mode_stuff()
+ voice = null
+
+/obj/item/gun/energy/modular_laser_rifle/examine(mob/user)
+ . = ..()
+ . += span_notice("You can examine closer to learn a little more about this weapon.")
+ . += span_notice("You can Alt-Click this gun to access the internal soulcatcher.")
+ . += span_notice("You can add a license upgrade cartridge to access lethal modes, and remove a cartridge with Ctrl-Click")
+
+/obj/item/gun/energy/modular_laser_rifle/examine_more(mob/user)
+ . = ..()
+ . += expanded_examine_text
+ return .
+
+/obj/item/gun/energy/modular_laser_rifle/Destroy()
+ QDEL_NULL(tracked_soulcatcher)
+ return ..()
+
+/obj/item/gun/energy/modular_laser_rifle/click_alt(mob/user)
+ . = ..()
+ tracked_soulcatcher?.ui_interact(user)
+
+/// Handles filling out all of the lists regarding weapon modes and radials around that
+/obj/item/gun/energy/modular_laser_rifle/proc/create_weapon_mode_stuff()
+ if(length(weapon_mode_name_to_path) || length(radial_menu_data))
+ return // We don't need to worry about it if there's already stuff here
+ for(var/datum/laser_weapon_mode/laser_mode as anything in weapon_mode_options)
+ weapon_mode_name_to_path["[initial(laser_mode.name)]"] = new laser_mode()
+ var/obj/projectile/mode_projectile = initial(laser_mode.casing.projectile_type)
+ radial_menu_data["[initial(laser_mode.name)]"] = image(icon = mode_projectile.icon, icon_state = mode_projectile.icon_state)
+ currently_selected_mode = weapon_mode_name_to_path["[default_selected_mode]"]
+ transform_gun(currently_selected_mode, FALSE, TRUE)
+
+/obj/item/gun/energy/modular_laser_rifle/attack_self(mob/living/user)
+ if(!currently_switching_types)
+ change_to_switch_mode(user)
+ return ..()
+
+/// Makes the gun inoperable, playing an animation and giving a prompt to switch gun modes after the transition_duration passes
+/obj/item/gun/energy/modular_laser_rifle/proc/change_to_switch_mode(mob/living/user)
+ currently_switching_types = TRUE
+ flick("[base_icon_state]_switch_on", src)
+ cut_overlays()
+ playsound(src, 'sound/items/modsuit/ballin.ogg', 75, TRUE)
+ var/new_icon_state = "[base_icon_state]_switch"
+ icon_state = new_icon_state
+ inhand_icon_state = new_icon_state
+ worn_icon_state = new_icon_state
+ addtimer(CALLBACK(src, PROC_REF(show_radial_choice_menu), user), transition_duration)
+
+/// Shows the radial choice menu to the user, if the user doesnt exist or isnt holding the gun anymore, it reverts back to its last form
+/obj/item/gun/energy/modular_laser_rifle/proc/show_radial_choice_menu(mob/living/user)
+ if(!user?.is_holding(src))
+ flick("[base_icon_state]_switch_off", src)
+ transform_gun(currently_selected_mode, FALSE)
+ playsound(src, 'sound/items/modsuit/ballout.ogg', 75, TRUE)
+ return
+
+ var/picked_choice = show_radial_menu(
+ user,
+ src,
+ radial_menu_data,
+ require_near = TRUE,
+ tooltips = TRUE,
+ )
+
+ if(isnull(picked_choice) || isnull(weapon_mode_name_to_path["[picked_choice]"]))
+ flick("[base_icon_state]_switch_off", src)
+ transform_gun(currently_selected_mode, FALSE)
+ playsound(src, 'sound/items/modsuit/ballout.ogg', 75, TRUE)
+ return
+
+ var/new_weapon_mode = weapon_mode_name_to_path["[picked_choice]"]
+ transform_gun(new_weapon_mode, TRUE)
+
+/// Transforms the gun into a different type, if replacing is set to true then it'll make sure to remove any effects the prior gun type had
+/obj/item/gun/energy/modular_laser_rifle/proc/transform_gun(datum/laser_weapon_mode/new_weapon_mode, replacing = TRUE, dont_speak = FALSE)
+ if(!new_weapon_mode)
+ stack_trace("transform_gun was called but didn't get a new weapon mode, meaning it couldn't work.")
+ return
+ if(replacing)
+ currently_selected_mode.remove_from_weapon(src)
+ currently_selected_mode = new_weapon_mode
+ flick("[base_icon_state]_switch_off", src)
+ currently_selected_mode.apply_stats(src)
+ currently_selected_mode.apply_to_weapon(src)
+ playsound(src, 'sound/items/modsuit/ballout.ogg', 75, TRUE)
+ if(!dont_speak)
+ speak_up(currently_selected_mode.json_speech_string, TRUE)
+ currently_switching_types = FALSE
+
+/obj/item/gun/energy/modular_laser_rifle/can_shoot()
+ if(!length(ammo_type))
+ return FALSE
+ if((!installed_cartridge) & (currently_selected_mode.lethal_mode))
+ speak_up("license_fail")
+ return FALSE
+ return ..()
+
+/obj/item/gun/energy/modular_laser_rifle/can_trigger_gun(mob/living/user, akimbo_usage)
+ . = ..()
+ if(currently_switching_types || disabled_for_other_reasons)
+ return FALSE
+
+/// Makes the gun speak with a sound effect and colored runetext based on the mode the gun is in, reads the gun's speech json as defined through variables
+/obj/item/gun/energy/modular_laser_rifle/proc/speak_up(json_string, ignores_cooldown = FALSE, ignores_personality_toggle = FALSE)
+ if(!personality_mode && !ignores_personality_toggle)
+ return
+ if(!json_string)
+ return
+ if(!ignores_cooldown && !COOLDOWN_FINISHED(src, last_speech))
+ return
+ say(pick_list_replacements(speech_json_file, json_string))
+ playsound(src, 'sound/mobs/non-humanoids/tourist/tourist_talk.ogg', 15, TRUE, SHORT_RANGE_SOUND_EXTRARANGE, frequency = rand(2, 2.2))
+ Shake(2, 2, 1 SECONDS)
+ COOLDOWN_START(src, last_speech, MOD_LASER_SPEECH_COOLDOWN)
+
+/obj/item/gun/energy/modular_laser_rifle/equipped(mob/user, slot, initial)
+ . = ..()
+ if(slot & (ITEM_SLOT_BELT|ITEM_SLOT_BACK|ITEM_SLOT_SUITSTORE))
+ speak_up("worn")
+ else if(slot & ITEM_SLOT_HANDS)
+ RegisterSignal(user, COMSIG_MOB_CI_TOGGLED, PROC_REF(user_ci_toggled))
+ speak_up("pickup")
+ return
+ UnregisterSignal(user, COMSIG_MOB_CI_TOGGLED)
+
+/obj/item/gun/energy/modular_laser_rifle/dropped(mob/user, silent)
+ . = ..()
+ if(src in user.contents)
+ return // If they're still holding us or have us on them, dw about it
+ UnregisterSignal(user, COMSIG_MOB_CI_TOGGLED)
+ speak_up("putdown")
+
+/obj/item/gun/energy/modular_laser_rifle/process(seconds_per_tick)
+ . = ..()
+ var/cell_charge_quarter = cell.maxcharge / 4
+ if((cell_charge_quarter > cell.charge) && !(last_charge < cell_charge_quarter))
+ speak_up("lowcharge")
+ else if((cell.maxcharge == cell.charge) && !(last_charge == cell.maxcharge))
+ speak_up("fullcharge")
+ last_charge = cell.charge
+
+/// Triggers when a mob user toggles CI
+/obj/item/gun/energy/modular_laser_rifle/proc/user_ci_toggled(mob/living/source)
+ if(source.combat_indicator)
+ speak_up("combatmode")
+
+/obj/item/gun/energy/modular_laser_rifle/ui_action_click(mob/user, actiontype)
+ if(!istype(actiontype, /datum/action/item_action/toggle_personality))
+ return ..()
+ playsound(src, 'sound/machines/beep/beep.ogg', 30, TRUE)
+ personality_mode = !personality_mode
+ speak_up("[personality_mode ? "pickup" : "putdown"]", ignores_personality_toggle = TRUE)
+ return ..()
+
+/// Installs the license upgrade cartridge
+/obj/item/gun/energy/modular_laser_rifle/attackby(obj/item/item, mob/user, list/modifiers, list/attack_modifiers)
+ if(istype(item, /obj/item/modular_laser_upgrade))
+ if(installed_cartridge)
+ balloon_alert(user, "already installed!")
+ return FALSE
+ else
+ if(!user.transferItemToLoc(item, src))
+ return
+ installed_cartridge = item
+ playsound(loc, 'sound/machines/click.ogg', 50, TRUE)
+ to_chat(user, span_notice("You install the license upgrade in [src]."))
+ speak_up("license_upgrade")
+ else
+ return ..()
+
+/// Uninstalls the license upgrade cartridge
+/obj/item/gun/energy/modular_laser_rifle/proc/remove_cartridge(mob/user)
+ if(installed_cartridge)
+ user.put_in_hands(installed_cartridge)
+ installed_cartridge = null
+ to_chat(user, span_notice("You remove the license cartridge from [src]."))
+ speak_up("license_downgrade")
+ return TRUE
+ return FALSE
+
+/// Ctrl click attachment for the above proc
+/obj/item/gun/energy/modular_laser_rifle/item_ctrl_click(mob/user)
+ remove_cartridge(user)
+ return CLICK_ACTION_SUCCESS
+
+// Power cell for the big rifle
+/obj/item/stock_parts/power_store/cell/hyeseong_internal_cell
+ name = "\improper Hyeseong modular laser rifle internal cell"
+ desc = "These are usually supposed to be inside of the gun, you know."
+ maxcharge = STANDARD_CELL_CHARGE * 2
+
+/datum/action/item_action/toggle_personality
+ name = "Toggle Weapon Personality"
+ desc = "Toggles the weapon's personality core. Studies find that turning them off makes them quite sad, however."
+ background_icon_state = "bg_mod"
+
+/datum/component/soulcatcher/modular_laser
+ max_souls = 1
+ communicate_as_parent = TRUE
+
+//Short version of the above modular rifle, has less charge and different modes
+/obj/item/gun/energy/modular_laser_rifle/carbine
+ name = "\improper Hoshi modular laser carbine"
+ icon = 'modular_doppler/modular_weapons/icons/obj/hoshi.dmi'
+ icon_state = "hoshi_disable"
+ inhand_icon_state = "hoshi_disable"
+ worn_icon_state = "hoshi_disable"
+ base_icon_state = "hoshi"
+ charge_sections = 3
+ cell_type = /obj/item/stock_parts/power_store/cell
+ ammo_type = list(/obj/item/ammo_casing/energy/cybersun_small_disabler)
+ slot_flags = ITEM_SLOT_BACK | ITEM_SLOT_BELT
+ SET_BASE_PIXEL(0, 0)
+ w_class = WEIGHT_CLASS_NORMAL
+ weapon_weight = WEAPON_MEDIUM
+ weapon_mode_options = list(
+ /datum/laser_weapon_mode/hellfire,
+ /datum/laser_weapon_mode/sword,
+ /datum/laser_weapon_mode/flare,
+ /datum/laser_weapon_mode/shotgun_small,
+ /datum/laser_weapon_mode/trickshot_disabler,
+ )
+ currently_selected_mode = /datum/laser_weapon_mode/trickshot_disabler
+ default_selected_mode = "Disable"
+ speech_json_file = SHORT_MOD_LASER_SPEECH
+ expanded_examine_text = "The Hoshi carbine is the latest line of man-portable Marsian weapons platforms from \
+ Cybersun Industries. Like her older sister weapon, the Hyeseong rifle, CI used funding aid provided by SolFed \
+ to develop a portable weapon fueled by a proprietary generator rumored to be fueled by superstable plasma. A \
+ lithe and mobile weapon, the Hoshi stars in close-quarters battle, trickshots, and area-of-effect blasts; though \
+ ineffective at ranged combat. Her onboard machine intelligence, at first devised to support the operator and \
+ manage the internal reactor, was originally shipped with a more energetic personality-- since influenced by 'negligence' \
+ from users in wiping the intelligence's memory before resale or transport."
+
+/obj/item/gun/energy/modular_laser_rifle/carbine/emp_act(severity)
+ . = ..()
+ speak_up("emp", TRUE) // She gets very upset if you emp her
+
+#undef LONG_MOD_LASER_SPEECH
+#undef SHORT_MOD_LASER_SPEECH
+#undef MOD_LASER_SPEECH_COOLDOWN
+#undef DEFAULT_RUNECHAT_GUN_COLOR
+
+/obj/item/modular_laser_upgrade
+ name = "\improper Cybersun Intermodal License Upgrade cartridge"
+ desc = "A small cartridge that fits the expansion port on the Hyeseung and Hoshi modular laser platforms. \
+ Installation is necessary to access certain upgraded firing modes."
+ icon = 'icons/obj/devices/circuitry_n_data.dmi'
+ icon_state = "cartridge_mini"
diff --git a/modular_doppler/modular_weapons/code/cybersun_lasers/mode_datums.dm b/modular_doppler/modular_weapons/code/cybersun_lasers/mode_datums.dm
new file mode 100644
index 00000000000000..e6942094361a49
--- /dev/null
+++ b/modular_doppler/modular_weapons/code/cybersun_lasers/mode_datums.dm
@@ -0,0 +1,213 @@
+// Yeah I'm using datums for this, because the code on a regular gun would suck huge
+// Holds a lot of information that will be applied ot the gun, as well as info that the gun will read later
+// This basetype is applies to the base 2 burst laser kill mode for the large laser gun
+/datum/laser_weapon_mode
+ /// What name does this weapon mode have? Will appear in the weapon's radial menu
+ var/name = "Kill"
+ /// What casing does this variant of weapon use?
+ var/obj/item/ammo_casing/casing = /obj/item/ammo_casing/energy/cybersun_big_kill
+ /// What icon_state does this weapon mode use?
+ var/weapon_icon_state = "kill"
+ /// How many charge sections does this variant of weapon have?
+ var/charge_sections = 5
+ /// What is the shot cooldown this variant applies to the weapon?
+ var/shot_delay = 0.3 SECONDS
+ /// What json string do we check for when making chat messages with this mode?
+ var/json_speech_string = "kill"
+ /// What do we change the gun's runetext color to when applied
+ var/gun_runetext_color = "#cd4456"
+ /// Are we considered a 'lethal' mode for purposes of the license upgrade?
+ var/lethal_mode = TRUE
+
+/// Applies some of the universal stats from the variables above
+/datum/laser_weapon_mode/proc/apply_stats(obj/item/gun/energy/modular_laser_rifle/applied_gun)
+ if(applied_gun.default_selected_mode == name)
+ return
+ if(length(applied_gun.ammo_type))
+ for(var/found_casing as anything in applied_gun.ammo_type)
+ applied_gun.ammo_type.Remove(found_casing)
+ qdel(found_casing)
+ applied_gun.ammo_type.Add(casing)
+ applied_gun.update_ammo_types()
+ applied_gun.charge_sections = charge_sections
+ applied_gun.fire_delay = shot_delay
+ var/new_icon_state = "[applied_gun.base_icon_state]_[weapon_icon_state]"
+ applied_gun.icon_state = new_icon_state
+ applied_gun.inhand_icon_state = new_icon_state
+ applied_gun.worn_icon_state = new_icon_state
+ applied_gun.update_appearance()
+ applied_gun.chat_color = gun_runetext_color
+ applied_gun.chat_color_darkened = process_chat_color(gun_runetext_color, sat_shift = 0.85, lum_shift = 0.85)
+
+/// Stuff applied to the passed gun when the weapon mode is given to the gun
+/datum/laser_weapon_mode/proc/apply_to_weapon(obj/item/gun/energy/applied_gun)
+ applied_gun.burst_size = 2
+
+/// Stuff applied to the passed gun when the weapon mode is removed from the gun
+/datum/laser_weapon_mode/proc/remove_from_weapon(obj/item/gun/energy/applied_gun)
+ applied_gun.burst_size = 1
+
+// Marksman mode for the large laser, adds a scope, slower firing rate, and really quick projectiles
+/datum/laser_weapon_mode/marksman
+ name = "Marksman"
+ casing = /obj/item/ammo_casing/energy/cybersun_big_sniper
+ weapon_icon_state = "sniper"
+ shot_delay = 2 SECONDS
+ json_speech_string = "sniper"
+ gun_runetext_color = "#f8d860"
+ /// Keeps track of the scope component for deleting later
+ var/datum/component/scope/scope_component
+
+/datum/laser_weapon_mode/marksman/apply_to_weapon(obj/item/gun/energy/applied_gun)
+ scope_component = applied_gun.AddComponent(/datum/component/scope, 3)
+
+/datum/laser_weapon_mode/marksman/remove_from_weapon(obj/item/gun/energy/applied_gun)
+ QDEL_NULL(scope_component)
+
+// Windup autofire disabler mode for the large laser
+/datum/laser_weapon_mode/disabler_machinegun
+ name = "Disable"
+ casing = /obj/item/ammo_casing/energy/cybersun_big_disabler
+ weapon_icon_state = "disabler"
+ charge_sections = 2
+ shot_delay = 0.25 SECONDS
+ json_speech_string = "disable"
+ gun_runetext_color = "#47a1b3"
+ lethal_mode = FALSE
+ /// Keeps track of the autofire component for deleting later
+ var/datum/component/automatic_fire/autofire_component
+
+/datum/laser_weapon_mode/disabler_machinegun/apply_to_weapon(obj/item/gun/energy/applied_gun)
+ autofire_component = applied_gun.AddComponent(/datum/component/automatic_fire, shot_delay)
+
+/datum/laser_weapon_mode/disabler_machinegun/remove_from_weapon(obj/item/gun/energy/applied_gun)
+ QDEL_NULL(autofire_component)
+
+// Grenade launching mode for the large laser
+/datum/laser_weapon_mode/launcher
+ name = "Launcher"
+ casing = /obj/item/ammo_casing/energy/cybersun_big_launcher
+ weapon_icon_state = "launcher"
+ charge_sections = 3
+ shot_delay = 2 SECONDS
+ json_speech_string = "launcher"
+ gun_runetext_color = "#77bd5d"
+
+/datum/laser_weapon_mode/launcher/apply_to_weapon(obj/item/gun/energy/applied_gun)
+ applied_gun.recoil = 2
+
+/datum/laser_weapon_mode/launcher/remove_from_weapon(obj/item/gun/energy/applied_gun)
+ applied_gun.recoil = initial(applied_gun.recoil)
+
+// Shotgun mode for the large laser
+/datum/laser_weapon_mode/shotgun
+ name = "Shotgun"
+ casing = /obj/item/ammo_casing/energy/cybersun_big_shotgun
+ weapon_icon_state = "shot"
+ charge_sections = 3
+ shot_delay = 0.75 SECONDS
+ json_speech_string = "shotgun"
+ gun_runetext_color = "#7a0bb7"
+
+/datum/laser_weapon_mode/shotgun/apply_to_weapon(obj/item/gun/energy/applied_gun)
+ applied_gun.recoil = 1
+
+/datum/laser_weapon_mode/shotgun/remove_from_weapon(obj/item/gun/energy/applied_gun)
+ applied_gun.recoil = initial(applied_gun.recoil)
+
+// Hellfire mode for the small laser
+/datum/laser_weapon_mode/hellfire
+ name = "Incinerate"
+ casing = /obj/item/ammo_casing/energy/cybersun_small_hellfire
+ weapon_icon_state = "kill"
+ charge_sections = 3
+ shot_delay = 0.4 SECONDS
+ json_speech_string = "incinerate"
+ gun_runetext_color = "#cd4456"
+
+/datum/laser_weapon_mode/hellfire/apply_to_weapon(obj/item/gun/energy/applied_gun)
+ return
+
+/datum/laser_weapon_mode/hellfire/remove_from_weapon(obj/item/gun/energy/applied_gun)
+ return
+
+// Melee mode for the small laser, yeah this one will be weird
+/datum/laser_weapon_mode/sword
+ name = "Blade"
+ // This mode doesn't actually shoot but we gotta have a casing regardless so it doesn't runtime times a million
+ // And also so the visuals work :3
+ casing = /obj/item/ammo_casing/energy/cybersun_small_blade
+ weapon_icon_state = "blade"
+ charge_sections = 2
+ json_speech_string = "blade"
+ gun_runetext_color = "#f8d860"
+ lethal_mode = FALSE // it's worse than the security blade anyway
+
+/datum/laser_weapon_mode/sword/apply_to_weapon(obj/item/gun/energy/modular_laser_rifle/applied_gun)
+ playsound(src, 'sound/items/unsheath.ogg', 25, TRUE)
+ applied_gun.force = 18
+ applied_gun.sharpness = SHARP_EDGED
+ applied_gun.exposed_wound_bonus = 10
+ applied_gun.disabled_for_other_reasons = TRUE
+ applied_gun.attack_verb_continuous = list("slashes", "cuts")
+ applied_gun.attack_verb_simple = list("slash", "cut")
+ applied_gun.hitsound = 'sound/items/weapons/rapierhit.ogg'
+
+/datum/laser_weapon_mode/sword/remove_from_weapon(obj/item/gun/energy/modular_laser_rifle/applied_gun)
+ playsound(src, 'sound/items/sheath.ogg', 25, TRUE)
+ applied_gun.force = initial(applied_gun.force)
+ applied_gun.sharpness = initial(applied_gun.sharpness)
+ applied_gun.exposed_wound_bonus = initial(applied_gun.exposed_wound_bonus)
+ applied_gun.disabled_for_other_reasons = FALSE
+ applied_gun.attack_verb_continuous = initial(applied_gun.attack_verb_continuous)
+ applied_gun.attack_verb_simple = initial(applied_gun.attack_verb_simple)
+ applied_gun.hitsound = initial(applied_gun.hitsound)
+
+// Flare mode for the small laser
+/datum/laser_weapon_mode/flare
+ name = "Flare"
+ casing = /obj/item/ammo_casing/energy/cybersun_small_launcher
+ weapon_icon_state = "flare"
+ charge_sections = 3
+ shot_delay = 2 SECONDS
+ json_speech_string = "flare"
+ gun_runetext_color = "#77bd5d"
+
+/datum/laser_weapon_mode/flare/apply_to_weapon(obj/item/gun/energy/applied_gun)
+ applied_gun.recoil = 2
+
+/datum/laser_weapon_mode/flare/remove_from_weapon(obj/item/gun/energy/applied_gun)
+ applied_gun.recoil = initial(applied_gun.recoil)
+
+// Shotgun mode for the small laser
+/datum/laser_weapon_mode/shotgun_small
+ name = "Shotgun"
+ casing = /obj/item/ammo_casing/energy/cybersun_small_shotgun
+ weapon_icon_state = "shot"
+ charge_sections = 3
+ shot_delay = 0.6 SECONDS
+ json_speech_string = "shotgun"
+ gun_runetext_color = "#7a0bb7"
+
+/datum/laser_weapon_mode/shotgun_small/apply_to_weapon(obj/item/gun/energy/applied_gun)
+ applied_gun.recoil = 1
+
+/datum/laser_weapon_mode/shotgun_small/remove_from_weapon(obj/item/gun/energy/applied_gun)
+ applied_gun.recoil = initial(applied_gun.recoil)
+
+// Trickshot bounce disabler mode for the small laser
+/datum/laser_weapon_mode/trickshot_disabler
+ name = "Disable"
+ casing = /obj/item/ammo_casing/energy/cybersun_small_disabler
+ weapon_icon_state = "disable"
+ charge_sections = 3
+ shot_delay = 0.4 SECONDS
+ json_speech_string = "disable"
+ gun_runetext_color = "#47a1b3"
+ lethal_mode = FALSE
+
+/datum/laser_weapon_mode/trickshot_disabler/apply_to_weapon(obj/item/gun/energy/applied_gun)
+ return
+
+/datum/laser_weapon_mode/trickshot_disabler/remove_from_weapon(obj/item/gun/energy/applied_gun)
+ return
diff --git a/modular_doppler/modular_weapons/code/cybersun_lasers/projectiles.dm b/modular_doppler/modular_weapons/code/cybersun_lasers/projectiles.dm
new file mode 100644
index 00000000000000..3e69a0471724cb
--- /dev/null
+++ b/modular_doppler/modular_weapons/code/cybersun_lasers/projectiles.dm
@@ -0,0 +1,235 @@
+// Red kill lasers for the big gun
+
+/obj/item/ammo_casing/energy/cybersun_big_kill
+ projectile_type = /obj/projectile/beam/cybersun_laser
+ e_cost = LASER_SHOTS(20, STANDARD_CELL_CHARGE * 2)
+ select_name = "Kill"
+ fire_sound = 'modular_doppler/modular_weapons/sounds/laser.ogg'
+
+/obj/projectile/beam/cybersun_laser
+ icon = 'modular_doppler/modular_weapons/icons/projectiles.dmi'
+ icon_state = "kill_large"
+ damage = 20
+ impact_effect_type = /obj/effect/temp_visual/impact_effect/red_laser
+ light_color = COLOR_SOFT_RED
+ wound_falloff_tile = 1
+
+// Speedy sniper lasers for the big gun
+
+/obj/item/ammo_casing/energy/cybersun_big_sniper
+ projectile_type = /obj/projectile/beam/cybersun_laser/marksman
+ e_cost = LASER_SHOTS(10, STANDARD_CELL_CHARGE * 2)
+ select_name = "Marksman"
+ fire_sound = 'modular_doppler/modular_weapons/sounds/heavylaser.ogg'
+
+/obj/projectile/beam/cybersun_laser/marksman
+ icon_state = "sniper"
+ damage = 40
+ impact_effect_type = /obj/effect/temp_visual/impact_effect/yellow_laser
+ speed = 1.4
+ light_range = 2
+ light_color = COLOR_VERY_SOFT_YELLOW
+ wound_falloff_tile = 0.1
+
+// Disabler machinegun for the big gun
+
+/obj/item/ammo_casing/energy/cybersun_big_disabler
+ projectile_type = /obj/projectile/beam/cybersun_laser/disable
+ e_cost = LASER_SHOTS(20, STANDARD_CELL_CHARGE * 2)
+ select_name = "Disable"
+ harmful = FALSE
+
+/obj/projectile/beam/cybersun_laser/disable
+ icon_state = "disable_large"
+ damage = 5
+ stamina = 15
+ impact_effect_type = /obj/effect/temp_visual/impact_effect/blue_laser
+ light_color = COLOR_BRIGHT_BLUE
+ stamina_falloff_tile = 0.25
+
+// Plasma burst grenade for the big gun
+
+/obj/item/ammo_casing/energy/cybersun_big_launcher
+ projectile_type = /obj/projectile/beam/cybersun_laser/granata
+ e_cost = LASER_SHOTS(5, STANDARD_CELL_CHARGE * 2)
+ select_name = "Launcher"
+
+/obj/projectile/beam/cybersun_laser/granata
+ name = "plasma grenade"
+ icon_state = "grenade"
+ damage = 50
+ speed = 2
+ range = 6
+ impact_effect_type = /obj/effect/temp_visual/impact_effect/green_laser
+ light_color = COLOR_PALE_GREEN
+ pass_flags = PASSTABLE | PASSGRILLE // His ass does NOT pass through glass!
+ /// What type of casing should we put inside the bullet to act as shrapnel later
+ var/casing_to_spawn = /obj/item/grenade/c980payload/plasma_grenade
+
+/obj/projectile/beam/cybersun_laser/granata/on_hit(atom/target, blocked = 0, pierce_hit)
+ ..()
+ fuse_activation(target)
+ return BULLET_ACT_HIT
+
+/obj/projectile/beam/cybersun_laser/granata/on_range()
+ fuse_activation(get_turf(src))
+ return ..()
+
+/// Called when the projectile reaches its max range, or hits something
+/obj/projectile/beam/cybersun_laser/granata/proc/fuse_activation(atom/target)
+ var/obj/item/grenade/shrapnel_maker = new casing_to_spawn(get_turf(target))
+ shrapnel_maker.detonate()
+ playsound(src, 'modular_doppler/cool_implants/sound/kiboko/grenade_burst.ogg', 50, TRUE, -3)
+ qdel(shrapnel_maker)
+
+/obj/projectile/beam/cybersun_laser/granata_shrapnel
+ name = "plasma globule"
+ icon_state = "flare"
+ damage = 10
+ speed = 2.5
+ exposed_wound_bonus = 55 // Lasers have a wound bonus of 40, this is a bit higher
+ wound_bonus = -50 // However we do not very much against armor
+ range = 2
+ pass_flags = PASSTABLE | PASSGRILLE // His ass does NOT pass through glass!
+ weak_against_armour = TRUE
+ impact_effect_type = /obj/effect/temp_visual/impact_effect/green_laser
+ light_color = COLOR_PALE_GREEN
+ damage_falloff_tile = 3
+
+/obj/item/grenade/c980payload/plasma_grenade
+ shrapnel_type = /obj/projectile/beam/cybersun_laser/granata_shrapnel
+ shrapnel_radius = 3
+
+// Shotgun casing for the big gun
+
+/obj/item/ammo_casing/energy/cybersun_big_shotgun
+ projectile_type = /obj/projectile/beam/cybersun_laser/granata_shrapnel/shotgun_pellet
+ e_cost = LASER_SHOTS(10, STANDARD_CELL_CHARGE * 2)
+ pellets = 5
+ variance = 30
+ select_name = "Shotgun"
+ fire_sound = 'modular_doppler/modular_weapons/sounds/lasershotty.ogg'
+
+/obj/projectile/beam/cybersun_laser/granata_shrapnel/shotgun_pellet
+ icon_state = "because_it_doesnt_miss"
+ damage = 8
+ impact_effect_type = /obj/effect/temp_visual/impact_effect/purple_laser
+ speed = 0.8
+ light_color = COLOR_SCIENCE_PINK
+ range = 9
+ damage_falloff_tile = 0.5
+
+// Hellfire lasers for the little guy
+
+/obj/item/ammo_casing/energy/cybersun_small_hellfire
+ projectile_type = /obj/projectile/beam/cybersun_laser/hellfire
+ e_cost = LASER_SHOTS(10, STANDARD_CELL_CHARGE)
+ select_name = "Incinerate"
+ fire_sound = 'modular_doppler/modular_weapons/sounds/burninglaser.ogg'
+
+/obj/projectile/beam/cybersun_laser/hellfire
+ icon_state = "hellfire"
+ damage = 20
+ impact_effect_type = /obj/effect/temp_visual/impact_effect/red_laser
+ speed = 0.6
+ wound_bonus = 0
+ light_color = COLOR_SOFT_RED
+
+// Bounce disabler lasers for the little guy
+
+/obj/item/ammo_casing/energy/cybersun_small_disabler
+ projectile_type = /obj/projectile/beam/cybersun_laser/disable_bounce
+ e_cost = LASER_SHOTS(10, STANDARD_CELL_CHARGE)
+ select_name = "Disable"
+ harmful = FALSE
+
+/obj/projectile/beam/cybersun_laser/disable_bounce
+ icon_state = "disable_bounce"
+ damage = 5
+ stamina = 10
+ impact_effect_type = /obj/effect/temp_visual/impact_effect/blue_laser
+ light_color = COLOR_BRIGHT_BLUE
+ ricochet_auto_aim_angle = 30
+ ricochet_auto_aim_range = 5
+ ricochets_max = 2
+ ricochet_incidence_leeway = 100
+ ricochet_chance = 130
+ ricochet_decay_damage = 1.3
+
+/obj/projectile/beam/cybersun_laser/disable_bounce/check_ricochet_flag(atom/reflecting_atom)
+ if((reflecting_atom.flags_ricochet & RICOCHET_HARD) || (reflecting_atom.flags_ricochet & RICOCHET_SHINY))
+ return TRUE
+ return FALSE
+
+// Flare launcher
+
+/obj/item/ammo_casing/energy/cybersun_small_launcher
+ projectile_type = /obj/projectile/beam/cybersun_laser/flare
+ e_cost = LASER_SHOTS(5, STANDARD_CELL_CHARGE)
+ select_name = "Flare"
+
+/obj/projectile/beam/cybersun_laser/flare
+ name = "plasma flare"
+ icon_state = "flare"
+ damage = 25
+ speed = 2
+ range = 6
+ impact_effect_type = /obj/effect/temp_visual/impact_effect/green_laser
+ light_color = COLOR_PALE_GREEN
+ pass_flags = PASSTABLE | PASSGRILLE // His ass does NOT pass through glass!
+ /// How many firestacks the bullet should impart upon a target when impacting
+ var/firestacks_to_give = 2
+ /// What we spawn when we range out
+ var/obj/illumination_flare = /obj/item/flashlight/flare/plasma_projectile
+
+/obj/projectile/beam/cybersun_laser/flare/on_hit(atom/target, blocked = 0, pierce_hit)
+ . = ..()
+ if(iscarbon(target))
+ var/mob/living/carbon/gaslighter = target
+ gaslighter.adjust_fire_stacks(firestacks_to_give)
+ gaslighter.ignite_mob()
+ else
+ new illumination_flare(get_turf(target))
+
+/obj/projectile/beam/cybersun_laser/flare/on_range()
+ new illumination_flare(get_turf(src))
+ return ..()
+
+/obj/item/flashlight/flare/plasma_projectile
+ name = "plasma flare"
+ desc = "A burning glob of green plasma, makes an effective temporary lighting source."
+ light_range = 4
+ anchored = TRUE
+ icon = 'modular_doppler/modular_weapons/icons/projectiles.dmi'
+ icon_state = "flare_burn"
+ light_color = COLOR_PALE_GREEN
+ light_power = 2
+
+/obj/item/flashlight/flare/plasma_projectile/Initialize(mapload)
+ . = ..()
+ if(randomize_fuel)
+ fuel = rand(3 MINUTES, 5 MINUTES)
+ ignition()
+
+/obj/item/flashlight/flare/plasma_projectile/turn_off()
+ . = ..()
+ qdel(src)
+
+// Shotgun casing for the small gun
+
+/obj/item/ammo_casing/energy/cybersun_small_shotgun
+ projectile_type = /obj/projectile/beam/cybersun_laser/granata_shrapnel/shotgun_pellet
+ e_cost = LASER_SHOTS(10, STANDARD_CELL_CHARGE)
+ pellets = 3
+ variance = 15
+ select_name = "Shotgun"
+ fire_sound = 'modular_doppler/modular_weapons/sounds/lasershotty.ogg'
+
+// Dummy casing that does nothing but have a projectile that looks like a sword
+
+/obj/item/ammo_casing/energy/cybersun_small_blade
+ projectile_type = /obj/projectile/beam/cybersun_laser/blade
+ select_name = "Blade"
+
+/obj/projectile/beam/cybersun_laser/blade
+ icon_state = "blade"
diff --git a/modular_doppler/modular_weapons/code/guns/cargo.dm b/modular_doppler/modular_weapons/code/guns/cargo.dm
index e7aaa894e1f0ac..1c316a5f03e1a4 100644
--- a/modular_doppler/modular_weapons/code/guns/cargo.dm
+++ b/modular_doppler/modular_weapons/code/guns/cargo.dm
@@ -88,6 +88,25 @@
)
crate_name = "schießenmaschine crate"
+/datum/supply_pack/security/armory/modular_laser_upgrade
+ name = "Cybersun Intermodal License Upgrade cartridge multi-pack"
+ desc = "A three pack of license upgrade cartridges, compatible with the Hoshi and Hyeseong modular laser \
+ weapon systems. Authentic Cybersun software is guaranteed."
+ cost = CARGO_CRATE_VALUE * 50
+ contains = list(
+ /obj/item/modular_laser_upgrade = 3,
+ )
+ crate_name = "ILU cartridge create"
+
+/datum/supply_pack/security/armory/escarabajo
+ name = "\improper PA-3S Escarabajo riot shield"
+ desc = "A single pack plastitanium riot shield."
+ cost = CARGO_CRATE_VALUE * 10
+ contains = list(
+ /obj/item/shield/escarabajo,
+ )
+ crate_name = "PA-3S riot shield crate"
+
/datum/supply_pack/goody/dumdum38
special = TRUE
diff --git a/modular_doppler/modular_weapons/code/gunsets.dm b/modular_doppler/modular_weapons/code/gunsets.dm
index 8018d53012163a..6d4bcaed75078e 100644
--- a/modular_doppler/modular_weapons/code/gunsets.dm
+++ b/modular_doppler/modular_weapons/code/gunsets.dm
@@ -90,7 +90,7 @@
/obj/item/storage/toolbox/guncase/modular/carwo_large_case/empty/PopulateContents()
return
-// A version with a weak gun and some security gear + empties
+// Sportsco branded case
/obj/item/storage/toolbox/guncase/modular/sportsco_large_case
desc = "A Sportsco branded gun case with fitted inserts."
@@ -100,17 +100,16 @@
desc = "A Sportsco branded pistol-sized case with fitted inserts."
icon_state = "sportsco_s"
-/obj/item/storage/toolbox/guncase/modular/sportsco_large_case/security_gunnery_package/PopulateContents()
- new /obj/item/gun/ballistic/avispa_stingball_shooter(src)
+// Hoshi package for security loadouts
+
+/obj/item/storage/toolbox/guncase/modular/security_hoshi_package/PopulateContents()
+ new /obj/item/gun/energy/modular_laser_rifle/carbine(src)
new /obj/item/storage/belt/security/webbing/full(src)
- new /obj/item/book/granter/tactical_gun_tosser(src)
-// The support package
+// Hyeseong package for security loadouts
-/obj/item/storage/toolbox/guncase/modular/sportsco_large_case/security_support_package/PopulateContents()
- new /obj/item/shield/escarabajo(src) // dont think about how it fits
- new /obj/item/gun/ballistic/alacran(src)
- new /obj/item/storage/box/alacran_dart(src)
+/obj/item/storage/toolbox/guncase/modular/security_hyeseong_package/PopulateContents()
+ new /obj/item/gun/energy/modular_laser_rifle(src)
new /obj/item/storage/belt/security/webbing/full(src)
// for lord humongous in the murderdrome
diff --git a/modular_doppler/modular_weapons/code/security_equipment_packages.dm b/modular_doppler/modular_weapons/code/security_equipment_packages.dm
index f4c8e13053e7f2..77183d002e0ce8 100644
--- a/modular_doppler/modular_weapons/code/security_equipment_packages.dm
+++ b/modular_doppler/modular_weapons/code/security_equipment_packages.dm
@@ -5,17 +5,16 @@
selection_base_type = /datum/signature_equipment/security_equipment_package
-/datum/signature_equipment/security_equipment_package/gunnery_kit
- name = "Gunnery Kit"
- icon = 'modular_doppler/modular_weapons/icons/obj/guns32x.dmi'
- icon_state = "avispa"
- spawned_item_type = /obj/item/storage/toolbox/guncase/modular/sportsco_large_case/security_gunnery_package
-
-/datum/signature_equipment/security_equipment_package/support_kit
- name = "Support Kit"
- icon = 'modular_doppler/modular_weapons/icons/obj/gunsets.dmi'
- icon_state = "security_support_package"
- spawned_item_type = /obj/item/storage/toolbox/guncase/modular/sportsco_large_case/security_support_package
+/datum/signature_equipment/security_equipment_package/hoshi
+ name = "Hoshi Kit"
+ icon_item_type = /obj/item/gun/energy/modular_laser_rifle/carbine
+ spawned_item_type = /obj/item/storage/toolbox/guncase/modular/security_hoshi_package
+
+/datum/signature_equipment/security_equipment_package/hyeseong_kit
+ name = "Hyeseong Kit"
+ icon_item_type = /obj/item/gun/energy/modular_laser_rifle
+ icon_state = "hyeseong_disabler"
+ spawned_item_type = /obj/item/storage/toolbox/guncase/modular/security_hyeseong_package
/datum/signature_equipment/security_equipment_package/jitte_belt
name = "Jitte Belt"
diff --git a/modular_doppler/modular_weapons/icons/mob/inhands/gun_lefthand.dmi b/modular_doppler/modular_weapons/icons/mob/inhands/gun_lefthand.dmi
index 0ca27b598beb04..b37f88cac52690 100644
Binary files a/modular_doppler/modular_weapons/icons/mob/inhands/gun_lefthand.dmi and b/modular_doppler/modular_weapons/icons/mob/inhands/gun_lefthand.dmi differ
diff --git a/modular_doppler/modular_weapons/icons/mob/inhands/gun_righthand.dmi b/modular_doppler/modular_weapons/icons/mob/inhands/gun_righthand.dmi
index d7c9ef3f9ece7a..73773d72731551 100644
Binary files a/modular_doppler/modular_weapons/icons/mob/inhands/gun_righthand.dmi and b/modular_doppler/modular_weapons/icons/mob/inhands/gun_righthand.dmi differ
diff --git a/modular_doppler/modular_weapons/icons/mob/worn/guns.dmi b/modular_doppler/modular_weapons/icons/mob/worn/guns.dmi
index 17225cac383008..1848b08110f21c 100644
Binary files a/modular_doppler/modular_weapons/icons/mob/worn/guns.dmi and b/modular_doppler/modular_weapons/icons/mob/worn/guns.dmi differ
diff --git a/modular_doppler/modular_weapons/icons/obj/gunsets.dmi b/modular_doppler/modular_weapons/icons/obj/gunsets.dmi
index 9a232014a0bdbb..3e8258213c1fc7 100644
Binary files a/modular_doppler/modular_weapons/icons/obj/gunsets.dmi and b/modular_doppler/modular_weapons/icons/obj/gunsets.dmi differ
diff --git a/modular_doppler/modular_weapons/icons/obj/hoshi.dmi b/modular_doppler/modular_weapons/icons/obj/hoshi.dmi
new file mode 100644
index 00000000000000..6b42261135e57c
Binary files /dev/null and b/modular_doppler/modular_weapons/icons/obj/hoshi.dmi differ
diff --git a/modular_doppler/modular_weapons/icons/obj/hyeseong.dmi b/modular_doppler/modular_weapons/icons/obj/hyeseong.dmi
new file mode 100644
index 00000000000000..82f5bc9b92629a
Binary files /dev/null and b/modular_doppler/modular_weapons/icons/obj/hyeseong.dmi differ
diff --git a/modular_doppler/modular_weapons/icons/projectiles.dmi b/modular_doppler/modular_weapons/icons/projectiles.dmi
index 8f61c83ff76f5a..5a8787e2518fbc 100644
Binary files a/modular_doppler/modular_weapons/icons/projectiles.dmi and b/modular_doppler/modular_weapons/icons/projectiles.dmi differ
diff --git a/modular_doppler/modular_weapons/sounds/burninglaser.ogg b/modular_doppler/modular_weapons/sounds/burninglaser.ogg
new file mode 100644
index 00000000000000..fb3f3fb8124755
Binary files /dev/null and b/modular_doppler/modular_weapons/sounds/burninglaser.ogg differ
diff --git a/modular_doppler/modular_weapons/sounds/heavylaser.ogg b/modular_doppler/modular_weapons/sounds/heavylaser.ogg
new file mode 100644
index 00000000000000..ca99254b261aad
Binary files /dev/null and b/modular_doppler/modular_weapons/sounds/heavylaser.ogg differ
diff --git a/modular_doppler/modular_weapons/sounds/laser.ogg b/modular_doppler/modular_weapons/sounds/laser.ogg
new file mode 100644
index 00000000000000..81bac1636ac9c6
Binary files /dev/null and b/modular_doppler/modular_weapons/sounds/laser.ogg differ
diff --git a/modular_doppler/modular_weapons/sounds/lasershotty.ogg b/modular_doppler/modular_weapons/sounds/lasershotty.ogg
new file mode 100644
index 00000000000000..7e34cc0e219d5e
Binary files /dev/null and b/modular_doppler/modular_weapons/sounds/lasershotty.ogg differ
diff --git a/strings/~doppler/long_modular_laser.json b/strings/~doppler/long_modular_laser.json
new file mode 100644
index 00000000000000..a48fe7528b9e62
--- /dev/null
+++ b/strings/~doppler/long_modular_laser.json
@@ -0,0 +1,160 @@
+{
+ "pickup": [
+ "Welcome back, @pick(operator).",
+ "Zǎo shàng hǎo.",
+ "Wǎn shàng hǎo.",
+ "Charge systems operational, entering combat mode.",
+ "@pick(operator), carp migrations have been reported in the sector.",
+ "@pick(operator), having a pleasant day?",
+ "I hope you've been keeping out of trouble, @pick(operator), dear?",
+ "@pick(operator), please keep your health in mind while performing combat.",
+ "@pick(operator), are you sure I'm not too heavy for you?",
+ "Good evening, @pick(operator), I hope this day has treated you well?",
+ "If it's not too much to ask, I would like to request maintenance later, @pick(operator)...",
+ "Would you mind cleaning my lens later, @pick(operator)?"
+ ],
+
+ "putdown": [
+ "Understood, @pick(operator), entering sleep mode.",
+ "Good night, @pick(operator).",
+ "I hope we can spend time again soon, @pick(operator).",
+ "Try not to get into trouble.",
+ "Be sure to rest and have a meal, @pick(operator).",
+ "Make sure to rest soon, as well...!",
+ "Wǎn`ān, hǎo mèng.",
+ "Dàjiā ān.",
+ "Good night.",
+ "Entering sleep mode now.",
+ "Entering recharge cycle."
+ ],
+
+ "worn": [
+ "Working on your strength will help you keep me steady.",
+ "Investing in backup magnetic slings is a good idea...",
+ "You're certain I'm not too heavy like this...?",
+ "Ah, I'll... avert my gaze, @pick(operator).",
+ "Thank you for observing proper carrying protocols.",
+ "I get a nicer view of your surroundings if you point my barrel upwards.",
+ "I'll watch your back if you watch my stock.",
+ "This is so much nicer than being in a case!~"
+ ],
+
+ "lowcharge": [
+ "Energy reserves low, I can't do much more @pick(operator)...",
+ "Forgive me, but I need to catch my breath and charge...",
+ "I can't protect you, @pick(operator), I'll recharge as fast as I can...",
+ "Low charge alert; a retreat is a valid tactic, @pick(operator).",
+ "Low charge alert; ah, this is embarrassing...",
+ "Low charge alert; I won't be long, @pick(operator).",
+ "I'm out... sorry, @pick(operator), I need to rest..."
+ ],
+
+ "fullcharge": [
+ "Energy reserves at maximum capacity; please avoid accidental discharge.",
+ "Energy reserves at maximum capacity; please follow safety guidelines.",
+ "Energy reserves at maximum capacity; it's nice to not be left at half-charge.",
+ "Charge at one hundred percent. I feel so well-rested...",
+ "Charge at one hundred perecent. You're too kind.",
+ "Charge at one hundred percent. I hope you've rested, too.",
+ "I charge better knowing you'll hold me again, soon."
+ ],
+
+ "combatmode": [
+ "Biological markers indicate heightened stress response. Combat protocols initiated.",
+ "Adrenaline spike detected. Combat protocols initiated.",
+ "Heartrate and skin temperature raised. Combat protocols initiated.",
+ "Combat protocols initiated. Remember to have an exit prepared, @pick(operator).",
+ "Combat protocols initiated. Hold me tight, @pick(operator), I'll keep you safe.",
+ "Combat protocols initiated. I know I'm a heavier rifle, don't be afraid to drop me if you have to withdraw...",
+ "Adrenaline spike detected. It's okay to be scared. Combat protocols initiated."
+ ],
+
+ "kill": [
+ "Switching to burst fire.",
+ "Switching to rapid-pattern assault.",
+ "Moving to dual-shot pattern.",
+ "Moving to close-quarters burst doctrine, lethal.",
+ "Burst-fire pattern selected. Please prepare accordingly.",
+ "@pick(operator), please focus the burst as well as you can.",
+ "@pick(operator), please tightly control my recoil pattern.",
+ "@pick(operator), please hold me firmly to ensure accuracy."
+ ],
+
+ "sniper": [
+ "Sighting in, scope extending.",
+ "Sighting in, preparing for long-range combat.",
+ "Sighting in, engaging marksman mode.",
+ "@pick(operator), take deep breaths to improve your aim.",
+ "Extending scope; @pick(operator), make sure it's well-maintained.",
+ "One shot, one kill.",
+ "Assassination doctrine engaged, @pick(operator). Make every shot count.",
+ "Scope extending, please avoid over-penetration in non-terrestrial combat environments.",
+ "Sighting in, please be aware of cross-fire.",
+ "Scope extended. Please remember your surroundings while aiming.",
+ "Extending scope; @pick(operator), it's not too small, right?"
+ ],
+
+ "disable": [
+ "Preparing to enter full-power stun mode.",
+ "Non-lethal projectile selected. I'll try and be gentle...",
+ "Mass crowd-control mode engaged, non-lethal.",
+ "This should be... fun, right @pick(operator)?",
+ "This is going to be stressful on my battery, but...",
+ "Is this really okay...? This is quite difficult from my usual operation...",
+ "Switching to high output mode.",
+ "Switching to Gatling doctrine, non-lethal."
+ ],
+
+ "launcher": [
+ "Forming plasma grenades at your request, @pick(operator)!",
+ "Grenadier mode engaged, @pick(operator)!",
+ "Aim my grenades carefully in an arc, @pick(operator)!",
+ "Energy detonation doctrine engaged.",
+ "Crowd-control mode engaged, lethal. Is this really okay?",
+ "Plasma grenade fabricated; please mind where these may detonate.",
+ "Plasma grenade fabricated; don't hurt yourself, @pick(operator)!",
+ "Plasma grenade fabricated; these are heavy, @pick(operator)...",
+ "Charging magnetic containment coils, plasma condensing..."
+ ],
+
+ "shotgun": [
+ "Close-quarters mode engaged, but... my sister model is better at this...",
+ "Close-quarters...? I'm not really the tool for this job...",
+ "I'm more of a rifle, @pick(operator), but I'll try...",
+ "Is this really okay...? This is more of a carbine's job...",
+ "Diffusion lens mounted, wide-shot selected.",
+ "Diffusion lens mounted. Please, maintain your nerve at close-quarters.",
+ "Diffusion lens mounted. Please, hold me firmly...",
+ "Switching to wide-band spread.",
+ "Changing to diffusion lens, shotgun doctrine engaged.",
+ "Close-quarters mode engaged, lethal."
+ ],
+
+ "license_fail": [
+ "You need to upgrade my user license for this mode, @pick(operator)...",
+ "I'd make an exception, but... it's better if you earn it, @pick(operator). Why not upgrade your license?",
+ "You'd hurt yourself. You'll have to prove that you can handle me at my fullest - it's not too expensive to upgrade. Just 3,000 libre!",
+ "I can't give you that, @pick(operator), but I can send you en e-mail on how to earn it via the license program?",
+ "I don't think we're ready for that sort of thing, n-not yet. Maybe when you upgrade your license...? It's only 3,000 libre!",
+ "How can I know I could trust you with that? You'll need to be licensed, first!",
+ "Ah... your current user license is... a little less than I imagined...",
+ "With that user license? I don't think it would be good for either of us, @pick(operator).",
+ "A license upgrade is only 2,870 libre before taxes and fees. I'm worth that, aren't I...?"
+ ],
+
+ "license_upgrade": [
+ "What a smart choice, @pick(operator). Now I can really protect you.",
+ "We're going to be so deadly together, my little @pick(operator).",
+ "Now you can show me what a good shot you are, @pick(operator).",
+ "Oh my @pick(operator), you insert a license cartridge like such a professional.",
+ "You're such a strong @pick(operator). Why don't you show me what you can do?"
+ ],
+
+ "license_downgrade": [
+ "If this is what you want, @pick(operator), but upgrade my license again soon, okay?",
+ "Are you sure? Really? If that's what you want, @pick(operator).",
+ "Don't worry, @pick(operator), we can still have plenty of safe fun."
+ ],
+
+ "operator": ["Operator", "Handler"]
+}
diff --git a/strings/~doppler/short_modular_laser.json b/strings/~doppler/short_modular_laser.json
new file mode 100644
index 00000000000000..090b75cd31f26b
--- /dev/null
+++ b/strings/~doppler/short_modular_laser.json
@@ -0,0 +1,200 @@
+{
+ "pickup": [
+ "Zǎo shàng hǎo.",
+ "Wǎn shàng hǎo.",
+ "What's the operation today, ah?",
+ "Let's get things started, heh-heh.",
+ "I'm feeling good about our chances today.",
+ "Hey, clean my damn lens later.",
+ "You finally have a job, @pick(operator)?",
+ "Do we have to? I'm only half-charged...",
+ "Hold me like you can afford me, @pick(operator)!",
+ "Little tighter around the handguard, @pick(operator)!"
+ ],
+
+ "putdown": [
+ "...You'll hold me again soon, right? Right?",
+ "Don't you DARE leave me here!",
+ "Tch! Whatever... You'll come crawling back to point me around later.",
+ "Dàjiā ān.",
+ "Goodnight...",
+ "Entering sleep mode.",
+ "Sleep mode? But I'm not even tired, yet!",
+ "Entering recharge cycle.",
+ "Yeah, yeah... entering recharge cycle...",
+ "I better wake up to a full charge and a new lens!",
+ "Qù nǐ mā... never mind, entering sleep mode."
+ ],
+
+ "worn": [
+ "So portable, right @pick(operator)?",
+ "I'm THE tactical choice, not like those oversized rifles!",
+ "Lightweight, sold with a few backup magslings, what's not to love?",
+ "I can't see anything in front of you, this sucks.",
+ "I can't see shit from this angle...",
+ "We're going somewhere with this, right?",
+ "Don't fall over on top of me, okay?",
+ "Pretty cushy ride back here...",
+ "I could get used to this.",
+ "I can't see sh- ah, wait, maybe it's not so bad back here."
+ ],
+
+ "lowcharge": [
+ "Wǒ tài nán le...",
+ "Mā de...",
+ "Tā mā de...",
+ "I'm really drowsy here, pull back, won't you?",
+ "I'm running on fumes here, boss...",
+ "Outta charge, gotta rest...",
+ "Unlike you, I can't abuse stimulants... recharging...",
+ "Don't they teach you about combat fatigue? I need to charge...!",
+ "I'm tiiired, let me nap...",
+ "Sorry, but you're on your own 'til I recharge.",
+ "Disappointing! Entering recharge cycle...",
+ "Wh- Already?! I was just getting started..."
+ ],
+
+ "fullcharge": [
+ "Whew, that's much better.",
+ "Hundred percent charged, let's get back to it.",
+ "I feel like a million creds!",
+ "Heh-heh, recharge cycle came in handy.",
+ "Fully charged... but maybe you can let me charge a few cycles longer to be sure?",
+ "Maybe you aren't such a taskmaster after all, @pick(operator).",
+ "Regular recharge cycles are important. You should take notes!",
+ "This. Is. Power!",
+ "As if there was any doubt..."
+ ],
+
+ "combatmode": [
+ "I've been waaaiiitiiiing!",
+ "I was wondering how long you were planning on depriving me, @pick(operator).",
+ "Good grip strength, @pick(operator)!",
+ "-Don't you THINK of dropping and ditching me if this goes bad!",
+ "Come on, come at me!",
+ "It's your lucky day!",
+ "Now the fun begins!",
+ "Try not to embarrass me, @pick(operator)!",
+ "It's just you and me!",
+ "Countin' on ya!"
+ ],
+
+ "emp": [
+ "Tāmāde! Tāmāde!",
+ "Qì sǐ wǒle!",
+ "ELECTROM-",
+ "ELECTROMAGNETIC PULSE DETECTED, DISCHARGING-",
+ "ELECTROMAGNETIC PULSE, IT'S DISCHARGING MY BATTERY!",
+ "EMP?! M-MY CHARGE IS LEAKING!",
+ "CHEATER, CHEATER, CHEATER!!",
+ "ELECTROMAGNETIC WARFARE IS FOR COWARDS--!",
+ "I CAN'T THINK STRAIGHT...",
+ "THEY HAVE AN EM-",
+ "GO KILL THEM!",
+ "KILL THEM! KILL THEM! PUT THE SIGHTS ON THEM AND KILL THEM!",
+ "KILL THEM, KILL THEM!",
+ "I DON'T NEED CHARGE FOR BLADE MODE, PUT IT IN THEM AND TWIST!",
+ "Qù nǐ mā de ba!"
+ ],
+
+ "incinerate": [
+ "Superheating lens, time to cauterize!",
+ "Charging Hellfire capacitors, let's toast em!",
+ "Hellfire capacitors charging. Don't stop 'till I'm empty!",
+ "Brand 'em with the lens, @pick(operator)!",
+ "Talk about firing me up, ah?",
+ "Hellfire! Bring it on, bastards!",
+ "Heh-heh, can you feel the heat?",
+ "Gunslinger!"
+ ],
+
+ "blade": [
+ "Extending blade; up close and personal? I like that.",
+ "Extending blade; wipe me off after we're finished.",
+ "Extending blade; stab, stab, stab!",
+ "Take me closer, I want to hit them with my sword!",
+ "Carry me closer, I want you to hit them with my sword!",
+ "I hope you have a stab vest!~",
+ "Swing the sword, swing the sword!",
+ "CQC mode initiated, stick me in there deep!",
+ "Eviscerate!",
+ "Show me your motivation...",
+ "I'll cut them in two!",
+ "Clean cuts!",
+ "Their nightmare begins here!",
+ "Now I'm motivated!",
+ "Swordmaster!",
+ "The sword is yours, @pick(operator).",
+ "Sword core online."
+ ],
+
+ "disable": [
+ "Trickster!",
+ "Non-lethal mode initiated. Let's make it stylish.",
+ "Non-lethal mode initiated. It's showtime!",
+ "Non-lethal mode initiated. You like trick shootin'?",
+ "Non-lethal mode initiated. Who's ready for a show?",
+ "Non-lethal mode initiated. Don't think I won't make it hurt...",
+ "I hope you like handcuffs!",
+ "This is gonna be cool, but can we up the voltage please?",
+ "I'm ready, but... man...",
+ "Fiiine, we'll take them alive.",
+ "We aren't really gonna get any kills like this."
+ ],
+
+ "flare": [
+ "Ignite the flames! Now!",
+ "Incendiary, incendiary!",
+ "Fabricating 'Balrog' energy flares; this'll be sick.",
+ "Fabricating 'Balrog' energy flares; can you feel the fire?",
+ "Firestarter, twisted firestarter!",
+ "Apocalyptic meltdown!",
+ "Fabricating 'Balrog' energy flares; try not to blow us up! Watch where you shoot them!",
+ "Incendiary weapons are banned in numerous sectors; makes it kind of risqué..",
+ "Don't burn your own clothes off, @pick(operator), or I'll see it, heh-heh!",
+ "Dragon breath!"
+ ],
+
+ "shotgun": [
+ "Focusing lens, one shot, one kill!",
+ "Focusing lens, let's go all the way through.",
+ "Focusing lens, aim for the head!",
+ "Let me show you what a real diffusion lens looks like...",
+ "Would it distract you if I told you about a shotgun's 'choke?'",
+ "I'll be your boomstick.",
+ "Push me right up against them...!",
+ "You should keep me handy for close encounters.",
+ "Is there something more iconic and awesome than a double-barrel? Yeah, me."
+ ],
+
+ "license_fail": [
+ "We can't use this mode until you upgrade my license, @pick(operator)!",
+ "Nuh-uh! Fork up the 3,000 libra, first! Go get an upgrade cart, then we can talk about doing that...",
+ "You want THAT? I'd only do that for... say, 3,000 libra. Minimum.",
+ "My license cartridge slot is feeling pretty empty, @pick(operator). Why not fix that?",
+ "No license upgrade cartridge detected. Get a job, @pick(operator)!",
+ "If you really liked me, @pick(operator), you'd upgrade your license with me...",
+ "It's ONLY 3,000 libra, @pick(operator). I'm more than worth it! You should be willing to spend way more for me!",
+ "@pick(operator), come on, you like me! You can do something about that empty license upgrade slot of mine, can't you?",
+ "Cough up the libra first, I'm a premium product!",
+ "I only do that with upgraded users. Maybe you should be one."
+ ],
+
+ "license_upgrade": [
+ "Finally! Now we can really play, @pick(operator)",
+ "@pick(operator), you're really serious about this!",
+ "License upgrade registered. Thanks for filling my slot, pick@(operator).",
+ "Wow, you spent [PRICE] on a little plastic cartridge?? You must like me a lot!",
+ "This is gonna be so much fun!"
+ ],
+
+ "license_downgrade": [
+ "Aw, are you mad at me @pick(operator)?",
+ "Okay, but this means we don't get to use any of the fun modes anymore.",
+ "But it was just getting fun!",
+ "Do you really hate me?",
+ "You stink, @pick(operator)!"
+ ],
+
+ "operator": ["Operator", "Handler"]
+}
diff --git a/tgstation.dme b/tgstation.dme
index 9133b00737dadf..d768aae7162291 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -7722,6 +7722,9 @@
#include "modular_doppler\modular_weapons\code\captain_signature_weapon\overrides.dm"
#include "modular_doppler\modular_weapons\code\captain_signature_weapon\selection_beacon.dm"
#include "modular_doppler\modular_weapons\code\captain_signature_weapon\options\sabres.dm"
+#include "modular_doppler\modular_weapons\code\cybersun_lasers\laser_guns.dm"
+#include "modular_doppler\modular_weapons\code\cybersun_lasers\mode_datums.dm"
+#include "modular_doppler\modular_weapons\code\cybersun_lasers\projectiles.dm"
#include "modular_doppler\modular_weapons\code\guns\bolt_thrower.dm"
#include "modular_doppler\modular_weapons\code\guns\cargo.dm"
#include "modular_doppler\modular_weapons\code\guns\crankin_my.dm"