mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-10 17:52:36 +00:00
Makes wound treatment with medical stack items less jank (#88257)
This commit is contained in:
@@ -303,8 +303,8 @@ GLOBAL_LIST_INIT(biotypes_to_scar_file, list(
|
||||
// ~random wound balance defines
|
||||
/// how quickly sanitization removes infestation and decays per second
|
||||
#define WOUND_BURN_SANITIZATION_RATE 0.075
|
||||
/// how much blood you can lose per tick per slash max.
|
||||
#define WOUND_SLASH_MAX_BLOODFLOW 4.5
|
||||
/// how much blood you can lose per tick per wound max.
|
||||
#define WOUND_MAX_BLOODFLOW 4.5
|
||||
/// further slash attacks on a bodypart with a slash wound have their blood_flow further increased by damage * this (10 damage slash adds .25 flow)
|
||||
#define WOUND_SLASH_DAMAGE_FLOW_COEFF 0.025
|
||||
/// if we suffer a bone wound to the head that creates brain traumas, the timer for the trauma cycle is +/- by this percent (0-100)
|
||||
|
||||
@@ -159,7 +159,7 @@
|
||||
if(4 to INFINITY)
|
||||
bandage_condition = "clean"
|
||||
|
||||
condition += " underneath a dressing of [bandage_condition] [limb.current_gauze.name]"
|
||||
condition += " underneath a dressing of [bandage_condition] [limb.current_gauze.name]."
|
||||
else
|
||||
switch(infestation)
|
||||
if(WOUND_INFECTION_MODERATE to WOUND_INFECTION_SEVERE)
|
||||
@@ -223,25 +223,13 @@
|
||||
new burn common procs
|
||||
*/
|
||||
|
||||
/// if someone is using ointment or mesh on our burns
|
||||
/datum/wound/burn/flesh/proc/ointmentmesh(obj/item/stack/medical/I, mob/user)
|
||||
user.visible_message(span_notice("[user] begins applying [I] to [victim]'s [limb.plaintext_zone]..."), span_notice("You begin applying [I] to [user == victim ? "your" : "[victim]'s"] [limb.plaintext_zone]..."))
|
||||
if (I.amount <= 0)
|
||||
/// Checks if the wound is in a state that ointment or flesh will help
|
||||
/datum/wound/burn/flesh/proc/can_be_ointmented_or_meshed()
|
||||
if(infestation > 0 || sanitization < infestation)
|
||||
return TRUE
|
||||
if(!do_after(user, (user == victim ? I.self_delay : I.other_delay), target = victim, extra_checks = CALLBACK(src, PROC_REF(still_exists))))
|
||||
if(flesh_damage > 0 || flesh_healing <= flesh_damage)
|
||||
return TRUE
|
||||
|
||||
limb.heal_damage(I.heal_brute, I.heal_burn)
|
||||
user.visible_message(span_green("[user] applies [I] to [victim]."), span_green("You apply [I] to [user == victim ? "your" : "[victim]'s"] [limb.plaintext_zone]."))
|
||||
I.use(1)
|
||||
sanitization += I.sanitization
|
||||
flesh_healing += I.flesh_regeneration
|
||||
|
||||
if((infestation <= 0 || sanitization >= infestation) && (flesh_damage <= 0 || flesh_healing > flesh_damage))
|
||||
to_chat(user, span_notice("You've done all you can with [I], now you must wait for the flesh on [victim]'s [limb.plaintext_zone] to recover."))
|
||||
return TRUE
|
||||
else
|
||||
return try_treating(I, user)
|
||||
return FALSE
|
||||
|
||||
/// Paramedic UV penlights
|
||||
/datum/wound/burn/flesh/proc/uv(obj/item/flashlight/pen/paramedic/I, mob/user)
|
||||
@@ -258,15 +246,7 @@
|
||||
return TRUE
|
||||
|
||||
/datum/wound/burn/flesh/treat(obj/item/I, mob/user)
|
||||
if(istype(I, /obj/item/stack/medical/ointment))
|
||||
return ointmentmesh(I, user)
|
||||
else if(istype(I, /obj/item/stack/medical/mesh))
|
||||
var/obj/item/stack/medical/mesh/mesh_check = I
|
||||
if(!mesh_check.is_open)
|
||||
to_chat(user, span_warning("You need to open [mesh_check] first."))
|
||||
return
|
||||
return ointmentmesh(mesh_check, user)
|
||||
else if(istype(I, /obj/item/flashlight/pen/paramedic))
|
||||
if(istype(I, /obj/item/flashlight/pen/paramedic))
|
||||
return uv(I, user)
|
||||
|
||||
// people complained about burns not healing on stasis beds, so in addition to checking if it's cured, they also get the special ability to very slowly heal on stasis beds if they have the healing effects stored
|
||||
|
||||
@@ -80,11 +80,12 @@
|
||||
if (!victim || HAS_TRAIT(victim, TRAIT_STASIS))
|
||||
return
|
||||
|
||||
set_blood_flow(min(blood_flow, WOUND_SLASH_MAX_BLOODFLOW))
|
||||
|
||||
if(limb.can_bleed())
|
||||
if(victim.bodytemperature < (BODYTEMP_NORMAL - 10))
|
||||
adjust_blood_flow(-0.1 * seconds_per_tick)
|
||||
if(QDELETED(src))
|
||||
return
|
||||
if(SPT_PROB(2.5, seconds_per_tick))
|
||||
to_chat(victim, span_notice("You feel the [LOWER_TEXT(name)] in your [limb.plaintext_zone] firming up from the cold!"))
|
||||
|
||||
@@ -92,15 +93,16 @@
|
||||
adjust_blood_flow(0.25 * seconds_per_tick) // old heparin used to just add +2 bleed stacks per tick, this adds 0.5 bleed flow to all open cuts which is probably even stronger as long as you can cut them first
|
||||
|
||||
if(limb.current_gauze)
|
||||
adjust_blood_flow(-limb.current_gauze.absorption_rate * gauzed_clot_rate * seconds_per_tick)
|
||||
limb.current_gauze.absorption_capacity -= limb.current_gauze.absorption_rate * seconds_per_tick
|
||||
var/gauze_power = limb.current_gauze.absorption_rate
|
||||
limb.seep_gauze(gauze_power * seconds_per_tick)
|
||||
adjust_blood_flow(-gauze_power * gauzed_clot_rate * seconds_per_tick)
|
||||
|
||||
if(blood_flow <= 0)
|
||||
qdel(src)
|
||||
|
||||
/datum/wound/pierce/bleed/on_stasis(seconds_per_tick, times_fired)
|
||||
/datum/wound/pierce/bleed/adjust_blood_flow(adjust_by, minimum)
|
||||
. = ..()
|
||||
if(blood_flow <= 0)
|
||||
if(blood_flow > WOUND_MAX_BLOODFLOW)
|
||||
blood_flow = WOUND_MAX_BLOODFLOW
|
||||
if(blood_flow <= 0 && !QDELETED(src))
|
||||
to_chat(victim, span_green("The holes on your [limb.plaintext_zone] have [!limb.can_bleed() ? "healed up" : "stopped bleeding"]!"))
|
||||
qdel(src)
|
||||
|
||||
/datum/wound/pierce/bleed/check_grab_treatments(obj/item/I, mob/user)
|
||||
@@ -108,9 +110,7 @@
|
||||
return TRUE
|
||||
|
||||
/datum/wound/pierce/bleed/treat(obj/item/I, mob/user)
|
||||
if(istype(I, /obj/item/stack/medical/suture))
|
||||
return suture(I, user)
|
||||
else if(I.tool_behaviour == TOOL_CAUTERY || I.get_temperature())
|
||||
if(I.tool_behaviour == TOOL_CAUTERY || I.get_temperature())
|
||||
return tool_cauterize(I, user)
|
||||
|
||||
/datum/wound/pierce/bleed/on_xadone(power)
|
||||
@@ -123,32 +123,6 @@
|
||||
. = ..()
|
||||
adjust_blood_flow(-0.025 * reac_volume) // 20u * 0.05 = -1 blood flow, less than with slashes but still good considering smaller bleed rates
|
||||
|
||||
/// If someone is using a suture to close this puncture
|
||||
/datum/wound/pierce/bleed/proc/suture(obj/item/stack/medical/suture/I, mob/user)
|
||||
var/self_penalty_mult = (user == victim ? 1.4 : 1)
|
||||
var/treatment_delay = base_treat_time * self_penalty_mult
|
||||
|
||||
if(HAS_TRAIT(src, TRAIT_WOUND_SCANNED))
|
||||
treatment_delay *= 0.5
|
||||
user.visible_message(span_notice("[user] begins expertly stitching [victim]'s [limb.plaintext_zone] with [I]..."), span_notice("You begin stitching [user == victim ? "your" : "[victim]'s"] [limb.plaintext_zone] with [I], keeping the holo-image information in mind..."))
|
||||
else
|
||||
user.visible_message(span_notice("[user] begins stitching [victim]'s [limb.plaintext_zone] with [I]..."), span_notice("You begin stitching [user == victim ? "your" : "[victim]'s"] [limb.plaintext_zone] with [I]..."))
|
||||
|
||||
if(!do_after(user, treatment_delay, target = victim, extra_checks = CALLBACK(src, PROC_REF(still_exists))))
|
||||
return TRUE
|
||||
var/bleeding_wording = (!limb.can_bleed() ? "holes" : "bleeding")
|
||||
user.visible_message(span_green("[user] stitches up some of the [bleeding_wording] on [victim]."), span_green("You stitch up some of the [bleeding_wording] on [user == victim ? "yourself" : "[victim]"]."))
|
||||
var/blood_sutured = I.stop_bleeding / self_penalty_mult
|
||||
adjust_blood_flow(-blood_sutured)
|
||||
limb.heal_damage(I.heal_brute, I.heal_burn)
|
||||
I.use(1)
|
||||
|
||||
if(blood_flow > 0)
|
||||
return try_treating(I, user)
|
||||
else
|
||||
to_chat(user, span_green("You successfully close the hole in [user == victim ? "your" : "[victim]'s"] [limb.plaintext_zone]."))
|
||||
return TRUE
|
||||
|
||||
/// If someone is using either a cautery tool or something with heat to cauterize this pierce
|
||||
/datum/wound/pierce/bleed/proc/tool_cauterize(obj/item/I, mob/user)
|
||||
|
||||
@@ -163,9 +137,13 @@
|
||||
else
|
||||
user.visible_message(span_danger("[user] begins cauterizing [victim]'s [limb.plaintext_zone] with [I]..."), span_warning("You begin cauterizing [user == victim ? "your" : "[victim]'s"] [limb.plaintext_zone] with [I]..."))
|
||||
|
||||
playsound(user, 'sound/items/handling/surgery/cautery1.ogg', 75, TRUE)
|
||||
|
||||
if(!do_after(user, treatment_delay, target = victim, extra_checks = CALLBACK(src, PROC_REF(still_exists))))
|
||||
return TRUE
|
||||
|
||||
playsound(user, 'sound/items/handling/surgery/cautery2.ogg', 75, TRUE)
|
||||
|
||||
var/bleeding_wording = (!limb.can_bleed() ? "holes" : "bleeding")
|
||||
user.visible_message(span_green("[user] cauterizes some of the [bleeding_wording] on [victim]."), span_green("You cauterize some of the [bleeding_wording] on [victim]."))
|
||||
victim.apply_damage(2 + severity, BURN, limb, wound_bonus = CANT_WOUND)
|
||||
|
||||
@@ -36,9 +36,6 @@
|
||||
/// Once the blood flow drops below minimum_flow, we demote it to this type of wound. If there's none, we're all better
|
||||
var/demotes_to
|
||||
|
||||
/// The maximum flow we've had so far
|
||||
var/highest_flow
|
||||
|
||||
/// A bad system I'm using to track the worst scar we earned (since we can demote, we want the biggest our wound has been, not what it was when it was cured (probably moderate))
|
||||
var/datum/scar/highest_scar
|
||||
|
||||
@@ -133,44 +130,23 @@
|
||||
return BLOOD_FLOW_INCREASING
|
||||
|
||||
/datum/wound/slash/flesh/handle_process(seconds_per_tick, times_fired)
|
||||
|
||||
if (!victim || HAS_TRAIT(victim, TRAIT_STASIS))
|
||||
return
|
||||
|
||||
// in case the victim has the NOBLOOD trait, the wound will simply not clot on its own
|
||||
if(limb.can_bleed())
|
||||
set_blood_flow(min(blood_flow, WOUND_SLASH_MAX_BLOODFLOW))
|
||||
if(clot_rate > 0)
|
||||
adjust_blood_flow(-clot_rate * seconds_per_tick)
|
||||
if(QDELETED(src))
|
||||
return
|
||||
|
||||
if(HAS_TRAIT(victim, TRAIT_BLOODY_MESS))
|
||||
adjust_blood_flow(0.25) // old heparin used to just add +2 bleed stacks per tick, this adds 0.5 bleed flow to all open cuts which is probably even stronger as long as you can cut them first
|
||||
|
||||
//gauze always reduces blood flow, even for non bleeders
|
||||
if(limb.current_gauze)
|
||||
if(clot_rate > 0)
|
||||
adjust_blood_flow(-clot_rate * seconds_per_tick)
|
||||
adjust_blood_flow(-limb.current_gauze.absorption_rate * seconds_per_tick)
|
||||
limb.seep_gauze(limb.current_gauze.absorption_rate * seconds_per_tick)
|
||||
//otherwise, only clot if it's a bleeder
|
||||
else if(limb.can_bleed())
|
||||
adjust_blood_flow(-clot_rate * seconds_per_tick)
|
||||
|
||||
if(blood_flow > highest_flow)
|
||||
highest_flow = blood_flow
|
||||
|
||||
if(blood_flow < minimum_flow)
|
||||
if(demotes_to)
|
||||
replace_wound(new demotes_to)
|
||||
else
|
||||
to_chat(victim, span_green("The cut on your [limb.plaintext_zone] has [!limb.can_bleed() ? "healed up" : "stopped bleeding"]!"))
|
||||
qdel(src)
|
||||
|
||||
/datum/wound/slash/flesh/on_stasis(seconds_per_tick, times_fired)
|
||||
if(blood_flow >= minimum_flow)
|
||||
return
|
||||
if(demotes_to)
|
||||
replace_wound(new demotes_to)
|
||||
return
|
||||
qdel(src)
|
||||
var/gauze_power = limb.current_gauze.absorption_rate
|
||||
limb.seep_gauze(gauze_power * seconds_per_tick)
|
||||
adjust_blood_flow(-gauze_power * seconds_per_tick)
|
||||
|
||||
/* BEWARE, THE BELOW NONSENSE IS MADNESS. bones.dm looks more like what I have in mind and is sufficiently clean, don't pay attention to this messiness */
|
||||
|
||||
@@ -185,8 +161,6 @@
|
||||
return las_cauterize(I, user)
|
||||
else if(I.tool_behaviour == TOOL_CAUTERY || I.get_temperature())
|
||||
return tool_cauterize(I, user)
|
||||
else if(istype(I, /obj/item/stack/medical/suture))
|
||||
return suture(I, user)
|
||||
|
||||
/datum/wound/slash/flesh/try_handling(mob/living/user)
|
||||
if(user.pulling != victim || !HAS_TRAIT(user, TRAIT_WOUND_LICKER) || !victim.try_inject(user, injection_flags = INJECT_TRY_SHOW_ERROR_MESSAGE))
|
||||
@@ -212,8 +186,7 @@
|
||||
/// if a felinid is licking this cut to reduce bleeding
|
||||
/datum/wound/slash/flesh/proc/lick_wounds(mob/living/carbon/human/user)
|
||||
// transmission is one way patient -> felinid since google said cat saliva is antiseptic or whatever, and also because felinids are already risking getting beaten for this even without people suspecting they're spreading a deathvirus
|
||||
for(var/i in victim.diseases)
|
||||
var/datum/disease/iter_disease = i
|
||||
for(var/datum/disease/iter_disease as anything in victim.diseases)
|
||||
if(iter_disease.spread_flags & (DISEASE_SPREAD_SPECIAL | DISEASE_SPREAD_NON_CONTAGIOUS))
|
||||
continue
|
||||
user.ForceContractDisease(iter_disease)
|
||||
@@ -225,18 +198,28 @@
|
||||
|
||||
user.visible_message(span_notice("[user] licks the wounds on [victim]'s [limb.plaintext_zone]."), span_notice("You lick some of the wounds on [victim]'s [limb.plaintext_zone]"), ignored_mobs=victim)
|
||||
to_chat(victim, span_green("[user] licks the wounds on your [limb.plaintext_zone]!"))
|
||||
var/mob/victim_stored = victim
|
||||
adjust_blood_flow(-0.5)
|
||||
|
||||
if(blood_flow > minimum_flow)
|
||||
try_handling(user)
|
||||
else if(demotes_to)
|
||||
to_chat(user, span_green("You successfully lower the severity of [victim]'s cuts."))
|
||||
to_chat(user, span_green("You successfully lower the severity of [user == victim_stored ? "your" : "[victim_stored]'s"] cuts."))
|
||||
|
||||
/datum/wound/slash/flesh/adjust_blood_flow(adjust_by, minimum)
|
||||
. = ..()
|
||||
if(blood_flow > WOUND_MAX_BLOODFLOW)
|
||||
blood_flow = WOUND_MAX_BLOODFLOW
|
||||
if(blood_flow < minimum_flow && !QDELETED(src))
|
||||
if(demotes_to)
|
||||
replace_wound(new demotes_to)
|
||||
else
|
||||
to_chat(victim, span_green("The cut on your [limb.plaintext_zone] has [!limb.can_bleed() ? "healed up" : "stopped bleeding"]!"))
|
||||
qdel(src)
|
||||
|
||||
/datum/wound/slash/flesh/on_xadone(power)
|
||||
. = ..()
|
||||
|
||||
if (limb) // parent can cause us to be removed, so its reasonable to check if we're still applied
|
||||
adjust_blood_flow(-0.03 * power) // i think it's like a minimum of 3 power, so .09 blood_flow reduction per tick is pretty good for 0 effort
|
||||
adjust_blood_flow(-0.03 * power) // i think it's like a minimum of 3 power, so .09 blood_flow reduction per tick is pretty good for 0 effort
|
||||
|
||||
/datum/wound/slash/flesh/on_synthflesh(reac_volume)
|
||||
. = ..()
|
||||
@@ -271,50 +254,29 @@
|
||||
else
|
||||
user.visible_message(span_danger("[user] begins cauterizing [victim]'s [limb.plaintext_zone] with [I]..."), span_warning("You begin cauterizing [user == victim ? "your" : "[victim]'s"] [limb.plaintext_zone] with [I]..."))
|
||||
|
||||
playsound(user, 'sound/items/handling/surgery/cautery1.ogg', 75, TRUE)
|
||||
|
||||
if(!do_after(user, treatment_delay, target = victim, extra_checks = CALLBACK(src, PROC_REF(still_exists))))
|
||||
return
|
||||
|
||||
playsound(user, 'sound/items/handling/surgery/cautery2.ogg', 75, TRUE)
|
||||
|
||||
var/bleeding_wording = (!limb.can_bleed() ? "cuts" : "bleeding")
|
||||
user.visible_message(span_green("[user] cauterizes some of the [bleeding_wording] on [victim]."), span_green("You cauterize some of the [bleeding_wording] on [victim]."))
|
||||
victim.apply_damage(2 + severity, BURN, limb, wound_bonus = CANT_WOUND)
|
||||
if(prob(30))
|
||||
victim.emote("scream")
|
||||
var/blood_cauterized = (0.6 / (self_penalty_mult * improv_penalty_mult))
|
||||
var/mob/victim_stored = victim
|
||||
adjust_blood_flow(-blood_cauterized)
|
||||
|
||||
if(blood_flow > minimum_flow)
|
||||
return try_treating(I, user)
|
||||
else if(demotes_to)
|
||||
to_chat(user, span_green("You successfully lower the severity of [user == victim ? "your" : "[victim]'s"] cuts."))
|
||||
to_chat(user, span_green("You successfully lower the severity of [user == victim_stored ? "your" : "[victim_stored]'s"] cuts."))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/// If someone is using a suture to close this cut
|
||||
/datum/wound/slash/flesh/proc/suture(obj/item/stack/medical/suture/I, mob/user)
|
||||
var/self_penalty_mult = (user == victim ? 1.4 : 1)
|
||||
var/treatment_delay = base_treat_time * self_penalty_mult
|
||||
|
||||
if(HAS_TRAIT(src, TRAIT_WOUND_SCANNED))
|
||||
treatment_delay *= 0.5
|
||||
user.visible_message(span_notice("[user] begins expertly stitching [victim]'s [limb.plaintext_zone] with [I]..."), span_notice("You begin stitching [user == victim ? "your" : "[victim]'s"] [limb.plaintext_zone] with [I], keeping the holo-image information in mind..."))
|
||||
else
|
||||
user.visible_message(span_notice("[user] begins stitching [victim]'s [limb.plaintext_zone] with [I]..."), span_notice("You begin stitching [user == victim ? "your" : "[victim]'s"] [limb.plaintext_zone] with [I]..."))
|
||||
|
||||
if(!do_after(user, treatment_delay, target = victim, extra_checks = CALLBACK(src, PROC_REF(still_exists))))
|
||||
return TRUE
|
||||
var/bleeding_wording = (!limb.can_bleed() ? "cuts" : "bleeding")
|
||||
user.visible_message(span_green("[user] stitches up some of the [bleeding_wording] on [victim]."), span_green("You stitch up some of the [bleeding_wording] on [user == victim ? "yourself" : "[victim]"]."))
|
||||
var/blood_sutured = I.stop_bleeding / self_penalty_mult
|
||||
adjust_blood_flow(-blood_sutured)
|
||||
limb.heal_damage(I.heal_brute, I.heal_burn)
|
||||
I.use(1)
|
||||
|
||||
if(blood_flow > minimum_flow)
|
||||
return try_treating(I, user)
|
||||
else if(demotes_to)
|
||||
to_chat(user, span_green("You successfully lower the severity of [user == victim ? "your" : "[victim]'s"] cuts."))
|
||||
return TRUE
|
||||
return TRUE
|
||||
|
||||
/datum/wound/slash/get_limb_examine_description()
|
||||
return span_warning("The flesh on this limb appears badly lacerated.")
|
||||
|
||||
|
||||
@@ -32,16 +32,35 @@
|
||||
var/sanitization
|
||||
/// How much we add to flesh_healing for burn wounds on application
|
||||
var/flesh_regeneration
|
||||
/// Time it takes to assess injuries when looping healing
|
||||
var/assessing_injury_delay = 1 SECONDS
|
||||
|
||||
/obj/item/stack/medical/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(!isliving(interacting_with))
|
||||
return NONE
|
||||
if(!begin_heal_loop(interacting_with, user))
|
||||
if(!begin_heal_loop(interacting_with, user, auto_change_zone = TRUE))
|
||||
return NONE // [ITEM_INTERACT_BLOCKING] would be redundant as we are nobludgeon
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/item/stack/medical/interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(!isliving(interacting_with))
|
||||
return NONE
|
||||
if(!begin_heal_loop(interacting_with, user, auto_change_zone = FALSE))
|
||||
return NONE // see above
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/item/stack/medical/Initialize(mapload, new_amount, merge, list/mat_override, mat_amt)
|
||||
. = ..()
|
||||
register_item_context()
|
||||
|
||||
/obj/item/stack/medical/add_item_context(obj/item/source, list/context, atom/target, mob/living/user)
|
||||
if(!isliving(target))
|
||||
return NONE
|
||||
if(iscarbon(target))
|
||||
context[SCREENTIP_CONTEXT_LMB] = "Auto Heal"
|
||||
context[SCREENTIP_CONTEXT_RMB] = "Manual Heal"
|
||||
else
|
||||
context[SCREENTIP_CONTEXT_LMB] = "Heal"
|
||||
return CONTEXTUAL_SCREENTIP_SET
|
||||
|
||||
/obj/item/stack/medical/apply_fantasy_bonuses(bonus)
|
||||
. = ..()
|
||||
if(heal_brute)
|
||||
@@ -65,134 +84,251 @@
|
||||
|
||||
/// Used to begin the recursive healing loop.
|
||||
/// Returns TRUE if we entered the loop, FALSE if we didn't
|
||||
/obj/item/stack/medical/proc/begin_heal_loop(mob/living/patient, mob/user)
|
||||
if(!can_heal(patient, user))
|
||||
/obj/item/stack/medical/proc/begin_heal_loop(mob/living/patient, mob/living/user, auto_change_zone = TRUE)
|
||||
if(DOING_INTERACTION_WITH_TARGET(user, patient))
|
||||
return FALSE
|
||||
|
||||
INVOKE_ASYNC(src, PROC_REF(try_heal), patient, user)
|
||||
var/heal_zone = check_zone(user.zone_selected)
|
||||
if(!try_heal_checks(patient, user, heal_zone))
|
||||
return FALSE
|
||||
SSblackbox.record_feedback("nested tally", "medical_item_used", 1, list(type, auto_change_zone ? "auto" : "manual"))
|
||||
patient.balloon_alert(user, "treating [parse_zone(heal_zone)]...")
|
||||
INVOKE_ASYNC(src, PROC_REF(try_heal), patient, user, heal_zone, FALSE, iscarbon(patient) && auto_change_zone) // auto change is useless for non-carbons
|
||||
return TRUE
|
||||
|
||||
/// Checks if the passed patient can be healed by the passed user
|
||||
/obj/item/stack/medical/proc/can_heal(mob/living/patient, mob/user)
|
||||
return patient.try_inject(user, injection_flags = INJECT_TRY_SHOW_ERROR_MESSAGE)
|
||||
|
||||
/// In which we print the message that we're starting to heal someone, then we try healing them. Does the do_after whether or not it can actually succeed on a targeted mob
|
||||
/obj/item/stack/medical/proc/try_heal(mob/living/patient, mob/user, silent = FALSE, looping = FALSE)
|
||||
if(!try_heal_checks(patient, user, heal_brute, heal_burn, looping))
|
||||
return
|
||||
var/new_self_delay = self_delay
|
||||
var/new_other_delay = other_delay
|
||||
if(iscarbon(patient))
|
||||
new_self_delay = looping ? clamp((self_delay - assessing_injury_delay), 0, self_delay) : self_delay
|
||||
new_other_delay = looping ? clamp((other_delay - assessing_injury_delay), 0, other_delay) : other_delay
|
||||
/**
|
||||
* What actually handles printing the message that we're starting to heal someone, and trying to heal them
|
||||
*
|
||||
* This proc is recursively called until we run out of charges OR until the patient is fully healed
|
||||
* OR until the target zone is fully healed (if auto_change_zone is FALSE)
|
||||
*
|
||||
* * patient - The mob we're trying to heal
|
||||
* * user - The mob that's trying to heal the patient
|
||||
* * healed_zone - The zone we're trying to heal on the patient
|
||||
* Disregarded if auto_change_zone is TRUE
|
||||
* * silent - If we should not print the message that we're starting to heal the patient
|
||||
* Used so looping the proc doesn't spam messages
|
||||
* * auto_change_zone - Handles the behavior when we finish healing a zone
|
||||
* If auto_change_zone is set to TRUE, it picks the next most damaged zone to heal
|
||||
* If auto_change_zone is set to FALSE, it'll give the user a chance to pick a new zone to heal
|
||||
*/
|
||||
/obj/item/stack/medical/proc/try_heal(mob/living/patient, mob/living/user, healed_zone, silent = FALSE, auto_change_zone = TRUE)
|
||||
if(patient == user)
|
||||
if(!silent)
|
||||
user.balloon_alert(user, "treating [parse_zone(healed_zone)]...")
|
||||
user.visible_message(
|
||||
span_notice("[user] starts to apply [src] on [user.p_them()]self..."),
|
||||
span_notice("You begin applying [src] on yourself..."),
|
||||
visible_message_flags = ALWAYS_SHOW_SELF_MESSAGE,
|
||||
)
|
||||
if(!do_after(
|
||||
user,
|
||||
new_self_delay,
|
||||
self_delay * (auto_change_zone ? 1 : 0.9),
|
||||
patient,
|
||||
extra_checks = CALLBACK(src, PROC_REF(can_heal), patient, user),
|
||||
extra_checks = CALLBACK(src, PROC_REF(can_heal), patient, user, healed_zone),
|
||||
))
|
||||
return
|
||||
if(!auto_change_zone)
|
||||
healed_zone = check_zone(user.zone_selected)
|
||||
if(!try_heal_checks(patient, user, healed_zone))
|
||||
return
|
||||
|
||||
else if(other_delay)
|
||||
if(!silent)
|
||||
patient.balloon_alert(user, "treating [parse_zone(healed_zone)]...")
|
||||
user.visible_message(
|
||||
span_notice("[user] starts to apply [src] on [patient]."),
|
||||
span_notice("You begin applying [src] on [patient]..."),
|
||||
visible_message_flags = ALWAYS_SHOW_SELF_MESSAGE,
|
||||
)
|
||||
if(!do_after(
|
||||
user,
|
||||
new_other_delay,
|
||||
other_delay * (auto_change_zone ? 1 : 0.9),
|
||||
patient,
|
||||
extra_checks = CALLBACK(src, PROC_REF(can_heal), patient, user),
|
||||
extra_checks = CALLBACK(src, PROC_REF(can_heal), patient, user, healed_zone),
|
||||
))
|
||||
return
|
||||
if(!auto_change_zone)
|
||||
healed_zone = check_zone(user.zone_selected)
|
||||
if(!try_heal_checks(patient, user, healed_zone))
|
||||
return
|
||||
|
||||
if(!heal(patient, user))
|
||||
return
|
||||
log_combat(user, patient, "healed", name)
|
||||
if(!use(1) || !repeating || amount <= 0)
|
||||
return
|
||||
if(!can_heal(patient, user))
|
||||
return
|
||||
try_heal(patient, user, silent = TRUE, looping = TRUE)
|
||||
else
|
||||
if(!silent)
|
||||
user.visible_message(
|
||||
span_notice("[user] applies [src] on [patient]."),
|
||||
span_notice("You apply [src] on [patient]."),
|
||||
visible_message_flags = ALWAYS_SHOW_SELF_MESSAGE,
|
||||
)
|
||||
|
||||
/// Apply the actual effects of the healing if it's a simple animal, goes to [/obj/item/stack/medical/proc/heal_carbon] if it's a carbon, returns TRUE if it works, FALSE if it doesn't
|
||||
/obj/item/stack/medical/proc/heal(mob/living/patient, mob/user)
|
||||
if(patient.stat == DEAD)
|
||||
patient.balloon_alert(user, "they're dead!")
|
||||
return FALSE
|
||||
if(iscarbon(patient))
|
||||
return heal_carbon(patient, user, heal_brute, heal_burn)
|
||||
if(!heal_carbon(patient, user, healed_zone))
|
||||
return
|
||||
else if(isanimal_or_basicmob(patient))
|
||||
if(!try_heal_checks(patient, user, heal_brute, heal_burn))
|
||||
return FALSE
|
||||
if(patient.heal_bodypart_damage((heal_brute * patient.maxHealth/100)))
|
||||
user.visible_message(span_infoplain(span_green("[user] applies [src] on [patient].")), span_infoplain(span_green("You apply [src] on [patient].")))
|
||||
return TRUE
|
||||
patient.balloon_alert(user, "can't heal [patient]!")
|
||||
return FALSE
|
||||
if(!heal_simplemob(patient, user))
|
||||
return
|
||||
else
|
||||
CRASH("Stack medical item healing a non-carbon, non-animal mob [patient] ([patient.type])")
|
||||
|
||||
log_combat(user, patient, "healed", src)
|
||||
if(!use(1) || !repeating || amount <= 0)
|
||||
var/atom/alert_loc = QDELETED(src) ? user : src
|
||||
alert_loc.balloon_alert(user, repeating ? "all used up!" : "treated [parse_zone(healed_zone)]")
|
||||
return
|
||||
|
||||
// first, just try looping
|
||||
// 1. we can keep healing the current target
|
||||
// 2. the user's changed their target (and thus we should heal that limb instead)
|
||||
var/preferred_target = check_zone(user.zone_selected)
|
||||
if(try_heal_checks(patient, user, preferred_target, silent = TRUE))
|
||||
if(preferred_target != healed_zone)
|
||||
patient.balloon_alert(user, "treating [parse_zone(preferred_target)]...")
|
||||
try_heal(patient, user, preferred_target, TRUE, auto_change_zone)
|
||||
return
|
||||
|
||||
// second, handle what happens otherwise
|
||||
if(!iscarbon(patient))
|
||||
// behavior 0: non-carbons have no limbs so we can assume they are fully healed
|
||||
patient.balloon_alert(user, "fully treated")
|
||||
else if(auto_change_zone)
|
||||
// behavior 1: automatically pick another zone to heal
|
||||
try_heal_auto_change_zone(patient, user, preferred_target, healed_zone)
|
||||
else
|
||||
// behavior 2: assess injury, giving the user time to manually pick another zone
|
||||
try_heal_manual_target(patient, user)
|
||||
|
||||
/obj/item/stack/medical/proc/try_heal_auto_change_zone(mob/living/carbon/patient, mob/living/user, preferred_target, last_zone)
|
||||
PRIVATE_PROC(TRUE)
|
||||
|
||||
var/list/other_affected_limbs = list()
|
||||
for(var/obj/item/bodypart/limb as anything in patient.bodyparts)
|
||||
if(!try_heal_checks(patient, user, limb.body_zone, silent = TRUE))
|
||||
continue
|
||||
other_affected_limbs += limb.body_zone
|
||||
|
||||
if(!length(other_affected_limbs))
|
||||
patient.balloon_alert(user, "fully treated")
|
||||
return
|
||||
|
||||
var/next_picked = (preferred_target in other_affected_limbs) ? preferred_target : other_affected_limbs[1]
|
||||
if(next_picked != last_zone)
|
||||
user.balloon_alert(user, "treating [parse_zone(next_picked)]...")
|
||||
try_heal(patient, user, next_picked, silent = TRUE, auto_change_zone = TRUE)
|
||||
|
||||
/obj/item/stack/medical/proc/try_heal_manual_target(mob/living/carbon/patient, mob/living/user)
|
||||
PRIVATE_PROC(TRUE)
|
||||
|
||||
patient.balloon_alert(user, "assessing injury...")
|
||||
if(!do_after(user, 1 SECONDS, patient))
|
||||
return
|
||||
var/new_zone = check_zone(user.zone_selected)
|
||||
if(!try_heal_checks(patient, user, new_zone))
|
||||
return
|
||||
patient.balloon_alert(user, "treating [parse_zone(new_zone)]...")
|
||||
try_heal(patient, user, new_zone, silent = TRUE, auto_change_zone = FALSE)
|
||||
|
||||
/// Checks if the passed patient can be healed by the passed user
|
||||
/obj/item/stack/medical/proc/can_heal(mob/living/patient, mob/living/user, healed_zone, silent = FALSE)
|
||||
return patient.try_inject(user, healed_zone, injection_flags = silent ? NONE : INJECT_TRY_SHOW_ERROR_MESSAGE)
|
||||
|
||||
/// Checks a bunch of stuff to see if we can heal the patient, including can_heal
|
||||
/// Gives a feedback if we can't ultimatly heal the patient (unless silent is TRUE)
|
||||
/obj/item/stack/medical/proc/try_heal_checks(mob/living/patient, mob/living/user, healed_zone, silent = FALSE)
|
||||
if(!can_heal(patient, user, healed_zone, silent))
|
||||
// has its own feedback
|
||||
return FALSE
|
||||
if(patient.stat == DEAD)
|
||||
if(!silent)
|
||||
patient.balloon_alert(user, "[patient.p_theyre()] dead!")
|
||||
return FALSE
|
||||
|
||||
/obj/item/stack/medical/proc/try_heal_checks(mob/living/patient, mob/user, brute, burn, looping = FALSE)
|
||||
if(iscarbon(patient))
|
||||
if(looping)
|
||||
balloon_alert(user, "assessing injuries...")
|
||||
if(!do_after(user, assessing_injury_delay, patient))
|
||||
return FALSE
|
||||
var/mob/living/carbon/carbon_patient = patient
|
||||
var/obj/item/bodypart/affecting = carbon_patient.get_bodypart(check_zone(user.zone_selected))
|
||||
var/obj/item/bodypart/affecting = carbon_patient.get_bodypart(healed_zone)
|
||||
if(!affecting) //Missing limb?
|
||||
carbon_patient.balloon_alert(user, "no [parse_zone(user.zone_selected)]!")
|
||||
if(!silent)
|
||||
carbon_patient.balloon_alert(user, "no [parse_zone(healed_zone)]!")
|
||||
return FALSE
|
||||
if(!IS_ORGANIC_LIMB(affecting)) //Limb must be organic to be healed - RR
|
||||
carbon_patient.balloon_alert(user, "[affecting.plaintext_zone] is not organic!")
|
||||
if(!silent)
|
||||
carbon_patient.balloon_alert(user, "[affecting.plaintext_zone] is not organic!")
|
||||
return FALSE
|
||||
if(!(affecting.brute_dam && brute) && !(affecting.burn_dam && burn))
|
||||
if(!affecting.brute_dam && !affecting.burn_dam)
|
||||
if(patient != user || !looping)
|
||||
|
||||
var/datum/wound/burn/flesh/any_burn_wound = locate() in affecting.wounds
|
||||
var/can_heal_burn_wounds = (flesh_regeneration || sanitization) && any_burn_wound?.can_be_ointmented_or_meshed()
|
||||
var/can_suture_bleeding = stop_bleeding && affecting.get_modified_bleed_rate() > 0
|
||||
var/brute_to_heal = heal_brute && affecting.brute_dam > 0
|
||||
var/burn_to_heal = heal_burn && affecting.burn_dam > 0
|
||||
|
||||
if(!brute_to_heal && !burn_to_heal && !can_heal_burn_wounds && !can_suture_bleeding)
|
||||
if(!silent)
|
||||
if(!brute_to_heal && stop_bleeding) // no brute, no bleeding
|
||||
carbon_patient.balloon_alert(user, "[affecting.plaintext_zone] is not bleeding or bruised!")
|
||||
else if(!burn_to_heal && (flesh_regeneration || sanitization) && any_burn_wound) // no burns, existing burn wounds are treated
|
||||
carbon_patient.balloon_alert(user, "[affecting.plaintext_zone] has been fully treated!")
|
||||
else if(!affecting.brute_dam && !affecting.burn_dam) // not hurt at all
|
||||
carbon_patient.balloon_alert(user, "[affecting.plaintext_zone] is not hurt!")
|
||||
else
|
||||
carbon_patient.balloon_alert(user, "can't heal [affecting.plaintext_zone] with [name]!")
|
||||
else // probably hurt in some way but we are not the right item for this
|
||||
carbon_patient.balloon_alert(user, "can't heal [affecting.plaintext_zone] with [name]!")
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
if(isanimal_or_basicmob(patient))
|
||||
if(patient.stat == DEAD)
|
||||
patient.balloon_alert(user, "they're dead!")
|
||||
return FALSE
|
||||
if(!heal_brute) // only brute can heal
|
||||
patient.balloon_alert(user, "can't heal with [name]!")
|
||||
if(!silent)
|
||||
patient.balloon_alert(user, "can't heal with [name]!")
|
||||
return FALSE
|
||||
if(!(patient.mob_biotypes & MOB_ORGANIC))
|
||||
patient.balloon_alert(user, "no organic tissue!")
|
||||
if(!silent)
|
||||
patient.balloon_alert(user, "no organic tissue!")
|
||||
return FALSE
|
||||
if(patient.health == patient.maxHealth)
|
||||
patient.balloon_alert(user, "not hurt!")
|
||||
if(!silent)
|
||||
patient.balloon_alert(user, "not hurt!")
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
return FALSE
|
||||
|
||||
/// The healing effects on a carbon patient. Since we have extra details for dealing with bodyparts, we get our own fancy proc. Still returns TRUE on success and FALSE on fail
|
||||
/obj/item/stack/medical/proc/heal_carbon(mob/living/carbon/patient, mob/user, brute, burn)
|
||||
var/obj/item/bodypart/affecting = patient.get_bodypart(check_zone(user.zone_selected))
|
||||
if(!try_heal_checks(patient, user, brute, burn))
|
||||
return FALSE
|
||||
/// The healing effects on a carbon patient.
|
||||
/// Since we have extra details for dealing with bodyparts, we get our own fancy proc.
|
||||
/// Still returns TRUE on success and FALSE on fail
|
||||
/obj/item/stack/medical/proc/heal_carbon(mob/living/carbon/patient, mob/living/user, healed_zone)
|
||||
var/obj/item/bodypart/affecting = patient.get_bodypart(healed_zone)
|
||||
user.visible_message(
|
||||
span_infoplain(span_green("[user] applies [src] on [patient]'s [affecting.plaintext_zone].")),
|
||||
span_infoplain(span_green("You apply [src] on [patient]'s [affecting.plaintext_zone]."))
|
||||
span_green("[user] applies [src] on [patient]'s [affecting.plaintext_zone]."),
|
||||
span_green("You apply [src] on [patient]'s [affecting.plaintext_zone]."),
|
||||
visible_message_flags = ALWAYS_SHOW_SELF_MESSAGE,
|
||||
)
|
||||
var/previous_damage = affecting.get_damage()
|
||||
if(affecting.heal_damage(brute, burn))
|
||||
if(affecting.heal_damage(heal_brute, heal_burn))
|
||||
patient.update_damage_overlays()
|
||||
if(stop_bleeding)
|
||||
for(var/datum/wound/wound as anything in affecting.wounds)
|
||||
if(wound.blood_flow)
|
||||
wound.adjust_blood_flow(-1 * stop_bleeding * (user == patient ? 0.7 : 1))
|
||||
break // one at a time
|
||||
affecting.adjustBleedStacks(-1 * stop_bleeding, 0)
|
||||
if(flesh_regeneration || sanitization)
|
||||
for(var/datum/wound/burn/flesh/wound as anything in affecting.wounds)
|
||||
if(wound.can_be_ointmented_or_meshed())
|
||||
wound.flesh_healing += flesh_regeneration
|
||||
wound.sanitization += sanitization
|
||||
break // one at a time
|
||||
post_heal_effects(max(previous_damage - affecting.get_damage(), 0), patient, user)
|
||||
return TRUE
|
||||
|
||||
///Override this proc for special post heal effects.
|
||||
/obj/item/stack/medical/proc/post_heal_effects(amount_healed, mob/living/carbon/healed_mob, mob/user)
|
||||
/// Healing a simple mob, just an adjustbruteloss call
|
||||
/obj/item/stack/medical/proc/heal_simplemob(mob/living/patient, mob/living/user)
|
||||
patient.adjustBruteLoss(-1 * (heal_brute * patient.maxHealth / 100))
|
||||
user.visible_message(
|
||||
span_green("[user] applies [src] on [patient]."),
|
||||
span_green("You apply [src] on [patient]."),
|
||||
visible_message_flags = ALWAYS_SHOW_SELF_MESSAGE,
|
||||
)
|
||||
return TRUE
|
||||
|
||||
///Override this proc for special post heal effects. Only called for carbon patients.
|
||||
/obj/item/stack/medical/proc/post_heal_effects(amount_healed, mob/living/carbon/healed_mob, mob/living/user)
|
||||
return
|
||||
|
||||
/obj/item/stack/medical/bruise_pack
|
||||
@@ -239,47 +375,79 @@
|
||||
SEND_SIGNAL(gauzed_bodypart, COMSIG_BODYPART_UNGAUZED, src)
|
||||
gauzed_bodypart = null
|
||||
|
||||
// gauze is only relevant for wounds, which are handled in the wounds themselves
|
||||
/obj/item/stack/medical/gauze/try_heal(mob/living/patient, mob/user, silent, looping)
|
||||
/obj/item/stack/medical/gauze/add_item_context(obj/item/source, list/context, atom/target, mob/living/user)
|
||||
if(iscarbon(target))
|
||||
context[SCREENTIP_CONTEXT_LMB] = "Apply Gauze"
|
||||
return CONTEXTUAL_SCREENTIP_SET
|
||||
return NONE
|
||||
|
||||
var/treatment_delay = (user == patient ? self_delay : other_delay)
|
||||
|
||||
var/obj/item/bodypart/limb = patient.get_bodypart(check_zone(user.zone_selected))
|
||||
if(!limb)
|
||||
patient.balloon_alert(user, "missing limb!")
|
||||
return
|
||||
/obj/item/stack/medical/gauze/try_heal_checks(mob/living/patient, mob/living/user, healed_zone, silent = FALSE)
|
||||
var/obj/item/bodypart/limb = patient.get_bodypart(healed_zone)
|
||||
if(isnull(limb))
|
||||
if(!silent)
|
||||
patient.balloon_alert(user, "no [parse_zone(healed_zone)]!")
|
||||
return FALSE
|
||||
if(!LAZYLEN(limb.wounds))
|
||||
patient.balloon_alert(user, "no wounds!") // good problem to have imo
|
||||
return
|
||||
|
||||
var/gauzeable_wound = FALSE
|
||||
var/datum/wound/woundies
|
||||
for(var/i in limb.wounds)
|
||||
woundies = i
|
||||
if(woundies.wound_flags & ACCEPTS_GAUZE)
|
||||
gauzeable_wound = TRUE
|
||||
break
|
||||
if(!gauzeable_wound)
|
||||
patient.balloon_alert(user, "can't heal those!")
|
||||
return
|
||||
|
||||
if(!silent)
|
||||
patient.balloon_alert(user, "no wounds!") // good problem to have imo
|
||||
return FALSE
|
||||
if(limb.current_gauze && (limb.current_gauze.absorption_capacity * 1.2 > absorption_capacity)) // ignore if our new wrap is < 20% better than the current one, so someone doesn't bandage it 5 times in a row
|
||||
patient.balloon_alert(user, pick("already bandaged!", "bandage is clean!")) // good enough
|
||||
return
|
||||
if(!silent)
|
||||
patient.balloon_alert(user, pick("already bandaged!", "bandage is clean!")) // good enough
|
||||
return FALSE
|
||||
for(var/datum/wound/woundies as anything in limb.wounds)
|
||||
if(woundies.wound_flags & ACCEPTS_GAUZE)
|
||||
return TRUE
|
||||
if(!silent)
|
||||
patient.balloon_alert(user, "can't gauze!")
|
||||
return FALSE
|
||||
|
||||
if(HAS_TRAIT(woundies, TRAIT_WOUND_SCANNED))
|
||||
// gauze is only relevant for wounds, which are handled in the wounds themselves
|
||||
/obj/item/stack/medical/gauze/try_heal(mob/living/patient, mob/living/user, silent, healed_zone, auto_change_zone)
|
||||
var/obj/item/bodypart/limb = patient.get_bodypart(healed_zone)
|
||||
var/treatment_delay = (user == patient ? self_delay : other_delay)
|
||||
var/any_scanned = FALSE
|
||||
for(var/datum/wound/woundies as anything in limb.wounds)
|
||||
if(HAS_TRAIT(woundies, TRAIT_WOUND_SCANNED))
|
||||
any_scanned = TRUE
|
||||
break
|
||||
|
||||
if(any_scanned)
|
||||
treatment_delay *= 0.5
|
||||
if(user == patient)
|
||||
to_chat(user, span_notice("You keep in mind the indications from the holo-image about your injury, and expertly begin wrapping your wounds with [src]."))
|
||||
if(!silent)
|
||||
user.visible_message(
|
||||
span_warning("[user] begins expertly wrapping the wounds on [p_their()]'s [limb.plaintext_zone] with [src]..."),
|
||||
span_warning("You begin quickly wrapping the wounds on your [limb.plaintext_zone] with [src], keeping the holo-image indications in mind..."),
|
||||
visible_message_flags = ALWAYS_SHOW_SELF_MESSAGE,
|
||||
)
|
||||
else
|
||||
user.visible_message(span_warning("[user] begins expertly wrapping the wounds on [patient]'s [limb.plaintext_zone] with [src]..."), span_warning("You begin quickly wrapping the wounds on [patient]'s [limb.plaintext_zone] with [src], keeping the holo-image indications in mind..."))
|
||||
if(!silent)
|
||||
user.visible_message(
|
||||
span_warning("[user] begins expertly wrapping the wounds on [patient]'s [limb.plaintext_zone] with [src]..."),
|
||||
span_warning("You begin quickly wrapping the wounds on [patient]'s [limb.plaintext_zone] with [src], keeping the holo-image indications in mind..."),
|
||||
visible_message_flags = ALWAYS_SHOW_SELF_MESSAGE,
|
||||
)
|
||||
else
|
||||
user.visible_message(span_warning("[user] begins wrapping the wounds on [patient]'s [limb.plaintext_zone] with [src]..."), span_warning("You begin wrapping the wounds on [user == patient ? "your" : "[patient]'s"] [limb.plaintext_zone] with [src]..."))
|
||||
if(!silent)
|
||||
user.visible_message(
|
||||
span_warning("[user] begins wrapping the wounds on [patient]'s [limb.plaintext_zone] with [src]..."),
|
||||
span_warning("You begin wrapping the wounds on [user == patient ? "your" : "[patient]'s"] [limb.plaintext_zone] with [src]..."),
|
||||
visible_message_flags = ALWAYS_SHOW_SELF_MESSAGE,
|
||||
)
|
||||
|
||||
patient.balloon_alert(user, "wrapping [parse_zone(healed_zone)]...")
|
||||
|
||||
if(!do_after(user, treatment_delay, target = patient))
|
||||
return
|
||||
|
||||
user.visible_message(span_infoplain(span_green("[user] applies [src] to [patient]'s [limb.plaintext_zone].")), span_infoplain(span_green("You bandage the wounds on [user == patient ? "your" : "[patient]'s"] [limb.plaintext_zone].")))
|
||||
if(!silent)
|
||||
patient.balloon_alert(user, "wrapped [parse_zone(healed_zone)]")
|
||||
user.visible_message(
|
||||
span_green("[user] applies [src] to [patient]'s [limb.plaintext_zone]."),
|
||||
span_green("You bandage the wounds on [user == patient ? "your" : "[patient]'s"] [limb.plaintext_zone]."),
|
||||
visible_message_flags = ALWAYS_SHOW_SELF_MESSAGE,
|
||||
)
|
||||
limb.apply_gauze(src)
|
||||
|
||||
/obj/item/stack/medical/gauze/twelve
|
||||
@@ -413,10 +581,11 @@
|
||||
return ..()
|
||||
icon_state = "regen_mesh_closed"
|
||||
|
||||
/obj/item/stack/medical/mesh/try_heal(mob/living/patient, mob/user, silent = FALSE, looping)
|
||||
/obj/item/stack/medical/mesh/try_heal_checks(mob/living/patient, mob/living/user, silent = FALSE)
|
||||
if(!is_open)
|
||||
balloon_alert(user, "open it first!")
|
||||
return
|
||||
if(!silent)
|
||||
balloon_alert(user, "open it first!")
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/obj/item/stack/medical/mesh/click_alt(mob/living/user)
|
||||
@@ -529,7 +698,11 @@
|
||||
/obj/item/stack/medical/poultice
|
||||
name = "mourning poultices"
|
||||
singular_name = "mourning poultice"
|
||||
desc = "A type of primitive herbal poultice.\nWhile traditionally used to prepare corpses for the mourning feast, it can also treat scrapes and burns on the living, however, it is liable to cause shortness of breath when employed in this manner.\nIt is imbued with ancient wisdom."
|
||||
desc = "A type of primitive herbal poultice.\n\
|
||||
While traditionally used to prepare corpses for the mourning feast, \
|
||||
it can also treat scrapes and burns on the living, however, \
|
||||
it is liable to cause shortness of breath when employed in this manner.\n\
|
||||
It is imbued with ancient wisdom."
|
||||
icon_state = "poultice"
|
||||
amount = 15
|
||||
max_amount = 15
|
||||
@@ -543,14 +716,9 @@
|
||||
hitsound = 'sound/misc/moist_impact.ogg'
|
||||
merge_type = /obj/item/stack/medical/poultice
|
||||
|
||||
/obj/item/stack/medical/poultice/heal(mob/living/patient, mob/user)
|
||||
if(iscarbon(patient))
|
||||
playsound(src, 'sound/misc/soggy.ogg', 30, TRUE)
|
||||
return heal_carbon(patient, user, heal_brute, heal_burn)
|
||||
return ..()
|
||||
|
||||
/obj/item/stack/medical/poultice/post_heal_effects(amount_healed, mob/living/carbon/healed_mob, mob/user)
|
||||
/obj/item/stack/medical/poultice/post_heal_effects(amount_healed, mob/living/carbon/healed_mob, mob/living/user)
|
||||
. = ..()
|
||||
playsound(src, 'sound/misc/soggy.ogg', 30, TRUE)
|
||||
healed_mob.adjustOxyLoss(amount_healed)
|
||||
|
||||
/obj/item/stack/medical/bandage
|
||||
|
||||
@@ -391,10 +391,7 @@
|
||||
/mob/living/carbon/human/try_inject(mob/user, target_zone, injection_flags)
|
||||
. = ..()
|
||||
if(!. && (injection_flags & INJECT_TRY_SHOW_ERROR_MESSAGE) && user)
|
||||
if(!target_zone)
|
||||
target_zone = get_bodypart(check_zone(user.zone_selected))
|
||||
var/obj/item/bodypart/the_part = isbodypart(target_zone) ? target_zone : get_bodypart(check_zone(target_zone)) //keep these synced
|
||||
to_chat(user, span_alert("There is no exposed flesh or thin material on [p_their()] [the_part.name]."))
|
||||
balloon_alert(user, "no exposed skin on [target_zone || check_zone(user.zone_selected)]!")
|
||||
|
||||
/mob/living/carbon/human/get_butt_sprite()
|
||||
var/obj/item/bodypart/chest/chest = get_bodypart(BODY_ZONE_CHEST)
|
||||
|
||||
@@ -1264,14 +1264,11 @@
|
||||
* * gauze- Just the gauze stack we're taking a sheet from to apply here
|
||||
*/
|
||||
/obj/item/bodypart/proc/apply_gauze(obj/item/stack/medical/gauze/new_gauze)
|
||||
if(!istype(new_gauze) || !new_gauze.absorption_capacity)
|
||||
if(!istype(new_gauze) || !new_gauze.absorption_capacity || !new_gauze.use(1))
|
||||
return
|
||||
var/newly_gauzed = FALSE
|
||||
if(!current_gauze)
|
||||
newly_gauzed = TRUE
|
||||
var/newly_gauzed = !current_gauze
|
||||
QDEL_NULL(current_gauze)
|
||||
current_gauze = new new_gauze.type(src, 1)
|
||||
new_gauze.use(1)
|
||||
current_gauze.gauzed_bodypart = src
|
||||
if(newly_gauzed)
|
||||
SEND_SIGNAL(src, COMSIG_BODYPART_GAUZED, current_gauze, new_gauze)
|
||||
|
||||
@@ -144,7 +144,7 @@
|
||||
)
|
||||
log_combat(user, target, "dressed burns in", addition="COMBAT MODE: [uppertext(user.combat_mode)]")
|
||||
pierce_wound.adjust_blood_flow(-0.5)
|
||||
if(pierce_wound.blood_flow > 0)
|
||||
if(!QDELETED(pierce_wound) && pierce_wound.blood_flow > 0)
|
||||
surgery.status = REALIGN_INNARDS
|
||||
to_chat(user, span_notice("<i>There still seems to be misaligned blood vessels to finish...</i>"))
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user