mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-05-14 10:50:50 +01:00
ad813f76d9
* cursed heart but funny * Flesh out this version a bit more * okay fine you get three shots miner gaming * Bitwise * Change wakeup method * Address Steel's review
675 lines
28 KiB
Plaintext
675 lines
28 KiB
Plaintext
//backpack item
|
|
|
|
/obj/item/defibrillator
|
|
name = "defibrillator"
|
|
desc = "A device that delivers powerful shocks to detachable paddles that resuscitate incapacitated patients."
|
|
icon = 'icons/obj/defib.dmi'
|
|
icon_state = "defibunit"
|
|
item_state = "defibunit"
|
|
slot_flags = SLOT_BACK
|
|
force = 5
|
|
throwforce = 6
|
|
w_class = WEIGHT_CLASS_BULKY
|
|
origin_tech = "biotech=4"
|
|
actions_types = list(/datum/action/item_action/toggle_paddles)
|
|
armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 50, ACID = 50)
|
|
sprite_sheets = list(
|
|
"Vox" = 'icons/mob/clothing/species/vox/back.dmi'
|
|
)
|
|
|
|
var/paddles_on_defib = TRUE //if the paddles are on the defib (TRUE)
|
|
var/powered = FALSE //if there's a cell in the defib with enough power for a revive, blocks paddles from reviving otherwise
|
|
var/obj/item/twohanded/shockpaddles/paddles
|
|
var/obj/item/stock_parts/cell/high/cell = null
|
|
var/safety = TRUE //if this is FALSE you can zap people with the defibs on harm mode
|
|
var/combat = FALSE //can we revive through space suits?
|
|
var/heart_attack = FALSE //if TRUE it always cause heart attacks if it is a combat defib.
|
|
base_icon_state = "defibpaddles"
|
|
var/obj/item/twohanded/shockpaddles/paddle_type = /obj/item/twohanded/shockpaddles
|
|
|
|
/obj/item/defibrillator/get_cell()
|
|
return cell
|
|
|
|
/obj/item/defibrillator/Initialize(mapload) //starts without a cell for rnd
|
|
. = ..()
|
|
paddles = new paddle_type(src)
|
|
update_icon(UPDATE_OVERLAYS)
|
|
|
|
/obj/item/defibrillator/loaded/Initialize(mapload) //starts with hicap
|
|
. = ..()
|
|
cell = new(src)
|
|
update_icon(UPDATE_OVERLAYS)
|
|
|
|
/obj/item/defibrillator/update_icon(updates=ALL)
|
|
update_power()
|
|
..()
|
|
|
|
/obj/item/defibrillator/examine(mob/user)
|
|
. = ..()
|
|
. += "<span class='notice'>Ctrl-click to remove the paddles from the defibrillator.</span>"
|
|
|
|
/obj/item/defibrillator/proc/update_power()
|
|
if(cell)
|
|
if(cell.charge < paddles.revivecost)
|
|
powered = FALSE
|
|
else
|
|
powered = TRUE
|
|
else
|
|
powered = FALSE
|
|
|
|
/obj/item/defibrillator/update_overlays()
|
|
. = ..()
|
|
if(paddles_on_defib)
|
|
. += "[icon_state]-paddles"
|
|
if(!safety)
|
|
. += "[icon_state]-emagged"
|
|
if(powered)
|
|
. += "[icon_state]-powered"
|
|
if(powered && cell)
|
|
var/ratio = cell.charge / cell.maxcharge
|
|
ratio = CEILING(ratio*4, 1) * 25
|
|
. += "[icon_state]-charge[ratio]"
|
|
if(!cell)
|
|
. += "[icon_state]-nocell"
|
|
|
|
/obj/item/defibrillator/CheckParts(list/parts_list)
|
|
..()
|
|
cell = locate(/obj/item/stock_parts/cell) in contents
|
|
update_icon(UPDATE_OVERLAYS)
|
|
|
|
/obj/item/defibrillator/ui_action_click()
|
|
toggle_paddles()
|
|
|
|
/obj/item/defibrillator/CtrlClick()
|
|
if(ishuman(usr) && Adjacent(usr))
|
|
toggle_paddles()
|
|
|
|
/obj/item/defibrillator/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 class='notice'>[src] already has a cell.</span>")
|
|
else
|
|
if(C.maxcharge < paddles.revivecost)
|
|
to_chat(user, "<span class='notice'>[src] requires a higher capacity cell.</span>")
|
|
return
|
|
user.drop_item()
|
|
W.loc = src
|
|
cell = W
|
|
to_chat(user, "<span class='notice'>You install a cell in [src].</span>")
|
|
|
|
if(istype(W, /obj/item/screwdriver))
|
|
if(cell)
|
|
cell.update_icon()
|
|
cell.loc = get_turf(loc)
|
|
cell = null
|
|
to_chat(user, "<span class='notice'>You remove the cell from [src].</span>")
|
|
|
|
update_icon(UPDATE_OVERLAYS)
|
|
return
|
|
|
|
/obj/item/defibrillator/emag_act(user as mob)
|
|
if(safety)
|
|
safety = FALSE
|
|
to_chat(user, "<span class='warning'>You silently disable [src]'s safety protocols with the card.")
|
|
else
|
|
safety = TRUE
|
|
to_chat(user, "<span class='notice'>You silently enable [src]'s safety protocols with the card.")
|
|
|
|
/obj/item/defibrillator/emp_act(severity)
|
|
if(cell)
|
|
deductcharge(1000 / severity)
|
|
if(safety)
|
|
safety = FALSE
|
|
visible_message("<span class='notice'>[src] beeps: Safety protocols disabled!</span>")
|
|
playsound(get_turf(src), 'sound/machines/defib_saftyoff.ogg', 50, 0)
|
|
else
|
|
safety = TRUE
|
|
visible_message("<span class='notice'>[src] beeps: Safety protocols enabled!</span>")
|
|
playsound(get_turf(src), 'sound/machines/defib_saftyon.ogg', 50, 0)
|
|
update_icon(UPDATE_OVERLAYS)
|
|
..()
|
|
|
|
/obj/item/defibrillator/verb/toggle_paddles()
|
|
set name = "Toggle Paddles"
|
|
set category = "Object"
|
|
|
|
var/mob/living/carbon/human/user = usr
|
|
|
|
if(paddles_on_defib)
|
|
//Detach the paddles into the user's hands
|
|
if(usr.incapacitated()) return
|
|
|
|
if(!usr.put_in_hands(paddles))
|
|
to_chat(user, "<span class='warning'>You need a free hand to hold the paddles!</span>")
|
|
update_icon(UPDATE_OVERLAYS)
|
|
return
|
|
paddles.loc = user
|
|
paddles_on_defib = FALSE
|
|
else if(user.is_in_active_hand(paddles))
|
|
//Remove from their hands and back onto the defib unit
|
|
remove_paddles(user)
|
|
|
|
update_icon(UPDATE_OVERLAYS)
|
|
for(var/X in actions)
|
|
var/datum/action/A = X
|
|
A.UpdateButtonIcon()
|
|
|
|
/obj/item/defibrillator/equipped(mob/user, slot)
|
|
..()
|
|
if(slot != slot_back)
|
|
remove_paddles(user)
|
|
update_icon(UPDATE_OVERLAYS)
|
|
|
|
/obj/item/defibrillator/item_action_slot_check(slot, mob/user)
|
|
if(slot == slot_back)
|
|
return TRUE
|
|
|
|
/obj/item/defibrillator/proc/remove_paddles(mob/user) // from your hands
|
|
var/mob/living/carbon/human/M = user
|
|
if(paddles in get_both_hands(M))
|
|
M.unEquip(paddles)
|
|
paddles_on_defib = TRUE
|
|
update_icon(UPDATE_OVERLAYS)
|
|
return
|
|
|
|
/obj/item/defibrillator/Destroy()
|
|
if(!paddles_on_defib)
|
|
var/M = get(paddles, /mob)
|
|
remove_paddles(M)
|
|
QDEL_NULL(paddles)
|
|
QDEL_NULL(cell)
|
|
return ..()
|
|
|
|
/obj/item/defibrillator/proc/deductcharge(chrgdeductamt)
|
|
if(cell)
|
|
if(cell.charge < (paddles.revivecost+chrgdeductamt))
|
|
powered = FALSE
|
|
update_icon(UPDATE_OVERLAYS)
|
|
if(cell.use(chrgdeductamt))
|
|
update_icon(UPDATE_OVERLAYS)
|
|
return TRUE
|
|
else
|
|
update_icon(UPDATE_OVERLAYS)
|
|
return FALSE
|
|
|
|
/obj/item/defibrillator/proc/cooldowncheck(mob/user)
|
|
spawn(50)
|
|
if(cell)
|
|
if(cell.charge >= paddles.revivecost)
|
|
user.visible_message("<span class='notice'>[src] beeps: Unit ready.</span>")
|
|
playsound(get_turf(src), 'sound/machines/defib_ready.ogg', 50, 0)
|
|
else
|
|
user.visible_message("<span class='notice'>[src] beeps: Charge depleted.</span>")
|
|
playsound(get_turf(src), 'sound/machines/defib_failed.ogg', 50, 0)
|
|
paddles.cooldown = FALSE
|
|
paddles.update_icon(UPDATE_ICON_STATE)
|
|
update_icon(UPDATE_OVERLAYS)
|
|
|
|
/obj/item/defibrillator/compact
|
|
name = "compact defibrillator"
|
|
desc = "A belt-mounted defibrillator that can be rapidly deployed."
|
|
icon_state = "defibcompact"
|
|
item_state = "defibcompact"
|
|
sprite_sheets = null //Because Vox had the belt defibrillator sprites in back.dm
|
|
w_class = WEIGHT_CLASS_NORMAL
|
|
slot_flags = SLOT_BELT
|
|
origin_tech = "biotech=5"
|
|
|
|
/obj/item/defibrillator/compact/loaded/Initialize(mapload)
|
|
. = ..()
|
|
cell = new(src)
|
|
update_icon(UPDATE_OVERLAYS)
|
|
|
|
/obj/item/defibrillator/compact/item_action_slot_check(slot, mob/user)
|
|
if(slot == slot_belt)
|
|
return TRUE
|
|
|
|
/obj/item/defibrillator/compact/combat
|
|
name = "combat defibrillator"
|
|
desc = "A belt-mounted blood-red defibrillator that can be rapidly deployed. Does not have the restrictions or safeties of conventional defibrillators and can revive through space suits."
|
|
icon_state = "defibcombat"
|
|
item_state = "defibcombat"
|
|
paddle_type = /obj/item/twohanded/shockpaddles/syndicate
|
|
combat = TRUE
|
|
safety = FALSE
|
|
heart_attack = TRUE
|
|
|
|
/obj/item/defibrillator/compact/combat/loaded/Initialize(mapload)
|
|
. = ..()
|
|
cell = new(src)
|
|
update_icon(UPDATE_OVERLAYS)
|
|
|
|
/obj/item/defibrillator/compact/advanced
|
|
name = "advanced compact defibrillator"
|
|
desc = "A belt-mounted state-of-the-art defibrillator that can be rapidly deployed in all environments. Uses an experimental self-charging cell, meaning that it will (probably) never stop working. Can be used to defibrillate through space suits. It is impossible to damage."
|
|
icon_state = "defibnt"
|
|
item_state = "defibnt"
|
|
paddle_type = /obj/item/twohanded/shockpaddles/advanced
|
|
combat = TRUE
|
|
safety = TRUE
|
|
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF //Objective item, better not have it destroyed.
|
|
|
|
var/next_emp_message //to prevent spam from the emagging message on the advanced defibrillator
|
|
|
|
/obj/item/defibrillator/compact/advanced/attackby(obj/item/W, mob/user, params)
|
|
if(W == paddles)
|
|
paddles.unwield()
|
|
toggle_paddles()
|
|
update_icon(UPDATE_OVERLAYS)
|
|
|
|
/obj/item/defibrillator/compact/advanced/loaded/Initialize(mapload)
|
|
. = ..()
|
|
cell = new /obj/item/stock_parts/cell/bluespace/charging(src)
|
|
update_icon(UPDATE_OVERLAYS)
|
|
|
|
/obj/item/defibrillator/compact/advanced/emp_act(severity)
|
|
if(world.time > next_emp_message)
|
|
atom_say("Warning: Electromagnetic pulse detected. Integrated shielding prevented all potential hardware damage.")
|
|
playsound(src, 'sound/machines/defib_saftyon.ogg', 50)
|
|
next_emp_message = world.time + 5 SECONDS
|
|
|
|
/obj/item/defibrillator/compact/advanced/attackby(obj/item/W, mob/user, params)
|
|
if(W == paddles)
|
|
paddles.unwield()
|
|
toggle_paddles()
|
|
update_icon(UPDATE_OVERLAYS)
|
|
return
|
|
|
|
//paddles
|
|
|
|
/obj/item/twohanded/shockpaddles
|
|
name = "defibrillator paddles"
|
|
desc = "A pair of plastic-gripped paddles with flat metal surfaces that are used to deliver powerful electric shocks."
|
|
icon = 'icons/obj/defib.dmi'
|
|
icon_state = "defibpaddles"
|
|
item_state = "defibpaddles"
|
|
force = 0
|
|
throwforce = 6
|
|
w_class = WEIGHT_CLASS_BULKY
|
|
resistance_flags = INDESTRUCTIBLE
|
|
toolspeed = 1
|
|
|
|
var/revivecost = 1000
|
|
var/cooldown = FALSE
|
|
var/busy = FALSE
|
|
base_icon_state = "defibpaddles"
|
|
var/obj/item/defibrillator/defib
|
|
|
|
/obj/item/twohanded/shockpaddles/New(mainunit)
|
|
..()
|
|
if(check_defib_exists(mainunit, src))
|
|
defib = mainunit
|
|
loc = defib
|
|
busy = FALSE
|
|
update_icon(UPDATE_ICON_STATE)
|
|
return
|
|
|
|
/obj/item/twohanded/shockpaddles/update_icon_state()
|
|
icon_state = "[base_icon_state][wielded]"
|
|
item_state = "[base_icon_state][wielded]"
|
|
if(cooldown)
|
|
icon_state = "[base_icon_state][wielded]_cooldown"
|
|
|
|
/obj/item/twohanded/shockpaddles/suicide_act(mob/user)
|
|
user.visible_message("<span class='danger'>[user] is putting the live paddles on [user.p_their()] chest! It looks like [user.p_theyre()] trying to commit suicide.</span>")
|
|
defib.deductcharge(revivecost)
|
|
playsound(get_turf(src), 'sound/machines/defib_zap.ogg', 50, 1, -1)
|
|
return OXYLOSS
|
|
|
|
/obj/item/twohanded/shockpaddles/dropped(mob/user)
|
|
..()
|
|
if(user)
|
|
var/obj/item/twohanded/offhand/O = user.get_inactive_hand()
|
|
if(istype(O))
|
|
O.unwield()
|
|
to_chat(user, "<span class='notice'>The paddles snap back into the main unit.</span>")
|
|
defib.paddles_on_defib = TRUE
|
|
loc = defib
|
|
defib.update_icon(UPDATE_OVERLAYS)
|
|
update_icon(UPDATE_ICON_STATE)
|
|
unwield(user)
|
|
|
|
/obj/item/twohanded/shockpaddles/on_mob_move(dir, mob/user)
|
|
if(defib)
|
|
var/turf/t = get_turf(defib)
|
|
if(!t.Adjacent(user))
|
|
defib.remove_paddles(user)
|
|
|
|
/obj/item/twohanded/shockpaddles/proc/check_defib_exists(mainunit, mob/living/carbon/human/M, obj/O)
|
|
if(!mainunit || !istype(mainunit, /obj/item/defibrillator)) //To avoid weird issues from admin spawns
|
|
M.unEquip(O)
|
|
qdel(O)
|
|
return FALSE
|
|
else
|
|
return TRUE
|
|
|
|
/obj/item/twohanded/shockpaddles/attack(mob/M, mob/user)
|
|
var/tobehealed
|
|
var/threshold = -HEALTH_THRESHOLD_DEAD
|
|
var/mob/living/carbon/human/H = M
|
|
|
|
if(busy)
|
|
return
|
|
if(!defib.powered)
|
|
user.visible_message("<span class='notice'>[defib] beeps: Unit is unpowered.</span>")
|
|
playsound(get_turf(src), 'sound/machines/defib_failed.ogg', 50, 0)
|
|
return
|
|
if(!wielded)
|
|
to_chat(user, "<span class='boldnotice'>You need to wield the paddles in both hands before you can use them on someone!</span>")
|
|
return
|
|
if(cooldown)
|
|
to_chat(user, "<span class='notice'>[defib] is recharging.</span>")
|
|
return
|
|
if(!ishuman(M))
|
|
to_chat(user, "<span class='notice'>The instructions on [defib] don't mention how to defibrillate that...</span>")
|
|
return
|
|
else
|
|
if(user.a_intent == INTENT_HARM && !defib.safety)
|
|
busy = TRUE
|
|
H.visible_message("<span class='danger'>[user] has touched [H.name] with [src]!</span>", \
|
|
"<span class='userdanger'>[user] has touched [H.name] with [src]!</span>")
|
|
H.adjustStaminaLoss(60)
|
|
H.KnockDown(10 SECONDS)
|
|
playsound(get_turf(src), 'sound/machines/defib_zap.ogg', 50, 1, -1)
|
|
H.emote("gasp")
|
|
if((defib.combat && defib.heart_attack) || prob(10) && (defib.combat)) // If the victim is not having a heart attack, and a 10% chance passes, or the defib has heart attack variable to TRUE while being a combat defib, or if another 10% chance passes with combat being TRUE
|
|
H.set_heartattack(TRUE)
|
|
SEND_SIGNAL(H, COMSIG_LIVING_MINOR_SHOCK, 100)
|
|
add_attack_logs(user, M, "Stunned with [src]")
|
|
defib.deductcharge(revivecost)
|
|
cooldown = TRUE
|
|
busy = FALSE
|
|
update_icon(UPDATE_ICON_STATE)
|
|
defib.cooldowncheck(user)
|
|
return
|
|
user.visible_message("<span class='warning'>[user] begins to place [src] on [M.name]'s chest.</span>", "<span class='warning'>You begin to place [src] on [M.name]'s chest.</span>")
|
|
busy = TRUE
|
|
update_icon(UPDATE_ICON_STATE)
|
|
var/mob/dead/observer/ghost = H.get_ghost(TRUE)
|
|
if(ghost && ghost.can_reenter_corpse)
|
|
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)
|
|
notify_ghosts()
|
|
ghost << sound('sound/effects/genetics.ogg')
|
|
if(do_after(user, 30 * toolspeed, target = M)) //beginning to place the paddles on patient's chest to allow some time for people to move away to stop the process
|
|
user.visible_message("<span class='notice'>[user] places [src] on [M.name]'s chest.</span>", "<span class='warning'>You place [src] on [M.name]'s chest.</span>")
|
|
playsound(get_turf(src), 'sound/machines/defib_charge.ogg', 50, 0)
|
|
|
|
if(ghost && !ghost.client && !QDELETED(ghost))
|
|
QDEL_NULL(ghost)
|
|
var/tplus = world.time - H.timeofdeath
|
|
var/tlimit = DEFIB_TIME_LIMIT
|
|
var/tloss = DEFIB_TIME_LOSS
|
|
var/total_burn = 0
|
|
var/total_brute = 0
|
|
|
|
var/signal_result = SEND_SIGNAL(M, COMSIG_LIVING_PRE_DEFIB, user, defib, ghost)
|
|
|
|
if(do_after(user, 20 * toolspeed, target = M)) //placed on chest and short delay to shock for dramatic effect, revive time is 5sec total
|
|
signal_result |= SEND_SIGNAL(M, COMSIG_LIVING_DEFIBBED, user, defib, ghost)
|
|
for(var/obj/item/carried_item in H.contents)
|
|
if(istype(carried_item, /obj/item/clothing/suit/space))
|
|
if(!defib.combat)
|
|
user.visible_message("<span class='notice'>[defib] buzzes: Patient's chest is obscured. Operation aborted.</span>")
|
|
playsound(get_turf(src), 'sound/machines/defib_failed.ogg', 50, 0)
|
|
busy = FALSE
|
|
update_icon(UPDATE_ICON_STATE)
|
|
return
|
|
if(signal_result & COMPONENT_DEFIB_OVERRIDE)
|
|
// let our signal handle it
|
|
return
|
|
if(H.undergoing_cardiac_arrest())
|
|
if(!H.get_int_organ(/obj/item/organ/internal/heart) && !H.get_int_organ(/obj/item/organ/internal/brain/slime)) //prevents defibing someone still alive suffering from a heart attack attack if they lack a heart
|
|
user.visible_message("<span class='boldnotice'>[defib] buzzes: Resuscitation failed - Failed to pick up any heart electrical activity.</span>")
|
|
playsound(get_turf(src), 'sound/machines/defib_failed.ogg', 50, 0)
|
|
busy = FALSE
|
|
update_icon(UPDATE_ICON_STATE)
|
|
return
|
|
else
|
|
var/obj/item/organ/internal/heart/heart = H.get_int_organ(/obj/item/organ/internal/heart)
|
|
if(heart.status & ORGAN_DEAD)
|
|
user.visible_message("<span class='boldnotice'>[defib] buzzes: Resuscitation failed - Heart necrosis detected.</span>")
|
|
playsound(get_turf(src), 'sound/machines/defib_failed.ogg', 50, 0)
|
|
busy = FALSE
|
|
update_icon(UPDATE_ICON_STATE)
|
|
return
|
|
H.set_heartattack(FALSE)
|
|
SEND_SIGNAL(H, COMSIG_LIVING_MINOR_SHOCK, 100)
|
|
user.visible_message("<span class='boldnotice'>[defib] pings: Cardiac arrhythmia corrected.</span>")
|
|
M.visible_message("<span class='warning'>[M]'s body convulses a bit.")
|
|
playsound(get_turf(src), 'sound/machines/defib_zap.ogg', 50, 1, -1)
|
|
playsound(get_turf(src), "bodyfall", 50, 1)
|
|
playsound(get_turf(src), 'sound/machines/defib_success.ogg', 50, 0)
|
|
defib.deductcharge(revivecost)
|
|
busy = FALSE
|
|
cooldown = TRUE
|
|
update_icon(UPDATE_ICON_STATE)
|
|
defib.cooldowncheck(user)
|
|
return
|
|
if(H.stat == DEAD)
|
|
var/health = H.health
|
|
M.visible_message("<span class='warning'>[M]'s body convulses a bit.")
|
|
playsound(get_turf(src), "bodyfall", 50, 1)
|
|
playsound(get_turf(src), 'sound/machines/defib_zap.ogg', 50, 1, -1)
|
|
for(var/obj/item/organ/external/O in H.bodyparts)
|
|
total_brute += O.brute_dam
|
|
total_burn += O.burn_dam
|
|
ghost = H.get_ghost(TRUE) // We have to double check whether the dead guy has entered their body during the above
|
|
if(total_burn <= 180 && total_brute <= 180 && !H.suiciding && !ghost && tplus < tlimit && !HAS_TRAIT(H, TRAIT_HUSK) && !HAS_TRAIT(H, TRAIT_BADDNA) && H.blood_volume > BLOOD_VOLUME_SURVIVE && (H.get_int_organ(/obj/item/organ/internal/heart) || H.get_int_organ(/obj/item/organ/internal/brain/slime)) && !(signal_result & COMPONENT_BLOCK_DEFIB))
|
|
tobehealed = min(health + threshold, 0) // It's HILARIOUS without this min statement, let me tell you
|
|
tobehealed -= 5 //They get 5 of each type of damage healed so excessive combined damage will not immediately kill them after they get revived
|
|
H.adjustOxyLoss(tobehealed)
|
|
H.adjustToxLoss(tobehealed)
|
|
H.adjustFireLoss(tobehealed)
|
|
H.adjustBruteLoss(tobehealed)
|
|
if(H.get_int_organ(/obj/item/organ/internal/brain) && H.getBrainLoss() >= 100)
|
|
// 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(src), 'sound/machines/defib_saftyoff.ogg', 50, 0)
|
|
user.visible_message("<span class='boldnotice'>[defib] chimes: Minimal brain activity detected, brain treatment recommended for full resuscitation.</span>")
|
|
else
|
|
playsound(get_turf(src), 'sound/machines/defib_success.ogg', 50, 0)
|
|
user.visible_message("<span class='boldnotice'>[defib] pings: Resuscitation successful.</span>")
|
|
H.update_revive()
|
|
H.KnockOut()
|
|
H.Paralyse(10 SECONDS)
|
|
H.emote("gasp")
|
|
if(tplus > tloss)
|
|
H.setBrainLoss( max(0, min(99, ((tlimit - tplus) / tlimit * 100))))
|
|
|
|
SEND_SIGNAL(H, COMSIG_LIVING_MINOR_SHOCK, 100)
|
|
if(ishuman(H.pulledby)) // for some reason, pulledby isnt a list despite it being possible to be pulled by multiple people
|
|
excess_shock(user, H, H.pulledby)
|
|
for(var/obj/item/grab/G in H.grabbed_by)
|
|
if(ishuman(G.assailant))
|
|
excess_shock(user, H, G.assailant)
|
|
|
|
H.med_hud_set_health()
|
|
H.med_hud_set_status()
|
|
defib.deductcharge(revivecost)
|
|
add_attack_logs(user, M, "Revived with [src]")
|
|
else
|
|
if(tplus > tlimit|| !H.get_int_organ(/obj/item/organ/internal/heart))
|
|
user.visible_message("<span class='boldnotice'>[defib] buzzes: Resuscitation failed - Heart tissue damage beyond point of no return for defibrillation.</span>")
|
|
else if(total_burn >= 180 || total_brute >= 180)
|
|
user.visible_message("<span class='boldnotice'>[defib] buzzes: Resuscitation failed - Severe tissue damage detected.</span>")
|
|
else if(HAS_TRAIT(H, TRAIT_HUSK))
|
|
user.visible_message("<span class='boldnotice'>[defib] buzzes: Resuscitation failed: Subject is husked.</span>")
|
|
else if (H.blood_volume < BLOOD_VOLUME_SURVIVE)
|
|
user.visible_message("<span class='boldnotice'>[defib] buzzes: Resuscitation failed: Patient blood volume critically low.</span>")
|
|
else if(ghost)
|
|
if(!ghost.can_reenter_corpse) // DNR or AntagHUD
|
|
user.visible_message("<span class='boldnotice'>[defib] buzzes: Resuscitation failed: No electrical brain activity detected.</span>")
|
|
else
|
|
user.visible_message("<span class='boldnotice'>[defib] buzzes: Resuscitation failed: Patient's brain is unresponsive. Further attempts may succeed.</span>")
|
|
else
|
|
user.visible_message("<span class='boldnotice'>[defib] buzzes: Resuscitation failed.</span>")
|
|
playsound(get_turf(src), 'sound/machines/defib_failed.ogg', 50, 0)
|
|
defib.deductcharge(revivecost)
|
|
cooldown = TRUE
|
|
update_icon(UPDATE_ICON_STATE)
|
|
defib.cooldowncheck(user)
|
|
else
|
|
user.visible_message("<span class='notice'>[defib] buzzes: Patient is not in a valid state. Operation aborted.</span>")
|
|
playsound(get_turf(src), 'sound/machines/defib_failed.ogg', 50, 0)
|
|
busy = FALSE
|
|
update_icon(UPDATE_ICON_STATE)
|
|
|
|
/*
|
|
* user = the person using the defib
|
|
* origin = person being revived
|
|
* affecting = person being shocked with excess energy from the defib
|
|
*/
|
|
/obj/item/twohanded/shockpaddles/proc/excess_shock(mob/user, mob/living/carbon/human/origin, mob/living/carbon/human/affecting)
|
|
if(user == affecting)
|
|
return
|
|
|
|
if(electrocute_mob(affecting, defib.cell, origin)) // shock anyone touching them >:)
|
|
var/obj/item/organ/internal/heart/HE = affecting.get_organ_slot("heart")
|
|
if(HE.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 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)
|
|
|
|
/obj/item/borg_defib
|
|
name = "defibrillator paddles"
|
|
desc = "A pair of paddles with flat metal surfaces that are used to deliver powerful electric shocks."
|
|
icon = 'icons/obj/defib.dmi'
|
|
icon_state = "defibpaddles0"
|
|
item_state = "defibpaddles0"
|
|
force = 0
|
|
w_class = WEIGHT_CLASS_BULKY
|
|
var/revivecost = 1000
|
|
var/cooldown = FALSE
|
|
var/busy = FALSE
|
|
var/safety = TRUE
|
|
flags = NODROP
|
|
toolspeed = 1
|
|
|
|
/obj/item/borg_defib/attack(mob/M, mob/user)
|
|
var/tobehealed
|
|
var/threshold = -HEALTH_THRESHOLD_DEAD
|
|
var/mob/living/carbon/human/H = M
|
|
|
|
if(busy)
|
|
return
|
|
if(cooldown)
|
|
to_chat(user, "<span class='notice'>[src] is recharging.</span>")
|
|
if(!ishuman(M))
|
|
to_chat(user, "<span class='notice'>This unit is only designed to work on humanoid lifeforms.</span>")
|
|
return
|
|
else
|
|
if(user.a_intent == INTENT_HARM && !safety)
|
|
busy = TRUE
|
|
H.visible_message("<span class='danger'>[user] has touched [H.name] with [src]!</span>", \
|
|
"<span class='userdanger'>[user] has touched [H.name] with [src]!</span>")
|
|
H.adjustStaminaLoss(50)
|
|
H.Weaken(10 SECONDS)
|
|
if(!H.undergoing_cardiac_arrest() && prob(10)) // Your heart explodes.
|
|
H.set_heartattack(TRUE)
|
|
SEND_SIGNAL(H, COMSIG_LIVING_MINOR_SHOCK, 100)
|
|
playsound(get_turf(src), 'sound/machines/defib_zap.ogg', 50, 1, -1)
|
|
H.emote("gasp")
|
|
add_attack_logs(user, M, "Stunned with [src]")
|
|
if(isrobot(user))
|
|
var/mob/living/silicon/robot/R = user
|
|
R.cell.use(revivecost)
|
|
cooldown = TRUE
|
|
busy = FALSE
|
|
update_icon(UPDATE_ICON_STATE)
|
|
spawn(50)
|
|
cooldown = FALSE
|
|
update_icon(UPDATE_ICON_STATE)
|
|
return
|
|
user.visible_message("<span class='warning'>[user] begins to place [src] on [M.name]'s chest.</span>", "<span class='warning'>You begin to place [src] on [M.name]'s chest.</span>")
|
|
busy = TRUE
|
|
update_icon()
|
|
if(do_after(user, 30 * toolspeed, target = M)) //beginning to place the paddles on patient's chest to allow some time for people to move away to stop the process
|
|
user.visible_message("<span class='notice'>[user] places [src] on [M.name]'s chest.</span>", "<span class='warning'>You place [src] on [M.name]'s chest.</span>")
|
|
playsound(get_turf(src), 'sound/machines/defib_charge.ogg', 50, 0)
|
|
var/mob/dead/observer/ghost = H.get_ghost()
|
|
if(ghost && !ghost.client)
|
|
// In case the ghost's not getting deleted for some reason
|
|
H.key = ghost.key
|
|
stack_trace("Ghost of name [ghost.name] is bound to [H.real_name], but lacks a client. Deleting ghost.")
|
|
|
|
QDEL_NULL(ghost)
|
|
var/tplus = world.time - H.timeofdeath
|
|
var/tlimit = 3000 //past this much time the patient is unrecoverable (in deciseconds)
|
|
var/tloss = 600 //brain damage starts setting in on the patient after some time left rotting
|
|
var/total_burn = 0
|
|
var/total_brute = 0
|
|
|
|
var/signal_result = SEND_SIGNAL(M, COMSIG_LIVING_PRE_DEFIB, user, src, ghost)
|
|
if(do_after(user, 20 * toolspeed, target = M)) //placed on chest and short delay to shock for dramatic effect, revive time is 5sec total
|
|
signal_result |= SEND_SIGNAL(M, COMSIG_LIVING_DEFIBBED, user, src, ghost)
|
|
if(H.stat == DEAD)
|
|
var/health = H.health
|
|
M.visible_message("<span class='warning'>[M]'s body convulses a bit.")
|
|
playsound(get_turf(src), "bodyfall", 50, 1)
|
|
playsound(get_turf(src), 'sound/machines/defib_zap.ogg', 50, 1, -1)
|
|
for(var/obj/item/organ/external/O in H.bodyparts)
|
|
total_brute += O.brute_dam
|
|
total_burn += O.burn_dam
|
|
if(total_burn <= 180 && total_brute <= 180 && !H.suiciding && !ghost && tplus < tlimit && !HAS_TRAIT(H, TRAIT_HUSK) && !(signal_result & COMPONENT_BLOCK_DEFIB))
|
|
tobehealed = min(health + threshold, 0) // It's HILARIOUS without this min statement, let me tell you
|
|
tobehealed -= 5 //They get 5 of each type of damage healed so excessive combined damage will not immediately kill them after they get revived
|
|
H.adjustOxyLoss(tobehealed)
|
|
H.adjustToxLoss(tobehealed)
|
|
H.adjustFireLoss(tobehealed)
|
|
H.adjustBruteLoss(tobehealed)
|
|
user.visible_message("<span class='notice'>[user] pings: Resuscitation successful.</span>")
|
|
playsound(get_turf(src), 'sound/machines/defib_success.ogg', 50, 0)
|
|
H.update_revive(FALSE)
|
|
H.KnockOut(FALSE)
|
|
H.Paralyse(10 SECONDS)
|
|
H.emote("gasp")
|
|
if(tplus > tloss)
|
|
H.setBrainLoss( max(0, min(99, ((tlimit - tplus) / tlimit * 100))))
|
|
SEND_SIGNAL(H, COMSIG_LIVING_MINOR_SHOCK, 100)
|
|
SEND_SIGNAL(H, COMSIG_LIVING_DEFIBBED, user, src)
|
|
if(isrobot(user))
|
|
var/mob/living/silicon/robot/R = user
|
|
R.cell.use(revivecost)
|
|
add_attack_logs(user, M, "Revived with [src]")
|
|
else
|
|
if(tplus > tlimit)
|
|
user.visible_message("<span class='warning'>[user] buzzes: Resuscitation failed - Heart tissue damage beyond point of no return for defibrillation.</span>")
|
|
else if(total_burn >= 180 || total_brute >= 180)
|
|
user.visible_message("<span class='warning'>[user] buzzes: Resuscitation failed - Severe tissue damage detected.</span>")
|
|
else if(ghost)
|
|
user.visible_message("<span class='notice'>[user] buzzes: Resuscitation failed: Patient's brain is unresponsive. Further attempts may succeed.</span>")
|
|
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)
|
|
ghost << sound('sound/effects/genetics.ogg')
|
|
else
|
|
user.visible_message("<span class='warning'>[user] buzzes: Resuscitation failed.</span>")
|
|
playsound(get_turf(src), 'sound/machines/defib_failed.ogg', 50, 0)
|
|
if(isrobot(user))
|
|
var/mob/living/silicon/robot/R = user
|
|
R.cell.use(revivecost)
|
|
cooldown = TRUE
|
|
update_icon(UPDATE_ICON_STATE)
|
|
spawn(50)
|
|
cooldown = FALSE
|
|
update_icon(UPDATE_ICON_STATE)
|
|
else
|
|
user.visible_message("<span class='notice'>[user] buzzes: Patient is not in a valid state. Operation aborted.</span>")
|
|
playsound(get_turf(src), 'sound/machines/defib_failed.ogg', 50, 0)
|
|
busy = FALSE
|
|
update_icon(UPDATE_ICON_STATE)
|
|
|
|
/obj/item/twohanded/shockpaddles/syndicate
|
|
name = "combat defibrillator paddles"
|
|
desc = "A pair of high-tech paddles with flat plasteel surfaces to revive deceased operatives (unless they exploded). They possess both the ability to penetrate armor and to deliver powerful or disabling shocks offensively."
|
|
icon_state = "syndiepaddles0"
|
|
item_state = "syndiepaddles0"
|
|
base_icon_state = "syndiepaddles"
|
|
|
|
/obj/item/twohanded/shockpaddles/advanced
|
|
name = "advanced defibrillator paddles"
|
|
desc = "A pair of high-tech paddles with flat plasteel surfaces that are used to deliver powerful electric shocks. They possess the ability to penetrate armor to deliver shock."
|
|
icon_state = "ntpaddles0"
|
|
item_state = "ntpaddles0"
|
|
base_icon_state = "ntpaddles"
|