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
@@ -16,7 +16,7 @@
#define COMSIG_LIVING_DOORCRUSHED "living_doorcrush"
///from base of mob/living/resist() (/mob/living)
#define COMSIG_LIVING_RESIST "living_resist"
///from base of mob/living/IgniteMob() (/mob/living)
///from base of mob/living/ignite_mob() (/mob/living)
#define COMSIG_LIVING_IGNITED "living_ignite"
///from base of mob/living/extinguish_mob() (/mob/living)
#define COMSIG_LIVING_EXTINGUISHED "living_extinguished"
+1
View File
@@ -38,3 +38,4 @@
#define STASIS_CHEMICAL_EFFECT "stasis_chemical"
#define STASIS_ASCENSION_EFFECT "heretic_ascension"
+5 -3
View File
@@ -1,11 +1,13 @@
/datum/component/igniter
var/fire_stacks
var/fire_type
/datum/component/igniter/Initialize(fire_stacks=1)
/datum/component/igniter/Initialize(fire_stacks = 1, fire_type = /datum/status_effect/fire_handler/fire_stacks)
if(!isitem(parent) && !ishostile(parent) && !isgun(parent) && !ismachinery(parent) && !isstructure(parent))
return COMPONENT_INCOMPATIBLE
src.fire_stacks = fire_stacks
src.fire_type = fire_type
/datum/component/igniter/RegisterWithParent()
if(ismachinery(parent) || isstructure(parent) || isgun(parent)) // turrets, etc
@@ -40,5 +42,5 @@
/datum/component/igniter/proc/do_igniter(atom/target)
if(isliving(target))
var/mob/living/L = target
L.adjust_fire_stacks(fire_stacks)
L.IgniteMob()
L.adjust_fire_stacks(fire_stacks, fire_type)
L.ignite_mob()
@@ -51,12 +51,12 @@
to_chat(M, span_warning("[pick("You feel hot.", "You hear a crackling noise.", "You smell smoke.")]"))
if(4)
Firestacks_stage_4(M, A)
M.IgniteMob()
M.ignite_mob()
to_chat(M, span_userdanger("Your skin bursts into flames!"))
M.emote("scream")
if(5)
Firestacks_stage_5(M, A)
M.IgniteMob()
M.ignite_mob()
to_chat(M, span_userdanger("Your skin erupts into an inferno!"))
M.emote("scream")
@@ -134,7 +134,7 @@ Bonus
M.visible_message(span_warning("[M]'s sweat sizzles and pops on contact with water!"))
explosion(M, devastation_range = -1, heavy_impact_range = (-1 + explosion_power), light_impact_range = (2 * explosion_power), explosion_cause = src)
Alkali_fire_stage_4(M, A)
M.IgniteMob()
M.ignite_mob()
to_chat(M, span_userdanger("Your sweat bursts into flames!"))
M.emote("scream")
if(5)
@@ -142,7 +142,7 @@ Bonus
M.visible_message(span_warning("[M]'s sweat sizzles and pops on contact with water!"))
explosion(M, devastation_range = -1, heavy_impact_range = (-1 + explosion_power), light_impact_range = (2 * explosion_power), explosion_cause = src)
Alkali_fire_stage_5(M, A)
M.IgniteMob()
M.ignite_mob()
to_chat(M, span_userdanger("Your skin erupts into an inferno!"))
M.emote("scream")
@@ -455,7 +455,7 @@
. = 0
var/mob/living/M = A.affected_mob
if(M.fire_stacks < 0)
M.set_fire_stacks(min(M.fire_stacks + 1 * absorption_coeff, 0))
M.adjust_fire_stacks(min(absorption_coeff, -M.fire_stacks))
. += power
if(M.reagents.has_reagent(/datum/reagent/water/holywater, needs_metabolizing = FALSE))
M.reagents.remove_reagent(/datum/reagent/water/holywater, 0.5 * absorption_coeff)
+1 -1
View File
@@ -32,7 +32,7 @@
if(DT_PROB(10, delta_time))
if(prob(50))
affected_mob.adjust_fire_stacks(2)
affected_mob.IgniteMob()
affected_mob.ignite_mob()
else
affected_mob.emote("gasp")
to_chat(affected_mob, span_danger("You feel a burning beat inside..."))
+2 -2
View File
@@ -146,7 +146,7 @@
return
our_lizard.adjust_fire_stacks(cone_levels)
our_lizard.IgniteMob()
our_lizard.ignite_mob()
to_chat(our_lizard, span_warning("Something in front of your mouth catches fire!"))
/obj/effect/proc_holder/spell/cone/staggered/firebreath/cast(list/targets, mob/user)
@@ -171,7 +171,7 @@
// The actual burn damage application is not blocked by fireproofing, like space dragons.
target_mob.apply_damage(max(10, 40 - (5 * level)), BURN, spread_damage = TRUE)
target_mob.adjust_fire_stacks(max(2, 5 - level))
target_mob.IgniteMob()
target_mob.ignite_mob()
/obj/effect/proc_holder/spell/cone/staggered/firebreath/do_obj_cone_effect(obj/target_obj, level)
// Further out objects experience less exposed_temperature and exposed_volume
+1 -1
View File
@@ -293,7 +293,7 @@
/datum/mutation/human/fire/on_life(delta_time, times_fired)
if(DT_PROB((0.05+(100-dna.stability)/19.5) * GET_MUTATION_SYNCHRONIZER(src), delta_time))
owner.adjust_fire_stacks(2 * GET_MUTATION_POWER(src))
owner.IgniteMob()
owner.ignite_mob()
/datum/mutation/human/fire/on_acquiring(mob/living/carbon/human/owner)
if(..())
+3 -3
View File
@@ -75,12 +75,12 @@
// Status effect process. Handles adjusting it's duration and ticks.
// If you're adding processed effects, put them in [proc/tick]
// instead of extending / overriding ththe process() proc.
/datum/status_effect/process(delta_time)
/datum/status_effect/process(delta_time, times_fired)
if(QDELETED(owner))
qdel(src)
return
if(tick_interval < world.time)
tick()
tick(delta_time, times_fired)
tick_interval = world.time + initial(tick_interval)
if(duration != -1 && duration < world.time)
qdel(src)
@@ -96,7 +96,7 @@
return null
/// Called every tick from process().
/datum/status_effect/proc/tick()
/datum/status_effect/proc/tick(delta_time, times_fired)
return
/// Called whenever the buff expires or is removed (qdeleted)
@@ -40,7 +40,8 @@
// Create the status effect with our mob + our arguments
var/datum/status_effect/new_instance = new new_effect(arguments)
return new_instance
if(!QDELETED(new_instance))
return new_instance
/**
* Removes all instances of a given status effect from this mob
@@ -0,0 +1,260 @@
/datum/status_effect/fire_handler
duration = -1
alert_type = null
status_type = STATUS_EFFECT_REFRESH //Custom code
on_remove_on_mob_delete = TRUE
tick_interval = 2 SECONDS
/// Current amount of stacks we have
var/stacks
/// Maximum of stacks that we could possibly get
var/stack_limit = 20
/// What status effect types do we remove uppon being applied. These are just deleted without any deduction from our or their stacks when forced.
var/list/enemy_types
/// What status effect types do we merge into if they exist. Ignored when forced.
var/list/merge_types
/// What status effect types do we override if they exist. These are simply deleted when forced.
var/list/override_types
/// For how much firestacks does one our stack count
var/stack_modifier = 1
/datum/status_effect/fire_handler/refresh(mob/living/new_owner, new_stacks, forced = FALSE)
if(forced)
set_stacks(new_stacks)
else
adjust_stacks(new_stacks)
/datum/status_effect/fire_handler/on_creation(mob/living/new_owner, new_stacks, forced = FALSE)
. = ..()
if(isanimal(owner))
qdel(src)
return
owner = new_owner
set_stacks(new_stacks)
for(var/enemy_type in enemy_types)
var/datum/status_effect/fire_handler/enemy_effect = owner.has_status_effect(enemy_type)
if(enemy_effect)
if(forced)
qdel(enemy_effect)
continue
var/cur_stacks = stacks
adjust_stacks(-enemy_effect.stacks * enemy_effect.stack_modifier / stack_modifier)
enemy_effect.adjust_stacks(-cur_stacks * stack_modifier / enemy_effect.stack_modifier)
if(enemy_effect.stacks <= 0)
qdel(enemy_effect)
if(stacks <= 0)
qdel(src)
return
if(!forced)
var/list/merge_effects = list()
for(var/merge_type in merge_types)
var/datum/status_effect/fire_handler/merge_effect = owner.has_status_effect(merge_type)
if(merge_effect)
merge_effects += merge_effects
if(LAZYLEN(merge_effects))
for(var/datum/status_effect/fire_handler/merge_effect in merge_effects)
merge_effect.adjust_stacks(stacks * stack_modifier / merge_effect.stack_modifier / LAZYLEN(merge_effects))
qdel(src)
return
for(var/override_type in override_types)
var/datum/status_effect/fire_handler/override_effect = owner.has_status_effect(override_type)
if(override_effect)
if(forced)
qdel(override_effect)
continue
adjust_stacks(override_effect.stacks)
qdel(override_effect)
/**
* Setter and adjuster procs for firestacks
*
* Arguments:
* - new_stacks
*
*/
/datum/status_effect/fire_handler/proc/set_stacks(new_stacks)
stacks = max(0, min(stack_limit, new_stacks))
cache_stacks()
/datum/status_effect/fire_handler/proc/adjust_stacks(new_stacks)
stacks = max(0, min(stack_limit, stacks + new_stacks))
cache_stacks()
/**
* Refresher for mob's fire_stacks
*/
/datum/status_effect/fire_handler/proc/cache_stacks()
owner.fire_stacks = 0
var/was_on_fire = owner.on_fire
owner.on_fire = FALSE
for(var/datum/status_effect/fire_handler/possible_fire in owner.status_effects)
owner.fire_stacks += possible_fire.stacks * possible_fire.stack_modifier
if(!istype(possible_fire, /datum/status_effect/fire_handler/fire_stacks))
continue
var/datum/status_effect/fire_handler/fire_stacks/our_fire = possible_fire
if(our_fire.on_fire)
owner.on_fire = TRUE
if(was_on_fire && !owner.on_fire)
owner.clear_alert(ALERT_FIRE)
else if(!was_on_fire && owner.on_fire)
owner.throw_alert(ALERT_FIRE, /atom/movable/screen/alert/fire)
/**
* Used to update owner's effect overlay
*/
/datum/status_effect/fire_handler/proc/update_overlay()
/datum/status_effect/fire_handler/fire_stacks
id = "fire_stacks" //fire_stacks and wet_stacks should have different IDs or else has_status_effect won't work
enemy_types = list(/datum/status_effect/fire_handler/wet_stacks)
stack_modifier = 1
/// If we're on fire
var/on_fire = FALSE
/// A weakref to the mob light emitter
var/datum/weakref/firelight_ref
/// Type of mob light emitter we use when on fire
var/firelight_type = /obj/effect/dummy/lighting_obj/moblight/fire
/// Stores current fire overlay icon state, for optimisation purposes
var/last_icon_state
/datum/status_effect/fire_handler/fire_stacks/tick(delta_time, times_fired)
if(stacks <= 0)
qdel(src)
return TRUE
if(!on_fire || isanimal(owner))
return TRUE
if(iscyborg(owner))
adjust_stacks(-0.55 * delta_time)
else
adjust_stacks(-0.05 * delta_time)
if(stacks <= 0)
qdel(src)
return TRUE
var/datum/gas_mixture/air = owner.loc.return_air()
if(!air.gases[/datum/gas/oxygen] || air.gases[/datum/gas/oxygen][MOLES] < 1)
qdel(src)
return TRUE
deal_damage(delta_time, times_fired)
update_overlay()
/**
* Proc that handles damage dealing and all special effects
*
* Arguments:
* - delta_time
* - times_fired
*
*/
/datum/status_effect/fire_handler/fire_stacks/proc/deal_damage(delta_time, times_fired)
owner.on_fire_stack(delta_time, times_fired, src)
var/turf/location = get_turf(owner)
location.hotspot_expose(700, 25 * delta_time, TRUE)
/**
* Used to deal damage to humans and count their protection.
*
* Arguments:
* - delta_time
* - times_fired
* - no_protection: When set to TRUE, fire will ignore any possible fire protection
*
*/
/datum/status_effect/fire_handler/fire_stacks/proc/harm_human(delta_time, times_fired, no_protection = FALSE)
var/mob/living/carbon/human/victim = owner
var/thermal_protection = victim.get_thermal_protection()
if(thermal_protection >= FIRE_IMMUNITY_MAX_TEMP_PROTECT && !no_protection)
return
if(thermal_protection >= FIRE_SUIT_MAX_TEMP_PROTECT && !no_protection)
victim.adjust_bodytemperature(5.5 * delta_time)
return
victim.adjust_bodytemperature((BODYTEMP_HEATING_MAX + (stacks * 12)) * 0.5 * delta_time)
SEND_SIGNAL(victim, COMSIG_ADD_MOOD_EVENT, "on_fire", /datum/mood_event/on_fire)
victim.mind?.add_memory(MEMORY_FIRE, list(DETAIL_PROTAGONIST = victim), story_value = STORY_VALUE_OKAY)
/**
* Handles mob ignition, should be the only way to set on_fire to TRUE
*
* Arguments:
* - silent: When set to TRUE, no message is displayed
*
*/
/datum/status_effect/fire_handler/fire_stacks/proc/ignite(silent = FALSE)
if(HAS_TRAIT(owner, TRAIT_NOFIRE))
return FALSE
on_fire = TRUE
if(!silent)
owner.visible_message(span_warning("[owner] catches fire!"), span_userdanger("You're set on fire!"))
if(firelight_type)
firelight_ref = WEAKREF(new firelight_type(owner))
SEND_SIGNAL(owner, COMSIG_LIVING_IGNITED, owner)
cache_stacks()
update_overlay()
/**
* Handles mob extinguishing, should be the only way to set on_fire to FALSE
*/
/datum/status_effect/fire_handler/fire_stacks/proc/extinguish()
if(firelight_ref)
qdel(firelight_ref)
on_fire = FALSE
SEND_SIGNAL(owner, COMSIG_CLEAR_MOOD_EVENT, "on_fire")
SEND_SIGNAL(owner, COMSIG_LIVING_EXTINGUISHED, owner)
cache_stacks()
update_overlay()
/datum/status_effect/fire_handler/fire_stacks/on_remove()
if(on_fire)
extinguish()
set_stacks(0)
update_overlay()
/datum/status_effect/fire_handler/fire_stacks/update_overlay()
last_icon_state = owner.update_fire_overlay(stacks, on_fire, last_icon_state)
/datum/status_effect/fire_handler/fire_stacks/on_apply()
. = ..()
update_overlay()
/datum/status_effect/fire_handler/wet_stacks
id = "wet_stacks"
enemy_types = list(/datum/status_effect/fire_handler/fire_stacks)
stack_modifier = -1
/datum/status_effect/fire_handler/wet_stacks/tick(delta_time)
adjust_stacks(-0.5 * delta_time)
if(stacks <= 0)
qdel(src)
+1 -1
View File
@@ -213,7 +213,7 @@ GLOBAL_LIST_INIT(voice_of_god_commands, init_voice_of_god_commands())
/datum/voice_of_god_command/burn/execute(list/listeners, mob/living/user, power_multiplier = 1, message)
for(var/mob/living/target as anything in listeners)
target.adjust_fire_stacks(1 * power_multiplier)
target.IgniteMob()
target.ignite_mob()
/// This command heats the listeners up like boiling water.
/datum/voice_of_god_command/hot
+1 -1
View File
@@ -368,7 +368,7 @@ GLOBAL_LIST_INIT(orion_events, generate_orion_events())
reason = "You ran out of fuel, and drift, slowly, into a star."
if(obj_flags & EMAGGED)
gamer.adjust_fire_stacks(5)
gamer.IgniteMob() //flew into a star, so you're on fire
gamer.ignite_mob() //flew into a star, so you're on fire
to_chat(gamer, span_userdanger("You feel an immense wave of heat emanate from the arcade machine. Your skin bursts into flames."))
if(obj_flags & EMAGGED)
+1 -1
View File
@@ -131,7 +131,7 @@
if(.)
if(resistance_flags & ON_FIRE) //Sets the mob on fire if you buckle them to a burning atom/movableect
M.adjust_fire_stacks(1)
M.IgniteMob()
M.ignite_mob()
/**
* Set a mob as unbuckled from src
@@ -69,7 +69,7 @@
/obj/effect/particle_effect/foam/firefighting/foam_mob(mob/living/L)
if(!istype(L))
return
L.adjust_fire_stacks(-2)
L.adjust_wet_stacks(2)
/obj/effect/particle_effect/foam/metal
name = "aluminium foam"
+1 -1
View File
@@ -713,7 +713,7 @@ GLOBAL_DATUM_INIT(fire_overlay, /mutable_appearance, mutable_appearance('icons/e
SEND_SIGNAL(src, COMSIG_MOVABLE_IMPACT, hit_atom, throwingdatum)
if(get_temperature() && isliving(hit_atom))
var/mob/living/L = hit_atom
L.IgniteMob()
L.ignite_mob()
var/itempush = 1
if(w_class < 4)
itempush = 0 //too light to push anything
+5 -5
View File
@@ -85,7 +85,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
if(!isliving(M))
return
if(lit && M.IgniteMob())
if(lit && M.ignite_mob())
message_admins("[ADMIN_LOOKUPFLW(user)] set [key_name_admin(M)] on fire with [src] at [AREACOORD(user)]")
log_game("[key_name(user)] set [key_name(M)] on fire with [src] at [AREACOORD(user)]")
@@ -312,7 +312,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
/obj/item/clothing/mask/cigarette/process(delta_time)
var/mob/living/user = isliving(loc) ? loc : null
user?.IgniteMob()
user?.ignite_mob()
if(!reagents.has_reagent(/datum/reagent/oxygen)) //cigarettes need oxygen
var/datum/gas_mixture/air = return_air()
if(!air || !air.has_gas(/datum/gas/oxygen, 1)) //or oxygen on a tile to burn
@@ -802,7 +802,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
/obj/item/lighter/attack(mob/living/carbon/M, mob/living/carbon/user)
if(lit && M.IgniteMob())
if(lit && M.ignite_mob())
message_admins("[ADMIN_LOOKUPFLW(user)] set [key_name_admin(M)] on fire with [src] at [AREACOORD(user)]")
log_game("[key_name(user)] set [key_name(M)] on fire with [src] at [AREACOORD(user)]")
var/obj/item/clothing/mask/cigarette/cig = help_light_cig(M)
@@ -1025,7 +1025,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
if(reagents.get_reagent_amount(/datum/reagent/fuel))
//HOT STUFF
vaper.adjust_fire_stacks(2)
vaper.IgniteMob()
vaper.ignite_mob()
if(reagents.get_reagent_amount(/datum/reagent/toxin/plasma)) // the plasma explodes when exposed to fire
var/datum/effect_system/reagents_explosion/e = new()
@@ -1040,7 +1040,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
var/mob/living/M = loc
if(isliving(loc))
M.IgniteMob()
M.ignite_mob()
if(!reagents.total_volume)
if(ismob(loc))
+2 -2
View File
@@ -145,7 +145,7 @@
if(isOn() && !QDELETED(attacked_atom) && isliving(attacked_atom)) // can't ignite something that doesn't exist
handle_fuel_and_temps(1, user)
var/mob/living/attacked_mob = attacked_atom
if(attacked_mob.IgniteMob())
if(attacked_mob.ignite_mob())
message_admins("[ADMIN_LOOKUPFLW(user)] set [key_name_admin(attacked_mob)] on fire with [src] at [AREACOORD(user)]")
log_game("[key_name(user)] set [key_name(attacked_mob)] on fire with [src] at [AREACOORD(user)]")
@@ -164,7 +164,7 @@
if(!QDELETED(attacked_atom) && isliving(attacked_atom)) // can't ignite something that doesn't exist
var/mob/living/attacked_mob = attacked_atom
if(attacked_mob.IgniteMob())
if(attacked_mob.ignite_mob())
message_admins("[ADMIN_LOOKUPFLW(user)] set [key_name_admin(attacked_mob)] on fire with [src] at [AREACOORD(user)]")
log_game("[key_name(user)] set [key_name(attacked_mob)] on fire with [src] at [AREACOORD(user)]")
+1 -1
View File
@@ -145,7 +145,7 @@
else if(isliving(burn_target))
var/mob/living/burn_victim = burn_target
burn_victim.adjust_fire_stacks(BONFIRE_FIRE_STACK_STRENGTH * 0.5 * delta_time)
burn_victim.IgniteMob()
burn_victim.ignite_mob()
else if(isobj(burn_target))
var/obj/burned_object = burn_target
if(grill && isitem(burned_object))
+1 -1
View File
@@ -220,7 +220,7 @@
burn_living.adjustFireLoss(lava_damage * delta_time)
if(!QDELETED(burn_living)) //mobs turning into object corpses could get deleted here.
burn_living.adjust_fire_stacks(lava_firestacks * delta_time)
burn_living.IgniteMob()
burn_living.ignite_mob()
/turf/open/lava/smooth
name = "lava"
@@ -36,7 +36,7 @@
. = ..()
reac_volume = return_mob_expose_reac_volume(exposed_mob, methods, reac_volume, show_message, touch_protection, overmind)
exposed_mob.adjust_fire_stacks(round(reac_volume/10))
exposed_mob.IgniteMob()
exposed_mob.ignite_mob()
if(exposed_mob)
exposed_mob.apply_damage(0.8*reac_volume, BURN, wound_bonus=CANT_WOUND)
if(iscarbon(exposed_mob))
@@ -31,7 +31,7 @@
for(var/obj/O in T)
O.extinguish()
for(var/mob/living/L in T)
L.adjust_fire_stacks(-2.5)
L.adjust_wet_stacks(2.5)
L.extinguish_mob()
/datum/reagent/blob/pressurized_slime
@@ -45,7 +45,7 @@
var/turf/open/location_turf = get_turf(exposed_mob)
if(istype(location_turf) && prob(reac_volume))
location_turf.MakeSlippery(TURF_WET_LUBE, min_wet_time = 10 SECONDS, wet_time_to_add = 5 SECONDS)
exposed_mob.adjust_fire_stacks(-(reac_volume / 10))
exposed_mob.adjust_wet_stacks(reac_volume / 10)
exposed_mob.apply_damage(0.4*reac_volume, BRUTE, wound_bonus=CANT_WOUND)
if(exposed_mob)
exposed_mob.adjustStaminaLoss(reac_volume, FALSE)
@@ -146,7 +146,7 @@
return
target.adjust_fire_stacks(1)
target.IgniteMob()
target.ignite_mob()
/datum/heretic_knowledge/spell/flame_birth
name = "Nightwater's Rebirth"
@@ -61,7 +61,7 @@
*/
/datum/status_effect/unholy_determination/proc/adjust_all_damages(amount)
owner.set_fire_stacks(max(owner.fire_stacks - 1, 0))
owner.adjust_fire_stacks(-1)
owner.losebreath = max(owner.losebreath - 0.5, 0)
owner.adjustToxLoss(-amount, FALSE, TRUE)
+1 -1
View File
@@ -15,7 +15,7 @@
/obj/item/assembly/igniter/suicide_act(mob/living/carbon/user)
user.visible_message(span_suicide("[user] is trying to ignite [user.p_them()]self with \the [src]! It looks like [user.p_theyre()] trying to commit suicide!"))
user.IgniteMob()
user.ignite_mob()
return FIRELOSS
/obj/item/assembly/igniter/Initialize(mapload)
@@ -6,7 +6,7 @@
requires_power = FALSE
static_lighting = FALSE
base_lighting_alpha = 255
/area/awaymission/snowdin/outside
name = "Snowdin Tundra Plains"
icon_state = "awaycontent25"
@@ -219,7 +219,7 @@
burn_human.visible_message(span_warning("[burn_human]'s [burn_limb.name] melts down to the bone!"), \
span_userdanger("You scream out in pain as your [burn_limb.name] melts down to the bone, leaving an eerie plasma-like glow where flesh used to be!"))
if(!plasma_parts.len && !robo_parts.len) //a person with no potential organic limbs left AND no robotic limbs, time to turn them into a plasmaman
burn_human.IgniteMob()
burn_human.ignite_mob()
burn_human.set_species(/datum/species/plasmaman)
burn_human.visible_message(span_warning("[burn_human] bursts into a brilliant purple flame as [burn_human.p_their()] entire body is that of a skeleton!"), \
span_userdanger("Your senses numb as all of your remaining flesh is turned into a purple slurry, sloshing off your body and leaving only your bones to show in a vibrant purple!"))
@@ -22,7 +22,7 @@
if(!istype(H))
return
if(H.fire_stacks)
if(H.fire_stacks > 0)
if(extinguishes_left)
if(next_extinguish > world.time)
return
@@ -152,8 +152,8 @@
for(var/mob/living/carbon/carbon_victim in range(6, owner))
if(carbon_victim != owner)
carbon_victim.adjust_fire_stacks(8)
carbon_victim.IgniteMob()
owner.set_fire_stacks(-20)
carbon_victim.ignite_mob()
owner.set_wet_stacks(20)
reactivearmor_cooldown = world.time + reactivearmor_cooldown_duration
return TRUE
@@ -161,7 +161,7 @@
owner.visible_message(span_danger("[src] just makes [attack_text] worse by spewing molten death on [owner]!"))
playsound(get_turf(owner),'sound/magic/fireball.ogg', 100, TRUE)
owner.adjust_fire_stacks(12)
owner.IgniteMob()
owner.ignite_mob()
reactivearmor_cooldown = world.time + reactivearmor_cooldown_duration
return FALSE
+1 -1
View File
@@ -1475,7 +1475,7 @@ GLOBAL_LIST_INIT(hallucination_list, list(
set waitfor = FALSE
..()
target.set_fire_stacks(max(target.fire_stacks, 0.1)) //Placebo flammability
fire_overlay = image('icons/mob/OnFire.dmi', target, "Standing", ABOVE_MOB_LAYER)
fire_overlay = image('icons/mob/onfire.dmi', target, "human_burning", ABOVE_MOB_LAYER)
if(target.client)
target.client.images += fire_overlay
to_chat(target, span_userdanger("You're set on fire!"))
@@ -81,7 +81,7 @@
var/obj/item/seeds/our_seed = our_plant.get_plant_seed()
to_chat(target, "<span class='danger'>You are lit on fire from the intense heat of [our_plant]!</span>")
target.adjust_fire_stacks(our_seed.potency / 20)
if(target.IgniteMob())
if(target.ignite_mob())
message_admins("[ADMIN_LOOKUPFLW(user)] set [ADMIN_LOOKUPFLW(target)] on fire with [our_plant] at [AREACOORD(user)]")
log_game("[key_name(user)] set [key_name(target)] on fire with [our_plant] at [AREACOORD(user)]")
our_plant.investigate_log("was used by [key_name(user)] to burn [key_name(target)] at [AREACOORD(user)]", INVESTIGATE_BOTANY)
@@ -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
+1 -1
View File
@@ -211,7 +211,7 @@
if(user.is_holding(I)) //checking if they're holding it in case TK is involved
user.dropItemToGround(I)
user.adjust_fire_stacks(1)
user.IgniteMob()
user.ignite_mob()
return
if(user.is_holding(src)) //no TK shit here.
+1 -1
View File
@@ -206,7 +206,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/ticket_machine, 32)
theirticket.fire_act()
user.dropItemToGround(theirticket)
user.adjust_fire_stacks(1)
user.IgniteMob()
user.ignite_mob()
return
/obj/item/ticket_machine_ticket
@@ -396,7 +396,7 @@
span_userdanger("You feel an inner fire as your skin bursts into flames!")
)
burned_mob.adjust_fire_stacks(5)
burned_mob.IgniteMob()
burned_mob.ignite_mob()
return
/obj/singularity/proc/mezzer()
@@ -139,7 +139,7 @@
var/mob/living/user = loc
user.visible_message(span_danger("Concentrated plasma discharges from [src] onto [user], burning them!"), span_userdanger("[src] malfunctions, spewing concentrated plasma onto you! It burns!"))
user.adjust_fire_stacks(4)
user.IgniteMob()
user.ignite_mob()
// Can we weld? Plasma cutter does not use charge continuously.
// Amount cannot be defaulted to 1: most of the code specifies 0 in the call.
+1 -1
View File
@@ -50,7 +50,7 @@
. = ..()
if(iscarbon(target))
var/mob/living/carbon/M = target
M.IgniteMob()
M.ignite_mob()
else if(isturf(target))
impact_effect_type = /obj/effect/temp_visual/impact_effect/red_laser/wall
@@ -10,7 +10,7 @@
if(iscarbon(target))
var/mob/living/carbon/M = target
M.adjust_fire_stacks(fire_stacks)
M.IgniteMob()
M.ignite_mob()
/obj/projectile/bullet/incendiary/Move()
. = ..()
@@ -88,7 +88,7 @@
if(iscarbon(target))
var/mob/living/carbon/M = target
M.adjust_fire_stacks(6)
M.IgniteMob()
M.ignite_mob()
/obj/projectile/bullet/c38/iceblox //see /obj/projectile/temp for the original code
name = ".38 Iceblox bullet"
+1 -1
View File
@@ -242,7 +242,7 @@
user.visible_message(span_notice("[user] snuffs out [src]'s flame."))
/obj/item/burner/attack(mob/living/carbon/M, mob/living/carbon/user)
if(lit && M.IgniteMob())
if(lit && M.ignite_mob())
message_admins("[ADMIN_LOOKUPFLW(user)] set [key_name_admin(M)] on fire with [src] at [AREACOORD(user)]")
log_game("[key_name(user)] set [key_name(M)] on fire with [src] at [AREACOORD(user)]")
return ..()
@@ -2441,7 +2441,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
drinker.adjust_bodytemperature(25 * REM * TEMPERATURE_DAMAGE_COEFFICIENT * delta_time)
if (DT_PROB(2.5, delta_time))
drinker.adjust_fire_stacks(1)
drinker.IgniteMob()
drinker.ignite_mob()
..()
/datum/reagent/consumable/ethanol/painkiller
@@ -221,7 +221,7 @@
return
exposed_mob.adjust_bodytemperature(-reac_volume * TEMPERATURE_DAMAGE_COEFFICIENT, 50)
exposed_mob.adjust_fire_stacks(-reac_volume / 2)
exposed_mob.adjust_fire_stacks(reac_volume / -2)
if(reac_volume >= metabolization_rate)
exposed_mob.extinguish_mob()
@@ -395,7 +395,7 @@
/datum/reagent/hellwater/on_mob_life(mob/living/carbon/M, delta_time, times_fired)
M.set_fire_stacks(min(M.fire_stacks + (1.5 * delta_time), 5))
M.IgniteMob() //Only problem with igniting people is currently the commonly available fire suits make you immune to being on fire
M.ignite_mob() //Only problem with igniting people is currently the commonly available fire suits make you immune to being on fire
M.adjustToxLoss(0.5*delta_time, 0)
M.adjustFireLoss(0.5*delta_time, 0) //Hence the other damages... ain't I a bastard?
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 2.5*delta_time, 150)
@@ -73,7 +73,7 @@
/datum/reagent/clf3/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume)
. = ..()
exposed_mob.adjust_fire_stacks(min(reac_volume/5, 10))
exposed_mob.IgniteMob()
exposed_mob.ignite_mob()
if(!locate(/obj/effect/hotspot) in exposed_mob.loc)
new /obj/effect/hotspot(exposed_mob.loc)
@@ -185,7 +185,7 @@
exposed_mob.adjust_fire_stacks(1)
var/burndmg = max(0.3*exposed_mob.fire_stacks, 0.3)
exposed_mob.adjustFireLoss(burndmg, 0)
exposed_mob.IgniteMob()
exposed_mob.ignite_mob()
/datum/reagent/phlogiston/on_mob_life(mob/living/carbon/metabolizer, delta_time, times_fired)
metabolizer.adjust_fire_stacks(1 * REM * delta_time)
@@ -424,7 +424,7 @@
/datum/reagent/toxin/spore_burning/on_mob_life(mob/living/carbon/M, delta_time, times_fired)
M.adjust_fire_stacks(2 * REM * delta_time)
M.IgniteMob()
M.ignite_mob()
return ..()
/datum/reagent/toxin/chloralhydrate
@@ -140,7 +140,7 @@
to_chat(C, span_userdanger("The divine explosion sears you!"))
C.Paralyze(40)
C.adjust_fire_stacks(5)
C.IgniteMob()
C.ignite_mob()
..()
/datum/chemical_reaction/gunpowder
@@ -632,7 +632,7 @@
/datum/status_effect/stabilized/darkblue/tick()
if(owner.fire_stacks > 0 && prob(80))
owner.adjust_fire_stacks(-1)
owner.adjust_wet_stacks(1)
if(owner.fire_stacks <= 0)
to_chat(owner, span_notice("[linked_extract] coats you in a watery goo, extinguishing the flames."))
var/obj/O = owner.get_active_held_item()
@@ -331,7 +331,7 @@
if(SLIME_ACTIVATE_MINOR)
to_chat(user, span_notice("You activate [src]. You start feeling colder!"))
user.extinguish_mob()
user.adjust_fire_stacks(-20)
user.adjust_wet_stacks(20)
user.reagents.add_reagent(/datum/reagent/consumable/frostoil,6)
user.reagents.add_reagent(/datum/reagent/medicine/regen_jelly,7)
return 100
+2 -2
View File
@@ -291,9 +291,9 @@
if(isliving(user))
var/mob/living/caster = user
if(caster.can_cast_magic(antimagic_flags))
caster.IgniteMob()
caster.ignite_mob()
else
return
return
for(var/mob/living/target in targets)
if(target.can_block_magic(antimagic_flags))
to_chat(user, span_warning("The spell can't seem to affect [target]!"))
+1 -1
View File
@@ -201,7 +201,7 @@
playsound(get_turf(owner), 'sound/weapons/flashbang.ogg', 100, TRUE)
to_chat(owner, span_userdanger("You feel an explosion erupt inside your [zone == BODY_ZONE_R_ARM ? "right" : "left"] arm as your implant breaks!"))
owner.adjust_fire_stacks(20)
owner.IgniteMob()
owner.ignite_mob()
owner.adjustFireLoss(25)
organ_flags |= ORGAN_FAILING
+1 -1
View File
@@ -5,7 +5,7 @@
TEST_ASSERT_EQUAL(human.fire_stacks, 0, "Human does not have 0 fire stacks pre-ignition")
human.adjust_fire_stacks(5)
human.IgniteMob()
human.ignite_mob()
TEST_ASSERT_EQUAL(human.fire_stacks, 5, "Human does not have 5 fire stacks pre-resist")
+1 -1
View File
@@ -577,7 +577,7 @@
for(var/mob/living/cookedalive as anything in occupants)
if(cookedalive.fire_stacks < 5)
cookedalive.adjust_fire_stacks(1)
cookedalive.IgniteMob()
cookedalive.ignite_mob()
///Displays a special speech bubble when someone inside the mecha speaks
/obj/vehicle/sealed/mecha/proc/display_speech_bubble(datum/source, list/speech_args)
Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

+1
View File
@@ -1121,6 +1121,7 @@
#include "code\datums\status_effects\debuffs\dizziness.dm"
#include "code\datums\status_effects\debuffs\drugginess.dm"
#include "code\datums\status_effects\debuffs\drunk.dm"
#include "code\datums\status_effects\debuffs\fire_stacks.dm"
#include "code\datums\status_effects\debuffs\speech_debuffs.dm"
#include "code\datums\weather\weather.dm"
#include "code\datums\weather\weather_types\ash_storm.dm"