mirror of
https://github.com/vgstation-coders/vgstation13.git
synced 2025-12-10 02:16:05 +00:00
311 lines
8.3 KiB
Plaintext
311 lines
8.3 KiB
Plaintext
|
|
/****************************************************
|
|
WOUNDS
|
|
****************************************************/
|
|
/datum/wound
|
|
// stages such as "cut", "deep cut", etc.
|
|
var/list/stages
|
|
// number representing the current stage
|
|
var/current_stage = 0
|
|
|
|
// description of the wound
|
|
var/desc = ""
|
|
|
|
// amount of damage this wound causes
|
|
var/damage = 0
|
|
// ticks of bleeding left.
|
|
var/bleed_timer = 0
|
|
// amount of damage the current wound type requires(less means we need to apply the next healing stage)
|
|
var/min_damage = 0
|
|
|
|
// one of CUT, BRUISE, BURN
|
|
var/damage_type = CUT
|
|
|
|
// whether this wound needs a bandage/salve to heal at all
|
|
var/needs_treatment = 0
|
|
|
|
// is the wound bandaged?
|
|
var/tmp/bandaged = 0
|
|
// Similar to bandaged, but works differently
|
|
var/tmp/clamped = 0
|
|
// is the wound salved?
|
|
var/tmp/salved = 0
|
|
// is the wound disinfected?
|
|
var/tmp/disinfected = 0
|
|
var/tmp/created = 0
|
|
|
|
// number of wounds of this type
|
|
var/tmp/amount = 1
|
|
|
|
// maximum stage at which bleeding should still happen, counted from the right rather than the left of the list
|
|
// 1 means all stages except the last should bleed
|
|
var/max_bleeding_stage = 1
|
|
|
|
// internal wounds can only be fixed through surgery
|
|
var/internal = 0
|
|
|
|
// amount of germs in the wound
|
|
var/germ_level = 0
|
|
|
|
// helper lists
|
|
var/tmp/list/desc_list = list()
|
|
var/tmp/list/damage_list = list()
|
|
|
|
/datum/wound/New(var/damage)
|
|
|
|
created = world.time
|
|
|
|
// reading from a list("stage" = damage) is pretty difficult, so build two separate
|
|
// lists from them instead
|
|
for(var/V in stages)
|
|
desc_list += V
|
|
damage_list += stages[V]
|
|
|
|
src.damage = damage
|
|
|
|
// initialize with the first stage
|
|
next_stage()
|
|
|
|
// this will ensure the size of the wound matches the damage
|
|
src.heal_damage(0)
|
|
|
|
// make the max_bleeding_stage count from the end of the list rather than the start
|
|
// this is more robust to changes to the list
|
|
max_bleeding_stage = src.desc_list.len - max_bleeding_stage
|
|
|
|
bleed_timer += damage / BLOODLOSS_SPEED_MULTIPLIER
|
|
|
|
// returns 1 if there's a next stage, 0 otherwise
|
|
/datum/wound/proc/next_stage()
|
|
if(current_stage + 1 > src.desc_list.len)
|
|
return 0
|
|
|
|
current_stage++
|
|
|
|
src.min_damage = damage_list[current_stage]
|
|
src.desc = desc_list[current_stage]
|
|
return 1
|
|
|
|
// returns 1 if the wound has started healing
|
|
/datum/wound/proc/started_healing()
|
|
return (current_stage > 1)
|
|
|
|
// checks whether the wound has been appropriately treated
|
|
// always returns 1 for wounds that don't need to be treated
|
|
/datum/wound/proc/is_treated()
|
|
if(!needs_treatment)
|
|
return 1
|
|
|
|
if(damage_type == BRUISE || damage_type == CUT)
|
|
return bandaged
|
|
else if(damage_type == BURN)
|
|
return salved
|
|
|
|
// checks if wound is considered open for external infections
|
|
// untreated cuts (and bleeding bruises) and burns are possibly infectable, chance higher if wound is bigger
|
|
/datum/wound/proc/can_infect()
|
|
if (is_treated() && damage < 10)
|
|
return 0
|
|
if (disinfected)
|
|
return 0
|
|
var/dam_coef = round(damage/10)
|
|
switch (damage_type)
|
|
if (BRUISE)
|
|
return prob(dam_coef*5) && bleeding() //bruises only infectable if bleeding
|
|
if (BURN)
|
|
return prob(dam_coef*10)
|
|
if (CUT)
|
|
return prob(dam_coef*20)
|
|
|
|
return 0
|
|
// heal the given amount of damage, and if the given amount of damage was more
|
|
// than what needed to be healed, return how much heal was left
|
|
// set @heals_internal to also heal internal organ damage
|
|
|
|
/datum/wound/proc/infection_check()
|
|
if (damage < 10)
|
|
return 0
|
|
if (is_treated() && damage < 25)
|
|
return 0
|
|
if (disinfected)
|
|
germ_level = 0
|
|
return 0
|
|
|
|
if(damage_type == BRUISE && !bleeding())
|
|
return 0
|
|
|
|
var/dam_coef = round(damage/10)
|
|
switch (damage_type)
|
|
if (BRUISE)
|
|
return prob(dam_coef*5)
|
|
if (BURN)
|
|
return prob(dam_coef*10)
|
|
if (CUT)
|
|
return prob(dam_coef*20)
|
|
|
|
return 0
|
|
|
|
/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
|
|
|
|
while(src.damage / src.amount < damage_list[current_stage] && current_stage < src.desc_list.len)
|
|
current_stage++
|
|
desc = desc_list[current_stage]
|
|
src.min_damage = damage_list[current_stage]
|
|
|
|
// return amount of healing still leftover, can be used for other wounds
|
|
return amount
|
|
|
|
// opens the wound again
|
|
/datum/wound/proc/open_wound(damage)
|
|
src.damage += damage
|
|
bleed_timer += damage / BLOODLOSS_SPEED_MULTIPLIER
|
|
|
|
while(src.current_stage > 1 && src.damage_list[current_stage-1] <= src.damage)
|
|
src.current_stage--
|
|
|
|
src.desc = desc_list[current_stage]
|
|
src.min_damage = damage_list[current_stage]
|
|
|
|
/datum/wound/proc/bleeding()
|
|
// internal wounds don't bleed in the sense of this function
|
|
return ((damage > 30 || bleed_timer > 0) && !(bandaged||clamped) && (damage_type == BRUISE && damage >= 20 || damage_type == CUT && damage >= 5) && current_stage <= max_bleeding_stage && !src.internal)
|
|
|
|
/** CUTS **/
|
|
/datum/wound/cut/small
|
|
// link wound descriptions to amounts of damage
|
|
max_bleeding_stage = 2
|
|
stages = list("ugly ripped cut" = 20, "ripped cut" = 10, "cut" = 5, "healing cut" = 2, "small scab" = 0)
|
|
|
|
/datum/wound/cut/deep
|
|
max_bleeding_stage = 3
|
|
stages = list("ugly deep ripped cut" = 25, "deep ripped cut" = 20, "deep cut" = 15, "clotted cut" = 8, "scab" = 2, "fresh skin" = 0)
|
|
|
|
/datum/wound/cut/flesh
|
|
max_bleeding_stage = 3
|
|
stages = list("ugly ripped flesh wound" = 35, "ugly flesh wound" = 30, "flesh wound" = 25, "blood soaked clot" = 15, "large scab" = 5, "fresh skin" = 0)
|
|
|
|
/datum/wound/cut/gaping
|
|
max_bleeding_stage = 2
|
|
stages = list("gaping wound" = 50, "large blood soaked clot" = 25, "large clot" = 15, "small angry scar" = 5, \
|
|
"small straight scar" = 0)
|
|
|
|
/datum/wound/cut/gaping_big
|
|
max_bleeding_stage = 2
|
|
stages = list("big gaping wound" = 60, "healing gaping wound" = 40, "large angry scar" = 10, "large straight scar" = 0)
|
|
|
|
needs_treatment = 1 // this only heals when bandaged
|
|
|
|
/datum/wound/cut/massive
|
|
max_bleeding_stage = 2
|
|
stages = list("massive wound" = 70, "massive healing wound" = 50, "massive angry scar" = 10, "massive jagged scar" = 0)
|
|
|
|
needs_treatment = 1 // this only heals when bandaged
|
|
|
|
/** BRUISES **/
|
|
/datum/wound/bruise
|
|
stages = list("monumental bruise" = 80, "huge bruise" = 50, "large bruise" = 30,\
|
|
"moderate bruise" = 20, "small bruise" = 10, "tiny bruise" = 5)
|
|
|
|
needs_treatment = 1 // this only heals when bandaged
|
|
damage_type = BRUISE
|
|
|
|
/datum/wound/bruise/monumental
|
|
|
|
// implement sub-paths by starting at a later stage
|
|
|
|
/datum/wound/bruise/tiny
|
|
current_stage = 5
|
|
needs_treatment = 0
|
|
|
|
/datum/wound/bruise/small
|
|
current_stage = 4
|
|
needs_treatment = 0
|
|
|
|
/datum/wound/bruise/moderate
|
|
current_stage = 3
|
|
needs_treatment = 0
|
|
|
|
/datum/wound/bruise/large
|
|
current_stage = 2
|
|
|
|
/datum/wound/bruise/huge
|
|
current_stage = 1
|
|
|
|
/** BURNS **/
|
|
/datum/wound/burn/moderate
|
|
stages = list("ripped burn" = 10, "moderate burn" = 5, "moderate salved burn" = 2, "fresh skin" = 0)
|
|
|
|
needs_treatment = 1 // this only heals when bandaged
|
|
|
|
damage_type = BURN
|
|
|
|
/datum/wound/burn/large
|
|
stages = list("ripped large burn" = 20, "large burn" = 15, "large salved burn" = 5, "fresh skin" = 0)
|
|
|
|
needs_treatment = 1 // this only heals when bandaged
|
|
|
|
damage_type = BURN
|
|
|
|
/datum/wound/burn/severe
|
|
stages = list("ripped severe burn" = 35, "severe burn" = 30, "severe salved burn" = 10, "burn scar" = 0)
|
|
|
|
needs_treatment = 1 // this only heals when bandaged
|
|
|
|
damage_type = BURN
|
|
|
|
/datum/wound/burn/deep
|
|
stages = list("ripped deep burn" = 45, "deep burn" = 40, "deep salved burn" = 15, "large burn scar" = 0)
|
|
|
|
needs_treatment = 1 // this only heals when bandaged
|
|
|
|
damage_type = BURN
|
|
|
|
|
|
/datum/wound/burn/carbonised
|
|
stages = list("carbonised area" = 50, "treated carbonised area" = 20, "massive burn scar" = 0)
|
|
|
|
needs_treatment = 1 // this only heals when bandaged
|
|
|
|
damage_type = BURN
|
|
|
|
/datum/wound/internal_bleeding
|
|
internal = 1
|
|
|
|
stages = list("severed vein" = 30, "cut vein" = 20, "damaged vein" = 10, "bruised vein" = 5)
|
|
max_bleeding_stage = 0
|
|
|
|
needs_treatment = 1
|
|
|
|
#undef BLOODLOSS_SPEED_MULTIPLIER
|
|
|
|
/datum/wound/send_to_past(var/duration)
|
|
var/static/list/resettable_vars = list(
|
|
"stages",
|
|
"current_stage",
|
|
"desc",
|
|
"damage",
|
|
"bleed_timer",
|
|
"min_damage",
|
|
"damage_type",
|
|
"needs_treatment",
|
|
"bandaged",
|
|
"clamped",
|
|
"salved",
|
|
"disinfected",
|
|
"created",
|
|
"amount",
|
|
"max_bleeding_stage",
|
|
"internal",
|
|
"germ_level",
|
|
"desc_list",
|
|
"damage_list")
|
|
|
|
reset_vars_after_duration(resettable_vars, duration, TRUE)
|