Files
Paradise/code/game/objects/items/devices/handheld_defib.dm
warriorstar-orion 525c68d617 Attack chain, initial setup. (pull *immediately* for *any* TM issues) (#26834)
* refactor: Attack chain, initial setup.

* migrate curtain to make dreamchecker happy

* update thurible

* don't call attacked_by separately for legacy attack chain

* remove duplicate proc

* condense similar code, put allowances for legacy code in new procs

* update docs, include diagram source

* add comment on how to update diagram

* fix admonition

* mindflayer updates

* remove commented out code

* clarify all steps

* after_attack should be overridable

* whoops

* retrofit recent changes

* duh, can't restrict this yet because of tool_acts

* i hate ore bags with the fire of a thousand suns

* return correct value for object attack logic

* Various cleanups.

We don't want to attempt to pull stuff out of `/obj/item/attackby`,
because those pieces are part of the related objects' migrations, not
`/obj/item` itself. Attempting to do this causes knockon effects where
things expected to call e.g. `/obj/item/storage/attackby` in the call
chain were not ferried over to the new item interaction code, because
the related objects hadn't actually been migrated over yet.

I've used refactoring /obj/vehicle as the example for migrating
`attackby` methods instead.

* simplify some argument names

* fuck it

* make it do the thing

* Rename CI module call

* Prove that CI works

* improve test output

* aaand fix it again

* fix curtain tool interactions

* fix compile error

* fix compile error

* Better docs, introduce migration plan tool.
2024-12-02 23:36:36 +00:00

105 lines
4.0 KiB
Plaintext

/obj/item/handheld_defibrillator
name = "handheld defibrillator"
desc = "Used to restart stopped hearts."
icon = 'icons/obj/medical.dmi'
lefthand_file = 'icons/mob/inhands/items_lefthand.dmi'
righthand_file = 'icons/mob/inhands/items_righthand.dmi'
icon_state = "defib-on"
item_state = "defib"
belt_icon = "defib"
var/icon_base = "defib"
///Can the defib shock yet?
var/cooldown = FALSE
///How long will it take to recharge after a shock?
var/charge_time = 10 SECONDS
///How long until we can attack the same person with any emagged handheld defib or baton again?
var/attack_cooldown = 3.5 SECONDS
///How long does this knock the target down for?
var/knockdown_duration = 10 SECONDS
/obj/item/handheld_defibrillator/emag_act(mob/user)
if(!emagged)
emagged = TRUE
desc += " The screen only shows the word KILL flashing over and over."
if(user)
to_chat(user, "<span class='warning'>you short out the safeties on [src]</span>")
return TRUE
else
emagged = FALSE
desc = "Used to restart stopped hearts."
if(user)
to_chat(user, "<span class='warning'>You restore the safeties on [src]</span>")
return TRUE
/obj/item/handheld_defibrillator/attack__legacy__attackchain(mob/living/carbon/human/H, mob/user)
if(!istype(H))
return ..()
if(cooldown)
to_chat(user, "<span class='warning'>[src] is still charging!</span>")
return
if(emagged)
var/user_UID = user.UID()
if(HAS_TRAIT_FROM(H, TRAIT_WAS_BATONNED, user_UID)) // no following up with baton or dual wielding defibs for stunlock cheese purposes
return
user.visible_message("<span class='danger'>[user] violently shocks [H] with [src]!</span>", "<span class='danger'>You violently shock [H] with [src]!</span>")
add_attack_logs(user, H, "emag-defibbed with [src]")
playsound(user.loc, "sound/weapons/egloves.ogg", 75, 1)
H.KnockDown(knockdown_duration)
H.apply_damage(60, STAMINA)
SEND_SIGNAL(H, COMSIG_LIVING_MINOR_SHOCK, 100)
ADD_TRAIT(H, TRAIT_WAS_BATONNED, user_UID)
cooldown = TRUE
icon_state = "[icon_base]-shock"
addtimer(CALLBACK(src, PROC_REF(allowhit), H, user_UID), attack_cooldown)
addtimer(CALLBACK(src, PROC_REF(short_charge)), 1 SECONDS)
addtimer(CALLBACK(src, PROC_REF(recharge)), charge_time)
return
if((H.health <= HEALTH_THRESHOLD_CRIT) || (H.undergoing_cardiac_arrest()))
user.visible_message("<span class='notice'>[user] shocks [H] with [src].</span>", "<span class='notice'>You shock [H] with [src].</span>")
add_attack_logs(user, H, "defibrillated with [src]")
playsound(user.loc, "sound/weapons/egloves.ogg", 75, 1)
if(H.stat == DEAD)
to_chat(user, "<span class='danger'>[H] doesn't respond at all!</span>")
else
H.set_heartattack(FALSE)
var/total_damage = H.getBruteLoss() + H.getFireLoss() + H.getToxLoss()
if(H.health <= HEALTH_THRESHOLD_CRIT)
if(total_damage >= 90)
to_chat(user, "<span class='danger'>[H] looks horribly injured. Resuscitation alone may not help revive them.</span>")
if(prob(66))
to_chat(user, "<span class='notice'>[H] inhales deeply!</span>")
H.adjustOxyLoss(-50)
else
to_chat(user, "<span class='danger'>[H] doesn't respond!</span>")
H.AdjustParalysis(6 SECONDS)
H.AdjustWeakened(10 SECONDS)
H.AdjustStuttering(20 SECONDS)
to_chat(H, "<span class='danger'>You feel a powerful jolt!</span>")
SEND_SIGNAL(H, COMSIG_LIVING_MINOR_SHOCK, 100)
cooldown = TRUE
icon_state = "[icon_base]-shock"
addtimer(CALLBACK(src, PROC_REF(short_charge)), 1 SECONDS)
addtimer(CALLBACK(src, PROC_REF(recharge)), charge_time)
else
to_chat(user, "<span class='notice'>[src]'s on board medical scanner indicates that no shock is required.</span>")
/obj/item/handheld_defibrillator/proc/allowhit(mob/living/target, user_UID)
REMOVE_TRAIT(target, TRAIT_WAS_BATONNED, user_UID)
/obj/item/handheld_defibrillator/proc/short_charge()
icon_state = "[icon_base]-off"
/obj/item/handheld_defibrillator/proc/recharge()
cooldown = FALSE
icon_state = "[icon_base]-on"
playsound(loc, "sound/weapons/flash.ogg", 75, 1)