From 69fbf94d1f1600ebd52e871657253699b928e050 Mon Sep 17 00:00:00 2001 From: MrMelbert Date: Thu, 2 Nov 2023 13:09:34 -0500 Subject: [PATCH] Tweaks --- maplestation.dme | 1 + .../closets/secure/quartermaster.dm | 1 - .../skill_learning/job_skillchips/medbay.dm | 76 +++++++++++++++++++ .../skill_learning/job_skillchips/mining.dm | 8 +- .../living/carbon/human/heart_rework/cpr.dm | 67 +++++++++++----- .../carbon/human/heart_rework/heart_attack.dm | 28 +++++-- .../human/heart_rework/heart_overrides.dm | 13 ++-- 7 files changed, 160 insertions(+), 34 deletions(-) create mode 100644 maplestation_modules/code/modules/library/skill_learning/job_skillchips/medbay.dm diff --git a/maplestation.dme b/maplestation.dme index efc11f8fb1c5..6853d9071c13 100644 --- a/maplestation.dme +++ b/maplestation.dme @@ -5571,6 +5571,7 @@ #include "maplestation_modules\code\modules\language\japanese.dm" #include "maplestation_modules\code\modules\language\language_holder.dm" #include "maplestation_modules\code\modules\language\skrellian.dm" +#include "maplestation_modules\code\modules\library\skill_learning\job_skillchips\medbay.dm" #include "maplestation_modules\code\modules\library\skill_learning\job_skillchips\mining.dm" #include "maplestation_modules\code\modules\loadouts\loadout_items\_limb_datums.dm" #include "maplestation_modules\code\modules\loadouts\loadout_items\_loadout_categories.dm" diff --git a/maplestation_modules/code/game/objects/structures/crate_lockers/closets/secure/quartermaster.dm b/maplestation_modules/code/game/objects/structures/crate_lockers/closets/secure/quartermaster.dm index 704fc952c60a..a42c59887207 100644 --- a/maplestation_modules/code/game/objects/structures/crate_lockers/closets/secure/quartermaster.dm +++ b/maplestation_modules/code/game/objects/structures/crate_lockers/closets/secure/quartermaster.dm @@ -1,5 +1,4 @@ // -- Quartermaster locker stuff. -- /obj/structure/closet/secure_closet/quartermaster/PopulateContents() . = ..() - new /obj/item/storage/box/skillchips/cargo(src) new /obj/item/storage/bag/garment/magic/quartermaster(src) // done at the veeeery end for a reason. diff --git a/maplestation_modules/code/modules/library/skill_learning/job_skillchips/medbay.dm b/maplestation_modules/code/modules/library/skill_learning/job_skillchips/medbay.dm new file mode 100644 index 000000000000..561d5d3f83df --- /dev/null +++ b/maplestation_modules/code/modules/library/skill_learning/job_skillchips/medbay.dm @@ -0,0 +1,76 @@ +/obj/item/skillchip/entrails_reader + complexity = 0 // who cares? + +/// Teaches you how to perform CPR without harming the patient +/obj/item/skillchip/job/cpr + name = "CPR-Aid" + skill_name = "CPR Training" + skill_description = "Provides the user with the knowledge of how to safely perform CPR on a patient." + skill_icon = FA_ICON_HEARTBEAT + activate_message = span_notice("You feel more confident in your ability to perform CPR.") + deactivate_message = span_notice("You suddenly feel less confident in your ability to perform CPR.") + auto_traits = list(TRAIT_CPR_CERTIFIED) + complexity = 0 // it's pretty minor, all things considered + +/datum/outfit/job/doctor/New() + . = ..() + LAZYADD(skillchips, /obj/item/skillchip/job/cpr) + +/datum/outfit/job/paramedic/New() + . = ..() + LAZYADD(skillchips, /obj/item/skillchip/job/cpr) + +/datum/outfit/job/cmo/New() + . = ..() + LAZYADD(skillchips, /obj/item/skillchip/job/cpr) + +/obj/item/storage/box/skillchips/medbay + name = "box of medbay skillchips" + desc = "Contains spares of every medical job skillchip." + +/obj/item/storage/box/skillchips/medbay/PopulateContents() + new /obj/item/skillchip/job/cpr(src) + new /obj/item/skillchip/job/cpr(src) + new /obj/item/skillchip/job/cpr(src) + new /obj/item/skillchip/job/cpr(src) + new /obj/item/skillchip/entrails_reader(src) + +/obj/structure/closet/secure_closet/chief_medical/PopulateContents() + . = ..() + new /obj/item/storage/box/skillchips/medbay(src) + +/// Book that grants the same trait as a skillchip, since reasonably there's no need for it to be chip locked +/obj/item/book/granter/cpr + name = "CPR Training Manual" + desc = "A book that teaches you how to perform CPR properly and safely." + icon_state = "book7" + remarks = list( + "Assess the situation for danger... But it's always dangerous on the station!", + "Make sure to check for a pulse and call for help before starting...", + "Thirty compressions followed by two breaths...", + "Match compressions to the beat of 'Staying Alive'... What?", + "Proper hand placement is crucial. Wait, are lizardperson hearts in the same location as humans?", + "Tilt the head back and pinch the nose before delivering breaths.", + "Let the chest return to its normal position after each compression.", + "Follow up with an AED if available.", + ) + pages_to_mastery = 6 + reading_time = 2 SECONDS + uses = INFINITY + +/obj/item/book/granter/cpr/can_learn(mob/living/user) + return !HAS_TRAIT_FROM(user, TRAIT_CPR_CERTIFIED, name) + +/obj/item/book/granter/cpr/on_reading_start(mob/living/user) + . = ..() + if(HAS_TRAIT(user, TRAIT_CPR_CERTIFIED)) + to_chat(user, span_notice("You already know how to perform CPR, but it can't hurt to brush up.")) + +/obj/item/book/granter/cpr/on_reading_finished(mob/living/user) + . = ..() + if(HAS_TRAIT(user, TRAIT_CPR_CERTIFIED)) + to_chat(user, span_green("You remind yourself of the proper way to perform CPR safely.")) + else + to_chat(user, span_green("You feel confident in your ability to perform CPR safely.")) + + ADD_TRAIT(user, TRAIT_CPR_CERTIFIED, name) diff --git a/maplestation_modules/code/modules/library/skill_learning/job_skillchips/mining.dm b/maplestation_modules/code/modules/library/skill_learning/job_skillchips/mining.dm index 872d34fba159..9366382d5da4 100644 --- a/maplestation_modules/code/modules/library/skill_learning/job_skillchips/mining.dm +++ b/maplestation_modules/code/modules/library/skill_learning/job_skillchips/mining.dm @@ -5,8 +5,8 @@ skill_name = "Off Station Pain Resistance" skill_description = "For the adventurous in life, this skillchip provides a reduction in pain received when off the station." skill_icon = "fist-raised" - activate_message = "You feel like you can safely take on the unknown." - deactivate_message = "You feel more vulnerable to the unknown." + activate_message = span_notice("You feel like you can safely take on the unknown.") + deactivate_message = span_notice("You feel more vulnerable to the unknown.") /obj/item/skillchip/job/off_z_pain_resistance/on_activate(mob/living/carbon/user, silent = FALSE) . = ..() @@ -47,3 +47,7 @@ /obj/item/storage/box/skillchips/cargo/PopulateContents() new /obj/item/skillchip/job/off_z_pain_resistance(src) new /obj/item/skillchip/job/off_z_pain_resistance(src) + +/obj/structure/closet/secure_closet/quartermaster/PopulateContents() + . = ..() + new /obj/item/storage/box/skillchips/cargo(src) diff --git a/maplestation_modules/code/modules/mob/living/carbon/human/heart_rework/cpr.dm b/maplestation_modules/code/modules/mob/living/carbon/human/heart_rework/cpr.dm index fbcb948273b9..0824f94511ee 100644 --- a/maplestation_modules/code/modules/mob/living/carbon/human/heart_rework/cpr.dm +++ b/maplestation_modules/code/modules/mob/living/carbon/human/heart_rework/cpr.dm @@ -12,6 +12,8 @@ /// Number of "beats" per CPR cycle /// This corresponds to N - 1 compressions and 1 breath #define BEATS_PER_CPR_CYCLE 16 +// Also I'm kinda cheating here because we do 15 compressions to 1 breath rather than 30 compressions to 2 breaths +// But it's close enough to the real thing (ratio wise) that I'm OK with it /mob/living/carbon/human/proc/cpr_process(mob/living/carbon/human/target, beat = 0, panicking = FALSE) set waitfor = FALSE @@ -21,10 +23,7 @@ return if(!panicking && target.stat != CONSCIOUS && beat >= BEATS_PER_CPR_CYCLE + 1) - if(HAS_TRAIT(src, TRAIT_CPR_CERTIFIED)) - to_chat(src, span_notice("[target] still isn't up - you pick up the pace.")) - else - to_chat(src, span_warning("[target] still isn't up! You try harder!")) + to_chat(src, span_warning("[target] still isn't up[HAS_TRAIT(src, TRAIT_CPR_CERTIFIED) ? " - you pick up the pace." : "! You try harder!"]")) panicking = TRUE var/doafter_mod = panicking ? 0.5 : 1 @@ -85,9 +84,12 @@ to_chat(target, span_unconscious("You feel a breath of fresh air... which is a sensation you don't recognise...")) else if (!target.get_organ_slot(ORGAN_SLOT_LUNGS)) to_chat(target, span_unconscious("You feel a breath of fresh air... but you don't feel any better...")) + else if(HAS_TRAIT(src, TRAIT_CPR_CERTIFIED)) + target.adjustOxyLoss(-20) + to_chat(target, span_unconscious("You feel a breath of fresh air enter your lungs... It feels good...")) else target.adjustOxyLoss(-12) - to_chat(target, span_unconscious("You feel a breath of fresh air enter your lungs... It feels good...")) + to_chat(target, span_unconscious("You feel a breath of fresh air enter your lungs...")) // Breath relieves some of the pressure on the chest var/obj/item/bodypart/chest/chest = target.get_bodypart(BODY_ZONE_CHEST) @@ -96,26 +98,33 @@ chest.heal_damage(brute = 3) target.cause_pain(BODY_ZONE_CHEST, -2) - log_combat(src, target, "CPRed", addition = "breath") + log_combat(src, target, "CPRed", addition = "(breath)") - else if(beat % (BEATS_PER_CPR_CYCLE / 4) == 0 && panicking && !HAS_TRAIT(src, TRAIT_CPR_CERTIFIED)) - // Apply damage directly to chest. I would use apply damage but I can't, kinda + else if(beat % (BEATS_PER_CPR_CYCLE / 4) == 0 && panicking) var/obj/item/bodypart/chest/chest = target.get_bodypart(BODY_ZONE_CHEST) if(IS_ORGANIC_LIMB(chest)) - if(prob(1) && target.undergoing_cardiac_arrest()) + var/critical_success = prob(1) && target.undergoing_cardiac_arrest() + if(!HAS_TRAIT(src, TRAIT_CPR_CERTIFIED)) + // Apply damage directly to chest. I would use apply damage but I can't, kinda + if(critical_success) + target.set_heartattack(FALSE) + to_chat(target, span_warning("You feel immense pressure on your chest, and a sudden wave of pain... and then relief.")) + chest.receive_damage(brute = 6, wound_bonus = CANT_WOUND, damage_source = "chest compressions") + target.cause_pain(BODY_ZONE_CHEST, 12) + + else + to_chat(target, span_warning("You feel pressure on your chest!")) + chest.receive_damage(brute = 3, wound_bonus = CANT_WOUND, damage_source = "chest compressions") + target.cause_pain(BODY_ZONE_CHEST, 2) + + to_chat(src, span_warning("You bruise [target.name]'s chest with the pressure!")) + + else if(critical_success) target.set_heartattack(FALSE) - to_chat(target, span_warning("You feel immense pressure on your chest, and a sudden wave of pain... then relief.")) - chest.receive_damage(brute = 6, wound_bonus = CANT_WOUND, damage_source = "chest compressions") - target.cause_pain(BODY_ZONE_CHEST, 12) - - else - to_chat(target, span_warning("You feel pressure on your chest!")) - chest.receive_damage(brute = 3, wound_bonus = CANT_WOUND, damage_source = "chest compressions") - target.cause_pain(BODY_ZONE_CHEST, 2) + to_chat(target, span_warning("You pressure fade away from your chest... and then relief.")) + target.cause_pain(BODY_ZONE_CHEST, 8) - to_chat(src, span_warning("You bruise [target.name]'s chest with the pressure!")) - - log_combat(src, target, "CPRed", addition = "compression") + log_combat(src, target, "CPRed", addition = "(compression)") if(target.body_position != LYING_DOWN) return @@ -132,3 +141,21 @@ duration = 1 SECONDS tick_interval = -1 status_type = STATUS_EFFECT_REFRESH + +/datum/status_effect/cpr_applied/on_apply() + if(!is_effective(owner)) + return FALSE + return TRUE + +/datum/status_effect/cpr_applied/refresh(effect, ...) + if(!is_effective(owner)) + return + return ..() + +/// Checks if CPR is effective against this mob +/datum/status_effect/cpr_applied/proc/is_effective(mob/checking) + if(isnull(checking)) + return FALSE + if(!get_organ_slot(ORGAN_SLOT_HEART)) // A heart is required for CPR to pump your heart + return FALSE + return TRUE diff --git a/maplestation_modules/code/modules/mob/living/carbon/human/heart_rework/heart_attack.dm b/maplestation_modules/code/modules/mob/living/carbon/human/heart_rework/heart_attack.dm index fc0a4eea7ca5..d4eb1a9d04e1 100644 --- a/maplestation_modules/code/modules/mob/living/carbon/human/heart_rework/heart_attack.dm +++ b/maplestation_modules/code/modules/mob/living/carbon/human/heart_rework/heart_attack.dm @@ -13,6 +13,7 @@ return FALSE RegisterSignal(owner, COMSIG_SPECIES_GAIN, PROC_REF(species_changed)) + RegisterSignal(owner, COMSIG_CARBON_ATTEMPT_BREATHE, PROC_REF(block_breath)) // You get 1 tick of grace before you fall over due to your heart stopping ko_timer = addtimer(CALLBACK(src, PROC_REF(delayed_ko)), initial(tick_interval), TIMER_STOPPABLE) @@ -23,9 +24,13 @@ deltimer(ko_timer) UnregisterSignal(owner, COMSIG_SPECIES_GAIN) + UnregisterSignal(owner, COMSIG_CARBON_ATTEMPT_BREATHE) UnregisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_NOBREATH)) UnregisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_NOBREATH)) + if(!QDELING(owner)) + owner.cause_pain(BODY_ZONE_CHEST, -20) + /datum/status_effect/heart_attack/proc/delayed_ko() if(!HAS_TRAIT(owner, TRAIT_NOBREATH)) ADD_TRAIT(owner, TRAIT_KNOCKEDOUT, TRAIT_STATUS_EFFECT(id)) @@ -39,27 +44,38 @@ if(isnull(new_species.mutantheart)) qdel(src) -/datum/status_effect/heart_attack/proc/gained_nobreath() +/datum/status_effect/heart_attack/proc/gained_nobreath(datum/source) SIGNAL_HANDLER REMOVE_TRAIT(owner, TRAIT_KNOCKEDOUT, TRAIT_STATUS_EFFECT(id)) -/datum/status_effect/heart_attack/proc/lost_nobreath() +/datum/status_effect/heart_attack/proc/lost_nobreath(datum/source) SIGNAL_HANDLER if(!HAS_TRAIT(owner, TRAIT_NOBREATH)) ADD_TRAIT(owner, TRAIT_KNOCKEDOUT, TRAIT_STATUS_EFFECT(id)) +/datum/status_effect/heart_attack/proc/block_breath(datum/source) + SIGNAL_HANDLER + + if(HAS_TRAIT(owner, TRAIT_NOBREATH)) + return NONE + + if(prob(10)) + INVOKE_ASYNC(owner, TYPE_PROC_REF(/mob, emote), "gasp") + + return COMSIG_CARBON_BLOCK_BREATH + /datum/status_effect/heart_attack/tick(seconds_per_tick, times_fired) - seconds_per_tick = initial(tick_interval) // to remove when upstream merge + seconds_per_tick = (initial(tick_interval) / 10) // to remove when upstream merge if(ko_timer) // Not yet return - if(HAS_TRAIT(owner, TRAIT_STABLEHEART) || HAS_TRAIT(owner, TRAIT_NOBLOOD)) + if(owner.stat == DEAD || HAS_TRAIT(owner, TRAIT_STABLEHEART) || HAS_TRAIT(owner, TRAIT_NOBLOOD) || IS_IN_STASIS(owner)) return - if(owner.get_organ_slot(ORGAN_SLOT_HEART) && owner.has_status_effect(/datum/status_effect/cpr_applied)) // A heart is required for CPR to work + if(owner.has_status_effect(/datum/status_effect/cpr_applied)) return if(!HAS_TRAIT(owner, TRAIT_NOBREATH)) owner.adjustOxyLoss(4 * seconds_per_tick) - owner.losebreath = max(owner.losebreath, 1) + // Tissues die without blood circulation owner.adjustBruteLoss(1 * seconds_per_tick) diff --git a/maplestation_modules/code/modules/mob/living/carbon/human/heart_rework/heart_overrides.dm b/maplestation_modules/code/modules/mob/living/carbon/human/heart_rework/heart_overrides.dm index 72db431ec45d..05624ad034c0 100644 --- a/maplestation_modules/code/modules/mob/living/carbon/human/heart_rework/heart_overrides.dm +++ b/maplestation_modules/code/modules/mob/living/carbon/human/heart_rework/heart_overrides.dm @@ -1,8 +1,3 @@ -/mob/living/carbon/human/setup_organless_effects() - . = ..() - // You don't spawn with a heart, so, technically... You spawn with a heart attack - apply_status_effect(/datum/status_effect/heart_attack) - /obj/item/organ/internal/heart/Stop() if(!beating) return @@ -36,3 +31,11 @@ // Glands can't stop beating but they are cringe /obj/item/organ/internal/heart/gland/Stop() return FALSE + +/* +// I think this is un-necessary, so I'm commenting it out even if it's SUPPOSED to be a thing +/mob/living/carbon/human/setup_organless_effects() + . = ..() + // You don't spawn with a heart, so, technically... You spawn with a heart attack + apply_status_effect(/datum/status_effect/heart_attack) +*/