Files
vgstation13/code/modules/organs/wound.dm
2021-10-18 16:28:55 -05:00

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)