diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index 866207201fa..43870e44884 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -236,6 +236,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_NANITE_MONITORING "nanite_monitoring" //The mob's nanites are sending a monitoring signal visible on diag HUD /// Prevents mob from riding mobs when buckled onto something #define TRAIT_CANT_RIDE "cant_ride" +#define TRAIT_BLOODY_MESS "bloody_mess" //from heparin, makes open bleeding wounds rapidly spill more blood +#define TRAIT_COAGULATING "coagulating" //from coagulant reagents, this doesn't affect the bleeding itself but does affect the bleed warning messages #define TRAIT_NOBLEED "nobleed" //This carbon doesn't bleed diff --git a/code/__DEFINES/wounds.dm b/code/__DEFINES/wounds.dm index 92a1d60ece9..01b39616e5a 100644 --- a/code/__DEFINES/wounds.dm +++ b/code/__DEFINES/wounds.dm @@ -43,6 +43,8 @@ /// the max amount of determination you can have #define WOUND_DETERMINATION_MAX 10 +/// While someone has determination in their system, their bleed rate is slightly reduced +#define WOUND_DETERMINATION_BLEED_MOD 0.85 // ~wound global lists // list in order of highest severity to lowest @@ -143,3 +145,14 @@ GLOBAL_LIST_INIT(global_all_wound_types, list(/datum/wound/blunt/critical, /datu #define SCAR_CURRENT_VERSION 3 /// how many scar slots, per character slot, we have to cycle through for persistent scarring, if enabled in character prefs #define PERSISTENT_SCAR_SLOTS 3 + +// ~blood_flow rates of change, these are used by [/datum/wound/proc/get_bleed_rate_of_change] from [/mob/living/carbon/proc/bleed_warn] to let the player know if their bleeding is getting better/worse/the same +/// Our wound is clotting and will eventually stop bleeding if this continues +#define BLOOD_FLOW_DECREASING -1 +/// Our wound is bleeding but is holding steady at the same rate. +#define BLOOD_FLOW_STEADY 0 +/// Our wound is bleeding and actively getting worse, like if we're a critical slash or if we're afflicted with heparin +#define BLOOD_FLOW_INCREASING 1 + +/// How often can we annoy the player about their bleeding? This duration is extended if it's not serious bleeding +#define BLEEDING_MESSAGE_BASE_CD 10 SECONDS diff --git a/code/datums/status_effects/wound_effects.dm b/code/datums/status_effects/wound_effects.dm index 5ea22249291..662b0f528cf 100644 --- a/code/datums/status_effects/wound_effects.dm +++ b/code/datums/status_effects/wound_effects.dm @@ -11,10 +11,17 @@ /datum/status_effect/determined/on_apply() . = ..() - owner.visible_message("[owner] grits [owner.p_their()] teeth in pain!", "Your senses sharpen as your body tenses up from the wounds you've sustained!", vision_distance=COMBAT_MESSAGE_RANGE) + owner.visible_message("[owner]'s body tenses up noticeably, gritting against [owner.p_their()] pain!", "Your senses sharpen as your body tenses up from the wounds you've sustained!", \ + vision_distance=COMBAT_MESSAGE_RANGE) + if(ishuman(owner)) + var/mob/living/carbon/human/human_owner = owner + human_owner.physiology.bleed_mod *= WOUND_DETERMINATION_BLEED_MOD /datum/status_effect/determined/on_remove() owner.visible_message("[owner]'s body slackens noticeably!", "Your adrenaline rush dies off, and the pain from your wounds come aching back in...", vision_distance=COMBAT_MESSAGE_RANGE) + if(ishuman(owner)) + var/mob/living/carbon/human/human_owner = owner + human_owner.physiology.bleed_mod /= WOUND_DETERMINATION_BLEED_MOD return ..() /datum/status_effect/limp @@ -50,16 +57,16 @@ /atom/movable/screen/alert/status_effect/limp name = "Limping" - desc = "One or more of your legs has been wounded, slowing down steps with that leg! Get it fixed, or at least splinted!" + desc = "One or more of your legs has been wounded, slowing down steps with that leg! Get it fixed, or at least in a sling of gauze!" /datum/status_effect/limp/proc/check_step(mob/whocares, OldLoc, Dir, forced) SIGNAL_HANDLER - if(!owner.client || owner.body_position == LYING_DOWN || !owner.has_gravity() || (owner.movement_type & FLYING) || forced) + if(!owner.client || owner.body_position == LYING_DOWN || !owner.has_gravity() || (owner.movement_type & FLYING) || forced || owner.buckled) return - var/determined_mod = 1 - if(owner.has_status_effect(STATUS_EFFECT_DETERMINED)) - determined_mod = 0.25 + // less limping while we have determination still + var/determined_mod = owner.has_status_effect(STATUS_EFFECT_DETERMINED) ? 0.25 : 1 + if(next_leg == left) owner.client.move_delay += slowdown_left * determined_mod next_leg = right diff --git a/code/datums/wounds/_wounds.dm b/code/datums/wounds/_wounds.dm index d779ff3c2e3..4a57959c9f2 100644 --- a/code/datums/wounds/_wounds.dm +++ b/code/datums/wounds/_wounds.dm @@ -340,6 +340,16 @@ /datum/wound/proc/drag_bleed_amount() return +/** + * get_bleed_rate_of_change() is used in [/mob/living/carbon/proc/bleed_warn] to gauge whether this wound (if bleeding) is becoming worse, better, or staying the same over time + * + * Returns BLOOD_FLOW_STEADY if we're not bleeding or there's no change (like piercing), BLOOD_FLOW_DECREASING if we're clotting (non-critical slashes, gauzed, coagulant, etc), BLOOD_FLOW_INCREASING if we're opening up (crit slashes/heparin) + */ +/datum/wound/proc/get_bleed_rate_of_change() + if(blood_flow && HAS_TRAIT(victim, TRAIT_BLOODY_MESS)) + return BLOOD_FLOW_INCREASING + return BLOOD_FLOW_STEADY + /** * get_examine_description() is used in carbon/examine and human/examine to show the status of this wound. Useful if you need to show some status like the wound being splinted or bandaged. * diff --git a/code/datums/wounds/burns.dm b/code/datums/wounds/burns.dm index 9525ef0bd0e..ee348d493df 100644 --- a/code/datums/wounds/burns.dm +++ b/code/datums/wounds/burns.dm @@ -34,10 +34,10 @@ /datum/wound/burn/handle_process() . = ..() - if(strikes_to_lose_limb == 0) + if(strikes_to_lose_limb == 0) // we've already hit sepsis, nothing more to do victim.adjustToxLoss(0.5) if(prob(1)) - victim.visible_message("The infection on the remnants of [victim]'s [limb.name] shift and bubble nauseatingly!", "You can feel the infection on the remnants of your [limb.name] coursing through your veins!") + victim.visible_message("The infection on the remnants of [victim]'s [limb.name] shift and bubble nauseatingly!", "You can feel the infection on the remnants of your [limb.name] coursing through your veins!", vision_distance = COMBAT_MESSAGE_RANGE) return if(victim.reagents) @@ -52,18 +52,22 @@ if(limb.current_gauze) limb.seep_gauze(WOUND_BURN_SANITIZATION_RATE) - if(flesh_healing > 0) + if(flesh_healing > 0) // good bandages multiply the length of flesh healing var/bandage_factor = (limb.current_gauze ? limb.current_gauze.splint_factor : 1) flesh_damage = max(0, flesh_damage - 1) - flesh_healing = max(0, flesh_healing - bandage_factor) // good bandages multiply the length of flesh healing + flesh_healing = max(0, flesh_healing - bandage_factor) + + // if we have little/no infection, the limb doesn't have much burn damage, and our nutrition is good, heal some flesh + if(infestation <= WOUND_INFECTION_MODERATE && (limb.burn_dam < 5) && (victim.nutrition >= NUTRITION_LEVEL_FED)) + flesh_healing += 0.2 // here's the check to see if we're cleared up - if((flesh_damage <= 0) && (infestation <= 1)) + if((flesh_damage <= 0) && (infestation <= WOUND_INFECTION_MODERATE)) to_chat(victim, "The burns on your [limb.name] have cleared up!") qdel(src) return - // sanitization is checked after the clearing check but before the rest, because we freeze the effects of infection while we have sanitization + // sanitization is checked after the clearing check but before the actual ill-effects, because we freeze the effects of infection while we have sanitization if(sanitization > 0) var/bandage_factor = (limb.current_gauze ? limb.current_gauze.splint_factor : 1) infestation = max(0, infestation - WOUND_BURN_SANITIZATION_RATE) @@ -118,7 +122,7 @@ /datum/wound/burn/get_examine_description(mob/user) if(strikes_to_lose_limb <= 0) - return "[victim.p_their(TRUE)] [limb.name] is completely dead and unrecognizable as organic." + return "[victim.p_their(TRUE)] [limb.name] has locked up completely and is non-functional." var/list/condition = list("[victim.p_their(TRUE)] [limb.name] [examine_desc]") if(limb.current_gauze) @@ -137,13 +141,13 @@ else switch(infestation) if(WOUND_INFECTION_MODERATE to WOUND_INFECTION_SEVERE) - condition += ", with small spots of discoloration along the nearby veins!" + condition += ", with early signs of infection." if(WOUND_INFECTION_SEVERE to WOUND_INFECTION_CRITICAL) - condition += ", with dark clouds spreading outwards under the skin!" + condition += ", with growing clouds of infection." if(WOUND_INFECTION_CRITICAL to WOUND_INFECTION_SEPTIC) - condition += ", with streaks of rotten infection pulsating outward!" + condition += ", with streaks of rotten, pulsating infection!" if(WOUND_INFECTION_SEPTIC to INFINITY) - return "[victim.p_their(TRUE)] [limb.name] is a mess of char and rot, skin literally dripping off the bone with infection!" + return "[victim.p_their(TRUE)] [limb.name] is a mess of charred skin and infected rot!" else condition += "!" @@ -152,7 +156,7 @@ /datum/wound/burn/get_scanner_description(mob/user) if(strikes_to_lose_limb == 0) var/oopsie = "Type: [name]\nSeverity: [severity_text()]" - oopsie += "
Infection Level: The infection is total. The bodypart is lost. Amputate or augment limb immediately.
" + oopsie += "
Infection Level: The bodypart has suffered complete sepsis and must be removed. Amputate or augment limb immediately.
" return oopsie . = ..() @@ -174,15 +178,15 @@ . += "\tSurgical debridement, antiobiotics/sterilizers, or regenerative mesh will rid infection. Paramedic UV penlights are also effective.\n" if(flesh_damage > 0) - . += "Flesh damage detected: Please apply ointment or regenerative mesh to allow recovery.\n" + . += "Flesh damage detected: Application of ointment, regenerative mesh, Synthflesh, or ingestion of \"Miner's Salve\" will repair damaged flesh. Good nutrition, rest, and keeping the wound clean can also slowly repair flesh.\n" . += "" /* new burn common procs */ -/// if someone is using ointment on our burns -/datum/wound/burn/proc/ointment(obj/item/stack/medical/ointment/I, mob/user) +/// if someone is using ointment or mesh on our burns +/datum/wound/burn/proc/ointmentmesh(obj/item/stack/medical/I, mob/user) user.visible_message("[user] begins applying [I] to [victim]'s [limb.name]...", "You begin applying [I] to [user == victim ? "your" : "[victim]'s"] [limb.name]...") if(!do_after(user, (user == victim ? I.self_delay : I.other_delay), extra_checks = CALLBACK(src, .proc/still_exists))) return @@ -198,26 +202,6 @@ else try_treating(I, user) -/// if someone is using mesh on our burns -/datum/wound/burn/proc/mesh(obj/item/stack/medical/mesh/I, mob/user) - if(!I.is_open) - to_chat(user, "You need to open [I] first.") - return - user.visible_message("[user] begins wrapping [victim]'s [limb.name] with [I]...", "You begin wrapping [user == victim ? "your" : "[victim]'s"] [limb.name] with [I]...") - if(!do_after(user, (user == victim ? I.self_delay : I.other_delay), target=victim, extra_checks = CALLBACK(src, .proc/still_exists))) - return - - limb.heal_damage(I.heal_brute, I.heal_burn) - user.visible_message("[user] applies [I] to [victim].", "You apply [I] to [user == victim ? "your" : "[victim]'s"] [limb.name].") - I.use(1) - sanitization += I.sanitization - flesh_healing += I.flesh_regeneration - - if(sanitization >= infestation && flesh_healing > flesh_damage) - to_chat(user, "You've done all you can with [I], now you must wait for the flesh on [victim]'s [limb.name] to recover.") - else - try_treating(I, user) - /// Paramedic UV penlights /datum/wound/burn/proc/uv(obj/item/flashlight/pen/paramedic/I, mob/user) if(!COOLDOWN_FINISHED(I, uv_cooldown)) @@ -233,9 +217,13 @@ /datum/wound/burn/treat(obj/item/I, mob/user) if(istype(I, /obj/item/stack/medical/ointment)) - ointment(I, user) + ointmentmesh(I, user) else if(istype(I, /obj/item/stack/medical/mesh)) - mesh(I, user) + var/obj/item/stack/medical/mesh/mesh_check = I + if(!mesh_check.is_open) + to_chat(user, "You need to open [mesh_check] first.") + return + ointmentmesh(mesh_check, user) else if(istype(I, /obj/item/flashlight/pen/paramedic)) uv(I, user) @@ -281,7 +269,7 @@ threshold_penalty = 40 status_effect_type = /datum/status_effect/wound/burn/severe treatable_by = list(/obj/item/flashlight/pen/paramedic, /obj/item/stack/medical/ointment, /obj/item/stack/medical/mesh) - infestation_rate = 0.05 // appx 13 minutes to reach sepsis without any treatment + infestation_rate = 0.07 // appx 9 minutes to reach sepsis without any treatment flesh_damage = 12.5 scar_keyword = "burnsevere" diff --git a/code/datums/wounds/pierce.dm b/code/datums/wounds/pierce.dm index 1142fd2c165..d6f9295f24a 100644 --- a/code/datums/wounds/pierce.dm +++ b/code/datums/wounds/pierce.dm @@ -49,6 +49,13 @@ new /obj/effect/temp_visual/dir_setting/bloodsplatter(victim.loc, victim.dir) victim.add_splatter_floor(get_step(victim.loc, victim.dir)) +/datum/wound/pierce/get_bleed_rate_of_change() + if(HAS_TRAIT(victim, TRAIT_BLOODY_MESS)) + return BLOOD_FLOW_INCREASING + if(limb.current_gauze) + return BLOOD_FLOW_DECREASING + return BLOOD_FLOW_STEADY + /datum/wound/pierce/handle_process() blood_flow = min(blood_flow, WOUND_SLASH_MAX_BLOODFLOW) @@ -57,8 +64,8 @@ if(prob(5)) to_chat(victim, "You feel the [lowertext(name)] in your [limb.name] firming up from the cold!") - if(victim.reagents.has_reagent(/datum/reagent/toxin/heparin)) - blood_flow += 0.5 // old herapin 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(HAS_TRAIT(victim, TRAIT_BLOODY_MESS)) + blood_flow += 0.5 // 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) blood_flow -= limb.current_gauze.absorption_rate * gauzed_clot_rate diff --git a/code/datums/wounds/slash.dm b/code/datums/wounds/slash.dm index 0f091cb95ec..417653f7090 100644 --- a/code/datums/wounds/slash.dm +++ b/code/datums/wounds/slash.dm @@ -18,14 +18,12 @@ var/initial_flow /// When we have less than this amount of flow, either from treatment or clotting, we demote to a lower cut or are healed of the wound var/minimum_flow - /// How fast our blood flow will naturally decrease per tick, not only do larger cuts bleed more faster, they clot slower + /// How much our blood_flow will naturally decrease per tick, not only do larger cuts bleed more blood faster, they clot slower (higher number = clot quicker, negative = opening up) var/clot_rate /// 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 - /// How much staunching per type (cautery, suturing, bandaging) you can have before that type is no longer effective for this cut NOT IMPLEMENTED - var/max_per_type /// The maximum flow we've had so far var/highest_flow @@ -84,6 +82,14 @@ return bleed_amt +/datum/wound/slash/get_bleed_rate_of_change() + if(HAS_TRAIT(victim, TRAIT_BLOODY_MESS)) + return BLOOD_FLOW_INCREASING + if(limb.current_gauze || clot_rate > 0) + return BLOOD_FLOW_DECREASING + if(clot_rate < 0) + return BLOOD_FLOW_INCREASING + /datum/wound/slash/handle_process() if(victim.stat == DEAD) blood_flow -= max(clot_rate, WOUND_SLASH_DEAD_CLOT_MIN) @@ -96,8 +102,8 @@ blood_flow = min(blood_flow, WOUND_SLASH_MAX_BLOODFLOW) - if(victim.reagents.has_reagent(/datum/reagent/toxin/heparin)) - blood_flow += 0.5 // old herapin 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(HAS_TRAIT(victim, TRAIT_BLOODY_MESS)) + blood_flow += 0.5 // 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) if(clot_rate > 0) @@ -254,7 +260,6 @@ severity = WOUND_SEVERITY_MODERATE initial_flow = 2 minimum_flow = 0.5 - max_per_type = 3 clot_rate = 0.12 threshold_minimum = 20 threshold_penalty = 10 @@ -272,7 +277,6 @@ initial_flow = 3.25 minimum_flow = 2.75 clot_rate = 0.06 - max_per_type = 4 threshold_minimum = 50 threshold_penalty = 25 demotes_to = /datum/wound/slash/moderate @@ -290,7 +294,6 @@ initial_flow = 4.25 minimum_flow = 4 clot_rate = -0.05 // critical cuts actively get worse instead of better - max_per_type = 5 threshold_minimum = 80 threshold_penalty = 40 demotes_to = /datum/wound/slash/severe diff --git a/code/modules/mob/living/blood.dm b/code/modules/mob/living/blood.dm index 95269688224..6abc0268ee0 100644 --- a/code/modules/mob/living/blood.dm +++ b/code/modules/mob/living/blood.dm @@ -68,24 +68,101 @@ if(temp_bleed) bleed(temp_bleed) + bleed_warn(temp_bleed) //Makes a blood drop, leaking amt units of blood from the mob /mob/living/carbon/proc/bleed(amt) - if(blood_volume) - blood_volume = max(blood_volume - amt, 0) - if (prob(sqrt(amt)*BLOOD_DRIP_RATE_MOD)) - if(isturf(src.loc)) //Blood loss still happens in locker, floor stays clean - if(amt >= 10) - add_splatter_floor(src.loc) - else - add_splatter_floor(src.loc, 1) + if(!blood_volume) + return + blood_volume = max(blood_volume - amt, 0) + + //Blood loss still happens in locker, floor stays clean + if(isturf(loc) && prob(sqrt(amt)*BLOOD_DRIP_RATE_MOD)) + add_splatter_floor(loc, (amt >= 10)) /mob/living/carbon/human/bleed(amt) amt *= physiology.bleed_mod if(!(NOBLOOD in dna.species.species_traits)) ..() +/// A helper to see how much blood we're losing per tick +/mob/living/carbon/proc/get_bleed_rate() + if(!blood_volume) + return + var/bleed_amt = 0 + for(var/X in bodyparts) + var/obj/item/bodypart/iter_bodypart = X + bleed_amt += iter_bodypart.get_bleed_rate() + return bleed_amt +/mob/living/carbon/human/get_bleed_rate() + if((NOBLOOD in dna.species.species_traits)) + return + . = ..() + . *= physiology.bleed_mod + +/** + * bleed_warn() is used to for carbons with an active client to occasionally receive messages warning them about their bleeding status (if applicable) + * + * Arguments: + * * bleed_amt- When we run this from [/mob/living/carbon/human/proc/handle_blood] we already know how much blood we're losing this tick, so we can skip tallying it again with this + * * forced- + */ +/mob/living/carbon/proc/bleed_warn(bleed_amt = 0, forced = FALSE) + if(!blood_volume || !client) + return + if(!COOLDOWN_FINISHED(src, bleeding_message_cd) && !forced) + return + + if(!bleed_amt) // if we weren't provided the amount of blood we lost this tick in the args + bleed_amt = get_bleed_rate() + + var/bleeding_severity = "" + var/next_cooldown = BLEEDING_MESSAGE_BASE_CD + + switch(bleed_amt) + if(-INFINITY to 0) + return + if(0 to 1) + bleeding_severity = "You feel light trickles of blood across your skin" + next_cooldown *= 2.5 + if(1 to 3) + bleeding_severity = "You feel a small stream of blood running across your body" + next_cooldown *= 2 + if(3 to 5) + bleeding_severity = "You skin feels clammy from the flow of blood leaving your body" + next_cooldown *= 1.7 + if(5 to 7) + bleeding_severity = "Your body grows more and more numb as blood streams out" + next_cooldown *= 1.5 + if(7 to INFINITY) + bleeding_severity = "Your heartbeat thrashes wildly trying to keep up with your bloodloss" + + var/rate_of_change = ", but it's getting better." // if there's no wounds actively getting bloodier or maintaining the same flow, we must be getting better! + if(HAS_TRAIT(src, TRAIT_COAGULATING)) // if we have coagulant, we're getting better quick + rate_of_change = ", but it's clotting up quickly!" + else + // flick through our wounds to see if there are any bleeding ones getting worse or holding flow (maybe move this to handle_blood and cache it so we don't need to cycle through the wounds so much) + for(var/i in all_wounds) + var/datum/wound/iter_wound = i + if(!iter_wound.blood_flow) + continue + var/iter_wound_roc = iter_wound.get_bleed_rate_of_change() + switch(iter_wound_roc) + if(BLOOD_FLOW_INCREASING) // assume the worst, if one wound is getting bloodier, we focus on that + rate_of_change = ", and it's getting worse!" + break + if(BLOOD_FLOW_STEADY) // our best case now is that our bleeding isn't getting worse + rate_of_change = ", and it's holding steady." + if(BLOOD_FLOW_DECREASING) // this only matters if none of the wounds fit the above two cases, included here for completeness + continue + + to_chat(src, "[bleeding_severity][rate_of_change]") + COOLDOWN_START(src, bleeding_message_cd, next_cooldown) + +/mob/living/carbon/human/bleed_warn(bleed_amt = 0, forced = FALSE) + if(!(NOBLOOD in dna.species.species_traits)) + return ..() /mob/living/proc/restore_blood() blood_volume = initial(blood_volume) diff --git a/code/modules/mob/living/brain/brain_item.dm b/code/modules/mob/living/brain/brain_item.dm index 76311a730a4..d2032ffc83d 100644 --- a/code/modules/mob/living/brain/brain_item.dm +++ b/code/modules/mob/living/brain/brain_item.dm @@ -12,7 +12,7 @@ attack_verb_simple = list("attack", "slap", "whack") ///The brain's organ variables are significantly more different than the other organs, with half the decay rate for balance reasons, and twice the maxHealth - decay_factor = STANDARD_ORGAN_DECAY / 2 //30 minutes of decaying to result in a fully damaged brain, since a fast decay rate would be unfun gameplay-wise + decay_factor = STANDARD_ORGAN_DECAY * 0.5 //30 minutes of decaying to result in a fully damaged brain, since a fast decay rate would be unfun gameplay-wise maxHealth = BRAIN_DAMAGE_DEATH low_threshold = 45 diff --git a/code/modules/mob/living/carbon/carbon_defines.dm b/code/modules/mob/living/carbon/carbon_defines.dm index 876b816d3c5..ada5e1ec9b1 100644 --- a/code/modules/mob/living/carbon/carbon_defines.dm +++ b/code/modules/mob/living/carbon/carbon_defines.dm @@ -106,3 +106,5 @@ /// Can other carbons be shoved into this one to make it fall? var/can_be_shoved_into = FALSE + + COOLDOWN_DECLARE(bleeding_message_cd) diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm index a9752477bad..d78a39c264c 100644 --- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm @@ -1360,26 +1360,41 @@ color = "#bb2424" metabolization_rate = 0.25 * REAGENTS_METABOLISM overdose_threshold = 20 - /// How much base clotting we do per bleeding wound, multiplied by the below number for each bleeding wound - var/clot_rate = 0.25 - /// If we have multiple bleeding wounds, we count the number of bleeding wounds, then multiply the clot rate by this^(n) before applying it to each cut, so more cuts = less clotting per cut (though still more total clotting) - var/clot_coeff_per_wound = 0.75 + /// The bloodiest wound that the patient has will have its blood_flow reduced by this much each tick + var/clot_rate = 0.3 + /// While this reagent is in our bloodstream, we reduce all bleeding by this factor + var/passive_bleed_modifier = 0.7 + /// For tracking when we tell the person we're no longer bleeding + var/was_working + +/datum/reagent/medicine/coagulant/on_mob_metabolize(mob/living/M) + ADD_TRAIT(M, TRAIT_COAGULATING, /datum/reagent/medicine/coagulant) + return ..() + +/datum/reagent/medicine/coagulant/on_mob_end_metabolize(mob/living/M) + REMOVE_TRAIT(M, TRAIT_COAGULATING, /datum/reagent/medicine/coagulant) + return ..() /datum/reagent/medicine/coagulant/on_mob_life(mob/living/carbon/M) . = ..() if(!M.blood_volume || !M.all_wounds) return - var/effective_clot_rate = clot_rate + var/datum/wound/bloodiest_wound for(var/i in M.all_wounds) var/datum/wound/iter_wound = i if(iter_wound.blood_flow) - effective_clot_rate *= clot_coeff_per_wound + if(iter_wound.blood_flow > bloodiest_wound?.blood_flow) + bloodiest_wound = iter_wound - for(var/i in M.all_wounds) - var/datum/wound/iter_wound = i - iter_wound.blood_flow = max(0, iter_wound.blood_flow - effective_clot_rate) + if(bloodiest_wound) + if(!was_working) + to_chat(M, "You can feel your flowing blood start thickening!") + was_working = TRUE + bloodiest_wound.blood_flow = max(0, bloodiest_wound.blood_flow - clot_rate) + else if(was_working) + was_working = FALSE /datum/reagent/medicine/coagulant/overdose_process(mob/living/M) . = ..() @@ -1402,13 +1417,30 @@ var/obj/item/organ/heart/our_heart = M.getorganslot(ORGAN_SLOT_HEART) our_heart.applyOrganDamage(1) +/datum/reagent/medicine/coagulant/on_mob_metabolize(mob/living/M) + if(!ishuman(M)) + return + + var/mob/living/carbon/human/blood_boy = M + blood_boy.physiology?.bleed_mod *= passive_bleed_modifier + +/datum/reagent/medicine/coagulant/on_mob_end_metabolize(mob/living/M) + if(was_working) + to_chat(M, "The medicine thickening your blood loses its effect!") + if(!ishuman(M)) + return + + var/mob/living/carbon/human/blood_boy = M + blood_boy.physiology?.bleed_mod /= passive_bleed_modifier + // i googled "natural coagulant" and a couple of results came up for banana peels, so after precisely 30 more seconds of research, i now dub grinding banana peels good for your blood /datum/reagent/medicine/coagulant/banana_peel name = "Pulped Banana Peel" description = "Ancient Clown Lore says that pulped banana peels are good for your blood, but are you really going to take medical advice from a clown about bananas?" - color = "#863333" // rgb: 175, 175, 0 + color = "#50531a" // rgb: 175, 175, 0 taste_description = "horribly stringy, bitter pulp" glass_name = "glass of banana peel pulp" glass_desc = "Ancient Clown Lore says that pulped banana peels are good for your blood, but are you really going to take medical advice from a clown about bananas?" - metabolization_rate = REAGENTS_METABOLISM - clot_coeff_per_wound = 0.6 + metabolization_rate = 0.5 * REAGENTS_METABOLISM + clot_rate = 0.2 + passive_bleed_modifier = 0.8 diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index 6055aefbbe5..553f33cc74e 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -2323,6 +2323,7 @@ color = "#E6E6DA" taste_mult = 0 +// "Second wind" reagent generated when someone suffers a wound. Epinephrine, adrenaline, and stimulants are all already taken so here we are /datum/reagent/determination name = "Determination" description = "For when you need to push on a little more. Do NOT allow near plants." diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm index 3ab31b8fe19..0adc13404c7 100644 --- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm @@ -787,6 +787,14 @@ metabolization_rate = 0.2 * REAGENTS_METABOLISM toxpwr = 0 +/datum/reagent/toxin/heparin/on_mob_metabolize(mob/living/M) + ADD_TRAIT(M, TRAIT_BLOODY_MESS, /datum/reagent/toxin/heparin) + return ..() + +/datum/reagent/toxin/heparin/on_mob_end_metabolize(mob/living/M) + REMOVE_TRAIT(M, TRAIT_BLOODY_MESS, /datum/reagent/toxin/heparin) + return ..() + /datum/reagent/toxin/rotatium //Rotatium. Fucks up your rotation and is hilarious name = "Rotatium" description = "A constantly swirling, oddly colourful fluid. Causes the consumer's sense of direction and hand-eye coordination to become wild." diff --git a/code/modules/research/nanites/nanite_programs/buffing.dm b/code/modules/research/nanites/nanite_programs/buffing.dm index 335522c4541..be8a8659587 100644 --- a/code/modules/research/nanites/nanite_programs/buffing.dm +++ b/code/modules/research/nanites/nanite_programs/buffing.dm @@ -74,22 +74,22 @@ H.physiology.armor.energy -= 20 /datum/nanite_program/coagulating - name = "Rapid Coagulation" - desc = "The nanites induce rapid coagulation when the host is wounded, dramatically reducing bleeding rate." - use_rate = 0.10 + name = "Vein Repressurization" + desc = "The nanites re-route circulating blood away from open wounds, dramatically reducing bleeding rate." + use_rate = 0.20 rogue_types = list(/datum/nanite_program/suffocating) /datum/nanite_program/coagulating/enable_passive_effect() . = ..() if(ishuman(host_mob)) var/mob/living/carbon/human/H = host_mob - H.physiology.bleed_mod *= 0.1 + H.physiology.bleed_mod *= 0.5 /datum/nanite_program/coagulating/disable_passive_effect() . = ..() if(ishuman(host_mob)) var/mob/living/carbon/human/H = host_mob - H.physiology.bleed_mod *= 10 + H.physiology.bleed_mod *= 2 /datum/nanite_program/conductive name = "Electric Conduction" diff --git a/code/modules/surgery/organs/heart.dm b/code/modules/surgery/organs/heart.dm index e413b467ef4..b97977f8acd 100644 --- a/code/modules/surgery/organs/heart.dm +++ b/code/modules/surgery/organs/heart.dm @@ -6,7 +6,7 @@ slot = ORGAN_SLOT_HEART healing_factor = STANDARD_ORGAN_HEALING - decay_factor = 3.5 * STANDARD_ORGAN_DECAY //designed to fail a little under 4 minutes after death + decay_factor = 2.5 * STANDARD_ORGAN_DECAY //designed to fail around 6 minutes after death low_threshold_passed = "Prickles of pain appear then die out from within your chest..." high_threshold_passed = "Something inside your chest hurts, and the pain isn't subsiding. You notice yourself breathing far faster than before." diff --git a/code/modules/surgery/organs/liver.dm b/code/modules/surgery/organs/liver.dm index 5d44c045121..7ec18430995 100755 --- a/code/modules/surgery/organs/liver.dm +++ b/code/modules/surgery/organs/liver.dm @@ -11,7 +11,7 @@ maxHealth = STANDARD_ORGAN_THRESHOLD healing_factor = STANDARD_ORGAN_HEALING - decay_factor = STANDARD_ORGAN_DECAY + decay_factor = STANDARD_ORGAN_DECAY // smack in the middle of decay times food_reagents = list(/datum/reagent/consumable/nutriment = 5, /datum/reagent/iron = 5) grind_results = list(/datum/reagent/consumable/nutriment/peptides = 5) diff --git a/code/modules/surgery/organs/lungs.dm b/code/modules/surgery/organs/lungs.dm index 1765d68cd58..eeee0d6d013 100644 --- a/code/modules/surgery/organs/lungs.dm +++ b/code/modules/surgery/organs/lungs.dm @@ -9,7 +9,7 @@ w_class = WEIGHT_CLASS_SMALL healing_factor = STANDARD_ORGAN_HEALING - decay_factor = STANDARD_ORGAN_DECAY + decay_factor = STANDARD_ORGAN_DECAY * 0.9 // fails around 16.5 minutes, lungs are one of the last organs to die (of the ones we have) low_threshold_passed = "You feel short of breath." high_threshold_passed = "You feel some sort of constriction around your chest as your breathing becomes shallow and rapid." diff --git a/code/modules/surgery/organs/stomach.dm b/code/modules/surgery/organs/stomach.dm index d3dc96e8a4e..2f2e5ea1db9 100755 --- a/code/modules/surgery/organs/stomach.dm +++ b/code/modules/surgery/organs/stomach.dm @@ -12,7 +12,7 @@ desc = "Onaka ga suite imasu." healing_factor = STANDARD_ORGAN_HEALING - decay_factor = STANDARD_ORGAN_DECAY + decay_factor = STANDARD_ORGAN_DECAY * 1.15 // ~13 minutes, the stomach is one of the first organs to die low_threshold_passed = "Your stomach flashes with pain before subsiding. Food doesn't seem like a good idea right now." high_threshold_passed = "Your stomach flares up with constant pain- you can hardly stomach the idea of food right now!" diff --git a/strings/tips.txt b/strings/tips.txt index e0d208821e7..8f2c6a4b9fc 100644 --- a/strings/tips.txt +++ b/strings/tips.txt @@ -52,7 +52,8 @@ As a Medical Doctor, you can point your penlight at people to create a medical h As a Medical Doctor, you can extract implants by holding an empty implant case in your offhand while performing the extraction step. As a Medical Doctor, you can deal with patients who have absurd amounts of wounds by putting them in cryo. This will slowly treat all of their wounds simultaneously, but is much slower than direct treatment. As a Medical Doctor, Critical Slash wounds are one of the most dangerous conditions someone can have. Apply gauze, epipens, sutures, cauteries, whatever you can, as soon as possible! -As a Medical Doctor, Saline-Glucose not only acts as a temporary boost to a patient's blood level, it also speeds regeneration! Perfect for drained patients! +As a Medical Doctor, Saline-Glucose not only acts as a temporary boost to a patient's blood level, it also speeds blood regeneration! Perfect for drained patients! +As a Medical Doctor, almost every type of wound can be treated at least temporarily with gauze. When in doubt, wrap it up! As a Paramedic, your UV penlight can be used to stem infections in burn wounds! Just target the infected limb and use it on the patient. As a Chemist, there are dozens of chemicals that can heal, and even more that can cause harm. Experiment! As a Chemist, some chemicals can only be synthesized by heating up the contents with a chemical heater or manually with lighters and similar tools. @@ -255,6 +256,7 @@ You can light a cigar on a supermatter crystal. Using sticky tape on items can make them stick to people and walls! Be careful, grenades might stick to your hand during the moment of truth! In a pinch, stripping yourself naked will give you a sizeable resistance to being tackled. What do you value more, your freedom or your dignity? Wearing riot armor makes you significantly more effective at performing tackle takedowns, but will use extra stamina with each leap! It will also significantly protect you from other tackles! -Epipens contain a powerful coagulant that drastically reduces bleeding on all bleeding wounds. If you don't have time to properly treat someone with lots of slashes or piercings, stick them with a pen to buy some time! +Standard epipens contain a potent coagulant that not only slow bloodloss, but also help clot whichever of your wounds is bleeding the most! If you're suffering multiple bad bleeding wounds, make sure to seek out additional treatment ASAP! Anything you can light a cigarette with, you can use to cauterize a bleeding wound. Technically, that includes the supermatter. If you're bleeding, you can apply pressure to the limb by grabbing yourself while targeting the bleeding limb. This will slow you down and take up a hand, but it'll slow down how fast you lose blood. Note this won't help the bleeding clot any faster. +Laying down will help slow down bloodloss. Death will halt it entirely.