-
Notifications
You must be signed in to change notification settings - Fork 33
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
14 changed files
with
390 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1 change: 0 additions & 1 deletion
1
...tation_modules/code/game/objects/structures/crate_lockers/closets/secure/quartermaster.dm
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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. |
76 changes: 76 additions & 0 deletions
76
maplestation_modules/code/modules/library/skill_learning/job_skillchips/medbay.dm
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
161 changes: 161 additions & 0 deletions
161
maplestation_modules/code/modules/mob/living/carbon/human/heart_rework/cpr.dm
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
|
||
/mob/living/carbon/human/do_cpr(mob/living/carbon/human/target) | ||
if(target == src) | ||
return FALSE | ||
|
||
if (DOING_INTERACTION_WITH_TARGET(src, target)) | ||
return FALSE | ||
|
||
cpr_process(target, beat = 1) // begin at beat 1, skip the first breath | ||
return TRUE | ||
|
||
/// 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 | ||
|
||
if (!target.appears_alive()) | ||
to_chat(src, span_warning("[target.name] is dead!")) | ||
return | ||
|
||
if(!panicking && target.stat != CONSCIOUS && beat >= BEATS_PER_CPR_CYCLE + 1) | ||
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 | ||
|
||
var/doing_a_breath = FALSE | ||
if(beat % BEATS_PER_CPR_CYCLE == 0) | ||
if (is_mouth_covered()) | ||
to_chat(src, span_warning("Your mouth is covered, so you can only perform compressions!")) | ||
|
||
else if (target.is_mouth_covered()) | ||
to_chat(src, span_warning("[p_their(TRUE)] mouth is covered, so you can only perform compressions!")) | ||
|
||
else if (!get_organ_slot(ORGAN_SLOT_LUNGS)) | ||
to_chat(src, span_warning("You have no lungs to breathe with, so you can only perform compressions!")) | ||
|
||
else if (HAS_TRAIT(src, TRAIT_NOBREATH)) | ||
to_chat(src, span_warning("You do not breathe, so you can only perform compressions!")) | ||
|
||
else | ||
doing_a_breath = TRUE | ||
|
||
if(doing_a_breath) | ||
visible_message( | ||
span_notice("[src] attempts to give [target.name] a rescue breath!"), | ||
span_notice("You attempt to give [target.name] a rescue breath as a part of CPR... Hold still!"), | ||
) | ||
|
||
if(!do_after(user = src, delay = doafter_mod * 6 SECONDS, target = target)) | ||
return | ||
|
||
add_mood_event("saved_life", /datum/mood_event/saved_life) | ||
visible_message( | ||
span_notice("[src] delivers a rescue breath on [target.name]!"), | ||
span_notice("You deliver a rescue breath on [target.name]."), | ||
) | ||
|
||
else | ||
var/is_first_compression = beat % BEATS_PER_CPR_CYCLE == 1 | ||
if(is_first_compression) | ||
visible_message( | ||
span_notice("[src] attempts to give [target.name] chest compressions!"), | ||
span_notice("You try to perform chest compressions as a part of CPR on [target.name]... Hold still!"), | ||
) | ||
|
||
if(!do_after(user = src, delay = doafter_mod * 1 SECONDS, target = target)) | ||
return | ||
|
||
if(is_first_compression) | ||
visible_message( | ||
span_notice("[src] delivers chest compressions on [target.name]!"), | ||
span_notice("You deliver chest compressions on [target.name]."), | ||
) | ||
|
||
target.apply_status_effect(/datum/status_effect/cpr_applied) | ||
|
||
if(doing_a_breath) | ||
if(HAS_TRAIT(target, TRAIT_NOBREATH)) | ||
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...")) | ||
|
||
// Breath relieves some of the pressure on the chest | ||
var/obj/item/bodypart/chest/chest = target.get_bodypart(BODY_ZONE_CHEST) | ||
if(IS_ORGANIC_LIMB(chest)) | ||
to_chat(target, span_notice("You feel the pressure on your chest ease!")) | ||
chest.heal_damage(brute = 3) | ||
target.cause_pain(BODY_ZONE_CHEST, -2) | ||
|
||
log_combat(src, target, "CPRed", addition = "(breath)") | ||
|
||
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)) | ||
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 pressure fade away from your chest... and then relief.")) | ||
target.cause_pain(BODY_ZONE_CHEST, 8) | ||
|
||
log_combat(src, target, "CPRed", addition = "(compression)") | ||
|
||
if(target.body_position != LYING_DOWN) | ||
return | ||
if(target.stat == CONSCIOUS) | ||
return | ||
|
||
cpr_process(target, beat + 1, panicking) | ||
|
||
#undef BEATS_PER_CPR_CYCLE | ||
|
||
/datum/status_effect/cpr_applied | ||
id = "cpr" | ||
alert_type = null | ||
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(!checking.get_organ_slot(ORGAN_SLOT_HEART)) // A heart is required for CPR to pump your heart | ||
return FALSE | ||
return TRUE |
Oops, something went wrong.