mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-08-26 13:37:58 +01:00
Reviving the revival of revivers reviving. Revival edition. (#27436)
* reviver * toxic * more changes * final changes * I lied one more * woe rename apon thee * Update code/modules/surgery/organs/augments_internal.dm Signed-off-by: DGamerL <108773801+DGamerL@users.noreply.github.com> --------- Signed-off-by: DGamerL <108773801+DGamerL@users.noreply.github.com> Co-authored-by: DGamerL <108773801+DGamerL@users.noreply.github.com>
This commit is contained in:
@@ -673,14 +673,23 @@
|
||||
/datum/status_effect/hope/tick()
|
||||
if(owner.stat == DEAD || owner.health <= HEALTH_THRESHOLD_DEAD) // No dead healing, or healing in dead crit
|
||||
return
|
||||
var/heal_multiplier = 0
|
||||
switch(owner.health)
|
||||
if(50 to INFINITY)
|
||||
heal_multiplier = 1
|
||||
if(0 to 50)
|
||||
heal_multiplier = 2
|
||||
if(-50 to 0)
|
||||
heal_multiplier = 3
|
||||
if(-100 to -50)
|
||||
heal_multiplier = 4
|
||||
owner.adjustBruteLoss(-heal_multiplier)
|
||||
owner.adjustFireLoss(-heal_multiplier)
|
||||
owner.adjustOxyLoss(-heal_multiplier)
|
||||
if(owner.health > 50)
|
||||
if(prob(0.5))
|
||||
hope_message()
|
||||
return
|
||||
var/heal_multiplier = min(3, ((50 - owner.health) / 50 + 1)) // 1 hp at 50 health, 2 at 0, 3 at -50
|
||||
owner.adjustBruteLoss(-heal_multiplier * 0.5)
|
||||
owner.adjustFireLoss(-heal_multiplier * 0.5)
|
||||
owner.adjustOxyLoss(-heal_multiplier)
|
||||
if(prob(heal_multiplier * 2))
|
||||
hope_message()
|
||||
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
|
||||
if(stat != DEAD)
|
||||
handle_organs()
|
||||
else
|
||||
handle_dead_organs()
|
||||
|
||||
//stuff in the stomach
|
||||
if(LAZYLEN(stomach_contents))
|
||||
@@ -205,6 +207,14 @@
|
||||
var/datum/organ/datum_organ_var_name_idk = internal_organ_datums[organ_tag]
|
||||
datum_organ_var_name_idk.on_life()
|
||||
|
||||
/mob/living/carbon/proc/handle_dead_organs()
|
||||
for(var/thing in internal_organs)
|
||||
var/obj/item/organ/internal/O = thing
|
||||
O.dead_process()
|
||||
for(var/organ_tag in internal_organ_datums)
|
||||
var/datum/organ/datum_organ_var_name_idk = internal_organ_datums[organ_tag]
|
||||
datum_organ_var_name_idk.dead_process()
|
||||
|
||||
/mob/living/carbon/handle_diseases()
|
||||
for(var/thing in viruses)
|
||||
var/datum/disease/D = thing
|
||||
|
||||
@@ -198,7 +198,7 @@
|
||||
friendly_fire_check = TRUE
|
||||
|
||||
|
||||
//Pandora's loot: Hope //Hope I know what to make it do
|
||||
//Pandora's loot: Hope
|
||||
/obj/item/clothing/accessory/necklace/pandora_hope
|
||||
name = "Hope"
|
||||
desc = "Found at the bottom of Pandora. After all the evil was released, this was the only thing left inside."
|
||||
|
||||
@@ -616,7 +616,7 @@
|
||||
name = "Reviver Implant"
|
||||
desc = "This implant will attempt to revive you if you lose consciousness. For the faint of heart!"
|
||||
id = "ci-reviver"
|
||||
req_tech = list("materials" = 5, "programming" = 4, "biotech" = 5)
|
||||
req_tech = list("materials" = 5, "programming" = 6, "biotech" = 7)
|
||||
build_type = PROTOLATHE | MECHFAB
|
||||
construction_time = 60
|
||||
materials = list(MAT_METAL = 800, MAT_GLASS = 800, MAT_GOLD = 300, MAT_URANIUM = 500)
|
||||
|
||||
@@ -663,14 +663,21 @@
|
||||
|
||||
/obj/item/organ/internal/cyberimp/chest/reviver
|
||||
name = "Reviver implant"
|
||||
desc = "This implant will attempt to heal you out of critical condition. For the faint of heart!"
|
||||
desc = "This implant will attempt to revive and heal you out of critical condition or death. For the faint of heart!"
|
||||
icon_state = "reviver_implant"
|
||||
implant_overlay = null
|
||||
origin_tech = "materials=5;programming=4;biotech=4"
|
||||
origin_tech = "materials=5;programming=5;biotech=6"
|
||||
slot = "heartdrive"
|
||||
var/revive_cost = 0
|
||||
/// How long the implant will go on cooldown for once the user has exited crit, in seconds.
|
||||
var/revive_cost = 0 SECONDS
|
||||
/// Are we in the progress of healing the user?
|
||||
var/reviving = FALSE
|
||||
var/cooldown = 0
|
||||
/// Have we defibed someone this heal period? If so, do not heal past crit without an upgraded heart, as it is low on juice.
|
||||
var/has_defibed = FALSE
|
||||
/// How long we are on cooldown for
|
||||
COOLDOWN_DECLARE(reviver_cooldown)
|
||||
/// How long till we can try to defib again
|
||||
COOLDOWN_DECLARE(defib_cooldown)
|
||||
|
||||
/obj/item/organ/internal/cyberimp/chest/reviver/hardened
|
||||
name = "Hardened reviver implant"
|
||||
@@ -680,52 +687,146 @@
|
||||
. = ..()
|
||||
desc += " The implant has been hardened. It is invulnerable to EMPs."
|
||||
|
||||
/obj/item/organ/internal/cyberimp/chest/reviver/dead_process()
|
||||
try_heal() // Allows implant to work even on dead people
|
||||
|
||||
/obj/item/organ/internal/cyberimp/chest/reviver/on_life()
|
||||
if(cooldown > world.time || owner.suiciding) // don't heal while you're in cooldown!
|
||||
return
|
||||
try_heal()
|
||||
|
||||
/obj/item/organ/internal/cyberimp/chest/reviver/proc/try_heal()
|
||||
if(reviving)
|
||||
reviving = FALSE
|
||||
if(owner.health <= HEALTH_THRESHOLD_CRIT + 10) //We do not want to leave them on the end of crit constantly.
|
||||
addtimer(CALLBACK(src, PROC_REF(heal)), 30)
|
||||
reviving = TRUE
|
||||
if(owner.health > HEALTH_THRESHOLD_CRIT && owner.HasDisease(new /datum/disease/critical/shock(0)) && prob(15)) //We do not do an else, as we need them to cure shock inside this magic zone of 10 damage
|
||||
for(var/datum/disease/critical/shock/S in owner.viruses)
|
||||
S.cure()
|
||||
revive_cost += 150
|
||||
to_chat(owner, "<span class='notice'>You feel better.</span>")
|
||||
if(!reviving)
|
||||
return
|
||||
cooldown = revive_cost + world.time
|
||||
revive_cost = 0
|
||||
reviving = TRUE
|
||||
if(owner.stat != DEAD && reached_heal_threshold()) //Don't stop healing when they are dead.
|
||||
COOLDOWN_START(src, reviver_cooldown, revive_cost)
|
||||
reviving = FALSE
|
||||
to_chat(owner, "<span class='notice'>Your reviver implant shuts down and starts recharging. It will be ready again in [DisplayTimeText(revive_cost)].</span>")
|
||||
else
|
||||
addtimer(CALLBACK(src, PROC_REF(heal)), 3 SECONDS)
|
||||
return
|
||||
if(!COOLDOWN_FINISHED(src, reviver_cooldown) || owner.suiciding) // don't heal while you're in cooldown!
|
||||
return
|
||||
if(owner.health <= 0 || owner.stat == DEAD)
|
||||
revive_cost = 0
|
||||
reviving = TRUE
|
||||
has_defibed = FALSE
|
||||
to_chat(owner, "<span class='notice'>You feel a faint buzzing as your reviver implant starts patching your wounds...</span>")
|
||||
COOLDOWN_START(src, defib_cooldown, 8 SECONDS) // 5 seconds after heal proc delay
|
||||
|
||||
/obj/item/organ/internal/cyberimp/chest/reviver/proc/heal()
|
||||
if(QDELETED(owner))
|
||||
return
|
||||
if(prob(90) && owner.getOxyLoss())
|
||||
// This is not on defib check so it doesnt revive IPCs either in a demon.
|
||||
if(HAS_TRAIT(owner, TRAIT_UNREVIVABLE))
|
||||
return
|
||||
if(COOLDOWN_FINISHED(src, defib_cooldown))
|
||||
revive_dead()
|
||||
/// boolean that stands for if PHYSICAL damage being patched
|
||||
var/body_damage_patched = FALSE
|
||||
if(owner.getOxyLoss())
|
||||
owner.adjustOxyLoss(-3)
|
||||
revive_cost += 5
|
||||
if(prob(75) && owner.getBruteLoss())
|
||||
owner.adjustBruteLoss(-2)
|
||||
revive_cost += 15
|
||||
if(prob(75) && owner.getFireLoss())
|
||||
owner.adjustFireLoss(-2)
|
||||
revive_cost += 15
|
||||
if(prob(40) && owner.getToxLoss())
|
||||
revive_cost += 0.5 SECONDS
|
||||
if(owner.getBruteLoss())
|
||||
owner.adjustBruteLoss(-2, robotic = TRUE)
|
||||
revive_cost += 4 SECONDS
|
||||
body_damage_patched = TRUE
|
||||
if(owner.getFireLoss())
|
||||
owner.adjustFireLoss(-2, robotic = TRUE)
|
||||
revive_cost += 4 SECONDS
|
||||
body_damage_patched = TRUE
|
||||
if(owner.getToxLoss())
|
||||
owner.adjustToxLoss(-1)
|
||||
revive_cost += 25
|
||||
revive_cost += 4 SECONDS
|
||||
|
||||
if(body_damage_patched && prob(25)) // healing is called every few seconds, not every tick
|
||||
if(owner.stat != CONSCIOUS)
|
||||
owner.visible_message("<span class='warning'>[owner]'s body [pick("twitches", "shifts", "shivers", "spasms", "vibrates")] a bit.</span>", \
|
||||
"<span class='notice'>You feel like something is patching your injured body.</span>")
|
||||
else // No twitching if awake.
|
||||
to_chat(owner, "<span class='notice'>You feel like something is patching your injured body.</span>")
|
||||
|
||||
/obj/item/organ/internal/cyberimp/chest/reviver/proc/revive_dead()
|
||||
if(!COOLDOWN_FINISHED(src, defib_cooldown) || owner.stat != DEAD || !can_defib())
|
||||
return
|
||||
var/mob/dead/observer/ghost = owner.get_ghost()
|
||||
if(ghost)
|
||||
if(!ghost.can_reenter_corpse)
|
||||
return
|
||||
to_chat(ghost, "<span class='ghostalert'>You are being revived by [src]!</span>")
|
||||
window_flash(ghost.client)
|
||||
SEND_SOUND(ghost, sound('sound/effects/genetics.ogg'))
|
||||
COOLDOWN_START(src, defib_cooldown, 16 SECONDS)
|
||||
playsound(get_turf(owner), 'sound/machines/defib_charge.ogg', 50, FALSE)
|
||||
owner.grab_ghost()
|
||||
owner.visible_message("<span class='warning'>[owner]'s body spasms violently!</span>")
|
||||
addtimer(CALLBACK(src, PROC_REF(zap_em)), 5 SECONDS)
|
||||
|
||||
/obj/item/organ/internal/cyberimp/chest/reviver/proc/zap_em()
|
||||
playsound(owner, 'sound/machines/defib_zap.ogg', 75, TRUE, -1)
|
||||
// Inflict some brain damage scaling with time spent dead
|
||||
var/time_dead = world.time - owner.timeofdeath
|
||||
var/obj/item/organ/internal/brain/sponge = owner.get_int_organ(/obj/item/organ/internal/brain)
|
||||
var/defib_time_brain_damage = min(100 * time_dead / BASE_DEFIB_TIME_LIMIT, 89) // 20 from 1 minute onward, +20 per minute up to 99 (10 organ damage flat added after)
|
||||
if(time_dead > DEFIB_TIME_LOSS && defib_time_brain_damage > sponge.damage)
|
||||
owner.setBrainLoss(defib_time_brain_damage)
|
||||
// Turns out it takes some raw materials to heal you so much and defib you from inside. We took some material from your organs and iron from blood, hope you do not mind!
|
||||
if(ishuman(owner))
|
||||
var/mob/living/carbon/human/H = owner
|
||||
for(var/obj/item/organ/internal/I in H.internal_organs)
|
||||
I.receive_damage(10, TRUE)
|
||||
H.blood_volume *= 0.85
|
||||
revive_cost += 10 MINUTES // Additional 10 minutes cooldown after revival.
|
||||
owner.SetLoseBreath(0) //Reset the heart attack losebreath of hell
|
||||
owner.set_heartattack(FALSE)
|
||||
owner.update_revive()
|
||||
owner.KnockOut()
|
||||
owner.Paralyse(10 SECONDS)
|
||||
owner.emote("gasp")
|
||||
owner.Jitter(20 SECONDS)
|
||||
has_defibed = TRUE
|
||||
SEND_SIGNAL(owner, COMSIG_LIVING_MINOR_SHOCK)
|
||||
add_attack_logs(owner, owner, "Revived with [src]")
|
||||
|
||||
/obj/item/organ/internal/cyberimp/chest/reviver/proc/can_defib()
|
||||
if(!owner)
|
||||
return FALSE
|
||||
// They will get up on their own.
|
||||
if(ismachineperson(owner))
|
||||
return FALSE
|
||||
// Slight tweak, revive if brute burn and oxygen loss *combined* are above 210, to avoid spam defibing at like, 200+ brute burn damage or 200 o2 loss
|
||||
if(!owner.is_revivable() || owner.getBruteLoss() + owner.getFireLoss() + owner.getOxyLoss() >= 210 || HAS_TRAIT(owner, TRAIT_HUSK) || owner.blood_volume < BLOOD_VOLUME_SURVIVE)
|
||||
return FALSE
|
||||
// Let us break this on multiple lines
|
||||
// Clone loss is a new addition outside defib code, to avoid endless revive hell.
|
||||
// Avoid defibing with over 125 toxin loss as well. This also means toxin will delay someone from being revived *much* longer.
|
||||
if(!owner.get_organ_slot("brain") || HAS_TRAIT(owner, TRAIT_FAKEDEATH) || HAS_TRAIT(owner, TRAIT_BADDNA) || owner.getCloneLoss() >= 180 || owner.getToxLoss() >= 125)
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/item/organ/internal/cyberimp/chest/reviver/proc/reached_heal_threshold()
|
||||
// By default, 0 health. Won't heal you out of shock alone, will need some medical attention still if you do not have meds!
|
||||
// Will heal you out of crit though with 2 ticks of extra healing, due to callback.
|
||||
if(ishuman(owner))
|
||||
var/mob/living/carbon/human/H = owner
|
||||
var/heal_threshold = 0
|
||||
var/obj/item/organ/internal/heart/cybernetic/upgraded/U = H.get_int_organ(/obj/item/organ/internal/heart/cybernetic/upgraded)
|
||||
if(U) // The heart assists in healing, and will heal you out of shock.
|
||||
heal_threshold = 25
|
||||
if(!has_defibed) // Not low on power, can heal you out of shock.
|
||||
heal_threshold = 25
|
||||
if(H.health > heal_threshold)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/item/organ/internal/cyberimp/chest/reviver/emp_act(severity)
|
||||
if(!owner || emp_proof)
|
||||
return
|
||||
if(reviving)
|
||||
revive_cost += 200
|
||||
revive_cost += 40 SECONDS
|
||||
COOLDOWN_START(src, defib_cooldown, 20 SECONDS)
|
||||
else
|
||||
cooldown += 200
|
||||
COOLDOWN_START(src, reviver_cooldown, 20 SECONDS)
|
||||
if(ishuman(owner))
|
||||
var/mob/living/carbon/human/H = owner
|
||||
if(H.stat != DEAD && prob(50 / severity))
|
||||
if(H.stat != DEAD && prob(50 / severity) && H.can_heartattack())
|
||||
H.set_heartattack(TRUE)
|
||||
addtimer(CALLBACK(src, PROC_REF(undo_heart_attack)), 600 / severity)
|
||||
|
||||
@@ -734,6 +835,8 @@
|
||||
if(!istype(H))
|
||||
return
|
||||
H.set_heartattack(FALSE)
|
||||
H.adjustOxyLoss(-100) ///In the unlikely case that you are still alive, this should get you maybe to livable circumstances.
|
||||
H.SetLoseBreath(0)
|
||||
if(H.stat == CONSCIOUS)
|
||||
to_chat(H, "<span class='notice'>You feel your heart beating again!</span>")
|
||||
|
||||
|
||||
@@ -14,12 +14,10 @@
|
||||
..()
|
||||
ADD_TRAIT(owner, TRAIT_XENO_HOST, TRAIT_GENERIC)
|
||||
ADD_TRAIT(owner, TRAIT_XENO_IMMUNE, "xeno immune")
|
||||
START_PROCESSING(SSobj, src)
|
||||
owner.med_hud_set_status()
|
||||
INVOKE_ASYNC(src, PROC_REF(AddInfectionImages), owner)
|
||||
|
||||
/obj/item/organ/internal/body_egg/remove(mob/living/carbon/M, special = 0)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
if(owner)
|
||||
REMOVE_TRAIT(owner, TRAIT_XENO_HOST, TRAIT_GENERIC)
|
||||
REMOVE_TRAIT(owner, TRAIT_XENO_IMMUNE, "xeno immune")
|
||||
@@ -27,10 +25,14 @@
|
||||
INVOKE_ASYNC(src, PROC_REF(RemoveInfectionImages), owner)
|
||||
. = ..()
|
||||
|
||||
/obj/item/organ/internal/body_egg/process()
|
||||
if(!owner)
|
||||
/obj/item/organ/internal/body_egg/on_life()
|
||||
if(!(src in owner.internal_organs)) // I can only presume this is here for a reason, so not touching it.
|
||||
remove(owner)
|
||||
return
|
||||
if(!(src in owner.internal_organs))
|
||||
egg_process()
|
||||
|
||||
/obj/item/organ/internal/body_egg/dead_process()
|
||||
if(!(src in owner.internal_organs)) // I can only presume this is here for a reason, so not touching it.
|
||||
remove(owner)
|
||||
return
|
||||
egg_process()
|
||||
|
||||
@@ -237,19 +237,23 @@
|
||||
if(prob(20) && emagged)
|
||||
attempted_restart = TRUE
|
||||
heart_datum.change_beating(TRUE) // Mötley Crüe - Kickstart My Heart
|
||||
owner.adjustOxyLoss(-100)
|
||||
owner.SetLoseBreath(0)
|
||||
addtimer(CALLBACK(src, PROC_REF(message_to_owner), owner, "<span class='warning'>Your [name] returns to its normal rhythm!</span>"), 3 SECONDS)
|
||||
addtimer(CALLBACK(src, PROC_REF(recharge)), 20 SECONDS)
|
||||
else if(prob(10))
|
||||
attempted_restart = TRUE
|
||||
heart_datum.change_beating(TRUE)
|
||||
owner.adjustOxyLoss(-100)
|
||||
owner.SetLoseBreath(0)
|
||||
addtimer(CALLBACK(src, PROC_REF(message_to_owner), owner, "<span class='warning'>Your [name] returns to its normal rhythm!</span>"), 3 SECONDS)
|
||||
addtimer(CALLBACK(src, PROC_REF(recharge)), 30 SECONDS)
|
||||
else
|
||||
attempted_restart = TRUE
|
||||
if(emagged)
|
||||
addtimer(CALLBACK(src, PROC_REF(recharge)), 20 SECONDS)
|
||||
addtimer(CALLBACK(src, PROC_REF(recharge)), 10 SECONDS)
|
||||
else
|
||||
addtimer(CALLBACK(src, PROC_REF(recharge)), 30 SECONDS)
|
||||
addtimer(CALLBACK(src, PROC_REF(recharge)), 15 SECONDS)
|
||||
addtimer(CALLBACK(src, PROC_REF(message_to_owner), owner, "<span class='warning'>Your [name] fails to return to its normal rhythm!</span>"), 3 SECONDS)
|
||||
|
||||
if(owner.HasDisease(/datum/disease/critical/heart_failure))
|
||||
@@ -259,19 +263,19 @@
|
||||
for(var/datum/disease/critical/heart_failure/HF in owner.viruses)
|
||||
HF.cure()
|
||||
addtimer(CALLBACK(src, PROC_REF(message_to_owner), owner, "<span class='warning'>Your [name] returns to its normal rhythm!</span>"), 30)
|
||||
addtimer(CALLBACK(src, PROC_REF(recharge)), 200)
|
||||
addtimer(CALLBACK(src, PROC_REF(recharge)), 20 SECONDS)
|
||||
else if(prob(25))
|
||||
attempted_restart = TRUE
|
||||
for(var/datum/disease/critical/heart_failure/HF in owner.viruses)
|
||||
HF.cure()
|
||||
addtimer(CALLBACK(src, PROC_REF(message_to_owner), owner, "<span class='warning'>Your [name] returns to its normal rhythm!</span>"), 30)
|
||||
addtimer(CALLBACK(src, PROC_REF(recharge)), 200)
|
||||
addtimer(CALLBACK(src, PROC_REF(recharge)), 20 SECONDS)
|
||||
else
|
||||
attempted_restart = TRUE
|
||||
if(emagged)
|
||||
addtimer(CALLBACK(src, PROC_REF(recharge)), 200)
|
||||
addtimer(CALLBACK(src, PROC_REF(recharge)), 10 SECONDS)
|
||||
else
|
||||
addtimer(CALLBACK(src, PROC_REF(recharge)), 300)
|
||||
addtimer(CALLBACK(src, PROC_REF(recharge)), 15 SECONDS)
|
||||
addtimer(CALLBACK(src, PROC_REF(message_to_owner), owner, "<span class='warning'>Your [name] fails to return to its normal rhythm!</span>"), 30)
|
||||
|
||||
|
||||
|
||||
@@ -25,6 +25,9 @@
|
||||
/datum/organ/proc/on_life()
|
||||
return
|
||||
|
||||
/datum/organ/proc/dead_process()
|
||||
return
|
||||
|
||||
/// Only called when the organ is robotic AND is not emp proof. Return true to override default functions
|
||||
/datum/organ/proc/on_successful_emp()
|
||||
return FALSE
|
||||
|
||||
@@ -170,6 +170,9 @@
|
||||
/obj/item/organ/internal/proc/on_life()
|
||||
return
|
||||
|
||||
/obj/item/organ/internal/proc/dead_process()
|
||||
return
|
||||
|
||||
//abstract proc called by carbon/death()
|
||||
/obj/item/organ/internal/proc/on_owner_death()
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user