diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index f586ecd56c..1bbb8845e7 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -252,6 +252,7 @@ // called when something steps onto a human // this handles mulebots and vehicles +// and now mobs on fire /mob/living/carbon/human/Crossed(var/atom/movable/AM) if(istype(AM, /mob/living/bot/mulebot)) var/mob/living/bot/mulebot/MB = AM @@ -261,6 +262,8 @@ var/obj/vehicle/V = AM V.RunOver(src) + spread_fire(AM) + // Get rank from ID, ID inside PDA, PDA, ID in wallet, etc. /mob/living/carbon/human/proc/get_authentification_rank(var/if_no_id = "No id", var/if_no_job = "No job") var/obj/item/device/pda/pda = wear_id @@ -1505,6 +1508,9 @@ /mob/living/carbon/human/is_muzzled() return (wear_mask && (istype(wear_mask, /obj/item/clothing/mask/muzzle) || istype(src.wear_mask, /obj/item/weapon/grenade))) +/mob/living/carbon/human/get_fire_icon_state() + return species.fire_icon_state + // Called by job_controller. Makes drones start with a permit, might be useful for other people later too. /mob/living/carbon/human/equip_post_job() var/braintype = get_FBP_type() diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 23dfdb2db3..ad05894be0 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -4,7 +4,7 @@ #define HUMAN_MAX_OXYLOSS 1 //Defines how much oxyloss humans can get per tick. A tile with no air at all (such as space) applies this value, otherwise it's a percentage of it. #define HUMAN_CRIT_MAX_OXYLOSS ( 2.0 / 6) //The amount of damage you'll get when in critical condition. We want this to be a 5 minute deal = 300s. There are 50HP to get through, so (1/6)*last_tick_duration per second. Breaths however only happen every 4 ticks. last_tick_duration = ~2.0 on average -#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_1 5 //Amount of damage applied when your body temperature just passes the 360.15k safety point #define HEAT_DAMAGE_LEVEL_2 10 //Amount of damage applied when your body temperature passes the 400K point #define HEAT_DAMAGE_LEVEL_3 20 //Amount of damage applied when your body temperature passes the 1000K point @@ -623,31 +623,35 @@ if(bodytemperature >= species.heat_level_1) //Body temperature is too hot. fire_alert = max(fire_alert, 1) - if(status_flags & GODMODE) return 1 //godmode + if(status_flags & GODMODE) + return 1 //godmode var/burn_dam = 0 - switch(bodytemperature) - if(species.heat_level_1 to species.heat_level_2) - burn_dam = HEAT_DAMAGE_LEVEL_1 - if(species.heat_level_2 to species.heat_level_3) - burn_dam = HEAT_DAMAGE_LEVEL_2 - if(species.heat_level_3 to INFINITY) - burn_dam = HEAT_DAMAGE_LEVEL_3 + + // switch() can't access numbers inside variables, so we need to use some ugly if() spam ladder. + if(bodytemperature >= species.heat_level_3) + burn_dam = HEAT_DAMAGE_LEVEL_3 + else if(bodytemperature >= species.heat_level_2) + burn_dam = HEAT_DAMAGE_LEVEL_2 + else if(bodytemperature >= species.heat_level_1) + burn_dam = HEAT_DAMAGE_LEVEL_1 + take_overall_damage(burn=burn_dam, used_weapon = "High Body Temperature") fire_alert = max(fire_alert, 2) else if(bodytemperature <= species.cold_level_1) fire_alert = max(fire_alert, 1) - if(status_flags & GODMODE) return 1 //godmode + if(status_flags & GODMODE) + return 1 //godmode if(!istype(loc, /obj/machinery/atmospherics/unary/cryo_cell)) var/burn_dam = 0 - switch(bodytemperature) - if(species.cold_level_1 to species.cold_level_2) - burn_dam = COLD_DAMAGE_LEVEL_1 - if(species.cold_level_2 to species.cold_level_3) - burn_dam = COLD_DAMAGE_LEVEL_2 - if(species.cold_level_3 to -INFINITY) - burn_dam = COLD_DAMAGE_LEVEL_3 + if(bodytemperature <= species.cold_level_3) + burn_dam = COLD_DAMAGE_LEVEL_3 + else if(bodytemperature <= species.cold_level_2) + burn_dam = COLD_DAMAGE_LEVEL_2 + else if(bodytemperature <= species.heat_level_1) + burn_dam = COLD_DAMAGE_LEVEL_1 + take_overall_damage(burn=burn_dam, used_weapon = "Low Body Temperature") fire_alert = max(fire_alert, 1) @@ -1181,7 +1185,7 @@ // Apply a fire overlay if we're burning. if(on_fire) - health_images += image('icons/mob/screen1_health.dmi',"burning") + health_images += image('icons/mob/OnFire.dmi',"[get_fire_icon_state()]") // Show a general pain/crit indicator if needed. if(trauma_val) @@ -1673,14 +1677,17 @@ if(..()) return - var/burn_temperature = fire_burn_temperature() - var/thermal_protection = get_heat_protection(burn_temperature) + var/thermal_protection = get_heat_protection(fire_stacks * 1500) // Arbitrary but below firesuit max temp when below 20 stacks. - if (thermal_protection < 1 && bodytemperature < burn_temperature) - bodytemperature += round(BODYTEMP_HEATING_MAX*(1-thermal_protection), 1) + if(thermal_protection == 1) // Immune. + return + else + bodytemperature += (BODYTEMP_HEATING_MAX + (fire_stacks * 15)) * (1-thermal_protection) /mob/living/carbon/human/rejuvenate() restore_blood() + shock_stage = 0 + traumatic_shock = 0 ..() #undef HUMAN_MAX_OXYLOSS diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm index 9dc3291215..ea4b993645 100644 --- a/code/modules/mob/living/carbon/human/species/species.dm +++ b/code/modules/mob/living/carbon/human/species/species.dm @@ -14,6 +14,7 @@ var/deform = 'icons/mob/human_races/r_def_human.dmi' // Mutated icon set. var/speech_bubble_appearance = "normal" // Part of icon_state to use for speech bubbles when talking. See talk.dmi for available icons. + var/fire_icon_state = "humanoid" // The icon_state used inside OnFire.dmi for when on fire. // Damage overlay and masks. var/damage_overlays = 'icons/mob/human_races/masks/dam_human.dmi' diff --git a/code/modules/mob/living/carbon/human/species/station/monkey.dm b/code/modules/mob/living/carbon/human/species/station/monkey.dm index 738284dd38..e70bc76f17 100644 --- a/code/modules/mob/living/carbon/human/species/station/monkey.dm +++ b/code/modules/mob/living/carbon/human/species/station/monkey.dm @@ -20,6 +20,7 @@ dusted_anim = "dust-m" death_message = "lets out a faint chimper as it collapses and stops moving..." tail = "chimptail" + fire_icon_state = "monkey" unarmed_types = list(/datum/unarmed_attack/bite, /datum/unarmed_attack/claws) inherent_verbs = list(/mob/living/proc/ventcrawl) diff --git a/code/modules/mob/living/carbon/human/species/station/seromi.dm b/code/modules/mob/living/carbon/human/species/station/seromi.dm index d3dd435997..372b52d607 100644 --- a/code/modules/mob/living/carbon/human/species/station/seromi.dm +++ b/code/modules/mob/living/carbon/human/species/station/seromi.dm @@ -32,6 +32,8 @@ damage_mask = 'icons/mob/human_races/masks/dam_mask_seromi.dmi' blood_mask = 'icons/mob/human_races/masks/blood_seromi.dmi' + fire_icon_state = "generic" // Humanoid is too big for them and spriting a new one is really annoying. + slowdown = -1 total_health = 50 brute_mod = 1.35 diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 9c372cf2e7..0909ed2575 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -1138,7 +1138,7 @@ var/global/list/damage_icon_parts = list() /mob/living/carbon/human/update_fire(var/update_icons=1) overlays_standing[FIRE_LAYER] = null if(on_fire) - overlays_standing[FIRE_LAYER] = image("icon"='icons/mob/OnFire.dmi', "icon_state"="Standing", "layer"=FIRE_LAYER) + overlays_standing[FIRE_LAYER] = image("icon"='icons/mob/OnFire.dmi', "icon_state" = get_fire_icon_state(), "layer"=FIRE_LAYER) if(update_icons) update_icons() diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index b33688e59b..ebe642809b 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -52,6 +52,9 @@ default behaviour is: if (istype(AM, /mob/living)) var/mob/living/tmob = AM + //Even if we don't push/swap places, we "touched" them, so spread fire + spread_fire(tmob) + for(var/mob/living/M in range(tmob, 1)) if(tmob.pinned.len || ((M.pulling == tmob && ( tmob.restrained() && !( M.restrained() ) && M.stat == 0)) || locate(/obj/item/weapon/grab, tmob.grabbed_by.len)) ) if ( !(world.time % 5) ) @@ -969,6 +972,10 @@ default behaviour is: return FALSE return TRUE +// Gets the correct icon_state for being on fire. See OnFire.dmi for the icons. +/mob/living/proc/get_fire_icon_state() + return "generic" + // Called by job_controller. /mob/living/proc/equip_post_job() return diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index 069630a49a..299c784ec3 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -351,6 +351,24 @@ adjust_fire_stacks(2) IgniteMob() +//Share fire evenly between the two mobs +//Called in MobCollide() and Crossed() +/mob/living/proc/spread_fire(mob/living/L) + if(!istype(L)) + return + var/L_old_on_fire = L.on_fire + + if(on_fire) //Only spread fire stacks if we're on fire + fire_stacks /= 2 + L.fire_stacks += fire_stacks + if(L.IgniteMob()) + message_admins("[key_name(src)] bumped into [key_name(L)] and set them on fire.") + + if(L_old_on_fire) //Only ignite us and gain their stacks if they were onfire before we bumped them + L.fire_stacks /= 2 + fire_stacks += L.fire_stacks + IgniteMob() + /mob/living/proc/get_cold_protection() return 0 diff --git a/code/modules/mob/living/silicon/robot/life.dm b/code/modules/mob/living/silicon/robot/life.dm index db8d7b2ead..6b914852c7 100644 --- a/code/modules/mob/living/silicon/robot/life.dm +++ b/code/modules/mob/living/silicon/robot/life.dm @@ -340,9 +340,9 @@ return canmove /mob/living/silicon/robot/update_fire() - overlays -= image("icon"='icons/mob/OnFire.dmi', "icon_state"="Standing") + overlays -= image("icon"='icons/mob/OnFire.dmi', "icon_state" = get_fire_icon_state()) if(on_fire) - overlays += image("icon"='icons/mob/OnFire.dmi', "icon_state"="Standing") + overlays += image("icon"='icons/mob/OnFire.dmi', "icon_state" = get_fire_icon_state()) /mob/living/silicon/robot/fire_act() if(!on_fire) //Silicons don't gain stacks from hotspots, but hotspots can ignite them diff --git a/code/modules/organs/wound.dm b/code/modules/organs/wound.dm index 85925d9158..dd7f5dcf89 100644 --- a/code/modules/organs/wound.dm +++ b/code/modules/organs/wound.dm @@ -85,10 +85,12 @@ return src.damage / src.amount proc/can_autoheal() + if(is_treated()) + return TRUE if(src.wound_damage() <= autoheal_cutoff) - return 1 - - return is_treated() + if(created + 10 MINUTES > world.time) // Wounds don't autoheal for ten minutes if not bandaged. + return FALSE + return TRUE // checks whether the wound has been appropriately treated proc/is_treated() diff --git a/icons/mob/OnFire.dmi b/icons/mob/OnFire.dmi index 8bf6e2c774..b201e636e9 100644 Binary files a/icons/mob/OnFire.dmi and b/icons/mob/OnFire.dmi differ diff --git a/icons/mob/screen1_health.dmi b/icons/mob/screen1_health.dmi index 6905268a13..9ceea63056 100644 Binary files a/icons/mob/screen1_health.dmi and b/icons/mob/screen1_health.dmi differ