diff --git a/code/game/objects/items/weapons/medical.dm b/code/game/objects/items/weapons/medical.dm
index 5752ef8601a..5ad5aec0d25 100644
--- a/code/game/objects/items/weapons/medical.dm
+++ b/code/game/objects/items/weapons/medical.dm
@@ -118,10 +118,18 @@ MEDICAL
if (!ointment && (affecting.status & BLEEDING))
affecting.status &= ~BLEEDING
- if (affecting.heal_damage(src.heal_brute, src.heal_burn))
- H.UpdateDamageIcon()
+ if(ointment)
+ for(var/datum/wound/W in affecting.wounds)
+ W.salved = 1
else
- H.UpdateDamage()
+ for(var/datum/wound/W in affecting.wounds)
+ W.bandaged = 1
+
+ // Don't do direct healing
+ //if (affecting.heal_damage(src.heal_brute, src.heal_burn))
+ // H.UpdateDamageIcon()
+ //else
+ H.UpdateDamage()
M.updatehealth()
diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm
index 4c1413ba5ef..110bb3a3073 100644
--- a/code/modules/mob/living/carbon/human/examine.dm
+++ b/code/modules/mob/living/carbon/human/examine.dm
@@ -223,23 +223,12 @@
msg += ""
-/* if (src.getBruteLoss())
- if (src.getBruteLoss() < 30)
- usr << "\red [src.name] looks slightly injured!"
- else
- usr << "\red [src.name] looks severely injured!"*/
-
if (src.cloneloss)
if (src.cloneloss < 30)
msg += "[t_He] looks slightly... unfinished?\n"
else
msg += "[t_He] looks very... unfinished?\n"
-/* if (src.getFireLoss())
- if (src.getFireLoss() < 30)
- usr << "\red [src.name] looks slightly burned!"
- else
- usr << "\red [src.name] looks severely burned!"*/
msg += ""
if (src.nutrition < 100)
msg += "[t_He] [t_is] severely malnourished.\n"
@@ -290,14 +279,13 @@
if(21 to INFINITY)
wound_flavor_text["[temp.display_name]"] += pick(" a lot of burns"," severe melting")
wound_flavor_text["[temp.display_name]"] += "!\n"
- else if(temp.wound_descs.len)
+ else if(temp.wounds.len)
var/list/wound_descriptors = list()
- for(var/time in temp.wound_descs)
- for(var/wound in temp.wound_descs[time])
- if(wound in wound_descriptors)
- wound_descriptors[wound]++
- continue
- wound_descriptors[wound] = 1
+ for(var/datum/wound/W in temp.wounds)
+ if(W.desc in wound_descriptors)
+ wound_descriptors[W.desc]++
+ continue
+ wound_descriptors[W.desc] = 1
var/list/flavor_text = list()
var/list/no_exclude = list("gaping wound", "big gaping wound", "massive wound", "large bruise",\
"huge bruise", "massive bruise", "severe burn", "large burn", "deep burn", "carbonised area")
diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm
index 1d6f37e8a8a..a1b18596ede 100644
--- a/code/modules/mob/living/carbon/human/life.dm
+++ b/code/modules/mob/living/carbon/human/life.dm
@@ -971,7 +971,12 @@
break
//At this point, we dun care which blood we are adding to, as long as they get more blood.
- B.volume = max(min(B.volume + 560/blood_volume,560), 0) //Less blood = More blood generated per tick
+ var/blood_regen = 0.5
+ if(B.volume < 400)
+ blood_regen = 1
+ if(B.volume < 200)
+ blood_regen = 1.5
+ B.volume = max(min(B.volume + blood_regen,560), 0) //Less blood = More blood generated per tick
if(blood_volume > 448)
if(pale)
diff --git a/code/modules/mob/living/carbon/monkey/examine.dm b/code/modules/mob/living/carbon/monkey/examine.dm
index 5ab18f0a61e..0d0eec8a4f4 100644
--- a/code/modules/mob/living/carbon/monkey/examine.dm
+++ b/code/modules/mob/living/carbon/monkey/examine.dm
@@ -50,14 +50,13 @@
if(21 to INFINITY)
wound_flavor_text["[temp.display_name]"] += pick(" a lot of burns"," severe melting")
wound_flavor_text["[temp.display_name]"] += "!\n"
- else if(temp.wound_descs)
+ else if(temp.wounds.len)
var/list/wound_descriptors = list()
- for(var/time in temp.wound_descs)
- for(var/wound in temp.wound_descs[time])
- if(wound in wound_descriptors)
- wound_descriptors[wound]++
- continue
- wound_descriptors[wound] = 1
+ for(var/datum/wound/W in temp.wounds)
+ if(W.desc in wound_descriptors)
+ wound_descriptors[W.desc]++
+ continue
+ wound_descriptors[W.desc] = 1
var/list/flavor_text = list()
var/list/no_exclude = list("gaping wound", "big gaping wound", "massive wound", "large bruise",\
"huge bruise", "massive bruise", "severe burn", "large burn", "deep burn", "carbonised area")
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index 5f0ad20254e..0a68f7523e8 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -184,7 +184,7 @@
affecting.status &= ~BROKEN
affecting.status &= ~SPLINTED
affecting.status &= ~DESTROYED
- del affecting.wound_descs
+ affecting.wounds.Cut()
H.UpdateDamageIcon()
H.update_body()
//src.fireloss = 0
@@ -218,7 +218,7 @@
e.status &= ~DESTROYED
e.perma_injury = 0
e.update_icon()
- del e.wound_descs
+ e.wounds.Cut()
del(H.vessel)
H.vessel = new/datum/reagents(560)
H.vessel.my_atom = H
diff --git a/code/modules/mob/organ/organ.dm b/code/modules/mob/organ/organ.dm
index 3d9844c625b..7beb047b609 100644
--- a/code/modules/mob/organ/organ.dm
+++ b/code/modules/mob/organ/organ.dm
@@ -2,43 +2,6 @@
//CONTAINS: ORGANS AND WOUNDS//
///////////////////////////////
-var/list/wound_progressions = list(
-//cut healing path"
-"cut" = "healing cut", "healing cut" = "small scab",\
-
-//deep cut healing path
-"deep cut" = "clotted cut", "clotted cut" = "scab", "scab" = "fresh skin",\
-
-//flesh wound healing path
-"flesh wound" = "blood soaked clot", "blood soaked clot" = "large scab", "large scab" = "fresh skin",\
-
-//gaping wound healing path
-"gaping wound" = "large blood soaked clot", "large blood soaked clot" = "large clot", "large clot" = "small angry scar",\
-"small angry scar" = "small straight scar",\
-
-//big gaping wound healing path
-"big gaping wound" = "gauze wrapped wound", "gauze wrapped wound" = "blood soaked bandage", "blood soaked bandage" = "large angry scar",\
-"large angry scar" = "large straight scar",\
-
-//massive wound healing path
-"massive wound" = "massive blood soaked bandage", "massive blood soaked bandage" = "huge bloody mess", "huge bloody mess" = "massive angry scar",\
-"massive angry scar" = "massive jagged scar",\
-
-//bruise healing path
-"monumental bruise" = "large bruise", "huge bruise" = "large bruise", "large bruise" = "moderate bruise",\
-"moderate bruise" = "small bruise", "small bruise" = "tiny bruise",\
-
-//moderate burn healing path
-"moderate burn" = "moderate salved burn", "moderate salved burn" = "fresh skin",\
-
-"large burn" = "large salved burn", "large salved burn" = "moderate salved burn",\
-
-"severe burn" = "severe salved burn", "severe salved burn" = "burn scar",\
-
-"deep burn" = "deep salved burn", "deep salved burn" = "large burn scar",\
-
-"carbonised area" = "treated carbonised area", "treated carbonised area" = "massive burn scar")
-
/datum/organ
var/name = "organ"
var/mob/living/carbon/human/owner = null
@@ -69,11 +32,196 @@ var/list/wound_progressions = list(
W.hits = hits
W.time_inflicted = time_inflicted
return W
-/* fuckign double defines
-#define CUT 0
-#define BRUISE 1
-#define BURN 2
-*/
+
+/****************************************************
+ 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
+
+ // amount of damage the current wound type requires(less means we need to apply the next healing stage)
+ var/min_damage = 0
+
+ // one of CUTE, BRUISE, BURN
+ var/damage_type = BRUTE
+
+ // whether this wound needs a bandage/salve to heal at all
+ var/needs_treatment = 0
+
+ // is the wound bleeding?
+ var/tmp/bleeding = 0
+ // is the wound bandaged?
+ var/tmp/bandaged = 0
+ // is the wound salved?
+ var/tmp/salved = 0
+ // is the wound disinfected?
+ var/tmp/disinfected = 0
+
+ // helper lists
+ var/tmp/list/desc_list = list()
+ var/tmp/list/damage_list = list()
+ New(var/damage)
+
+ // 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]
+
+ // initialize with the first stage
+ next_stage()
+
+ // this will ensure the size of the wound matches the damage
+ src.heal_damage(0)
+
+ // returns 1 if there's a next stage, 0 otherwise
+ 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
+ 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
+ proc/is_treated()
+ if(!needs_treatment) return 1
+
+ if(damage_type == BRUISE || damage_type == CUT)
+ return bandaged
+ else if(damage_type == BURN)
+ return salved
+
+ // 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
+ proc/heal_damage(amount)
+ var/healed_damage = min(src.damage, amount)
+ amount -= healed_damage
+ src.damage -= healed_damage
+
+ while(src.damage > damage[current_stage] && current_stage < src.desc_list.len)
+ current_stage++
+ desc = desc_list[current_stage]
+
+ // return amount of healing still leftover, can be used for other wounds
+ return amount
+
+ // opens the wound again
+ proc/open_wound()
+ if(current_stage > 1)
+ // e.g. current_stage is 2, then reset it to 0 and do next_stage(), bringing it to 1
+ current_stage -= 2
+ next_stage()
+
+/** CUTS **/
+/datum/wound/cut
+ // link wound descriptions to amounts of damage
+ stages = list("cut" = 5, "healing cut" = 2, "small scab" = 0)
+
+/datum/wound/deep_cut
+ stages = list("deep cut" = 15, "clotted cut" = 8, "scab" = 2, "fresh skin" = 0)
+
+/datum/wound/flesh_wound
+ stages = list("flesh wound" = 25, "blood soaked clot" = 15, "large scab" = 5, "fresh skin" = 0)
+
+/datum/wound/gaping_wound
+ stages = list("gaping wound" = 50, "large blood soaked clot" = 25, "large clot" = 15, "small angry scar" = 5, \
+ "small straight scar" = 0)
+
+/datum/wound/big_gaping_wound
+ stages = list("big gaping wound" = 60, "gauze wrapped wound" = 50, "blood soaked bandage" = 25,\
+ "large angry scar" = 10, "large straight scar" = 0)
+
+ needs_treatment = 1 // this only heals when bandaged
+
+/datum/wound/massive_wound
+ stages = list("massive wound" = 70, "massive blood soaked bandage" = 40, "huge bloody mess" = 20,\
+ "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_bruise
+
+// implement sub-paths by starting at a later stage
+/datum/wound/bruise/huge_bruise
+ current_stage = 1
+
+/datum/wound/bruise/large_bruise
+ current_stage = 2
+
+/datum/wound/bruise/moderate_bruise
+ current_stage = 3
+ needs_treatment = 0
+
+/datum/wound/bruise/small_bruise
+ current_stage = 4
+ needs_treatment = 0
+
+/datum/wound/bruise/tiny_bruise
+ current_stage = 5
+ needs_treatment = 0
+
+/** BURNS **/
+/datum/wound/moderate_burn
+ stages = list("moderate burn" = 5, "moderate salved burn" = 2, "fresh skin" = 0)
+
+ needs_treatment = 1 // this only heals when bandaged
+
+ damage_type = BURN
+
+/datum/wound/large_burn
+ stages = list("large burn" = 15, "large salved burn" = 5, "fresh skin" = 0)
+
+ needs_treatment = 1 // this only heals when bandaged
+
+ damage_type = BURN
+
+/datum/wound/severe_burn
+ stages = list("severe burn" = 30, "severe salved burn" = 10, "burn scar" = 0)
+
+ needs_treatment = 1 // this only heals when bandaged
+
+ damage_type = BURN
+
+/datum/wound/deep_burn
+ stages = list("deep burn" = 40, "deep salved burn" = 15, "large burn scar" = 0)
+
+ needs_treatment = 1 // this only heals when bandaged
+
+ damage_type = BURN
+
+/datum/wound/carbonised_area
+ stages = list("carbonised area" = 50, "treated carbonised area" = 20, "massive burn scar" = 0)
+
+ needs_treatment = 1 // this only heals when bandaged
+
+ damage_type = BURN
+
+
/****************************************************
EXTERNAL ORGANS
****************************************************/
@@ -90,9 +238,7 @@ var/list/wound_progressions = list(
var/tmp/list/obj/item/weapon/implant/implant
var/display_name
-
- var/tmp/list/wound_descs = list()
- var/tmp/next_wound_update = 0
+ var/list/wounds = list()
var/tmp/perma_injury = 0
var/tmp/perma_dmg = 0
@@ -103,7 +249,7 @@ var/list/wound_progressions = list(
var/datum/organ/external/parent
var/list/datum/organ/external/children
- var/damage_msg = "\red You feel a intense pain"
+ var/damage_msg = "\red You feel an intense pain"
var/status = 0
var/broken_description
@@ -119,6 +265,7 @@ var/list/wound_progressions = list(
H.organs[name] = src
proc/take_damage(brute, burn, sharp, used_weapon = null, list/forbidden_limbs = list())
+ // TODO: this proc needs to be rewritten to not update damages directly
if((brute <= 0) && (burn <= 0))
return 0
if(status & DESTROYED)
@@ -204,31 +351,63 @@ var/list/wound_progressions = list(
return result
+
proc/heal_damage(brute, burn, internal = 0, robo_repair = 0)
if(status & ROBOT && !robo_repair)
return
- // var/brute_to_heal = 0
- // var/brute_wounds = list()
- // var/burn_to_heal = 0
- // var/burn_wounds = list()
- // for(var/datum/organ/wound/W in brute_wounds)
- brute_dam = max(0, brute_dam-brute)
- burn_dam = max(0, burn_dam-burn)
+ // heal damage on the individual wounds
+ for(var/datum/wound/W in wounds)
+ if(brute == 0 && burn == 0)
+ break
+
+ // heal brute damage
+ if(W.damage_type == CUT || W.damage_type == BRUISE)
+ burn = W.heal_damage(brute)
+ else if(W.damage_type == BURN)
+ burn = W.heal_damage(burn)
+
+ // sync organ damage with wound damages
+ update_damages()
if(internal)
status &= ~BROKEN
perma_injury = 0
+
// if all damage is healed, replace the wounds with scars
if(brute_dam + burn_dam == 0)
for(var/V in autopsy_data)
var/datum/autopsy_data/W = autopsy_data[V]
del W
autopsy_data = list()
+
owner.updatehealth()
var/result = update_icon()
return result
+ proc/update_damages()
+ brute_dam = 0
+ burn_dam = 0
+ status &= ~BLEEDING
+ for(var/datum/wound/W in wounds)
+ if(W.damage_type == CUT || W.damage_type == BRUISE)
+ brute_dam += W.damage
+ else if(W.damage_type == BURN)
+ burn_dam += W.damage
+
+ if(W.bleeding && !W.bandaged)
+ status |= BLEEDING
+
+ proc/update_wounds()
+ for(var/datum/wound/W in wounds)
+ if(W.is_treated())
+ // slow healing
+ var/amount = 0.5
+ if(W.bandaged) amount++
+ if(W.salved) amount++
+ if(W.disinfected) amount++
+ W.heal_damage(amount / 10)
+
proc/add_wound(var/used_weapon, var/damage)
var/datum/autopsy_data/W = autopsy_data[used_weapon]
if(!W)
@@ -253,8 +432,10 @@ var/list/wound_progressions = list(
return burn_dam
process()
- if(next_wound_update && world.time > next_wound_update)
- update_wounds()
+ // process wounds, doing healing etc.
+ update_wounds()
+ // update damages from wounds
+ update_damages()
if(status & DESTROYED)
if(!destspawn)
droplimb()
@@ -268,7 +449,6 @@ var/list/wound_progressions = list(
return
if(brute_dam > min_broken_damage && !(status & ROBOT))
if(!(status & BROKEN))
- //owner.unlock_medal("Broke Yarrr Bones!", 0, "Break a bone.", "easy")
owner.visible_message("\red You hear a loud cracking sound coming from \the [owner].","\red Something feels like it shattered in your [display_name]!","You hear a sickening crack.")
owner.emote("scream")
status |= BROKEN
@@ -411,62 +591,44 @@ var/list/wound_progressions = list(
proc/createwound(var/type = CUT, var/damage)
if(hasorgans(owner))
- var/wound_name
- var/update_time = world.time + damage*100
+ var/wound_type
var/size = min( max( 1, damage/10 ) , 6)
+
+ // first check whether we can widen an existing wound
+ if((type == CUT || type == BRUISE) && damage >= 5)
+ var/datum/wound/W = pick(wounds)
+ if(W.started_healing())
+ damage -= 5
+ W.open_wound()
+ owner.visible_message("\red The wound on [owner.name]'s [display_name] widens with a nasty ripping voice.",\
+ "\red The wound on your [display_name] widens with a nasty ripping voice.",\
+ "You hear a nasty ripping noise, as if flesh is being torn apart.")
+
+ if(damage == 0) return
+
switch(type)
if(CUT)
src.status |= BLEEDING
- var/list/size_names = list("cut", "deep cut", "flesh wound", "gaping wound", "big gaping wound", "massive wound")
- wound_name = size_names[size]
- if(wound_descs["[update_time]"])
- var/list/update_next = wound_descs["[update_time]"]
- update_next += wound_name
- else
- if (next_wound_update > update_time)
- next_wound_update = update_time
- wound_descs["[update_time]"] = list(wound_name)
- if(BRUISE)
- var/list/size_names = list("tiny bruise", "small bruise", "moderate bruise", "large bruise", "huge bruise", "monumental bruise")
- wound_name = size_names[size]
- if(wound_descs["[update_time]"])
- var/list/update_next = wound_descs["[update_time]"]
- update_next += wound_name
- else
- if (next_wound_update > update_time)
- next_wound_update = update_time
- wound_descs["[update_time]"] = list(wound_name)
- if(BURN)
- var/list/size_names = list("small burn", "moderate burn", "large burn", "severe burn", "deep burn", "carbonised area")
- wound_name = size_names[size]
- update_time += damage*300
- if(wound_descs["[update_time]"])
- var/list/update_next = wound_descs["[update_time]"]
- update_next += wound_name
- else
- if (next_wound_update > update_time)
- next_wound_update = update_time
- wound_descs["[update_time]"] = list(wound_name)
+ var/list/size_names = list(/datum/wound/cut, /datum/wound/deep_cut, /datum/wound/flesh_wound, /datum/wound/gaping_wound, /datum/wound/big_gaping_wound, /datum/wound/massive_wound)
+ wound_type = size_names[size]
- proc/update_wounds()
- var/list/wounds_to_update = wound_descs["[next_wound_update]"]
- for(var/wound in wounds_to_update)
- if(wound_progressions[wound])
- var/wound_name = wound_progressions[wound]
- var/next_update = world.time + 600*rand(5,13)
- if(wound_descs["[next_update]"])
- var/list/update_next = wound_descs["[next_update]"]
- update_next += wound_name
- else
- wound_descs["[next_update]"] = list(wound_name)
- wound_descs.Remove("[next_wound_update]")
- if(wound_descs.len)
- var/next_update = text2num(wound_descs[1])
- for(var/wound in wound_descs)
- next_update = min(next_update, text2num(wound))
- next_wound_update = next_update
- else
- next_wound_update = 0
+ var/datum/wound/W = new wound_type()
+ W.damage = damage
+ wounds += W
+ if(BRUISE)
+ var/list/size_names = list(/datum/wound/bruise/tiny_bruise, /datum/wound/bruise/small_bruise, /datum/wound/bruise/moderate_bruise, /datum/wound/bruise/large_bruise, /datum/wound/bruise/huge_bruise, /datum/wound/bruise/monumental_bruise)
+ wound_type = size_names[size]
+
+ var/datum/wound/W = new wound_type()
+ W.damage = damage
+ wounds += W
+ if(BURN)
+ var/list/size_names = list(/datum/wound/moderate_burn, /datum/wound/large_burn, /datum/wound/severe_burn, /datum/wound/deep_burn, /datum/wound/carbonised_area)
+ wound_type = size_names[size]
+
+ var/datum/wound/W = new wound_type()
+ W.damage = damage
+ wounds += W
proc/emp_act(severity)
if(!(status & ROBOT))
diff --git a/code/setup.dm b/code/setup.dm
index 92e06912af6..a060fbf04e7 100644
--- a/code/setup.dm
+++ b/code/setup.dm
@@ -473,4 +473,5 @@ var/list/liftable_structures = list(\
#define BROKEN 32
#define DESTROYED 64
#define ROBOT 128
-#define SPLINTED 256
\ No newline at end of file
+#define SPLINTED 256
+#define SALVED 512
\ No newline at end of file