[MIRROR] Humans have more complicated body temperatures (#1825)

* Humans have more complicated body temperatures (#54550)

This changes how carbon/humans stabilize body temperature, and changes how damage and wounds are applied based on temperature.

Humans now have a core body temperature along with body temperature. The core temperature is used for natural stabilization and what viruses like fever and shivers target by raising or lowing the core temperature of the mob.
The standard body temperature still exists and acts exactly the same for most items at this time but is now treated as surface temperature in humans.

Damage from body temperature for humans is now based on the core temperature instead of body temperature now.
Humans will now receive burn wounds when the body (surface) temperature is to high for to long.

This causes you to see alerts for the area temperature before you take damage in most cases improving visibility of dangerous situations.

* Humans have more complicated body temperatures

Co-authored-by: NightRed <nightred@gmail.com>
This commit is contained in:
SkyratBot
2020-11-25 13:56:04 +01:00
committed by GitHub
co-authored by NightRed
parent d64fb339ce
commit a25041431b
22 changed files with 322 additions and 144 deletions
@@ -905,6 +905,8 @@
for(var/datum/mutation/human/HM in dna.mutations)
if(HM.quality != POSITIVE)
dna.remove_mutation(HM.name)
coretemperature = get_body_temp_normal(apply_change=FALSE)
heat_exposure_stacks = 0
return ..()
/mob/living/carbon/human/is_literate()
@@ -70,3 +70,9 @@
/// How many "units of blood" we have on our hands
var/blood_in_hands = 0
/// The core temperature of the human compaired to the skin temp of the body
var/coretemperature = BODYTEMP_NORMAL
///Exposure to damaging heat levels increases stacks, stacks clean over time when temperatures are lower. Stack is consumed to add a wound.
var/heat_exposure_stacks = 0
+14 -2
View File
@@ -38,6 +38,9 @@
handle_heart()
handle_liver()
//Body temperature stability and damage
dna.species.handle_body_temperature(src)
dna.species.spec_life(src) // for mutantraces
else
for(var/i in all_wounds)
@@ -111,8 +114,17 @@
return
dna.species.handle_environment(environment, src)
dna.species.handle_environment_pressure(environment, src)
dna.species.handle_body_temperature(src)
/**
* Adjust the core temperature of a mob
*
* vars:
* * amount The amount of degrees to change body temperature by
* * min_temp (optional) The minimum body temperature after adjustment
* * max_temp (optional) The maximum body temperature after adjustment
*/
/mob/living/carbon/human/proc/adjust_coretemperature(amount, min_temp=0, max_temp=INFINITY)
coretemperature = clamp(coretemperature + amount, min_temp, max_temp)
/**
* get_body_temperature Returns the body temperature with any modifications applied
+219 -117
View File
@@ -1614,87 +1614,244 @@ GLOBAL_LIST_EMPTY(roundstart_races)
//////////////////////////
/**
* environment handler for species
* Environment handler for species
*
* vars:
* * environment The environment gas mix
* * H The mob we will stabilize
* * environment (required) The environment gas mix
* * humi (required)(type: /mob/living/carbon/human) The mob we will target
*/
/datum/species/proc/handle_environment(datum/gas_mixture/environment, mob/living/carbon/human/H)
var/areatemp = H.get_temperature(environment)
/datum/species/proc/handle_environment(datum/gas_mixture/environment, mob/living/carbon/human/humi)
handle_environment_pressure(environment, humi)
if(H.stat != DEAD) // If you are dead your body does not stabilize naturally
natural_bodytemperature_stabilization(environment, H)
/**
* Body temperature handler for species
*
* These procs manage body temp, bamage, and alerts
* Some of these will still fire when not alive to balance body temp to the room temp.
* vars:
* * humi (required)(type: /mob/living/carbon/human) The mob we will target
*/
/datum/species/proc/handle_body_temperature(mob/living/carbon/human/humi)
//when in a cryo unit we suspend all natural body regulation
if(istype(humi.loc, /obj/machinery/atmospherics/components/unary/cryo_cell))
return
//when dead the air still effects your skin temp
if(humi.stat == DEAD)
body_temperature_skin(humi)
else //when alive do all the things
body_temperature_core(humi)
body_temperature_skin(humi)
body_temperature_alerts(humi)
body_temperature_damage(humi)
if(!H.on_fire || areatemp > H.bodytemperature) // If we are not on fire or the area is hotter
H.adjust_bodytemperature((areatemp - H.bodytemperature), use_insulation=TRUE, use_steps=TRUE)
/**
* Used to stabilize the core temperature back to normal on living mobs
*
* The metabolisim heats up the core of the mob trying to keep it at the normal body temp
* vars:
* * humi (required) The mob we will stabilize
*/
/datum/species/proc/body_temperature_core(mob/living/carbon/human/humi)
var/natural_change = get_temp_change_amount(humi.get_body_temp_normal() - humi.coretemperature, 0.12)
humi.adjust_coretemperature(humi.metabolism_efficiency * natural_change)
/// Handle the body temperature status effects for the species
/// Traits for resitance to heat or cold are handled here.
/datum/species/proc/handle_body_temperature(mob/living/carbon/human/H)
/**
* Used to normalize the skin temperature on living mobs
*
* The core temp effects the skin, then the enviroment effects the skin, then we refect that back to the core.
* This happens even when dead so bodies revert to room temp over time.
* vars:
* * humi (required) The mob we will targeting
*/
/datum/species/proc/body_temperature_skin(mob/living/carbon/human/humi)
// change the core based on the skin temp
var/skin_core_diff = humi.bodytemperature - humi.coretemperature
// change rate of 0.08 to be slightly below area to skin change rate and still have a solid curve
var/skin_core_change = get_temp_change_amount(skin_core_diff, 0.08)
humi.adjust_coretemperature(skin_core_change)
// get the enviroment details of where the mob is standing
var/datum/gas_mixture/environment = humi.loc.return_air()
if(!environment) // if there is no environment (nullspace) drop out here.
return
// Get the temperature of the environment for area
var/area_temp = humi.get_temperature(environment)
// Get the insulation value based on the area's temp
var/thermal_protection = humi.get_insulation_protection(area_temp)
// Changes to the skin temperature based on the area
var/area_skin_diff = area_temp - humi.bodytemperature
if(!humi.on_fire || area_skin_diff > 0)
// change rate of 0.1 as area temp has large impact on the surface
var/area_skin_change = get_temp_change_amount(area_skin_diff, 0.1)
// We need to apply the thermal protection of the clothing when applying area to surface change
// If the core bodytemp goes over the normal body temp you are overheating and becom sweaty
// This will cause the insulation value of any clothing to reduced in effect (70% normal rating)
// we add 10 degree over normal body temp before triggering as thick insulation raises body temp
if(humi.get_body_temp_normal(apply_change=FALSE) + 10 < humi.coretemperature)
// we are overheating and sweaty insulation is not as good reducing thermal protection
area_skin_change = (1 - (thermal_protection * 0.7)) * area_skin_change
else
area_skin_change = (1 - thermal_protection) * area_skin_change
humi.adjust_bodytemperature(area_skin_change)
// Core to skin temp transfer, when not on fire
if(!humi.on_fire)
// Get the changes to the skin from the core temp
var/core_skin_diff = humi.coretemperature - humi.bodytemperature
// change rate of 0.08 to reflect temp back in to the core at the same rate as core to skin
var/core_skin_change = (1 + thermal_protection) * get_temp_change_amount(core_skin_diff, 0.08)
// We do not want to over shoot after using protection
if(core_skin_diff > 0)
core_skin_change = min(core_skin_change, core_skin_diff)
else
core_skin_change = max(core_skin_change, core_skin_diff)
humi.adjust_bodytemperature(core_skin_change)
/**
* Used to set alerts and debuffs based on body temperature
* vars:
* * humi (required) The mob we will targeting
*/
/datum/species/proc/body_temperature_alerts(mob/living/carbon/human/humi)
// Body temperature is too hot, and we do not have resist traits
if(H.bodytemperature > bodytemp_heat_damage_limit && !HAS_TRAIT(H, TRAIT_RESISTHEAT))
if(humi.bodytemperature > bodytemp_heat_damage_limit && !HAS_TRAIT(humi, TRAIT_RESISTHEAT))
// Clear cold mood and apply hot mood
SEND_SIGNAL(H, COMSIG_CLEAR_MOOD_EVENT, "cold")
SEND_SIGNAL(H, COMSIG_ADD_MOOD_EVENT, "hot", /datum/mood_event/hot)
SEND_SIGNAL(humi, COMSIG_CLEAR_MOOD_EVENT, "cold")
SEND_SIGNAL(humi, COMSIG_ADD_MOOD_EVENT, "hot", /datum/mood_event/hot)
//Remove any slowdown from the cold.
H.remove_movespeed_modifier(/datum/movespeed_modifier/cold)
var/burn_damage = 0
var/firemodifier = H.fire_stacks / 50
if (!H.on_fire) // We are not on fire, reduce the modifier
firemodifier = min(firemodifier, 0)
// this can go below 5 at log 2.5
burn_damage = max(log(2 - firemodifier, (H.bodytemperature - H.get_body_temp_normal(apply_change=FALSE))) - 5,0)
// Display alerts based on the amount of fire damage being taken
if (burn_damage)
switch(burn_damage)
if(0 to 2)
H.throw_alert("temp", /atom/movable/screen/alert/hot, 1)
if(2 to 4)
H.throw_alert("temp", /atom/movable/screen/alert/hot, 2)
else
H.throw_alert("temp", /atom/movable/screen/alert/hot, 3)
// Apply species and physiology modifiers to heat damage
burn_damage = burn_damage * heatmod * H.physiology.heat_mod
// 40% for level 3 damage on humans to scream in pain
if (H.stat < UNCONSCIOUS && (prob(burn_damage) * 10) / 4)
H.emote("scream")
// Apply the damage to all body parts
H.apply_damage(burn_damage, BURN, spread_damage = TRUE)
humi.remove_movespeed_modifier(/datum/movespeed_modifier/cold)
// display alerts based on how hot it is
switch(humi.bodytemperature)
if(0 to 461)
humi.throw_alert("temp", /atom/movable/screen/alert/hot, 1)
if(460 to 700)
humi.throw_alert("temp", /atom/movable/screen/alert/hot, 2)
else
humi.throw_alert("temp", /atom/movable/screen/alert/hot, 3)
// Body temperature is too cold, and we do not have resist traits
else if(H.bodytemperature < bodytemp_cold_damage_limit && !HAS_TRAIT(H, TRAIT_RESISTCOLD))
else if(humi.bodytemperature < bodytemp_cold_damage_limit && !HAS_TRAIT(humi, TRAIT_RESISTCOLD))
// clear any hot moods and apply cold mood
SEND_SIGNAL(H, COMSIG_CLEAR_MOOD_EVENT, "hot")
SEND_SIGNAL(H, COMSIG_ADD_MOOD_EVENT, "cold", /datum/mood_event/cold)
SEND_SIGNAL(humi, COMSIG_CLEAR_MOOD_EVENT, "hot")
SEND_SIGNAL(humi, COMSIG_ADD_MOOD_EVENT, "cold", /datum/mood_event/cold)
// Apply cold slow down
H.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/cold, multiplicative_slowdown = ((bodytemp_cold_damage_limit - H.bodytemperature) / COLD_SLOWDOWN_FACTOR))
// Display alerts based on the amount of cold damage being taken
// Apply more damage based on how cold you are
switch(H.bodytemperature)
if(200 to bodytemp_cold_damage_limit)
H.throw_alert("temp", /atom/movable/screen/alert/cold, 1)
H.apply_damage(COLD_DAMAGE_LEVEL_1 * coldmod * H.physiology.cold_mod, BURN)
humi.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/cold, multiplicative_slowdown = ((bodytemp_cold_damage_limit - humi.bodytemperature) / COLD_SLOWDOWN_FACTOR))
// Display alerts based how cold it is
switch(humi.bodytemperature)
if(201 to bodytemp_cold_damage_limit)
humi.throw_alert("temp", /atom/movable/screen/alert/cold, 1)
if(120 to 200)
H.throw_alert("temp", /atom/movable/screen/alert/cold, 2)
H.apply_damage(COLD_DAMAGE_LEVEL_2 * coldmod * H.physiology.cold_mod, BURN)
humi.throw_alert("temp", /atom/movable/screen/alert/cold, 2)
else
H.throw_alert("temp", /atom/movable/screen/alert/cold, 3)
H.apply_damage(COLD_DAMAGE_LEVEL_3 * coldmod * H.physiology.cold_mod, BURN)
humi.throw_alert("temp", /atom/movable/screen/alert/cold, 3)
// We are not to hot or cold, remove status and moods
else
H.clear_alert("temp")
H.remove_movespeed_modifier(/datum/movespeed_modifier/cold)
SEND_SIGNAL(H, COMSIG_CLEAR_MOOD_EVENT, "cold")
SEND_SIGNAL(H, COMSIG_CLEAR_MOOD_EVENT, "hot")
humi.clear_alert("temp")
humi.remove_movespeed_modifier(/datum/movespeed_modifier/cold)
SEND_SIGNAL(humi, COMSIG_CLEAR_MOOD_EVENT, "cold")
SEND_SIGNAL(humi, COMSIG_CLEAR_MOOD_EVENT, "hot")
/**
* Used to apply wounds and damage based on core/body temp
* vars:
* * humi (required) The mob we will targeting
*/
/datum/species/proc/body_temperature_damage(mob/living/carbon/human/humi)
//If the body temp is above the wound limit start adding exposure stacks
if(humi.bodytemperature > BODYTEMP_HEAT_WOUND_LIMIT)
humi.heat_exposure_stacks = min(humi.heat_exposure_stacks + 1, 40)
else //When below the wound limit, reduce the exposure stacks fast.
humi.heat_exposure_stacks = max(humi.heat_exposure_stacks - 4, 0)
//when exposure stacks are greater then 10 + rand20 try to apply wounds and reset stacks
if(humi.heat_exposure_stacks > (10 + rand(0, 20)))
apply_burn_wounds(humi)
humi.heat_exposure_stacks = 0
// Body temperature is too hot, and we do not have resist traits
// Apply some burn damage to the body
if(humi.coretemperature > bodytemp_heat_damage_limit && !HAS_TRAIT(humi, TRAIT_RESISTHEAT))
var/firemodifier = humi.fire_stacks / 50
if (!humi.on_fire) // We are not on fire, reduce the modifier
firemodifier = min(firemodifier, 0)
// this can go below 5 at log 2.5
var/burn_damage = max(log(2 - firemodifier, (humi.coretemperature - humi.get_body_temp_normal(apply_change=FALSE))) - 5,0)
// Apply species and physiology modifiers to heat damage
burn_damage = burn_damage * heatmod * humi.physiology.heat_mod
// 40% for level 3 damage on humans to scream in pain
if (humi.stat < UNCONSCIOUS && (prob(burn_damage) * 10) / 4)
humi.emote("scream")
// Apply the damage to all body parts
humi.apply_damage(burn_damage, BURN, spread_damage = TRUE)
// Apply some burn damage to the body
if(humi.coretemperature < bodytemp_cold_damage_limit && !HAS_TRAIT(humi, TRAIT_RESISTCOLD))
switch(humi.coretemperature)
if(201 to bodytemp_cold_damage_limit)
humi.apply_damage(COLD_DAMAGE_LEVEL_1 * coldmod * humi.physiology.cold_mod, BURN)
if(120 to 200)
humi.apply_damage(COLD_DAMAGE_LEVEL_2 * coldmod * humi.physiology.cold_mod, BURN)
else
humi.apply_damage(COLD_DAMAGE_LEVEL_3 * coldmod * humi.physiology.cold_mod, BURN)
/**
* Used to apply burn wounds on random limbs
*
* This is called from body_temperature_damage when exposure to extream heat adds up and causes a wound.
* The wounds will increase in severity as the temperature increases.
* vars:
* * humi (required) The mob we will targeting
*/
/datum/species/proc/apply_burn_wounds(mob/living/carbon/human/humi)
// If we are resistant to heat exit
if(HAS_TRAIT(humi, TRAIT_RESISTHEAT))
return
// If our body temp is to low for a wound exit
if(humi.bodytemperature < BODYTEMP_HEAT_WOUND_LIMIT)
return
// Lets pick a random body part and check for an existing burn
var/obj/item/bodypart/bodypart = pick(humi.bodyparts)
var/datum/wound/burn/existing_burn = locate(/datum/wound/burn) in bodypart.wounds
// If we have an existing burn try to upgrade it
if(existing_burn)
switch(existing_burn.severity)
if(WOUND_SEVERITY_MODERATE)
if(humi.bodytemperature > BODYTEMP_HEAT_WOUND_LIMIT + 400) // 800k
bodypart.force_wound_upwards(/datum/wound/burn/severe)
if(WOUND_SEVERITY_SEVERE)
if(humi.bodytemperature > BODYTEMP_HEAT_WOUND_LIMIT + 2800) // 3200k
bodypart.force_wound_upwards(/datum/wound/burn/critical)
else // If we have no burn apply the lowest level burn
bodypart.force_wound_upwards(/datum/wound/burn/moderate)
// always take some burn damage
var/burn_damage = HEAT_DAMAGE_LEVEL_1
if(humi.bodytemperature > BODYTEMP_HEAT_WOUND_LIMIT + 400)
burn_damage = HEAT_DAMAGE_LEVEL_2
if(humi.bodytemperature > BODYTEMP_HEAT_WOUND_LIMIT + 2800)
burn_damage = HEAT_DAMAGE_LEVEL_3
humi.apply_damage(burn_damage, BURN, bodypart)
/// Handle the air pressure of the environment
/datum/species/proc/handle_environment_pressure(datum/gas_mixture/environment, mob/living/carbon/human/H)
@@ -1738,61 +1895,6 @@ GLOBAL_LIST_EMPTY(roundstart_races)
H.adjustBruteLoss(LOW_PRESSURE_DAMAGE * H.physiology.pressure_mod)
H.throw_alert("pressure", /atom/movable/screen/alert/lowpressure, 2)
/**
* Used to stabilize the body temperature back to normal on living mobs
*
* vars:
* * environment The environment gas mix
* * H The mob we will stabilize
*/
/datum/species/proc/natural_bodytemperature_stabilization(datum/gas_mixture/environment, mob/living/carbon/human/H)
var/areatemp = H.get_temperature(environment)
var/body_temp = H.bodytemperature // Get current body temperature
var/body_temperature_difference = H.get_body_temp_normal() - body_temp
var/natural_change = 0
// We are very cold, increate body temperature
if(body_temp <= bodytemp_cold_damage_limit)
natural_change = max((body_temperature_difference * H.metabolism_efficiency / BODYTEMP_AUTORECOVERY_DIVISOR), \
bodytemp_autorecovery_min)
// we are cold, reduce the minimum increment and do not jump over the difference
else if(body_temp > bodytemp_cold_damage_limit && body_temp < H.get_body_temp_normal())
natural_change = max(body_temperature_difference * H.metabolism_efficiency / BODYTEMP_AUTORECOVERY_DIVISOR, \
min(body_temperature_difference, bodytemp_autorecovery_min / 4))
// We are hot, reduce the minimum increment and do not jump below the difference
else if(body_temp > H.get_body_temp_normal() && body_temp <= bodytemp_heat_damage_limit)
natural_change = min(body_temperature_difference * H.metabolism_efficiency / BODYTEMP_AUTORECOVERY_DIVISOR, \
max(body_temperature_difference, -(bodytemp_autorecovery_min / 4)))
// We are very hot, reduce the body temperature
else if(body_temp >= bodytemp_heat_damage_limit)
natural_change = min((body_temperature_difference / BODYTEMP_AUTORECOVERY_DIVISOR), -bodytemp_autorecovery_min)
var/thermal_protection = H.get_insulation_protection(body_temp + natural_change)
if(areatemp > body_temp) // It is hot here
if(body_temp < H.get_body_temp_normal())
// Our bodytemp is below normal we are cold, insulation helps us retain body heat
// and will reduce the heat we lose to the environment
natural_change = (thermal_protection + 1) * natural_change
else
// Our bodytemp is above normal and sweating, insulation hinders out ability to reduce heat
// but will reduce the amount of heat we get from the environment
natural_change = (1 / (thermal_protection + 1)) * natural_change
else // It is cold here
if(!H.on_fire) // If on fire ignore ignore local temperature in cold areas
if(body_temp < H.get_body_temp_normal())
// Our bodytemp is below normal, insulation helps us retain body heat
// and will reduce the heat we lose to the environment
natural_change = (thermal_protection + 1) * natural_change
else
// Our bodytemp is above normal and sweating, insulation hinders out ability to reduce heat
// but will reduce the amount of heat we get from the environment
natural_change = (1 / (thermal_protection + 1)) * natural_change
// Apply the natural stabilization changes
H.adjust_bodytemperature(natural_change)
//////////
// FIRE //
@@ -33,7 +33,7 @@
ass_image = 'icons/ass/asslizard.png'
/// Lizards are cold blooded and do not stabilize body temperature naturally
/datum/species/lizard/natural_bodytemperature_stabilization(datum/gas_mixture/environment, mob/living/carbon/human/H)
/datum/species/lizard/body_temperature_core(mob/living/carbon/human/humi)
return
/datum/species/lizard/random_name(gender,unique,lastname)
@@ -37,7 +37,7 @@
changesource_flags = MIRROR_BADMIN | WABBAJACK | ERT_SPAWN
/// Zombies do not stabilize body temperature they are the walking dead and are cold blooded
/datum/species/zombie/natural_bodytemperature_stabilization(datum/gas_mixture/environment, mob/living/carbon/human/H)
/datum/species/zombie/body_temperature_core(mob/living/carbon/human/humi)
return
/datum/species/zombie/infectious/check_roundstart_eligible()
+1 -1
View File
@@ -701,7 +701,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
amount = (amount > 0) ? min(amount, BODYTEMP_HEATING_MAX) : max(amount, BODYTEMP_COOLING_MAX)
if(bodytemperature >= min_temp && bodytemperature <= max_temp)
bodytemperature = clamp(bodytemperature + amount,min_temp,max_temp)
bodytemperature = clamp(bodytemperature + amount, min_temp, max_temp)
///////////