diff --git a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_attack.dm b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_attack.dm index 0a49f7d538f..6299fae7a08 100644 --- a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_attack.dm +++ b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_attack.dm @@ -24,6 +24,8 @@ #define COMSIG_ATOM_FIX "atom_fix" /// from base of [/atom/proc/atom_destruction]: (damage_flag) #define COMSIG_ATOM_DESTRUCTION "atom_destruction" +/// from base of [/atom/proc/extinguish] +#define COMSIG_ATOM_EXTINGUISH "atom_extinguish" ///from base of [/atom/proc/update_integrity]: (old_value, new_value) #define COMSIG_ATOM_INTEGRITY_CHANGED "atom_integrity_changed" ///from base of [/atom/proc/take_damage]: (damage_amount, damage_type, damage_flag, sound_effect, attack_dir, aurmor_penetration) diff --git a/code/__DEFINES/flags.dm b/code/__DEFINES/flags.dm index dfe85cd97bf..51a177b08ea 100644 --- a/code/__DEFINES/flags.dm +++ b/code/__DEFINES/flags.dm @@ -168,7 +168,9 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204 #define LAVA_PROOF (1<<0) /// 100% immune to fire damage (but not necessarily to lava or heat) #define FIRE_PROOF (1<<1) +/// atom is flammable and can have the burning component #define FLAMMABLE (1<<2) +/// currently burning #define ON_FIRE (1<<3) /// acid can't even appear on it, let alone melt it. #define UNACIDABLE (1<<4) diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm index fafc3212bfd..d30b65d5a50 100644 --- a/code/__DEFINES/subsystems.dm +++ b/code/__DEFINES/subsystems.dm @@ -214,7 +214,7 @@ #define FIRE_PRIOTITY_SMOOTHING 35 #define FIRE_PRIORITY_OBJ 40 #define FIRE_PRIORITY_ACID 40 -#define FIRE_PRIOTITY_BURNING 40 +#define FIRE_PRIORITY_BURNING 40 #define FIRE_PRIORITY_DEFAULT 50 #define FIRE_PRIORITY_PARALLAX 65 #define FIRE_PRIORITY_INSTRUMENTS 80 diff --git a/code/controllers/subsystem/fire_burning.dm b/code/controllers/subsystem/fire_burning.dm deleted file mode 100644 index 345c0e27615..00000000000 --- a/code/controllers/subsystem/fire_burning.dm +++ /dev/null @@ -1,40 +0,0 @@ -SUBSYSTEM_DEF(fire_burning) - name = "Fire Burning" - priority = FIRE_PRIOTITY_BURNING - flags = SS_NO_INIT|SS_BACKGROUND - runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME - - var/list/currentrun = list() - var/list/processing = list() - -/datum/controller/subsystem/fire_burning/stat_entry(msg) - msg = "P:[length(processing)]" - return ..() - - -/datum/controller/subsystem/fire_burning/fire(resumed = 0) - if (!resumed) - src.currentrun = processing.Copy() - - //cache for sanic speed (lists are references anyways) - var/list/currentrun = src.currentrun - var/seconds_per_tick = wait * 0.1 - - while(currentrun.len) - var/obj/O = currentrun[currentrun.len] - currentrun.len-- - if (!O || QDELETED(O)) - processing -= O - if (MC_TICK_CHECK) - return - continue - - - if(O.resistance_flags & ON_FIRE) //in case an object is extinguished while still in currentrun - if(!(O.resistance_flags & FIRE_PROOF)) - O.take_damage(10 * seconds_per_tick, BURN, FIRE, 0) - else - O.extinguish() - - if (MC_TICK_CHECK) - return diff --git a/code/controllers/subsystem/processing/fire_burning.dm b/code/controllers/subsystem/processing/fire_burning.dm new file mode 100644 index 00000000000..43c9ffd3306 --- /dev/null +++ b/code/controllers/subsystem/processing/fire_burning.dm @@ -0,0 +1,6 @@ +/// The subsystem used to tick [/datum/component/burning] instances. +PROCESSING_SUBSYSTEM_DEF(fire_burning) + name = "Fire Burning" + priority = FIRE_PRIORITY_BURNING + flags = SS_NO_INIT|SS_BACKGROUND + runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME diff --git a/code/datums/components/acid.dm b/code/datums/components/acid.dm index a1594f6f00e..f5c2551f8d6 100644 --- a/code/datums/components/acid.dm +++ b/code/datums/components/acid.dm @@ -1,3 +1,5 @@ +GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/effects/effects.dmi', "acid")) + /** Component representing acid applied to an object. * * Must be attached to an atom. diff --git a/code/datums/components/burning.dm b/code/datums/components/burning.dm new file mode 100644 index 00000000000..d2ccd03147c --- /dev/null +++ b/code/datums/components/burning.dm @@ -0,0 +1,70 @@ +GLOBAL_DATUM_INIT(fire_overlay, /mutable_appearance, mutable_appearance('icons/effects/fire.dmi', "fire", appearance_flags = RESET_COLOR)) + +/** + * Component representing an atom being on fire. + * Should not be used on mobs, they use the fire stacks system. + */ +/datum/component/burning + /// Fire overlay appearance we apply + var/fire_overlay + /// Particle holder for fire particles, if any + var/obj/effect/abstract/particle_holder/particle_effect + +/datum/component/burning/Initialize(fire_overlay, fire_particles) + if(!isatom(parent)) + return COMPONENT_INCOMPATIBLE + var/atom/atom_parent = parent + if(!atom_parent.uses_integrity) + stack_trace("Tried to add /datum/component/burning to an atom ([atom_parent]) that does not use atom_integrity!") + return COMPONENT_INCOMPATIBLE + // only flammable atoms should have this component, but it's not really an error if we try to apply this to a non flammable one + if(!(atom_parent.resistance_flags & FLAMMABLE) || (atom_parent.resistance_flags & FIRE_PROOF)) + qdel(src) + return + src.fire_overlay = fire_overlay + if(fire_particles) + particle_effect = new(atom_parent, fire_particles) + atom_parent.resistance_flags |= ON_FIRE + START_PROCESSING(SSfire_burning, src) + +/datum/component/burning/RegisterWithParent() + . = ..() + RegisterSignal(parent, COMSIG_ATOM_UPDATE_OVERLAYS, PROC_REF(on_update_overlays)) + RegisterSignal(parent, COMSIG_ATOM_EXTINGUISH, PROC_REF(on_extinguish)) + var/atom/atom_parent = parent + atom_parent.update_appearance(UPDATE_ICON) + +/datum/component/burning/UnregisterFromParent() + . = ..() + UnregisterSignal(parent, list(COMSIG_ATOM_UPDATE_OVERLAYS, COMSIG_ATOM_EXTINGUISH)) + +/datum/component/burning/Destroy(force, silent) + STOP_PROCESSING(SSfire_burning, src) + if(particle_effect) + QDEL_NULL(particle_effect) + var/atom/atom_parent = parent + if(!QDELING(atom_parent) && (atom_parent.resistance_flags & ON_FIRE)) + atom_parent.resistance_flags &= ~ON_FIRE + atom_parent.update_appearance(UPDATE_ICON) + return ..() + +/datum/component/burning/process(seconds_per_tick) + var/atom/atom_parent = parent + // Check if the parent somehow became fireproof + if(atom_parent.resistance_flags & FIRE_PROOF) + atom_parent.extinguish() + return + atom_parent.take_damage(10 * seconds_per_tick, BURN, FIRE, FALSE) + +/// Maintains the burning overlay on the parent atom +/datum/component/burning/proc/on_update_overlays(atom/source, list/overlays) + SIGNAL_HANDLER + + if(fire_overlay) + overlays += fire_overlay + +/// Deletes the component when the atom gets extinguished +/datum/component/burning/proc/on_extinguish(atom/source, list/overlays) + SIGNAL_HANDLER + + qdel(src) diff --git a/code/game/atom_defense.dm b/code/game/atom_defense.dm index 8087fd4dc4b..b2760f23597 100644 --- a/code/game/atom_defense.dm +++ b/code/game/atom_defense.dm @@ -140,3 +140,19 @@ /// A cut-out proc for [/atom/proc/bullet_act] so living mobs can have their own armor behavior checks without causing issues with needing their own on_hit call /atom/proc/check_projectile_armor(def_zone, obj/projectile/impacting_projectile, is_silent) return 0 + +/** + * Should be called when the atom is destroyed by fire + * This proc is terrible. I do not know why it exists. + * Please remove it at some point. + */ +/atom/proc/burn() + return + +/** + * Sends COMSIG_ATOM_EXTINGUISH signal which properly removes burning component. + * Can be hooked onto for extra behavior. + */ +/atom/proc/extinguish() + SHOULD_CALL_PARENT(TRUE) + return SEND_SIGNAL(src, COMSIG_ATOM_EXTINGUISH) diff --git a/code/game/objects/effects/particles/smoke.dm b/code/game/objects/effects/particles/smoke.dm index bf66fdb6b07..d4b6f21cd48 100644 --- a/code/game/objects/effects/particles/smoke.dm +++ b/code/game/objects/effects/particles/smoke.dm @@ -14,6 +14,9 @@ gravity = list(0, 0.95) grow = 0.05 +/particles/smoke/burning + position = list(0, 0, 0) + /particles/smoke/steam icon_state = list("steam_1" = 1, "steam_2" = 1, "steam_3" = 2) fade = 1.5 SECONDS diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index f0a1e4eba2c..8c73c37f167 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -1,5 +1,3 @@ -GLOBAL_DATUM_INIT(fire_overlay, /mutable_appearance, mutable_appearance('icons/effects/fire.dmi', "fire", appearance_flags = RESET_COLOR)) - /// Anything you can pick up and hold. /obj/item name = "item" diff --git a/code/game/objects/items/cigs_lighters.dm b/code/game/objects/items/cigs_lighters.dm index 4d20b58911c..bde68404844 100644 --- a/code/game/objects/items/cigs_lighters.dm +++ b/code/game/objects/items/cigs_lighters.dm @@ -78,6 +78,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM STOP_PROCESSING(SSobj, src) /obj/item/match/extinguish() + . = ..() matchburnout() /obj/item/match/dropped(mob/user) @@ -304,6 +305,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM M.update_held_items() /obj/item/clothing/mask/cigarette/extinguish() + . = ..() if(!lit) return attack_verb_continuous = null @@ -792,6 +794,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM update_appearance() /obj/item/lighter/extinguish() + . = ..() set_lit(FALSE) /obj/item/lighter/attack_self(mob/living/user) diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm index 7e5a0a89ece..ffdad36cb6d 100644 --- a/code/game/objects/items/devices/flashlight.dm +++ b/code/game/objects/items/devices/flashlight.dm @@ -350,9 +350,9 @@ . = ..() //SKYRAT EDIT - MODULAR PARENT PROC /obj/item/flashlight/flare/extinguish() - if(fuel != INFINITY && can_be_extinguished) + . = ..() + if((fuel != INFINITY) && can_be_extinguished) turn_off() - return ..() /obj/item/flashlight/flare/update_brightness() ..() diff --git a/code/game/objects/obj_defense.dm b/code/game/objects/obj_defense.dm index 2cde9cee4c9..34f5bdbc90b 100644 --- a/code/game/objects/obj_defense.dm +++ b/code/game/objects/obj_defense.dm @@ -96,8 +96,6 @@ ///// ACID -GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/effects/effects.dmi', "acid")) - ///the obj's reaction when touched by acid /obj/acid_act(acidpwr, acid_volume) . = ..() @@ -123,25 +121,15 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e if(exposed_temperature && !(resistance_flags & FIRE_PROOF)) take_damage(clamp(0.02 * exposed_temperature, 0, 20), BURN, FIRE, 0) if(!(resistance_flags & ON_FIRE) && (resistance_flags & FLAMMABLE) && !(resistance_flags & FIRE_PROOF)) - resistance_flags |= ON_FIRE - SSfire_burning.processing[src] = src - update_appearance() - return 1 + AddComponent(/datum/component/burning, custom_fire_overlay || GLOB.fire_overlay, burning_particles) + return TRUE return ..() ///called when the obj is destroyed by fire -/obj/proc/burn() - if(resistance_flags & ON_FIRE) - SSfire_burning.processing -= src +/obj/burn() + . = ..() deconstruct(FALSE) -///Called when the obj is no longer on fire. -/obj/proc/extinguish() - if(resistance_flags & ON_FIRE) - resistance_flags &= ~ON_FIRE - update_appearance() - SSfire_burning.processing -= src - ///Called when the obj is hit by a tesla bolt. /obj/zap_act(power, zap_flags) if(QDELETED(src)) diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index cbb89e7fb8c..644c3e0ea6d 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -35,8 +35,10 @@ /// Example: If req_one_access = list(ACCESS_ENGINE, ACCESS_CE)- then the user must have either ACCESS_ENGINE or ACCESS_CE in order to use the object. var/list/req_one_access - /// Custom fire overlay icon + /// Custom fire overlay icon, will just use the default overlay if this is null var/custom_fire_overlay + /// Particles this obj uses when burning, if any + var/burning_particles var/renamedByPlayer = FALSE //set when a player uses a pen on a renamable object diff --git a/code/game/objects/structures.dm b/code/game/objects/structures.dm index dbc061a34bf..71d15fb3f58 100644 --- a/code/game/objects/structures.dm +++ b/code/game/objects/structures.dm @@ -9,8 +9,9 @@ receive_ricochet_chance_mod = 0.6 pass_flags_self = PASSSTRUCTURE blocks_emissive = EMISSIVE_BLOCK_GENERIC - var/broken = FALSE armor_type = /datum/armor/obj_structure + burning_particles = /particles/smoke/burning + var/broken = FALSE /datum/armor/obj_structure fire = 50 diff --git a/code/game/objects/structures/bonfire.dm b/code/game/objects/structures/bonfire.dm index 9de1ff76362..287db0e4b4d 100644 --- a/code/game/objects/structures/bonfire.dm +++ b/code/game/objects/structures/bonfire.dm @@ -166,12 +166,14 @@ bonfire_burn(seconds_per_tick) /obj/structure/bonfire/extinguish() - if(burning) - icon_state = "bonfire" - burning = FALSE - set_light(0) - QDEL_NULL(particles) - STOP_PROCESSING(SSobj, src) + . = ..() + if(!burning) + return + icon_state = "bonfire" + burning = FALSE + set_light(0) + QDEL_NULL(particles) + STOP_PROCESSING(SSobj, src) /obj/structure/bonfire/buckle_mob(mob/living/buckled_mob, force = FALSE, check_loc = TRUE) if(..()) diff --git a/code/game/objects/structures/fireplace.dm b/code/game/objects/structures/fireplace.dm index 0e7e4f8bd71..81a6626810f 100644 --- a/code/game/objects/structures/fireplace.dm +++ b/code/game/objects/structures/fireplace.dm @@ -118,12 +118,12 @@ adjust_light() /obj/structure/fireplace/extinguish() + . = ..() if(lit) var/fuel = burn_time_remaining() flame_expiry_timer = 0 put_out() adjust_fuel_timer(fuel) - . = ..() /obj/structure/fireplace/proc/adjust_fuel_timer(amount) if(lit) diff --git a/code/modules/antagonists/blob/structures/_blob.dm b/code/modules/antagonists/blob/structures/_blob.dm index e4a691395be..b3a71944e6d 100644 --- a/code/modules/antagonists/blob/structures/_blob.dm +++ b/code/modules/antagonists/blob/structures/_blob.dm @@ -232,7 +232,7 @@ return ..() //You don't get to do it for free /obj/structure/blob/extinguish() - ..() + . = ..() if(overmind) overmind.blobstrain.extinguish_reaction(src) diff --git a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm index f4fe733bd54..6f88d9ffa25 100644 --- a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm +++ b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm @@ -130,9 +130,9 @@ if(to_be_destroyed && exposed_temperature >= max_fire_temperature_sustained) max_fire_temperature_sustained = min(exposed_temperature, max_fire_temperature_sustained + heat_capacity / 4) //Ramp up to 100% yeah? if(to_be_destroyed && !changing_turf) - burn() + burn_turf() -/turf/proc/burn() +/turf/proc/burn_turf() burn_tile() var/chance_of_deletion if (heat_capacity) //beware of division by zero diff --git a/code/modules/awaymissions/mission_code/Cabin.dm b/code/modules/awaymissions/mission_code/Cabin.dm index f2c55228fcf..3a7bdef7be9 100644 --- a/code/modules/awaymissions/mission_code/Cabin.dm +++ b/code/modules/awaymissions/mission_code/Cabin.dm @@ -76,6 +76,7 @@ icon_state = "firepit" /obj/structure/firepit/extinguish() + . = ..() if(active) active = FALSE toggleFirepit() diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm index 5ffc4209404..b9e401f3127 100644 --- a/code/modules/paperwork/paper.dm +++ b/code/modules/paperwork/paper.dm @@ -325,10 +325,6 @@ return . += span_warning("You cannot read it!") -/obj/item/paper/extinguish() - ..() - update_appearance() - /obj/item/paper/ui_status(mob/user,/datum/ui_state/state) // Are we on fire? Hard to read if so if(resistance_flags & ON_FIRE) diff --git a/code/modules/reagents/chemistry/items.dm b/code/modules/reagents/chemistry/items.dm index 0a8f0cc5f39..b2e29e3c5d6 100644 --- a/code/modules/reagents/chemistry/items.dm +++ b/code/modules/reagents/chemistry/items.dm @@ -231,6 +231,7 @@ update_icon() /obj/item/burner/extinguish() + . = ..() set_lit(FALSE) /obj/item/burner/attack_self(mob/living/user) diff --git a/code/modules/reagents/chemistry/machinery/chem_separator.dm b/code/modules/reagents/chemistry/machinery/chem_separator.dm index 10aaded82e2..41fd1eb188d 100644 --- a/code/modules/reagents/chemistry/machinery/chem_separator.dm +++ b/code/modules/reagents/chemistry/machinery/chem_separator.dm @@ -143,9 +143,9 @@ start() /obj/structure/chem_separator/extinguish() + . = ..() if(burning) stop() - return ..() /// Ignite the burner to start the separation process /obj/structure/chem_separator/proc/start() diff --git a/modular_skyrat/modules/liquids/code/liquid_systems/liquid_effect.dm b/modular_skyrat/modules/liquids/code/liquid_systems/liquid_effect.dm index 4c7cdf7de40..051f3843676 100644 --- a/modular_skyrat/modules/liquids/code/liquid_systems/liquid_effect.dm +++ b/modular_skyrat/modules/liquids/code/liquid_systems/liquid_effect.dm @@ -112,6 +112,7 @@ return total_burn_power /obj/effect/abstract/liquid_turf/extinguish() + . = ..() if(fire_state) set_fire_state(LIQUID_FIRE_STATE_NONE) diff --git a/tgstation.dme b/tgstation.dme index 6aef59a85cc..740b7fa9c42 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -640,7 +640,6 @@ #include "code\controllers\subsystem\eigenstate.dm" #include "code\controllers\subsystem\events.dm" #include "code\controllers\subsystem\explosions.dm" -#include "code\controllers\subsystem\fire_burning.dm" #include "code\controllers\subsystem\fluids.dm" #include "code\controllers\subsystem\garbage.dm" #include "code\controllers\subsystem\icon_smooth.dm" @@ -719,6 +718,7 @@ #include "code\controllers\subsystem\processing\clock_component.dm" #include "code\controllers\subsystem\processing\conveyors.dm" #include "code\controllers\subsystem\processing\fastprocess.dm" +#include "code\controllers\subsystem\processing\fire_burning.dm" #include "code\controllers\subsystem\processing\greyscale.dm" #include "code\controllers\subsystem\processing\instruments.dm" #include "code\controllers\subsystem\processing\obj.dm" @@ -944,6 +944,7 @@ #include "code\datums\components\bloodysoles.dm" #include "code\datums\components\boomerang.dm" #include "code\datums\components\bumpattack.dm" +#include "code\datums\components\burning.dm" #include "code\datums\components\butchering.dm" #include "code\datums\components\caltrop.dm" #include "code\datums\components\chasm.dm"