mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-08-29 16:10:02 +01:00
1616 lines
60 KiB
Plaintext
1616 lines
60 KiB
Plaintext
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32
|
|
|
|
//NOTE: Breathing happens once per FOUR TICKS, unless the last breath fails. In which case it happens once per ONE TICK! So oxyloss healing is done once per 4 ticks while oxyloss damage is applied once per tick!
|
|
|
|
#define HEAT_DAMAGE_LEVEL_1 2 //Amount of damage applied when your body temperature just passes the 360.15k safety point
|
|
#define HEAT_DAMAGE_LEVEL_2 4 //Amount of damage applied when your body temperature passes the 400K point
|
|
#define HEAT_DAMAGE_LEVEL_3 8 //Amount of damage applied when your body temperature passes the 1000K point
|
|
|
|
#define COLD_DAMAGE_LEVEL_1 0.5 //Amount of damage applied when your body temperature just passes the 260.15k safety point
|
|
#define COLD_DAMAGE_LEVEL_2 1.5 //Amount of damage applied when your body temperature passes the 200K point
|
|
#define COLD_DAMAGE_LEVEL_3 3 //Amount of damage applied when your body temperature passes the 120K point
|
|
|
|
//Note that gas heat damage is only applied once every FOUR ticks.
|
|
#define HEAT_GAS_DAMAGE_LEVEL_1 2 //Amount of damage applied when the current breath's temperature just passes the 360.15k safety point
|
|
#define HEAT_GAS_DAMAGE_LEVEL_2 4 //Amount of damage applied when the current breath's temperature passes the 400K point
|
|
#define HEAT_GAS_DAMAGE_LEVEL_3 8 //Amount of damage applied when the current breath's temperature passes the 1000K point
|
|
|
|
#define COLD_GAS_DAMAGE_LEVEL_1 0.5 //Amount of damage applied when the current breath's temperature just passes the 260.15k safety point
|
|
#define COLD_GAS_DAMAGE_LEVEL_2 1.5 //Amount of damage applied when the current breath's temperature passes the 200K point
|
|
#define COLD_GAS_DAMAGE_LEVEL_3 3 //Amount of damage applied when the current breath's temperature passes the 120K point
|
|
|
|
#define RADIATION_SPEED_COEFFICIENT 0.1
|
|
|
|
/mob/living/carbon/human
|
|
var/oxygen_alert = 0
|
|
var/phoron_alert = 0
|
|
var/co2_alert = 0
|
|
var/fire_alert = 0
|
|
var/pressure_alert = 0
|
|
var/temperature_alert = 0
|
|
|
|
/mob/living/carbon/human/Life(seconds_per_tick, times_fired)
|
|
if (transforming)
|
|
return
|
|
|
|
fire_alert = 0 //Reset this here, because both breathe() and handle_environment() have a chance to set it.
|
|
|
|
//TODO: seperate this out
|
|
// update the current life tick, can be used to e.g. only do something every 4 ticks
|
|
life_tick++
|
|
|
|
// This is not an ideal place for this but it will do for now.
|
|
if(wearing_rig && wearing_rig.offline)
|
|
wearing_rig = null
|
|
|
|
var/shock_value = get_shock()
|
|
|
|
..()
|
|
|
|
if(life_tick%30==5)//Makes huds update every 10 seconds instead of every 30 seconds
|
|
hud_updateflag = 1022
|
|
|
|
voice = GetVoice()
|
|
|
|
//No need to update all of these procs if the guy is dead or in stasis
|
|
if(stat != DEAD && !InStasis())
|
|
//Updates the number of stored chemicals for powers
|
|
handle_changeling()
|
|
|
|
//Organs
|
|
handle_organs(seconds_per_tick)
|
|
stabilize_body_temperature() //Body temperature adjusts itself (self-regulation)
|
|
|
|
//Random events (vomiting etc)
|
|
handle_random_events()
|
|
|
|
handle_shock(shock_value)
|
|
|
|
handle_pain()
|
|
|
|
handle_fever()
|
|
|
|
//Handles regenerating stamina if we have sufficient air and no oxyloss
|
|
handle_stamina(shock_value)
|
|
|
|
if (is_diona())
|
|
diona_handle_light(DS)
|
|
|
|
handle_shared_dreaming()
|
|
|
|
if(!handle_some_updates())
|
|
return //We go ahead and process them 5 times for HUD images and other stuff though.
|
|
|
|
//Update our name based on whether our face is obscured/disfigured
|
|
name = get_visible_name()
|
|
|
|
if(mind)
|
|
var/datum/vampire/vampire = mind.antag_datums[MODE_VAMPIRE]
|
|
if(vampire)
|
|
handle_vampire()
|
|
|
|
/mob/living/carbon/human/think()
|
|
..()
|
|
species.handle_npc(src)
|
|
|
|
/mob/living/carbon/human/proc/handle_some_updates()
|
|
if(life_tick > 5 && timeofdeath && (timeofdeath < 5 || world.time - timeofdeath > 6000)) //We are long dead, or we're junk mobs spawned like the clowns on the clown shuttle
|
|
return 0
|
|
return 1
|
|
|
|
/mob/living/carbon/human/breathe()
|
|
if(!InStasis())
|
|
..()
|
|
|
|
// Calculate how vulnerable the human is to the current pressure.
|
|
// Returns 0 (equals 0 %) if sealed in an undamaged suit that's rated for the pressure, 1 if unprotected (equals 100%).
|
|
// Suitdamage can modifiy this in 10% steps.
|
|
/mob/living/carbon/human/get_pressure_weakness(pressure)
|
|
var/pressure_adjustment_coefficient = 0
|
|
var/list/zones = list(HEAD, UPPER_TORSO, LOWER_TORSO, LEGS, FEET, ARMS, HANDS)
|
|
for(var/zone in zones)
|
|
var/list/covers = get_covering_equipped_items(zone)
|
|
var/zone_exposure = 1
|
|
for(var/obj/item/clothing/C in covers)
|
|
zone_exposure = min(zone_exposure, C.get_pressure_weakness(pressure,zone))
|
|
if(zone_exposure >= 1)
|
|
return 1
|
|
pressure_adjustment_coefficient = max(pressure_adjustment_coefficient, zone_exposure)
|
|
pressure_adjustment_coefficient = clamp(pressure_adjustment_coefficient, 0, 1) // So it isn't less than 0 or larger than 1.
|
|
|
|
return pressure_adjustment_coefficient
|
|
|
|
// Calculate how much of the enviroment pressure-difference affects the human.
|
|
/mob/living/carbon/human/calculate_affecting_pressure(var/pressure)
|
|
var/pressure_difference
|
|
|
|
// First get the absolute pressure difference.
|
|
if(pressure < ONE_ATMOSPHERE) // We are in an underpressure.
|
|
pressure_difference = ONE_ATMOSPHERE - pressure
|
|
|
|
else //We are in an overpressure or standard atmosphere.
|
|
pressure_difference = pressure - ONE_ATMOSPHERE
|
|
|
|
if(pressure_difference < 5) // If the difference is small, don't bother calculating the fraction.
|
|
pressure_difference = 0
|
|
|
|
else
|
|
// Otherwise calculate how much of that absolute pressure difference affects us, can be 0 to 1 (equals 0% to 100%).
|
|
// This is our relative difference.
|
|
pressure_difference *= get_pressure_weakness()
|
|
|
|
// The difference is always positive to avoid extra calculations.
|
|
// Apply the relative difference on a standard atmosphere to get the final result.
|
|
// The return value will be the adjusted_pressure of the human that is the basis of pressure warnings and damage.
|
|
if(pressure < ONE_ATMOSPHERE)
|
|
return ONE_ATMOSPHERE - pressure_difference
|
|
else
|
|
return ONE_ATMOSPHERE + pressure_difference
|
|
|
|
/mob/living/carbon/human/handle_disabilities()
|
|
..()
|
|
//Vision
|
|
var/obj/item/organ/vision
|
|
if(species.vision_organ)
|
|
vision = species.get_vision_organ(src)
|
|
|
|
if (!vision)
|
|
if (species.vision_organ) // if they should have eyes but don't, they can't see
|
|
eye_blind = 1
|
|
blinded = 1
|
|
eye_blurry = 1
|
|
else // if they're not supposed to have a vision organ, then they must see by some other means
|
|
eye_blind = 0
|
|
blinded = 0
|
|
eye_blurry = 0
|
|
else if (vision.is_broken()) // if their eyes have been damaged or detached, they're blinded
|
|
eye_blind = 1
|
|
blinded = 1
|
|
eye_blurry = 1
|
|
else
|
|
//blindness
|
|
if(!(sdisabilities & BLIND))
|
|
if(!src.is_diona() && equipment_tint_total >= TINT_BLIND) // Covered eyes, heal faster
|
|
eye_blurry = max(eye_blurry-2, 0)
|
|
else
|
|
eye_blurry = max(eye_blurry-1, 0)
|
|
|
|
if (disabilities & EPILEPSY)
|
|
if ((prob(1) && paralysis < 1))
|
|
to_chat(src, SPAN_WARNING("You have a seizure!"))
|
|
for(var/mob/O in viewers(src, null))
|
|
if(O == src)
|
|
continue
|
|
O.show_message(SPAN_DANGER("[src] starts having a seizure!"), 1)
|
|
Paralyse(10)
|
|
make_jittery(1000)
|
|
if (disabilities & COUGHING)
|
|
if ((prob(5) && paralysis <= 1))
|
|
drop_item()
|
|
emote("cough")
|
|
return
|
|
|
|
if((disabilities & ASTHMA) && getOxyLoss() >= 10)
|
|
if(prob(5))
|
|
emote("cough")
|
|
|
|
if(disabilities & STUTTERING)
|
|
var/aid = 1 + chem_effects[CE_NOSTUTTER]
|
|
if(aid < 3 && prob(10/aid)) //NOSTUTTER at 2 or above prevents it completely.
|
|
stuttering = max(10/aid, stuttering)
|
|
|
|
/mob/living/carbon/human/handle_mutations_and_radiation()
|
|
if(InStasis())
|
|
return
|
|
|
|
if(getFireLoss() && ((mutations & COLD_RESISTANCE) || prob(1)))
|
|
heal_organ_damage(0,1)
|
|
|
|
// DNA2 - Gene processing.
|
|
// The HULK stuff that was here is now in the hulk gene.
|
|
for(var/datum/dna/gene/gene in dna_genes)
|
|
if(!gene.block)
|
|
continue
|
|
if(gene.is_active(src))
|
|
gene.OnMobLife(src)
|
|
|
|
total_radiation = clamp(total_radiation,0,100)
|
|
|
|
if (total_radiation)
|
|
if(src.is_diona())
|
|
diona_handle_regeneration(get_dionastats())
|
|
return
|
|
else
|
|
var/damage = 0
|
|
total_radiation -= 1 * RADIATION_SPEED_COEFFICIENT
|
|
if(prob(25))
|
|
damage = 2
|
|
|
|
if (total_radiation > 50)
|
|
damage = 3
|
|
total_radiation -= 1 * RADIATION_SPEED_COEFFICIENT
|
|
if(prob(5) && prob(100 * RADIATION_SPEED_COEFFICIENT))
|
|
src.apply_radiation(-5 * RADIATION_SPEED_COEFFICIENT)
|
|
to_chat(src, SPAN_WARNING("You feel weak."))
|
|
Weaken(3)
|
|
if(!lying)
|
|
emote("collapse")
|
|
if(prob(5) && prob(100 * RADIATION_SPEED_COEFFICIENT) && species.name == SPECIES_HUMAN) //apes go bald
|
|
if((h_style != "Bald" || f_style != "Shaved" ))
|
|
to_chat(src, SPAN_WARNING("Your hair falls out."))
|
|
h_style = "Bald"
|
|
f_style = "Shaved"
|
|
update_hair()
|
|
|
|
if (total_radiation > 75)
|
|
src.apply_radiation(-1 * RADIATION_SPEED_COEFFICIENT)
|
|
damage = 7
|
|
if(prob(5))
|
|
take_overall_damage(0, 10 * RADIATION_SPEED_COEFFICIENT, used_weapon = "Radiation Burns")
|
|
to_chat(src, SPAN_WARNING("You feel a burning sensation!"))
|
|
if(prob(1))
|
|
to_chat(src, SPAN_WARNING("You feel strange!"))
|
|
adjustCloneLoss(5 * RADIATION_SPEED_COEFFICIENT)
|
|
emote("gasp")
|
|
hallucination = max(hallucination, 20) //At this level, you're in a constant state of low-level hallucinations. As if you didn't have enough problems.
|
|
|
|
|
|
if(damage)
|
|
adjustToxLoss(damage * RADIATION_SPEED_COEFFICIENT)
|
|
updatehealth()
|
|
if(organs.len)
|
|
var/obj/item/organ/external/O = pick(organs)
|
|
if(istype(O)) O.add_autopsy_data("Radiation Poisoning", damage)
|
|
|
|
/** breathing **/
|
|
|
|
/mob/living/carbon/human/handle_chemical_smoke(var/datum/gas_mixture/environment)
|
|
if(wear_mask && (wear_mask.item_flags & ITEM_FLAG_BLOCK_GAS_SMOKE_EFFECT))
|
|
return
|
|
if(glasses && (glasses.item_flags & ITEM_FLAG_BLOCK_GAS_SMOKE_EFFECT))
|
|
return
|
|
if(head && (head.item_flags & ITEM_FLAG_BLOCK_GAS_SMOKE_EFFECT))
|
|
return
|
|
..()
|
|
|
|
/mob/living/carbon/human/get_breath_from_internal(volume_needed=BREATH_VOLUME)
|
|
if(internal)
|
|
|
|
var/obj/item/tank/rig_supply
|
|
if(istype(back,/obj/item/rig))
|
|
var/obj/item/rig/rig = back
|
|
if(!rig.offline && (rig.air_supply && internal == rig.air_supply))
|
|
rig_supply = rig.air_supply
|
|
|
|
if (!rig_supply && (!contents.Find(internal) || !((wear_mask && (wear_mask.item_flags & ITEM_FLAG_AIRTIGHT)) || (head && (head.item_flags & ITEM_FLAG_AIRTIGHT)))))
|
|
internal = null
|
|
|
|
if(internal)
|
|
return internal.remove_air_volume(volume_needed)
|
|
else if(internals)
|
|
internals.icon_state = "internal0"
|
|
return null
|
|
|
|
/mob/living/carbon/human/get_breath_from_environment(var/volume_needed=BREATH_VOLUME)
|
|
var/datum/gas_mixture/breath = ..()
|
|
|
|
if(breath)
|
|
//exposure to extreme pressures can rupture lungs
|
|
var/check_pressure = breath.return_pressure()
|
|
if(check_pressure < ONE_ATMOSPHERE / 5 || check_pressure > ONE_ATMOSPHERE * 5)
|
|
if(!is_lung_ruptured() && prob(5))
|
|
rupture_lung()
|
|
|
|
return breath
|
|
|
|
/mob/living/carbon/human/handle_environment(datum/gas_mixture/environment)
|
|
..()
|
|
|
|
if(!environment)
|
|
return
|
|
|
|
//Stuff like the xenomorph's plasma regen happens here.
|
|
species.handle_environment_special(src)
|
|
|
|
//Moved pressure calculations here for use in skip-processing check.
|
|
var/pressure = environment.return_pressure()
|
|
var/adjusted_pressure = calculate_affecting_pressure(pressure)
|
|
|
|
if (consume_nutrition_from_air)
|
|
environment.remove(diona_handle_air(get_dionastats(), pressure))
|
|
|
|
//Check for contaminants before anything else because we don't want to skip it.
|
|
for(var/g in environment.gas)
|
|
if(gas_data.flags[g] & XGM_GAS_CONTAMINANT && environment.gas[g] > gas_data.overlay_limit[g] + 1)
|
|
pl_effects()
|
|
break
|
|
|
|
if(istype(get_turf(src), /turf/space))
|
|
//Don't bother if the temperature drop is less than 0.1 anyways. Hopefully BYOND is smart enough to turn this constant expression into a constant
|
|
if(bodytemperature > (0.1 * HUMAN_HEAT_CAPACITY/(HUMAN_EXPOSED_SURFACE_AREA*STEFAN_BOLTZMANN_CONSTANT))**(1/4) + COSMIC_RADIATION_TEMPERATURE)
|
|
//Thermal radiation into space
|
|
var/heat_loss = HUMAN_EXPOSED_SURFACE_AREA * STEFAN_BOLTZMANN_CONSTANT * ((bodytemperature - COSMIC_RADIATION_TEMPERATURE)**4)
|
|
var/temperature_loss = heat_loss/HUMAN_HEAT_CAPACITY
|
|
bodytemperature -= temperature_loss
|
|
else
|
|
var/loc_temp = T0C
|
|
if(istype(loc, /obj/machinery/atmospherics/unary/cryo_cell))
|
|
var/obj/machinery/atmospherics/unary/cryo_cell/C = loc
|
|
loc_temp = C.air_contents?.temperature
|
|
else
|
|
loc_temp = environment.temperature
|
|
|
|
if(adjusted_pressure < species.warning_high_pressure && adjusted_pressure > species.warning_low_pressure && abs(loc_temp - bodytemperature) < 20 && bodytemperature < species.heat_level_1 && bodytemperature > species.cold_level_1)
|
|
pressure_alert = 0
|
|
return // Temperatures are within normal ranges, fuck all this processing. ~Ccomp
|
|
|
|
//Body temperature adjusts depending on surrounding atmosphere based on your thermal protection (convection)
|
|
var/temp_adj = 0
|
|
if(loc_temp < bodytemperature) //Place is colder than we are
|
|
var/thermal_protection = get_cold_protection(loc_temp) //This returns a 0 - 1 value, which corresponds to the percentage of protection based on what you're wearing and what you're exposed to.
|
|
if(thermal_protection < 1)
|
|
temp_adj = (1-thermal_protection) * ((loc_temp - bodytemperature) / BODYTEMP_COLD_DIVISOR) //this will be negative
|
|
else if (loc_temp > bodytemperature) //Place is hotter than we are
|
|
var/thermal_protection = get_heat_protection(loc_temp) //This returns a 0 - 1 value, which corresponds to the percentage of protection based on what you're wearing and what you're exposed to.
|
|
if(thermal_protection < 1)
|
|
temp_adj = (1-thermal_protection) * ((loc_temp - bodytemperature) / BODYTEMP_HEAT_DIVISOR)
|
|
|
|
//Use heat transfer as proportional to the gas density. However, we only care about the relative density vs standard 101 kPa/20 C air. Therefore we can use mole ratios
|
|
var/relative_density = environment.total_moles / MOLES_CELLSTANDARD
|
|
bodytemperature += between(BODYTEMP_COOLING_MAX, temp_adj*relative_density, BODYTEMP_HEATING_MAX)
|
|
|
|
var/cold_bonus = 0
|
|
var/hot_bonus = 0
|
|
if(HAS_TRAIT(src, TRAIT_ORIGIN_COLD_RESISTANCE))
|
|
cold_bonus = 20
|
|
if(HAS_TRAIT(src, TRAIT_ORIGIN_HOT_RESISTANCE))
|
|
hot_bonus = 20
|
|
|
|
// +/- 50 degrees from 310.15K is the 'safe' zone, where no damage is dealt.
|
|
if(bodytemperature >= (species.heat_level_1 + hot_bonus))
|
|
//Body temperature is too hot.
|
|
fire_alert = max(fire_alert, 1)
|
|
if(status_flags & GODMODE) return 1 //godmode
|
|
var/burn_dam = 0
|
|
if(bodytemperature < species.heat_level_2)
|
|
burn_dam = HEAT_DAMAGE_LEVEL_1
|
|
else if(bodytemperature < species.heat_level_3)
|
|
burn_dam = HEAT_DAMAGE_LEVEL_2
|
|
else
|
|
burn_dam = HEAT_DAMAGE_LEVEL_3
|
|
take_overall_damage(burn = burn_dam, used_weapon = "extreme heat")
|
|
fire_alert = max(fire_alert, 2)
|
|
|
|
else if(bodytemperature <= (species.cold_level_1 - cold_bonus))
|
|
fire_alert = max(fire_alert, 1)
|
|
if(status_flags & GODMODE)
|
|
return 1
|
|
|
|
var/burn_dam = 0
|
|
|
|
if(bodytemperature > species.cold_level_2)
|
|
burn_dam = COLD_DAMAGE_LEVEL_1
|
|
else if(bodytemperature > species.cold_level_3)
|
|
burn_dam = COLD_DAMAGE_LEVEL_2
|
|
else
|
|
burn_dam = COLD_DAMAGE_LEVEL_3
|
|
SetStasis(getCryogenicFactor(bodytemperature), STASIS_COLD)
|
|
if(!chem_effects[CE_CRYO])
|
|
take_overall_damage(burn = burn_dam, used_weapon = "extreme cold")
|
|
fire_alert = max(fire_alert, 1)
|
|
|
|
// Account for massive pressure differences. Done by Polymorph
|
|
// Made it possible to actually have something that can protect against high pressure... Done by Errorage. Polymorph now has an axe sticking from his head for his previous hardcoded nonsense!
|
|
if(status_flags & GODMODE)
|
|
return 1 //godmode
|
|
|
|
if(adjusted_pressure >= species.hazard_high_pressure)
|
|
var/pressure_damage = min( ( (adjusted_pressure / species.hazard_high_pressure) -1 )*PRESSURE_DAMAGE_COEFFICIENT , MAX_HIGH_PRESSURE_DAMAGE)
|
|
take_overall_damage(pressure_damage, used_weapon = "High Pressure")
|
|
pressure_alert = 2
|
|
else if(adjusted_pressure >= species.warning_high_pressure)
|
|
pressure_alert = 1
|
|
else if(adjusted_pressure >= species.warning_low_pressure)
|
|
pressure_alert = 0
|
|
else if(adjusted_pressure >= species.hazard_low_pressure)
|
|
pressure_alert = -1
|
|
else
|
|
if(!pressure_resistant())
|
|
var/list/obj/item/organ/external/organs = get_damageable_organs()
|
|
for(var/obj/item/organ/external/O in organs)
|
|
if(QDELETED(O))
|
|
continue
|
|
if((O.damage + LOW_PRESSURE_DAMAGE) < O.max_damage)
|
|
O.take_damage(brute = LOW_PRESSURE_DAMAGE, used_weapon = "Low Pressure")
|
|
if(getOxyLoss() < 55)
|
|
adjustOxyLoss(4)
|
|
pressure_alert = -2
|
|
else
|
|
pressure_alert = -1
|
|
|
|
if (is_diona())
|
|
diona_handle_temperature(DS)
|
|
|
|
/mob/living/carbon/human/proc/get_baseline_body_temperature()
|
|
var/baseline = species.body_temperature
|
|
for(var/obj/item/clothing/clothing in list(w_uniform, wear_suit))
|
|
baseline += clothing.body_temperature_change
|
|
return baseline
|
|
|
|
/mob/living/carbon/human/proc/stabilize_body_temperature()
|
|
if (species.passive_temp_gain) // We produce heat naturally.
|
|
species.handle_temperature_regulation(src)
|
|
|
|
if (species.body_temperature == null)
|
|
return //this species doesn't have metabolic thermoregulation
|
|
|
|
var/body_temperature_difference = get_baseline_body_temperature() - bodytemperature
|
|
|
|
if (abs(body_temperature_difference) < 0.5)
|
|
return //fuck this precision
|
|
if (on_fire)
|
|
return //too busy for pesky metabolic regulation
|
|
|
|
if(bodytemperature < species.cold_level_1) //260.15 is 310.15 - 50, the temperature where you start to feel effects.
|
|
if(nutrition >= 2) //If we are very, very cold we'll use up quite a bit of nutriment to heat us up.
|
|
adjustNutritionLoss(2)
|
|
var/recovery_amt = max((body_temperature_difference / BODYTEMP_AUTORECOVERY_DIVISOR), BODYTEMP_AUTORECOVERY_MINIMUM)
|
|
bodytemperature += recovery_amt
|
|
else if(species.cold_level_1 <= bodytemperature && bodytemperature <= species.heat_level_1)
|
|
var/recovery_amt = body_temperature_difference / BODYTEMP_AUTORECOVERY_DIVISOR
|
|
bodytemperature += recovery_amt
|
|
else if(bodytemperature > species.heat_level_1) //360.15 is 310.15 + 50, the temperature where you start to feel effects.
|
|
if(hydration >= 2)
|
|
adjustHydrationLoss(2)
|
|
if((species.flags & CAN_SWEAT) && fire_stacks == 0)
|
|
fire_stacks = -1
|
|
var/recovery_amt = min((body_temperature_difference / BODYTEMP_AUTORECOVERY_DIVISOR), -BODYTEMP_AUTORECOVERY_MINIMUM) //We're dealing with negative numbers
|
|
bodytemperature += recovery_amt
|
|
|
|
/**
|
|
* Returns a bitflag for the body parts currently heat-protected. Called and used by get_heat_protection()
|
|
* If the passed temperature is less than the item's max_heat_protection_temperature, then the flag is added to the associated body part(s).
|
|
* Refer to 'code/__DEFINES/item_clothing.dm' for details.
|
|
*
|
|
* * temperature - the temperature the living/carbon/human is being exposed to.
|
|
*/
|
|
/mob/living/carbon/human/proc/get_heat_protection_flags(temperature) //Temperature is the temperature you're being exposed to.
|
|
var/thermal_protection_flags = 0
|
|
//Handle normal clothing
|
|
if(head)
|
|
if(head.max_heat_protection_temperature && head.max_heat_protection_temperature >= temperature)
|
|
thermal_protection_flags |= head.heat_protection
|
|
if(wear_suit)
|
|
if(wear_suit.max_heat_protection_temperature && wear_suit.max_heat_protection_temperature >= temperature)
|
|
thermal_protection_flags |= wear_suit.heat_protection
|
|
if(w_uniform)
|
|
if(w_uniform.max_heat_protection_temperature && w_uniform.max_heat_protection_temperature >= temperature)
|
|
thermal_protection_flags |= w_uniform.heat_protection
|
|
if(shoes)
|
|
if(shoes.max_heat_protection_temperature && shoes.max_heat_protection_temperature >= temperature)
|
|
thermal_protection_flags |= shoes.heat_protection
|
|
if(gloves)
|
|
if(gloves.max_heat_protection_temperature && gloves.max_heat_protection_temperature >= temperature)
|
|
thermal_protection_flags |= gloves.heat_protection
|
|
if(wear_mask)
|
|
if(wear_mask.max_heat_protection_temperature && wear_mask.max_heat_protection_temperature >= temperature)
|
|
thermal_protection_flags |= wear_mask.heat_protection
|
|
|
|
return thermal_protection_flags
|
|
|
|
/**
|
|
* Returns a bitflag for the body parts currently heat-protected. Called by get_heat_protection()
|
|
* If the passed temperature is less than the item's max_heat_protection_temperature, then the flag is added to the associated body part(s).
|
|
* Refer to 'code/__DEFINES/item_clothing.dm' for details.
|
|
*
|
|
* * temperature - the temperature the living/carbon/human is being exposed to.
|
|
*/
|
|
/mob/living/carbon/human/get_heat_protection(temperature)
|
|
var/thermal_protection_flags = get_heat_protection_flags(temperature)
|
|
|
|
var/thermal_protection = 0.0
|
|
if(thermal_protection_flags)
|
|
if(thermal_protection_flags & HEAD)
|
|
thermal_protection += THERMAL_PROTECTION_HEAD
|
|
if(thermal_protection_flags & UPPER_TORSO)
|
|
thermal_protection += THERMAL_PROTECTION_UPPER_TORSO
|
|
if(thermal_protection_flags & LOWER_TORSO)
|
|
thermal_protection += THERMAL_PROTECTION_LOWER_TORSO
|
|
if(thermal_protection_flags & LEG_LEFT)
|
|
thermal_protection += THERMAL_PROTECTION_LEG_LEFT
|
|
if(thermal_protection_flags & LEG_RIGHT)
|
|
thermal_protection += THERMAL_PROTECTION_LEG_RIGHT
|
|
if(thermal_protection_flags & FOOT_LEFT)
|
|
thermal_protection += THERMAL_PROTECTION_FOOT_LEFT
|
|
if(thermal_protection_flags & FOOT_RIGHT)
|
|
thermal_protection += THERMAL_PROTECTION_FOOT_RIGHT
|
|
if(thermal_protection_flags & ARM_LEFT)
|
|
thermal_protection += THERMAL_PROTECTION_ARM_LEFT
|
|
if(thermal_protection_flags & ARM_RIGHT)
|
|
thermal_protection += THERMAL_PROTECTION_ARM_RIGHT
|
|
if(thermal_protection_flags & HAND_LEFT)
|
|
thermal_protection += THERMAL_PROTECTION_HAND_LEFT
|
|
if(thermal_protection_flags & HAND_RIGHT)
|
|
thermal_protection += THERMAL_PROTECTION_HAND_RIGHT
|
|
|
|
|
|
return min(1,thermal_protection)
|
|
|
|
//See proc/get_heat_protection_flags(temperature) for the description of this proc.
|
|
/mob/living/carbon/human/proc/get_cold_protection_flags(temperature)
|
|
var/thermal_protection_flags = 0
|
|
//Handle normal clothing
|
|
|
|
if(head)
|
|
if(head.min_cold_protection_temperature && head.min_cold_protection_temperature <= temperature)
|
|
thermal_protection_flags |= head.cold_protection
|
|
if(wear_suit)
|
|
if(wear_suit.min_cold_protection_temperature && wear_suit.min_cold_protection_temperature <= temperature)
|
|
thermal_protection_flags |= wear_suit.cold_protection
|
|
if(w_uniform)
|
|
if(w_uniform.min_cold_protection_temperature && w_uniform.min_cold_protection_temperature <= temperature)
|
|
thermal_protection_flags |= w_uniform.cold_protection
|
|
if(shoes)
|
|
if(shoes.min_cold_protection_temperature && shoes.min_cold_protection_temperature <= temperature)
|
|
thermal_protection_flags |= shoes.cold_protection
|
|
if(gloves)
|
|
if(gloves.min_cold_protection_temperature && gloves.min_cold_protection_temperature <= temperature)
|
|
thermal_protection_flags |= gloves.cold_protection
|
|
if(wear_mask)
|
|
if(wear_mask.min_cold_protection_temperature && wear_mask.min_cold_protection_temperature <= temperature)
|
|
thermal_protection_flags |= wear_mask.cold_protection
|
|
|
|
return thermal_protection_flags
|
|
|
|
/mob/living/carbon/human/get_cold_protection(temperature)
|
|
if((mutations & COLD_RESISTANCE))
|
|
return 1 //Fully protected from the cold.
|
|
|
|
temperature = max(temperature, 2.7) //There is an occasional bug where the temperature is miscalculated in ares with a small amount of gas on them, so this is necessary to ensure that that bug does not affect this calculation. Space's temperature is 2.7K and most suits that are intended to protect against any cold, protect down to 2.0K.
|
|
var/thermal_protection_flags = get_cold_protection_flags(temperature)
|
|
|
|
var/thermal_protection = 0.0
|
|
if(thermal_protection_flags)
|
|
if(thermal_protection_flags & HEAD)
|
|
thermal_protection += THERMAL_PROTECTION_HEAD
|
|
if(thermal_protection_flags & UPPER_TORSO)
|
|
thermal_protection += THERMAL_PROTECTION_UPPER_TORSO
|
|
if(thermal_protection_flags & LOWER_TORSO)
|
|
thermal_protection += THERMAL_PROTECTION_LOWER_TORSO
|
|
if(thermal_protection_flags & LEG_LEFT)
|
|
thermal_protection += THERMAL_PROTECTION_LEG_LEFT
|
|
if(thermal_protection_flags & LEG_RIGHT)
|
|
thermal_protection += THERMAL_PROTECTION_LEG_RIGHT
|
|
if(thermal_protection_flags & FOOT_LEFT)
|
|
thermal_protection += THERMAL_PROTECTION_FOOT_LEFT
|
|
if(thermal_protection_flags & FOOT_RIGHT)
|
|
thermal_protection += THERMAL_PROTECTION_FOOT_RIGHT
|
|
if(thermal_protection_flags & ARM_LEFT)
|
|
thermal_protection += THERMAL_PROTECTION_ARM_LEFT
|
|
if(thermal_protection_flags & ARM_RIGHT)
|
|
thermal_protection += THERMAL_PROTECTION_ARM_RIGHT
|
|
if(thermal_protection_flags & HAND_LEFT)
|
|
thermal_protection += THERMAL_PROTECTION_HAND_LEFT
|
|
if(thermal_protection_flags & HAND_RIGHT)
|
|
thermal_protection += THERMAL_PROTECTION_HAND_RIGHT
|
|
|
|
return min(1,thermal_protection)
|
|
|
|
/mob/living/carbon/human/handle_chemicals_in_body()
|
|
if(InStasis())
|
|
return
|
|
|
|
chem_effects.Cut()
|
|
|
|
var/datum/reagents/metabolism/ingested = get_ingested_reagents()
|
|
|
|
if(reagents)
|
|
analgesic = 0
|
|
|
|
if(touching) touching.metabolize()
|
|
if(bloodstr) bloodstr.metabolize()
|
|
if(ingested) metabolize_ingested_reagents()
|
|
if(breathing) breathing.metabolize()
|
|
|
|
if(CE_PAINKILLER in chem_effects)
|
|
analgesic = chem_effects[CE_PAINKILLER]
|
|
|
|
if(CE_TOXIN in chem_effects)
|
|
adjustToxLoss(chem_effects[CE_TOXIN])
|
|
|
|
if(CE_EMETIC in chem_effects)
|
|
if(prob(chem_effects[CE_EMETIC]))
|
|
delayed_vomit()
|
|
|
|
if(CE_ITCH in chem_effects)
|
|
var/itching = chem_effects[CE_ITCH]
|
|
if(CE_NOITCH in chem_effects)
|
|
itching -= chem_effects[CE_NOITCH]
|
|
if(itching < 5)
|
|
if(prob(5))
|
|
to_chat(src, SPAN_WARNING(pick("You have an annoying itch.", "You have a slight itch.")))
|
|
if(itching >= 5)
|
|
if(prob(2))
|
|
to_chat(src, SPAN_WARNING(pick("The itch is becoming progressively worse.", "You need to scratch that itch!", "The itch isn't going!")))
|
|
|
|
if(CE_HAUNTED in chem_effects)
|
|
var/haunted = chem_effects[CE_HAUNTED]
|
|
if(haunted < 5)
|
|
if(prob(20))
|
|
set_see_invisible(SEE_INVISIBLE_CULT)
|
|
if(prob(5))
|
|
emote("shiver")
|
|
to_chat(src, SPAN_GOOD(pick("You hear the clinking of dinner plates and laughter.", "You hear a distant voice of someone you know talking to you.", "Fond memories of a departed loved one flocks to your mind.", "You feel the reassuring presence of a departed loved one.", "You feel a hand squeezing yours.")))
|
|
if(haunted >= 5)
|
|
set_see_invisible(SEE_INVISIBLE_CULT)
|
|
make_jittery(5)
|
|
if(prob(5))
|
|
visible_message("<b>[src]</b> trembles uncontrollably.", SPAN_WARNING("You tremble uncontrollably."))
|
|
to_chat(src, SPAN_CULT(pick("You feel fingers tracing up your back.", "You hear the distant wailing and sobbing of a departed loved one.", "You feel like you are being closely watched.", "You hear the hysterical laughter of a departed loved one.", "You no longer feel the reassuring presence of a departed loved one.", "You feel a hand taking hold of yours, digging its nails into you as it clings on.")))
|
|
if(haunted >= 10)
|
|
if(prob(5))
|
|
emote(pick("shiver", "twitch"))
|
|
to_chat(src, SPAN_CULT(pick("You feel a cold and threatening air wrapping around you.", "Whispering shadows, ceaseless in their demands, twist your thoughts...", "The whispering, anything to make them stop!", "Your head spins amid the cacophony of screaming, wailing and maniacal laughter of distant loved ones.", "You feel vestiges of decaying souls cling to you, trying to re-enter the world of the living.")))
|
|
|
|
sprint_speed_factor = species.sprint_speed_factor
|
|
max_stamina = species.stamina
|
|
if(HAS_TRAIT(src, TRAIT_ORIGIN_STAMINA_BONUS))
|
|
max_stamina *= 1.1
|
|
stamina_recovery = species.stamina_recovery
|
|
sprint_cost_factor = species.sprint_cost_factor
|
|
|
|
if(CE_ADRENALINE in chem_effects)
|
|
sprint_speed_factor += 0.1*chem_effects[CE_ADRENALINE]
|
|
max_stamina *= 1 + chem_effects[CE_ADRENALINE]
|
|
sprint_cost_factor -= 0.35 * chem_effects[CE_ADRENALINE]
|
|
stamina_recovery += max ((stamina_recovery * 0.7 * chem_effects[CE_ADRENALINE]), 5)
|
|
|
|
var/obj/item/clothing/suit = wear_suit
|
|
var/protected = FALSE
|
|
if(suit && (suit.body_parts_covered & HANDS) && (suit.heat_protection & HANDS))
|
|
protected = TRUE
|
|
|
|
if(gloves && (gloves.heat_protection & HANDS))
|
|
protected = TRUE
|
|
|
|
if(!protected)
|
|
for(var/obj/item/held_item in src)
|
|
if(held_item.contaminated && !(species.flags & PHORON_IMMUNE))
|
|
if(held_item == r_hand)
|
|
apply_damage(GLOB.vsc.plc.CONTAMINATION_LOSS, DAMAGE_BURN, BP_R_HAND)
|
|
else if(held_item == l_hand)
|
|
apply_damage(GLOB.vsc.plc.CONTAMINATION_LOSS, DAMAGE_BURN, BP_L_HAND)
|
|
else
|
|
adjustFireLoss(GLOB.vsc.plc.CONTAMINATION_LOSS)
|
|
|
|
if (intoxication)
|
|
handle_intoxication()
|
|
|
|
if(status_flags & GODMODE) return 0 //godmode
|
|
|
|
if(species.light_dam)
|
|
var/light_amount = 0
|
|
if(isturf(loc))
|
|
var/turf/T = loc
|
|
light_amount = T.get_lumcount() * 10
|
|
if(light_amount > species.light_dam) //if there's enough light, start dying
|
|
take_overall_damage(5,5)
|
|
else //heal in the dark
|
|
heal_overall_damage(5,5)
|
|
|
|
// nutrition decrease over time
|
|
if(max_nutrition > 0)
|
|
if (nutrition > 0 && stat != 2)
|
|
adjustNutritionLoss(nutrition_loss * nutrition_attrition_rate)
|
|
|
|
if (nutrition / max_nutrition > CREW_NUTRITION_OVEREATEN)
|
|
adjustNutritionLoss(1)
|
|
if(overeatduration < 600) //capped so people don't take forever to unfat
|
|
overeatduration++
|
|
else
|
|
if(overeatduration > 1)
|
|
overeatduration -= 2 //doubled the unfat rate
|
|
|
|
// hydration decrease over time
|
|
if(max_hydration > 0)
|
|
if (hydration > 0 && stat != 2)
|
|
adjustHydrationLoss(hydration_loss * hydration_attrition_rate)
|
|
|
|
if (hydration / max_hydration > CREW_HYDRATION_OVERHYDRATED)
|
|
adjustHydrationLoss(2)
|
|
if(overdrinkduration < 600) //capped so people don't take forever to undrink
|
|
overdrinkduration++
|
|
else
|
|
if(overdrinkduration > 1)
|
|
overdrinkduration -= 2 //doubled the undrink rate
|
|
|
|
// TODO: stomach and bloodstream organ.
|
|
if(!isSynthetic())
|
|
handle_trace_chems()
|
|
if(vessel && (/singleton/reagent/blood in vessel.reagent_data))
|
|
// update the trace chems in our blood vessels
|
|
var/singleton/reagent/blood/B = GET_SINGLETON(/singleton/reagent/blood)
|
|
B.handle_trace_chems(vessel)
|
|
|
|
for(var/_R in chem_doses)
|
|
if ((_R in bloodstr.reagent_volumes) || (_R in ingested.reagent_volumes) || (_R in breathing.reagent_volumes) || (_R in touching.reagent_volumes))
|
|
continue
|
|
chem_doses -= _R //We're no longer metabolizing this reagent. Remove it from chem_doses
|
|
|
|
updatehealth()
|
|
|
|
return //TODO: DEFERRED
|
|
|
|
/mob/living/carbon/human/handle_regular_status_updates()
|
|
if(!handle_some_updates())
|
|
return 0
|
|
|
|
if(status_flags & GODMODE)
|
|
return 0
|
|
|
|
if(recently_slept)
|
|
recently_slept -= 1
|
|
|
|
//SSD check, if a logged player is awake put them back to sleep!
|
|
if(species.show_ssd && (!client && !vr_mob) && !teleop && ((world.realtime - disconnect_time) >= 5 MINUTES)) //only sleep after 5 minutes, should help those with intermittent internet connections
|
|
Sleeping(2)
|
|
if(stat == DEAD) //DEAD. BROWN BREAD. SWIMMING WITH THE SPESS CARP
|
|
blinded = 1
|
|
silent = 0
|
|
else //ALIVE. LIGHTS ARE ON
|
|
updatehealth() //TODO
|
|
|
|
if(handle_death_check())
|
|
death()
|
|
blinded = 1
|
|
silent = 0
|
|
return 1
|
|
|
|
if(hallucination)
|
|
if(HAS_TRAIT(src, TRAIT_BYPASS_HALLUCINATION_RESTRICTION) || !((species.flags & NO_POISON) && (species.flags & IS_PLANT)))
|
|
handle_hallucinations()
|
|
|
|
if(get_shock() >= species.total_health)
|
|
if(!stat && !paralysis)
|
|
to_chat(src, SPAN_WARNING("[species.halloss_message_self]"))
|
|
src.visible_message("<B>[src]</B> [species.halloss_message]")
|
|
Paralyse(10)
|
|
|
|
if(paralysis || sleeping || InStasis())
|
|
blinded = TRUE
|
|
if(sleeping && !stat)
|
|
species.sleep_msg(src)
|
|
set_stat(UNCONSCIOUS)
|
|
if(!sleeping_msg_debounce)
|
|
sleeping_msg_debounce = TRUE
|
|
to_chat(src, SPAN_NOTICE(FONT_LARGE("You are now unconscious.<br>You will not remember anything you \"see\" happening around you until you regain consciousness.")))
|
|
|
|
adjustHalLoss(-3)
|
|
if (species.tail)
|
|
animate_tail_reset()
|
|
if(prob(2) && is_asystole() && isSynthetic())
|
|
visible_message("<b>[src]</b> [pick("emits low pitched whirr","beeps urgently")].")
|
|
|
|
if(paralysis)
|
|
AdjustParalysis(-1)
|
|
|
|
else if(sleeping)
|
|
handle_dreams()
|
|
if(mind)
|
|
//Are they SSD? If so we'll keep them asleep but work off some of that sleep var in case of stoxin or similar.
|
|
if(client || sleeping > 3 || istype(bg))
|
|
if(sleeping_indefinitely)
|
|
sleep_buffer++
|
|
else
|
|
AdjustSleeping(-1)
|
|
if(prob(2) && health && !failed_last_breath && !InStasis())
|
|
if(!paralysis && species.snores)
|
|
emote(species.snore_key)
|
|
|
|
//CONSCIOUS
|
|
else if(!InStasis())
|
|
set_stat(CONSCIOUS)
|
|
sleeping_msg_debounce = FALSE
|
|
willfully_sleeping = FALSE
|
|
|
|
// Check everything else.
|
|
|
|
//Periodically double-check embedded_flag
|
|
if(embedded_flag && !(life_tick % 10))
|
|
if(!embedded_needs_process())
|
|
embedded_flag = 0
|
|
|
|
//Resting
|
|
if(resting)
|
|
dizziness = max(0, dizziness - 15)
|
|
jitteriness = max(0, jitteriness - 15)
|
|
drowsiness = max(0, drowsiness - 5)
|
|
adjustHalLoss(-3)
|
|
else
|
|
dizziness = max(0, dizziness - 3)
|
|
jitteriness = max(0, jitteriness - 3)
|
|
adjustHalLoss(-1)
|
|
|
|
//Other
|
|
handle_statuses()
|
|
|
|
if (drowsiness)
|
|
if (drowsiness < 0)
|
|
drowsiness = 0
|
|
else
|
|
drowsiness--
|
|
eye_blurry = max(drowsiness, eye_blurry)
|
|
if(drowsiness > 5)
|
|
if(prob(drowsiness/5))
|
|
slurring += rand(1, 5)
|
|
if(prob(3))
|
|
make_dizzy(100 + drowsiness)
|
|
if(!sleeping)
|
|
emote("yawn")
|
|
if(prob(drowsiness/10))
|
|
eye_blind += 2
|
|
|
|
// If you're dirty, your gloves will become dirty, too.
|
|
if(gloves && germ_level > gloves.germ_level && prob(10))
|
|
gloves.germ_level += 1
|
|
|
|
return 1
|
|
|
|
|
|
/mob/living/carbon/human
|
|
var/tmp/last_brute_overlay
|
|
var/tmp/last_frenzy_state
|
|
var/tmp/last_oxy_overlay
|
|
|
|
var/list/status_overlays = null
|
|
|
|
/mob/living/carbon/human/can_update_hud()
|
|
if((!client && !bg) || QDELETED(src))
|
|
return FALSE
|
|
return TRUE
|
|
|
|
// corresponds with the status overlay in hud_status.dmi
|
|
#define DRUNK_STRING "drunk"
|
|
#define BLEEDING_STRING "bleeding"
|
|
#define POSING_STRING "posing"
|
|
|
|
/mob/living/carbon/human/handle_regular_hud_updates()
|
|
if(hud_updateflag) // update our mob's hud overlays, AKA what others see flaoting above our head
|
|
handle_hud_list()
|
|
|
|
// now handle what we see on our screen
|
|
if(!..())
|
|
return
|
|
|
|
if(stat != DEAD)
|
|
if((stat == UNCONSCIOUS && health < maxHealth / 2) || paralysis || InStasis())
|
|
//Critical damage passage overlay
|
|
var/severity = 0
|
|
switch(health - maxHealth/2)
|
|
if(-20 to -10) severity = 1
|
|
if(-30 to -20) severity = 2
|
|
if(-40 to -30) severity = 3
|
|
if(-50 to -40) severity = 4
|
|
if(-60 to -50) severity = 5
|
|
if(-70 to -60) severity = 6
|
|
if(-80 to -70) severity = 7
|
|
if(-90 to -80) severity = 8
|
|
if(-95 to -90) severity = 9
|
|
if(-INFINITY to -95) severity = 10
|
|
if(paralysis || InStasis())
|
|
severity = max(severity, 8)
|
|
overlay_fullscreen("crit", /atom/movable/screen/fullscreen/crit, severity)
|
|
else
|
|
clear_fullscreen("crit")
|
|
//Oxygen damage overlay
|
|
if(getOxyLoss())
|
|
var/severity = 0
|
|
switch(getOxyLoss())
|
|
if(10 to 20) severity = 1
|
|
if(20 to 25) severity = 2
|
|
if(25 to 30) severity = 3
|
|
if(30 to 35) severity = 4
|
|
if(35 to 40) severity = 5
|
|
if(40 to 45) severity = 6
|
|
if(45 to INFINITY) severity = 7
|
|
overlay_fullscreen("oxy", /atom/movable/screen/fullscreen/oxy, severity)
|
|
else
|
|
clear_fullscreen("oxy")
|
|
|
|
//Fire and Brute damage overlay (BSSR)
|
|
var/hurtdamage = src.getBruteLoss() + src.getFireLoss() + damageoverlaytemp
|
|
damageoverlaytemp = 0 // We do this so we can detect if someone hits us or not.
|
|
if(hurtdamage)
|
|
var/severity = 0
|
|
switch(hurtdamage)
|
|
if(10 to 25) severity = 1
|
|
if(25 to 40) severity = 2
|
|
if(40 to 55) severity = 3
|
|
if(55 to 70) severity = 4
|
|
if(70 to 85) severity = 5
|
|
if(85 to INFINITY) severity = 6
|
|
overlay_fullscreen("brute", /atom/movable/screen/fullscreen/brute, severity)
|
|
else
|
|
clear_fullscreen("brute")
|
|
|
|
if(paralysis_indicator)
|
|
if(paralysis)
|
|
paralysis_indicator.icon_state = "paralysis1"
|
|
else
|
|
paralysis_indicator.icon_state = "paralysis0"
|
|
|
|
if(healths)
|
|
healths.overlays.Cut()
|
|
if (chem_effects[CE_PAINKILLER] > 100)
|
|
healths.icon_state = "health_numb"
|
|
else
|
|
// Generate a by-limb health display.
|
|
healths.icon_state = "blank"
|
|
|
|
var/no_damage = 1
|
|
var/trauma_val = 0 // Used in calculating softcrit/hardcrit indicators.
|
|
if(can_feel_pain())
|
|
trauma_val = max(shock_stage,get_shock())/(species.total_health-100)
|
|
// Collect and apply the images all at once to avoid appearance churn.
|
|
var/list/health_images = list()
|
|
for(var/obj/item/organ/external/E in organs)
|
|
if(no_damage && (E.brute_dam || E.burn_dam))
|
|
no_damage = 0
|
|
health_images += E.get_damage_hud_image()
|
|
|
|
// Add wound overlays
|
|
for(var/obj/item/organ/external/O in organs)
|
|
if(O.damage_state == "00") continue
|
|
var/cache_index = "[O.damage_state]/[O.icon_name]/[get_blood_color()]/[species.get_bodytype()]"
|
|
var/list/damage_icon_parts = SSicon_cache.damage_icon_parts
|
|
var/icon/DI = damage_icon_parts[cache_index]
|
|
if(!DI)
|
|
DI = new /icon(species.damage_overlays, O.damage_state) // the damage icon for whole human
|
|
DI.Blend(new /icon(species.damage_mask, O.icon_name), ICON_MULTIPLY) // mask with this organ's pixels
|
|
DI.Blend(get_blood_color(), ICON_MULTIPLY)
|
|
damage_icon_parts[cache_index] = DI
|
|
health_images += DI
|
|
if(O.is_stump())
|
|
continue
|
|
var/bandage_icon = species.bandages_icon
|
|
if(!bandage_icon)
|
|
continue
|
|
var/bandage_level = O.bandage_level
|
|
if(bandage_level)
|
|
health_images += image(bandage_icon, "[O.icon_name][bandage_level]")
|
|
|
|
// Apply a fire overlay if we're burning.
|
|
if(on_fire)
|
|
var/image/burning_image = image('icons/mob/screen1_health.dmi', "burning", pixel_x = species.healths_overlay_x)
|
|
var/midway_point = FIRE_MAX_STACKS / 2
|
|
burning_image.color = color_rotation((midway_point - fire_stacks) * 3)
|
|
|
|
// Show a general pain/crit indicator if needed.
|
|
if(is_asystole())
|
|
var/image/hardcrit_image = image('icons/mob/screen1_health.dmi', "hardcrit", pixel_x = species.healths_overlay_x)
|
|
health_images += hardcrit_image
|
|
else if(trauma_val)
|
|
if(can_feel_pain())
|
|
if(trauma_val > 0.7)
|
|
var/image/softcrit_image = image('icons/mob/screen1_health.dmi', "softcrit", pixel_x = species.healths_overlay_x)
|
|
health_images += softcrit_image
|
|
if(trauma_val >= 1)
|
|
var/image/hardcrit_image = image('icons/mob/screen1_health.dmi', "hardcrit", pixel_x = species.healths_overlay_x)
|
|
health_images += hardcrit_image
|
|
else if(no_damage)
|
|
var/image/fullhealth_image = image('icons/mob/screen1_health.dmi', "fullhealth", pixel_x = species.healths_overlay_x)
|
|
health_images += fullhealth_image
|
|
|
|
healths.overlays += health_images
|
|
|
|
//Update hunger and thirst UI less often, its not important
|
|
if((life_tick % 3 == 0))
|
|
if(nutrition_icon)
|
|
var/nut_factor = max_nutrition ? clamp(nutrition / max_nutrition, 0, 1) : 1
|
|
var/nut_icon = 5 //5 to 0, with 5 being lowest, 0 being highest
|
|
if(nut_factor >= CREW_NUTRITION_OVEREATEN)
|
|
nut_icon = 0
|
|
else if (nut_factor >= CREW_NUTRITION_FULL)
|
|
nut_icon = 1
|
|
else if (nut_factor >= CREW_NUTRITION_SLIGHTLYHUNGRY)
|
|
nut_icon = 2
|
|
else if (nut_factor >= CREW_NUTRITION_HUNGRY)
|
|
nut_icon = 3
|
|
else if (nut_factor >= CREW_NUTRITION_VERYHUNGRY)
|
|
nut_icon = 4
|
|
var/new_val = "[isSynthetic() ? "charge" : "nutrition"][nut_icon]"
|
|
if (nutrition_icon.icon_state != new_val)
|
|
nutrition_icon.icon_state = new_val
|
|
|
|
if(hydration_icon)
|
|
var/hyd_factor = max_hydration ? clamp(hydration / max_hydration, 0, 1) : 1
|
|
var/hyd_icon = 5
|
|
if(hyd_factor >= CREW_HYDRATION_OVERHYDRATED)
|
|
hyd_icon = 0
|
|
else if(hyd_factor >= CREW_HYDRATION_HYDRATED)
|
|
hyd_icon = 1
|
|
else if(hyd_factor >= CREW_HYDRATION_SLIGHTLYTHIRSTY)
|
|
hyd_icon = 2
|
|
else if(hyd_factor >= CREW_HYDRATION_THIRSTY)
|
|
hyd_icon = 3
|
|
else if(hyd_factor >= CREW_HYDRATION_VERYTHIRSTY)
|
|
hyd_icon = 4
|
|
var/new_val = "thirst[hyd_icon]"
|
|
if (hydration_icon.icon_state != new_val)
|
|
hydration_icon.icon_state = new_val
|
|
|
|
if(isSynthetic())
|
|
var/obj/item/organ/internal/machine/power_core/IC = internal_organs_by_name[BP_CELL]
|
|
if(istype(IC) && IC.is_usable())
|
|
var/chargeNum = clamp(Ceiling(IC.percent()/25), 0, 4) //0-100 maps to 0-4, but give it a paranoid clamp just in case.
|
|
cells.icon_state = "charge[chargeNum]"
|
|
else
|
|
cells.icon_state = "charge-empty"
|
|
|
|
if(pressure)
|
|
var/new_pressure = "pressure[pressure_alert]"
|
|
if (pressure.icon_state != new_pressure)
|
|
pressure.icon_state = new_pressure
|
|
|
|
if(toxin)
|
|
var/new_tox = (phoron_alert) ? "tox1" : "tox0"
|
|
if (toxin.icon_state != new_tox)
|
|
toxin.icon_state = new_tox
|
|
|
|
if(oxygen)
|
|
var/new_oxy = (oxygen_alert) ? "oxy1" : "oxy0"
|
|
if (oxygen.icon_state != new_oxy)
|
|
oxygen.icon_state = new_oxy
|
|
|
|
if(fire)
|
|
//fire_alert is either 0 if no alert, 1 for cold and 2 for heat.
|
|
var/new_fire = fire_alert ? "fire[fire_alert]" : "fire0"
|
|
if (fire.icon_state != new_fire)
|
|
fire.icon_state = new_fire
|
|
|
|
if(bodytemp)
|
|
var/new_temp
|
|
if (!species)
|
|
switch(bodytemperature) //310.055 optimal body temp
|
|
if(370 to INFINITY)
|
|
new_temp = "temp4"
|
|
if(350 to 370)
|
|
new_temp = "temp3"
|
|
if(335 to 350)
|
|
new_temp = "temp2"
|
|
if(320 to 335)
|
|
new_temp = "temp1"
|
|
if(300 to 320)
|
|
new_temp = "temp0"
|
|
if(295 to 300)
|
|
new_temp = "temp-1"
|
|
if(280 to 295)
|
|
new_temp = "temp-2"
|
|
if(260 to 280)
|
|
new_temp = "temp-3"
|
|
else
|
|
new_temp = "temp-4"
|
|
else
|
|
//TODO: precalculate all of this stuff when the species datum is created
|
|
var/base_temperature = species.body_temperature
|
|
if(base_temperature == null) //some species don't have a set metabolic temperature
|
|
base_temperature = (species.heat_level_1 + species.cold_level_1)/2
|
|
|
|
var/temp_step
|
|
if (bodytemperature >= base_temperature)
|
|
temp_step = (species.heat_level_1 - base_temperature)/4
|
|
|
|
if (bodytemperature >= species.heat_level_1)
|
|
new_temp = "temp4"
|
|
else if (bodytemperature >= base_temperature + temp_step*3)
|
|
new_temp = "temp3"
|
|
else if (bodytemperature >= base_temperature + temp_step*2)
|
|
new_temp = "temp2"
|
|
else if (bodytemperature >= base_temperature + temp_step*1)
|
|
new_temp = "temp1"
|
|
else
|
|
new_temp = "temp0"
|
|
|
|
else if (bodytemperature < base_temperature)
|
|
temp_step = (base_temperature - species.cold_level_1)/4
|
|
|
|
if (bodytemperature <= species.cold_level_1)
|
|
new_temp = "temp-4"
|
|
else if (bodytemperature <= base_temperature - temp_step*3)
|
|
new_temp = "temp-3"
|
|
else if (bodytemperature <= base_temperature - temp_step*2)
|
|
new_temp = "temp-2"
|
|
else if (bodytemperature <= base_temperature - temp_step*1)
|
|
new_temp = "temp-1"
|
|
else
|
|
new_temp = "temp0"
|
|
|
|
if (bodytemp.icon_state != new_temp)
|
|
bodytemp.icon_state = new_temp
|
|
|
|
if(client)
|
|
var/has_drunk_status = LAZYISIN(status_overlays, DRUNK_STRING)
|
|
if(is_drunk())
|
|
if(!has_drunk_status)
|
|
add_status_to_hud(DRUNK_STRING, SPAN_GOOD("You are drunk. Your words are slurred, and your movements are uncoordinated."))
|
|
else if(has_drunk_status)
|
|
client.screen -= status_overlays[DRUNK_STRING]
|
|
qdel(status_overlays[DRUNK_STRING])
|
|
status_overlays -= DRUNK_STRING
|
|
|
|
var/has_bleeding_limb = FALSE
|
|
var/has_bleeding_status = LAZYISIN(status_overlays, BLEEDING_STRING)
|
|
for(var/obj/item/organ/external/damaged_limb as anything in bad_external_organs)
|
|
if(damaged_limb.status & ORGAN_BLEEDING)
|
|
has_bleeding_limb = TRUE
|
|
break
|
|
if(has_bleeding_limb)
|
|
if(!has_bleeding_status)
|
|
add_status_to_hud(BLEEDING_STRING, SPAN_HIGHDANGER("Blood gushes from one of your bodyparts, inspect yourself and seal the wound."))
|
|
else if(has_bleeding_status)
|
|
client.screen -= status_overlays[BLEEDING_STRING]
|
|
qdel(status_overlays[BLEEDING_STRING])
|
|
status_overlays -= BLEEDING_STRING
|
|
|
|
var/has_posing_status = LAZYISIN(status_overlays, POSING_STRING)
|
|
if(pose)
|
|
if(!has_posing_status)
|
|
add_status_to_hud(POSING_STRING, SPAN_NOTICE("You are posing. Your current pose is \"[pose]\""))
|
|
else if(has_posing_status)
|
|
client.screen -= status_overlays[POSING_STRING]
|
|
qdel(status_overlays[POSING_STRING])
|
|
status_overlays -= POSING_STRING
|
|
|
|
UNSETEMPTY(status_overlays)
|
|
else
|
|
for(var/status in status_overlays)
|
|
qdel(status_overlays[status])
|
|
status_overlays = null
|
|
return 1
|
|
|
|
#undef DRUNK_STRING
|
|
#undef BLEEDING_STRING
|
|
#undef POSING_STRING
|
|
|
|
/mob/living/carbon/human/proc/add_status_to_hud(var/set_overlay, var/set_status_message)
|
|
var/atom/movable/screen/status/new_status = new /atom/movable/screen/status(null, ui_style2icon(client.prefs.UI_style), set_overlay, set_status_message)
|
|
new_status.alpha = client.prefs.UI_style_alpha
|
|
new_status.color = client.prefs.UI_style_color
|
|
new_status.screen_loc = get_status_loc(status_overlays ? LAZYLEN(status_overlays) + 1 : 1)
|
|
client.screen += new_status
|
|
LAZYSET(status_overlays, set_overlay, new_status)
|
|
|
|
/mob/living/carbon/human/proc/get_status_loc(var/placement)
|
|
var/col = ((placement - 1)%(13)) + 1
|
|
var/coord_col = "-[col-1]"
|
|
var/coord_col_offset = "-[4+2*col]"
|
|
|
|
var/row = round((placement-1)/13)
|
|
var/coord_row = "[-1 - row]"
|
|
var/coord_row_offset = 8
|
|
return "EAST[coord_col]:[coord_col_offset],NORTH[coord_row]:[coord_row_offset]"
|
|
|
|
/mob/living/carbon/human/handle_random_events()
|
|
if(InStasis())
|
|
return
|
|
|
|
// Puke if toxloss is too high
|
|
if(!stat)
|
|
if (getToxLoss() >= 45 && !lastpuke)
|
|
if (prob(3))
|
|
delayed_vomit()
|
|
else if (prob(1))
|
|
vomit()
|
|
|
|
//0.1% chance of playing a scary sound to someone who's in complete darkness
|
|
if(isturf(loc) && rand(1,1000) == 1)
|
|
var/turf/T = loc
|
|
if (T.get_lumcount() < 0.01) // give a little bit of tolerance for near-dark areas.
|
|
playsound(null, pick(GLOB.scarySounds), 50, TRUE)
|
|
|
|
if(HAS_TRAIT(src, TRAIT_ORIGIN_DARK_AFRAID))
|
|
if(T.get_lumcount() < 0.1)
|
|
if(prob(2))
|
|
var/list/assunzione_messages = list(
|
|
"You feel a bit afraid...",
|
|
"You feel somewhat nervous...",
|
|
"You could use a little light here...",
|
|
"Ennoia be with you, it's a bit too dark..."
|
|
)
|
|
to_chat(src, SPAN_WARNING(pick(assunzione_messages)))
|
|
|
|
if(HAS_TRAIT(src, TRAIT_ORIGIN_LIGHT_SENSITIVE))
|
|
if(T.get_lumcount() > 0.8)
|
|
if(prob(1))
|
|
if(prob(5))
|
|
var/list/eye_sensitivity_messages = list(
|
|
"Your eyes tire a bit.",
|
|
"Your eyes sting a little.",
|
|
"Your vision feels a bit strained."
|
|
)
|
|
to_chat(src, SPAN_WARNING(pick(eye_sensitivity_messages)))
|
|
|
|
/mob/living/carbon/human/proc/handle_changeling()
|
|
if(mind)
|
|
var/datum/changeling/changeling = mind.antag_datums[MODE_CHANGELING]
|
|
if(changeling)
|
|
changeling.regenerate()
|
|
|
|
/**
|
|
* This proc assumes that if traumatic_shock = null, then a shock value was NOT passed in, and thus it calculates it itself.
|
|
* If you for some reason need to call this alongside a lot of other shit that needs shock, make sure you cache that value, because calculating it is expensive.
|
|
*/
|
|
/mob/living/carbon/human/proc/handle_shock(traumatic_shock = null)
|
|
if(status_flags & GODMODE)
|
|
return 0
|
|
var/is_asystole = is_asystole()
|
|
if(is_asystole && isSynthetic())
|
|
if(!lying && !buckled_to)
|
|
to_chat(src, SPAN_WARNING("You don't have enough energy to function!"))
|
|
Paralyse(3)
|
|
return
|
|
if(!can_feel_pain())
|
|
if(isSynthetic() &&(get_total_health() < maxHealth * 0.5))
|
|
stuttering = max(stuttering, 5)
|
|
return
|
|
|
|
if(is_asystole)
|
|
shock_stage = max(shock_stage + 1, 61)
|
|
|
|
if(isnull(traumatic_shock))
|
|
traumatic_shock = get_shock()
|
|
|
|
if(traumatic_shock >= max(30, 0.8*shock_stage))
|
|
shock_stage += 1
|
|
else if (!is_asystole)
|
|
shock_stage = min(shock_stage, 160)
|
|
var/recovery = 1
|
|
if(traumatic_shock < 0.5 * shock_stage) //lower shock faster if pain is gone completely
|
|
recovery++
|
|
if(traumatic_shock < 0.25 * shock_stage)
|
|
recovery++
|
|
shock_stage = max(shock_stage - recovery, 0)
|
|
return
|
|
|
|
if(stat)
|
|
return 0
|
|
|
|
if(shock_stage == 10)
|
|
custom_pain("[pick(species.pain_messages)]!", 10, nohalloss = TRUE)
|
|
|
|
if(shock_stage >= 30)
|
|
if(shock_stage == 30)
|
|
visible_message("<b>[src]</b> is having trouble keeping [get_pronoun("his")] eyes open.")
|
|
if(prob(30))
|
|
eye_blurry = max(2, eye_blurry)
|
|
stuttering = max(stuttering, 5)
|
|
|
|
if(shock_stage == 40)
|
|
custom_pain("[pick("The pain is excruciating", "Please, just end the pain", "Your whole body is going numb")]!", 40, nohalloss = TRUE)
|
|
|
|
if (shock_stage >= 60)
|
|
if(shock_stage == 60)
|
|
visible_message("<b>[src]</b>'s body becomes limp.", SPAN_DANGER("Your body becomes limp."))
|
|
if (prob(2))
|
|
custom_pain("[pick("The pain is excruciating", "Please, just end the pain", "Your whole body is going numb")]!", shock_stage, nohalloss = TRUE)
|
|
Weaken(20)
|
|
|
|
if(shock_stage >= 80)
|
|
if (prob(5))
|
|
custom_pain("[pick("The pain is excruciating", "Please, just end the pain", "Your whole body is going numb")]!", shock_stage, nohalloss = TRUE)
|
|
Weaken(20)
|
|
|
|
if(shock_stage >= 120)
|
|
if (prob(2))
|
|
custom_pain("[pick("You black out", "You feel like you could die any moment now", "You're about to lose consciousness")]!", shock_stage, nohalloss = TRUE)
|
|
Paralyse(5)
|
|
|
|
if(shock_stage == 150)
|
|
visible_message("<b>[src]</b> can no longer stand, collapsing!")
|
|
Weaken(20)
|
|
|
|
if(shock_stage >= 150)
|
|
Weaken(20)
|
|
|
|
|
|
/*
|
|
Called by life(), instead of having the individual hud items update icons each tick and check for status changes
|
|
we only set those statuses and icons upon changes. Then those HUD items will simply add those pre-made images.
|
|
This proc below is only called when those HUD elements need to change as determined by the mobs hud_updateflag.
|
|
*/
|
|
|
|
|
|
/mob/living/carbon/human/proc/handle_hud_list(var/force_update = FALSE)
|
|
if(force_update)
|
|
hud_updateflag = 1022
|
|
|
|
if (BITTEST(hud_updateflag, HEALTH_HUD))
|
|
if(hud_list[HEALTH_HUD])
|
|
var/image/holder = hud_list[HEALTH_HUD]
|
|
if(stat == DEAD || (status_flags & FAKEDEATH))
|
|
holder.icon_state = "0" // X_X
|
|
else if(is_asystole())
|
|
holder.icon_state = "flatline"
|
|
else
|
|
holder.icon_state = "[pulse()]"
|
|
hud_list[HEALTH_HUD] = holder
|
|
if(hud_list[TRIAGE_HUD])
|
|
var/image/holder = hud_list[TRIAGE_HUD]
|
|
holder.icon_state = triage_tag
|
|
hud_list[TRIAGE_HUD] = holder
|
|
|
|
if (BITTEST(hud_updateflag, LIFE_HUD) && hud_list[LIFE_HUD])
|
|
var/image/holder = hud_list[LIFE_HUD]
|
|
if(stat == DEAD || (status_flags & FAKEDEATH))
|
|
holder.icon_state = "huddead"
|
|
else
|
|
holder.icon_state = "hudhealthy"
|
|
hud_list[LIFE_HUD] = holder
|
|
|
|
if (BITTEST(hud_updateflag, STATUS_HUD) && hud_list[STATUS_HUD] && hud_list[STATUS_HUD_OOC])
|
|
var/image/holder = hud_list[STATUS_HUD]
|
|
if(stat == DEAD || (status_flags & FAKEDEATH))
|
|
holder.icon_state = "huddead"
|
|
else if(status_flags & XENO_HOST)
|
|
holder.icon_state = "hudxeno"
|
|
else
|
|
holder.icon_state = "hudhealthy"
|
|
|
|
var/image/holder2 = hud_list[STATUS_HUD_OOC]
|
|
if(stat == DEAD || (status_flags & FAKEDEATH))
|
|
holder2.icon_state = "huddead"
|
|
else if(status_flags & XENO_HOST)
|
|
holder2.icon_state = "hudxeno"
|
|
else if(has_brain_worms())
|
|
holder2.icon_state = "hudbrainworm"
|
|
else
|
|
holder2.icon_state = "hudhealthy"
|
|
|
|
hud_list[STATUS_HUD] = holder
|
|
hud_list[STATUS_HUD_OOC] = holder2
|
|
|
|
if (BITTEST(hud_updateflag, ID_HUD) && hud_list[ID_HUD])
|
|
var/image/holder = hud_list[ID_HUD]
|
|
|
|
//The following function is found in code/defines/procs/hud.dm
|
|
holder.icon_state = get_sec_hud_icon(src)
|
|
hud_list[ID_HUD] = holder
|
|
|
|
if (BITTEST(hud_updateflag, WANTED_HUD))
|
|
var/image/holder = hud_list[WANTED_HUD]
|
|
holder.icon_state = "hudblank"
|
|
var/perpname = name
|
|
if(wear_id)
|
|
var/obj/item/card/id/I = wear_id.GetID()
|
|
if(I)
|
|
perpname = I.registered_name
|
|
|
|
var/datum/record/general/R = SSrecords.find_record("name", perpname)
|
|
if(istype(R) && istype(R.security))
|
|
if(R.security.criminal == "*Arrest*")
|
|
holder.icon_state = "hudwanted"
|
|
else if(R.security.criminal == "Search")
|
|
holder.icon_state = "hudsearch"
|
|
else if(R.security.criminal == "Incarcerated")
|
|
holder.icon_state = "hudprisoner"
|
|
else if(R.security.criminal == "Parolled")
|
|
holder.icon_state = "hudparolled"
|
|
else if(R.security.criminal == "Released")
|
|
holder.icon_state = "hudreleased"
|
|
hud_list[WANTED_HUD] = holder
|
|
|
|
if ( BITTEST(hud_updateflag, IMPLOYAL_HUD) \
|
|
|| BITTEST(hud_updateflag, IMPCHEM_HUD) \
|
|
|| BITTEST(hud_updateflag, IMPTRACK_HUD))
|
|
|
|
var/image/holder1 = hud_list[IMPTRACK_HUD]
|
|
var/image/holder2 = hud_list[IMPLOYAL_HUD]
|
|
var/image/holder3 = hud_list[IMPCHEM_HUD]
|
|
|
|
holder1.icon_state = "hudblank"
|
|
holder2.icon_state = "hudblank"
|
|
holder3.icon_state = "hudblank"
|
|
for(var/obj/item/implant/I in src)
|
|
if(I.implanted)
|
|
if(istype(I,/obj/item/implant/tracking))
|
|
holder1.icon_state = "hud_imp_tracking"
|
|
if(istype(I,/obj/item/implant/mindshield) && !istype(I,/obj/item/implant/mindshield/loyalty))
|
|
holder2.icon_state = "hud_imp_loyal"
|
|
if(istype(I,/obj/item/implant/chem))
|
|
holder3.icon_state = "hud_imp_chem"
|
|
|
|
hud_list[IMPTRACK_HUD] = holder1
|
|
hud_list[IMPLOYAL_HUD] = holder2
|
|
hud_list[IMPCHEM_HUD] = holder3
|
|
|
|
if (BITTEST(hud_updateflag, SPECIALROLE_HUD))
|
|
var/image/holder = hud_list[SPECIALROLE_HUD]
|
|
holder.icon_state = "hudblank"
|
|
if(mind && mind.special_role)
|
|
if(GLOB.hud_icon_reference[mind.special_role])
|
|
holder.icon_state = GLOB.hud_icon_reference[mind.special_role]
|
|
else
|
|
holder.icon_state = "hudsyndicate"
|
|
hud_list[SPECIALROLE_HUD] = holder
|
|
hud_updateflag = 0
|
|
|
|
/**
|
|
* If parent proc returns TRUE, this entity is no longer on fire (nothing to see here, in that case).
|
|
* Otherwise, we first get burn temperature, calculated from the entity's current fire stacks.
|
|
* This has a minimum of 700 K (approx. temp of a cool flame). The maximum temperature of the air
|
|
* to which a burning creature is exposed, at any point during its fiery adventure, is the base
|
|
* temperature of the fire, scaling upwards with fire_stacks.
|
|
*/
|
|
/mob/living/carbon/human/handle_fire(var/seconds_per_tick, var/datum/gas_mixture/environment)
|
|
if(..())
|
|
return
|
|
|
|
var/burn_temperature = fire_burn_temperature()
|
|
var/thermal_protection = get_heat_protection(burn_temperature)
|
|
|
|
// Increment bodytemp up by up to BODYTEMP_HEATING_MAX C / sec, as modified by thermal protection.
|
|
if (thermal_protection < 1 && bodytemperature < burn_temperature)
|
|
bodytemperature += round(BODYTEMP_HEATING_MAX * (1-thermal_protection) * 20 * seconds_per_tick, 1)
|
|
|
|
/mob/living/carbon/human/rejuvenate()
|
|
restore_blood()
|
|
..()
|
|
|
|
/mob/living/carbon/human/handle_vision()
|
|
if(client)
|
|
client.screen.Remove(GLOB.global_hud.blurry, GLOB.global_hud.druggy, GLOB.global_hud.vimpaired, GLOB.global_hud.darkMask, GLOB.global_hud.nvg, GLOB.global_hud.thermal, GLOB.global_hud.meson, GLOB.global_hud.science)
|
|
var/machine_has_equipment_vision = FALSE
|
|
if(machine)
|
|
var/viewflags = machine.check_eye(src)
|
|
if(viewflags < 0)
|
|
reset_view(null, 0)
|
|
else if(viewflags)
|
|
set_sight(sight|viewflags)
|
|
machine_has_equipment_vision = machine.grants_equipment_vision(src)
|
|
if(eyeobj && eyeobj.owner != src)
|
|
reset_view(null)
|
|
|
|
if((mRemote in mutations) && remoteview_target && remoteview_target.stat != CONSCIOUS)
|
|
remoteview_target = null
|
|
reset_view(null, 0)
|
|
|
|
update_equipment_vision(machine_has_equipment_vision)
|
|
species.handle_vision(src)
|
|
|
|
/mob/living/carbon/human/handle_hearing()
|
|
..()
|
|
|
|
if(ear_damage < HEARING_DAMAGE_LIMIT)
|
|
//Hearing aids allow our ear_deaf to reach zero, if we have a hearing disability
|
|
if(ear_deaf <= 1 && (sdisabilities & DEAF) && has_hearing_aid())
|
|
setEarDamage(-1, max(ear_deaf-1, 0))
|
|
|
|
var/ear_safety = get_hearing_protection()
|
|
|
|
if(ear_safety >= EAR_PROTECTION_MAJOR) // resting your ears make them heal faster
|
|
adjustEarDamage(-0.15, 0)
|
|
setEarDamage(-1)
|
|
else if(ear_safety > EAR_PROTECTION_NONE)
|
|
adjustEarDamage(-0.10, 0)
|
|
else if(ear_damage < HEARING_DAMAGE_SLOW_HEAL) //ear damage heals slowly under this threshold. otherwise you'll need earmuffs
|
|
adjustEarDamage(-0.05, 0)
|
|
|
|
/mob/living/carbon/human/update_sight()
|
|
..()
|
|
if(stat == DEAD)
|
|
return
|
|
if((mutations & XRAY))
|
|
set_sight(sight|SEE_TURFS|SEE_MOBS|SEE_OBJS)
|
|
lighting_alpha = default_lighting_alpha
|
|
|
|
/**
|
|
* This proc assumes that if shock_value = null, then a shock value was NOT passed in, and thus it calculates it itself.
|
|
* If you for some reason need to call this alongside a lot of other shit that needs shock, make sure you cache that value, because calculating it is expensive.
|
|
*/
|
|
/mob/living/carbon/human/proc/handle_stamina(traumatic_shock = null)
|
|
if (species.stamina == -1) //If species stamina is -1, it has special mechanics which will be handled elsewhere
|
|
return //so quit this function
|
|
|
|
if (!exhaust_threshold) // Also quit if there's no exhaust threshold specified, because division by 0 is amazing.
|
|
return
|
|
|
|
if(isnull(traumatic_shock))
|
|
traumatic_shock = get_shock() // used again later for stamina regeneration
|
|
if (failed_last_breath || (getOxyLoss() + traumatic_shock) > exhaust_threshold)//Can't catch our breath if we're suffocating
|
|
flash_pain(getOxyLoss()/2)
|
|
return
|
|
|
|
if (nutrition <= 0)
|
|
if (prob(1.5))
|
|
to_chat(src, SPAN_WARNING("You feel hungry and exhausted, eat something to regain your energy!"))
|
|
return
|
|
|
|
if (hydration <= 0)
|
|
if (prob(1.5))
|
|
to_chat(src, SPAN_WARNING("You feel thirsty and exhausted, drink something to regain your energy!"))
|
|
return
|
|
|
|
if (stamina != max_stamina)
|
|
//Any suffocation damage slows stamina regen.
|
|
//This includes oxyloss from low blood levels
|
|
var/regen = stamina_recovery * (1 - min(((getOxyLoss()) / exhaust_threshold) + (traumatic_shock / exhaust_threshold), 1))
|
|
if(is_drowsy())
|
|
regen *= 0.85
|
|
if (regen > 0)
|
|
stamina = min(max_stamina, stamina+regen)
|
|
adjustNutritionLoss(stamina_recovery*0.09)
|
|
adjustHydrationLoss(stamina_recovery*0.32)
|
|
if (client)
|
|
hud_used.move_intent.update_move_icon(src)
|
|
|
|
/mob/living/carbon/human/proc/update_oxy_overlay()
|
|
var/new_oxy
|
|
if(getOxyLoss())
|
|
var/severity = 0
|
|
switch(getOxyLoss())
|
|
if(10 to 20) severity = 1
|
|
if(20 to 25) severity = 2
|
|
if(25 to 30) severity = 3
|
|
if(30 to 35) severity = 4
|
|
if(35 to 40) severity = 5
|
|
if(40 to 45) severity = 6
|
|
if(45 to INFINITY) severity = 7
|
|
new_oxy = "oxydamageoverlay[severity]"
|
|
|
|
if(new_oxy != last_oxy_overlay)
|
|
damageoverlay.CutOverlays(last_oxy_overlay)
|
|
damageoverlay.AddOverlays(new_oxy)
|
|
last_oxy_overlay = new_oxy
|
|
else if (last_oxy_overlay)
|
|
damageoverlay.CutOverlays(last_oxy_overlay)
|
|
last_oxy_overlay = null
|
|
|
|
//Fevers
|
|
//This handles infection fevers as well as fevers caused by chem effects
|
|
/mob/living/carbon/human/proc/handle_fever()
|
|
var/normal_temp = species?.body_temperature || (T0C+37)
|
|
//If we have infections, they give us a fever. Get all of their germ levels and find what our bodytemp will raise by.
|
|
var/fever = get_infection_germ_level() / INFECTION_LEVEL_ONE
|
|
//See what chemicals in our body affect our fever for better or worse
|
|
if(CE_FEVER in chem_effects)
|
|
fever += chem_effects[CE_FEVER]
|
|
if(CE_NOFEVER in chem_effects)
|
|
fever -= chem_effects[CE_NOFEVER]
|
|
|
|
//Apply changes to body temp. I absolutely hate body temp code -Doxx
|
|
if(fever < 0) //If we have enough anti-fever meds to bring us back towards normal temperature, do so.
|
|
if(bodytemperature >= normal_temp) //We don't have any effect if we're colder than normal.
|
|
bodytemperature = max(bodytemperature + fever, normal_temp)
|
|
return
|
|
if(fever > 0) //We're getting a fever, raise body temp. 10C above normal is our max for fevers.
|
|
if(bodytemperature < normal_temp) //If we're colder than usual, we'll slowly raise to normal temperature
|
|
bodytemperature = min(bodytemperature + fever, normal_temp)
|
|
else if(bodytemperature <= normal_temp + 10) //If we're hotter than max due to like, being on fire, don't keep increasing.
|
|
bodytemperature = normal_temp + min(fever, 10) //We use normal_temp here to maintain a steady temperature, otherwise even a small infection steadily increases bodytemp to max. This way it's easier to diagnose the intensity of an infection based on how bad the fever is.
|
|
//Apply side effects for having a fever. Separate from body temp changes.
|
|
if(fever >= 2)
|
|
do_fever_effects(fever)
|
|
|
|
|
|
//Getting the total germ level for all infected organs, affects fever
|
|
/mob/living/carbon/human/proc/get_infection_germ_level()
|
|
var/germs
|
|
for(var/obj/item/organ/I in internal_organs)
|
|
if(I.is_infected())
|
|
germs += I.germ_level
|
|
for(var/obj/item/organ/external/E in organs)
|
|
if(E.is_infected())
|
|
germs += E.germ_level
|
|
return germs
|
|
|
|
/mob/living/carbon/human/proc/do_fever_effects(var/fever)
|
|
var/list/fever_messages = list("You feel cold and clammy...", "You shiver as if a breeze has passed through.", "Your muscles ache.", "You feel tired and fatigued.")
|
|
notify_message(SPAN_WARNING(pick(fever_messages)), 30 SECONDS, key = "fever_effect_message")
|
|
if(prob(25)) // once every 8 seconds, roughly
|
|
drowsiness += 5
|
|
if(prob(20))
|
|
adjustHalLoss(5 * min(fever, 5)) // muscle pain from fever
|
|
if(fever >= 7 && prob(10)) // your organs are boiling, figuratively speaking
|
|
var/obj/item/organ/internal/IO = pick(internal_organs)
|
|
IO.take_internal_damage(1)
|