From d4cdd6b63ea61fe4ac713dd59ffbcc56b13d56e0 Mon Sep 17 00:00:00 2001 From: Ghom <42542238+Ghommie@users.noreply.github.com> Date: Fri, 7 Jul 2023 11:04:33 +0200 Subject: [PATCH] Replaces lava and chasm's "safeties" and ignoring turf slowdown on catwalks with traits and a new element. (#76376) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## About The Pull Request This adds a new element for movables that grants turfs they're in traits, changes lava and the chasm component to check for traits instead, ditto for turf slowdown. It also implements another trait that prevents wet floor from slipping people, as well as some other changes (feel free to opine on them really): - Tables and conveyor belts now stop turf slowdown, much like catwalks, as I imagine people walking on them are not really touching the floor. (I'd include protection against lava too... until they melt, but that'd mean finding a way to have these objects burn in the first place, and lava code is still stupid despite a years old refactor I did) - Tables also stop slippery turfs from slipping (bananas, soaps etc. still apply). I wish there were a way to make some objects slippery by coating them in water vapor or splashing water/lube, but that's outside the scope of this PR. - Fixed an edge case in which a mob standing on a lava turf would be left permanently visually on fire if the lava is changed to another kind of turf. - Removed unused code from stone tiles. I'm going to include these traits in that global list for admin-added traits... tomorrow perhaps. 💤 ## Why It's Good For The Game Replacing some hard-coded mechanics with easier to use traits and an element, which I also need for the submerge element PR. ## Changelog :cl: refactor: Replaced hardcoded "safeties" for lava, chasms and ignoring turf slowdowns on catwalks with traits. balance: much like catwalks, tables and conveyors also disable turf slowdowns. balance: slippery turfs won't slip you when walking on a table. fix: Fixed an edge case in which a mob standing on a lava turf would be left visually but permanently on fire if the lava is changed to another kind of turf. /:cl: --- .../signals/signals_atom/signals_atom_main.dm | 4 +- code/__DEFINES/mobs.dm | 2 + code/__DEFINES/traits.dm | 9 ++ code/controllers/subsystem/atoms.dm | 6 +- code/datums/components/chasm.dm | 93 ++++++++++++------- code/datums/components/slippery.dm | 4 + code/datums/components/wet_floor.dm | 12 +-- code/datums/elements/give_turf_traits.dm | 81 ++++++++++++++++ .../proximity_monitor/proximity_monitor.dm | 2 +- code/game/atoms.dm | 3 - code/game/objects/structures/lattice.dm | 9 ++ code/game/objects/structures/tables_racks.dm | 18 ++-- code/game/turfs/open/chasm.dm | 10 +- code/game/turfs/open/lava.dm | 23 ++--- code/game/turfs/open/openspace.dm | 12 +-- code/game/turfs/open/space/transit.dm | 4 +- .../industrial_lift/industrial_lift.dm | 4 +- .../ruins/objects_and_mobs/necropolis_gate.dm | 69 +------------- code/modules/mining/machine_processing.dm | 4 +- .../modules/mob/living/carbon/init_signals.dm | 11 +++ code/modules/mob/living/living_movement.dm | 11 +-- code/modules/mod/modules/modules_general.dm | 2 +- code/modules/recycling/conveyor.dm | 2 + tgstation.dme | 1 + 24 files changed, 237 insertions(+), 159 deletions(-) create mode 100644 code/datums/elements/give_turf_traits.dm 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"