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"