mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-28 23:58:07 +01:00
Burning and acid components fixes and improvements (#74803)
## About The Pull Request Generally cleans up code on both components. Moves burn proc back to /obj level, I'm not sure why I moved it to /atom level, it was unnecessary. Acid component generalized so it can be used on any atom that uses atom_integrity. Fixes a bug where objects that stopped burning didn't update their burn overlay properly due to bad removal logic and leftover code. Standardizes examine messages on burning items by just slapping an examine signal registration on the component. Adds fire particles to items thanks to Lemon's PR: https://github.com/tgstation/tgstation/pull/74524 ## Why It's Good For The Game Particles look cool   Bugfixes are good Code improvements are good ## Changelog 🆑 add: Burning items now get (small) smoke particles. Sick. fix: Burning objects now clear their burning overlay properly. qol: Examining burning objects will always tell you that they are burning. /🆑 --------- Co-authored-by: san7890 <the@san7890.com>
This commit is contained in:
co-authored by
san7890
parent
652ef28e3c
commit
b093b12e03
@@ -1,10 +1,11 @@
|
||||
GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/effects/effects.dmi', "acid"))
|
||||
GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/effects/acid.dmi', "default"))
|
||||
|
||||
/** Component representing acid applied to an object.
|
||||
*
|
||||
/**
|
||||
* Component representing acid applied to an object.
|
||||
* Must be attached to an atom.
|
||||
* Processes, repeatedly damaging whatever it is attached to.
|
||||
* If the parent atom is a turf it applies acid to the contents of the turf.
|
||||
* If not being applied to a mob or turf, the atom must use the integrity system.
|
||||
*/
|
||||
/datum/component/acid
|
||||
dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS
|
||||
@@ -14,6 +15,8 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e
|
||||
var/acid_volume
|
||||
/// The maximum volume of acid on the parent [/atom].
|
||||
var/max_volume = INFINITY
|
||||
/// Acid overlay appearance we apply
|
||||
var/acid_overlay
|
||||
/// The ambiant sound of acid eating away at the parent [/atom].
|
||||
var/datum/looping_sound/acid/sizzle
|
||||
/// Used exclusively for melting turfs. TODO: Move integrity to the atom level so that this can be dealt with there.
|
||||
@@ -23,71 +26,80 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e
|
||||
/// The proc used to handle the parent [/atom] when processing. TODO: Unify damage and resistance flags so that this doesn't need to exist!
|
||||
var/datum/callback/process_effect
|
||||
|
||||
/datum/component/acid/Initialize(_acid_power, _acid_volume, _max_volume=null)
|
||||
if((_acid_power) <= 0 || (_acid_volume <= 0))
|
||||
stack_trace("Acid component added with insufficient acid power ([_acid_power]) or acid volume ([_acid_power]).")
|
||||
return COMPONENT_INCOMPATIBLE // Not enough acid or the acid's too weak, either one.
|
||||
/datum/component/acid/Initialize(acid_power = ACID_POWER_MELT_TURF, acid_volume = 50, acid_overlay = GLOB.acid_overlay)
|
||||
if(!isatom(parent))
|
||||
stack_trace("Acid component added to [parent] ([parent?.type]) which is not a /atom subtype.")
|
||||
return COMPONENT_INCOMPATIBLE // Incompatible type. TODO: Rework take_damage to the atom level and move this there.
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
//not incompatible, but pointless
|
||||
var/atom/atom_parent = parent
|
||||
if((acid_power) <= 0 || (acid_volume <= 0))
|
||||
stack_trace("Acid component added to an atom ([atom_parent.type]) with insufficient acid power ([acid_power]) or acid volume ([acid_volume]).")
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
if(isobj(parent))
|
||||
var/obj/parent_object = parent
|
||||
if(parent_object.resistance_flags & UNACIDABLE) // The parent object cannot have acid. Should never happen, will happen.
|
||||
stack_trace("Acid component added to unacidable object [parent].")
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
max_volume = OBJ_ACID_VOLUME_MAX
|
||||
process_effect = CALLBACK(src, PROC_REF(process_obj), parent)
|
||||
else if(isliving(parent))
|
||||
if(isliving(parent))
|
||||
max_volume = MOB_ACID_VOLUME_MAX
|
||||
process_effect = CALLBACK(src, PROC_REF(process_mob), parent)
|
||||
else if(isturf(parent))
|
||||
max_volume = TURF_ACID_VOLUME_MAX
|
||||
process_effect = CALLBACK(src, PROC_REF(process_turf), parent)
|
||||
//if we failed all other checks, we must be an /atom/movable that uses integrity
|
||||
else if(atom_parent.uses_integrity)
|
||||
// The parent object cannot have acid. Not incompatible, but should not really happen.
|
||||
if(atom_parent.resistance_flags & UNACIDABLE)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
acid_power = _acid_power
|
||||
set_volume(_acid_volume)
|
||||
max_volume = MOVABLE_ACID_VOLUME_MAX
|
||||
process_effect = CALLBACK(src, PROC_REF(process_movable), parent)
|
||||
//or not...
|
||||
else
|
||||
stack_trace("Tried to add /datum/component/acid to an atom ([atom_parent.type]) which does not use atom_integrity!")
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
src.acid_power = acid_power
|
||||
set_volume(acid_volume)
|
||||
src.acid_overlay = acid_overlay
|
||||
|
||||
var/atom/parent_atom = parent
|
||||
RegisterSignal(parent, COMSIG_ATOM_UPDATE_OVERLAYS, PROC_REF(on_update_overlays))
|
||||
parent_atom.update_appearance()
|
||||
sizzle = new(parent, TRUE)
|
||||
START_PROCESSING(SSacid, src)
|
||||
|
||||
/datum/component/acid/Destroy(force, silent)
|
||||
STOP_PROCESSING(SSacid, src)
|
||||
QDEL_NULL(sizzle)
|
||||
if(sizzle)
|
||||
QDEL_NULL(sizzle)
|
||||
if(process_effect)
|
||||
QDEL_NULL(process_effect)
|
||||
UnregisterSignal(parent, COMSIG_ATOM_UPDATE_OVERLAYS)
|
||||
if(parent && !QDELING(parent))
|
||||
var/atom/parent_atom = parent
|
||||
parent_atom.update_appearance()
|
||||
return ..()
|
||||
|
||||
/datum/component/acid/RegisterWithParent()
|
||||
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, PROC_REF(on_examine))
|
||||
RegisterSignal(parent, COMSIG_ATOM_UPDATE_OVERLAYS, PROC_REF(on_update_overlays))
|
||||
RegisterSignal(parent, COMSIG_COMPONENT_CLEAN_ACT, PROC_REF(on_clean))
|
||||
RegisterSignal(parent, COMSIG_ATOM_ATTACK_HAND, PROC_REF(on_attack_hand))
|
||||
RegisterSignal(parent, COMSIG_ATOM_EXPOSE_REAGENT, PROC_REF(on_expose_reagent))
|
||||
if(isturf(parent))
|
||||
RegisterSignal(parent, COMSIG_ATOM_ENTERED, PROC_REF(on_entered))
|
||||
var/atom/atom_parent = parent
|
||||
atom_parent.update_appearance()
|
||||
|
||||
/datum/component/acid/UnregisterFromParent()
|
||||
UnregisterSignal(parent, list(
|
||||
COMSIG_PARENT_EXAMINE,
|
||||
COMSIG_ATOM_UPDATE_OVERLAYS,
|
||||
COMSIG_COMPONENT_CLEAN_ACT,
|
||||
COMSIG_ATOM_ATTACK_HAND,
|
||||
COMSIG_ATOM_EXPOSE_REAGENT))
|
||||
|
||||
if(isturf(parent))
|
||||
UnregisterSignal(parent, COMSIG_ATOM_ENTERED)
|
||||
var/atom/atom_parent = parent
|
||||
if(!QDELETED(atom_parent))
|
||||
atom_parent.update_appearance()
|
||||
|
||||
/// Averages corrosive power and sums volume.
|
||||
/datum/component/acid/InheritComponent(datum/component/C, i_am_original, _acid_power, _acid_volume)
|
||||
acid_power = ((acid_power * acid_volume) + (_acid_power * _acid_volume)) / (acid_volume + _acid_volume)
|
||||
set_volume(acid_volume + _acid_volume)
|
||||
/datum/component/acid/InheritComponent(datum/component/new_comp, i_am_original, acid_power, acid_volume)
|
||||
acid_power = ((src.acid_power * src.acid_volume) + (acid_power * acid_volume)) / (src.acid_volume + acid_volume)
|
||||
set_volume(src.acid_volume + acid_volume)
|
||||
|
||||
/// Sets the acid volume to a new value. Limits the acid volume by the amount allowed to exist on the parent atom.
|
||||
/datum/component/acid/proc/set_volume(new_volume)
|
||||
@@ -95,7 +107,6 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e
|
||||
if(!acid_volume)
|
||||
qdel(src)
|
||||
|
||||
|
||||
/// Handles the slow corrosion of the parent [/atom].
|
||||
/datum/component/acid/process(seconds_per_tick)
|
||||
process_effect?.InvokeAsync(seconds_per_tick)
|
||||
@@ -103,11 +114,11 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e
|
||||
return
|
||||
set_volume(acid_volume - (ACID_DECAY_BASE + (ACID_DECAY_SCALING*round(sqrt(acid_volume)))) * seconds_per_tick)
|
||||
|
||||
/// Handles processing on a [/obj].
|
||||
/datum/component/acid/proc/process_obj(obj/target, seconds_per_tick)
|
||||
/// Handles processing on an [/atom/movable] (that uses atom_integrity).
|
||||
/datum/component/acid/proc/process_movable(atom/movable/target, seconds_per_tick)
|
||||
if(target.resistance_flags & ACID_PROOF)
|
||||
return
|
||||
target.take_damage(min(1 + round(sqrt(acid_power * acid_volume)*0.3), OBJ_ACID_DAMAGE_MAX) * seconds_per_tick, BURN, ACID, 0)
|
||||
target.take_damage(min(1 + round(sqrt(acid_power * acid_volume)*0.3), MOVABLE_ACID_DAMAGE_MAX) * seconds_per_tick, BURN, ACID, 0)
|
||||
|
||||
/// Handles processing on a [/mob/living].
|
||||
/datum/component/acid/proc/process_mob(mob/living/target, seconds_per_tick)
|
||||
@@ -117,8 +128,7 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e
|
||||
/datum/component/acid/proc/process_turf(turf/target_turf, seconds_per_tick)
|
||||
var/acid_used = min(acid_volume * 0.05, 20) * seconds_per_tick
|
||||
var/applied_targets = 0
|
||||
for(var/am in target_turf)
|
||||
var/atom/movable/target_movable = am
|
||||
for(var/atom/movable/target_movable as anything in target_turf)
|
||||
if(target_movable.acid_act(acid_power, acid_used))
|
||||
applied_targets++
|
||||
|
||||
@@ -150,16 +160,17 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e
|
||||
/datum/component/acid/proc/on_update_overlays(atom/parent_atom, list/overlays)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
overlays += mutable_appearance('icons/effects/acid.dmi', parent_atom.custom_acid_overlay || ACID_OVERLAY_DEFAULT)
|
||||
if(acid_overlay)
|
||||
overlays += acid_overlay
|
||||
|
||||
/// Alerts any examiners to the acid on the parent atom.
|
||||
/datum/component/acid/proc/on_examine(atom/A, mob/user, list/examine_list)
|
||||
/datum/component/acid/proc/on_examine(atom/source, mob/user, list/examine_list)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
examine_list += span_danger("[A.p_theyre()] covered in corrosive liquid!")
|
||||
examine_list += span_danger("[source.p_theyre(TRUE)] covered in a corrosive liquid!")
|
||||
|
||||
/// Makes it possible to clean acid off of objects.
|
||||
/datum/component/acid/proc/on_clean(atom/A, clean_types)
|
||||
/datum/component/acid/proc/on_clean(atom/source, clean_types)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(!(clean_types & CLEAN_TYPE_ACID))
|
||||
@@ -178,7 +189,6 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e
|
||||
set_volume(acid_volume + reac_volume)
|
||||
return NONE
|
||||
|
||||
|
||||
/// Handles searing the hand of anyone who tries to touch this without protection.
|
||||
/datum/component/acid/proc/on_attack_hand(atom/parent_atom, mob/living/carbon/user)
|
||||
SIGNAL_HANDLER
|
||||
@@ -201,7 +211,6 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e
|
||||
user.update_damage_overlays()
|
||||
return COMPONENT_CANCEL_ATTACK_CHAIN
|
||||
|
||||
|
||||
/// Handles searing the feet of whoever walks over this without protection. Only active if the parent is a turf.
|
||||
/datum/component/acid/proc/on_entered(datum/source, atom/movable/arrived, atom/old_loc, list/atom/old_locs)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
@@ -2,7 +2,8 @@ GLOBAL_DATUM_INIT(fire_overlay, /mutable_appearance, mutable_appearance('icons/e
|
||||
|
||||
/**
|
||||
* Component representing an atom being on fire.
|
||||
* Should not be used on mobs, they use the fire stacks system.
|
||||
* Should not be used on mobs, they use the fire stacks status effects.
|
||||
* Can only be used on atoms that use the integrity system.
|
||||
*/
|
||||
/datum/component/burning
|
||||
/// Fire overlay appearance we apply
|
||||
@@ -10,12 +11,12 @@ GLOBAL_DATUM_INIT(fire_overlay, /mutable_appearance, mutable_appearance('icons/e
|
||||
/// Particle holder for fire particles, if any
|
||||
var/obj/effect/abstract/particle_holder/particle_effect
|
||||
|
||||
/datum/component/burning/Initialize(fire_overlay, fire_particles)
|
||||
/datum/component/burning/Initialize(fire_overlay = GLOB.fire_overlay, fire_particles = /particles/smoke/burning)
|
||||
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!")
|
||||
stack_trace("Tried to add /datum/component/burning to an atom ([atom_parent.type]) 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))
|
||||
@@ -23,30 +24,30 @@ GLOBAL_DATUM_INIT(fire_overlay, /mutable_appearance, mutable_appearance('icons/e
|
||||
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)
|
||||
// burning particles look pretty bad when they stack on mobs, so that behavior is not wanted for items
|
||||
particle_effect = new(atom_parent, fire_particles, isitem(atom_parent) ? NONE : PARTICLE_ATTACH_MOB)
|
||||
START_PROCESSING(SSburning, src)
|
||||
|
||||
/datum/component/burning/Destroy(force, silent)
|
||||
STOP_PROCESSING(SSburning, src)
|
||||
if(particle_effect)
|
||||
QDEL_NULL(particle_effect)
|
||||
return ..()
|
||||
|
||||
/datum/component/burning/RegisterWithParent()
|
||||
. = ..()
|
||||
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, PROC_REF(on_examine))
|
||||
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)
|
||||
atom_parent.resistance_flags |= ON_FIRE
|
||||
atom_parent.update_appearance()
|
||||
|
||||
/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)
|
||||
UnregisterSignal(parent, list(COMSIG_PARENT_EXAMINE, COMSIG_ATOM_UPDATE_OVERLAYS, COMSIG_ATOM_EXTINGUISH))
|
||||
var/atom/atom_parent = parent
|
||||
if(!QDELING(atom_parent) && (atom_parent.resistance_flags & ON_FIRE))
|
||||
if(!QDELETED(atom_parent))
|
||||
atom_parent.resistance_flags &= ~ON_FIRE
|
||||
atom_parent.update_appearance(UPDATE_ICON)
|
||||
return ..()
|
||||
atom_parent.update_appearance()
|
||||
|
||||
/datum/component/burning/process(seconds_per_tick)
|
||||
var/atom/atom_parent = parent
|
||||
@@ -56,10 +57,20 @@ GLOBAL_DATUM_INIT(fire_overlay, /mutable_appearance, mutable_appearance('icons/e
|
||||
return
|
||||
atom_parent.take_damage(10 * seconds_per_tick, BURN, FIRE, FALSE)
|
||||
|
||||
/// Alerts any examiners that the parent is on fire (even though it should be rather obvious)
|
||||
/datum/component/burning/proc/on_examine(atom/source, mob/user, list/examine_list)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
examine_list += span_danger("[source.p_theyre(TRUE)] burning!")
|
||||
|
||||
/// Maintains the burning overlay on the parent atom
|
||||
/datum/component/burning/proc/on_update_overlays(atom/source, list/overlays)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
//most likely means the component is being removed
|
||||
if(!(source.resistance_flags & ON_FIRE))
|
||||
return
|
||||
|
||||
if(fire_overlay)
|
||||
overlays += fire_overlay
|
||||
|
||||
|
||||
Reference in New Issue
Block a user