Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Police Tonfa - Sec Stun Baton alternative #10112

Merged
merged 21 commits into from
Mar 28, 2024
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
205 changes: 204 additions & 1 deletion code/game/objects/items/melee/misc.dm
Original file line number Diff line number Diff line change
Expand Up @@ -203,11 +203,19 @@
. = list()

.["visibletrip"] = "<span class ='danger'>[user] has knocked [target]'s legs out from under them with [src]!</span>"
.["localtrip"] = "<span class ='danger'>[user] has knocked your legs out from under you [src]!</span>"
.["localtrip"] = "<span class ='danger'>[user] has knocked your legs out from under you with [src]!</span>"
.["visibleknockout"] = "<span class ='danger'>[user] has violently knocked out [target] with [src]!</span>"
.["localknockout"] = "<span class ='danger'>[user] has beat you with such force on the head with [src] you fall unconscious...</span>"
.["visibledisarm"] = "<span class ='danger'>[user] has disarmed [target] with [src]!</span>"
.["localdisarm"] = "<span class ='danger'>[user] whacks your arm with [src], causing a coursing pain!</span>"
.["visiblestun"] = "<span class ='danger'>[user] beat [target] with [src]!</span>"
.["localstun"] = "<span class ='danger'>[user] has beat you with [src]!</span>"
.["visibleshead"] = "<span class ='danger'>[user] beat [target] on the head with [src]!</span>"
.["localhead"] = "<span class ='danger'>[user] has beat your head with [src]!</span>"
.["visiblearm"] = "<span class ='danger'>[user] beat [target]'s arm with [src]!</span>"
.["localarm"] = "<span class ='danger'>[user] has beat your arm with [src]!</span>"
.["visibleleg"] = "<span class ='danger'>[user] beat [target]'s leg with [src]!</span>"
.["localleg"] = "<span class ='danger'>[user] has beat you in the leg with [src]!</span>"

return .

Expand Down Expand Up @@ -326,6 +334,201 @@
cooldown = 10
stamina_damage = 20

//Former Wooden Baton
/obj/item/melee/classic_baton/police/beater
name = "OMNI Beater"
desc = "Favored by hot headed Security Officers who don't want to get in trouble with CentCom but still want to get that nostalgic feeling of beating some criminal scum upside the head with a chunk of wood."
icon_state = "beater"
item_state = "beater"
lefthand_file = 'icons/mob/inhands/equipment/security_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/security_righthand.dmi'
force = 8
throwforce = 7
cooldown = 0
Nakalon marked this conversation as resolved.
Show resolved Hide resolved
stamina_damage = 17
stun_animation = TRUE
/// Per-mob sleep cooldowns.
/// [mob] = [world.time where the cooldown ends]
var/static/list/sleep_cooldowns = list()
/// Per-mob trip cooldowns.
/// [mob] = [world.time where the cooldown ends]
var/static/list/trip_cooldowns = list()

/obj/item/melee/classic_baton/police/beater/attack(mob/living/target, mob/living/user)
if(!on)
return ..()
var/def_check = target.getarmor(type = MELEE, penetration = armour_penetration)

add_fingerprint(user)
if((HAS_TRAIT(user, TRAIT_CLUMSY)) && prob(50))
to_chat(user, "<span class ='danger'>You hit yourself over the head.</span>")
user.adjustStaminaLoss(stamina_damage)

additional_effects_carbon(user) // user is the target here
if(ishuman(user))
var/mob/living/carbon/human/H = user
H.apply_damage(2*force, BRUTE, BODY_ZONE_HEAD)
else
user.take_bodypart_damage(2*force)
return
if(iscyborg(target))
// We don't stun if we're on harm.
if (user.a_intent != INTENT_HARM)
if (affect_silicon)
Nakalon marked this conversation as resolved.
Show resolved Hide resolved
var/list/desc = get_silicon_stun_description(target, user)

target.flash_act(affect_silicon = TRUE)
target.Paralyze(stun_time_silicon)
additional_effects_silicon(target, user)

user.visible_message(desc["visible"], desc["local"])
playsound(get_turf(src), on_stun_sound, 100, TRUE, -1)

if (stun_animation)
user.do_attack_animation(target)
else
..()
else
..()
return
Nakalon marked this conversation as resolved.
Show resolved Hide resolved
if(!isliving(target))
return
Nakalon marked this conversation as resolved.
Show resolved Hide resolved
if (user.a_intent == INTENT_HARM)
if(!..())
return
if(!iscyborg(target))
return
else
if(COOLDOWN_FINISHED(src, cooldown_check))
if(ishuman(target))
Nakalon marked this conversation as resolved.
Show resolved Hide resolved
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)
var/obj/item/bodypart/La = target.get_bodypart(BODY_ZONE_L_ARM)
var/obj/item/bodypart/Ra = target.get_bodypart(BODY_ZONE_R_ARM)
var/obj/item/bodypart/Ll = target.get_bodypart(BODY_ZONE_L_LEG)
var/obj/item/bodypart/Rl = target.get_bodypart(BODY_ZONE_R_LEG)
var/mob/living/carbon/human/T = target

if (stun_animation)
user.do_attack_animation(target)
playsound(get_turf(src), on_stun_sound, 75, 1, -1)
additional_effects_carbon(target, user)
if((user.zone_selected == BODY_ZONE_CHEST))
target.apply_damage(stamina_damage, STAMINA, BODY_ZONE_CHEST, def_check)
log_combat(user, target, "stunned", src)
target.visible_message(desc["visiblestun"], desc["localstun"])

if((user.zone_selected == BODY_ZONE_HEAD))
target.apply_damage(14, STAMINA, BODY_ZONE_HEAD, def_check)

if(target.staminaloss > 89 && !target.has_status_effect(STATUS_EFFECT_SLEEPING) && (!sleep_cooldowns[target] || COOLDOWN_FINISHED(src, sleep_cooldowns[target])))
T.force_say(user)
target.balloon_alert_to_viewers("Knock-Out!")
if(!target.has_status_effect(STATUS_EFFECT_SLEEPING))
target.Sleeping(80)
target.setStaminaLoss(0)
playsound(usr.loc, "sound/machines/bellsound.ogg", 15, 1)
log_combat(user, target, "Knocked-Out", src)
if(CHECK_BITFIELD(target.mobility_flags, MOBILITY_STAND)) //this is here so the "falls" message doesn't appear if the target is already on the floor
target.visible_message("<span class='emote'><b>[T]</b> [pick(list("falls unconscious.","falls limp like a bag of bricks.","falls to the ground, unresponsive.","lays down on the ground for a little nap.","got [T.p_their()] dome rung in."))]</span>")
else
target.visible_message("<span class='emote'><b>[T]</b> [pick(list("falls unconscious.","falls into a deep sleep.","was sent to dreamland.","closes [T.p_their()] and prepares for a little nap."))]</span>")
COOLDOWN_START(src, sleep_cooldowns[target], 16 SECONDS)
else
log_combat(user, target, "stunned", src)
target.visible_message(desc["visiblestun"], desc["localstun"])

if(user.zone_selected == BODY_ZONE_L_LEG)
log_combat(user, target, "stunned", src)
target.visible_message(desc["visibleleg"], desc["localleg"])
if (Rl.get_staminaloss() < 26 && Ra.get_staminaloss() < 26 && La.get_staminaloss() < 26)
target.apply_damage(25, STAMINA, BODY_ZONE_L_LEG, def_check)
else
target.apply_damage(10, STAMINA, BODY_ZONE_L_LEG, def_check)
if (Ll.get_staminaloss() == 50)
target.apply_damage(10, STAMINA, BODY_ZONE_CHEST, def_check)
else
target.apply_damage(5, STAMINA, BODY_ZONE_CHEST, def_check)

if(Ll.get_staminaloss() == 50 && CHECK_BITFIELD(target.mobility_flags, MOBILITY_STAND) && (!trip_cooldowns[target] || COOLDOWN_FINISHED(src, trip_cooldowns[target])))
target.visible_message("<span class='emote'><b>[T]</b> [pick(list("falls down.","falls face first into the floor.","gets viciously tripped.","got clumsy."))]</span>")
target.balloon_alert_to_viewers("Tripped!")
target.Knockdown(7)
log_combat(user, target, "tripped", src)
target.visible_message(desc["visibletrip"], desc["localtrip"])
playsound(usr.loc, "sound/misc/slip.ogg", 30, 1)
COOLDOWN_START(src, trip_cooldowns[target], 3 SECONDS)

if(user.zone_selected == BODY_ZONE_R_LEG)
log_combat(user, target, "stunned", src)
target.visible_message(desc["visibleleg"], desc["localleg"])
if (Ll.get_staminaloss() < 26 && Ra.get_staminaloss() < 26 && La.get_staminaloss() < 26)
target.apply_damage(25, STAMINA, BODY_ZONE_R_LEG, def_check)
else
target.apply_damage(10, STAMINA, BODY_ZONE_R_LEG, def_check)
if (Rl.get_staminaloss() == 50)
target.apply_damage(10, STAMINA, BODY_ZONE_CHEST, def_check)
else
target.apply_damage(5, STAMINA, BODY_ZONE_CHEST, def_check)

if(Rl.get_staminaloss() == 50 && CHECK_BITFIELD(target.mobility_flags, MOBILITY_STAND) && (!trip_cooldowns[target] || COOLDOWN_FINISHED(src, trip_cooldowns[target])))
target.visible_message("<span class='emote'><b>[T]</b> [pick(list("falls down.","falls face first into the floor.","gets viciously tripped.","got clumsy."))]</span>")
target.balloon_alert_to_viewers("Tripped!")
target.Knockdown(7)
log_combat(user, target, "tripped", src)
playsound(usr.loc, "sound/misc/slip.ogg", 30, 1)
target.visible_message(desc["visibletrip"], desc["localtrip"])
COOLDOWN_START(src, trip_cooldowns[target], 3 SECONDS)

if(user.zone_selected == BODY_ZONE_L_ARM)
if(!La.get_staminaloss() == 50)
log_combat(user, target, "stunned", src)
target.visible_message(desc["visiblearm"], desc["localarm"])
else
log_combat(user, target, "disarmed", src)
target.visible_message(desc["visibledisarm"], desc["localdisarm"])
if (Ra.get_staminaloss() < 26 && Ll.get_staminaloss() < 26 && Rl.get_staminaloss() < 26)
target.apply_damage(20, STAMINA, BODY_ZONE_L_ARM, def_check)
else
target.apply_damage(5, STAMINA, BODY_ZONE_L_ARM, def_check)
if (La.get_staminaloss() == 50)
target.apply_damage(10, STAMINA, BODY_ZONE_CHEST, def_check)
else
target.apply_damage(4, STAMINA, BODY_ZONE_CHEST, def_check)

if(user.zone_selected == BODY_ZONE_R_ARM)
if(!Ra.get_staminaloss() == 50)
log_combat(user, target, "stunned", src)
target.visible_message(desc["visiblearm"], desc["localarm"])
else
log_combat(user, target, "disarmed", src)
target.visible_message(desc["visibledisarm"], desc["localdisarm"])
if (La.get_staminaloss() < 26 && Ll.get_staminaloss() < 26 && Rl.get_staminaloss() < 26)
target.apply_damage(20, STAMINA, BODY_ZONE_R_ARM, def_check)
else
target.apply_damage(5, STAMINA, BODY_ZONE_R_ARM, def_check)
if (Ra.get_staminaloss() == 50)
target.apply_damage(10, STAMINA, BODY_ZONE_CHEST, def_check)
else
target.apply_damage(4, STAMINA, BODY_ZONE_CHEST, def_check)

add_fingerprint(user)

if(!iscarbon(user))
target.LAssailant = null
else
target.LAssailant = WEAKREF(user)
COOLDOWN_START(src, cooldown_check, cooldown)
else
var/wait_desc = get_wait_description()
if (wait_desc)
to_chat(user, wait_desc)
Nakalon marked this conversation as resolved.
Show resolved Hide resolved

//Telescopic Baton
/obj/item/melee/classic_baton/police/telescopic
name = "telescopic baton"
Expand Down
4 changes: 4 additions & 0 deletions code/modules/surgery/bodyparts/bodyparts.dm
Nakalon marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,10 @@
total = max(total, stamina_dam)
return total

//Returns only stamina damage.
/obj/item/bodypart/proc/get_staminaloss()
return stamina_dam

//Checks disabled status thresholds
/obj/item/bodypart/proc/update_disabled()
set_disabled(is_disabled())
Expand Down
3 changes: 2 additions & 1 deletion code/modules/vending/security.dm
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
/obj/item/flashlight/seclite = 4,
/obj/item/holosign_creator/security = 3,
/obj/item/restraints/legcuffs/bola/energy = 7,
/obj/item/club = 5)
/obj/item/club = 5,
/obj/item/melee/classic_baton/police/beater = 5)
contraband = list(/obj/item/clothing/glasses/sunglasses/advanced = 2)
premium = list(/obj/item/storage/belt/security/webbing = 5,
/obj/item/storage/backpack/duffelbag/sec/deputy = 4,
Expand Down
Binary file modified icons/mob/inhands/equipment/security_lefthand.dmi
Binary file not shown.
Binary file modified icons/mob/inhands/equipment/security_righthand.dmi
Binary file not shown.
Binary file modified icons/obj/items_and_weapons.dmi
Binary file not shown.