diff --git a/_maps/templates/holodeck_doppler_sword_trainer.dmm b/_maps/templates/holodeck_doppler_sword_trainer.dmm
new file mode 100644
index 0000000000000..91743b296245e
--- /dev/null
+++ b/_maps/templates/holodeck_doppler_sword_trainer.dmm
@@ -0,0 +1,435 @@
+//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
+"a" = (
+/obj/effect/turf_decal/tile/dark/half{
+ dir = 4
+ },
+/obj/effect/turf_decal/trimline/yellow/warning{
+ dir = 8
+ },
+/turf/open/floor/holofloor{
+ icon_state = "smooth_large";
+ base_icon_state = "smooth_large"
+ },
+/area/template_noop)
+"c" = (
+/obj/effect/turf_decal/tile/dark/half{
+ dir = 4
+ },
+/obj/effect/turf_decal/trimline/yellow/warning{
+ dir = 8
+ },
+/turf/open/floor/holofloor{
+ base_icon_state = "smooth_half";
+ icon_state = "smooth_half";
+ dir = 1
+ },
+/area/template_noop)
+"d" = (
+/obj/effect/turf_decal/tile/neutral/half/contrasted{
+ dir = 4
+ },
+/turf/open/floor/holofloor{
+ base_icon_state = "smooth";
+ icon_state = "smooth";
+ dir = 1
+ },
+/area/template_noop)
+"e" = (
+/obj/structure/chair{
+ dir = 4
+ },
+/turf/open/floor/holofloor{
+ base_icon_state = "smooth_half";
+ icon_state = "smooth_half";
+ dir = 1
+ },
+/area/template_noop)
+"f" = (
+/obj/effect/turf_decal/arrows/white,
+/turf/open/floor/holofloor{
+ icon_state = "smooth_large";
+ base_icon_state = "smooth_large"
+ },
+/area/template_noop)
+"h" = (
+/obj/effect/turf_decal/bot_white/left,
+/turf/open/floor/holofloor{
+ icon_state = "smooth_large";
+ base_icon_state = "smooth_large"
+ },
+/area/template_noop)
+"k" = (
+/obj/effect/turf_decal/tile/dark/half{
+ dir = 8
+ },
+/obj/effect/turf_decal/trimline/yellow/warning{
+ dir = 4
+ },
+/turf/open/floor/holofloor{
+ icon_state = "smooth_large";
+ base_icon_state = "smooth_large"
+ },
+/area/template_noop)
+"l" = (
+/obj/effect/turf_decal/trimline/neutral/warning{
+ dir = 5
+ },
+/turf/open/floor/holofloor{
+ base_icon_state = "smooth_half";
+ icon_state = "smooth_half";
+ dir = 1
+ },
+/area/template_noop)
+"m" = (
+/obj/effect/turf_decal/trimline/neutral/warning{
+ dir = 4
+ },
+/turf/open/floor/holofloor{
+ base_icon_state = "smooth_half";
+ icon_state = "smooth_half";
+ dir = 1
+ },
+/area/template_noop)
+"n" = (
+/turf/open/floor/holofloor{
+ base_icon_state = "smooth";
+ icon_state = "smooth";
+ dir = 1
+ },
+/area/template_noop)
+"o" = (
+/obj/effect/turf_decal/trimline/neutral/warning{
+ dir = 6
+ },
+/turf/open/floor/holofloor{
+ base_icon_state = "smooth_half";
+ icon_state = "smooth_half";
+ dir = 1
+ },
+/area/template_noop)
+"q" = (
+/obj/structure/rack,
+/obj/item/storage/belt/secsword/training,
+/obj/item/storage/belt/secsword/training{
+ pixel_y = 4
+ },
+/obj/effect/turf_decal/bot_white,
+/turf/open/floor/holofloor{
+ icon_state = "smooth_large";
+ base_icon_state = "smooth_large"
+ },
+/area/template_noop)
+"r" = (
+/obj/effect/turf_decal/tile/neutral/full,
+/turf/open/floor/holofloor{
+ icon_state = "smooth_large";
+ base_icon_state = "smooth_large"
+ },
+/area/template_noop)
+"v" = (
+/obj/effect/turf_decal/trimline/neutral/warning{
+ dir = 5
+ },
+/obj/machinery/shower/directional/east,
+/obj/structure/fluff/shower_drain,
+/turf/open/floor/holofloor{
+ base_icon_state = "smooth_half";
+ icon_state = "smooth_half";
+ dir = 1
+ },
+/area/template_noop)
+"w" = (
+/turf/open/floor/holofloor{
+ icon_state = "smooth_large";
+ base_icon_state = "smooth_large"
+ },
+/area/template_noop)
+"x" = (
+/obj/effect/turf_decal/arrows/white{
+ dir = 1
+ },
+/turf/open/floor/holofloor{
+ icon_state = "smooth_large";
+ base_icon_state = "smooth_large"
+ },
+/area/template_noop)
+"y" = (
+/obj/structure/rack,
+/obj/item/shield/riot{
+ pixel_x = 2
+ },
+/obj/item/shield/riot{
+ pixel_y = 4;
+ pixel_x = 2
+ },
+/obj/item/shield/riot{
+ pixel_x = -2
+ },
+/obj/item/shield/riot{
+ pixel_y = 4;
+ pixel_x = -2
+ },
+/obj/structure/railing{
+ dir = 5
+ },
+/obj/effect/turf_decal/bot_white,
+/turf/open/floor/holofloor{
+ icon_state = "smooth_large";
+ base_icon_state = "smooth_large"
+ },
+/area/template_noop)
+"B" = (
+/turf/open/floor/holofloor{
+ base_icon_state = "smooth_half";
+ icon_state = "smooth_half";
+ dir = 1
+ },
+/area/template_noop)
+"C" = (
+/obj/effect/turf_decal/delivery/white,
+/obj/item/kirbyplants/random/fullysynthetic,
+/turf/open/floor/holofloor{
+ icon_state = "smooth_large";
+ base_icon_state = "smooth_large"
+ },
+/area/template_noop)
+"D" = (
+/obj/structure/railing{
+ dir = 5
+ },
+/obj/structure/rack,
+/obj/item/storage/medkit/frontier,
+/obj/item/storage/box/bandages,
+/turf/open/floor/holofloor{
+ icon_state = "smooth_large";
+ base_icon_state = "smooth_large"
+ },
+/area/template_noop)
+"F" = (
+/obj/effect/turf_decal/caution/white{
+ dir = 8
+ },
+/turf/open/floor/holofloor{
+ base_icon_state = "smooth_half";
+ icon_state = "smooth_half";
+ dir = 1
+ },
+/area/template_noop)
+"I" = (
+/obj/effect/turf_decal/loading_area/white{
+ dir = 4
+ },
+/turf/open/floor/holofloor{
+ icon_state = "smooth_large";
+ base_icon_state = "smooth_large"
+ },
+/area/template_noop)
+"L" = (
+/obj/effect/turf_decal/bot_white/right,
+/turf/open/floor/holofloor{
+ icon_state = "smooth_large";
+ base_icon_state = "smooth_large"
+ },
+/area/template_noop)
+"M" = (
+/obj/structure/railing{
+ dir = 4
+ },
+/obj/effect/turf_decal/delivery/white,
+/obj/item/kirbyplants/random/fullysynthetic,
+/turf/open/floor/holofloor{
+ icon_state = "smooth_large";
+ base_icon_state = "smooth_large"
+ },
+/area/template_noop)
+"P" = (
+/obj/structure/rack,
+/obj/item/shield/riot{
+ pixel_x = -2
+ },
+/obj/item/shield/riot{
+ pixel_y = 4;
+ pixel_x = -2
+ },
+/obj/item/shield/riot{
+ pixel_x = 2
+ },
+/obj/item/shield/riot{
+ pixel_y = 4;
+ pixel_x = 2
+ },
+/obj/structure/railing{
+ dir = 6
+ },
+/obj/effect/turf_decal/bot_white,
+/turf/open/floor/holofloor{
+ icon_state = "smooth_large";
+ base_icon_state = "smooth_large"
+ },
+/area/template_noop)
+"Q" = (
+/obj/effect/turf_decal/delivery/white,
+/obj/structure/reagent_dispensers/water_cooler,
+/turf/open/floor/holofloor{
+ icon_state = "smooth_large";
+ base_icon_state = "smooth_large"
+ },
+/area/template_noop)
+"R" = (
+/obj/structure/railing{
+ dir = 4
+ },
+/obj/effect/turf_decal/delivery/white,
+/obj/structure/closet/boxinggloves,
+/turf/open/floor/holofloor{
+ icon_state = "smooth_large";
+ base_icon_state = "smooth_large"
+ },
+/area/template_noop)
+"W" = (
+/obj/effect/turf_decal/trimline/neutral/warning{
+ dir = 6
+ },
+/obj/machinery/shower/directional/east,
+/obj/structure/fluff/shower_drain,
+/turf/open/floor/holofloor{
+ base_icon_state = "smooth_half";
+ icon_state = "smooth_half";
+ dir = 1
+ },
+/area/template_noop)
+"X" = (
+/obj/structure/railing{
+ dir = 6
+ },
+/obj/structure/table,
+/obj/item/clothing/mask/whistle{
+ pixel_y = 7
+ },
+/turf/open/floor/holofloor{
+ icon_state = "smooth_large";
+ base_icon_state = "smooth_large"
+ },
+/area/template_noop)
+"Y" = (
+/obj/effect/turf_decal/tile/dark/half{
+ dir = 8
+ },
+/obj/effect/turf_decal/trimline/yellow/warning{
+ dir = 4
+ },
+/turf/open/floor/holofloor{
+ base_icon_state = "smooth_half";
+ icon_state = "smooth_half";
+ dir = 1
+ },
+/area/template_noop)
+
+(1,1,1) = {"
+Q
+m
+o
+I
+v
+W
+I
+l
+m
+C
+"}
+(2,1,1) = {"
+q
+f
+x
+n
+f
+x
+n
+f
+x
+q
+"}
+(3,1,1) = {"
+q
+B
+F
+h
+e
+B
+L
+F
+B
+q
+"}
+(4,1,1) = {"
+M
+P
+r
+d
+D
+X
+d
+r
+y
+R
+"}
+(5,1,1) = {"
+k
+Y
+Y
+k
+Y
+Y
+k
+Y
+Y
+k
+"}
+(6,1,1) = {"
+n
+f
+x
+n
+f
+x
+n
+f
+x
+n
+"}
+(7,1,1) = {"
+L
+B
+B
+w
+B
+B
+w
+B
+B
+h
+"}
+(8,1,1) = {"
+n
+f
+x
+n
+f
+x
+n
+f
+x
+n
+"}
+(9,1,1) = {"
+a
+c
+c
+a
+c
+c
+a
+c
+c
+a
+"}
diff --git a/code/game/machinery/recharger.dm b/code/game/machinery/recharger.dm
index 226e19bfe84f1..14198f01409dd 100644
--- a/code/game/machinery/recharger.dm
+++ b/code/game/machinery/recharger.dm
@@ -18,6 +18,7 @@
/obj/item/ammo_box/magazine/recharge,
/obj/item/modular_computer,
/obj/item/gun/ballistic/automatic/battle_rifle,
+ /obj/item/melee/baton/doppler_security, // DOPPLER EDIT ADDITION
))
/obj/machinery/recharger/RefreshParts()
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/security.dm b/code/game/objects/structures/crates_lockers/closets/secure/security.dm
index e4488b0b7f436..b3881326668c9 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm
@@ -67,7 +67,7 @@
new /obj/item/storage/lockbox/loyalty(src)
new /obj/item/storage/box/flashbangs(src)
new /obj/item/shield/riot/tele(src)
- new /obj/item/storage/belt/security/full(src)
+ new /obj/item/storage/belt/secsword/full(src) // DOPPLER EDIT - new /obj/item/storage/belt/security/full(src)
new /obj/item/circuitboard/machine/techfab/department/security(src)
new /obj/item/storage/photo_album/hos(src)
@@ -92,7 +92,7 @@
new /obj/item/storage/bag/garment/warden(src)
new /obj/item/storage/box/zipties(src)
new /obj/item/storage/box/flashbangs(src)
- new /obj/item/storage/belt/security/full(src)
+ new /obj/item/storage/belt/secsword/full(src) // DOPPLER EDIT - new /obj/item/storage/belt/security/full(src)
new /obj/item/flashlight/seclite(src)
new /obj/item/door_remote/head_of_security(src)
@@ -115,7 +115,7 @@
/obj/structure/closet/secure_closet/security/sec/PopulateContents()
..()
- new /obj/item/storage/belt/security/full(src)
+ new /obj/item/storage/belt/secsword/full(src) // DOPPLER EDIT - new /obj/item/storage/belt/security/full(src)
/obj/structure/closet/secure_closet/security/cargo
diff --git a/modular_doppler/modular_weapons/code/sec_swords/baton.dm b/modular_doppler/modular_weapons/code/sec_swords/baton.dm
new file mode 100644
index 0000000000000..27be1e35b6f9e
--- /dev/null
+++ b/modular_doppler/modular_weapons/code/sec_swords/baton.dm
@@ -0,0 +1,175 @@
+/obj/item/melee/baton/doppler_security
+ name = "electro baton"
+ desc = "A high power baton for incapacitating humans and similar with. Delivers powerful jolts of electricity \
+ that may cause bodily harm, but will -- without a doubt -- entice cooperation."
+
+ desc_controls = "Left Click to stun, Right Click to harm."
+ context_living_rmb_active = "Harmful Stun"
+ attack_verb_continuous = list("beats")
+ attack_verb_simple = list("beat")
+
+ icon = 'modular_doppler/modular_weapons/icons/obj/sec_swords.dmi'
+ icon_state = "baton_two"
+ lefthand_file = 'modular_doppler/modular_weapons/icons/mob/inhands/melee_lefthand.dmi'
+ righthand_file = 'modular_doppler/modular_weapons/icons/mob/inhands/melee_righthand.dmi'
+ inhand_icon_state = "baton_two"
+ icon_angle = -20
+
+ on_stun_sound = 'sound/items/weapons/taserhit.ogg'
+ on_stun_volume = 50
+ drop_sound = 'sound/items/baton/stun_baton_active_drop.ogg'
+ pickup_sound = 'sound/items/baton/stun_baton_active_pickup.ogg'
+ sound_vary = TRUE
+
+ active = TRUE
+ force = 10
+ wound_bonus = 0
+ armor_type = /datum/armor/baton_security
+ throwforce = 7
+ force_say_chance = 50
+ stamina_damage = 35 // DOPPLER EDIT - 4 baton crit now (Original: 60)
+ knockdown_time = 5 SECONDS
+ clumsy_knockdown_time = 15 SECONDS
+ cooldown = 2.5 SECONDS
+
+ var/obj/item/stock_parts/power_store/cell
+ var/preload_cell_type //if not empty the baton starts with this type of cell
+ var/cell_hit_cost = STANDARD_CELL_CHARGE
+
+/obj/item/melee/baton/doppler_security/Initialize(mapload)
+ . = ..()
+ if(preload_cell_type)
+ if(!ispath(preload_cell_type, /obj/item/stock_parts/power_store/cell))
+ log_mapping("[src] at [AREACOORD(src)] had an invalid preload_cell_type: [preload_cell_type].")
+ else
+ cell = new preload_cell_type(src)
+
+/obj/item/melee/baton/doppler_security/get_cell()
+ return cell
+
+/obj/item/melee/baton/doppler_security/suicide_act(mob/living/user)
+ if(cell?.charge && active)
+ user.visible_message(span_suicide("[user] is putting the live [name] right to [user.p_their()] heart! It looks like [user.p_theyre()] trying to commit suicide!"))
+ attack(user, user)
+ return FIRELOSS
+ return
+
+/obj/item/melee/baton/doppler_security/Destroy()
+ if(cell)
+ QDEL_NULL(cell)
+ UnregisterSignal(src, COMSIG_ATOM_ATTACKBY)
+ return ..()
+
+/obj/item/melee/baton/doppler_security/examine(mob/user)
+ . = ..()
+ if(cell)
+ . += span_notice("\The [src] is [round(cell.percent())]% charged.")
+ else
+ . += span_warning("\The [src] does not have a power source installed.")
+
+/obj/item/melee/baton/doppler_security/proc/deductcharge(deducted_charge)
+ if(!cell)
+ return
+ //Note this value returned is significant, as it will determine
+ //if a stun is applied or not
+ . = cell.use(deducted_charge)
+
+/obj/item/melee/baton/doppler_security/clumsy_check(mob/living/carbon/human/user)
+ if(!active || !HAS_TRAIT(user, TRAIT_CLUMSY) || prob(50))
+ return FALSE
+ user.visible_message(span_danger("[user] accidentally touches the prongs of [src]! Fool they are!"), span_userdanger("You accidentally touch the prongs of [src]!"))
+
+ if(iscyborg(user))
+ if(affect_cyborg)
+ user.flash_act(affect_silicon = TRUE)
+ user.Paralyze(clumsy_knockdown_time)
+ additional_effects_cyborg(user, user) // user is the target here
+ if(on_stun_sound)
+ playsound(get_turf(src), on_stun_sound, on_stun_volume, TRUE, -1)
+ else
+ playsound(get_turf(src), 'sound/items/weapons/taserhit.ogg', 10, TRUE)
+ else
+ if(ishuman(user))
+ var/mob/living/carbon/human/human_user = user
+ human_user.force_say()
+ user.Knockdown(clumsy_knockdown_time)
+ user.apply_damage(stamina_damage, STAMINA)
+ additional_effects_non_cyborg(user, user)
+ if(on_stun_sound)
+ playsound(get_turf(src), on_stun_sound, on_stun_volume, TRUE, -1)
+
+ user.apply_damage(2 * force, BURN, BODY_ZONE_CHEST, attacking_item = src)
+
+ log_combat(user, user, "accidentally stun attacked [user.p_them()]self due to their clumsiness", src)
+ if(stun_animation)
+ user.do_attack_animation(user)
+ SEND_SIGNAL(user, COMSIG_LIVING_MINOR_SHOCK)
+ deductcharge(cell_hit_cost)
+
+/// Handles prodding targets with turned off stunbatons and right clicking stun'n'bash
+/obj/item/melee/baton/doppler_security/baton_attack(mob/living/target, mob/living/user, modifiers)
+ . = ..()
+ if(. != BATON_DO_NORMAL_ATTACK)
+ return
+ if(LAZYACCESS(modifiers, RIGHT_CLICK))
+ if(active && cooldown_check <= world.time && !check_parried(target, user))
+ finalize_baton_attack(target, user, modifiers, in_attack_chain = FALSE)
+ else if(!user.combat_mode)
+ target.visible_message(span_warning("[user] prods [target] with [src]. Luckily it was off."), \
+ span_warning("[user] prods you with [src]. Luckily it was off."))
+ return BATON_ATTACK_DONE
+
+/obj/item/melee/baton/doppler_security/baton_effect(mob/living/target, mob/living/user, modifiers, stun_override)
+ if(iscyborg(loc))
+ var/mob/living/silicon/robot/robot = loc
+ if(!robot || !robot.cell || !robot.cell.use(cell_hit_cost))
+ return FALSE
+ else if(!deductcharge(cell_hit_cost))
+ return FALSE
+ stun_override = 0 //Avoids knocking people down prematurely.
+ return ..()
+
+/obj/item/melee/baton/doppler_security/additional_effects_non_cyborg(mob/living/target, mob/living/user)
+ target.set_jitter_if_lower(40 SECONDS)
+ target.set_stutter_if_lower(16 SECONDS)
+ if(iscarbon(target))
+ var/mob/living/carbon/big_shocker = target
+ big_shocker.electrocute_act(10, src, 1, jitter_time = 0 SECONDS, stutter_time = 0 SECONDS, stun_duration = 0 SECONDS)
+ else
+ target.electrocute_act(10, src, 1)
+ SEND_SIGNAL(target, COMSIG_LIVING_MINOR_SHOCK)
+ addtimer(CALLBACK(src, PROC_REF(apply_stun_effect_end), target), 2 SECONDS)
+
+/// After the initial stun period, we check to see if the target needs to have the stun applied.
+/obj/item/melee/baton/doppler_security/proc/apply_stun_effect_end(mob/living/target)
+ var/trait_check = HAS_TRAIT(target, TRAIT_BATON_RESISTANCE) //var since we check it in out to_chat as well as determine stun duration
+ if(!target.IsKnockdown())
+ to_chat(target, span_warning("Your muscles seize, making you collapse[trait_check ? ", but your body quickly recovers..." : "!"]"))
+
+ if(!trait_check)
+ target.Knockdown(knockdown_time)
+
+/obj/item/melee/baton/doppler_security/get_wait_description()
+ return span_danger("The baton is still charging!")
+
+/obj/item/melee/baton/doppler_security/get_stun_description(mob/living/target, mob/living/user)
+ . = list()
+
+ .["visible"] = span_danger("[user] shocks [target] with [src]!")
+ .["local"] = span_userdanger("[user] shocks you with [src]!")
+
+/obj/item/melee/baton/doppler_security/get_unga_dunga_cyborg_stun_description(mob/living/target, mob/living/user)
+ . = list()
+
+ .["visible"] = span_danger("[user] tries to shock [target] with [src], and predictably fails!")
+ .["local"] = span_userdanger("[user] tries to... shock you with [src]?")
+
+/obj/item/melee/baton/doppler_security/emp_act(severity)
+ . = ..()
+ if (!cell)
+ return
+ if (!(. & EMP_PROTECT_SELF))
+ deductcharge(STANDARD_CELL_CHARGE / severity)
+
+/obj/item/melee/baton/doppler_security/loaded //this one starts with a cell pre-installed.
+ preload_cell_type = /obj/item/stock_parts/power_store/cell/high
diff --git a/modular_doppler/modular_weapons/code/sec_swords/big_sword.dm b/modular_doppler/modular_weapons/code/sec_swords/big_sword.dm
new file mode 100644
index 0000000000000..4ce45b2d631fc
--- /dev/null
+++ b/modular_doppler/modular_weapons/code/sec_swords/big_sword.dm
@@ -0,0 +1,49 @@
+/obj/item/melee/secblade
+ name = "security shortblade"
+ desc = "A utilitarian weapon, handle and blade, with little more. \
+ Designed for ease of blade replacement when it inevitably breaks due to mistreatment."
+
+ icon = 'modular_doppler/modular_weapons/icons/obj/sec_swords.dmi'
+ icon_state = "sec_sword"
+ lefthand_file = 'modular_doppler/modular_weapons/icons/mob/inhands/melee_lefthand.dmi'
+ righthand_file = 'modular_doppler/modular_weapons/icons/mob/inhands/melee_righthand.dmi'
+ inhand_icon_state = "sec_sword"
+ icon_angle = -20
+
+ hitsound = 'sound/items/weapons/bladeslice.ogg'
+ block_sound = 'sound/items/weapons/parry.ogg'
+
+ obj_flags = CONDUCTS_ELECTRICITY
+ sharpness = SHARP_EDGED
+ w_class = WEIGHT_CLASS_BULKY
+ obj_flags = UNIQUE_RENAME
+
+ force = 18
+ throwforce = 10
+ block_chance = 1 // Nah, I'd win
+ wound_bonus = 0
+ bare_wound_bonus = 20
+
+ attack_verb_continuous = list("attacks", "slashes", "slices", "tears", "lacerates", "rips", "dices", "rends")
+ attack_verb_simple = list("attack", "slash", "slice", "tear", "lacerate", "rip", "dice", "rend")
+
+ var/list/alt_continuous = list("stabs", "pierces", "impales")
+ var/list/alt_simple = list("stab", "pierce", "impale")
+
+/obj/item/melee/secblade/Initialize(mapload)
+ . = ..()
+ AddComponent(/datum/component/butchering, speed = 4 SECONDS, effectiveness = 100)
+ alt_continuous = string_list(alt_continuous)
+ alt_simple = string_list(alt_simple)
+ AddComponent(/datum/component/alternative_sharpness, SHARP_POINTY, alt_continuous, alt_simple, -5)
+
+/obj/item/melee/secblade/training
+ name = "training shortblade"
+ desc = "A utilitarian weapon, handle and blade, with little more. \
+ This one doesn't seem completely real, incapable of bloodshed but likely still hurts quite a lot."
+
+ icon_state = "training_sword"
+
+ damtype = STAMINA
+ wound_bonus = -50
+ bare_wound_bonus = -50
diff --git a/modular_doppler/modular_weapons/code/sec_swords/holodeck_trainer.dm b/modular_doppler/modular_weapons/code/sec_swords/holodeck_trainer.dm
new file mode 100644
index 0000000000000..1f2eab3526d7d
--- /dev/null
+++ b/modular_doppler/modular_weapons/code/sec_swords/holodeck_trainer.dm
@@ -0,0 +1,4 @@
+/datum/map_template/holodeck/doppler_sword_trainer
+ name = "Holodeck - Shortblade Trainer"
+ template_id = "holodeck_doppler_sword_trainer"
+ mappath = "_maps/templates/holodeck_doppler_sword_trainer.dmm"
diff --git a/modular_doppler/modular_weapons/code/sec_swords/sheath.dm b/modular_doppler/modular_weapons/code/sec_swords/sheath.dm
new file mode 100644
index 0000000000000..aa070c9405d3c
--- /dev/null
+++ b/modular_doppler/modular_weapons/code/sec_swords/sheath.dm
@@ -0,0 +1,109 @@
+/obj/item/storage/belt/secsword
+ name = "security weapons sheath"
+ desc = "A large block of metal made for safely holding on to a shortblade and matching electro baton, \
+ along with the rest of an officer's security equipment."
+ icon = 'modular_doppler/modular_weapons/icons/obj/sec_swords.dmi'
+ icon_state = "swordcase"
+ base_icon_state = "swordcase"
+ worn_icon = 'modular_doppler/modular_weapons/icons/mob/worn/cases.dmi'
+ worn_icon_state = "swordcase"
+ w_class = WEIGHT_CLASS_BULKY
+ interaction_flags_click = parent_type::interaction_flags_click | NEED_DEXTERITY | NEED_HANDS
+ obj_flags = UNIQUE_RENAME
+
+/obj/item/storage/belt/secsword/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/update_icon_updates_onmob)
+
+ atom_storage.max_slots = 5
+ atom_storage.do_rustle = FALSE
+ atom_storage.max_specific_storage = WEIGHT_CLASS_BULKY
+ atom_storage.max_total_storage = (WEIGHT_CLASS_BULKY + (WEIGHT_CLASS_NORMAL * 4)) // One sword four other things
+ atom_storage.set_holdable(list(
+ /obj/item/ammo_box,
+ /obj/item/ammo_casing/shotgun,
+ /obj/item/assembly/flash/handheld,
+ /obj/item/clothing/glasses,
+ /obj/item/clothing/gloves,
+ /obj/item/flashlight/seclite,
+ /obj/item/food/donut,
+ /obj/item/grenade,
+ /obj/item/holosign_creator/security,
+ /obj/item/knife/combat,
+ /obj/item/melee/baton,
+ /obj/item/radio,
+ /obj/item/reagent_containers/spray/pepper,
+ /obj/item/restraints/handcuffs,
+ /obj/item/restraints/legcuffs/bola,
+ /obj/item/melee/secblade,
+ ))
+ atom_storage.open_sound = 'sound/items/handling/holster_open.ogg'
+ atom_storage.open_sound_vary = TRUE
+
+/obj/item/storage/belt/secsword/examine(mob/user)
+ . = ..()
+ if(length(contents))
+ . += span_notice("Left Click to draw a stored blade, Right Click to draw a stored baton while wearing.")
+
+/obj/item/storage/belt/secsword/attack_hand(mob/user, list/modifiers)
+ if(!(user.get_slot_by_item(src) & ITEM_SLOT_BELT))
+ return ..()
+ for(var/obj/item/melee/secblade/blade_runner in contents)
+ user.visible_message(span_notice("[user] draws [blade_runner] from [src]."), span_notice("You draw [blade_runner] from [src]."))
+ user.put_in_hands(blade_runner)
+ playsound(user, 'sound/items/sheath.ogg', 50, TRUE)
+ update_appearance()
+ return
+ return ..()
+
+/obj/item/storage/belt/secsword/attack_hand_secondary(mob/user, list/modifiers)
+ if(!(user.get_slot_by_item(src) & ITEM_SLOT_BELT))
+ return ..()
+ for(var/obj/item/melee/baton/doppler_security/simply_shocking in contents)
+ user.visible_message(span_notice("[user] draws [simply_shocking] from [src]."), span_notice("You draw [simply_shocking] from [src]."))
+ user.put_in_hands(simply_shocking)
+ playsound(user, 'sound/items/sheath.ogg', 50, TRUE)
+ update_appearance()
+ return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
+ return ..()
+
+/obj/item/storage/belt/secsword/update_icon_state()
+ var/has_sword = FALSE
+ var/has_baton = FALSE
+ for(var/obj/thing in contents)
+ if(has_baton && has_sword)
+ break
+ if(istype(thing, /obj/item/melee/baton/doppler_security))
+ has_baton = TRUE
+ if(istype(thing, /obj/item/melee/secblade))
+ has_sword = TRUE
+
+ icon_state = initial(icon_state)
+ worn_icon_state = initial(worn_icon_state)
+
+ var/next_appendage
+ if(has_sword && has_baton)
+ next_appendage = "-full"
+ else if(has_sword)
+ next_appendage = "-blayde"
+ else if(has_baton)
+ next_appendage = "-stun"
+
+ if(next_appendage)
+ icon_state += next_appendage
+ worn_icon_state += next_appendage
+ return ..()
+
+/obj/item/storage/belt/secsword/full/PopulateContents()
+ new /obj/item/melee/secblade(src)
+ new /obj/item/melee/baton/doppler_security/loaded(src)
+ new /obj/item/restraints/handcuffs(src)
+ new /obj/item/reagent_containers/spray/pepper(src)
+ new /obj/item/assembly/flash/handheld(src)
+ update_appearance()
+
+/obj/item/storage/belt/secsword/training/PopulateContents()
+ new /obj/item/melee/secblade/training(src) // No way attack on titan
+ new /obj/item/melee/secblade/training(src)
+ new /obj/item/melee/baton/doppler_security/loaded(src)
+ update_appearance()
diff --git a/modular_doppler/modular_weapons/icons/mob/inhands/melee_lefthand.dmi b/modular_doppler/modular_weapons/icons/mob/inhands/melee_lefthand.dmi
new file mode 100644
index 0000000000000..d7263232529c3
Binary files /dev/null and b/modular_doppler/modular_weapons/icons/mob/inhands/melee_lefthand.dmi differ
diff --git a/modular_doppler/modular_weapons/icons/mob/inhands/melee_righthand.dmi b/modular_doppler/modular_weapons/icons/mob/inhands/melee_righthand.dmi
new file mode 100644
index 0000000000000..41680f8b2fe38
Binary files /dev/null and b/modular_doppler/modular_weapons/icons/mob/inhands/melee_righthand.dmi differ
diff --git a/modular_doppler/modular_weapons/icons/mob/worn/cases.dmi b/modular_doppler/modular_weapons/icons/mob/worn/cases.dmi
index f029c2956292f..eea1dd5794f4a 100644
Binary files a/modular_doppler/modular_weapons/icons/mob/worn/cases.dmi and b/modular_doppler/modular_weapons/icons/mob/worn/cases.dmi differ
diff --git a/modular_doppler/modular_weapons/icons/obj/sec_swords.dmi b/modular_doppler/modular_weapons/icons/obj/sec_swords.dmi
new file mode 100644
index 0000000000000..adfbab70fd885
Binary files /dev/null and b/modular_doppler/modular_weapons/icons/obj/sec_swords.dmi differ
diff --git a/modular_doppler/time_clock/code/console_tgui.dm b/modular_doppler/time_clock/code/console_tgui.dm
index a6734b54ee55d..f19069b9305df 100644
--- a/modular_doppler/time_clock/code/console_tgui.dm
+++ b/modular_doppler/time_clock/code/console_tgui.dm
@@ -2,8 +2,11 @@
#define TIME_CLOCK_RETURN_ITEMS list( \
/obj/item/melee/baton/security, \
/obj/item/melee/baton/security/loaded, \
+ /obj/item/melee/baton/doppler_security, \
+ /obj/item/melee/baton/doppler_security/loaded, \
/obj/item/melee/baton/telescopic, \
/obj/item/melee/baton, \
+ /obj/item/melee/secblade, \
/obj/item/assembly/flash/handheld, \
/obj/item/gun/energy/disabler, \
/obj/item/megaphone/command, \
@@ -25,6 +28,7 @@
/obj/item/clothing/shoes/magboots/advance, \
/obj/item/shield/riot/tele, \
/obj/item/storage/belt/security/full, \
+ /obj/item/storage/belt/secsword/full, \
/obj/item/gun/energy/e_gun/hos, \
/obj/item/pinpointer/nuke, \
/obj/item/gun/energy/e_gun, \
diff --git a/tgstation.dme b/tgstation.dme
index 73aa5a0c84765..d96b19a59796d 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -7173,6 +7173,10 @@
#include "modular_doppler\modular_weapons\code\gunsets.dm"
#include "modular_doppler\modular_weapons\code\jousting.dm"
#include "modular_doppler\modular_weapons\code\melee.dm"
+#include "modular_doppler\modular_weapons\code\sec_swords\baton.dm"
+#include "modular_doppler\modular_weapons\code\sec_swords\big_sword.dm"
+#include "modular_doppler\modular_weapons\code\sec_swords\holodeck_trainer.dm"
+#include "modular_doppler\modular_weapons\code\sec_swords\sheath.dm"
#include "modular_doppler\modular_weapons\company_and_or_faction_based\carwo_defense_systems\gunsets.dm"
#include "modular_doppler\modular_weapons\manufacturer_examine\code\gun_company_additions.dm"
#include "modular_doppler\modular_weapons\manufacturer_examine\code\manufacturer_element.dm"