mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-08-21 20:11:04 +01:00
Ports arterial bleeding and tendon severing (#7432)
This commit is contained in:
@@ -131,18 +131,53 @@ var/const/BLOOD_VOLUME_SURVIVE = 122
|
||||
|
||||
//Bleeding out
|
||||
var/blood_max = 0
|
||||
var/open_wound
|
||||
var/list/do_spray = list()
|
||||
for(var/obj/item/organ/external/temp in organs)
|
||||
if(!(temp.status & ORGAN_BLEEDING) || temp.status & ORGAN_ROBOT)
|
||||
continue
|
||||
for(var/datum/wound/W in temp.wounds)
|
||||
if(W.bleeding())
|
||||
blood_max += ((W.damage / 40) * species.bleed_mod)
|
||||
open_wound = TRUE
|
||||
if(temp.applied_pressure)
|
||||
if(ishuman(temp.applied_pressure))
|
||||
var/mob/living/carbon/human/H = temp.applied_pressure
|
||||
H.bloody_hands(src, 0)
|
||||
var/min_eff_damage = max(0, W.damage - 10) / 6
|
||||
blood_max += max(min_eff_damage, W.damage - 30) / 40
|
||||
else
|
||||
blood_max += ((W.damage / 40) * species.bleed_mod)
|
||||
if(temp.status & ORGAN_ARTERY_CUT)
|
||||
var/bleed_amount = Floor(vessel.total_volume / (temp.applied_pressure || !open_wound ? 450 : 300))
|
||||
if(bleed_amount)
|
||||
if(open_wound)
|
||||
blood_max += bleed_amount
|
||||
do_spray += temp.name
|
||||
else
|
||||
blood_max += W.damage / 40
|
||||
if (temp.open)
|
||||
blood_max += 2 * species.bleed_mod //Yer stomach is cut open
|
||||
drip(blood_max)
|
||||
|
||||
if(world.time >= next_blood_squirt && istype(loc, /turf) && do_spray.len)
|
||||
visible_message("<span class='danger'>Blood squirts from \the [src]'s [pick(do_spray)]!</span>", "<span class='danger'><font size='3'>Blood is squirting out of your [pick(do_spray)]!</font></span>")
|
||||
eye_blurry = 2
|
||||
Stun(1)
|
||||
next_blood_squirt = world.time + 100
|
||||
var/turf/sprayloc = get_turf(src)
|
||||
blood_max -= drip(Ceiling(blood_max/3), sprayloc)
|
||||
if(blood_max > 0)
|
||||
blood_max -= blood_squirt(blood_max, sprayloc)
|
||||
if(blood_max > 0)
|
||||
drip(blood_max, get_turf(src))
|
||||
else
|
||||
drip(blood_max)
|
||||
|
||||
/mob/living/carbon/human
|
||||
var/next_blood_squirt = 0
|
||||
|
||||
//Makes a blood drop, leaking amt units of blood from the mob
|
||||
/mob/living/carbon/human/proc/drip(var/amt as num)
|
||||
|
||||
/mob/living/carbon/human/proc/drip(var/amt as num, var/tar = src, var/spraydir)
|
||||
|
||||
if(species && species.flags & NO_BLOOD) //TODO: Make drips come from the reagents instead.
|
||||
return
|
||||
@@ -151,7 +186,52 @@ var/const/BLOOD_VOLUME_SURVIVE = 122
|
||||
return
|
||||
|
||||
vessel.remove_reagent("blood",amt)
|
||||
blood_splatter(src,src)
|
||||
blood_splatter(tar, src, spray_dir = spraydir)
|
||||
|
||||
#define BLOOD_SPRAY_DISTANCE 2
|
||||
/mob/living/carbon/human/proc/blood_squirt(var/amt, var/turf/sprayloc)
|
||||
if(amt <= 0 || !istype(sprayloc))
|
||||
return
|
||||
var/spraydir = pick(alldirs)
|
||||
amt = Ceiling(amt/BLOOD_SPRAY_DISTANCE)
|
||||
var/bled = 0
|
||||
spawn(0)
|
||||
for(var/i = 1 to BLOOD_SPRAY_DISTANCE)
|
||||
sprayloc = get_step(sprayloc, spraydir)
|
||||
if(!istype(sprayloc) || sprayloc.density)
|
||||
break
|
||||
var/hit_mob
|
||||
for(var/thing in sprayloc)
|
||||
var/atom/A = thing
|
||||
if(!A.simulated)
|
||||
continue
|
||||
|
||||
if(ishuman(A))
|
||||
var/mob/living/carbon/human/H = A
|
||||
if(!H.lying)
|
||||
H.bloody_body(src)
|
||||
H.bloody_hands(src)
|
||||
var/blinding = FALSE
|
||||
if(ran_zone("head", 75))
|
||||
blinding = TRUE
|
||||
for(var/obj/item/I in list(H.head, H.glasses, H.wear_mask))
|
||||
if(I && (I.body_parts_covered & EYES))
|
||||
blinding = FALSE
|
||||
break
|
||||
if(blinding)
|
||||
H.eye_blurry = max(H.eye_blurry, 10)
|
||||
H.eye_blind = max(H.eye_blind, 5)
|
||||
to_chat(H, "<span class='danger'>You are blinded by a spray of blood!</span>")
|
||||
else
|
||||
to_chat(H, "<span class='danger'>You are hit by a spray of blood!</span>")
|
||||
hit_mob = TRUE
|
||||
|
||||
if(hit_mob || !A.CanPass(src, sprayloc))
|
||||
break
|
||||
drip(amt, sprayloc, spraydir)
|
||||
bled += amt
|
||||
return bled
|
||||
#undef BLOOD_SPRAY_DISTANCE
|
||||
|
||||
/****************************************************
|
||||
BLOOD TRANSFERS
|
||||
@@ -274,7 +354,7 @@ proc/blood_incompatible(donor,receiver,donor_species,receiver_species)
|
||||
//AB is a universal receiver.
|
||||
return 0
|
||||
|
||||
proc/blood_splatter(var/target,var/datum/reagent/blood/source,var/large)
|
||||
proc/blood_splatter(var/target, var/datum/reagent/blood/source, var/large, var/spray_dir)
|
||||
|
||||
var/obj/effect/decal/cleanable/blood/B
|
||||
var/decal_type = /obj/effect/decal/cleanable/blood/splatter
|
||||
@@ -283,7 +363,6 @@ proc/blood_splatter(var/target,var/datum/reagent/blood/source,var/large)
|
||||
var/mob/living/carbon/human/M = source
|
||||
source = M.get_blood(M.vessel)
|
||||
|
||||
|
||||
// Are we dripping or splattering?
|
||||
var/list/drips = list()
|
||||
// Only a certain number of drips (or one large splatter) can be on a given turf.
|
||||
@@ -312,6 +391,10 @@ proc/blood_splatter(var/target,var/datum/reagent/blood/source,var/large)
|
||||
B.basecolor = source.data["blood_colour"]
|
||||
B.update_icon()
|
||||
|
||||
if(spray_dir)
|
||||
B.icon_state = "squirt"
|
||||
B.dir = spray_dir
|
||||
|
||||
// Update blood information.
|
||||
if(source.data["blood_DNA"])
|
||||
B.blood_DNA = list()
|
||||
|
||||
@@ -51,7 +51,10 @@
|
||||
var/encased // Needs to be opened with a saw to access the organs.
|
||||
var/list/implants = list()
|
||||
var/wound_update_accuracy = 1 // how often wounds should be updated, a higher number means less often
|
||||
var/has_tendon = FALSE //Does this limb have a tendon?
|
||||
var/joint = "joint" // Descriptive string used in dislocation.
|
||||
var/artery_name = "artery" //Name of the artery. Cartoid, etc.
|
||||
var/tendon_name = "tendon" //Name of the limb's tendon. Achilles heel, etc.
|
||||
var/amputation_point // Descriptive string used in amputation.
|
||||
var/dislocated = 0 // If you target a joint, you can dislocate the limb, causing temporary damage to the organ.
|
||||
var/can_grasp //It would be more appropriate if these two were named "affects_grasp" and "affects_stand" at this point
|
||||
@@ -64,6 +67,8 @@
|
||||
var/maim_bonus = 0.75 //For special projectile gibbing calculation, dubbed "maiming"
|
||||
var/can_be_maimed = TRUE //Can this limb be 'maimed'?
|
||||
|
||||
var/atom/movable/applied_pressure //Pressure applied to wounds. It'll make them bleed less, generally.
|
||||
|
||||
/obj/item/organ/external/proc/invalidate_marking_cache()
|
||||
cached_markings = null
|
||||
|
||||
@@ -79,6 +84,8 @@
|
||||
for(var/obj/item/organ/O in internal_organs)
|
||||
qdel(O)
|
||||
|
||||
applied_pressure = null
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/item/organ/external/attack_self(var/mob/user)
|
||||
@@ -401,10 +408,14 @@ This function completely restores a damaged organ to perfect condition.
|
||||
//moved this before the open_wound check so that having many small wounds for example doesn't somehow protect you from taking internal damage (because of the return)
|
||||
//Possibly trigger an internal wound, too.
|
||||
var/local_damage = brute_dam + burn_dam + damage
|
||||
if(damage > 15 && type != BURN && local_damage > 30 && prob(damage) && !(status & ORGAN_ROBOT))
|
||||
var/datum/wound/internal_bleeding/I = new (min(damage - 15, 15))
|
||||
wounds += I
|
||||
owner.custom_pain("You feel something rip in your [name]!", 1)
|
||||
if(damage > 15 && type != BURN && local_damage > 30 && !(status & ORGAN_ROBOT))
|
||||
var/internal_damage
|
||||
if(prob(damage) && sever_artery())
|
||||
internal_damage = TRUE
|
||||
if(prob(Ceiling(damage / 4)) && type == CUT && sever_tendon())
|
||||
internal_damage = TRUE
|
||||
if(internal_damage)
|
||||
owner.custom_pain("You feel something rip in your [name]!", 25)
|
||||
|
||||
// first check whether we can widen an existing wound
|
||||
if(wounds.len > 0 && prob(max(50+(number_wounds-1)*10,90)))
|
||||
@@ -631,18 +642,6 @@ Note that amputating the affected organ does in fact remove the infection from t
|
||||
if (W.damage > 0)
|
||||
updatehud = 1//If there are any wounds with damage to heal, then we'll update health huds
|
||||
|
||||
// Internal wounds get worse over time. Low temperatures (cryo) stop them.
|
||||
if(W.damage && W.internal && owner.bodytemperature >= 170)
|
||||
var/bicardose = owner.reagents.get_reagent_amount("bicaridine")
|
||||
var/inaprovaline = owner.reagents.get_reagent_amount("inaprovaline")
|
||||
if(!(W.can_autoheal() || (bicardose && inaprovaline))) //bicaridine and inaprovaline stop internal wounds from growing bigger with time, unless it is so small that it is already healing
|
||||
W.open_wound(0.09 * wound_update_accuracy)
|
||||
|
||||
if(!owner.reagents.has_reagent("coagulant", 2))
|
||||
owner.vessel.remove_reagent("blood", wound_update_accuracy * W.damage/40) //line should possibly be moved to handle_blood, so all the bleeding stuff is in one place.
|
||||
if(prob(1 * wound_update_accuracy))
|
||||
owner.custom_pain("You feel a stabbing pain in your [name]!",1)
|
||||
|
||||
// slow healing
|
||||
var/heal_amt = 0
|
||||
|
||||
@@ -687,11 +686,10 @@ Note that amputating the affected organ does in fact remove the infection from t
|
||||
|
||||
//update damage counts
|
||||
for(var/datum/wound/W in wounds)
|
||||
if(!W.internal) //so IB doesn't count towards crit/paincrit
|
||||
if(W.damage_type == BURN)
|
||||
burn_dam += W.damage
|
||||
else
|
||||
brute_dam += W.damage
|
||||
if(W.damage_type == BURN)
|
||||
burn_dam += W.damage
|
||||
else
|
||||
brute_dam += W.damage
|
||||
|
||||
if(!(status & ORGAN_ROBOT) && W.bleeding() && (H && !(H.species.flags & NO_BLOOD)))
|
||||
W.bleed_timer--
|
||||
@@ -870,7 +868,6 @@ Note that amputating the affected organ does in fact remove the infection from t
|
||||
// checks if all wounds on the organ are bandaged
|
||||
/obj/item/organ/external/proc/is_bandaged()
|
||||
for(var/datum/wound/W in wounds)
|
||||
if(W.internal) continue
|
||||
if(!W.bandaged)
|
||||
return 0
|
||||
return 1
|
||||
@@ -878,7 +875,6 @@ Note that amputating the affected organ does in fact remove the infection from t
|
||||
// checks if all wounds on the organ are salved
|
||||
/obj/item/organ/external/proc/is_salved()
|
||||
for(var/datum/wound/W in wounds)
|
||||
if(W.internal) continue
|
||||
if(!W.salved)
|
||||
return 0
|
||||
return 1
|
||||
@@ -886,7 +882,6 @@ Note that amputating the affected organ does in fact remove the infection from t
|
||||
// checks if all wounds on the organ are disinfected
|
||||
/obj/item/organ/external/proc/is_disinfected()
|
||||
for(var/datum/wound/W in wounds)
|
||||
if(W.internal) continue
|
||||
if(!W.disinfected)
|
||||
return 0
|
||||
return 1
|
||||
@@ -895,7 +890,6 @@ Note that amputating the affected organ does in fact remove the infection from t
|
||||
var/rval = 0
|
||||
status &= ~ORGAN_BLEEDING
|
||||
for(var/datum/wound/W in wounds)
|
||||
if(W.internal) continue
|
||||
rval |= !W.bandaged
|
||||
W.bandaged = 1
|
||||
return rval
|
||||
@@ -910,7 +904,6 @@ Note that amputating the affected organ does in fact remove the infection from t
|
||||
/obj/item/organ/external/proc/disinfect()
|
||||
var/rval = 0
|
||||
for(var/datum/wound/W in wounds)
|
||||
if(W.internal) continue
|
||||
rval |= !W.disinfected
|
||||
W.disinfected = 1
|
||||
W.germ_level = 0
|
||||
@@ -920,7 +913,6 @@ Note that amputating the affected organ does in fact remove the infection from t
|
||||
var/rval = 0
|
||||
src.status &= ~ORGAN_BLEEDING
|
||||
for(var/datum/wound/W in wounds)
|
||||
if(W.internal) continue
|
||||
rval |= !W.clamped
|
||||
W.clamped = 1
|
||||
return rval
|
||||
@@ -1020,7 +1012,7 @@ Note that amputating the affected organ does in fact remove the infection from t
|
||||
return 0
|
||||
|
||||
/obj/item/organ/external/proc/is_usable()
|
||||
return !is_dislocated() && !(status & (ORGAN_MUTATED|ORGAN_DEAD))
|
||||
return !is_dislocated() && !(status & (ORGAN_MUTATED|ORGAN_DEAD)) && !(status & ORGAN_TENDON_CUT)
|
||||
|
||||
/obj/item/organ/external/proc/is_malfunctioning()
|
||||
return ((status & ORGAN_ROBOT) && (brute_dam + burn_dam) >= 10 && prob(brute_dam + burn_dam))
|
||||
@@ -1139,7 +1131,6 @@ Note that amputating the affected organ does in fact remove the infection from t
|
||||
else if (open)
|
||||
wound_descriptors["an incision"] = 1
|
||||
for(var/datum/wound/W in wounds)
|
||||
if(W.internal && !open) continue // can't see internal wounds
|
||||
var/this_wound_desc = W.desc
|
||||
if(W.damage_type == BURN && W.salved) this_wound_desc = "salved [this_wound_desc]"
|
||||
if(W.bleeding()) this_wound_desc = "bleeding [this_wound_desc]"
|
||||
@@ -1182,3 +1173,18 @@ Note that amputating the affected organ does in fact remove the infection from t
|
||||
if(6 to INFINITY)
|
||||
flavor_text += "a ton of [wound]\s"
|
||||
return english_list(flavor_text)
|
||||
|
||||
/obj/item/organ/external/proc/sever_artery()
|
||||
if((status & ORGAN_ROBOT) || (status & ORGAN_ARTERY_CUT) || !species || species.flags & NO_BLOOD || species.flags & NO_ARTERIES)
|
||||
return FALSE
|
||||
else
|
||||
status |= ORGAN_ARTERY_CUT
|
||||
return TRUE
|
||||
|
||||
/obj/item/organ/external/proc/sever_tendon()
|
||||
if(!has_tendon || (status & ORGAN_ROBOT) || (status & ORGAN_TENDON_CUT) || species.flags & NO_TENDONS)
|
||||
return FALSE
|
||||
else
|
||||
status |= ORGAN_TENDON_CUT
|
||||
return TRUE
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
vital = 1
|
||||
amputation_point = "spine"
|
||||
joint = "neck"
|
||||
artery_name = "internal thoracic artery"
|
||||
dislocated = -1
|
||||
gendered_icon = 1
|
||||
cannot_amputate = 1
|
||||
@@ -32,6 +33,7 @@
|
||||
parent_organ = BP_CHEST
|
||||
amputation_point = "lumbar"
|
||||
joint = "hip"
|
||||
artery_name = "iliac artery"
|
||||
dislocated = -1
|
||||
gendered_icon = 1
|
||||
maim_bonus = 0.25
|
||||
@@ -46,6 +48,9 @@
|
||||
body_part = ARM_LEFT
|
||||
parent_organ = BP_CHEST
|
||||
joint = "left elbow"
|
||||
has_tendon = TRUE
|
||||
tendon_name = "palmaris longus tendon"
|
||||
artery_name = "basilic vein"
|
||||
amputation_point = "left shoulder"
|
||||
can_grasp = 1
|
||||
|
||||
@@ -55,6 +60,9 @@
|
||||
icon_name = "r_arm"
|
||||
body_part = ARM_RIGHT
|
||||
joint = "right elbow"
|
||||
has_tendon = TRUE
|
||||
tendon_name = "cruciate ligament"
|
||||
artery_name = "brachial artery"
|
||||
amputation_point = "right shoulder"
|
||||
|
||||
/obj/item/organ/external/leg
|
||||
@@ -68,6 +76,9 @@
|
||||
icon_position = LEFT
|
||||
parent_organ = BP_GROIN
|
||||
joint = "left knee"
|
||||
has_tendon = TRUE
|
||||
tendon_name = "quadriceps tendon"
|
||||
artery_name = "femoral artery"
|
||||
amputation_point = "left hip"
|
||||
can_stand = 1
|
||||
|
||||
@@ -120,6 +131,8 @@
|
||||
body_part = HAND_LEFT
|
||||
parent_organ = BP_L_ARM
|
||||
joint = "left wrist"
|
||||
has_tendon = TRUE
|
||||
tendon_name = "carpal ligament"
|
||||
amputation_point = "left wrist"
|
||||
can_grasp = 1
|
||||
maim_bonus = 1
|
||||
@@ -152,6 +165,7 @@
|
||||
vital = 1
|
||||
parent_organ = BP_CHEST
|
||||
joint = "jaw"
|
||||
artery_name = "cartoid artery"
|
||||
amputation_point = "neck"
|
||||
gendered_icon = 1
|
||||
encased = "skull"
|
||||
@@ -187,4 +201,4 @@
|
||||
/obj/item/organ/external/head/undislocate()
|
||||
. = ..()
|
||||
if(owner)
|
||||
owner.brokejaw = 0
|
||||
owner.brokejaw = 0
|
||||
|
||||
@@ -36,8 +36,6 @@
|
||||
|
||||
// stages such as "cut", "deep cut", etc.
|
||||
var/list/stages
|
||||
// internal wounds can only be fixed through surgery
|
||||
var/internal = 0
|
||||
// maximum stage at which bleeding should still happen. Beyond this stage bleeding is prevented.
|
||||
var/max_bleeding_stage = 0
|
||||
// one of CUT, BRUISE, PIERCE , BURN
|
||||
@@ -157,10 +155,6 @@
|
||||
// than what needed to be healed, return how much heal was left
|
||||
// set @heals_internal to also heal internal organ damage
|
||||
/datum/wound/proc/heal_damage(amount, heals_internal = 0)
|
||||
if(src.internal && !heals_internal)
|
||||
// heal nothing
|
||||
return amount
|
||||
|
||||
var/healed_damage = min(src.damage, amount)
|
||||
amount -= healed_damage
|
||||
src.damage -= healed_damage
|
||||
@@ -170,16 +164,6 @@
|
||||
desc = desc_list[current_stage]
|
||||
src.min_damage = damage_list[current_stage]
|
||||
|
||||
//Internal wounds should vanish if damage reaches 0
|
||||
if (internal && damage <= 0)
|
||||
//Wounds can't clean themselves up. Instead we'll set vars that will make the organ delete us
|
||||
internal = 0
|
||||
bleed_timer = 0
|
||||
damage = 0
|
||||
created = -6000//Wounds only disappear after 10 mins
|
||||
//These vars will cause this wound to be removed and GC'd next tick
|
||||
|
||||
|
||||
// return amount of healing still leftover, can be used for other wounds
|
||||
return amount
|
||||
|
||||
@@ -213,9 +197,6 @@
|
||||
return 1
|
||||
|
||||
/datum/wound/proc/bleeding()
|
||||
if (src.internal)
|
||||
return 0 // internal wounds don't bleed in the sense of this function
|
||||
|
||||
if (current_stage > max_bleeding_stage)
|
||||
return 0
|
||||
|
||||
@@ -373,13 +354,6 @@ datum/wound/puncture/massive
|
||||
/datum/wound/burn/carbonised
|
||||
stages = list("carbonised area" = 50, "healing carbonised area" = 20, "massive burn scar" = 0)
|
||||
|
||||
/** INTERNAL BLEEDING **/
|
||||
/datum/wound/internal_bleeding
|
||||
internal = 1
|
||||
stages = list("severed artery" = 30, "cut artery" = 20, "damaged artery" = 10, "bruised artery" = 5)
|
||||
autoheal_cutoff = 5
|
||||
max_bleeding_stage = 4 //all stages bleed. It's called internal bleeding after all.
|
||||
|
||||
/** EXTERNAL ORGAN LOSS **/
|
||||
/datum/wound/lost_limb
|
||||
|
||||
|
||||
Reference in New Issue
Block a user