diff --git a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_main.dm b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_main.dm
index 94bd86920fe..a80324115f1 100644
--- a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_main.dm
+++ b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_main.dm
@@ -3,10 +3,10 @@
// All signals send the source datum of the signal as the first argument
// /atom signals
-///from base of atom/proc/Initialize(): sent any time a new atom is created in this atom
-#define COMSIG_ATOM_INITIALIZED_ON "atom_initialized_on"
//from SSatoms InitAtom - Only if the atom was not deleted or failed initialization
#define COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZE "atom_init_success"
+//from SSatoms InitAtom - Only if the atom was not deleted or failed initialization and has a loc
+#define COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZED_ON "atom_init_success_on"
///from base of atom/examine(): (/mob, list/examine_text)
#define COMSIG_ATOM_EXAMINE "atom_examine"
///from base of atom/get_examine_name(): (/mob, list/overrides)
diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm
index bb17412a2da..5d2bbd635ab 100644
--- a/code/__DEFINES/mobs.dm
+++ b/code/__DEFINES/mobs.dm
@@ -362,6 +362,8 @@
#define GALOSHES_DONT_HELP (1<<3)
/// Slip works even if you're already on the ground
#define SLIP_WHEN_CRAWLING (1<<4)
+/// the mob won't slip if the turf has the TRAIT_TURF_IGNORE_SLIPPERY trait.
+#define SLIPPERY_TURF (1<<5)
#define MAX_CHICKENS 50
diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm
index 61459485ab8..a817cfdca6c 100644
--- a/code/__DEFINES/traits.dm
+++ b/code/__DEFINES/traits.dm
@@ -618,6 +618,15 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
/// This movable atom has the explosive block element
#define TRAIT_BLOCKING_EXPLOSIVES "blocking_explosives"
+///Lava will be safe to cross while it has this trait.
+#define TRAIT_LAVA_STOPPED "lava_stopped"
+///Chasms will be safe to cross while they've this trait.
+#define TRAIT_CHASM_STOPPED "chasm_stopped"
+///Turf slowdown will be ignored when this trait is added to a turf.
+#define TRAIT_TURF_IGNORE_SLOWDOWN "turf_ignore_slowdown"
+///Mobs won't slip on a wet turf while it has this trait
+#define TRAIT_TURF_IGNORE_SLIPPERY "turf_ignore_slippery"
+
/// Mobs with this trait can't send the mining shuttle console when used outside the station itself
#define TRAIT_FORBID_MINING_SHUTTLE_CONSOLE_OUTSIDE_STATION "forbid_mining_shuttle_console_outside_station"
diff --git a/code/controllers/subsystem/atoms.dm b/code/controllers/subsystem/atoms.dm
index 14e58869389..5e2bfb58ef6 100644
--- a/code/controllers/subsystem/atoms.dm
+++ b/code/controllers/subsystem/atoms.dm
@@ -154,7 +154,11 @@ SUBSYSTEM_DEF(atoms)
else if(!(A.flags_1 & INITIALIZED_1))
BadInitializeCalls[the_type] |= BAD_INIT_DIDNT_INIT
else
- SEND_SIGNAL(A,COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZE)
+ SEND_SIGNAL(A, COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZE)
+ var/atom/movable/location = A.loc
+ if(location)
+ /// Sends a signal that the new atom `src`, has been created at `loc`
+ SEND_SIGNAL(location, COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZED_ON, A, arguments[1])
if(created_atoms && from_template && ispath(the_type, /atom/movable))//we only want to populate the list with movables
created_atoms += A.get_all_contents()
diff --git a/code/datums/components/chasm.dm b/code/datums/components/chasm.dm
index 7f1a3f6a599..0064999d798 100644
--- a/code/datums/components/chasm.dm
+++ b/code/datums/components/chasm.dm
@@ -34,14 +34,20 @@ GLOBAL_LIST_INIT(chasm_storage, list())
/obj/effect/fishing_lure,
))
-/datum/component/chasm/Initialize(turf/target)
- RegisterSignal(parent, COMSIG_ATOM_ENTERED, PROC_REF(Entered))
+/datum/component/chasm/Initialize(turf/target, mapload)
+ RegisterSignal(parent, SIGNAL_ADDTRAIT(TRAIT_CHASM_STOPPED), PROC_REF(on_chasm_stopped))
+ RegisterSignal(parent, SIGNAL_REMOVETRAIT(TRAIT_CHASM_STOPPED), PROC_REF(on_chasm_no_longer_stopped))
target_turf = target
- START_PROCESSING(SSobj, src) // process on create, in case stuff is still there
+ RegisterSignal(parent, COMSIG_ATOM_ABSTRACT_ENTERED, PROC_REF(entered))
+ RegisterSignal(parent, COMSIG_ATOM_ABSTRACT_EXITED, PROC_REF(exited))
+ RegisterSignal(parent, COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZED_ON, PROC_REF(initialized_on))
+ //allow catwalks to give the turf the CHASM_STOPPED trait before dropping stuff when the turf is changed.
+ //otherwise don't do anything because turfs and areas are initialized before movables.
+ if(!mapload)
+ addtimer(CALLBACK(src, PROC_REF(drop_stuff)), 0)
src.parent.AddElement(/datum/element/lazy_fishing_spot, FISHING_SPOT_PRESET_CHASM)
/datum/component/chasm/UnregisterFromParent()
- STOP_PROCESSING(SSobj, src)
remove_storage()
/**
@@ -58,47 +64,58 @@ GLOBAL_LIST_INIT(chasm_storage, list())
chasm_storage += ref
GLOB.chasm_storage = chasm_storage
-/datum/component/chasm/proc/Entered(datum/source, atom/movable/arrived, atom/old_loc, list/atom/old_locs)
+/datum/component/chasm/proc/entered(datum/source, atom/movable/arrived, atom/old_loc, list/atom/old_locs)
SIGNAL_HANDLER
+ drop_stuff()
- START_PROCESSING(SSobj, src)
- drop_stuff(arrived)
+/datum/component/chasm/proc/exited(datum/source, atom/movable/exited)
+ SIGNAL_HANDLER
+ UnregisterSignal(exited, list(COMSIG_MOVETYPE_FLAG_DISABLED, COMSIG_LIVING_SET_BUCKLED, COMSIG_MOVABLE_THROW_LANDED))
-/datum/component/chasm/process()
- if (!drop_stuff())
- STOP_PROCESSING(SSobj, src)
+/datum/component/chasm/proc/initialized_on(datum/source, atom/movable/movable, mapload)
+ SIGNAL_HANDLER
+ drop_stuff(movable)
-/datum/component/chasm/proc/is_safe()
- //if anything matching this typecache is found in the chasm, we don't drop things
- var/static/list/chasm_safeties_typecache = typecacheof(list(/obj/structure/lattice, /obj/structure/lattice/catwalk, /obj/structure/stone_tile))
+/datum/component/chasm/proc/on_chasm_stopped(datum/source)
+ SIGNAL_HANDLER
+ UnregisterSignal(source, list(COMSIG_ATOM_ENTERED, COMSIG_ATOM_EXITED, COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZED_ON))
+ for(var/atom/movable/movable as anything in source)
+ UnregisterSignal(movable, list(COMSIG_MOVETYPE_FLAG_DISABLED, COMSIG_LIVING_SET_BUCKLED, COMSIG_MOVABLE_THROW_LANDED))
- var/atom/parent = src.parent
- var/list/found_safeties = typecache_filter_list(parent.contents, chasm_safeties_typecache)
- for(var/obj/structure/stone_tile/S in found_safeties)
- if(S.fallen)
- LAZYREMOVE(found_safeties, S)
- return LAZYLEN(found_safeties)
+/datum/component/chasm/proc/on_chasm_no_longer_stopped(datum/source)
+ SIGNAL_HANDLER
+ RegisterSignal(parent, COMSIG_ATOM_ENTERED, PROC_REF(entered))
+ RegisterSignal(parent, COMSIG_ATOM_EXITED, PROC_REF(exited))
+ RegisterSignal(parent, COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZED_ON, PROC_REF(initialized_on))
+ drop_stuff()
-/datum/component/chasm/proc/drop_stuff(dropped_thing)
- if (is_safe())
- return FALSE
+#define CHASM_NOT_DROPPING 0
+#define CHASM_DROPPING 1
+///Doesn't drop the movable, but registers a few signals to try again if the conditions change.
+#define CHASM_REGISTER_SIGNALS 2
- var/atom/parent = src.parent
- var/to_check = dropped_thing ? list(dropped_thing) : parent.contents
- for (var/thing in to_check)
- if (droppable(thing))
- . = TRUE
- INVOKE_ASYNC(src, PROC_REF(drop), thing)
+/datum/component/chasm/proc/drop_stuff(atom/movable/dropped_thing)
+ if(HAS_TRAIT(parent, TRAIT_CHASM_STOPPED))
+ return
+ var/atom/atom_parent = parent
+ var/to_check = dropped_thing ? list(dropped_thing) : atom_parent.contents
+ for (var/atom/movable/thing as anything in to_check)
+ var/dropping = droppable(thing)
+ switch(dropping)
+ if(CHASM_DROPPING)
+ INVOKE_ASYNC(src, PROC_REF(drop), thing)
+ if(CHASM_REGISTER_SIGNALS)
+ RegisterSignals(thing, list(COMSIG_MOVETYPE_FLAG_DISABLED, COMSIG_LIVING_SET_BUCKLED, COMSIG_MOVABLE_THROW_LANDED), PROC_REF(drop_stuff), TRUE)
/datum/component/chasm/proc/droppable(atom/movable/dropped_thing)
var/datum/weakref/falling_ref = WEAKREF(dropped_thing)
// avoid an infinite loop, but allow falling a large distance
if(falling_atoms[falling_ref] && falling_atoms[falling_ref] > 30)
- return FALSE
- if(!isliving(dropped_thing) && !isobj(dropped_thing))
- return FALSE
- if(is_type_in_typecache(dropped_thing, forbidden_types) || dropped_thing.throwing || (dropped_thing.movement_type & (FLOATING|FLYING)))
- return FALSE
+ return CHASM_NOT_DROPPING
+ if(is_type_in_typecache(dropped_thing, forbidden_types) || (!isliving(dropped_thing) && !isobj(dropped_thing)))
+ return CHASM_NOT_DROPPING
+ if(dropped_thing.throwing || (dropped_thing.movement_type & (FLOATING|FLYING)))
+ return CHASM_REGISTER_SIGNALS
//Flies right over the chasm
if(ismob(dropped_thing))
@@ -106,7 +123,7 @@ GLOBAL_LIST_INIT(chasm_storage, list())
if(M.buckled) //middle statement to prevent infinite loops just in case!
var/mob/buckled_to = M.buckled
if((!ismob(M.buckled) || (buckled_to.buckled != M)) && !droppable(M.buckled))
- return FALSE
+ return CHASM_REGISTER_SIGNALS
if(ishuman(dropped_thing))
var/mob/living/carbon/human/victim = dropped_thing
if(istype(victim.belt, /obj/item/wormhole_jaunter))
@@ -115,8 +132,12 @@ GLOBAL_LIST_INIT(chasm_storage, list())
var/fall_into_chasm = jaunter.chasm_react(victim)
if(!fall_into_chasm)
chasm.visible_message(span_boldwarning("[victim] falls into the [chasm]!")) //To freak out any bystanders
- return fall_into_chasm
- return TRUE
+ return fall_into_chasm ? CHASM_DROPPING : CHASM_NOT_DROPPING
+ return CHASM_DROPPING
+
+#undef CHASM_NOT_DROPPING
+#undef CHASM_DROPPING
+#undef CHASM_REGISTER_SIGNALS
/datum/component/chasm/proc/drop(atom/movable/dropped_thing)
var/datum/weakref/falling_ref = WEAKREF(dropped_thing)
diff --git a/code/datums/components/slippery.dm b/code/datums/components/slippery.dm
index 9956a54df04..5f1dd18bdfd 100644
--- a/code/datums/components/slippery.dm
+++ b/code/datums/components/slippery.dm
@@ -98,6 +98,10 @@
SIGNAL_HANDLER
if(!isliving(arrived))
return
+ if(lube_flags & SLIPPERY_TURF)
+ var/turf/turf = get_turf(source)
+ if(HAS_TRAIT(turf, TRAIT_TURF_IGNORE_SLIPPERY))
+ return
var/mob/living/victim = arrived
if((victim.movement_type & (FLYING | FLOATING)))
return
diff --git a/code/datums/components/wet_floor.dm b/code/datums/components/wet_floor.dm
index 9c795fb8a18..0b3b92fd2e3 100644
--- a/code/datums/components/wet_floor.dm
+++ b/code/datums/components/wet_floor.dm
@@ -75,23 +75,23 @@
/datum/component/wet_floor/proc/update_flags()
var/intensity
- lube_flags = NONE
+ lube_flags = SLIPPERY_TURF
switch(highest_strength)
if(TURF_WET_WATER)
intensity = 60
- lube_flags = NO_SLIP_WHEN_WALKING
+ lube_flags |= NO_SLIP_WHEN_WALKING
if(TURF_WET_LUBE)
intensity = 80
- lube_flags = SLIDE | GALOSHES_DONT_HELP
+ lube_flags |= SLIDE | GALOSHES_DONT_HELP
if(TURF_WET_ICE)
intensity = 120
- lube_flags = SLIDE | GALOSHES_DONT_HELP
+ lube_flags |= SLIDE | GALOSHES_DONT_HELP
if(TURF_WET_PERMAFROST)
intensity = 120
- lube_flags = SLIDE_ICE | GALOSHES_DONT_HELP
+ lube_flags |= SLIDE_ICE | GALOSHES_DONT_HELP
if(TURF_WET_SUPERLUBE)
intensity = 120
- lube_flags = SLIDE | GALOSHES_DONT_HELP | SLIP_WHEN_CRAWLING
+ lube_flags |= SLIDE | GALOSHES_DONT_HELP | SLIP_WHEN_CRAWLING
else
qdel(parent.GetComponent(/datum/component/slippery))
return
diff --git a/code/datums/elements/give_turf_traits.dm b/code/datums/elements/give_turf_traits.dm
new file mode 100644
index 00000000000..e374b16d63c
--- /dev/null
+++ b/code/datums/elements/give_turf_traits.dm
@@ -0,0 +1,81 @@
+///A bespoke element that adds a set of traits to the turf while occupied by at least one attached movabled.
+/datum/element/give_turf_traits
+ element_flags = ELEMENT_DETACH_ON_HOST_DESTROY|ELEMENT_BESPOKE
+ argument_hash_start_idx = 2
+ ///A list of traits that are added to the turf while occupied.
+ var/list/traits
+ ///The list of occupied turfs: Assoc value is a list of movables with this element that are occupying the turf.
+ var/list/occupied_turfs = list()
+
+/datum/element/give_turf_traits/Attach(atom/movable/target, list/traits)
+ . = ..()
+ if(!istype(target))
+ return ELEMENT_INCOMPATIBLE
+
+ src.traits = traits
+
+ RegisterSignal(target, COMSIG_MOVABLE_MOVED, PROC_REF(on_moved))
+ if(isturf(target.loc))
+ add_to_occupied_turfs(target.loc, target)
+
+/datum/element/give_turf_traits/Detach(atom/movable/source)
+ UnregisterSignal(source, COMSIG_MOVABLE_MOVED)
+ if(isturf(source.loc))
+ remove_from_occupied_turfs(source.loc, source)
+ return ..()
+
+///Removes the trait from the old turf and adds it to the new one.
+/datum/element/give_turf_traits/proc/on_moved(atom/movable/source, atom/old_loc)
+ SIGNAL_HANDLER
+ if(isturf(old_loc))
+ remove_from_occupied_turfs(old_loc, source)
+
+ if(isturf(source.loc))
+ add_to_occupied_turfs(source.loc, source)
+
+/**
+ * Registers the turf signals if it was previously unoccupied and adds it to the list of occupied turfs.
+ * Otherwise, it just adds the movable to the assoc value of lists occupying the turf.
+ */
+/datum/element/give_turf_traits/proc/add_to_occupied_turfs(turf/location, atom/movable/source)
+ if(occupied_turfs[location])
+ occupied_turfs[location] += source
+ return
+
+ occupied_turfs[location] = list(source)
+ RegisterSignal(location, COMSIG_TURF_CHANGE, PROC_REF(pre_change_turf))
+
+ var/update_movespeeds = (TRAIT_TURF_IGNORE_SLOWDOWN in traits) && !HAS_TRAIT(location, TRAIT_TURF_IGNORE_SLOWDOWN)
+ for(var/trait in traits)
+ ADD_TRAIT(location, trait, REF(src))
+ if(update_movespeeds)
+ for(var/mob/living/living in location)
+ living.update_turf_movespeed()
+
+/**
+ * Unregisters the turf signals if it's no longer unoccupied and removes it from the list of occupied turfs.
+ * Otherwise, it just removes the movable from the assoc value of lists occupying the turf.
+ */
+/datum/element/give_turf_traits/proc/remove_from_occupied_turfs(turf/location, atom/movable/source)
+ LAZYREMOVE(occupied_turfs[location], source)
+ if(occupied_turfs[location])
+ return
+
+ occupied_turfs -= location
+ UnregisterSignal(location, COMSIG_TURF_CHANGE)
+
+ for(var/trait in traits)
+ REMOVE_TRAIT(location, trait, REF(src))
+
+ if((TRAIT_TURF_IGNORE_SLOWDOWN in traits) && !HAS_TRAIT(location, TRAIT_TURF_IGNORE_SLOWDOWN))
+ for(var/mob/living/living in location)
+ living.update_turf_movespeed()
+
+///Signals and components are carried over when the turf is changed, so they've to be readded post-change.
+/datum/element/give_turf_traits/proc/pre_change_turf(turf/changed, path, list/new_baseturfs, flags, list/post_change_callbacks)
+ SIGNAL_HANDLER
+ post_change_callbacks += CALLBACK(src, PROC_REF(reoccupy_turf))
+
+/datum/element/give_turf_traits/proc/reoccupy_turf(turf/changed)
+ for(var/trait in traits)
+ ADD_TRAIT(changed, trait, REF(src))
diff --git a/code/datums/proximity_monitor/proximity_monitor.dm b/code/datums/proximity_monitor/proximity_monitor.dm
index c7c8165a431..fc28212202d 100644
--- a/code/datums/proximity_monitor/proximity_monitor.dm
+++ b/code/datums/proximity_monitor/proximity_monitor.dm
@@ -11,7 +11,7 @@
var/static/list/loc_connections = list(
COMSIG_ATOM_ENTERED = PROC_REF(on_entered),
COMSIG_ATOM_EXITED = PROC_REF(on_uncrossed),
- COMSIG_ATOM_INITIALIZED_ON = PROC_REF(on_entered),
+ COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZED_ON = PROC_REF(on_entered),
)
/datum/proximity_monitor/New(atom/_host, range, _ignore_if_not_on_turf = TRUE)
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index bcd9e0b6f9e..a1e3ed547ef 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -244,9 +244,6 @@
stack_trace("Warning: [src]([type]) initialized multiple times!")
flags_1 |= INITIALIZED_1
- if(loc)
- SEND_SIGNAL(loc, COMSIG_ATOM_INITIALIZED_ON, src, mapload) /// Sends a signal that the new atom `src`, has been created at `loc`
-
SET_PLANE_IMPLICIT(src, plane)
if(greyscale_config && greyscale_colors) //we'll check again at item/init for inhand/belt/worn configs.
diff --git a/code/game/objects/structures/lattice.dm b/code/game/objects/structures/lattice.dm
index f0477d24501..ff85112bea6 100644
--- a/code/game/objects/structures/lattice.dm
+++ b/code/game/objects/structures/lattice.dm
@@ -16,6 +16,13 @@
canSmoothWith = SMOOTH_GROUP_LATTICE + SMOOTH_GROUP_WALLS + SMOOTH_GROUP_OPEN_FLOOR
var/number_of_mats = 1
var/build_material = /obj/item/stack/rods
+ var/list/give_turf_traits = list(TRAIT_CHASM_STOPPED)
+
+/obj/structure/lattice/Initialize(mapload)
+ . = ..()
+ if(length(give_turf_traits))
+ give_turf_traits = string_list(give_turf_traits)
+ AddElement(/datum/element/give_turf_traits, give_turf_traits)
/datum/armor/structure_lattice
melee = 50
@@ -92,6 +99,7 @@
smoothing_groups = SMOOTH_GROUP_CATWALK + SMOOTH_GROUP_LATTICE + SMOOTH_GROUP_OPEN_FLOOR
canSmoothWith = SMOOTH_GROUP_CATWALK
obj_flags = CAN_BE_HIT | BLOCK_Z_OUT_DOWN | BLOCK_Z_IN_UP
+ give_turf_traits = list(TRAIT_TURF_IGNORE_SLOWDOWN, TRAIT_LAVA_STOPPED, TRAIT_CHASM_STOPPED)
/obj/structure/lattice/catwalk/Initialize(mapload)
. = ..()
@@ -146,6 +154,7 @@
canSmoothWith = SMOOTH_GROUP_LATTICE
obj_flags = CAN_BE_HIT | BLOCK_Z_OUT_DOWN | BLOCK_Z_IN_UP
resistance_flags = FIRE_PROOF | LAVA_PROOF
+ give_turf_traits = list(TRAIT_LAVA_STOPPED, TRAIT_CHASM_STOPPED)
/obj/structure/lattice/lava/deconstruction_hints(mob/user)
return span_notice("The rods look like they could be cut, but the heat treatment will shatter off. There's space for a tile.")
diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm
index fb7fc9e612d..b364c0c2e67 100644
--- a/code/game/objects/structures/tables_racks.dm
+++ b/code/game/objects/structures/tables_racks.dm
@@ -23,6 +23,12 @@
pass_flags_self = PASSTABLE | LETPASSTHROW
layer = TABLE_LAYER
obj_flags = CAN_BE_HIT | IGNORE_DENSITY
+ custom_materials = list(/datum/material/iron =SHEET_MATERIAL_AMOUNT)
+ max_integrity = 100
+ integrity_failure = 0.33
+ smoothing_flags = SMOOTH_BITMASK
+ smoothing_groups = SMOOTH_GROUP_TABLES
+ canSmoothWith = SMOOTH_GROUP_TABLES
///TRUE if the table can be climbed on and have living mobs placed on it normally, FALSE otherwise
var/climbable = TRUE
var/frame = /obj/structure/table_frame
@@ -32,13 +38,7 @@
var/busy = FALSE
var/buildstackamount = 1
var/framestackamount = 2
- var/deconstruction_ready = 1
- custom_materials = list(/datum/material/iron =SHEET_MATERIAL_AMOUNT)
- max_integrity = 100
- integrity_failure = 0.33
- smoothing_flags = SMOOTH_BITMASK
- smoothing_groups = SMOOTH_GROUP_TABLES
- canSmoothWith = SMOOTH_GROUP_TABLES
+ var/deconstruction_ready = TRUE
/obj/structure/table/Initialize(mapload, _buildstack)
. = ..()
@@ -54,6 +54,8 @@
)
AddElement(/datum/element/connect_loc, loc_connections)
+ var/static/list/give_turf_traits = list(TRAIT_TURF_IGNORE_SLOWDOWN, TRAIT_TURF_IGNORE_SLIPPERY)
+ AddElement(/datum/element/give_turf_traits, give_turf_traits)
register_context()
/obj/structure/table/add_context(atom/source, list/context, obj/item/held_item, mob/living/user)
@@ -593,7 +595,7 @@
icon = 'icons/obj/smooth_structures/reinforced_table.dmi'
icon_state = "reinforced_table-0"
base_icon_state = "reinforced_table"
- deconstruction_ready = 0
+ deconstruction_ready = FALSE
buildstack = /obj/item/stack/sheet/plasteel
max_integrity = 200
integrity_failure = 0.25
diff --git a/code/game/turfs/open/chasm.dm b/code/game/turfs/open/chasm.dm
index e8b94e3eeec..4c8ac12202d 100644
--- a/code/game/turfs/open/chasm.dm
+++ b/code/game/turfs/open/chasm.dm
@@ -14,7 +14,7 @@
/turf/open/chasm/Initialize(mapload)
. = ..()
- apply_components()
+ apply_components(mapload)
/// Lets people walk into chasms.
/turf/open/chasm/CanAllowThrough(atom/movable/mover, border_dir)
@@ -76,8 +76,8 @@
build_with_floor_tiles(C, user)
/// Handles adding the chasm component to the turf (So stuff falls into it!)
-/turf/open/chasm/proc/apply_components()
- AddComponent(/datum/component/chasm, GET_TURF_BELOW(src))
+/turf/open/chasm/proc/apply_components(mapload)
+ AddComponent(/datum/component/chasm, GET_TURF_BELOW(src), mapload)
// Chasms for Lavaland, with planetary atmos and lava glow
/turf/open/chasm/lavaland
@@ -118,5 +118,5 @@
/turf/open/chasm/true
desc = "There's nothing at the bottom. Absolutely nothing."
-/turf/open/chasm/true/apply_components()
- AddComponent(/datum/component/chasm) //Don't pass anything for below_turf.
+/turf/open/chasm/true/apply_components(mapload)
+ AddComponent(/datum/component/chasm, null, mapload) //Don't pass anything for below_turf.
diff --git a/code/game/turfs/open/lava.dm b/code/game/turfs/open/lava.dm
index 78cb09fe7c5..6f734763e5c 100644
--- a/code/game/turfs/open/lava.dm
+++ b/code/game/turfs/open/lava.dm
@@ -134,12 +134,13 @@
/turf/open/lava/Exited(atom/movable/gone, direction)
. = ..()
- if(isliving(gone))
- var/mob/living/leaving_mob = gone
- if(!islava(leaving_mob.loc))
- REMOVE_TRAIT(leaving_mob, TRAIT_PERMANENTLY_ONFIRE, TURF_TRAIT)
- if(!leaving_mob.on_fire)
- leaving_mob.update_fire()
+ if(isliving(gone) && !islava(gone.loc))
+ REMOVE_TRAIT(gone, TRAIT_PERMANENTLY_ONFIRE, TURF_TRAIT)
+
+/turf/open/lava/Destroy()
+ for(var/mob/living/leaving_mob in contents)
+ REMOVE_TRAIT(leaving_mob, TRAIT_PERMANENTLY_ONFIRE, TURF_TRAIT)
+ return ..()
/turf/open/lava/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum)
if(burn_stuff(AM))
@@ -216,13 +217,9 @@
return TRUE
/turf/open/lava/proc/is_safe()
- //if anything matching this typecache is found in the lava, we don't burn things
- var/static/list/lava_safeties_typecache = typecacheof(list(/obj/structure/lattice/catwalk, /obj/structure/stone_tile, /obj/structure/lattice/lava))
- var/list/found_safeties = typecache_filter_list(contents, lava_safeties_typecache)
- for(var/obj/structure/stone_tile/S in found_safeties)
- if(S.fallen)
- LAZYREMOVE(found_safeties, S)
- return LAZYLEN(found_safeties)
+ if(HAS_TRAIT(src, TRAIT_LAVA_STOPPED))
+ return TRUE
+ return FALSE
///Generic return value of the can_burn_stuff() proc. Does nothing.
#define LAVA_BE_IGNORING 0
diff --git a/code/game/turfs/open/openspace.dm b/code/game/turfs/open/openspace.dm
index 23d561e4af6..98628a0c68f 100644
--- a/code/game/turfs/open/openspace.dm
+++ b/code/game/turfs/open/openspace.dm
@@ -23,7 +23,7 @@
// I am so sorry
/turf/open/openspace/Initialize(mapload) // handle plane and layer here so that they don't cover other obs/turfs in Dream Maker
. = ..()
- RegisterSignal(src, COMSIG_ATOM_INITIALIZED_ON, PROC_REF(on_atom_created))
+ RegisterSignal(src, COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZED_ON, PROC_REF(on_atom_created))
var/area/our_area = loc
if(istype(our_area, /area/space))
force_no_gravity = TRUE
@@ -34,7 +34,7 @@
AddElement(/datum/element/turf_z_transparency)
/turf/open/openspace/ChangeTurf(path, list/new_baseturfs, flags)
- UnregisterSignal(src, COMSIG_ATOM_INITIALIZED_ON)
+ UnregisterSignal(src, COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZED_ON)
return ..()
/**
@@ -54,15 +54,13 @@
if(movable.set_currently_z_moving(CURRENTLY_Z_FALLING))
zFall(movable, falling_from_move = TRUE)
/**
- * Drops movables spawned on this turf only after they are successfully initialized.
- * so flying mobs, qdeleted movables and things that were moved somewhere else during
- * Initialize() won't fall by accident.
+ * Drops movables spawned on this turf after they are successfully initialized.
+ * so that spawned movables that should fall to gravity, will fall.
*/
/turf/open/openspace/proc/on_atom_created(datum/source, atom/created_atom)
SIGNAL_HANDLER
if(ismovable(created_atom))
- //Drop it only when it's finished initializing, not before.
- addtimer(CALLBACK(src, PROC_REF(zfall_if_on_turf), created_atom), 0 SECONDS)
+ zfall_if_on_turf(created_atom)
/turf/open/openspace/proc/zfall_if_on_turf(atom/movable/movable)
if(QDELETED(movable) || movable.loc != src)
diff --git a/code/game/turfs/open/space/transit.dm b/code/game/turfs/open/space/transit.dm
index f754438c2f6..6253db9ec2c 100644
--- a/code/game/turfs/open/space/transit.dm
+++ b/code/game/turfs/open/space/transit.dm
@@ -12,11 +12,11 @@
update_appearance()
RegisterSignal(src, COMSIG_TURF_RESERVATION_RELEASED, PROC_REF(launch_contents))
RegisterSignal(src, COMSIG_ATOM_ENTERED, PROC_REF(initialize_drifting))
- RegisterSignal(src, COMSIG_ATOM_INITIALIZED_ON, PROC_REF(initialize_drifting_but_from_initialize))
+ RegisterSignal(src, COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZED_ON, PROC_REF(initialize_drifting_but_from_initialize))
/turf/open/space/transit/Destroy()
//Signals are NOT removed from turfs upon replacement, and we get replaced ALOT, so unregister our signal
- UnregisterSignal(src, list(COMSIG_TURF_RESERVATION_RELEASED, COMSIG_ATOM_ENTERED, COMSIG_ATOM_INITIALIZED_ON))
+ UnregisterSignal(src, list(COMSIG_TURF_RESERVATION_RELEASED, COMSIG_ATOM_ENTERED, COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZED_ON))
return ..()
diff --git a/code/modules/industrial_lift/industrial_lift.dm b/code/modules/industrial_lift/industrial_lift.dm
index 95880740068..e554c15cb99 100644
--- a/code/modules/industrial_lift/industrial_lift.dm
+++ b/code/modules/industrial_lift/industrial_lift.dm
@@ -102,11 +102,11 @@ GLOBAL_LIST_EMPTY(lifts)
/obj/structure/industrial_lift/proc/set_movement_registrations(list/turfs_to_set)
for(var/turf/turf_loc as anything in turfs_to_set || locs)
RegisterSignal(turf_loc, COMSIG_ATOM_EXITED, PROC_REF(UncrossedRemoveItemFromLift))
- RegisterSignals(turf_loc, list(COMSIG_ATOM_ENTERED,COMSIG_ATOM_INITIALIZED_ON), PROC_REF(AddItemOnLift))
+ RegisterSignals(turf_loc, list(COMSIG_ATOM_ENTERED, COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZED_ON), PROC_REF(AddItemOnLift))
///unset our movement registrations from turfs that no longer contain us (or every loc if turfs_to_unset is unspecified)
/obj/structure/industrial_lift/proc/unset_movement_registrations(list/turfs_to_unset)
- var/static/list/registrations = list(COMSIG_ATOM_ENTERED, COMSIG_ATOM_EXITED, COMSIG_ATOM_INITIALIZED_ON)
+ var/static/list/registrations = list(COMSIG_ATOM_ENTERED, COMSIG_ATOM_EXITED, COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZED_ON)
for(var/turf/turf_loc as anything in turfs_to_unset || locs)
UnregisterSignal(turf_loc, registrations)
diff --git a/code/modules/mapfluff/ruins/objects_and_mobs/necropolis_gate.dm b/code/modules/mapfluff/ruins/objects_and_mobs/necropolis_gate.dm
index 8d7ed7e6f2f..54e167fb255 100644
--- a/code/modules/mapfluff/ruins/objects_and_mobs/necropolis_gate.dm
+++ b/code/modules/mapfluff/ruins/objects_and_mobs/necropolis_gate.dm
@@ -240,10 +240,6 @@ GLOBAL_DATUM(necropolis_gate, /obj/structure/necropolis_gate/legion_gate)
/obj/structure/necropolis_arch/singularity_pull()
return 0
-#define STABLE 0 //The tile is stable and won't collapse/sink when crossed.
-#define COLLAPSE_ON_CROSS 1 //The tile is unstable and will temporary become unusable when crossed.
-#define DESTROY_ON_CROSS 2 //The tile is nearly broken and will permanently become unusable when crossed.
-#define UNIQUE_EFFECT 3 //The tile has some sort of unique effect when crossed.
//stone tiles for boss arenas
/obj/structure/stone_tile
name = "stone tile"
@@ -255,69 +251,19 @@ GLOBAL_DATUM(necropolis_gate, /obj/structure/necropolis_gate/legion_gate)
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
var/tile_key = "pristine_tile"
var/tile_random_sprite_max = 24
- var/fall_on_cross = STABLE //If the tile has some sort of effect when crossed
- var/fallen = FALSE //If the tile is unusable
- var/falling = FALSE //If the tile is falling
/obj/structure/stone_tile/Initialize(mapload)
. = ..()
icon_state = "[tile_key][rand(1, tile_random_sprite_max)]"
- var/static/list/loc_connections = list(
- COMSIG_ATOM_ENTERED = PROC_REF(on_entered),
- )
- AddElement(/datum/element/connect_loc, loc_connections)
+
+ var/static/list/give_turf_traits
+ if(!give_turf_traits)
+ give_turf_traits = string_list(list(TRAIT_LAVA_STOPPED, TRAIT_CHASM_STOPPED))
+ AddElement(/datum/element/give_turf_traits, give_turf_traits)
/obj/structure/stone_tile/singularity_pull()
return
-/obj/structure/stone_tile/proc/on_entered(datum/source, atom/movable/AM)
- SIGNAL_HANDLER
- if(falling || fallen)
- return
- var/turf/T = get_turf(src)
- if(!islava(T) && !ischasm(T)) //nothing to sink or fall into
- return
- var/obj/item/I
- if(isitem(AM))
- I = AM
- var/mob/living/L
- if(isliving(AM))
- L = AM
- switch(fall_on_cross)
- if(COLLAPSE_ON_CROSS, DESTROY_ON_CROSS)
- if((I && I.w_class >= WEIGHT_CLASS_BULKY) || (L && !(L.movement_type & FLYING) && L.mob_size >= MOB_SIZE_HUMAN)) //too heavy! too big! aaah!
- INVOKE_ASYNC(src, PROC_REF(collapse))
- if(UNIQUE_EFFECT)
- crossed_effect(AM)
-
-/obj/structure/stone_tile/proc/collapse()
- falling = TRUE
- var/break_that_sucker = fall_on_cross == DESTROY_ON_CROSS
- playsound(src, 'sound/effects/pressureplate.ogg', 50, TRUE)
- Shake(-1, -1, 25)
- sleep(0.5 SECONDS)
- if(break_that_sucker)
- playsound(src, 'sound/effects/break_stone.ogg', 50, TRUE)
- else
- playsound(src, 'sound/mecha/mechmove04.ogg', 50, TRUE)
- animate(src, alpha = 0, pixel_y = pixel_y - 3, time = 5)
- fallen = TRUE
- if(break_that_sucker)
- QDEL_IN(src, 10)
- else
- addtimer(CALLBACK(src, PROC_REF(rebuild)), 55)
-
-/obj/structure/stone_tile/proc/rebuild()
- pixel_x = initial(pixel_x)
- pixel_y = initial(pixel_y) - 5
- animate(src, alpha = initial(alpha), pixel_x = initial(pixel_x), pixel_y = initial(pixel_y), time = 30)
- sleep(3 SECONDS)
- falling = FALSE
- fallen = FALSE
-
-/obj/structure/stone_tile/proc/crossed_effect(atom/movable/AM)
- return
-
/obj/structure/stone_tile/block
name = "stone block"
icon_state = "pristine_block1"
@@ -411,8 +357,3 @@ GLOBAL_DATUM(necropolis_gate, /obj/structure/necropolis_gate/legion_gate)
name = "burnt stone surrounding tile"
icon_state = "burnt_surrounding_tile1"
tile_key = "burnt_surrounding_tile"
-
-#undef STABLE
-#undef COLLAPSE_ON_CROSS
-#undef DESTROY_ON_CROSS
-#undef UNIQUE_EFFECT
diff --git a/code/modules/mining/machine_processing.dm b/code/modules/mining/machine_processing.dm
index 869779f6c36..b89083824fd 100644
--- a/code/modules/mining/machine_processing.dm
+++ b/code/modules/mining/machine_processing.dm
@@ -24,12 +24,12 @@
/obj/machinery/mineral/proc/register_input_turf()
input_turf = get_step(src, input_dir)
if(input_turf) // make sure there is actually a turf
- RegisterSignals(input_turf, list(COMSIG_ATOM_INITIALIZED_ON, COMSIG_ATOM_ENTERED), PROC_REF(pickup_item))
+ RegisterSignals(input_turf, list(COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZED_ON, COMSIG_ATOM_ENTERED), PROC_REF(pickup_item))
/// Unregisters signals that are registered the machine's input turf, if it has one.
/obj/machinery/mineral/proc/unregister_input_turf()
if(input_turf)
- UnregisterSignal(input_turf, list(COMSIG_ATOM_ENTERED, COMSIG_ATOM_INITIALIZED_ON))
+ UnregisterSignal(input_turf, list(COMSIG_ATOM_ENTERED, COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZED_ON))
/obj/machinery/mineral/Moved(atom/old_loc, movement_dir, forced, list/old_locs, momentum_change = TRUE)
. = ..()
diff --git a/code/modules/mob/living/carbon/init_signals.dm b/code/modules/mob/living/carbon/init_signals.dm
index 0094c54b43a..190fe9d8453 100644
--- a/code/modules/mob/living/carbon/init_signals.dm
+++ b/code/modules/mob/living/carbon/init_signals.dm
@@ -14,6 +14,11 @@
RegisterSignal(src, SIGNAL_ADDTRAIT(TRAIT_GENELESS), PROC_REF(on_geneless_trait_gain))
+ RegisterSignals(src, list(
+ SIGNAL_ADDTRAIT(TRAIT_PERMANENTLY_ONFIRE),
+ SIGNAL_REMOVETRAIT(TRAIT_PERMANENTLY_ONFIRE),
+ ), PROC_REF(update_permanently_on_fire))
+
/**
* On gain of TRAIT_AGENDER
*
@@ -85,6 +90,12 @@
reagents.end_metabolization(keep_liverless = TRUE)
+///On gain of TRAIT_PERMANENTLY_ONFIRE, update the visuals if not on fire
+/mob/living/carbon/proc/update_permanently_on_fire(datum/source)
+ SIGNAL_HANDLER
+ if(!on_fire)
+ update_fire()
+
/**
* On gain of TRAIT_VIRUSIMMUNE
*
diff --git a/code/modules/mob/living/living_movement.dm b/code/modules/mob/living/living_movement.dm
index 0187522460f..aba648bb188 100644
--- a/code/modules/mob/living/living_movement.dm
+++ b/code/modules/mob/living/living_movement.dm
@@ -78,16 +78,15 @@
/mob/living/proc/update_move_intent_slowdown()
add_movespeed_modifier((m_intent == MOVE_INTENT_WALK)? /datum/movespeed_modifier/config_walk_run/walk : /datum/movespeed_modifier/config_walk_run/run)
-/mob/living/proc/update_turf_movespeed(turf/open/T)
- if(isopenturf(T) && !is_type_on_turf(T, /obj/structure/lattice/catwalk))
- if(T.slowdown != current_turf_slowdown)
- add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/turf_slowdown, multiplicative_slowdown = T.slowdown)
- current_turf_slowdown = T.slowdown
+/mob/living/proc/update_turf_movespeed(turf/open/turf)
+ if(isopenturf(turf) && !HAS_TRAIT(turf, TRAIT_TURF_IGNORE_SLOWDOWN))
+ if(turf.slowdown != current_turf_slowdown)
+ add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/turf_slowdown, multiplicative_slowdown = turf.slowdown)
+ current_turf_slowdown = turf.slowdown
else if(current_turf_slowdown)
remove_movespeed_modifier(/datum/movespeed_modifier/turf_slowdown)
current_turf_slowdown = 0
-
/mob/living/proc/update_pull_movespeed()
SEND_SIGNAL(src, COMSIG_LIVING_UPDATING_PULL_MOVESPEED)
diff --git a/code/modules/mod/modules/modules_general.dm b/code/modules/mod/modules/modules_general.dm
index 7846db58723..459c828549d 100644
--- a/code/modules/mod/modules/modules_general.dm
+++ b/code/modules/mod/modules/modules_general.dm
@@ -738,7 +738,7 @@
)
var/static/list/loc_connections = list(
COMSIG_ATOM_ENTERED = PROC_REF(on_obj_entered),
- COMSIG_ATOM_INITIALIZED_ON = PROC_REF(on_atom_initialized_on),
+ COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZED_ON = PROC_REF(on_atom_initialized_on),
)
var/datum/component/connect_loc_behalf/connector
diff --git a/code/modules/recycling/conveyor.dm b/code/modules/recycling/conveyor.dm
index 393a917764d..496c9dfe1ff 100644
--- a/code/modules/recycling/conveyor.dm
+++ b/code/modules/recycling/conveyor.dm
@@ -40,6 +40,8 @@ GLOBAL_LIST_EMPTY(conveyors_by_id)
/obj/machinery/conveyor/Initialize(mapload)
. = ..()
AddElement(/datum/element/footstep_override, priority = STEP_SOUND_CONVEYOR_PRIORITY)
+ var/static/list/give_turf_traits = list(TRAIT_TURF_IGNORE_SLOWDOWN)
+ AddElement(/datum/element/give_turf_traits, give_turf_traits)
/obj/machinery/conveyor/examine(mob/user)
. = ..()
diff --git a/tgstation.dme b/tgstation.dme
index 63e5121df2a..5a3665c57e0 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -1217,6 +1217,7 @@
#include "code\datums\elements\footstep_override.dm"
#include "code\datums\elements\forced_gravity.dm"
#include "code\datums\elements\frozen.dm"
+#include "code\datums\elements\give_turf_traits.dm"
#include "code\datums\elements\haunted.dm"
#include "code\datums\elements\high_fiver.dm"
#include "code\datums\elements\honkspam.dm"