From 20468c3f15eaf408b2f9250a9195d7ba0c4ea8c7 Mon Sep 17 00:00:00 2001
From: Ghom <42542238+Ghommie@users.noreply.github.com>
Date: Thu, 9 Sep 2021 17:40:20 +0200
Subject: [PATCH] Baton refactor. item/melee/baton is now a subtype of
item/melee/baton (formerly classic_baton) (#61207)
Merged the item/melee/classic_baton and item/melee/baton families in this unholy matrimony.
Bad jokes aside. I have refactored the underlying code of both items with the scope of reducing potential copypasta,inconsistencies, logging, renewing some old code (like teleprods) and extending the anti-dual batoning and TRAIT_STUNRESISTANCE code** to all batons and not just security ones. Otherwise, I have tried to maintain the gameplay functionality of these items intact. They work just like they did for the most part.
** A badly designed feature that only considers one source of knockdowns - stunbatons - out of a multitude of different devices with corresponding purposes present in the game. The only thing it does is reduce the knockdown from them by 90%. The stamina damage and confusion are fully applied. The knockdown from batons is 5 seconds, standing up takes an extra 1 second and the baton cooldown is about 2.5. Doing the math, you'll have the grand advantage of one puny second of not lying horizontal on the floor with this trait before getting batoned again by the same guy because the stamina damage and the confusion have really hampered your chances of getting some distance. I wish to make the trait suck less in the future, but for now I'm including a slight gameplay change here, more for consistency than anything because as I already told you, it'll still be disappointingly bad per se.
The abductor baton is also no more a subtype of stun batons but batons, which don't use power cells to work. Its power cell is effectively infinite and can't be removed, and It overrides functions such as toggling the baton on/off. It hinders maintainability to keep it a subtype of stun batons.
Replaced the anchored check for mobs in teleprods with one for overwhelming move resistance and removed its clumsy_check copypasta (it was stunning clowns twices).
---
.../LavaRuins/lavaland_surface_xeno_nest.dmm | 2 +-
_maps/RandomRuins/SpaceRuins/TheDerelict.dmm | 2 +-
_maps/RandomRuins/SpaceRuins/abandonedzoo.dmm | 2 +-
.../RandomRuins/SpaceRuins/gasthelizards.dmm | 2 +-
.../SpaceRuins/mrow_thats_right.dmm | 4 +-
_maps/RandomZLevels/caves.dmm | 2 +-
_maps/RandomZLevels/moonoutpost19.dmm | 2 +-
_maps/RandomZLevels/research.dmm | 2 +-
_maps/RandomZLevels/snowdin.dmm | 2 +-
_maps/map_files/MetaStation/MetaStation.dmm | 2 +-
_maps/map_files/generic/CentCom.dmm | 8 +-
_maps/shuttles/emergency_pubby.dmm | 2 +-
_maps/shuttles/ruin_pirate_cutter.dmm | 2 +-
_maps/shuttles/whiteship_box.dmm | 2 +-
_maps/shuttles/whiteship_tram.dmm | 2 +-
_maps/templates/holodeck_animeschool.dmm | 2 +-
code/__DEFINES/combat.dm | 8 +
code/__DEFINES/inventory.dm | 5 -
code/_globalvars/lists/maintenance_loot.dm | 4 +-
code/controllers/subsystem/traumas.dm | 4 +-
code/datums/components/crafting/recipes.dm | 8 +-
code/game/machinery/recharger.dm | 10 +-
code/game/objects/items/melee/baton.dm | 656 ++++++++++++++++++
code/game/objects/items/melee/misc.dm | 265 -------
code/game/objects/items/storage/belt.dm | 5 +-
.../game/objects/items/storage/uplink_kits.dm | 2 +-
code/game/objects/items/stunbaton.dm | 352 ----------
code/game/objects/items/teleprod.dm | 44 --
code/game/objects/items/weaponry.dm | 4 +-
.../crates_lockers/closets/gimmick.dm | 4 +-
.../objects/structures/ghost_role_spawners.dm | 2 +-
code/game/objects/structures/watercloset.dm | 32 +-
.../abductor/equipment/abduction_gear.dm | 91 +--
.../awaymissions/mission_code/snowdin.dm | 4 +-
code/modules/cargo/bounties/assistant.dm | 2 +-
code/modules/cargo/exports/weapons.dm | 4 +-
code/modules/cargo/packs.dm | 6 +-
code/modules/clothing/outfits/ert.dm | 30 +-
code/modules/clothing/suits/bio.dm | 2 +-
code/modules/clothing/suits/labcoat.dm | 4 +-
code/modules/clothing/suits/wintercoats.dm | 8 +-
code/modules/explorer_drone/loot.dm | 2 +-
code/modules/jobs/job_types/captain.dm | 2 +-
code/modules/jobs/job_types/chief_engineer.dm | 2 +-
.../jobs/job_types/chief_medical_officer.dm | 2 +-
code/modules/jobs/job_types/detective.dm | 2 +-
.../jobs/job_types/head_of_personnel.dm | 2 +-
.../jobs/job_types/head_of_security.dm | 4 +-
.../jobs/job_types/research_director.dm | 2 +-
.../jobs/job_types/security_officer.dm | 4 +-
code/modules/jobs/job_types/warden.dm | 2 +-
code/modules/mining/abandoned_crates.dm | 2 +-
.../mob/living/silicon/robot/robot_modules.dm | 9 +-
.../living/simple_animal/bot/construction.dm | 2 +-
.../mob/living/simple_animal/bot/secbot.dm | 2 +-
.../research/designs/weapon_designs.dm | 2 +-
code/modules/surgery/revival.dm | 8 +-
tgstation.dme | 3 +-
58 files changed, 810 insertions(+), 838 deletions(-)
create mode 100644 code/game/objects/items/melee/baton.dm
delete mode 100644 code/game/objects/items/stunbaton.dm
delete mode 100644 code/game/objects/items/teleprod.dm
diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_xeno_nest.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_xeno_nest.dmm
index d0bb6f6db9a..45d59812bb2 100644
--- a/_maps/RandomRuins/LavaRuins/lavaland_surface_xeno_nest.dmm
+++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_xeno_nest.dmm
@@ -85,7 +85,7 @@
/obj/effect/decal/cleanable/blood/gibs,
/obj/item/clothing/under/rank/security/officer,
/obj/item/clothing/suit/armor/vest,
-/obj/item/melee/baton/loaded,
+/obj/item/melee/baton/security/loaded,
/obj/item/clothing/head/helmet,
/turf/open/floor/plating/asteroid/basalt/lava_land_surface,
/area/ruin/unpowered/xenonest)
diff --git a/_maps/RandomRuins/SpaceRuins/TheDerelict.dmm b/_maps/RandomRuins/SpaceRuins/TheDerelict.dmm
index f2c587a41f7..696453702a2 100644
--- a/_maps/RandomRuins/SpaceRuins/TheDerelict.dmm
+++ b/_maps/RandomRuins/SpaceRuins/TheDerelict.dmm
@@ -491,7 +491,7 @@
/area/ruin/space/derelict/bridge/access)
"cy" = (
/obj/structure/rack,
-/obj/item/melee/classic_baton,
+/obj/item/melee/baton,
/turf/open/floor/iron,
/area/ruin/space/derelict/bridge/access)
"cz" = (
diff --git a/_maps/RandomRuins/SpaceRuins/abandonedzoo.dmm b/_maps/RandomRuins/SpaceRuins/abandonedzoo.dmm
index e52c3efbb63..1b479fda27f 100644
--- a/_maps/RandomRuins/SpaceRuins/abandonedzoo.dmm
+++ b/_maps/RandomRuins/SpaceRuins/abandonedzoo.dmm
@@ -179,7 +179,7 @@
pixel_x = -25
},
/obj/structure/rack,
-/obj/item/melee/baton/cattleprod,
+/obj/item/melee/baton/security/cattleprod,
/obj/effect/spawner/lootdrop/maintenance,
/obj/structure/cable,
/turf/open/floor/iron/dark/side,
diff --git a/_maps/RandomRuins/SpaceRuins/gasthelizards.dmm b/_maps/RandomRuins/SpaceRuins/gasthelizards.dmm
index 0bb6c7036e6..a9582a09ed7 100644
--- a/_maps/RandomRuins/SpaceRuins/gasthelizards.dmm
+++ b/_maps/RandomRuins/SpaceRuins/gasthelizards.dmm
@@ -263,7 +263,7 @@
"J" = (
/obj/structure/rack,
/obj/item/storage/toolbox/drone,
-/obj/item/melee/baton/cattleprod,
+/obj/item/melee/baton/security/cattleprod,
/turf/open/floor/iron,
/area/ruin/space/has_grav/gasthelizard)
"K" = (
diff --git a/_maps/RandomRuins/SpaceRuins/mrow_thats_right.dmm b/_maps/RandomRuins/SpaceRuins/mrow_thats_right.dmm
index 7791bf72bb5..807c112eda8 100644
--- a/_maps/RandomRuins/SpaceRuins/mrow_thats_right.dmm
+++ b/_maps/RandomRuins/SpaceRuins/mrow_thats_right.dmm
@@ -469,8 +469,8 @@
/area/ruin/space/has_grav/powered/cat_man)
"bx" = (
/obj/structure/rack,
-/obj/item/melee/baton/cattleprod,
-/obj/item/melee/baton/cattleprod,
+/obj/item/melee/baton/security/cattleprod,
+/obj/item/melee/baton/security/cattleprod,
/obj/item/restraints/handcuffs,
/obj/item/restraints/handcuffs,
/turf/open/floor/carpet,
diff --git a/_maps/RandomZLevels/caves.dmm b/_maps/RandomZLevels/caves.dmm
index 6bbfabd94ce..2e976fbd99c 100644
--- a/_maps/RandomZLevels/caves.dmm
+++ b/_maps/RandomZLevels/caves.dmm
@@ -856,7 +856,7 @@
/area/awaymission/caves/research)
"cX" = (
/obj/structure/table,
-/obj/item/melee/baton,
+/obj/item/melee/baton/security,
/turf/open/floor/iron{
initial_gas_mix = "n2=23;o2=14;TEMP=2.7"
},
diff --git a/_maps/RandomZLevels/moonoutpost19.dmm b/_maps/RandomZLevels/moonoutpost19.dmm
index ea6a2fa738d..50f8436a74e 100644
--- a/_maps/RandomZLevels/moonoutpost19.dmm
+++ b/_maps/RandomZLevels/moonoutpost19.dmm
@@ -164,7 +164,7 @@
/obj/item/clothing/mask/facehugger/impregnated,
/obj/item/clothing/under/rank/security/officer,
/obj/item/clothing/suit/armor/vest,
-/obj/item/melee/baton/loaded,
+/obj/item/melee/baton/security/loaded,
/obj/item/clothing/head/helmet,
/turf/open/floor/plating/asteroid{
heat_capacity = 1e+006;
diff --git a/_maps/RandomZLevels/research.dmm b/_maps/RandomZLevels/research.dmm
index 18744ac612d..544673fc7a3 100644
--- a/_maps/RandomZLevels/research.dmm
+++ b/_maps/RandomZLevels/research.dmm
@@ -3016,7 +3016,7 @@
/turf/open/floor/iron/white,
/area/awaymission/research/interior/cryo)
"gR" = (
-/obj/item/melee/classic_baton/telescopic,
+/obj/item/melee/baton/telescopic,
/obj/effect/turf_decal/tile/purple{
dir = 1
},
diff --git a/_maps/RandomZLevels/snowdin.dmm b/_maps/RandomZLevels/snowdin.dmm
index efa24a9ba6f..d9740c16474 100644
--- a/_maps/RandomZLevels/snowdin.dmm
+++ b/_maps/RandomZLevels/snowdin.dmm
@@ -11334,7 +11334,7 @@
/obj/item/clothing/head/helmet{
pixel_y = 8
},
-/obj/item/melee/baton{
+/obj/item/melee/baton/security{
pixel_x = 4
},
/turf/open/floor/plating/asteroid/snow,
diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm
index d780c0cc682..3e75df4262d 100644
--- a/_maps/map_files/MetaStation/MetaStation.dmm
+++ b/_maps/map_files/MetaStation/MetaStation.dmm
@@ -24056,7 +24056,7 @@
"gkw" = (
/obj/structure/safe,
/obj/item/storage/secure/briefcase{
- contents = newlist(/obj/item/clothing/suit/armor/vest,/obj/item/gun/ballistic/automatic/pistol,/obj/item/suppressor,/obj/item/melee/classic_baton/telescopic,/obj/item/clothing/mask/balaclava,/obj/item/bodybag,/obj/item/soap/nanotrasen)
+ contents = newlist(/obj/item/clothing/suit/armor/vest,/obj/item/gun/ballistic/automatic/pistol,/obj/item/suppressor,/obj/item/melee/baton/telescopic,/obj/item/clothing/mask/balaclava,/obj/item/bodybag,/obj/item/soap/nanotrasen)
},
/obj/item/storage/backpack/duffelbag/syndie/hitman,
/obj/item/card/id/advanced/silver/reaper,
diff --git a/_maps/map_files/generic/CentCom.dmm b/_maps/map_files/generic/CentCom.dmm
index 2f7f7edc161..35ffe84198f 100644
--- a/_maps/map_files/generic/CentCom.dmm
+++ b/_maps/map_files/generic/CentCom.dmm
@@ -111,7 +111,7 @@
/obj/item/clothing/shoes/sneakers/brown,
/obj/item/clothing/suit/armor/tdome/red,
/obj/item/clothing/head/helmet/thunderdome,
-/obj/item/melee/baton/loaded,
+/obj/item/melee/baton/security/loaded,
/obj/item/melee/energy/sword/saber/red,
/obj/effect/turf_decal/stripes/line{
dir = 4
@@ -182,7 +182,7 @@
/obj/item/clothing/shoes/sneakers/brown,
/obj/item/clothing/suit/armor/tdome/green,
/obj/item/clothing/head/helmet/thunderdome,
-/obj/item/melee/baton/loaded,
+/obj/item/melee/baton/security/loaded,
/obj/item/melee/energy/sword/saber/green,
/obj/effect/turf_decal/stripes/line{
dir = 8
@@ -12151,7 +12151,7 @@
/obj/item/clothing/shoes/sneakers/brown,
/obj/item/clothing/suit/armor/tdome/red,
/obj/item/clothing/head/helmet/thunderdome,
-/obj/item/melee/baton/loaded,
+/obj/item/melee/baton/security/loaded,
/obj/item/melee/energy/sword/saber/red,
/obj/effect/turf_decal/stripes/line{
dir = 4
@@ -12275,7 +12275,7 @@
/obj/item/clothing/shoes/sneakers/brown,
/obj/item/clothing/suit/armor/tdome/green,
/obj/item/clothing/head/helmet/thunderdome,
-/obj/item/melee/baton/loaded,
+/obj/item/melee/baton/security/loaded,
/obj/item/melee/energy/sword/saber/green,
/obj/effect/turf_decal/stripes/line{
dir = 8
diff --git a/_maps/shuttles/emergency_pubby.dmm b/_maps/shuttles/emergency_pubby.dmm
index 7f3fa041b22..5a503d0e380 100644
--- a/_maps/shuttles/emergency_pubby.dmm
+++ b/_maps/shuttles/emergency_pubby.dmm
@@ -608,7 +608,7 @@
"bz" = (
/obj/structure/table/reinforced,
/obj/item/restraints/handcuffs,
-/obj/item/melee/baton,
+/obj/item/melee/baton/security,
/turf/open/floor/mineral/plastitanium/red/brig,
/area/shuttle/escape/brig)
"bA" = (
diff --git a/_maps/shuttles/ruin_pirate_cutter.dmm b/_maps/shuttles/ruin_pirate_cutter.dmm
index b9bd78ba0de..fadc30ff55b 100644
--- a/_maps/shuttles/ruin_pirate_cutter.dmm
+++ b/_maps/shuttles/ruin_pirate_cutter.dmm
@@ -991,7 +991,7 @@
"Xq" = (
/obj/structure/table/reinforced,
/obj/machinery/recharger,
-/obj/item/melee/classic_baton,
+/obj/item/melee/baton,
/obj/effect/turf_decal/tile/red,
/turf/open/floor/iron/dark,
/area/shuttle/caravan/pirate)
diff --git a/_maps/shuttles/whiteship_box.dmm b/_maps/shuttles/whiteship_box.dmm
index 4728d36e876..218f32bf7b4 100644
--- a/_maps/shuttles/whiteship_box.dmm
+++ b/_maps/shuttles/whiteship_box.dmm
@@ -1898,7 +1898,7 @@
/obj/structure/rack,
/obj/item/storage/box/zipties,
/obj/item/assembly/flash/handheld,
-/obj/item/melee/classic_baton/telescopic,
+/obj/item/melee/baton/telescopic,
/obj/machinery/light/small/built/directional/west,
/obj/machinery/airalarm/all_access{
dir = 4;
diff --git a/_maps/shuttles/whiteship_tram.dmm b/_maps/shuttles/whiteship_tram.dmm
index 127b179181a..0db5c869dfe 100644
--- a/_maps/shuttles/whiteship_tram.dmm
+++ b/_maps/shuttles/whiteship_tram.dmm
@@ -1295,7 +1295,7 @@
/obj/effect/decal/cleanable/dirt,
/obj/item/storage/box/zipties,
/obj/item/assembly/flash/handheld,
-/obj/item/melee/classic_baton/telescopic,
+/obj/item/melee/baton/telescopic,
/turf/open/floor/mineral/titanium/tiled/blue,
/area/shuttle/abandoned/bridge)
"ds" = (
diff --git a/_maps/templates/holodeck_animeschool.dmm b/_maps/templates/holodeck_animeschool.dmm
index 117dab6e78e..6b5afca430c 100644
--- a/_maps/templates/holodeck_animeschool.dmm
+++ b/_maps/templates/holodeck_animeschool.dmm
@@ -63,7 +63,7 @@
"Y" = (
/obj/structure/table/wood,
/obj/item/folder,
-/obj/item/melee/classic_baton/telescopic,
+/obj/item/melee/baton/telescopic,
/turf/open/floor/holofloor,
/area/template_noop)
diff --git a/code/__DEFINES/combat.dm b/code/__DEFINES/combat.dm
index 4e7480888b7..3d378b53d2a 100644
--- a/code/__DEFINES/combat.dm
+++ b/code/__DEFINES/combat.dm
@@ -309,3 +309,11 @@ GLOBAL_LIST_INIT(shove_disarming_types, typecacheof(list(
/// IF an object is weak against armor, this is the value that any present armor is multiplied by
#define ARMOR_WEAKENED_MULTIPLIER 2
+
+/// Return values used in item/melee/baton/baton_attack.
+/// Does a normal item attack.
+#define BATON_DO_NORMAL_ATTACK 1
+/// The attack has been stopped. Either because the user was clumsy or the attack was blocked.
+#define BATON_ATTACK_DONE 2
+/// The baton attack is still going. baton_effect() is called.
+#define BATON_ATTACKING 3
diff --git a/code/__DEFINES/inventory.dm b/code/__DEFINES/inventory.dm
index e9dfa9ed70f..12627a95a9a 100644
--- a/code/__DEFINES/inventory.dm
+++ b/code/__DEFINES/inventory.dm
@@ -157,7 +157,6 @@ GLOBAL_LIST_INIT(advanced_hardsuit_allowed, typecacheof(list(
/obj/item/flashlight,
/obj/item/gun,
/obj/item/melee/baton,
- /obj/item/melee/classic_baton,
/obj/item/reagent_containers/spray/pepper,
/obj/item/restraints/handcuffs,
/obj/item/tank/internals,
@@ -170,7 +169,6 @@ GLOBAL_LIST_INIT(security_hardsuit_allowed, typecacheof(list(
/obj/item/gun/ballistic,
/obj/item/gun/energy,
/obj/item/melee/baton,
- /obj/item/melee/classic_baton,
/obj/item/reagent_containers/spray/pepper,
/obj/item/restraints/handcuffs,
/obj/item/tank/internals,
@@ -185,7 +183,6 @@ GLOBAL_LIST_INIT(detective_vest_allowed, typecacheof(list(
/obj/item/gun/energy,
/obj/item/lighter,
/obj/item/melee/baton,
- /obj/item/melee/classic_baton,
/obj/item/reagent_containers/spray/pepper,
/obj/item/restraints/handcuffs,
/obj/item/storage/fancy/cigarettes,
@@ -204,7 +201,6 @@ GLOBAL_LIST_INIT(security_vest_allowed, typecacheof(list(
/obj/item/gun/energy,
/obj/item/kitchen/knife/combat,
/obj/item/melee/baton,
- /obj/item/melee/classic_baton,
/obj/item/reagent_containers/spray/pepper,
/obj/item/restraints/handcuffs,
/obj/item/tank/internals/emergency_oxygen,
@@ -219,7 +215,6 @@ GLOBAL_LIST_INIT(security_wintercoat_allowed, typecacheof(list(
/obj/item/gun/ballistic,
/obj/item/gun/energy,
/obj/item/melee/baton,
- /obj/item/melee/classic_baton,
/obj/item/reagent_containers/spray/pepper,
/obj/item/restraints/handcuffs,
/obj/item/storage/belt/holster/detective,
diff --git a/code/_globalvars/lists/maintenance_loot.dm b/code/_globalvars/lists/maintenance_loot.dm
index 45f22771f41..d86a9b79545 100644
--- a/code/_globalvars/lists/maintenance_loot.dm
+++ b/code/_globalvars/lists/maintenance_loot.dm
@@ -169,7 +169,7 @@ GLOBAL_LIST_INIT(uncommon_loot, list(//uncommon: useful items
/obj/item/restraints/handcuffs/cable = 1,
/obj/item/spear = 1,
/obj/item/grenade/iedcasing/spawned = 1,
- /obj/item/melee/baton/cattleprod = 1,
+ /obj/item/melee/baton/security/cattleprod = 1,
/obj/item/pen/fountain = 1,
) = 8,
@@ -271,7 +271,7 @@ GLOBAL_LIST_INIT(rarity_loot, list(//rare: really good items
/obj/item/kitchen/knife = 1,
/obj/item/restraints/handcuffs = 1,
/obj/item/shield/riot/buckler = 1,
- /obj/item/melee/baton/cattleprod/teleprod = 1,
+ /obj/item/melee/baton/security/cattleprod/teleprod = 1,
/obj/item/throwing_star = 1,
/obj/item/pen/survival = 1,
/obj/item/flashlight/flashdark = 1,
diff --git a/code/controllers/subsystem/traumas.dm b/code/controllers/subsystem/traumas.dm
index 088c90db696..c0da85d7275 100644
--- a/code/controllers/subsystem/traumas.dm
+++ b/code/controllers/subsystem/traumas.dm
@@ -79,7 +79,7 @@ SUBSYSTEM_DEF(traumas)
/obj/item/trash/cheesie,
)),
- "greytide" = typecacheof(list(/obj/item/clothing/under/color/grey, /obj/item/melee/baton/cattleprod,
+ "greytide" = typecacheof(list(/obj/item/clothing/under/color/grey, /obj/item/melee/baton/security/cattleprod,
/obj/item/spear, /obj/item/clothing/mask/gas,
)),
@@ -124,7 +124,7 @@ SUBSYSTEM_DEF(traumas)
/obj/item/clothing/under/rank/security/head_of_security, /obj/item/clothing/under/rank/rnd/research_director,
/obj/item/clothing/under/rank/medical/chief_medical_officer, /obj/item/clothing/under/rank/engineering/chief_engineer,
/obj/item/clothing/under/rank/centcom/officer, /obj/item/clothing/under/rank/centcom/commander,
- /obj/item/melee/classic_baton/telescopic, /obj/item/card/id/advanced/silver, /obj/item/card/id/advanced/gold,
+ /obj/item/melee/baton/telescopic, /obj/item/card/id/advanced/silver, /obj/item/card/id/advanced/gold,
/obj/item/card/id/advanced/centcom, /obj/machinery/door/airlock/command, /obj/item/card/id/advanced/black,
)),
diff --git a/code/datums/components/crafting/recipes.dm b/code/datums/components/crafting/recipes.dm
index 90fdacc0a00..badf9801541 100644
--- a/code/datums/components/crafting/recipes.dm
+++ b/code/datums/components/crafting/recipes.dm
@@ -95,7 +95,7 @@
/datum/crafting_recipe/stunprod
name = "Stunprod"
- result = /obj/item/melee/baton/cattleprod
+ result = /obj/item/melee/baton/security/cattleprod
reqs = list(/obj/item/restraints/handcuffs/cable = 1,
/obj/item/stack/rods = 1,
/obj/item/assembly/igniter = 1)
@@ -105,7 +105,7 @@
/datum/crafting_recipe/teleprod
name = "Teleprod"
- result = /obj/item/melee/baton/cattleprod/teleprod
+ result = /obj/item/melee/baton/security/cattleprod/teleprod
reqs = list(/obj/item/restraints/handcuffs/cable = 1,
/obj/item/stack/rods = 1,
/obj/item/assembly/igniter = 1,
@@ -341,7 +341,7 @@
result = /mob/living/simple_animal/bot/secbot
reqs = list(/obj/item/assembly/signaler = 1,
/obj/item/clothing/head/helmet/sec = 1,
- /obj/item/melee/baton = 1,
+ /obj/item/melee/baton/security/ = 1,
/obj/item/assembly/prox_sensor = 1,
/obj/item/bodypart/r_arm/robot = 1)
tool_behaviors = list(TOOL_WELDER)
@@ -539,7 +539,7 @@
/obj/item/spear = 1,
/obj/item/storage/toolbox= 1)
tool_behaviors = list(TOOL_SCREWDRIVER)
- tool_paths = list(/obj/item/clothing/gloves/color/yellow, /obj/item/clothing/mask/gas, /obj/item/melee/baton/cattleprod)
+ tool_paths = list(/obj/item/clothing/gloves/color/yellow, /obj/item/clothing/mask/gas, /obj/item/melee/baton/security/cattleprod)
time = 300 //contemplate for a bit
category = CAT_WEAPONRY
subcategory = CAT_WEAPON
diff --git a/code/game/machinery/recharger.dm b/code/game/machinery/recharger.dm
index 800af0d2c39..7c72604a9b3 100755
--- a/code/game/machinery/recharger.dm
+++ b/code/game/machinery/recharger.dm
@@ -17,7 +17,7 @@
var/static/list/allowed_devices = typecacheof(list(
/obj/item/gun/energy,
- /obj/item/melee/baton,
+ /obj/item/melee/baton/security,
/obj/item/ammo_box/magazine/recharge,
/obj/item/modular_computer))
@@ -167,10 +167,10 @@
if(E.cell)
E.cell.emp_act(severity)
- else if(istype(charging, /obj/item/melee/baton))
- var/obj/item/melee/baton/B = charging
- if(B.cell)
- B.cell.charge = 0
+ else if(istype(charging, /obj/item/melee/baton/security))
+ var/obj/item/melee/baton/security/batong = charging
+ if(batong.cell)
+ batong.cell.charge = 0
/obj/machinery/recharger/update_appearance(updates)
. = ..()
diff --git a/code/game/objects/items/melee/baton.dm b/code/game/objects/items/melee/baton.dm
new file mode 100644
index 00000000000..54b0ca0db81
--- /dev/null
+++ b/code/game/objects/items/melee/baton.dm
@@ -0,0 +1,656 @@
+/obj/item/melee/baton
+ name = "police baton"
+ desc = "A wooden truncheon for beating criminal scum. Left click to stun, right click to harm."
+ icon = 'icons/obj/items_and_weapons.dmi'
+ icon_state = "classic_baton"
+ inhand_icon_state = "classic_baton"
+ worn_icon_state = "classic_baton"
+ lefthand_file = 'icons/mob/inhands/equipment/security_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/equipment/security_righthand.dmi'
+ slot_flags = ITEM_SLOT_BELT
+ force = 12 //9 hit crit
+ w_class = WEIGHT_CLASS_NORMAL
+ wound_bonus = 15
+
+ /// Whether this baton is active or not
+ var/active = TRUE
+ /// Used interally, you don't want to modify
+ var/cooldown_check = 0
+ /// Default wait time until can stun again.
+ var/cooldown = (4 SECONDS)
+ /// The length of the knockdown applied to a struck living, non-cyborg mob.
+ var/knockdown_time = (1.5 SECONDS)
+ /// If affect_cyborg is TRUE, this is how long we stun cyborgs for on a hit.
+ var/stun_time_cyborg = (5 SECONDS)
+ /// The length of the knockdown applied to the user on clumsy_check()
+ var/clumsy_knockdown_time = 18 SECONDS
+ /// How much stamina damage we deal on a successful hit against a living, non-cyborg mob.
+ var/stamina_damage = 55
+ /// Can we stun cyborgs?
+ var/affect_cyborg = FALSE
+ /// The path of the default sound to play when we stun something.
+ var/on_stun_sound = 'sound/effects/woodhit.ogg'
+ /// The volume of the above.
+ var/on_stun_volume = 75
+ /// Do we animate the "hit" when stunning something?
+ var/stun_animation = TRUE
+ /// Whether the stun attack is logged. Only relevant for abductor batons, which have different modes.
+ var/log_stun_attack = TRUE
+
+/obj/item/melee/baton/Initialize()
+ . = ..()
+ // Adding an extra break for the sake of presentation
+ if(stamina_damage != 0)
+ offensive_notes = "\nVarious interviewed security forces report being able to beat criminals into exhaustion with only [span_warning("[CEILING(100 / stamina_damage, 1)] hit\s!")]"
+
+/**
+ * Ok, think of baton attacks like a melee attack chain:
+ *
+ * [/baton_attack()] comes first. It checks if the user is clumsy, if the target parried the attack and handles some messages and sounds.
+ * * Depending on its return value, it'll either do a normal attack, continue to the next step or stop the attack.
+ *
+ * [/finalize_baton_attack()] is then called. It handles logging stuff, sound effects and calls baton_effect().
+ * * The proc is also called in other situations such as stunbatons right clicking or throw impact. Basically when baton_attack()
+ * * checks are either redundant or unnecessary.
+ *
+ * [/baton_effect()] is third in the line. It knockdowns targets, along other effects called in additional_effects_cyborg() and
+ * * additional_effects_non_cyborg().
+ *
+ * Last but not least [/set_batoned()], which gives the target the IWASBATONED trait with REF(user) as source and then removes it
+ * * after a cooldown has passed. Basically, it stops users from cheesing the cooldowns by dual wielding batons.
+ *
+ * TL;DR: [/baton_attack()] -> [/finalize_baton_attack()] -> [/baton_effect()] -> [/set_batoned()]
+ */
+/obj/item/melee/baton/attack(mob/living/target, mob/living/user, params)
+ add_fingerprint(user)
+ var/list/modifiers = params2list(params)
+ switch(baton_attack(target, user, modifiers))
+ if(BATON_DO_NORMAL_ATTACK)
+ return ..()
+ if(BATON_ATTACKING)
+ finalize_baton_attack(target, user, modifiers)
+
+/obj/item/melee/baton/proc/baton_attack(mob/living/target, mob/living/user, modifiers)
+ . = BATON_ATTACKING
+
+ if(clumsy_check(user, target))
+ return BATON_ATTACK_DONE
+
+ if(!active || LAZYACCESS(modifiers, RIGHT_CLICK))
+ return BATON_DO_NORMAL_ATTACK
+
+ if(cooldown_check > world.time)
+ var/wait_desc = get_wait_description()
+ if (wait_desc)
+ to_chat(user, wait_desc)
+ return BATON_ATTACK_DONE
+
+ if(check_parried(target, user))
+ return BATON_ATTACK_DONE
+
+ if(HAS_TRAIT_FROM(target, TRAIT_IWASBATONED, REF(user))) //no doublebaton abuse anon!
+ to_chat(user, span_danger("You fumble and miss [target]!"))
+ return BATON_ATTACK_DONE
+
+ if(stun_animation)
+ user.do_attack_animation(target)
+
+ var/list/desc
+
+ if(iscyborg(target))
+ if(affect_cyborg)
+ desc = get_cyborg_stun_description(target, user)
+ else
+ desc = get_unga_dunga_cyborg_stun_description(target, user)
+ playsound(get_turf(src), 'sound/effects/bang.ogg', 10, TRUE) //bonk
+ . = BATON_ATTACK_DONE
+ else
+ desc = get_stun_description(target, user)
+
+ if(desc)
+ target.visible_message(desc["visible"], desc["local"])
+
+/obj/item/melee/baton/proc/check_parried(mob/living/carbon/human/human_target, mob/living/user)
+ if(!ishuman(human_target))
+ return
+ if (human_target.check_shields(src, 0, "[user]'s [name]", MELEE_ATTACK))
+ playsound(human_target, 'sound/weapons/genhit.ogg', 50, TRUE)
+ return TRUE
+ if(check_martial_counter(human_target, user))
+ return TRUE
+
+/obj/item/melee/baton/proc/finalize_baton_attack(mob/living/target, mob/living/user, modifiers, in_attack_chain = TRUE)
+ if(!in_attack_chain && HAS_TRAIT_FROM(target, TRAIT_IWASBATONED, REF(user)))
+ return BATON_ATTACK_DONE
+
+ cooldown_check = world.time + cooldown
+ if(on_stun_sound)
+ playsound(get_turf(src), on_stun_sound, on_stun_volume, TRUE, -1)
+ if(user)
+ target.lastattacker = user.real_name
+ target.lastattackerckey = user.ckey
+ target.LAssailant = WEAKREF(user)
+ if(log_stun_attack)
+ log_combat(user, target, "stun attacked", src)
+ if(baton_effect(target, user, modifiers) && user)
+ set_batoned(target, user, cooldown)
+
+/obj/item/melee/baton/proc/baton_effect(mob/living/target, mob/living/user, modifiers, stun_override)
+ var/trait_check = HAS_TRAIT(target, TRAIT_STUNRESISTANCE)
+ if(iscyborg(target))
+ if(!affect_cyborg)
+ return FALSE
+ target.flash_act(affect_silicon = TRUE)
+ target.Paralyze((isnull(stun_override) ? stun_time_cyborg : stun_override) * (trait_check ? 0.1 : 1))
+ additional_effects_cyborg(target, user)
+ else
+ target.apply_damage(stamina_damage, STAMINA, BODY_ZONE_CHEST)
+ target.Knockdown((isnull(stun_override) ? knockdown_time : stun_override) * (trait_check ? 0.1 : 1))
+ additional_effects_non_cyborg(target, user)
+ return TRUE
+
+/// Description for trying to stun when still on cooldown.
+/obj/item/melee/baton/proc/get_wait_description()
+ return
+
+/// Default message for stunning a living, non-cyborg mob.
+/obj/item/melee/baton/proc/get_stun_description(mob/living/target, mob/living/user)
+ . = list()
+
+ .["visible"] = "[user] knocks [target] down with [src]!"
+ .["local"] = "[user] knocks you down with [src]!"
+
+ return .
+
+/// Default message for stunning a cyborg.
+/obj/item/melee/baton/proc/get_cyborg_stun_description(mob/living/target, mob/living/user)
+ . = list()
+
+ .["visible"] = span_danger("[user] pulses [target]'s sensors with the baton!")
+ .["local"] = span_danger("You pulse [target]'s sensors with the baton!")
+
+ return .
+
+/// Default message for trying to stun a cyborg with a baton that can't stun cyborgs.
+/obj/item/melee/baton/proc/get_unga_dunga_cyborg_stun_description(mob/living/target, mob/living/user)
+ . = list()
+
+ .["visible"] = "[user] tries to knock down [target] with [src], and predictably fails!" //look at this duuuuuude
+ .["local"] = "[target] tries to... knock you down with [src]?" //look at the top of his head!
+
+ return .
+
+/// Contains any special effects that we apply to living, non-cyborg mobs we stun. Does not include applying a knockdown, dealing stamina damage, etc.
+/obj/item/melee/baton/proc/additional_effects_non_cyborg(mob/living/target, mob/living/user)
+ return
+
+/// Contains any special effects that we apply to cyborgs we stun. Does not include flashing the cyborg's screen, hardstunning them, etc.
+/obj/item/melee/baton/proc/additional_effects_cyborg(mob/living/target, mob/living/user)
+ return
+
+/obj/item/melee/baton/proc/set_batoned(mob/living/target, mob/living/user, cooldown)
+ if(!cooldown)
+ return
+ var/user_ref = REF(user) // avoids harddels.
+ ADD_TRAIT(target, TRAIT_IWASBATONED, user_ref)
+ addtimer(TRAIT_CALLBACK_REMOVE(target, TRAIT_IWASBATONED, user_ref), cooldown)
+
+/obj/item/melee/baton/proc/clumsy_check(mob/living/user, mob/living/intented_target)
+ if(!active || !HAS_TRAIT(user, TRAIT_CLUMSY) || prob(50))
+ return FALSE
+ user.visible_message(span_danger("[user] accidentally hits [user.p_them()]self over the head with [src]! What a doofus!"), span_userdanger("You accidentally hit yourself over the head with [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/effects/bang.ogg', 10, TRUE)
+ else
+ user.Knockdown(clumsy_knockdown_time)
+ user.apply_damage(stamina_damage, STAMINA, BODY_ZONE_HEAD)
+ additional_effects_non_cyborg(user, user) // user is the target here
+ if(on_stun_sound)
+ playsound(get_turf(src), on_stun_sound, on_stun_volume, TRUE, -1)
+
+ user.apply_damage(2*force, BRUTE, BODY_ZONE_HEAD)
+
+ log_combat(user, user, "accidentally stun attacked [user.p_them()]self due to their clumsiness", src)
+ if(stun_animation)
+ user.do_attack_animation(user)
+ return
+
+/obj/item/conversion_kit
+ name = "conversion kit"
+ desc = "A strange box containing wood working tools and an instruction paper to turn stun batons into something else."
+ icon = 'icons/obj/storage.dmi'
+ icon_state = "uk"
+ custom_price = PAYCHECK_HARD * 4.5
+
+/obj/item/melee/baton/telescopic
+ name = "telescopic baton"
+ desc = "A compact yet robust personal defense weapon. Can be concealed when folded."
+ icon_state = "telebaton"
+ lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi'
+ inhand_icon_state = null
+ attack_verb_continuous = list("hits", "pokes")
+ attack_verb_simple = list("hit", "poke")
+ worn_icon_state = "tele_baton"
+ slot_flags = ITEM_SLOT_BELT
+ w_class = WEIGHT_CLASS_SMALL
+ item_flags = NONE
+ force = 0
+ bare_wound_bonus = 5
+ clumsy_knockdown_time = 15 SECONDS
+ active = FALSE
+
+ /// The sound effecte played when our baton is extended.
+ var/on_sound = 'sound/weapons/batonextend.ogg'
+ /// The inhand iconstate used when our baton is extended.
+ var/on_inhand_icon_state = "nullrod"
+ /// The force on extension.
+ var/active_force = 10
+
+/obj/item/melee/baton/telescopic/Initialize()
+ . = ..()
+ AddComponent(/datum/component/transforming, \
+ force_on = active_force, \
+ hitsound_on = hitsound, \
+ w_class_on = WEIGHT_CLASS_NORMAL, \
+ clumsy_check = FALSE, \
+ attack_verb_continuous_on = list("smacks", "strikes", "cracks", "beats"), \
+ attack_verb_simple_on = list("smack", "strike", "crack", "beat"))
+ RegisterSignal(src, COMSIG_TRANSFORMING_ON_TRANSFORM, .proc/on_transform)
+
+/obj/item/melee/baton/telescopic/suicide_act(mob/user)
+ var/mob/living/carbon/human/human_user = user
+ var/obj/item/organ/brain/our_brain = human_user.getorgan(/obj/item/organ/brain)
+
+ user.visible_message(span_suicide("[user] stuffs [src] up [user.p_their()] nose and presses the 'extend' button! It looks like [user.p_theyre()] trying to clear [user.p_their()] mind."))
+ if(active)
+ playsound(src, on_sound, 50, TRUE)
+ add_fingerprint(user)
+ else
+ attack_self(user)
+
+ sleep(3)
+ if (!QDELETED(human_user))
+ if(!QDELETED(our_brain))
+ human_user.internal_organs -= our_brain
+ qdel(our_brain)
+ new /obj/effect/gibspawner/generic(human_user.drop_location(), human_user)
+ return (BRUTELOSS)
+
+/*
+ * Signal proc for [COMSIG_TRANSFORMING_ON_TRANSFORM].
+ *
+ * Gives feedback to the user and makes it show up inhand.
+ */
+/obj/item/melee/baton/telescopic/proc/on_transform(obj/item/source, mob/user, active)
+ SIGNAL_HANDLER
+
+ src.active = active
+ inhand_icon_state = active ? on_inhand_icon_state : null // When inactive, there is no inhand icon_state.
+ balloon_alert(user, active ? "extended" : "collapsed")
+ playsound(user ? user : src, on_sound, 50, TRUE)
+ return COMPONENT_NO_DEFAULT_MESSAGE
+
+/obj/item/melee/baton/telescopic/contractor_baton
+ name = "contractor baton"
+ desc = "A compact, specialised baton assigned to Syndicate contractors. Applies light electrical shocks to targets."
+ icon = 'icons/obj/items_and_weapons.dmi'
+ icon_state = "contractor_baton"
+ worn_icon_state = "contractor_baton"
+ lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi'
+ slot_flags = ITEM_SLOT_BELT
+ w_class = WEIGHT_CLASS_SMALL
+ item_flags = NONE
+ force = 5
+ cooldown = 2.5 SECONDS
+ stamina_damage = 85
+ clumsy_knockdown_time = 24 SECONDS
+ affect_cyborg = TRUE
+ on_stun_sound = 'sound/effects/contractorbatonhit.ogg'
+
+ on_inhand_icon_state = "contractor_baton_on"
+ on_sound = 'sound/weapons/contractorbatonextend.ogg'
+ active_force = 16
+
+/obj/item/melee/baton/telescopic/contractor_baton/get_wait_description()
+ return span_danger("The baton is still charging!")
+
+/obj/item/melee/baton/telescopic/contractor_baton/additional_effects_non_cyborg(mob/living/target, mob/living/user)
+ target.Jitter(20)
+ target.stuttering += 20
+
+/obj/item/melee/baton/security
+ name = "stun baton"
+ desc = "A stun baton for incapacitating people with. Left click to stun, right click to harm."
+
+ icon_state = "stunbaton"
+ inhand_icon_state = "baton"
+ worn_icon_state = "baton"
+
+ force = 10
+ wound_bonus = 0
+ attack_verb_continuous = list("beats")
+ attack_verb_simple = list("beat")
+
+ armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 50, BIO = 0, RAD = 0, FIRE = 80, ACID = 80)
+
+ throwforce = 7
+ stamina_damage = 60
+ knockdown_time = 5 SECONDS
+ clumsy_knockdown_time = 15 SECONDS
+ cooldown = 2.5 SECONDS
+ on_stun_sound = 'sound/weapons/egloves.ogg'
+ on_stun_volume = 50
+ active = FALSE
+
+ var/throw_stun_chance = 35
+ var/obj/item/stock_parts/cell/cell
+ var/preload_cell_type //if not empty the baton starts with this type of cell
+ var/cell_hit_cost = 1000
+ var/can_remove_cell = TRUE
+ var/convertible = TRUE //if it can be converted with a conversion kit
+
+/obj/item/melee/baton/security/Initialize()
+ . = ..()
+ if(preload_cell_type)
+ if(!ispath(preload_cell_type,/obj/item/stock_parts/cell))
+ log_mapping("[src] at [AREACOORD(src)] had an invalid preload_cell_type: [preload_cell_type].")
+ else
+ cell = new preload_cell_type(src)
+ RegisterSignal(src, COMSIG_PARENT_ATTACKBY, .proc/convert)
+ update_appearance()
+
+/obj/item/melee/baton/security/get_cell()
+ return cell
+
+/obj/item/melee/baton/security/suicide_act(mob/user)
+ if(cell?.charge && active)
+ user.visible_message(span_suicide("[user] is putting the live [name] in [user.p_their()] mouth! It looks like [user.p_theyre()] trying to commit suicide!"))
+ . = (FIRELOSS)
+ attack(user,user)
+ else
+ user.visible_message(span_suicide("[user] is shoving the [name] down their throat! It looks like [user.p_theyre()] trying to commit suicide!"))
+ . = (OXYLOSS)
+
+/obj/item/melee/baton/security/Destroy()
+ if(cell)
+ QDEL_NULL(cell)
+ UnregisterSignal(src, COMSIG_PARENT_ATTACKBY)
+ return ..()
+
+/obj/item/melee/baton/security/proc/convert(datum/source, obj/item/I, mob/user)
+ SIGNAL_HANDLER
+
+ if(istype(I,/obj/item/conversion_kit) && convertible)
+ var/turf/source_turf = get_turf(src)
+ var/obj/item/melee/baton/baton = new (source_turf)
+ baton.alpha = 20
+ playsound(source_turf, 'sound/items/drill_use.ogg', 80, TRUE, -1)
+ animate(src, alpha = 0, time = 10)
+ animate(baton, alpha = 255, time = 10)
+ qdel(I)
+ qdel(src)
+
+/obj/item/melee/baton/security/Exited(atom/movable/mov_content)
+ . = ..()
+ if(mov_content == cell)
+ cell.update_appearance()
+ cell = null
+ active = FALSE
+ update_appearance()
+
+/obj/item/melee/baton/security/update_icon_state()
+ if(active)
+ icon_state = "[initial(icon_state)]_active"
+ return ..()
+ if(!cell)
+ icon_state = "[initial(icon_state)]_nocell"
+ return ..()
+ icon_state = "[initial(icon_state)]"
+ return ..()
+
+/obj/item/melee/baton/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/security/attackby(obj/item/W, mob/user, params)
+ if(istype(W, /obj/item/stock_parts/cell))
+ var/obj/item/stock_parts/cell/C = W
+ if(cell)
+ to_chat(user, span_warning("[src] already has a cell!"))
+ else
+ if(C.maxcharge < cell_hit_cost)
+ to_chat(user, span_notice("[src] requires a higher capacity cell."))
+ return
+ if(!user.transferItemToLoc(W, src))
+ return
+ cell = W
+ to_chat(user, span_notice("You install a cell in [src]."))
+ update_appearance()
+
+ else if(W.tool_behaviour == TOOL_SCREWDRIVER)
+ tryremovecell(user)
+ else
+ return ..()
+
+/obj/item/melee/baton/security/proc/tryremovecell(mob/user)
+ if(cell && can_remove_cell)
+ cell.forceMove(drop_location())
+ to_chat(user, span_notice("You remove the cell from [src]."))
+
+/obj/item/melee/baton/security/attack_self(mob/user)
+ if(cell?.charge >= cell_hit_cost)
+ active = !active
+ balloon_alert(user, "turned [active ? "on" : "off"]")
+ playsound(src, "sparks", 75, TRUE, -1)
+ else
+ active = FALSE
+ if(!cell)
+ balloon_alert(user, "no power source!")
+ else
+ balloon_alert(user, "out of charge!")
+ update_appearance()
+ add_fingerprint(user)
+
+/obj/item/melee/baton/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)
+ if(active && cell.charge < cell_hit_cost)
+ //we're below minimum, turn off
+ active = FALSE
+ update_appearance()
+ playsound(src, "sparks", 75, TRUE, -1)
+
+/obj/item/melee/baton/security/clumsy_check(mob/living/carbon/human/user)
+ . = ..()
+ if(.)
+ 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/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)
+ 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/security/baton_effect(mob/living/target, mob/living/user, modifiers, stun_override)
+ if(iscyborg(loc))
+ var/mob/living/silicon/robot/R = loc
+ if(!R || !R.cell || !R.cell.use(cell_hit_cost))
+ return FALSE
+ else if(!deductcharge(cell_hit_cost))
+ return FALSE
+ stun_override = 0 //Avoids knocking people down prematurely.
+ return ..()
+
+/*
+ * After a target is hit, we apply some status effects.
+ * After a period of time, we then check to see what stun duration we give.
+ */
+/obj/item/melee/baton/security/additional_effects_non_cyborg(mob/living/target, mob/living/user)
+ target.Jitter(20)
+ target.set_confusion(max(10, target.get_confusion()))
+ target.stuttering = max(8, target.stuttering)
+
+ SEND_SIGNAL(target, COMSIG_LIVING_MINOR_SHOCK)
+ addtimer(CALLBACK(src, .proc/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/security/proc/apply_stun_effect_end(mob/living/target)
+ var/trait_check = HAS_TRAIT(target, TRAIT_STUNRESISTANCE) //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..." : "!"]"))
+
+ target.Knockdown(knockdown_time * (trait_check ? 0.1 : 1))
+
+/obj/item/melee/baton/security/get_wait_description()
+ return span_danger("The baton is still charging!")
+
+/obj/item/melee/baton/security/get_stun_description(mob/living/target, mob/living/user)
+ . = list()
+
+ .["visible"] = span_danger("[user] stuns [target] with [src]!")
+ .["local"] = span_userdanger("[user] stuns you with [src]!")
+
+/obj/item/melee/baton/security/get_unga_dunga_cyborg_stun_description(mob/living/target, mob/living/user)
+ . = list()
+
+ .["visible"] = span_danger("[user] tries to stun [target] with [src], and predictably fails!")
+ .["local"] = span_userdanger("[target] tries to... stun you with [src]?")
+
+/obj/item/melee/baton/security/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
+ . = ..()
+ if(active && prob(throw_stun_chance) && isliving(hit_atom))
+ finalize_baton_attack(hit_atom, thrownby?.resolve(), in_attack_chain = FALSE)
+
+/obj/item/melee/baton/security/emp_act(severity)
+ . = ..()
+ if (!(. & EMP_PROTECT_SELF))
+ deductcharge(1000 / severity)
+
+/obj/item/melee/baton/security/loaded //this one starts with a cell pre-installed.
+ preload_cell_type = /obj/item/stock_parts/cell/high
+
+//Makeshift stun baton. Replacement for stun gloves.
+/obj/item/melee/baton/security/cattleprod
+ name = "stunprod"
+ desc = "An improvised stun baton. Left click to stun, right click to harm."
+ icon_state = "stunprod"
+ inhand_icon_state = "prod"
+ worn_icon_state = null
+ lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi'
+ w_class = WEIGHT_CLASS_BULKY
+ force = 3
+ throwforce = 5
+ cell_hit_cost = 2000
+ throw_stun_chance = 10
+ slot_flags = ITEM_SLOT_BACK
+ convertible = FALSE
+ var/obj/item/assembly/igniter/sparkler
+
+/obj/item/melee/baton/security/cattleprod/Initialize()
+ . = ..()
+ sparkler = new (src)
+
+/obj/item/melee/baton/security/cattleprod/attackby(obj/item/item, mob/user, params)//handles sticking a crystal onto a stunprod to make a teleprod
+ if(istype(item, /obj/item/stack/ore/bluespace_crystal))
+ if(!cell)
+ var/obj/item/stack/ore/bluespace_crystal/crystal = item
+ var/obj/item/melee/baton/security/cattleprod/teleprod/prod = new
+ remove_item_from_storage(user)
+ qdel(src)
+ crystal.use(1)
+ user.put_in_hands(prod)
+ to_chat(user, span_notice("You place the bluespace crystal firmly into the igniter."))
+ else
+ user.visible_message(span_warning("You can't put the crystal onto the stunprod while it has a power cell installed!"))
+ else
+ return ..()
+
+/obj/item/melee/baton/security/cattleprod/baton_effect()
+ if(!sparkler.activate())
+ return BATON_ATTACK_DONE
+ return ..()
+
+/obj/item/melee/baton/security/cattleprod/Destroy()
+ if(sparkler)
+ QDEL_NULL(sparkler)
+ return ..()
+
+/obj/item/melee/baton/security/boomerang
+ name = "\improper OZtek Boomerang"
+ desc = "A device invented in 2486 for the great Space Emu War by the confederacy of Australicus, these high-tech boomerangs also work exceptionally well at stunning crewmembers. Just be careful to catch it when thrown!"
+ throw_speed = 1
+ icon_state = "boomerang"
+ inhand_icon_state = "boomerang"
+ force = 5
+ throwforce = 5
+ throw_range = 5
+ cell_hit_cost = 2000
+ throw_stun_chance = 99 //Have you prayed today?
+ convertible = FALSE
+ custom_materials = list(/datum/material/iron = 10000, /datum/material/glass = 4000, /datum/material/silver = 10000, /datum/material/gold = 2000)
+
+/obj/item/melee/baton/security/boomerang/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback, force, gentle = FALSE, quickstart = TRUE)
+ if(active)
+ if(ishuman(thrower))
+ var/mob/living/carbon/human/H = thrower
+ H.throw_mode_off(THROW_MODE_TOGGLE) //so they can catch it on the return.
+ return ..()
+
+/obj/item/melee/baton/security/boomerang/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
+ if(active)
+ var/caught = hit_atom.hitby(src, FALSE, FALSE, throwingdatum=throwingdatum)
+ var/mob/thrown_by = thrownby?.resolve()
+ if(isliving(hit_atom) && !iscyborg(hit_atom) && !caught && prob(throw_stun_chance))//if they are a living creature and they didn't catch it
+ finalize_baton_attack(hit_atom, thrown_by, in_attack_chain = FALSE)
+ if(thrown_by && !caught)
+ addtimer(CALLBACK(src, /atom/movable.proc/throw_at, thrown_by, throw_range+2, throw_speed, null, TRUE), 1)
+ else
+ return ..()
+
+/obj/item/melee/baton/security/boomerang/loaded //Same as above, comes with a cell.
+ preload_cell_type = /obj/item/stock_parts/cell/high
+
+/obj/item/melee/baton/security/cattleprod/teleprod
+ name = "teleprod"
+ desc = "A prod with a bluespace crystal on the end. The crystal doesn't look too fun to touch."
+ w_class = WEIGHT_CLASS_NORMAL
+ icon_state = "teleprod"
+ inhand_icon_state = "teleprod"
+ slot_flags = null
+
+/obj/item/melee/baton/security/cattleprod/teleprod/clumsy_check(mob/living/carbon/human/user)
+ . = ..()
+ if(!.)
+ return
+ do_teleport(user, get_turf(user), 50, channel = TELEPORT_CHANNEL_BLUESPACE)
+
+/obj/item/melee/baton/security/cattleprod/teleprod/baton_effect(mob/living/target, mob/living/user, modifiers, stun_override)
+ . = ..()
+ if(!. || target.move_resist >= MOVE_FORCE_OVERPOWERING)
+ return
+ do_teleport(target, get_turf(target), 15, channel = TELEPORT_CHANNEL_BLUESPACE)
diff --git a/code/game/objects/items/melee/misc.dm b/code/game/objects/items/melee/misc.dm
index 245db54e609..0996797e5a5 100644
--- a/code/game/objects/items/melee/misc.dm
+++ b/code/game/objects/items/melee/misc.dm
@@ -171,271 +171,6 @@
playsound(get_turf(src), hitsound, 75, TRUE, -1)
return TOXLOSS
-/obj/item/melee/classic_baton
- name = "police baton"
- desc = "A wooden truncheon for beating criminal scum. Left click to stun, right click to harm."
- icon = 'icons/obj/items_and_weapons.dmi'
- icon_state = "classic_baton"
- inhand_icon_state = "classic_baton"
- worn_icon_state = "classic_baton"
- lefthand_file = 'icons/mob/inhands/equipment/security_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/equipment/security_righthand.dmi'
- slot_flags = ITEM_SLOT_BELT
- force = 12 //9 hit crit
- w_class = WEIGHT_CLASS_NORMAL
- wound_bonus = 15
-
- /// Whether this baton is active or not
- var/extended = TRUE
- /// Used interally, you don't want to modify
- var/cooldown_check = 0
- /// Default wait time until can stun again.
- var/cooldown = (4 SECONDS)
- /// The length of the knockdown applied to a struck living, non-cyborg mob.
- var/knockdown_time = (1.5 SECONDS)
- /// If affect_cyborg is TRUE, this is how long we stun cyborgs for on a hit.
- var/stun_time_cyborg = (5 SECONDS)
- /// How much stamina damage we deal on a successful hit against a living, non-cyborg mob.
- var/stamina_damage = 55
- /// Can we stun cyborgs?
- var/affect_cyborg = FALSE
- /// The path of the default sound to play when we stun something.
- var/on_stun_sound = 'sound/effects/woodhit.ogg'
- /// Do we animate the "hit" when stunning something?
- var/stun_animation = TRUE
-
-
-/obj/item/melee/classic_baton/Initialize()
- . = ..()
- // Adding an extra break for the sake of presentation
- if(stamina_damage != 0)
- offensive_notes = "\nVarious interviewed security forces report being able to beat criminals into exhaustion with only [span_warning("[round(100 / stamina_damage, 0.1)] hit\s!")]"
-
-/// Description for trying to stun when still on cooldown.
-/obj/item/melee/classic_baton/proc/get_wait_description()
- return
-
-/// Default message for stunning a living, non-cyborg mob.
-/obj/item/melee/classic_baton/proc/get_stun_description(mob/living/target, mob/living/user)
- . = list()
-
- .["visible"] = "[user] knocks [target] down with [src]!"
- .["local"] = "[user] knocks you down with [src]!"
-
- return .
-
-/// Default message for stunning a cyborg.
-/obj/item/melee/classic_baton/proc/get_cyborg_stun_description(mob/living/target, mob/living/user)
- . = list()
-
- .["visible"] = span_danger("[user] pulses [target]'s sensors with the baton!")
- .["local"] = span_danger("You pulse [target]'s sensors with the baton!")
-
- return .
-
-/// Default message for trying to stun a cyborg with a baton that can't stun cyborgs.
-/obj/item/melee/classic_baton/proc/get_unga_dunga_cyborg_stun_description(mob/living/target, mob/living/user)
- . = list()
-
- .["visible"] = "[user] tries to knock down [target] with [src], and predictably fails!" //look at this duuuuuude
- .["local"] = "[target] tries to... knock you down with [src]?" //look at the top of his head!
-
- return .
-
-/// Contains any special effects that we apply to living, non-cyborg mobs we stun. Does not include applying a knockdown, dealing stamina damage, etc.
-/obj/item/melee/classic_baton/proc/additional_effects_non_cyborg(mob/living/target, mob/living/user)
- return
-
-/// Contains any special effects that we apply to cyborgs we stun. Does not include flashing the cyborg's screen, hardstunning them, etc.
-/obj/item/melee/classic_baton/proc/additional_effects_cyborg(mob/living/target, mob/living/user)
- return
-
-/obj/item/melee/classic_baton/attack(mob/living/target, mob/living/user, params)
- if(!extended)
- return ..()
-
- add_fingerprint(user)
- if((HAS_TRAIT(user, TRAIT_CLUMSY)) && prob(50))
- user.visible_message(span_danger("[user] accidentally hits [user.p_them()]self over the head with [src]! What a doofus!"), span_userdanger("You accidentally hit yourself over the head with [src]!"))
-
- if(iscyborg(user))
- if(affect_cyborg)
- user.flash_act(affect_silicon = TRUE)
- user.Paralyze(stun_time_cyborg * force)
- additional_effects_cyborg(user, user) // user is the target here
- playsound(get_turf(src), on_stun_sound, 100, TRUE, -1)
- else
- playsound(get_turf(src), 'sound/effects/bang.ogg', 10, TRUE)
- else
- user.Paralyze(knockdown_time * force)
- user.apply_damage(stamina_damage, STAMINA, BODY_ZONE_HEAD)
- additional_effects_non_cyborg(user, user) // user is the target here
- playsound(get_turf(src), on_stun_sound, 75, TRUE, -1)
-
- user.apply_damage(2*force, BRUTE, BODY_ZONE_HEAD)
-
- log_combat(user, target, "accidentally stun attacked [user.p_them()]self due to their clumsiness", src)
- if(stun_animation)
- user.do_attack_animation(user)
- return
- if(!isliving(target))
- return
- var/list/modifiers = params2list(params)
-
- if(LAZYACCESS(modifiers, RIGHT_CLICK))
- ..()
- return
- if(cooldown_check > world.time)
- var/wait_desc = get_wait_description()
- if (wait_desc)
- to_chat(user, wait_desc)
- return
- if(ishuman(target))
- var/mob/living/carbon/human/H = target
- if (H.check_shields(src, 0, "[user]'s [name]", MELEE_ATTACK))
- return
- if(check_martial_counter(H, user))
- return
-
- var/list/desc = get_stun_description(target, user)
-
- if(iscyborg(target))
- if(affect_cyborg)
- desc = get_cyborg_stun_description(target, user)
-
- target.flash_act(affect_silicon = TRUE)
- target.Paralyze(stun_time_cyborg)
- additional_effects_cyborg(target, user)
-
- playsound(get_turf(src), on_stun_sound, 75, TRUE, -1)
- else
- desc = get_unga_dunga_cyborg_stun_description(target, user)
-
- playsound(get_turf(src), 'sound/effects/bang.ogg', 10, TRUE) //bonk
- else
- target.Knockdown(knockdown_time)
- target.apply_damage(stamina_damage, STAMINA, BODY_ZONE_CHEST)
- additional_effects_non_cyborg(target, user)
-
- playsound(get_turf(src), on_stun_sound, 75, TRUE, -1)
-
- target.visible_message(desc["visible"], desc["local"])
- log_combat(user, target, "stun attacked", src)
- if(stun_animation)
- user.do_attack_animation(target)
-
- if(!iscarbon(user))
- target.LAssailant = null
- else
- target.LAssailant = WEAKREF(user)
- cooldown_check = world.time + cooldown
- return
-
-
-/obj/item/conversion_kit
- name = "conversion kit"
- desc = "A strange box containing wood working tools and an instruction paper to turn stun batons into something else."
- icon = 'icons/obj/storage.dmi'
- icon_state = "uk"
- custom_price = PAYCHECK_HARD * 4.5
-
-/obj/item/melee/classic_baton/telescopic
- name = "telescopic baton"
- desc = "A compact yet robust personal defense weapon. Can be concealed when folded."
- icon = 'icons/obj/items_and_weapons.dmi'
- icon_state = "telebaton"
- lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi'
- inhand_icon_state = null
- attack_verb_continuous = list("hits", "pokes")
- attack_verb_simple = list("hit", "poke")
- worn_icon_state = "tele_baton"
- slot_flags = ITEM_SLOT_BELT
- w_class = WEIGHT_CLASS_SMALL
- item_flags = NONE
- force = 0
- bare_wound_bonus = 5
- extended = FALSE
-
- /// The sound effecte played when our baton is extended.
- var/on_sound = 'sound/weapons/batonextend.ogg'
- /// The inhand iconstate used when our baton is extended.
- var/on_inhand_icon_state = "nullrod"
- /// The force on extension.
- var/active_force = 10
-
-/obj/item/melee/classic_baton/telescopic/Initialize()
- . = ..()
- AddComponent(/datum/component/transforming, \
- force_on = active_force, \
- hitsound_on = hitsound, \
- w_class_on = WEIGHT_CLASS_NORMAL, \
- clumsy_check = FALSE, \
- attack_verb_continuous_on = list("smacks", "strikes", "cracks", "beats"), \
- attack_verb_simple_on = list("smack", "strike", "crack", "beat"))
- RegisterSignal(src, COMSIG_TRANSFORMING_ON_TRANSFORM, .proc/on_transform)
-
-/obj/item/melee/classic_baton/telescopic/suicide_act(mob/user)
- var/mob/living/carbon/human/human_user = user
- var/obj/item/organ/brain/our_brain = human_user.getorgan(/obj/item/organ/brain)
-
- user.visible_message(span_suicide("[user] stuffs [src] up [user.p_their()] nose and presses the 'extend' button! It looks like [user.p_theyre()] trying to clear [user.p_their()] mind."))
- if(extended)
- playsound(src, on_sound, 50, TRUE)
- add_fingerprint(user)
- else
- attack_self(user)
-
- sleep(3)
- if (!QDELETED(human_user))
- if(!QDELETED(our_brain))
- human_user.internal_organs -= our_brain
- qdel(our_brain)
- new /obj/effect/gibspawner/generic(human_user.drop_location(), human_user)
- return (BRUTELOSS)
-
-/*
- * Signal proc for [COMSIG_TRANSFORMING_ON_TRANSFORM].
- *
- * Gives feedback to the user and makes it show up inhand.
- */
-/obj/item/melee/classic_baton/telescopic/proc/on_transform(obj/item/source, mob/user, active)
- SIGNAL_HANDLER
-
- extended = active
- inhand_icon_state = active ? on_inhand_icon_state : null // When inactive, there is no inhand icon_state.
- balloon_alert(user, "[active ? "extended" : "collapsed"] [src]")
- playsound(user ? user : src, on_sound, 50, TRUE)
- return COMPONENT_NO_DEFAULT_MESSAGE
-
-/obj/item/melee/classic_baton/telescopic/contractor_baton
- name = "contractor baton"
- desc = "A compact, specialised baton assigned to Syndicate contractors. Applies light electrical shocks to targets."
- icon = 'icons/obj/items_and_weapons.dmi'
- icon_state = "contractor_baton"
- worn_icon_state = "contractor_baton"
- lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi'
- slot_flags = ITEM_SLOT_BELT
- w_class = WEIGHT_CLASS_SMALL
- item_flags = NONE
- force = 5
- cooldown = 25
- stamina_damage = 85
- affect_cyborg = TRUE
- on_stun_sound = 'sound/effects/contractorbatonhit.ogg'
-
- on_inhand_icon_state = "contractor_baton_on"
- on_sound = 'sound/weapons/contractorbatonextend.ogg'
- active_force = 16
-
-/obj/item/melee/classic_baton/telescopic/contractor_baton/get_wait_description()
- return span_danger("The baton is still charging!")
-
-/obj/item/melee/classic_baton/telescopic/contractor_baton/additional_effects_non_cyborg(mob/living/target, mob/living/user)
- target.Jitter(20)
- target.stuttering += 20
-
/obj/item/melee/supermatter_sword
name = "supermatter sword"
desc = "In a station full of bad ideas, this might just be the worst."
diff --git a/code/game/objects/items/storage/belt.dm b/code/game/objects/items/storage/belt.dm
index 4a86fd7eda2..a305f3a51fd 100644
--- a/code/game/objects/items/storage/belt.dm
+++ b/code/game/objects/items/storage/belt.dm
@@ -235,7 +235,6 @@
STR.max_w_class = WEIGHT_CLASS_NORMAL
STR.set_holdable(list(
/obj/item/melee/baton,
- /obj/item/melee/classic_baton,
/obj/item/grenade,
/obj/item/reagent_containers/spray/pepper,
/obj/item/restraints/handcuffs,
@@ -246,7 +245,7 @@
/obj/item/food/donut,
/obj/item/kitchen/knife/combat,
/obj/item/flashlight/seclite,
- /obj/item/melee/classic_baton/telescopic,
+ /obj/item/melee/baton/telescopic,
/obj/item/radio,
/obj/item/clothing/gloves,
/obj/item/restraints/legcuffs/bola,
@@ -258,7 +257,7 @@
new /obj/item/restraints/handcuffs(src)
new /obj/item/grenade/flashbang(src)
new /obj/item/assembly/flash/handheld(src)
- new /obj/item/melee/baton/loaded(src)
+ new /obj/item/melee/baton/security/loaded(src)
update_appearance()
/obj/item/storage/belt/security/webbing
diff --git a/code/game/objects/items/storage/uplink_kits.dm b/code/game/objects/items/storage/uplink_kits.dm
index 0732670e635..91ae423fde8 100644
--- a/code/game/objects/items/storage/uplink_kits.dm
+++ b/code/game/objects/items/storage/uplink_kits.dm
@@ -322,7 +322,7 @@
/obj/item/storage/box/syndicate/contract_kit/PopulateContents()
new /obj/item/modular_computer/tablet/syndicate_contract_uplink/preset/uplink(src)
new /obj/item/storage/box/syndicate/contractor_loadout(src)
- new /obj/item/melee/classic_baton/telescopic/contractor_baton(src)
+ new /obj/item/melee/baton/telescopic/contractor_baton(src)
// All about 4 TC or less - some nukeops only items, but fit nicely to the theme.
var/list/item_list = list(
diff --git a/code/game/objects/items/stunbaton.dm b/code/game/objects/items/stunbaton.dm
deleted file mode 100644
index ffa08daefcd..00000000000
--- a/code/game/objects/items/stunbaton.dm
+++ /dev/null
@@ -1,352 +0,0 @@
-/obj/item/melee/baton
- name = "stun baton"
- desc = "A stun baton for incapacitating people with. Left click to stun, right click to harm."
-
- icon_state = "stunbaton"
- inhand_icon_state = "baton"
- worn_icon_state = "baton"
- lefthand_file = 'icons/mob/inhands/equipment/security_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/equipment/security_righthand.dmi'
-
- force = 10
- attack_verb_continuous = list("beats")
- attack_verb_simple = list("beat")
-
- w_class = WEIGHT_CLASS_NORMAL
- slot_flags = ITEM_SLOT_BELT
- armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 50, BIO = 0, RAD = 0, FIRE = 80, ACID = 80)
-
- throwforce = 7
- var/throw_stun_chance = 35
-
- var/obj/item/stock_parts/cell/cell
- var/preload_cell_type //if not empty the baton starts with this type of cell
- var/cell_hit_cost = 1000
- var/can_remove_cell = TRUE
-
- var/turned_on = FALSE
- var/activate_sound = "sparks"
-
- var/attack_cooldown_check = 0 SECONDS
- var/attack_cooldown = 2.5 SECONDS
- var/stun_sound = 'sound/weapons/egloves.ogg'
-
- var/confusion_amt = 10
- var/stamina_loss_amt = 60
- var/apply_stun_delay = 2 SECONDS
- var/stun_time = 5 SECONDS
-
- var/convertible = TRUE //if it can be converted with a conversion kit
-
-/obj/item/melee/baton/get_cell()
- return cell
-
-/obj/item/melee/baton/suicide_act(mob/user)
- if(cell?.charge && turned_on)
- user.visible_message(span_suicide("[user] is putting the live [name] in [user.p_their()] mouth! It looks like [user.p_theyre()] trying to commit suicide!"))
- . = (FIRELOSS)
- attack(user,user)
- else
- user.visible_message(span_suicide("[user] is shoving the [name] down their throat! It looks like [user.p_theyre()] trying to commit suicide!"))
- . = (OXYLOSS)
-
-/obj/item/melee/baton/Initialize()
- . = ..()
- // Adding an extra break for the sake of presentation
- if(stamina_loss_amt != 0)
- offensive_notes = "\nVarious interviewed security forces report being able to beat criminals into exhaustion with only [span_warning("[round(100 / stamina_loss_amt, 0.1)] hit\s!")]"
- if(preload_cell_type)
- if(!ispath(preload_cell_type,/obj/item/stock_parts/cell))
- log_mapping("[src] at [AREACOORD(src)] had an invalid preload_cell_type: [preload_cell_type].")
- else
- cell = new preload_cell_type(src)
- update_appearance()
- RegisterSignal(src, COMSIG_PARENT_ATTACKBY, .proc/convert)
-
-
-/obj/item/melee/baton/Destroy()
- if(cell)
- QDEL_NULL(cell)
- UnregisterSignal(src, COMSIG_PARENT_ATTACKBY)
- return ..()
-
-/obj/item/melee/baton/proc/convert(datum/source, obj/item/I, mob/user)
- SIGNAL_HANDLER
-
- if(istype(I,/obj/item/conversion_kit) && convertible)
- var/turf/T = get_turf(src)
- var/obj/item/melee/classic_baton/B = new /obj/item/melee/classic_baton (T)
- B.alpha = 20
- playsound(T, 'sound/items/drill_use.ogg', 80, TRUE, -1)
- animate(src, alpha = 0, time = 10)
- animate(B, alpha = 255, time = 10)
- qdel(I)
- qdel(src)
-
-/obj/item/melee/baton/handle_atom_del(atom/A)
- if(A == cell)
- cell = null
- turned_on = FALSE
- update_appearance()
- return ..()
-
-/obj/item/melee/baton/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
- ..()
- //Only mob/living types have stun handling
- if(turned_on && prob(throw_stun_chance) && isliving(hit_atom) && !iscyborg(hit_atom))
- baton_effect(hit_atom)
-
-/obj/item/melee/baton/loaded //this one starts with a cell pre-installed.
- preload_cell_type = /obj/item/stock_parts/cell/high
-
-/obj/item/melee/baton/proc/deductcharge(chrgdeductamt)
- if(cell)
- //Note this value returned is significant, as it will determine
- //if a stun is applied or not
- . = cell.use(chrgdeductamt)
- if(turned_on && cell.charge < cell_hit_cost)
- //we're below minimum, turn off
- turned_on = FALSE
- update_appearance()
- playsound(src, activate_sound, 75, TRUE, -1)
-
-
-/obj/item/melee/baton/update_icon_state()
- if(turned_on)
- icon_state = "[initial(icon_state)]_active"
- return ..()
- if(!cell)
- icon_state = "[initial(icon_state)]_nocell"
- return ..()
- icon_state = "[initial(icon_state)]"
- return ..()
-
-/obj/item/melee/baton/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/attackby(obj/item/W, mob/user, params)
- if(istype(W, /obj/item/stock_parts/cell))
- var/obj/item/stock_parts/cell/C = W
- if(cell)
- to_chat(user, span_warning("[src] already has a cell!"))
- else
- if(C.maxcharge < cell_hit_cost)
- to_chat(user, span_notice("[src] requires a higher capacity cell."))
- return
- if(!user.transferItemToLoc(W, src))
- return
- cell = W
- to_chat(user, span_notice("You install a cell in [src]."))
- update_appearance()
-
- else if(W.tool_behaviour == TOOL_SCREWDRIVER)
- tryremovecell(user)
- else
- return ..()
-
-/obj/item/melee/baton/proc/tryremovecell(mob/user)
- if(cell && can_remove_cell)
- cell.update_appearance()
- cell.forceMove(get_turf(src))
- cell = null
- to_chat(user, span_notice("You remove the cell from [src]."))
- turned_on = FALSE
- update_appearance()
-
-/obj/item/melee/baton/attack_self(mob/user)
- toggle_on(user)
-
-/obj/item/melee/baton/proc/toggle_on(mob/user)
- if(cell && cell.charge >= cell_hit_cost)
- turned_on = !turned_on
- to_chat(user, span_notice("[src] is now [turned_on ? "on" : "off"]."))
- playsound(src, activate_sound, 75, TRUE, -1)
- else
- turned_on = FALSE
- if(!cell)
- to_chat(user, span_warning("[src] does not have a power source!"))
- else
- to_chat(user, span_warning("[src] is out of charge."))
- update_appearance()
- add_fingerprint(user)
-
-/obj/item/melee/baton/proc/clumsy_check(mob/living/carbon/human/user)
- if(turned_on && HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50))
- playsound(src, stun_sound, 75, TRUE, -1)
- user.visible_message(span_danger("[user] accidentally hits [user.p_them()]self with [src]!"), \
- span_userdanger("You accidentally hit yourself with [src]!"))
- user.Knockdown(stun_time*3) //should really be an equivalent to attack(user,user)
- deductcharge(cell_hit_cost)
- return TRUE
- return FALSE
-
-/obj/item/melee/baton/attack(mob/M, mob/living/carbon/human/user, params)
- if(clumsy_check(user))
- return FALSE
-
- if(iscyborg(M))
- ..()
- return
-
-
- if(ishuman(M))
- var/mob/living/carbon/human/L = M
- if(check_martial_counter(L, user))
- return
-
- var/list/modifiers = params2list(params)
- if(LAZYACCESS(modifiers, RIGHT_CLICK))
- if(turned_on)
- if(attack_cooldown_check <= world.time)
- baton_effect(M, user)
- ..()
- return
- else if(turned_on)
- if(attack_cooldown_check <= world.time)
- if(baton_effect(M, user))
- user.do_attack_animation(M)
- return
- else
- to_chat(user, span_danger("The baton is still charging!"))
- return
- else if(user.combat_mode && !turned_on)
- ..()
- return
- else
- M.visible_message(span_warning("[user] prods [M] with [src]. Luckily it was off."), \
- span_warning("[user] prods you with [src]. Luckily it was off."))
- return
-
-/obj/item/melee/baton/proc/baton_effect(mob/living/L, mob/user)
- if(shields_blocked(L, user))
- return FALSE
- if(HAS_TRAIT_FROM(L, TRAIT_IWASBATONED, user)) //no doublebaton abuse anon!
- to_chat(user, span_danger("[L] manages to avoid the attack!"))
- return FALSE
- if(iscyborg(loc))
- var/mob/living/silicon/robot/R = loc
- if(!R || !R.cell || !R.cell.use(cell_hit_cost))
- return FALSE
- else
- if(!deductcharge(cell_hit_cost))
- return FALSE
- /// After a target is hit, we do a chunk of stamina damage, along with other effects.
- /// After a period of time, we then check to see what stun duration we give.
- L.Jitter(20)
- L.set_confusion(max(confusion_amt, L.get_confusion()))
- L.stuttering = max(8, L.stuttering)
- L.apply_damage(stamina_loss_amt, STAMINA, BODY_ZONE_CHEST)
-
- SEND_SIGNAL(L, COMSIG_LIVING_MINOR_SHOCK)
- addtimer(CALLBACK(src, .proc/apply_stun_effect_end, L), apply_stun_delay)
-
- if(user)
- L.lastattacker = user.real_name
- L.lastattackerckey = user.ckey
- L.visible_message(span_danger("[user] stuns [L] with [src]!"), \
- span_userdanger("[user] stuns you with [src]!"))
- log_combat(user, L, "stunned")
-
- playsound(src, stun_sound, 50, TRUE, -1)
-
- attack_cooldown_check = world.time + attack_cooldown
-
- ADD_TRAIT(L, TRAIT_IWASBATONED, user)
- addtimer(TRAIT_CALLBACK_REMOVE(L, TRAIT_IWASBATONED, user), attack_cooldown)
-
- return 1
-
-/// After the initial stun period, we check to see if the target needs to have the stun applied.
-/obj/item/melee/baton/proc/apply_stun_effect_end(mob/living/target)
- var/trait_check = HAS_TRAIT(target, TRAIT_STUNRESISTANCE) //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(stun_time * 0.1)
- else
- target.Knockdown(stun_time)
-
-/obj/item/melee/baton/emp_act(severity)
- . = ..()
- if (!(. & EMP_PROTECT_SELF))
- deductcharge(1000 / severity)
-
-/obj/item/melee/baton/proc/shields_blocked(mob/living/L, mob/user)
- if(ishuman(L))
- var/mob/living/carbon/human/H = L
- if(H.check_shields(src, 0, "[user]'s [name]", MELEE_ATTACK)) //No message; check_shields() handles that
- playsound(H, 'sound/weapons/genhit.ogg', 50, TRUE)
- return TRUE
- return FALSE
-
-//Makeshift stun baton. Replacement for stun gloves.
-/obj/item/melee/baton/cattleprod
- name = "stunprod"
- desc = "An improvised stun baton. Left click to stun, right click to harm."
- icon_state = "stunprod"
- inhand_icon_state = "prod"
- worn_icon_state = null
- lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi'
- w_class = WEIGHT_CLASS_BULKY
- force = 3
- throwforce = 5
- stun_time = 5 SECONDS
- cell_hit_cost = 2000
- throw_stun_chance = 10
- slot_flags = ITEM_SLOT_BACK
- convertible = FALSE
- var/obj/item/assembly/igniter/sparkler = 0
-
-/obj/item/melee/baton/cattleprod/Initialize()
- . = ..()
- sparkler = new (src)
-
-/obj/item/melee/baton/cattleprod/baton_effect()
- if(sparkler.activate())
- ..()
-
-/obj/item/melee/baton/cattleprod/Destroy()
- if(sparkler)
- QDEL_NULL(sparkler)
- return ..()
-
-/obj/item/melee/baton/boomerang
- name = "\improper OZtek Boomerang"
- desc = "A device invented in 2486 for the great Space Emu War by the confederacy of Australicus, these high-tech boomerangs also work exceptionally well at stunning crewmembers. Just be careful to catch it when thrown!"
- throw_speed = 1
- icon_state = "boomerang"
- inhand_icon_state = "boomerang"
- force = 5
- throwforce = 5
- throw_range = 5
- cell_hit_cost = 2000
- throw_stun_chance = 99 //Have you prayed today?
- convertible = FALSE
- custom_materials = list(/datum/material/iron = 10000, /datum/material/glass = 4000, /datum/material/silver = 10000, /datum/material/gold = 2000)
-
-/obj/item/melee/baton/boomerang/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback, force, gentle = FALSE, quickstart = TRUE)
- if(turned_on)
- if(ishuman(thrower))
- var/mob/living/carbon/human/H = thrower
- H.throw_mode_off(THROW_MODE_TOGGLE) //so they can catch it on the return.
- return ..()
-
-/obj/item/melee/baton/boomerang/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
- if(turned_on)
- var/caught = hit_atom.hitby(src, FALSE, FALSE, throwingdatum=throwingdatum)
- if(isliving(hit_atom) && !iscyborg(hit_atom) && !caught && prob(throw_stun_chance))//if they are a living creature and they didn't catch it
- baton_effect(hit_atom)
- var/mob/thrown_by = thrownby?.resolve()
- if(thrown_by && !caught)
- addtimer(CALLBACK(src, /atom/movable.proc/throw_at, thrown_by, throw_range+2, throw_speed, null, TRUE), 1)
- else
- return ..()
-
-/obj/item/melee/baton/boomerang/loaded //Same as above, comes with a cell.
- preload_cell_type = /obj/item/stock_parts/cell/high
diff --git a/code/game/objects/items/teleprod.dm b/code/game/objects/items/teleprod.dm
deleted file mode 100644
index 2e2eee5f678..00000000000
--- a/code/game/objects/items/teleprod.dm
+++ /dev/null
@@ -1,44 +0,0 @@
-/obj/item/melee/baton/cattleprod/teleprod
- name = "teleprod"
- desc = "A prod with a bluespace crystal on the end. The crystal doesn't look too fun to touch."
- w_class = WEIGHT_CLASS_NORMAL
- icon_state = "teleprod"
- inhand_icon_state = "teleprod"
- slot_flags = null
-
-/obj/item/melee/baton/cattleprod/teleprod/attack(mob/living/carbon/M, mob/living/carbon/user)//handles making things teleport when hit
- ..()
- if(turned_on && HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50))
- user.visible_message(span_danger("[user] accidentally hits [user.p_them()]self with [src]!"), \
- span_userdanger("You accidentally hit yourself with [src]!"))
- if(do_teleport(user, get_turf(user), 50, channel = TELEPORT_CHANNEL_BLUESPACE))//honk honk
- SEND_SIGNAL(user, COMSIG_LIVING_MINOR_SHOCK)
- user.Paralyze(stun_time*3)
- deductcharge(cell_hit_cost)
- else
- SEND_SIGNAL(user, COMSIG_LIVING_MINOR_SHOCK)
- user.Paralyze(stun_time*3)
- deductcharge(cell_hit_cost/4)
- return
- else
- if(turned_on)
- if(!istype(M) && M.anchored)
- return .
- else
- SEND_SIGNAL(M, COMSIG_LIVING_MINOR_SHOCK)
- do_teleport(M, get_turf(M), 15, channel = TELEPORT_CHANNEL_BLUESPACE)
-
-/obj/item/melee/baton/cattleprod/attackby(obj/item/I, mob/user, params)//handles sticking a crystal onto a stunprod to make a teleprod
- if(istype(I, /obj/item/stack/ore/bluespace_crystal))
- if(!cell)
- var/obj/item/stack/ore/bluespace_crystal/BSC = I
- var/obj/item/melee/baton/cattleprod/teleprod/S = new /obj/item/melee/baton/cattleprod/teleprod
- remove_item_from_storage(user)
- qdel(src)
- BSC.use(1)
- user.put_in_hands(S)
- to_chat(user, span_notice("You place the bluespace crystal firmly into the igniter."))
- else
- user.visible_message(span_warning("You can't put the crystal onto the stunprod while it has a power cell installed!"))
- else
- return ..()
diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm
index 1befd79fb64..9c91fbf245d 100644
--- a/code/game/objects/items/weaponry.dm
+++ b/code/game/objects/items/weaponry.dm
@@ -300,7 +300,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
to_chat(user, span_notice("You fasten the glass shard to the top of the rod with the cable."))
else if(istype(I, /obj/item/assembly/igniter) && !(HAS_TRAIT(I, TRAIT_NODROP)))
- var/obj/item/melee/baton/cattleprod/P = new /obj/item/melee/baton/cattleprod
+ var/obj/item/melee/baton/security/cattleprod/prod = new
remove_item_from_storage(user)
@@ -309,7 +309,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
qdel(I)
qdel(src)
- user.put_in_hands(P)
+ user.put_in_hands(prod)
else
return ..()
diff --git a/code/game/objects/structures/crates_lockers/closets/gimmick.dm b/code/game/objects/structures/crates_lockers/closets/gimmick.dm
index c61e340e45a..1587bff56e0 100644
--- a/code/game/objects/structures/crates_lockers/closets/gimmick.dm
+++ b/code/game/objects/structures/crates_lockers/closets/gimmick.dm
@@ -71,7 +71,7 @@
for(var/i in 1 to 3)
new /obj/item/gun/energy/laser(src)
for(var/i in 1 to 3)
- new /obj/item/melee/baton/loaded(src)
+ new /obj/item/melee/baton/security/loaded(src)
for(var/i in 1 to 3)
new /obj/item/storage/box/flashbangs(src)
for(var/i in 1 to 3)
@@ -90,7 +90,7 @@
for(var/i in 1 to 3)
new /obj/item/gun/energy/laser(src)
for(var/i in 1 to 3)
- new /obj/item/melee/baton/loaded(src)
+ new /obj/item/melee/baton/security/loaded(src)
for(var/i in 1 to 3)
new /obj/item/storage/box/flashbangs(src)
for(var/i in 1 to 3)
diff --git a/code/game/objects/structures/ghost_role_spawners.dm b/code/game/objects/structures/ghost_role_spawners.dm
index ecd281a2c8c..2712bb6e640 100644
--- a/code/game/objects/structures/ghost_role_spawners.dm
+++ b/code/game/objects/structures/ghost_role_spawners.dm
@@ -488,7 +488,7 @@
/datum/outfit/syndicate_empty/battlecruiser/assault/captain
name = "Syndicate Battlecruiser Captain"
l_pocket = /obj/item/melee/energy/sword/saber/red
- r_pocket = /obj/item/melee/classic_baton/telescopic
+ r_pocket = /obj/item/melee/baton/telescopic
suit = /obj/item/clothing/suit/armor/vest/capcarapace/syndicate
suit_store = /obj/item/gun/ballistic/revolver/mateba
back = /obj/item/storage/backpack/satchel/leather
diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm
index 7f09ebf2f93..56c7dc75b30 100644
--- a/code/game/objects/structures/watercloset.dm
+++ b/code/game/objects/structures/watercloset.dm
@@ -361,16 +361,16 @@
to_chat(user, span_notice("\The [RG] is full."))
return FALSE
- if(istype(O, /obj/item/melee/baton))
- var/obj/item/melee/baton/B = O
- if(B.cell && B.cell.charge && B.turned_on)
+ if(istype(O, /obj/item/melee/baton/security))
+ var/obj/item/melee/baton/security/baton = O
+ if(baton.cell?.charge && baton.active)
flick("baton_active", src)
- user.Paralyze(B.stun_time)
- user.stuttering = B.stun_time/20
- B.deductcharge(B.cell_hit_cost)
- user.visible_message(span_warning("[user] shocks [user.p_them()]self while attempting to wash the active [B.name]!"), \
- span_userdanger("You unwisely attempt to wash [B] while it's still on."))
- playsound(src, B.stun_sound, 50, TRUE)
+ user.Paralyze(baton.knockdown_time)
+ user.stuttering = baton.knockdown_time*0.5
+ baton.cell.use(baton.cell_hit_cost)
+ user.visible_message(span_warning("[user] shocks [user.p_them()]self while attempting to wash the active [baton.name]!"), \
+ span_userdanger("You unwisely attempt to wash [baton] while it's still on."))
+ playsound(src, baton.on_stun_sound, 50, TRUE)
return
if(istype(O, /obj/item/mop))
@@ -571,16 +571,16 @@
to_chat(user, span_notice("\The [container] is full."))
return FALSE
- if(istype(O, /obj/item/melee/baton))
- var/obj/item/melee/baton/baton = O
- if(baton.cell && baton.cell.charge && baton.turned_on)
+ if(istype(O, /obj/item/melee/baton/security))
+ var/obj/item/melee/baton/security/baton = O
+ if(baton.cell?.charge && baton.active)
flick("baton_active", src)
- user.Paralyze(baton.stun_time)
- user.stuttering = baton.stun_time * 0.05
- baton.deductcharge(baton.cell_hit_cost)
+ user.Paralyze(baton.knockdown_time)
+ user.stuttering = baton.knockdown_time*0.5
+ baton.cell.use(baton.cell_hit_cost)
user.visible_message(span_warning("[user] shocks [user.p_them()]self while attempting to wash the active [baton.name]!"), \
span_userdanger("You unwisely attempt to wash [baton] while it's still on."))
- playsound(src, baton.stun_sound, 50, TRUE)
+ playsound(src, baton.on_stun_sound, 50, TRUE)
return
if(istype(O, /obj/item/mop))
diff --git a/code/modules/antagonists/abductor/equipment/abduction_gear.dm b/code/modules/antagonists/abductor/equipment/abduction_gear.dm
index 399394c7e13..0b3599229eb 100644
--- a/code/modules/antagonists/abductor/equipment/abduction_gear.dm
+++ b/code/modules/antagonists/abductor/equipment/abduction_gear.dm
@@ -17,7 +17,6 @@
actions_types = list(/datum/action/item_action/hands_free/activate)
allowed = list(
/obj/item/abductor,
- /obj/item/melee/baton/abductor,
/obj/item/melee/baton,
/obj/item/gun/energy,
/obj/item/restraints/handcuffs
@@ -442,22 +441,15 @@ Congratulations! You are now trained for invasive xenobiology research!"}
inhand_icon_state = "wonderprod"
force = 7
-
- w_class = WEIGHT_CLASS_NORMAL
- slot_flags = ITEM_SLOT_BELT
+ wound_bonus = FALSE
actions_types = list(/datum/action/item_action/toggle_mode)
- convertible = FALSE
- attack_cooldown = 0 SECONDS
- confusion_amt = 0
- stamina_loss_amt = 0
- apply_stun_delay = 0 SECONDS
- stun_time = 14 SECONDS
-
- preload_cell_type = /obj/item/stock_parts/cell/infinite //Any sufficiently advanced technology is indistinguishable from magic
- activate_sound = null
- can_remove_cell = FALSE
+ cooldown = 0 SECONDS
+ stamina_damage = 0
+ knockdown_time = 14 SECONDS
+ on_stun_sound = 'sound/weapons/egloves.ogg'
+ affect_cyborg = TRUE
var/mode = BATON_STUN
@@ -483,8 +475,14 @@ Congratulations! You are now trained for invasive xenobiology research!"}
if(BATON_PROBE)
txt = "probing"
- if(!turned_on)
- toggle_on(user)
+ var/is_stun_mode = mode == BATON_STUN
+ var/is_stun_or_sleep = mode == BATON_STUN || mode == BATON_SLEEP
+
+ affect_cyborg = is_stun_mode
+ log_stun_attack = is_stun_mode // other modes have their own log entries.
+ stun_animation = is_stun_or_sleep
+ on_stun_sound = is_stun_or_sleep ? 'sound/weapons/egloves.ogg' : null
+
to_chat(usr, span_notice("You switch the baton to [txt] mode."))
update_appearance()
@@ -504,61 +502,40 @@ Congratulations! You are now trained for invasive xenobiology research!"}
icon_state = "wonderprodProbe"
inhand_icon_state = "wonderprodProbe"
-/obj/item/melee/baton/abductor/attack(mob/target, mob/living/user)
+/obj/item/melee/baton/abductor/baton_attack(mob/target, mob/living/user, modifiers)
if(!AbductorCheck(user))
- return FALSE
-
- if(!deductcharge(cell_hit_cost))
- to_chat(user, span_warning("[src] [cell ? "is out of charge" : "does not have a power source installed"]."))
- return FALSE
-
- if(!turned_on)
- toggle_on(user)
-
- if(iscyborg(target))
- if(mode == BATON_STUN)
- ..()
- return FALSE
-
- if(!isliving(target))
- return FALSE
-
- if(clumsy_check(user))
- return FALSE
-
- var/mob/living/L = target
-
- user.do_attack_animation(L)
-
- if(shields_blocked(L, user))
- return FALSE
+ return BATON_ATTACK_DONE
+ return ..()
+/obj/item/melee/baton/abductor/baton_effect(mob/living/target, mob/living/user, modifiers, stun_override)
switch (mode)
if(BATON_STUN)
- ..()
+ target.visible_message(span_danger("[user] stuns [target] with [src]!"),
+ span_userdanger("[user] stuns you with [src]!"))
+ target.Jitter(20)
+ target.set_confusion(max(10, target.get_confusion()))
+ target.stuttering = max(8, target.stuttering)
+ SEND_SIGNAL(target, COMSIG_LIVING_MINOR_SHOCK)
+ target.Paralyze(knockdown_time * (HAS_TRAIT(target, TRAIT_STUNRESISTANCE) ? 0.1 : 1))
if(BATON_SLEEP)
- SleepAttack(L,user)
+ SleepAttack(target,user)
if(BATON_CUFF)
- CuffAttack(L,user)
+ CuffAttack(target,user)
if(BATON_PROBE)
- ProbeAttack(L,user)
- return
+ ProbeAttack(target,user)
-/obj/item/melee/baton/abductor/apply_stun_effect_end(mob/living/target)
- StunAttack(target)
+/obj/item/melee/baton/abductor/get_stun_description(mob/living/target, mob/living/user)
+ return // chat messages are handled in their own procs.
-/obj/item/melee/baton/abductor/proc/StunAttack(mob/living/L)
- L.Paralyze(stun_time)
+/obj/item/melee/baton/abductor/get_cyborg_stun_description(mob/living/target, mob/living/user)
+ return // same as above.
/obj/item/melee/baton/abductor/attack_self(mob/living/user)
+ . = ..()
toggle(user)
-/obj/item/melee/baton/abductor/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
- turned_on = FALSE
- ..()
-
/obj/item/melee/baton/abductor/proc/SleepAttack(mob/living/L,mob/living/user)
- playsound(src, stun_sound, 50, TRUE, -1)
+ playsound(src, on_stun_sound, 50, TRUE, -1)
if(L.incapacitated(TRUE, TRUE))
if(L.anti_magic_check(FALSE, FALSE, TRUE))
to_chat(user, span_warning("The specimen's tinfoil protection is interfering with the sleep inducement!"))
diff --git a/code/modules/awaymissions/mission_code/snowdin.dm b/code/modules/awaymissions/mission_code/snowdin.dm
index 02d0ee4dead..f4a7540cce6 100644
--- a/code/modules/awaymissions/mission_code/snowdin.dm
+++ b/code/modules/awaymissions/mission_code/snowdin.dm
@@ -443,8 +443,8 @@
/obj/effect/spawner/lootdrop/snowdin/dungeonlite
name = "dungeon lite"
- loot = list(/obj/item/melee/classic_baton = 11,
- /obj/item/melee/classic_baton/telescopic = 12,
+ loot = list(/obj/item/melee/baton = 11,
+ /obj/item/melee/baton/telescopic = 12,
/obj/item/book/granter/spell/smoke = 10,
/obj/item/book/granter/spell/blind = 10,
/obj/item/storage/firstaid/regular = 45,
diff --git a/code/modules/cargo/bounties/assistant.dm b/code/modules/cargo/bounties/assistant.dm
index af9c46f889a..b2ef5f5d360 100644
--- a/code/modules/cargo/bounties/assistant.dm
+++ b/code/modules/cargo/bounties/assistant.dm
@@ -21,7 +21,7 @@
name = "Stunprod"
description = "CentCom demands a stunprod to use against dissidents. Craft one, then ship it."
reward = CARGO_CRATE_VALUE * 2.6
- wanted_types = list(/obj/item/melee/baton/cattleprod)
+ wanted_types = list(/obj/item/melee/baton/security/cattleprod)
/datum/bounty/item/assistant/soap
name = "Soap"
diff --git a/code/modules/cargo/exports/weapons.dm b/code/modules/cargo/exports/weapons.dm
index 779b935c5f0..b62cd7126d0 100644
--- a/code/modules/cargo/exports/weapons.dm
+++ b/code/modules/cargo/exports/weapons.dm
@@ -6,8 +6,8 @@
/datum/export/weapon/baton
cost = CARGO_CRATE_VALUE * 0.5
unit_name = "stun baton"
- export_types = list(/obj/item/melee/baton)
- exclude_types = list(/obj/item/melee/baton/cattleprod)
+ export_types = list(/obj/item/melee/baton/security)
+ exclude_types = list(/obj/item/melee/baton/security/cattleprod)
include_subtypes = TRUE
/datum/export/weapon/knife
diff --git a/code/modules/cargo/packs.dm b/code/modules/cargo/packs.dm
index bbbdf9455b3..3e6de23a7d3 100644
--- a/code/modules/cargo/packs.dm
+++ b/code/modules/cargo/packs.dm
@@ -418,9 +418,9 @@
desc = "Arm the Civil Protection Forces with three stun batons. Batteries included. Requires Security access to open."
cost = CARGO_CRATE_VALUE * 2
access_view = ACCESS_SECURITY
- contains = list(/obj/item/melee/baton/loaded,
- /obj/item/melee/baton/loaded,
- /obj/item/melee/baton/loaded)
+ contains = list(/obj/item/melee/baton/security/loaded,
+ /obj/item/melee/baton/security/loaded,
+ /obj/item/melee/baton/security/loaded)
crate_name = "stun baton crate"
/datum/supply_pack/security/wall_flash
diff --git a/code/modules/clothing/outfits/ert.dm b/code/modules/clothing/outfits/ert.dm
index 0be53013ce5..dfddcf4c017 100644
--- a/code/modules/clothing/outfits/ert.dm
+++ b/code/modules/clothing/outfits/ert.dm
@@ -38,7 +38,7 @@
suit_store = /obj/item/gun/energy/e_gun
back = /obj/item/storage/backpack/ert
backpack_contents = list(
- /obj/item/melee/baton/loaded = 1,
+ /obj/item/melee/baton/security/loaded = 1,
/obj/item/storage/box/survival/engineer = 1,
)
belt = /obj/item/storage/belt/security/full
@@ -59,7 +59,7 @@
backpack_contents = list(
/obj/item/gun/energy/pulse/pistol/loyalpin = 1,
- /obj/item/melee/baton/loaded = 1,
+ /obj/item/melee/baton/security/loaded = 1,
/obj/item/storage/box/survival/engineer = 1,
)
glasses = /obj/item/clothing/glasses/thermal/eyepatch
@@ -73,7 +73,7 @@
suit_store = /obj/item/gun/energy/e_gun/stun
back = /obj/item/storage/backpack/ert/security
backpack_contents = list(
- /obj/item/melee/baton/loaded = 1,
+ /obj/item/melee/baton/security/loaded = 1,
/obj/item/storage/box/handcuffs = 1,
/obj/item/storage/box/survival/engineer = 1,
)
@@ -96,7 +96,7 @@
belt = /obj/item/gun/energy/pulse/carbine/loyalpin
backpack_contents = list(
- /obj/item/melee/baton/loaded = 1,
+ /obj/item/melee/baton/security/loaded = 1,
/obj/item/storage/belt/security/full = 1,
/obj/item/storage/box/handcuffs = 1,
/obj/item/storage/box/survival/engineer = 1,
@@ -111,7 +111,7 @@
back = /obj/item/storage/backpack/ert/medical
backpack_contents = list(
/obj/item/gun/medbeam = 1,
- /obj/item/melee/baton/loaded = 1,
+ /obj/item/melee/baton/security/loaded = 1,
/obj/item/reagent_containers/hypospray/combat = 1,
/obj/item/storage/box/hug/plushes = 1,
/obj/item/storage/box/survival/engineer = 1,
@@ -136,7 +136,7 @@
backpack_contents = list(
/obj/item/gun/energy/pulse/pistol/loyalpin = 1,
/obj/item/gun/medbeam = 1,
- /obj/item/melee/baton/loaded = 1,
+ /obj/item/melee/baton/security/loaded = 1,
/obj/item/reagent_containers/hypospray/combat/nanites = 1,
/obj/item/storage/box/hug/plushes = 1,
/obj/item/storage/box/survival/engineer = 1,
@@ -152,7 +152,7 @@
back = /obj/item/storage/backpack/ert/engineer
backpack_contents = list(
/obj/item/construction/rcd/loaded/upgraded = 1,
- /obj/item/melee/baton/loaded = 1,
+ /obj/item/melee/baton/security/loaded = 1,
/obj/item/pipe_dispenser = 1,
/obj/item/storage/box/survival/engineer = 1,
)
@@ -176,7 +176,7 @@
backpack_contents = list(
/obj/item/construction/rcd/combat = 1,
/obj/item/gun/energy/pulse/pistol/loyalpin = 1,
- /obj/item/melee/baton/loaded = 1,
+ /obj/item/melee/baton/security/loaded = 1,
/obj/item/pipe_dispenser = 1,
/obj/item/storage/box/survival/engineer = 1,
)
@@ -232,7 +232,7 @@
suit_store = /obj/item/gun/energy/e_gun/stun
backpack_contents = list(
/obj/item/construction/rcd/loaded = 1,
- /obj/item/melee/baton/loaded = 1,
+ /obj/item/melee/baton/security/loaded = 1,
/obj/item/storage/box/handcuffs = 1,
/obj/item/storage/box/survival/engineer = 1,
)
@@ -243,7 +243,7 @@
suit = /obj/item/clothing/suit/space/hardsuit/ert/paranormal/inquisitor
backpack_contents = list(
/obj/item/gun/medbeam = 1,
- /obj/item/melee/baton/loaded = 1,
+ /obj/item/melee/baton/security/loaded = 1,
/obj/item/storage/box/survival/engineer = 1,
/obj/item/reagent_containers/hypospray/combat = 1,
/obj/item/reagent_containers/hypospray/combat/heresypurge = 1,
@@ -289,7 +289,7 @@
back = /obj/item/storage/backpack/ert/janitor
backpack_contents = list(
/obj/item/grenade/clusterbuster/cleaner = 1,
- /obj/item/melee/baton/loaded = 1,
+ /obj/item/melee/baton/security/loaded = 1,
/obj/item/mop/advanced = 1,
/obj/item/reagent_containers/glass/bucket = 1,
/obj/item/storage/box/lights/mixed = 1,
@@ -316,7 +316,7 @@
backpack_contents = list(
/obj/item/grenade/clusterbuster/cleaner = 3,
- /obj/item/melee/baton/loaded = 1,
+ /obj/item/melee/baton/security/loaded = 1,
/obj/item/storage/box/lights/mixed = 1,
/obj/item/storage/box/survival/engineer = 1,
)
@@ -363,7 +363,7 @@
backpack_contents = list(
/obj/item/storage/box/survival = 1,
)
- belt = /obj/item/melee/classic_baton
+ belt = /obj/item/melee/baton
ears = /obj/item/radio/headset/headset_cent
glasses = /obj/item/clothing/glasses/sunglasses
gloves = /obj/item/clothing/gloves/color/black
@@ -395,7 +395,7 @@
suit = /obj/item/clothing/suit/armor/vest
suit_store = /obj/item/gun/ballistic/rifle/boltaction/brand_new
- belt = /obj/item/melee/baton/loaded
+ belt = /obj/item/melee/baton/security/loaded
head = /obj/item/clothing/head/intern
l_hand = /obj/item/megaphone
@@ -436,7 +436,7 @@
/obj/item/storage/box/handcuffs = 1,
/obj/item/storage/box/survival/engineer = 1,
)
- belt = /obj/item/melee/classic_baton/telescopic
+ belt = /obj/item/melee/baton/telescopic
l_pocket = /obj/item/assembly/flash
r_pocket = /obj/item/storage/wallet
diff --git a/code/modules/clothing/suits/bio.dm b/code/modules/clothing/suits/bio.dm
index cb41cb438ac..1e0b6c0d963 100644
--- a/code/modules/clothing/suits/bio.dm
+++ b/code/modules/clothing/suits/bio.dm
@@ -84,7 +84,7 @@
/obj/item/clothing/suit/bio_suit/cmo/Initialize()
. = ..()
- allowed += list(/obj/item/melee/classic_baton/telescopic)
+ allowed += list(/obj/item/melee/baton/telescopic)
//Plague Dr mask can be found in clothing/masks/gasmask.dm
/obj/item/clothing/suit/bio_suit/plaguedoctorsuit
diff --git a/code/modules/clothing/suits/labcoat.dm b/code/modules/clothing/suits/labcoat.dm
index bb1c8ce248b..cd263ae5ef8 100644
--- a/code/modules/clothing/suits/labcoat.dm
+++ b/code/modules/clothing/suits/labcoat.dm
@@ -38,8 +38,8 @@
/obj/item/clothing/suit/toggle/labcoat/cmo/Initialize()
. = ..()
allowed += list(
- /obj/item/melee/classic_baton/telescopic,
- )
+ /obj/item/melee/baton/telescopic,
+ )
/obj/item/clothing/suit/toggle/labcoat/paramedic
name = "paramedic's jacket"
diff --git a/code/modules/clothing/suits/wintercoats.dm b/code/modules/clothing/suits/wintercoats.dm
index ce2649f196b..19c1a676b3c 100644
--- a/code/modules/clothing/suits/wintercoats.dm
+++ b/code/modules/clothing/suits/wintercoats.dm
@@ -82,7 +82,7 @@
inhand_icon_state = "coathop"
armor = list(MELEE = 10, BULLET = 15, LASER = 15, ENERGY = 25, BOMB = 10, BIO = 0, RAD = 0, FIRE = 0, ACID = 35)
allowed = list(
- /obj/item/melee/classic_baton/telescopic,
+ /obj/item/melee/baton/telescopic,
)
hoodtype = /obj/item/clothing/head/hooded/winterhood/hop
@@ -206,7 +206,7 @@
/obj/item/clothing/suit/hooded/wintercoat/medical/cmo/Initialize()
. = ..()
allowed += list(
- /obj/item/melee/classic_baton/telescopic,
+ /obj/item/melee/baton/telescopic,
)
/obj/item/clothing/head/hooded/winterhood/medical/cmo
@@ -289,7 +289,7 @@
/obj/item/clothing/suit/hooded/wintercoat/science/rd/Initialize()
. = ..()
allowed += list(
- /obj/item/melee/classic_baton/telescopic,
+ /obj/item/melee/baton/telescopic,
)
/obj/item/clothing/head/hooded/winterhood/science/rd
@@ -354,7 +354,7 @@
/obj/item/clothing/suit/hooded/wintercoat/engineering/ce/Initialize()
. = ..()
allowed += list(
- /obj/item/melee/classic_baton/telescopic,
+ /obj/item/melee/baton/telescopic,
)
/obj/item/clothing/head/hooded/winterhood/engineering/ce
diff --git a/code/modules/explorer_drone/loot.dm b/code/modules/explorer_drone/loot.dm
index 9a600d1d3ec..47f12b8cf28 100644
--- a/code/modules/explorer_drone/loot.dm
+++ b/code/modules/explorer_drone/loot.dm
@@ -84,7 +84,7 @@ GLOBAL_LIST_INIT(adventure_loot_generator_index,generate_generator_index())
/// Assorted weaponry
/datum/adventure_loot_generator/simple/weapons
id = "weapons"
- loot_list = list(/obj/item/gun/energy/laser,/obj/item/melee/baton/loaded)
+ loot_list = list(/obj/item/gun/energy/laser,/obj/item/melee/baton/security/loaded)
/// Pets and pet accesories in carriers
/datum/adventure_loot_generator/pet
diff --git a/code/modules/jobs/job_types/captain.dm b/code/modules/jobs/job_types/captain.dm
index 5a063c585da..6abda221483 100755
--- a/code/modules/jobs/job_types/captain.dm
+++ b/code/modules/jobs/job_types/captain.dm
@@ -57,7 +57,7 @@
suit = /obj/item/clothing/suit/armor/vest/capcarapace
shoes = /obj/item/clothing/shoes/sneakers/brown
head = /obj/item/clothing/head/caphat
- backpack_contents = list(/obj/item/melee/classic_baton/telescopic=1, /obj/item/station_charter=1)
+ backpack_contents = list(/obj/item/melee/baton/telescopic=1, /obj/item/station_charter=1)
skillchips = list(/obj/item/skillchip/disk_verifier)
diff --git a/code/modules/jobs/job_types/chief_engineer.dm b/code/modules/jobs/job_types/chief_engineer.dm
index ee3e5a7714f..e7ed1b42e36 100644
--- a/code/modules/jobs/job_types/chief_engineer.dm
+++ b/code/modules/jobs/job_types/chief_engineer.dm
@@ -62,7 +62,7 @@
shoes = /obj/item/clothing/shoes/sneakers/brown
head = /obj/item/clothing/head/hardhat/white
gloves = /obj/item/clothing/gloves/color/black
- backpack_contents = list(/obj/item/melee/classic_baton/telescopic=1, /obj/item/modular_computer/tablet/preset/advanced/command/engineering=1)
+ backpack_contents = list(/obj/item/melee/baton/telescopic=1, /obj/item/modular_computer/tablet/preset/advanced/command/engineering=1)
backpack = /obj/item/storage/backpack/industrial
satchel = /obj/item/storage/backpack/satchel/eng
diff --git a/code/modules/jobs/job_types/chief_medical_officer.dm b/code/modules/jobs/job_types/chief_medical_officer.dm
index a652828bffa..41e7ec3cbcf 100644
--- a/code/modules/jobs/job_types/chief_medical_officer.dm
+++ b/code/modules/jobs/job_types/chief_medical_officer.dm
@@ -60,7 +60,7 @@
suit = /obj/item/clothing/suit/toggle/labcoat/cmo
l_hand = /obj/item/storage/firstaid/medical
suit_store = /obj/item/flashlight/pen/paramedic
- backpack_contents = list(/obj/item/melee/classic_baton/telescopic=1, /obj/item/modular_computer/tablet/preset/advanced/command=1)
+ backpack_contents = list(/obj/item/melee/baton/telescopic=1, /obj/item/modular_computer/tablet/preset/advanced/command=1)
skillchips = list(/obj/item/skillchip/entrails_reader)
diff --git a/code/modules/jobs/job_types/detective.dm b/code/modules/jobs/job_types/detective.dm
index cf4a9090a3f..b2b05eb8024 100644
--- a/code/modules/jobs/job_types/detective.dm
+++ b/code/modules/jobs/job_types/detective.dm
@@ -58,7 +58,7 @@
r_pocket = /obj/item/lighter
backpack_contents = list(/obj/item/storage/box/evidence=1,\
/obj/item/detective_scanner=1,\
- /obj/item/melee/classic_baton=1)
+ /obj/item/melee/baton=1)
mask = /obj/item/clothing/mask/cigarette
implants = list(/obj/item/implant/mindshield)
diff --git a/code/modules/jobs/job_types/head_of_personnel.dm b/code/modules/jobs/job_types/head_of_personnel.dm
index ff04f7e2649..f22c1431157 100644
--- a/code/modules/jobs/job_types/head_of_personnel.dm
+++ b/code/modules/jobs/job_types/head_of_personnel.dm
@@ -57,7 +57,7 @@
shoes = /obj/item/clothing/shoes/sneakers/brown
head = /obj/item/clothing/head/hopcap
backpack_contents = list(/obj/item/storage/box/ids=1,\
- /obj/item/melee/classic_baton/telescopic=1, /obj/item/modular_computer/tablet/preset/advanced/command = 1)
+ /obj/item/melee/baton/telescopic=1, /obj/item/modular_computer/tablet/preset/advanced/command = 1)
chameleon_extras = list(/obj/item/gun/energy/e_gun, /obj/item/stamp/hop)
diff --git a/code/modules/jobs/job_types/head_of_security.dm b/code/modules/jobs/job_types/head_of_security.dm
index 15d95d14ba0..92683212061 100644
--- a/code/modules/jobs/job_types/head_of_security.dm
+++ b/code/modules/jobs/job_types/head_of_security.dm
@@ -58,7 +58,7 @@
suit_store = /obj/item/gun/energy/e_gun
r_pocket = /obj/item/assembly/flash/handheld
l_pocket = /obj/item/restraints/handcuffs
- backpack_contents = list(/obj/item/melee/baton/loaded=1, /obj/item/modular_computer/tablet/preset/advanced/command=1)
+ backpack_contents = list(/obj/item/melee/baton/security/loaded=1, /obj/item/modular_computer/tablet/preset/advanced/command=1)
backpack = /obj/item/storage/backpack/security
satchel = /obj/item/storage/backpack/satchel/sec
@@ -77,4 +77,4 @@
mask = /obj/item/clothing/mask/gas/sechailer
suit = /obj/item/clothing/suit/space/hardsuit/security/hos
suit_store = /obj/item/tank/internals/oxygen
- backpack_contents = list(/obj/item/melee/baton/loaded=1)
+ backpack_contents = list(/obj/item/melee/baton/security/loaded=1)
diff --git a/code/modules/jobs/job_types/research_director.dm b/code/modules/jobs/job_types/research_director.dm
index a79780cf9f4..84b460d3d4b 100644
--- a/code/modules/jobs/job_types/research_director.dm
+++ b/code/modules/jobs/job_types/research_director.dm
@@ -59,7 +59,7 @@
suit = /obj/item/clothing/suit/toggle/labcoat
l_hand = /obj/item/clipboard
l_pocket = /obj/item/laser_pointer
- backpack_contents = list(/obj/item/melee/classic_baton/telescopic=1, /obj/item/modular_computer/tablet/preset/advanced/command=1)
+ backpack_contents = list(/obj/item/melee/baton/telescopic=1, /obj/item/modular_computer/tablet/preset/advanced/command=1)
backpack = /obj/item/storage/backpack/science
satchel = /obj/item/storage/backpack/satchel/science
diff --git a/code/modules/jobs/job_types/security_officer.dm b/code/modules/jobs/job_types/security_officer.dm
index 1e63771b97d..2b2fa5a4099 100644
--- a/code/modules/jobs/job_types/security_officer.dm
+++ b/code/modules/jobs/job_types/security_officer.dm
@@ -34,7 +34,7 @@
/obj/item/food/donut/matcha = 10,
/obj/item/food/donut/blumpkin = 5,
/obj/item/clothing/mask/whistle = 5,
- /obj/item/melee/baton/boomerang/loaded = 1
+ /obj/item/melee/baton/security/boomerang/loaded = 1
)
job_flags = JOB_ANNOUNCE_ARRIVAL | JOB_CREW_MANIFEST | JOB_EQUIP_RANK | JOB_CREW_MEMBER | JOB_NEW_PLAYER_JOINABLE | JOB_REOPEN_ON_ROUNDSTART_LOSS | JOB_ASSIGN_QUIRKS
@@ -204,7 +204,7 @@ GLOBAL_LIST_EMPTY(security_officer_distribution)
l_pocket = /obj/item/restraints/handcuffs
r_pocket = /obj/item/assembly/flash/handheld
suit_store = /obj/item/gun/energy/disabler
- backpack_contents = list(/obj/item/melee/baton/loaded=1)
+ backpack_contents = list(/obj/item/melee/baton/security/loaded=1)
backpack = /obj/item/storage/backpack/security
satchel = /obj/item/storage/backpack/satchel/sec
diff --git a/code/modules/jobs/job_types/warden.dm b/code/modules/jobs/job_types/warden.dm
index a983e620773..610c73893b3 100644
--- a/code/modules/jobs/job_types/warden.dm
+++ b/code/modules/jobs/job_types/warden.dm
@@ -56,7 +56,7 @@
r_pocket = /obj/item/assembly/flash/handheld
l_pocket = /obj/item/restraints/handcuffs
suit_store = /obj/item/gun/energy/disabler
- backpack_contents = list(/obj/item/melee/baton/loaded=1)
+ backpack_contents = list(/obj/item/melee/baton/security/loaded=1)
backpack = /obj/item/storage/backpack/security
satchel = /obj/item/storage/backpack/satchel/sec
diff --git a/code/modules/mining/abandoned_crates.dm b/code/modules/mining/abandoned_crates.dm
index becd950c48c..54ee5a6b1fa 100644
--- a/code/modules/mining/abandoned_crates.dm
+++ b/code/modules/mining/abandoned_crates.dm
@@ -150,7 +150,7 @@
if(46 to 50)
new /obj/item/storage/box/syndie_kit/chameleon/broken
if(51 to 52) // 2% chance
- new /obj/item/melee/classic_baton(src)
+ new /obj/item/melee/baton(src)
if(53 to 54)
new /obj/item/toy/balloon/corgi(src)
if(55 to 56)
diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm
index 51ce2ba4e46..fb953ddaea7 100644
--- a/code/modules/mob/living/silicon/robot/robot_modules.dm
+++ b/code/modules/mob/living/silicon/robot/robot_modules.dm
@@ -101,10 +101,9 @@
F.times_used = 0
F.burnt_out = FALSE
F.update_appearance()
- else if(istype(I, /obj/item/melee/baton))
- var/obj/item/melee/baton/B = I
- if(B.cell)
- B.cell.charge = B.cell.maxcharge
+ else if(istype(I, /obj/item/melee/baton/security))
+ var/obj/item/melee/baton/security/baton = I
+ baton.cell?.charge = baton.cell.maxcharge
else if(istype(I, /obj/item/gun/energy))
var/obj/item/gun/energy/EG = I
if(!EG.chambered)
@@ -422,7 +421,7 @@
basic_modules = list(
/obj/item/assembly/flash/cyborg,
/obj/item/restraints/handcuffs/cable/zipties,
- /obj/item/melee/baton/loaded,
+ /obj/item/melee/baton/security/loaded,
/obj/item/gun/energy/disabler/cyborg,
/obj/item/clothing/mask/gas/sechailer/cyborg,
/obj/item/extinguisher/mini)
diff --git a/code/modules/mob/living/simple_animal/bot/construction.dm b/code/modules/mob/living/simple_animal/bot/construction.dm
index 0613b78b417..9d682c311d4 100644
--- a/code/modules/mob/living/simple_animal/bot/construction.dm
+++ b/code/modules/mob/living/simple_animal/bot/construction.dm
@@ -366,7 +366,7 @@
build_step--
if(ASSEMBLY_FOURTH_STEP)
- if(istype(I, /obj/item/melee/baton))
+ if(istype(I, /obj/item/melee/baton/security))
if(!can_finish_build(I, user))
return
to_chat(user, span_notice("You complete the Securitron! Beep boop."))
diff --git a/code/modules/mob/living/simple_animal/bot/secbot.dm b/code/modules/mob/living/simple_animal/bot/secbot.dm
index 83600bd7b42..db2818cf12a 100644
--- a/code/modules/mob/living/simple_animal/bot/secbot.dm
+++ b/code/modules/mob/living/simple_animal/bot/secbot.dm
@@ -23,7 +23,7 @@
combat_mode = TRUE
- var/baton_type = /obj/item/melee/baton
+ var/baton_type = /obj/item/melee/baton/security
var/obj/item/weapon
var/mob/living/carbon/target
var/oldtarget_name
diff --git a/code/modules/research/designs/weapon_designs.dm b/code/modules/research/designs/weapon_designs.dm
index 28875da4779..68020ff781c 100644
--- a/code/modules/research/designs/weapon_designs.dm
+++ b/code/modules/research/designs/weapon_designs.dm
@@ -335,6 +335,6 @@
id = "stun_boomerang"
build_type = PROTOLATHE | AWAY_LATHE
materials = list(/datum/material/iron = 10000, /datum/material/glass = 4000, /datum/material/silver = 10000, /datum/material/gold = 2000)
- build_path = /obj/item/melee/baton/boomerang
+ build_path = /obj/item/melee/baton/security/boomerang
category = list("Weapons")
departmental_flags = DEPARTMENTAL_FLAG_SECURITY
diff --git a/code/modules/surgery/revival.dm b/code/modules/surgery/revival.dm
index b8d620a98db..d8cedff3426 100644
--- a/code/modules/surgery/revival.dm
+++ b/code/modules/surgery/revival.dm
@@ -30,7 +30,7 @@
name = "shock body"
implements = list(
/obj/item/shockpaddles = 100,
- /obj/item/melee/baton = 75,
+ /obj/item/melee/baton/security = 75,
/obj/item/gun/energy = 60)
repeatable = TRUE
time = 5 SECONDS
@@ -42,9 +42,9 @@
if((paddles.req_defib && !paddles.defib.powered) || !paddles.wielded || paddles.cooldown || paddles.busy)
to_chat(user, span_warning("You need to wield both paddles, and [paddles.defib] must be powered!"))
return FALSE
- if(istype(tool, /obj/item/melee/baton))
- var/obj/item/melee/baton/baton = tool
- if(!baton.turned_on)
+ if(istype(tool, /obj/item/melee/baton/security))
+ var/obj/item/melee/baton/security/baton = tool
+ if(!baton.active)
to_chat(user, span_warning("[baton] needs to be active!"))
return FALSE
if(istype(tool, /obj/item/gun/energy))
diff --git a/tgstation.dme b/tgstation.dme
index a23a3d1a841..19cc621090e 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -1268,11 +1268,9 @@
#include "code\game\objects\items\singularityhammer.dm"
#include "code\game\objects\items\skub.dm"
#include "code\game\objects\items\spear.dm"
-#include "code\game\objects\items\stunbaton.dm"
#include "code\game\objects\items\tail_pin.dm"
#include "code\game\objects\items\taster.dm"
#include "code\game\objects\items\teleportation.dm"
-#include "code\game\objects\items\teleprod.dm"
#include "code\game\objects\items\theft_tools.dm"
#include "code\game\objects\items\toy_mechs.dm"
#include "code\game\objects\items\toys.dm"
@@ -1378,6 +1376,7 @@
#include "code\game\objects\items\implants\implanter.dm"
#include "code\game\objects\items\implants\implantpad.dm"
#include "code\game\objects\items\implants\implantuplink.dm"
+#include "code\game\objects\items\melee\baton.dm"
#include "code\game\objects\items\melee\energy.dm"
#include "code\game\objects\items\melee\misc.dm"
#include "code\game\objects\items\robot\ai_upgrades.dm"