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"