mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-28 15:47:15 +01:00
[MIRROR] Heart code cleanup [MDB IGNORE] (#25019)
* Heart code cleanup (#79602) ## About The Pull Request General clean up of heart code. - Use `Stop` and `Restart` in `set_heart_attack` - Use `SEND_SOUND()` rather than `playsound_local` for heartbeats - Use `update_icon_blocker` - Correctly ensures ethereal hearts get their overlay - Adds heartbeat animation to ethereal hearts ## Changelog 🆑 Melbert code: General heart code cleanup. fix: Heartbeat sound effects are no longer sourced to the exact tile you fell into crit at fix: Abductors glands are less likely to become invisible or look wrong fix: Ethereal hearts are less likely to become invisible or look wrong, and now properly spawn with their shine overlay image: Adds heartbeat animation to beating Ethereal Hearts /🆑 * Heart code cleanup --------- Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com>
This commit is contained in:
@@ -78,10 +78,7 @@
|
||||
name = odd_organ_name()
|
||||
icon_state = FLY_INFUSED_ORGAN_ICON
|
||||
AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/fly)
|
||||
|
||||
/obj/item/organ/internal/heart/fly/update_icon_state()
|
||||
SHOULD_CALL_PARENT(FALSE)
|
||||
return //don't set icon thank you
|
||||
AddElement(/datum/element/update_icon_blocker)
|
||||
|
||||
/obj/item/organ/internal/lungs/fly
|
||||
desc = FLY_INFUSED_ORGAN_DESC
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
icon = 'icons/obj/antags/abductor.dmi'
|
||||
icon_state = "gland"
|
||||
organ_flags = ORGAN_ROBOTIC // weird?
|
||||
beating = TRUE
|
||||
/// Shows name of the gland as well as a description of what it does upon examination by abductor scientists and observers.
|
||||
var/abductor_hint = "baseline placebo referencer"
|
||||
|
||||
@@ -26,12 +25,16 @@
|
||||
/obj/item/organ/internal/heart/gland/Initialize(mapload)
|
||||
. = ..()
|
||||
icon_state = pick(list("health", "spider", "slime", "emp", "species", "egg", "vent", "mindshock", "viral"))
|
||||
AddElement(/datum/element/update_icon_blocker)
|
||||
|
||||
/obj/item/organ/internal/heart/gland/examine(mob/user)
|
||||
. = ..()
|
||||
if(HAS_MIND_TRAIT(user, TRAIT_ABDUCTOR_SCIENTIST_TRAINING) || isobserver(user))
|
||||
. += span_notice("It is \a [abductor_hint]")
|
||||
|
||||
/obj/item/organ/internal/heart/gland/Stop()
|
||||
return FALSE
|
||||
|
||||
/obj/item/organ/internal/heart/gland/proc/ownerCheck()
|
||||
if(ishuman(owner))
|
||||
return TRUE
|
||||
@@ -102,9 +105,6 @@
|
||||
update_gland_hud()
|
||||
|
||||
/obj/item/organ/internal/heart/gland/on_life(seconds_per_tick, times_fired)
|
||||
if(!beating)
|
||||
// alien glands are immune to stopping.
|
||||
beating = TRUE
|
||||
if(!active)
|
||||
return
|
||||
if(!ownerCheck())
|
||||
|
||||
@@ -50,8 +50,8 @@
|
||||
/obj/item/organ/internal/heart/nightmare
|
||||
name = "heart of darkness"
|
||||
desc = "An alien organ that twists and writhes when exposed to light."
|
||||
icon = 'icons/obj/medical/organs/organs.dmi'
|
||||
icon_state = "demon_heart-on"
|
||||
base_icon_state = "demon_heart"
|
||||
visual = TRUE
|
||||
color = "#1C1C1C"
|
||||
decay_factor = 0
|
||||
@@ -60,10 +60,6 @@
|
||||
/// The armblade granted to the host of this heart.
|
||||
var/obj/item/light_eater/blade
|
||||
|
||||
/obj/item/organ/internal/heart/nightmare/Initialize(mapload)
|
||||
AddElement(/datum/element/update_icon_blocker)
|
||||
return ..()
|
||||
|
||||
/obj/item/organ/internal/heart/nightmare/attack(mob/M, mob/living/carbon/user, obj/target)
|
||||
if(M != user)
|
||||
return ..()
|
||||
@@ -94,7 +90,7 @@
|
||||
QDEL_NULL(blade)
|
||||
|
||||
/obj/item/organ/internal/heart/nightmare/Stop()
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
/obj/item/organ/internal/heart/nightmare/on_death(seconds_per_tick, times_fired)
|
||||
if(!owner)
|
||||
|
||||
@@ -237,7 +237,7 @@
|
||||
|
||||
//assess heart
|
||||
if(body_part == BODY_ZONE_CHEST)//if we're listening to the chest
|
||||
if(isnull(heart) || !heart.beating || carbon_patient.stat == DEAD)
|
||||
if(isnull(heart) || !heart.is_beating() || carbon_patient.stat == DEAD)
|
||||
render_list += "<span class='danger ml-1'>You don't hear a heartbeat!</span>\n"//they're dead or their heart isn't beating
|
||||
else if(heart.damage > 10 || carbon_patient.blood_volume <= BLOOD_VOLUME_OKAY)
|
||||
render_list += "<span class='danger ml-1'>You hear a weak heartbeat.</span>\n"//their heart is damaged, or they have critical blood
|
||||
@@ -289,7 +289,7 @@
|
||||
user.visible_message(span_notice("[user] presses their fingers against [carbon_patient]'s [body_part]."), ignored_mobs = user)
|
||||
|
||||
//assess pulse (heart & blood level)
|
||||
if(isnull(heart) || !heart.beating || carbon_patient.blood_volume <= BLOOD_VOLUME_OKAY || carbon_patient.stat == DEAD)
|
||||
if(isnull(heart) || !heart.is_beating() || carbon_patient.blood_volume <= BLOOD_VOLUME_OKAY || carbon_patient.stat == DEAD)
|
||||
render_list += "<span class='danger ml-1'>You can't find a pulse!</span>\n"//they're dead, their heart isn't beating, or they have critical blood
|
||||
else
|
||||
if(heart.damage > 10)
|
||||
|
||||
@@ -21,9 +21,8 @@ GLOBAL_LIST_EMPTY(dead_players_during_shift)
|
||||
if(stat == DEAD)
|
||||
return
|
||||
stop_sound_channel(CHANNEL_HEARTBEAT)
|
||||
var/obj/item/organ/internal/heart/H = get_organ_slot(ORGAN_SLOT_HEART)
|
||||
if(H)
|
||||
H.beat = BEAT_NONE
|
||||
var/obj/item/organ/internal/heart/human_heart = get_organ_slot(ORGAN_SLOT_HEART)
|
||||
human_heart?.beat = BEAT_NONE
|
||||
|
||||
. = ..()
|
||||
|
||||
|
||||
@@ -803,12 +803,19 @@
|
||||
*/
|
||||
/mob/living/carbon/proc/undergoing_cardiac_arrest()
|
||||
var/obj/item/organ/internal/heart/heart = get_organ_slot(ORGAN_SLOT_HEART)
|
||||
if(istype(heart) && heart.beating)
|
||||
if(istype(heart) && heart.is_beating())
|
||||
return FALSE
|
||||
else if(!needs_heart())
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* Causes the mob to either start or stop having a heart attack.
|
||||
*
|
||||
* status - Pass TRUE to start a heart attack, or FALSE to stop one.
|
||||
*
|
||||
* Returns TRUE if heart status was changed (heart attack -> no heart attack, or visa versa)
|
||||
*/
|
||||
/mob/living/carbon/proc/set_heartattack(status)
|
||||
if(!can_heartattack())
|
||||
return FALSE
|
||||
@@ -817,5 +824,7 @@
|
||||
if(!istype(heart))
|
||||
return FALSE
|
||||
|
||||
heart.beating = !status
|
||||
return TRUE
|
||||
if(status)
|
||||
return heart.Stop()
|
||||
|
||||
return heart.Restart()
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
/obj/item/organ/internal/appendix/golem
|
||||
name = "internal forge"
|
||||
desc = "This expanded digestive chamber allows golems to smelt minerals, provided that they are immersed in lava."
|
||||
icon_state = "ethereal_heart"
|
||||
icon_state = "ethereal_heart-off"
|
||||
color = COLOR_GOLEM_GRAY
|
||||
organ_flags = ORGAN_MINERAL
|
||||
/// Action which performs smelting
|
||||
|
||||
@@ -10,54 +10,84 @@
|
||||
healing_factor = STANDARD_ORGAN_HEALING
|
||||
decay_factor = 2.5 * STANDARD_ORGAN_DECAY //designed to fail around 6 minutes after death
|
||||
|
||||
low_threshold_passed = "<span class='info'>Prickles of pain appear then die out from within your chest...</span>"
|
||||
high_threshold_passed = "<span class='warning'>Something inside your chest hurts, and the pain isn't subsiding. You notice yourself breathing far faster than before.</span>"
|
||||
now_fixed = "<span class='info'>Your heart begins to beat again.</span>"
|
||||
high_threshold_cleared = "<span class='info'>The pain in your chest has died down, and your breathing becomes more relaxed.</span>"
|
||||
low_threshold_passed = span_info("Prickles of pain appear then die out from within your chest...")
|
||||
high_threshold_passed = span_warning("Something inside your chest hurts, and the pain isn't subsiding. You notice yourself breathing far faster than before.")
|
||||
now_fixed = span_info("Your heart begins to beat again.")
|
||||
high_threshold_cleared = span_info("The pain in your chest has died down, and your breathing becomes more relaxed.")
|
||||
|
||||
// Heart attack code is in code/modules/mob/living/carbon/human/life.dm
|
||||
var/beating = TRUE
|
||||
attack_verb_continuous = list("beats", "thumps")
|
||||
attack_verb_simple = list("beat", "thump")
|
||||
var/beat = BEAT_NONE//is this mob having a heatbeat sound played? if so, which?
|
||||
var/failed = FALSE //to prevent constantly running failing code
|
||||
var/operated = FALSE //whether the heart's been operated on to fix some of its damages
|
||||
|
||||
// Heart attack code is in code/modules/mob/living/carbon/human/life.dm
|
||||
|
||||
/// Whether the heart is currently beating.
|
||||
/// Do not set this directly. Use Restart() and Stop() instead.
|
||||
VAR_PRIVATE/beating = TRUE
|
||||
|
||||
/// is this mob having a heatbeat sound played? if so, which?
|
||||
var/beat = BEAT_NONE
|
||||
/// whether the heart's been operated on to fix some of its damages
|
||||
var/operated = FALSE
|
||||
|
||||
/obj/item/organ/internal/heart/update_icon_state()
|
||||
. = ..()
|
||||
icon_state = "[base_icon_state]-[beating ? "on" : "off"]"
|
||||
return ..()
|
||||
|
||||
/obj/item/organ/internal/heart/Remove(mob/living/carbon/heartless, special = 0)
|
||||
. = ..()
|
||||
if(!special)
|
||||
addtimer(CALLBACK(src, PROC_REF(stop_if_unowned)), 120)
|
||||
addtimer(CALLBACK(src, PROC_REF(stop_if_unowned)), 12 SECONDS)
|
||||
beat = BEAT_NONE
|
||||
owner?.stop_sound_channel(CHANNEL_HEARTBEAT)
|
||||
|
||||
/obj/item/organ/internal/heart/proc/stop_if_unowned()
|
||||
if(!owner)
|
||||
if(QDELETED(src))
|
||||
return
|
||||
if(IS_ROBOTIC_ORGAN(src))
|
||||
return
|
||||
if(isnull(owner))
|
||||
Stop()
|
||||
|
||||
/obj/item/organ/internal/heart/attack_self(mob/user)
|
||||
..()
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
if(!beating)
|
||||
user.visible_message("<span class='notice'>[user] squeezes [src] to \
|
||||
make it beat again!</span>",span_notice("You squeeze [src] to make it beat again!"))
|
||||
user.visible_message(
|
||||
span_notice("[user] squeezes [src] to make it beat again!"),
|
||||
span_notice("You squeeze [src] to make it beat again!"),
|
||||
)
|
||||
Restart()
|
||||
addtimer(CALLBACK(src, PROC_REF(stop_if_unowned)), 80)
|
||||
addtimer(CALLBACK(src, PROC_REF(stop_if_unowned)), 8 SECONDS)
|
||||
return TRUE
|
||||
|
||||
/obj/item/organ/internal/heart/proc/Stop()
|
||||
if(!beating)
|
||||
return FALSE
|
||||
|
||||
beating = FALSE
|
||||
update_appearance()
|
||||
beat = BEAT_NONE
|
||||
owner?.stop_sound_channel(CHANNEL_HEARTBEAT)
|
||||
return TRUE
|
||||
|
||||
/obj/item/organ/internal/heart/proc/Restart()
|
||||
if(beating)
|
||||
return FALSE
|
||||
|
||||
beating = TRUE
|
||||
update_appearance()
|
||||
return TRUE
|
||||
|
||||
/obj/item/organ/internal/heart/OnEatFrom(eater, feeder)
|
||||
. = ..()
|
||||
beating = FALSE
|
||||
update_appearance()
|
||||
Stop()
|
||||
|
||||
/// Checks if the heart is beating.
|
||||
/// Can be overridden to add more conditions for more complex hearts.
|
||||
/obj/item/organ/internal/heart/proc/is_beating()
|
||||
return beating
|
||||
|
||||
/obj/item/organ/internal/heart/on_life(seconds_per_tick, times_fired)
|
||||
..()
|
||||
@@ -66,34 +96,32 @@
|
||||
if(!owner.needs_heart())
|
||||
return
|
||||
|
||||
if(owner.client && beating)
|
||||
failed = FALSE
|
||||
var/sound/slowbeat = sound('sound/health/slowbeat.ogg', repeat = TRUE)
|
||||
var/sound/fastbeat = sound('sound/health/fastbeat.ogg', repeat = TRUE)
|
||||
// Handle "sudden" heart attack
|
||||
if(!beating || (organ_flags & ORGAN_FAILING))
|
||||
if(owner.can_heartattack() && Stop())
|
||||
if(owner.stat == CONSCIOUS)
|
||||
owner.visible_message(span_danger("[owner] clutches at [owner.p_their()] chest as if [owner.p_their()] heart is stopping!"))
|
||||
to_chat(owner, span_userdanger("You feel a terrible pain in your chest, as if your heart has stopped!"))
|
||||
return
|
||||
|
||||
if(owner.health <= owner.crit_threshold && beat != BEAT_SLOW)
|
||||
// Beyond deals with sound effects, so nothing needs to be done if no client
|
||||
if(isnull(owner.client))
|
||||
return
|
||||
|
||||
if(owner.stat == SOFT_CRIT)
|
||||
if(beat != BEAT_SLOW)
|
||||
beat = BEAT_SLOW
|
||||
owner.playsound_local(get_turf(owner), slowbeat, 40, 0, channel = CHANNEL_HEARTBEAT, use_reverb = FALSE)
|
||||
to_chat(owner, span_notice("You feel your heart slow down..."))
|
||||
if(beat == BEAT_SLOW && owner.health > owner.crit_threshold)
|
||||
owner.stop_sound_channel(CHANNEL_HEARTBEAT)
|
||||
beat = BEAT_NONE
|
||||
SEND_SOUND(owner, sound('sound/health/slowbeat.ogg', repeat = TRUE, channel = CHANNEL_HEARTBEAT, volume = 40))
|
||||
|
||||
if(owner.has_status_effect(/datum/status_effect/jitter))
|
||||
if(owner.health > HEALTH_THRESHOLD_FULLCRIT && (!beat || beat == BEAT_SLOW))
|
||||
owner.playsound_local(get_turf(owner), fastbeat, 40, 0, channel = CHANNEL_HEARTBEAT, use_reverb = FALSE)
|
||||
beat = BEAT_FAST
|
||||
else if(owner.stat == HARD_CRIT)
|
||||
if(beat != BEAT_FAST && owner.has_status_effect(/datum/status_effect/jitter))
|
||||
SEND_SOUND(owner, sound('sound/health/fastbeat.ogg', repeat = TRUE, channel = CHANNEL_HEARTBEAT, volume = 40))
|
||||
beat = BEAT_FAST
|
||||
|
||||
else if(beat == BEAT_FAST)
|
||||
owner.stop_sound_channel(CHANNEL_HEARTBEAT)
|
||||
beat = BEAT_NONE
|
||||
|
||||
if(organ_flags & ORGAN_FAILING && owner.can_heartattack() && !(HAS_TRAIT(src, TRAIT_STABLEHEART))) //heart broke, stopped beating, death imminent... unless you have veins that pump blood without a heart
|
||||
if(owner.stat == CONSCIOUS)
|
||||
owner.visible_message(span_danger("[owner] clutches at [owner.p_their()] chest as if [owner.p_their()] heart is stopping!"), \
|
||||
span_userdanger("You feel a terrible pain in your chest, as if your heart has stopped!"))
|
||||
owner.set_heartattack(TRUE)
|
||||
failed = TRUE
|
||||
else if(beat == BEAT_SLOW)
|
||||
owner.stop_sound_channel(CHANNEL_HEARTBEAT)
|
||||
beat = BEAT_NONE
|
||||
|
||||
/obj/item/organ/internal/heart/get_availability(datum/species/owner_species, mob/living/owner_mob)
|
||||
return owner_species.mutantheart
|
||||
@@ -222,4 +250,3 @@
|
||||
owner.heal_overall_damage(brute = 15, burn = 15, required_bodytype = BODYTYPE_ORGANIC)
|
||||
if(owner.reagents.get_reagent_amount(/datum/reagent/medicine/ephedrine) < 20)
|
||||
owner.reagents.add_reagent(/datum/reagent/medicine/ephedrine, 10)
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/obj/item/organ/internal/heart/ethereal
|
||||
name = "crystal core"
|
||||
icon_state = "ethereal_heart" //Welp. At least it's more unique in functionaliy.
|
||||
icon_state = "ethereal_heart-on"
|
||||
base_icon_state = "ethereal_heart"
|
||||
visual = TRUE //This is used by the ethereal species for color
|
||||
desc = "A crystal-like organ that functions similarly to a heart for Ethereals. It can revive its owner."
|
||||
|
||||
@@ -18,6 +19,7 @@
|
||||
/obj/item/organ/internal/heart/ethereal/Initialize(mapload)
|
||||
. = ..()
|
||||
add_atom_colour(ethereal_color, FIXED_COLOUR_PRIORITY)
|
||||
update_appearance()
|
||||
|
||||
/obj/item/organ/internal/heart/ethereal/Insert(mob/living/carbon/heart_owner, special = FALSE, drop_if_replaced = TRUE)
|
||||
. = ..()
|
||||
@@ -36,7 +38,7 @@
|
||||
|
||||
/obj/item/organ/internal/heart/ethereal/update_overlays()
|
||||
. = ..()
|
||||
var/mutable_appearance/shine = mutable_appearance(icon, icon_state = "[icon_state]_shine")
|
||||
var/mutable_appearance/shine = mutable_appearance(icon, icon_state = "[base_icon_state]_overlay-[beating ? "on" : "off"]")
|
||||
shine.appearance_flags = RESET_COLOR //No color on this, just pure white
|
||||
. += shine
|
||||
|
||||
@@ -193,13 +195,13 @@
|
||||
add_atom_colour(ethereal_heart.ethereal_color, FIXED_COLOUR_PRIORITY)
|
||||
crystal_heal_timer = addtimer(CALLBACK(src, PROC_REF(heal_ethereal)), CRYSTALIZE_HEAL_TIME, TIMER_STOPPABLE)
|
||||
set_light(4, 10, ethereal_heart.ethereal_color)
|
||||
update_icon()
|
||||
update_appearance(UPDATE_OVERLAYS)
|
||||
flick("ethereal_crystal_forming", src)
|
||||
addtimer(CALLBACK(src, PROC_REF(start_crystalization)), 1 SECONDS)
|
||||
|
||||
/obj/structure/ethereal_crystal/proc/start_crystalization()
|
||||
being_built = FALSE
|
||||
update_icon()
|
||||
update_appearance(UPDATE_OVERLAYS)
|
||||
|
||||
/obj/structure/ethereal_crystal/atom_destruction(damage_flag)
|
||||
playsound(get_turf(ethereal_heart.owner), 'sound/effects/ethereal_revive_fail.ogg', 100)
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 37 KiB |
Reference in New Issue
Block a user