Refactors firestacks into status effects (#66573)

This PR refactors firestacks into two status effects: fire_stacks, which behave like normal firestacks you have right now, and wet_stacks, which are your negative fire stacks right now. This allows for custom fires with custom behaviors and icons to be made.

Some fire related is moved away from species(what the fuck was it even doing there) into these as well.
Oh and I fixed the bug where monkeys on fire had a human fire overlay, why wasn't this fixed already, it's like ancient.

Also changed some related proc names to be snake_case like everything should be.

This allows for custom fire types with custom behaviours, like freezing freon fire or radioactive tritium fire. Removing vars from living and moving them to status effects for modularity is also good.
Nothing to argue about since there's nothing player-facing
This commit is contained in:
SmArtKar
2022-05-04 23:52:07 -07:00
committed by GitHub
parent 24326bc649
commit 442ef897bc
82 changed files with 609 additions and 324 deletions
@@ -131,3 +131,6 @@ In all, this is a lot like the monkey code. /N
/mob/living/carbon/alien/acid_act(acidpwr, acid_volume)
return FALSE//aliens are immune to acid.
/mob/living/carbon/alien/on_fire_stack(delta_time, times_fired, datum/status_effect/fire_handler/fire_stacks/fire_handler)
adjust_bodytemperature(BODYTEMP_HEATING_MAX * 0.5 * delta_time)
@@ -46,9 +46,3 @@
//natural reduction of movement delay due to stun.
if(move_delay_add > 0)
move_delay_add = max(0, move_delay_add - (0.5 * rand(1, 2) * delta_time))
/mob/living/carbon/alien/handle_fire(delta_time, times_fired)//Aliens on fire code
. = ..()
if(.) //if the mob isn't on fire anymore
return
adjust_bodytemperature(BODYTEMP_HEATING_MAX * 0.5 * delta_time) //If you're on fire, you heat up!
+24 -10
View File
@@ -260,7 +260,6 @@
if(fire_stacks <= 0 && !QDELETED(src))
visible_message(span_danger("[src] successfully extinguishes [p_them()]self!"), \
span_notice("You extinguish yourself."))
extinguish_mob()
return
/mob/living/carbon/resist_restraints()
@@ -965,15 +964,6 @@
I.extinguish() //extinguishes our clothes
..()
/mob/living/carbon/fakefire(fire_icon = "Generic_mob_burning")
var/mutable_appearance/new_fire_overlay = mutable_appearance('icons/mob/OnFire.dmi', fire_icon, -FIRE_LAYER)
new_fire_overlay.appearance_flags = RESET_COLOR
overlays_standing[FIRE_LAYER] = new_fire_overlay
apply_overlay(FIRE_LAYER)
/mob/living/carbon/fakefireextinguish()
remove_overlay(FIRE_LAYER)
/mob/living/carbon/proc/create_bodyparts()
var/l_arm_index_next = -1
@@ -1424,3 +1414,27 @@
our_splatter.blood_dna_info = get_blood_dna_list()
var/turf/targ = get_ranged_target_turf(src, splatter_direction, splatter_strength)
our_splatter.fly_towards(targ, splatter_strength)
/mob/living/carbon/update_fire_overlay(stacks, on_fire, last_icon_state, suffix = "")
var/fire_icon = "generic_burning[suffix]"
if(!GLOB.fire_appearances[fire_icon])
var/mutable_appearance/new_fire_overlay = mutable_appearance('icons/mob/onfire.dmi', fire_icon, -FIRE_LAYER)
new_fire_overlay.appearance_flags = RESET_COLOR
GLOB.fire_appearances[fire_icon] = new_fire_overlay
if((stacks > 0 && on_fire) || HAS_TRAIT(src, TRAIT_PERMANENTLY_ONFIRE))
if(fire_icon == last_icon_state)
return last_icon_state
remove_overlay(FIRE_LAYER)
overlays_standing[FIRE_LAYER] = GLOB.fire_appearances[fire_icon]
apply_overlay(FIRE_LAYER)
return fire_icon
if(!last_icon_state)
return last_icon_state
remove_overlay(FIRE_LAYER)
apply_overlay(FIRE_LAYER)
return null
@@ -47,7 +47,6 @@
update_fire()
update_body_parts()
/mob/living/carbon/update_inv_hands()
remove_overlay(HANDS_LAYER)
if (handcuffed)
@@ -78,16 +77,6 @@
overlays_standing[HANDS_LAYER] = hands
apply_overlay(HANDS_LAYER)
/mob/living/carbon/update_fire(fire_icon = "Generic_mob_burning")
remove_overlay(FIRE_LAYER)
if(on_fire || HAS_TRAIT(src, TRAIT_PERMANENTLY_ONFIRE))
var/mutable_appearance/new_fire_overlay = mutable_appearance('icons/mob/OnFire.dmi', fire_icon, -FIRE_LAYER)
new_fire_overlay.appearance_flags = RESET_COLOR
overlays_standing[FIRE_LAYER] = new_fire_overlay
apply_overlay(FIRE_LAYER)
/mob/living/carbon/update_damage_overlays()
remove_overlay(DAMAGE_LAYER)
+2 -2
View File
@@ -96,9 +96,9 @@
if(HAS_TRAIT(src, TRAIT_DUMB))
msg += "[t_He] seem[p_s()] to be clumsy and unable to think.\n"
if(fire_stacks > 0)
if(has_status_effect(/datum/status_effect/fire_handler/fire_stacks))
msg += "[t_He] [t_is] covered in something flammable.\n"
if(fire_stacks < 0)
if(has_status_effect(/datum/status_effect/fire_handler/wet_stacks))
msg += "[t_He] look[p_s()] a little soaked.\n"
if(pulledby?.grab_state)
@@ -214,9 +214,9 @@
msg += "<b>[t_He] [t_has] severe cellular damage!</b>\n"
if(fire_stacks > 0)
if(has_status_effect(/datum/status_effect/fire_handler/fire_stacks))
msg += "[t_He] [t_is] covered in something flammable.\n"
if(fire_stacks < 0)
if(has_status_effect(/datum/status_effect/fire_handler/wet_stacks))
msg += "[t_He] look[p_s()] a little soaked.\n"
@@ -966,3 +966,97 @@
for(var/obj/item/I in torn_items)
I.take_damage(damage_amount, damage_type, damage_flag, 0)
/**
* Used by fire code to damage worn items.
*
* Arguments:
* - delta_time
* - times_fired
* - stacks: Current amount of firestacks
*
*/
/mob/living/carbon/human/proc/burn_clothing(delta_time, times_fired, stacks)
var/list/burning_items = list()
var/obscured = check_obscured_slots(TRUE)
//HEAD//
if(glasses && !(obscured & ITEM_SLOT_EYES))
burning_items += glasses
if(wear_mask && !(obscured & ITEM_SLOT_MASK))
burning_items += wear_mask
if(wear_neck && !(obscured & ITEM_SLOT_NECK))
burning_items += wear_neck
if(ears && !(obscured & ITEM_SLOT_EARS))
burning_items += ears
if(head)
burning_items += head
//CHEST//
if(w_uniform && !(obscured & ITEM_SLOT_ICLOTHING))
burning_items += w_uniform
if(wear_suit)
burning_items += wear_suit
//ARMS & HANDS//
var/obj/item/clothing/arm_clothes = null
if(gloves && !(obscured & ITEM_SLOT_GLOVES))
arm_clothes = gloves
else if(wear_suit && ((wear_suit.body_parts_covered & HANDS) || (wear_suit.body_parts_covered & ARMS)))
arm_clothes = wear_suit
else if(w_uniform && ((w_uniform.body_parts_covered & HANDS) || (w_uniform.body_parts_covered & ARMS)))
arm_clothes = w_uniform
if(arm_clothes)
burning_items |= arm_clothes
//LEGS & FEET//
var/obj/item/clothing/leg_clothes = null
if(shoes && !(obscured & ITEM_SLOT_FEET))
leg_clothes = shoes
else if(wear_suit && ((wear_suit.body_parts_covered & FEET) || (wear_suit.body_parts_covered & LEGS)))
leg_clothes = wear_suit
else if(w_uniform && ((w_uniform.body_parts_covered & FEET) || (w_uniform.body_parts_covered & LEGS)))
leg_clothes = w_uniform
if(leg_clothes)
burning_items |= leg_clothes
for(var/obj/item/burning in burning_items)
burning.fire_act((stacks * 25 * delta_time)) //damage taken is reduced to 2% of this value by fire_act()
/mob/living/carbon/human/update_fire_overlay(stacks, on_fire, last_icon_state, suffix = "")
var/fire_icon = "generic_burning[suffix]"
if(stacks > HUMAN_FIRE_STACK_ICON_NUM)
if(dna && dna.species)
fire_icon = "[dna.species.fire_overlay][suffix]"
else
fire_icon = "human_burning[suffix]"
if(!GLOB.fire_appearances[fire_icon])
var/mutable_appearance/new_fire_overlay = mutable_appearance('icons/mob/onfire.dmi', fire_icon, -FIRE_LAYER)
new_fire_overlay.appearance_flags = RESET_COLOR
GLOB.fire_appearances[fire_icon] = new_fire_overlay
if((stacks > 0 && on_fire) || HAS_TRAIT(src, TRAIT_PERMANENTLY_ONFIRE))
if(fire_icon == last_icon_state)
return last_icon_state
remove_overlay(FIRE_LAYER)
overlays_standing[FIRE_LAYER] = GLOB.fire_appearances[fire_icon]
apply_overlay(FIRE_LAYER)
return fire_icon
if(!last_icon_state)
return last_icon_state
remove_overlay(FIRE_LAYER)
apply_overlay(FIRE_LAYER)
return null
/mob/living/carbon/human/on_fire_stack(delta_time, times_fired, datum/status_effect/fire_handler/fire_stacks/fire_handler)
SEND_SIGNAL(src, COMSIG_HUMAN_BURNING)
burn_clothing(delta_time, times_fired, fire_handler.stacks)
var/no_protection = FALSE
if(dna && dna.species)
no_protection = dna.species.handle_fire(src, delta_time, times_fired, no_protection)
fire_handler.harm_human(delta_time, times_fired, no_protection)
@@ -64,7 +64,6 @@
/// What types of mobs are allowed to ride/buckle to this mob
var/static/list/can_ride_typecache = typecacheof(list(/mob/living/carbon/human, /mob/living/simple_animal/slime, /mob/living/simple_animal/parrot))
var/lastpuke = 0
var/last_fire_update
var/account_id
var/hardcore_survival_score = 0
@@ -69,10 +69,6 @@ There are several things that need to be remembered:
dna.species.handle_body(src)
..()
/mob/living/carbon/human/update_fire()
..((fire_stacks > HUMAN_FIRE_STACK_ICON_NUM) ? "Standing" : "Generic_mob_burning")
/* --------------------------------------- */
//For legacy support.
/mob/living/carbon/human/regenerate_icons()
@@ -154,22 +154,6 @@
/mob/living/carbon/human/get_body_temp_cold_damage_limit()
return dna.species.bodytemp_cold_damage_limit
///FIRE CODE
/mob/living/carbon/human/handle_fire(delta_time, times_fired)
. = ..()
if(.) //if the mob isn't on fire anymore
return
if(dna)
. = dna.species.handle_fire(src, delta_time, times_fired) //do special handling based on the mob's species. TRUE = they are immune to the effects of the fire.
if(!last_fire_update)
last_fire_update = fire_stacks
if((fire_stacks > HUMAN_FIRE_STACK_ICON_NUM && last_fire_update <= HUMAN_FIRE_STACK_ICON_NUM) || (fire_stacks <= HUMAN_FIRE_STACK_ICON_NUM && last_fire_update > HUMAN_FIRE_STACK_ICON_NUM))
last_fire_update = fire_stacks
update_fire()
/mob/living/carbon/human/proc/get_thermal_protection()
var/thermal_protection = 0 //Simple check to estimate how protected we are against multiple temperatures
if(wear_suit)
@@ -181,20 +165,8 @@
thermal_protection = round(thermal_protection)
return thermal_protection
/mob/living/carbon/human/IgniteMob()
//If have no DNA or can be Ignited, call parent handling to light user
//If firestacks are high enough
if(!dna || dna.species.CanIgniteMob(src))
return ..()
. = FALSE //No ignition
/mob/living/carbon/human/extinguish_mob()
if(!dna || !dna.species.extinguish_mob(src))
last_fire_update = null
..()
//END FIRE CODE
//This proc returns a number made up of the flags for body parts which you are protected on. (such as HEAD, CHEST, GROIN, etc. See setup.dm for the full list)
/mob/living/carbon/human/proc/get_heat_protection_flags(temperature) //Temperature is the temperature you're being exposed to.
var/thermal_protection_flags = 0
@@ -165,7 +165,7 @@ GLOBAL_LIST_EMPTY(features_by_species)
var/bodytemp_cold_damage_limit = BODYTEMP_COLD_DAMAGE_LIMIT
/// The icon_state of the fire overlay added when sufficently ablaze and standing. see onfire.dmi
var/fire_overlay = "Standing"
var/fire_overlay = "human_burning"
///the species that body parts are surgically compatible with (found in _DEFINES/mobs.dm)
///current acceptable bitfields are HUMAN_BODY, ALIEN_BODY, LARVA_BODY, MONKEY_BODY, or NONE
@@ -1721,77 +1721,7 @@ GLOBAL_LIST_EMPTY(features_by_species)
//////////
/datum/species/proc/handle_fire(mob/living/carbon/human/H, delta_time, times_fired, no_protection = FALSE)
if(!CanIgniteMob(H))
return TRUE
if(H.on_fire)
SEND_SIGNAL(H, COMSIG_HUMAN_BURNING)
//the fire tries to damage the exposed clothes and items
var/list/burning_items = list()
var/obscured = H.check_obscured_slots(TRUE)
//HEAD//
if(H.glasses && !(obscured & ITEM_SLOT_EYES))
burning_items += H.glasses
if(H.wear_mask && !(obscured & ITEM_SLOT_MASK))
burning_items += H.wear_mask
if(H.wear_neck && !(obscured & ITEM_SLOT_NECK))
burning_items += H.wear_neck
if(H.ears && !(obscured & ITEM_SLOT_EARS))
burning_items += H.ears
if(H.head)
burning_items += H.head
//CHEST//
if(H.w_uniform && !(obscured & ITEM_SLOT_ICLOTHING))
burning_items += H.w_uniform
if(H.wear_suit)
burning_items += H.wear_suit
//ARMS & HANDS//
var/obj/item/clothing/arm_clothes = null
if(H.gloves && !(obscured & ITEM_SLOT_GLOVES))
arm_clothes = H.gloves
else if(H.wear_suit && ((H.wear_suit.body_parts_covered & HANDS) || (H.wear_suit.body_parts_covered & ARMS)))
arm_clothes = H.wear_suit
else if(H.w_uniform && ((H.w_uniform.body_parts_covered & HANDS) || (H.w_uniform.body_parts_covered & ARMS)))
arm_clothes = H.w_uniform
if(arm_clothes)
burning_items |= arm_clothes
//LEGS & FEET//
var/obj/item/clothing/leg_clothes = null
if(H.shoes && !(obscured & ITEM_SLOT_FEET))
leg_clothes = H.shoes
else if(H.wear_suit && ((H.wear_suit.body_parts_covered & FEET) || (H.wear_suit.body_parts_covered & LEGS)))
leg_clothes = H.wear_suit
else if(H.w_uniform && ((H.w_uniform.body_parts_covered & FEET) || (H.w_uniform.body_parts_covered & LEGS)))
leg_clothes = H.w_uniform
if(leg_clothes)
burning_items |= leg_clothes
for(var/X in burning_items)
var/obj/item/I = X
I.fire_act((H.fire_stacks * 50)) //damage taken is reduced to 2% of this value by fire_act()
var/thermal_protection = H.get_thermal_protection()
if(thermal_protection >= FIRE_IMMUNITY_MAX_TEMP_PROTECT && !no_protection)
return
if(thermal_protection >= FIRE_SUIT_MAX_TEMP_PROTECT && !no_protection)
H.adjust_bodytemperature(5.5 * delta_time)
else
H.adjust_bodytemperature((BODYTEMP_HEATING_MAX + (H.fire_stacks * 12)) * 0.5 * delta_time)
SEND_SIGNAL(H, COMSIG_ADD_MOOD_EVENT, "on_fire", /datum/mood_event/on_fire)
H.mind?.add_memory(MEMORY_FIRE, list(DETAIL_PROTAGONIST = H), story_value = STORY_VALUE_OKAY)
/datum/species/proc/CanIgniteMob(mob/living/carbon/human/H)
if(HAS_TRAIT(H, TRAIT_NOFIRE))
return FALSE
return TRUE
/datum/species/proc/extinguish_mob(mob/living/carbon/human/H)
return
return no_protection
////////////
// Stun //
@@ -173,7 +173,7 @@
to_chat(owner, span_notice("You ignite yourself!"))
else
to_chat(owner, span_warning("You try to ignite yourself, but fail!"))
H.IgniteMob() //firestacks are already there passively
H.ignite_mob() //firestacks are already there passively
//Harder to hurt
/datum/species/golem/diamond
@@ -54,7 +54,7 @@
BODY_ZONE_R_LEG = /obj/item/bodypart/r_leg/monkey,
BODY_ZONE_CHEST = /obj/item/bodypart/chest/monkey,
)
fire_overlay = "Monkey_burning"
fire_overlay = "monkey_burning"
dust_anim = "dust-m"
gib_anim = "gibbed-m"
@@ -64,7 +64,7 @@
/datum/species/plasmaman/spec_life(mob/living/carbon/human/H, delta_time, times_fired)
var/atmos_sealed = TRUE
if(CanIgniteMob(H))
if(!HAS_TRAIT(H, TRAIT_NOFIRE))
atmos_sealed = FALSE
else if(!isclothing(H.wear_suit) || !(H.wear_suit.clothing_flags & STOPSPRESSUREDAMAGE))
atmos_sealed = FALSE
@@ -99,7 +99,7 @@
H.adjust_fire_stacks(0.25 * delta_time)
if(!H.on_fire && H.fire_stacks > 0)
H.visible_message(span_danger("[H]'s body reacts with the atmosphere and bursts into flames!"),span_userdanger("Your body reacts with the atmosphere and bursts into flame!"))
H.IgniteMob()
H.ignite_mob()
internal_fire = TRUE
else if(H.fire_stacks)
@@ -117,7 +117,6 @@
no_protection = TRUE
. = ..()
/datum/species/plasmaman/pre_equip_species_outfit(datum/job/job, mob/living/carbon/human/equipping, visuals_only = FALSE)
if(job.plasmaman_outfit)
equipping.equipOutfit(job.plasmaman_outfit, visuals_only)
@@ -68,7 +68,7 @@
to_chat(vampire, span_warning("You don't belong here!"))
vampire.adjustFireLoss(10 * delta_time)
vampire.adjust_fire_stacks(3 * delta_time)
vampire.IgniteMob()
vampire.ignite_mob()
/datum/species/vampire/check_species_weakness(obj/item/weapon, mob/living/attacker)
if(istype(weapon, /obj/item/nullrod/whip))
-19
View File
@@ -71,8 +71,6 @@
handle_traits(delta_time, times_fired) // eye, ear, brain damages
handle_status_effects(delta_time, times_fired) //all special effects, stun, knockdown, jitteryness, hallucination, sleeping, etc
handle_fire(delta_time, times_fired)
if(machine)
machine.check_eye(src)
@@ -110,23 +108,6 @@
else // this is a hot place
adjust_bodytemperature(min(min(temp_delta / BODYTEMP_DIVISOR, BODYTEMP_HEATING_MAX) * delta_time, temp_delta))
/mob/living/proc/handle_fire(delta_time, times_fired)
if(fire_stacks < 0) //If we've doused ourselves in water to avoid fire, dry off slowly
set_fire_stacks(min(0, fire_stacks + (0.5 * delta_time))) //So we dry ourselves back to default, nonflammable.
if(!on_fire)
return TRUE //the mob is no longer on fire, no need to do the rest.
if(fire_stacks > 0)
adjust_fire_stacks(-0.05 * delta_time) //the fire is slowly consumed
else
extinguish_mob()
return TRUE //mob was put out, on_fire = FALSE via extinguish_mob(), no need to update everything down the chain.
var/datum/gas_mixture/G = loc.return_air() // Check if we're standing in an oxygenless environment
if(!G.gases[/datum/gas/oxygen] || G.gases[/datum/gas/oxygen][MOLES] < 1)
extinguish_mob() //If there's no oxygen in the tile we're on, put out the fire
return TRUE
var/turf/location = get_turf(src)
location.hotspot_expose(700, 25 * delta_time, TRUE)
/**
* Get the fullness of the mob
*
+110 -52
View File
@@ -839,7 +839,6 @@
hallucination = 0
heal_overall_damage(INFINITY, INFINITY, INFINITY, null, TRUE) //heal brute and burn dmg on both organic and robotic limbs, and update health right away.
extinguish_mob()
fire_stacks = 0
set_confusion(0)
set_drowsyness(0)
jitteriness = 0
@@ -1385,27 +1384,28 @@
G.Recall()
to_chat(G, span_holoparasite("Your summoner has changed form!"))
/mob/living/proc/fakefireextinguish()
return
/mob/living/proc/fakefire()
return
/mob/living/proc/unfry_mob() //Callback proc to tone down spam from multiple sizzling frying oil dipping.
REMOVE_TRAIT(src, TRAIT_OIL_FRIED, "cooking_oil_react")
//Mobs on Fire
/mob/living/proc/IgniteMob()
if(fire_stacks <= 0 || on_fire)
/// Global list that containes cached fire overlays for mobs
GLOBAL_LIST_EMPTY(fire_appearances)
/mob/living/proc/ignite_mob()
if(fire_stacks <= 0)
return FALSE
on_fire = TRUE
src.visible_message(span_warning("[src] catches fire!"), \
span_userdanger("You're set on fire!"))
firelight_ref = WEAKREF(new /obj/effect/dummy/lighting_obj/moblight/fire(src))
throw_alert(ALERT_FIRE, /atom/movable/screen/alert/fire)
update_fire()
SEND_SIGNAL(src, COMSIG_LIVING_IGNITED,src)
return TRUE
var/datum/status_effect/fire_handler/fire_stacks/fire_status = has_status_effect(/datum/status_effect/fire_handler/fire_stacks)
if(!fire_status || fire_status.on_fire)
return FALSE
return fire_status.ignite()
/mob/living/proc/update_fire()
var/datum/status_effect/fire_handler/fire_handler = has_status_effect(/datum/status_effect/fire_handler)
if(fire_handler)
fire_handler.update_overlay()
/**
* Extinguish all fire on the mob
@@ -1414,15 +1414,10 @@
* Signals the extinguishing.
*/
/mob/living/proc/extinguish_mob()
if(!on_fire)
var/datum/status_effect/fire_handler/fire_stacks/fire_status = has_status_effect(/datum/status_effect/fire_handler/fire_stacks)
if(!fire_status || !fire_status.on_fire)
return
on_fire = FALSE
fire_stacks = min(0, fire_stacks) //Makes sure we don't get rid of negative firestacks.
QDEL_NULL(firelight_ref)
clear_alert(ALERT_FIRE)
SEND_SIGNAL(src, COMSIG_CLEAR_MOOD_EVENT, "on_fire")
SEND_SIGNAL(src, COMSIG_LIVING_EXTINGUISHED, src)
update_fire()
remove_status_effect(/datum/status_effect/fire_handler/fire_stacks)
/**
* Adjust the amount of fire stacks on a mob
@@ -1430,10 +1425,19 @@
* This modifies the fire stacks on a mob.
*
* Vars:
* * add_fire_stacks: int The amount to modify the fire stacks
* * stacks: int The amount to modify the fire stacks
* * fire_type: type Type of fire status effect that we apply, should be subtype of /datum/status_effect/fire_handler/fire_stacks
*/
/mob/living/proc/adjust_fire_stacks(add_fire_stacks)
set_fire_stacks(fire_stacks + add_fire_stacks)
/mob/living/proc/adjust_fire_stacks(stacks, fire_type = /datum/status_effect/fire_handler/fire_stacks)
if(stacks < 0)
stacks = max(-fire_stacks, stacks)
apply_status_effect(fire_type, stacks)
/mob/living/proc/adjust_wet_stacks(stacks, wet_type = /datum/status_effect/fire_handler/wet_stacks)
if(stacks < 0)
stacks = max(fire_stacks, stacks)
apply_status_effect(wet_type, stacks)
/**
* Set the fire stacks on a mob
@@ -1443,38 +1447,95 @@
*
* Vars:
* * stacks: int The amount to set fire_stacks to
* * fire_type: type Type of fire status effect that we apply, should be subtype of /datum/status_effect/fire_handler/fire_stacks
* * remove_wet_stacks: bool If we remove all wet stacks upon doing this
*/
/mob/living/proc/set_fire_stacks(stacks)
fire_stacks = clamp(stacks, -20, 20)
if(fire_stacks <= 0)
extinguish_mob()
/mob/living/proc/set_fire_stacks(stacks, fire_type = /datum/status_effect/fire_handler/fire_stacks, remove_wet_stacks = TRUE)
if(stacks < 0) //Shouldn't happen, ever
CRASH("set_fire_stacks recieved negative [stacks] fire stacks")
if(remove_wet_stacks)
remove_status_effect(/datum/status_effect/fire_handler/wet_stacks)
if(stacks == 0)
remove_status_effect(fire_type)
return
apply_status_effect(fire_type, stacks, TRUE)
/mob/living/proc/set_wet_stacks(stacks, wet_type = /datum/status_effect/fire_handler/wet_stacks, remove_fire_stacks = TRUE)
if(stacks < 0)
CRASH("set_wet_stacks recieved negative [stacks] wet stacks")
if(remove_fire_stacks)
remove_status_effect(/datum/status_effect/fire_handler/fire_stacks)
if(stacks == 0)
remove_status_effect(wet_type)
return
apply_status_effect(wet_type, stacks, TRUE)
//Share fire evenly between the two mobs
//Called in MobBump() and Crossed()
/mob/living/proc/spreadFire(mob/living/L)
if(!istype(L))
/mob/living/proc/spreadFire(mob/living/spread_to)
if(!istype(spread_to))
return
// can't spread fire to mobs that don't catch on fire
if(HAS_TRAIT(L, TRAIT_NOFIRE_SPREAD) || HAS_TRAIT(src, TRAIT_NOFIRE_SPREAD))
if(HAS_TRAIT(spread_to, TRAIT_NOFIRE_SPREAD) || HAS_TRAIT(src, TRAIT_NOFIRE_SPREAD))
return
if(on_fire)
if(L.on_fire) // If they were also on fire
var/firesplit = (fire_stacks + L.fire_stacks)/2
set_fire_stacks(firesplit)
L.set_fire_stacks(firesplit)
else // If they were not
set_fire_stacks(fire_stacks / 2)
L.adjust_fire_stacks(fire_stacks)
if(L.IgniteMob()) // Ignite them
log_game("[key_name(src)] bumped into [key_name(L)] and set them on fire")
var/datum/status_effect/fire_handler/fire_stacks/fire_status = has_status_effect(/datum/status_effect/fire_handler/fire_stacks)
var/datum/status_effect/fire_handler/fire_stacks/their_fire_status = spread_to.has_status_effect(/datum/status_effect/fire_handler/fire_stacks)
if(fire_status && fire_status.on_fire)
if(their_fire_status && their_fire_status.on_fire)
var/firesplit = (fire_stacks + spread_to.fire_stacks) / 2
var/fire_type = (spread_to.fire_stacks > fire_stacks) ? their_fire_status.type : fire_status.type
set_fire_stacks(firesplit, fire_type)
spread_to.set_fire_stacks(firesplit, fire_type)
return
else if(L.on_fire) // If they were on fire and we were not
L.set_fire_stacks(L.fire_stacks / 2)
adjust_fire_stacks(L.fire_stacks)
IgniteMob() // Ignite us
adjust_fire_stacks(-fire_stacks / 2, fire_status.type)
spread_to.adjust_fire_stacks(fire_stacks, fire_status.type)
if(spread_to.ignite_mob())
log_game("[key_name(src)] bumped into [key_name(spread_to)] and set them on fire")
return
if(!their_fire_status || !their_fire_status.on_fire)
return
spread_to.adjust_fire_stacks(-spread_to.fire_stacks / 2, their_fire_status.type)
adjust_fire_stacks(spread_to.fire_stacks, their_fire_status.type)
ignite_mob()
/**
* Sets fire overlay of the mob.
*
* Vars:
* * stacks: Current amount of fire_stacks
* * on_fire: If we're lit on fire
* * last_icon_state: Holds last fire overlay icon state, used for optimization
* * suffix: Suffix for the fire icon state for special fire types
*
* This should return last_icon_state for the fire status efect
*/
/mob/living/proc/update_fire_overlay(stacks, on_fire, last_icon_state, suffix = "")
return last_icon_state
/**
* Handles effects happening when mob is on normal fire
*
* Vars:
* * delta_time
* * times_fired
* * fire_handler: Current fire status effect that called the proc
*/
/mob/living/proc/on_fire_stack(delta_time, times_fired, datum/status_effect/fire_handler/fire_stacks/fire_handler)
return
//Mobs on Fire end
@@ -1636,9 +1697,6 @@
if(NAMEOF(src, resting))
set_resting(var_value)
. = TRUE
if(NAMEOF(src, fire_stacks))
set_fire_stacks(var_value)
. = TRUE
if(NAMEOF(src, lying_angle))
set_lying_angle(var_value)
. = TRUE
+1 -1
View File
@@ -129,7 +129,7 @@
/mob/living/fire_act()
adjust_fire_stacks(3)
IgniteMob()
ignite_mob()
/mob/living/proc/grabbedby(mob/living/carbon/user, supress_message = FALSE)
if(user == src || anchored || !isturf(user.loc))
+4 -5
View File
@@ -54,6 +54,10 @@
var/last_special = 0 ///Used by the resist verb, likely used to prevent players from bypassing next_move by logging in/out.
var/timeofdeath = 0
/// Helper vars for quick access to firestacks, these should be updated every time firestacks are adjusted
var/on_fire = FALSE
var/fire_stacks = 0
/**
* Allows mobs to move through dense areas without restriction. For instance, in space or out of holder objects.
*
@@ -75,11 +79,6 @@
/// Time of death
var/tod = null
var/on_fire = FALSE ///The "Are we on fire?" var
/// Weak reference to the light our fire is causing, if there is one
var/datum/weakref/firelight_ref
var/fire_stacks = 0 ///Tracks how many stacks of fire we have on, max is usually 20
var/limb_destroyer = 0 //1 Sets AI behavior that allows mobs to target and dismember limbs with their basic attack.
var/mob_size = MOB_SIZE_HUMAN
+2 -3
View File
@@ -241,9 +241,8 @@
if(istype(A, initial(AM.power_type)))
qdel(A)
/mob/living/silicon/ai/IgniteMob()
fire_stacks = 0
. = ..()
/mob/living/silicon/ai/ignite_mob()
return FALSE
/mob/living/silicon/ai/proc/set_core_display_icon(input, client/C)
if(client && !C)
@@ -61,9 +61,8 @@
src.visible_message(span_warning("The electrically-charged projectile disrupts [src]'s holomatrix, forcing [src] to fold in!"))
. = ..(Proj)
/mob/living/silicon/pai/IgniteMob()
fire_stacks = 0
. = ..()
/mob/living/silicon/pai/ignite_mob()
return FALSE
/mob/living/silicon/pai/proc/take_holo_damage(amount)
emitterhealth = clamp((emitterhealth - amount), -50, emittermaxhealth)
@@ -70,23 +70,3 @@
throw_alert(ALERT_CHARGE, /atom/movable/screen/alert/emptycell)
else
throw_alert(ALERT_CHARGE, /atom/movable/screen/alert/nocell)
//Robots on fire
/mob/living/silicon/robot/handle_fire(delta_time, times_fired)
. = ..()
if(.) //if the mob isn't on fire anymore
return
if(fire_stacks > 0)
adjust_fire_stacks(-0.5 * delta_time)
else
extinguish_mob()
return TRUE
//adjustFireLoss(3)
/mob/living/silicon/robot/update_fire()
var/mutable_appearance/fire_overlay = mutable_appearance('icons/mob/OnFire.dmi', "Generic_mob_burning")
if(on_fire)
add_overlay(fire_overlay)
else
cut_overlay(fire_overlay)
@@ -983,3 +983,23 @@
/mob/living/silicon/robot/proc/untip_roleplay()
to_chat(src, span_notice("Your frustration has empowered you! You can now right yourself faster!"))
/mob/living/silicon/robot/update_fire_overlay(stacks, on_fire, last_icon_state, suffix = "")
var/fire_icon = "generic_burning[suffix]"
if(!GLOB.fire_appearances[fire_icon])
var/mutable_appearance/new_fire_overlay = mutable_appearance('icons/mob/onfire.dmi', fire_icon, -FIRE_LAYER)
new_fire_overlay.appearance_flags = RESET_COLOR
GLOB.fire_appearances[fire_icon] = new_fire_overlay
if(stacks && on_fire)
if(last_icon_state == fire_icon)
return last_icon_state
add_overlay(GLOB.fire_appearances[fire_icon])
return fire_icon
if(!last_icon_state)
return last_icon_state
cut_overlay(GLOB.fire_appearances[fire_icon])
return null
@@ -312,7 +312,7 @@ GLOBAL_LIST_INIT(blacklisted_borg_hats, typecacheof(list( //Hats that don't real
/mob/living/silicon/robot/fire_act()
if(!on_fire) //Silicons don't gain stacks from hotspots, but hotspots can ignite them
IgniteMob()
ignite_mob()
/mob/living/silicon/robot/emp_act(severity)
. = ..()
@@ -49,4 +49,4 @@
var/mob/living/M = AM
if(!hasmatchingsummoner(M) && M != summoner && M.fire_stacks < 7)
M.set_fire_stacks(7)
M.IgniteMob()
M.ignite_mob()
@@ -163,7 +163,7 @@
K.transform = final
living_target.adjustFireLoss(30)
living_target.adjust_fire_stacks(0.2)//Just here for the showmanship
living_target.IgniteMob()
living_target.ignite_mob()
playsound(living_target,'sound/weapons/sear.ogg', 50, TRUE)
addtimer(CALLBACK(src, .proc/AttackRecovery), 5)
return
@@ -203,7 +203,7 @@
var/mob/living/L = target
if (istype(L))
L.adjust_fire_stacks(0.1)
L.IgniteMob()
L.ignite_mob()
/obj/projectile/temp/basilisk/icewing
damage = 5
@@ -294,7 +294,7 @@
if(isliving(mover))
var/mob/living/fire_walker = mover
fire_walker.adjust_fire_stacks(5)
fire_walker.IgniteMob()
fire_walker.ignite_mob()
/obj/structure/legionnaire_bonfire/Destroy()
if(myowner != null)
@@ -490,10 +490,7 @@
return FALSE
return TRUE
/mob/living/simple_animal/handle_fire(delta_time, times_fired)
return TRUE
/mob/living/simple_animal/IgniteMob()
/mob/living/simple_animal/ignite_mob()
return FALSE
/mob/living/simple_animal/extinguish_mob()
-3
View File
@@ -49,9 +49,6 @@
/mob/proc/update_hair()
return
/mob/proc/update_fire()
return
/mob/proc/update_inv_gloves()
return