Files
Paradise/code/datums/components/defibrillator.dm
T
036b8e0182 Mindflayers v0.9, Playable Edition! (#26596)
* adds antaghud icon

* TGUI bundle build dont push changes i didnt stage challenge 2025 (IMPOSSIBLE)

* Adds organ repair passive

* Description fix

* Runs prettier

* Fixes desc 2

* Fix revert

* Remove vamp text

* Fix some CI + Partial refactor

* Fixes CI

* Fixes gamemodes I messed with

* Moves these procs over

* Description fix again

* Add back limit requiring drainees to have ckeys

* Adds terminator icon

* Update code/datums/status_effects/buffs.dm

Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>
Signed-off-by: DGamerL <108773801+DGamerL@users.noreply.github.com>

* Update code/modules/surgery/organs/augments_internal.dm

Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>
Signed-off-by: BiancaWilkson <42818125+BiancaWilkson@users.noreply.github.com>

* Update code/modules/antagonists/mind_flayer/powers/flayer_stealth_powers.dm

Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>
Signed-off-by: BiancaWilkson <42818125+BiancaWilkson@users.noreply.github.com>

* More lewv review

* Clamps the EMP severity

* Fixes "surveilance" typos

* The TODO is gone and can't hurt me anymore

* Update code/modules/antagonists/mind_flayer/flayer_datum.dm

Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>
Signed-off-by: BiancaWilkson <42818125+BiancaWilkson@users.noreply.github.com>

* Update code/game/objects/items/weapons/pneumaticCannon.dm

Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>
Signed-off-by: BiancaWilkson <42818125+BiancaWilkson@users.noreply.github.com>

* Update code/game/objects/items/weapons/stunbaton.dm

Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>
Signed-off-by: BiancaWilkson <42818125+BiancaWilkson@users.noreply.github.com>

* More lewc reviews

* Update code/modules/antagonists/_common/antag_datum.dm

Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>
Signed-off-by: BiancaWilkson <42818125+BiancaWilkson@users.noreply.github.com>

* Update code/modules/antagonists/_common/antag_datum.dm

Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>
Signed-off-by: BiancaWilkson <42818125+BiancaWilkson@users.noreply.github.com>

* Update code/modules/antagonists/mind_flayer/flayer_datum.dm

Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>
Signed-off-by: BiancaWilkson <42818125+BiancaWilkson@users.noreply.github.com>

* Update code/modules/antagonists/mind_flayer/flayer_datum.dm

Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>
Signed-off-by: BiancaWilkson <42818125+BiancaWilkson@users.noreply.github.com>

* Update code/modules/antagonists/mind_flayer/flayer_datum.dm

Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>
Signed-off-by: BiancaWilkson <42818125+BiancaWilkson@users.noreply.github.com>

* Update code/modules/antagonists/mind_flayer/flayer_datum.dm

Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>
Signed-off-by: BiancaWilkson <42818125+BiancaWilkson@users.noreply.github.com>

* Update code/modules/antagonists/mind_flayer/flayer_power.dm

Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>
Signed-off-by: BiancaWilkson <42818125+BiancaWilkson@users.noreply.github.com>

* Fixes some camera bug issues + lewc reviews

* Update code/modules/antagonists/mind_flayer/powers/flayer_passives.dm

Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>
Signed-off-by: BiancaWilkson <42818125+BiancaWilkson@users.noreply.github.com>

* Update code/modules/antagonists/mind_flayer/flayer_power.dm

Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>
Signed-off-by: BiancaWilkson <42818125+BiancaWilkson@users.noreply.github.com>

* Updates a comment and fixes whitespace

* Autodocs flayerprod

* Update code/modules/antagonists/mind_flayer/powers/flayer_mobility_powers.dm

Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>
Signed-off-by: BiancaWilkson <42818125+BiancaWilkson@users.noreply.github.com>

* qdel things we dont need anymore + typing an argument of add_abillity

* Remove debug log

* Update code/modules/antagonists/mind_flayer/flayer_power.dm

Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>
Signed-off-by: BiancaWilkson <42818125+BiancaWilkson@users.noreply.github.com>

* Slightly buffs, and fixes GC issues of tether

* I no longer feel i am a mindflayer

* Fixes formatting of greeting

* Better greeting

* Worlds shittiest sprite

* Don't need this TODO anymore

* Fixes double description

* Changes the wording on the borg laws

* and bundle too

* The cannon uses shrapnel now

* Initial style changes

* Ratios for brain damage

* Adds a chemical to test for flayerism

* Fixes the brain damage ratios

* Abilities are purchasable again

* Updates TGUI properly

* im sorry linter

* Steam smoke

* Hi bundle

* Re-abstracts this proc post syndi orgs

* Fixes gamemode logic post cling round removal

* I WONT FORGET IT THIS TIME

* Fix name of steam ability

* I'm a fool

* Fixes processed passives + removes debug message

* Fixes updating abilities inside UI

* Better description for quicksilver form

* First part lewc review

* Remove debug thingy

* Apply suggestions from code review

Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>
Signed-off-by: DGamerL <108773801+DGamerL@users.noreply.github.com>

* Fixes defines + GCs weapon spells

* We don't need this

* Eyes GC properly

* Update code/modules/antagonists/mind_flayer/powers/flayer_mobility_powers.dm

Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>
Signed-off-by: BiancaWilkson <42818125+BiancaWilkson@users.noreply.github.com>

* adds better logging to the assimilate

* Adds parenthesis

Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>
Signed-off-by: BiancaWilkson <42818125+BiancaWilkson@users.noreply.github.com>

* TGUI Bundle Rebuild

* Fixes and Reworks TGUI

* Cleaner JS and Fixes

* adds anti-snitching clause to borg laws

* changes the span for the borg messages

* No holoparasites

* Puts baton silence in line with glare

* Fixes total_swarms_gathered

* Nuke old trait

* Gun no longer not stuck

* Rejuv clears delayed knockdown

* Some weapon ability fixes

* Makes radio enable timers not counterintuitive

* Fixes beepsky runtimes

* Makes naming more consistent

* Adds one-click-antag

* Adds the mind flayer toggle (doesn't technically work)

* Adds flayers to check_antagonist

* Gives IDs to the status effects

* Also this one

* Makes retracting work again if it's in your offhand

* Fixes pacification tech levels

* Grapple is a weapon ability now, nullifcation retracts implants

* Fixed descriptions

* Adds some pizzaz to torque enhancer

* This actually needs to be like this

* Moves a helper proc over to a helper proc file

* Extra admin visibility

* Nukes the wacky flayer mob

* Makes silicon administrative access more sane

* Terminator form better description

* Makes rejuv set stamina to 0

* Various price increases

* AAAAAAAAAAAAA

* Better feedback + logging on cyborg subversion

* Swarm purchase display (temp fix)

* Makes mindflayer sounds more silent

* UI improvements

* Various mindflayer fixes

* Typo

* More fixes

* Fixes innates from being stupid

* Forgot to add this check earlier

* Oh this is how you add things to the protolathe

* Changes some description and upgrade messages

* Allows you to drain people beyond your limit

* Fixes some weapon upgrade issues

* Fix CI

* Fixes some draining issues

* More UI Tweaks and QoL

* Fixes most of the issues

* text

* Fixes

* Adds a radio jamming option to intruder

* Gives obfusciation to jammer ability

* Small passive cleanup

* Fixes Search and Adds Ability Stages to UI

* Adds freebie abilities

* Restructuring chain and adding blackbox

* Tgui polish

* Small fix for traceroute

* Fixes one click antag

* Increases EMP resistance cost

* Changes the pneumatic cannon into a shotgun

* Slightly lower static

* Fixed innate building rendering in upgrades

* Fixes icon and description

* Consistency

* Punctuation fix.

* Quick reboot + terminator form synergy

* Adds safety deleting

* Fix level for torque

* Fixes a bad bug

* Update code/game/gamemodes/objective.dm

Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>
Signed-off-by: DGamerL <108773801+DGamerL@users.noreply.github.com>

* Aaaaaaaaaaa

* Makes torque a martial art and some martial arts safeties

* Replaces vortex arm with barrier

* Fix paths

* Adds torque knockdown

* Part 1 lewc review

* HIIIII SQUIDWARD I'M IN YOUR BRANCH NOW

* Removes flak cannon

* Flayer respects mindshielding now on vamp+cling

* Fixes EMP resist

* More fixes

* DGL review

* Contra review

* Clean up weapon powers

* Various tweaks

* Borg hand slight improvements

* Parent call needs to be after this

* Fixes stuff

* Adds a new proc that is called when a spell is purchased

* NEW SPRITES WOOOO

* Traceroute update

* Slightly lower traceroute cost

* Formatting

* Oops

* Wow this could've been bad

* Overclock small buff

* Reduces cost of 1st level EMP immunity

* Lewc review

* TGUI Bundle Rebuild

* Fix barricades

* Lewc review

* Okay FINE qwerty I'll change this

* Traceroute thingy

* I am an idiot

* First part

* Lewc review

* Forgor  this one

* Last bits

* Update code/game/objects/items/control_wand.dm

Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>
Signed-off-by: DGamerL <108773801+DGamerL@users.noreply.github.com>

* Update code/modules/antagonists/mind_flayer/powers/flayer_mobility_powers.dm

Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>
Signed-off-by: DGamerL <108773801+DGamerL@users.noreply.github.com>

* Null

* Static-ness

* Update code/game/gamemodes/changeling/traitor_chan.dm

Signed-off-by: DGamerL <108773801+DGamerL@users.noreply.github.com>

* Update code/__DEFINES/mindflayer_defines.dm

Signed-off-by: DGamerL <108773801+DGamerL@users.noreply.github.com>

* Last bits

---------

Signed-off-by: DGamerL <108773801+DGamerL@users.noreply.github.com>
Signed-off-by: BiancaWilkson <42818125+BiancaWilkson@users.noreply.github.com>
Co-authored-by: DGamerL <daan.lyklema@gmail.com>
Co-authored-by: DGamerL <108773801+DGamerL@users.noreply.github.com>
Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>
Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com>
Co-authored-by: Qwertytoforty <52090703+Qwertytoforty@users.noreply.github.com>
2024-10-30 18:35:29 +00:00

415 lines
19 KiB
Plaintext

/**
* A component for an item that attempts to defibrillate a mob when activated.
*/
#define DEFIB_TIME 5 SECONDS
/datum/component/defib
/// If this is being used by a borg or not, with necessary safeties applied if so.
var/robotic
/// If it should penetrate space suits
var/combat
/// If combat is true, this determines whether or not it should always cause a heart attack.
var/heart_attack_chance
/// Whether the safeties are enabled or not
var/safety
/// If the defib is actively performing a defib cycle
var/busy = FALSE
/// Cooldown length for this defib in deciseconds
var/cooldown
/// Whether or not we're currently on cooldown
var/on_cooldown = FALSE
/// How fast the defib should work.
var/speed_multiplier
/// If true, EMPs will have no effect.
var/emp_proof
/// If true, this cannot be emagged.
var/emag_proof
/// uid to an item that should be making noise and handling things that our direct parent shouldn't be concerned with.
var/actual_unit_uid
/// Sound for defib windup.
var/charge_sound = 'sound/machines/defib_charge.ogg'
/// Sound when the defib is successful.
var/success_sound = 'sound/machines/defib_success.ogg'
/// Sound when the defib fails.
var/fail_sound = 'sound/machines/defib_failed.ogg'
/// Sound when the defib shocks the patient.
var/zap_sound = 'sound/machines/defib_zap.ogg'
/// Sound when the defib's safety is enabled.
var/safety_on_sound = 'sound/machines/defib_saftyon.ogg'
/// Sound when the defib's safety is disabled.
var/safety_off_sound = 'sound/machines/defib_saftyoff.ogg'
/**
* Create a new defibrillation component.
*
* Arguments:
* * robotic - whether this should be treated like a borg module.
* * cooldown - Minimum time possible between shocks.
* * speed_multiplier - Speed multiplier for defib do-afters.
* * combat - If true, the defib can zap through hardsuits.
* * heart_attack_chance - If combat and safeties are off, the % chance for this to cause a heart attack on harm intent.
* * safe_by_default - If true, safety will be enabled by default.
* * emp_proof - If true, safety won't be switched by emp. Note that the device itself can still have behavior from it, it's just that the component will not.
* * emag_proof - If true, safety won't be switched by emag. Note that the device itself can still have behavior from it, it's just that the component will not.
* * actual_unit - Unit which the component's parent is based from, such as a large defib unit or a borg. The actual_unit will make the sounds and be the "origin" of visible messages, among other things.
*/
/datum/component/defib/Initialize(robotic, cooldown = 5 SECONDS, speed_multiplier = 1, combat = FALSE, heart_attack_chance = 100, safe_by_default = TRUE, emp_proof = FALSE, emag_proof = FALSE, obj/item/actual_unit = null)
if(!isitem(parent))
return COMPONENT_INCOMPATIBLE
src.robotic = robotic
src.speed_multiplier = speed_multiplier
src.cooldown = cooldown
src.combat = combat
src.heart_attack_chance = heart_attack_chance
safety = safe_by_default
src.emp_proof = emp_proof
src.emag_proof = emag_proof
if(actual_unit)
actual_unit_uid = actual_unit.UID()
var/effect_target = isnull(actual_unit) ? parent : actual_unit
RegisterSignal(parent, COMSIG_ITEM_ATTACK, PROC_REF(trigger_defib))
RegisterSignal(effect_target, COMSIG_ATOM_EMAG_ACT, PROC_REF(on_emag))
RegisterSignal(effect_target, COMSIG_ATOM_EMP_ACT, PROC_REF(on_emp))
/**
* Get the "parent" that effects (emags, EMPs) should be applied onto.
*/
/datum/component/defib/proc/get_effect_target()
var/actual_unit = locateUID(actual_unit_uid)
if(!actual_unit)
return parent
return actual_unit
/datum/component/defib/proc/on_emp(obj/item/unit)
SIGNAL_HANDLER // COMSIG_ATOM_EMP_ACT
if(emp_proof)
return
if(safety)
safety = FALSE
unit.visible_message("<span class='notice'>[unit] beeps: Safety protocols disabled!</span>")
playsound(get_turf(unit), safety_off_sound, 50, FALSE)
else
safety = TRUE
unit.visible_message("<span class='notice'>[unit] beeps: Safety protocols enabled!</span>")
playsound(get_turf(unit), safety_on_sound, 50, FALSE)
/datum/component/defib/proc/on_emag(obj/item/unit, mob/user)
SIGNAL_HANDLER // COMSIG_ATOM_EMAG_ACT
if(emag_proof)
return
safety = !safety
if(user && !robotic)
to_chat(user, "<span class='warning'>You silently [safety ? "disable" : "enable"] [unit]'s safety protocols with the card.")
/datum/component/defib/proc/set_cooldown(how_short)
on_cooldown = TRUE
addtimer(CALLBACK(src, PROC_REF(end_cooldown)), how_short)
/datum/component/defib/proc/end_cooldown()
on_cooldown = FALSE
SEND_SIGNAL(parent, COMSIG_DEFIB_READY)
/**
* Start the defibrillation process when triggered by a signal.
*/
/datum/component/defib/proc/trigger_defib(obj/item/paddles, mob/living/carbon/human/target, mob/living/user)
SIGNAL_HANDLER // COMSIG_ITEM_ATTACK
// This includes some do-afters, so we have to pass it off asynchronously
INVOKE_ASYNC(src, PROC_REF(defibrillate), user, target)
return TRUE
/**
* Perform a defibrillation.
*/
/datum/component/defib/proc/defibrillate(mob/living/user, mob/living/carbon/human/target)
// Before we do all the hard work, make sure we aren't already defibbing someone
if(busy)
return
var/parent_unit = locateUID(actual_unit_uid)
var/should_cause_harm = user.a_intent == INTENT_HARM && !safety
// Find what the defib should be referring to itself as
var/atom/defib_ref
if(parent_unit)
defib_ref = parent_unit
else if(robotic)
defib_ref = user
if(!defib_ref) // Contingency
defib_ref = parent
// Check what the unit itself has to say about how the defib went
var/application_result = SEND_SIGNAL(parent, COMSIG_DEFIB_PADDLES_APPLIED, user, target, should_cause_harm)
if(application_result & COMPONENT_BLOCK_DEFIB_DEAD)
user.visible_message("<span class='notice'>[defib_ref] beeps: Unit is unpowered.</span>")
playsound(get_turf(defib_ref), fail_sound, 50, FALSE)
return
if(on_cooldown)
to_chat(user, "<span class='notice'>[defib_ref] is recharging.</span>")
return
if(application_result & COMPONENT_BLOCK_DEFIB_MISC)
return // The unit should handle this
if(!istype(target))
if(robotic)
to_chat(user, "<span class='notice'>This unit is only designed to work on humanoid lifeforms.</span>")
else
to_chat(user, "<span class='notice'>The instructions on [defib_ref] don't mention how to defibrillate that...</span>")
return
if(should_cause_harm && combat && heart_attack_chance == 100)
combat_fibrillate(user, target)
SEND_SIGNAL(parent, COMSIG_DEFIB_SHOCK_APPLIED, user, target, should_cause_harm, TRUE)
busy = FALSE
return
if(should_cause_harm)
fibrillate(user, target)
SEND_SIGNAL(parent, COMSIG_DEFIB_SHOCK_APPLIED, user, target, should_cause_harm, TRUE)
return
user.visible_message(
"<span class='warning'>[user] begins to place [parent] on [target]'s chest.</span>",
"<span class='warning'>You begin to place [parent] on [target.name]'s chest.</span>"
)
busy = TRUE
var/mob/dead/observer/ghost = target.get_ghost()
if(ghost)
to_chat(ghost, "<span class='ghostalert'>Your heart is being defibrillated. Return to your body if you want to be revived!</span> (Verbs -> Ghost -> Re-enter corpse)")
window_flash(ghost.client)
SEND_SOUND(ghost, sound('sound/effects/genetics.ogg'))
else if(HAS_TRAIT_FROM(target, TRAIT_FAKEDEATH, CHANGELING_TRAIT))
to_chat(target, "<span class='ghostalert'>Your heart is being defibrillated. Click the defibrillator status to be revived!</span>")
window_flash(target.client)
SEND_SOUND(target, sound('sound/effects/genetics.ogg'))
target.throw_alert("cling_defib", /atom/movable/screen/alert/changeling_defib_revive, alert_args = list(parent, target))
user.visible_message("<span class='notice'>[user] places [parent] on [target]'s chest.</span>", "<span class='warning'>You place [parent] on [target]'s chest.</span>")
playsound(get_turf(defib_ref), charge_sound, 50, FALSE)
if(ghost && !ghost.client && !QDELETED(ghost))
log_debug("Ghost of name [ghost.name] is bound to [target.real_name], but lacks a client. Deleting ghost.")
QDEL_NULL(ghost)
var/signal_result = SEND_SIGNAL(target, COMSIG_LIVING_PRE_DEFIB, user, parent, ghost)
if(!do_after(user, DEFIB_TIME * speed_multiplier, target = target)) // Placed on chest and short delay to shock for dramatic effect, revive time is 5sec total
busy = FALSE
return
if(istype(target.wear_suit, /obj/item/clothing/suit/space) && !combat)
user.visible_message("<span class='notice'>[defib_ref] buzzes: Patient's chest is obscured. Operation aborted.</span>")
playsound(get_turf(defib_ref), fail_sound, 50, FALSE)
busy = FALSE
return
signal_result |= SEND_SIGNAL(target, COMSIG_LIVING_DEFIBBED, user, parent, ghost)
if(signal_result & COMPONENT_DEFIB_OVERRIDE)
// Let our signal handle it
busy = FALSE
return
if(target.undergoing_cardiac_arrest() && target.stat != DEAD) // Can have a heart attack and heart is either missing, necrotic, or not beating
var/datum/organ/heart/heart = target.get_int_organ_datum(ORGAN_DATUM_HEART)
if(!heart)
user.visible_message("<span class='boldnotice'>[defib_ref] buzzes: Resuscitation failed - Failed to pick up any heart electrical activity.</span>")
else if(heart.linked_organ.status & ORGAN_DEAD)
user.visible_message("<span class='boldnotice'>[defib_ref] buzzes: Resuscitation failed - Heart necrosis detected.</span>")
if(!heart || (heart.linked_organ.status & ORGAN_DEAD))
playsound(get_turf(defib_ref), fail_sound, 50, FALSE)
busy = FALSE
return
target.set_heartattack(FALSE)
SEND_SIGNAL(target, COMSIG_LIVING_MINOR_SHOCK, 100)
SEND_SIGNAL(parent, COMSIG_DEFIB_SHOCK_APPLIED, user, target, should_cause_harm, TRUE)
set_cooldown(cooldown)
user.visible_message("<span class='boldnotice'>[defib_ref] pings: Cardiac arrhythmia corrected.</span>")
target.visible_message("<span class='warning'>[target]'s body convulses a bit.</span>", "<span class='userdanger'>You feel a jolt, and your heartbeat seems to steady.</span>")
playsound(get_turf(defib_ref), zap_sound, 50, TRUE, -1)
playsound(get_turf(defib_ref), "bodyfall", 50, TRUE)
playsound(get_turf(defib_ref), success_sound, 50, FALSE)
busy = FALSE
return
if(target.stat != DEAD && !HAS_TRAIT(target, TRAIT_FAKEDEATH))
user.visible_message("<span class='notice'>[defib_ref] buzzes: Patient is not in a valid state. Operation aborted.</span>")
playsound(get_turf(defib_ref), fail_sound, 50, FALSE)
busy = FALSE
return
target.visible_message("<span class='warning'>[target]'s body convulses a bit.</span>")
playsound(get_turf(defib_ref), "bodyfall", 50, TRUE)
playsound(get_turf(defib_ref), zap_sound, 50, TRUE, -1)
ghost = target.get_ghost(TRUE) // We have to double check whether the dead guy has entered their body during the above
// Run through some quick failure states after shocking.
var/time_dead = world.time - target.timeofdeath
var/failure_message
if(!target.is_revivable())
failure_message = "<span class='boldnotice'>[defib_ref] buzzes: Resuscitation failed - Heart tissue damage beyond point of no return for defibrillation.</span>"
else if(target.getBruteLoss() >= 180 || target.getFireLoss() >= 180)
failure_message = "<span class='boldnotice'>[defib_ref] buzzes: Resuscitation failed - Severe tissue damage detected.</span>"
else if(HAS_TRAIT(target, TRAIT_HUSK))
failure_message = "<span class='boldnotice'>[defib_ref] buzzes: Resuscitation failed - Subject is husked.</span>"
else if(target.blood_volume < BLOOD_VOLUME_SURVIVE)
failure_message = "<span class='boldnotice'>[defib_ref] buzzes: Resuscitation failed - Patient blood volume critically low.</span>"
else if(!target.get_organ_slot("brain")) // So things like headless clings don't get outed
failure_message = "<span class='boldnotice'>[defib_ref] buzzes: Resuscitation failed - No brain detected within patient.</span>"
else if(ghost)
if(!ghost.can_reenter_corpse || target.suiciding) // DNR or AntagHUD
failure_message = "<span class='boldnotice'>[defib_ref] buzzes: Resuscitation failed - No electrical brain activity detected.</span>"
else
failure_message = "<span class='boldnotice'>[defib_ref] buzzes: Resuscitation failed - Patient's brain is unresponsive. Further attempts may succeed.</span>"
else if(HAS_TRAIT(target, TRAIT_FAKEDEATH))
if(signal_result & COMPONENT_DEFIB_FAKEDEATH_DENIED)
failure_message = "<span class='boldnotice'>[defib_ref] buzzes: Resuscitation failed - Patient's brain is unresponsive. Further attempts may succeed.</span>"
else if(signal_result & COMPONENT_DEFIB_FAKEDEATH_ACCEPTED)
// as much as I hate that this is here, it has to come after the `Patient is not in a valid state. Operation aborted.` check.
REMOVE_TRAIT(target, TRAIT_FAKEDEATH, CHANGELING_TRAIT)
else
failure_message = "<span class='boldnotice'>[defib_ref] buzzes: Resuscitation failed.</span>" // has a fakedeath like capulettium
else if((signal_result & COMPONENT_BLOCK_DEFIB) || HAS_TRAIT(target, TRAIT_BADDNA) || target.suiciding) // these are a bit more arbitrary
failure_message = "<span class='boldnotice'>[defib_ref] buzzes: Resuscitation failed.</span>"
if(failure_message)
user.visible_message(failure_message)
playsound(get_turf(defib_ref), fail_sound, 50, FALSE)
else
// Heal each basic damage type by as much as we're under -100 health
var/damage_above_threshold = -(min(target.health, HEALTH_THRESHOLD_DEAD) - HEALTH_THRESHOLD_DEAD)
var/heal_amount = damage_above_threshold + 5
target.adjustOxyLoss(-heal_amount)
target.adjustToxLoss(-heal_amount)
target.adjustFireLoss(-heal_amount)
target.adjustBruteLoss(-heal_amount)
// Inflict some brain damage scaling with time spent dead
var/obj/item/organ/internal/brain/sponge = target.get_int_organ(/obj/item/organ/internal/brain)
var/defib_time_brain_damage = min(100 * time_dead / BASE_DEFIB_TIME_LIMIT, 99) // 20 from 1 minute onward, +20 per minute up to 99
if(time_dead > DEFIB_TIME_LOSS && defib_time_brain_damage > sponge.damage)
target.setBrainLoss(defib_time_brain_damage)
target.set_heartattack(FALSE)
target.update_revive()
target.KnockOut()
target.Paralyse(10 SECONDS)
target.emote("gasp")
// Check if the brain has more than a critical amount of brain damage
if(target.check_brain_threshold(BRAIN_DAMAGE_RATIO_CRITICAL))
// If you want to treat this with mannitol, it'll have to metabolize while the patient is alive, so it's alright to bring them back up for a minute
playsound(get_turf(defib_ref), safety_off_sound, 50, FALSE)
user.visible_message("<span class='boldnotice'>[defib_ref] chimes: Minimal brain activity detected, brain treatment recommended for full resuscitation.</span>")
else
playsound(get_turf(defib_ref), success_sound, 50, FALSE)
user.visible_message("<span class='boldnotice'>[defib_ref] pings: Resuscitation successful.</span>")
SEND_SIGNAL(target, COMSIG_LIVING_MINOR_SHOCK, 100)
if(ishuman(target.pulledby)) // For some reason, pulledby isnt a list despite it being possible to be pulled by multiple people
excess_shock(user, target, target.pulledby, defib_ref)
for(var/obj/item/grab/G in target.grabbed_by)
if(ishuman(G.assailant))
excess_shock(user, target, G.assailant, defib_ref)
if(target.receiving_cpr_from)
var/mob/living/carbon/human/H = locateUID(target.receiving_cpr_from)
if(istype(H))
excess_shock(user, target, H, defib_ref)
target.med_hud_set_health()
target.med_hud_set_status()
add_attack_logs(user, target, "Revived with [defib_ref]")
SSblackbox.record_feedback("tally", "players_revived", 1, "defibrillator")
SEND_SIGNAL(parent, COMSIG_DEFIB_SHOCK_APPLIED, user, target, should_cause_harm, isnull(failure_message))
set_cooldown(cooldown)
busy = FALSE
/**
* Inflict stamina loss (and possibly inflict cardiac arrest) on someone.
*
* Arguments:
* * user - wielder of the defib
* * target - person getting shocked
*/
/datum/component/defib/proc/fibrillate(mob/user, mob/living/carbon/human/target)
if(!istype(target))
return
busy = TRUE
target.visible_message("<span class='danger'>[user] has touched [target] with [parent]!</span>", \
"<span class='userdanger'>[user] touches you with [parent], and you feel a strong jolt!</span>")
target.apply_damage(60, STAMINA)
target.KnockDown(10 SECONDS)
playsound(get_turf(parent), zap_sound, 50, TRUE, -1)
target.emote("gasp")
if(combat && prob(heart_attack_chance))
target.set_heartattack(TRUE)
SEND_SIGNAL(target, COMSIG_LIVING_MINOR_SHOCK, 100)
add_attack_logs(user, target, "Stunned with [parent]")
set_cooldown(cooldown)
busy = FALSE
/datum/component/defib/proc/combat_fibrillate(mob/user, mob/living/carbon/human/target)
if(!istype(target))
return
busy = TRUE
target.apply_damage(60, STAMINA)
target.emote("gasp")
add_attack_logs(user, target, "Stunned with [parent]")
target.KnockDown(4 SECONDS)
if(IS_HORIZONTAL(target) && HAS_TRAIT(target, TRAIT_HANDS_BLOCKED)) // Weakening exists which doesn't floor you while stunned
add_attack_logs(user, target, "Gave a heart attack with [parent]")
target.set_heartattack(TRUE)
target.visible_message("<span class='danger'>[user] has touched [target] with [parent]!</span>", \
"<span class='userdanger'>[user] touches you with [parent], and you feel a strong jolt!</span>")
playsound(get_turf(parent), zap_sound, 50, TRUE, -1)
SEND_SIGNAL(target, COMSIG_LIVING_MINOR_SHOCK, 100)
set_cooldown(cooldown)
return
target.visible_message("<span class='danger'>[user] touches [target] lightly with [parent]!</span>")
set_cooldown(2.5 SECONDS)
/*
* Pass excess shock from a defibrillation into someone else.
*
* Arguments:
* * user - The person using the defib
* * origin - The person the shock was originally applied to, the person being defibrillated
* * affecting - The person the shock is spreading to and negatively affecting.
* * cell_location - item holding the power source.
*/
/datum/component/defib/proc/excess_shock(mob/user, mob/living/origin, mob/living/carbon/human/affecting, obj/item/cell_location)
if(user == affecting)
return
var/power_source
if(robotic)
power_source = user
else
if(cell_location)
power_source = locate(/obj/item/stock_parts/cell) in cell_location
if(!power_source)
return
if(electrocute_mob(affecting, power_source, origin)) // shock anyone touching them >:)
var/datum/organ/heart/heart = affecting.get_int_organ_datum(ORGAN_DATUM_HEART)
if(heart.linked_organ.parent_organ == "chest" && affecting.has_both_hands()) // making sure the shock will go through their heart (drask hearts are in their head), and that they have both arms so the shock can cross their heart inside their chest
affecting.visible_message("<span class='danger'>[affecting]'s entire body shakes as a shock travels up [affecting.p_their()] arm!</span>", \
"<span class='userdanger'>You feel a powerful shock travel up your [affecting.hand ? affecting.get_organ("l_arm") : affecting.get_organ("r_arm")] and back down your [affecting.hand ? affecting.get_organ("r_arm") : affecting.get_organ("l_arm")]!</span>")
affecting.set_heartattack(TRUE)
#undef DEFIB_TIME