From 0065c967696bc12ab2348ca4c2197d48db67d5cf Mon Sep 17 00:00:00 2001 From: Will <7099514+Willburd@users.noreply.github.com> Date: Wed, 24 Sep 2025 08:35:10 -0400 Subject: [PATCH] Turf slip component [NEEDS TESTING] (#18057) * turf slip component * remove magic numbers * don't dupe timers * Water fix, lube buff * fix --------- Co-authored-by: Cameron Lennox --- code/__defines/turfs.dm | 6 ++ code/datums/components/turfslip.dm | 91 +++++++++++++++++++++++ code/game/turfs/simulated.dm | 66 +++------------- code/modules/xenobio/items/extracts_vr.dm | 2 +- vorestation.dme | 1 + 5 files changed, 109 insertions(+), 57 deletions(-) create mode 100644 code/datums/components/turfslip.dm diff --git a/code/__defines/turfs.dm b/code/__defines/turfs.dm index 40329df795f..524670f9a10 100644 --- a/code/__defines/turfs.dm +++ b/code/__defines/turfs.dm @@ -39,5 +39,11 @@ locate(min(CENTER.x+(H_RADIUS),world.maxx), min(CENTER.y+(V_RADIUS),world.maxy), CENTER.z) \ ) +// Wet turfs have different slipping intensities +#define TURFSLIP_DRY 0 +#define TURFSLIP_WET 1 +#define TURFSLIP_LUBE 2 +#define TURFSLIP_ICE 3 + ///Returns all turfs in a zlevel #define Z_TURFS(ZLEVEL) block(1, 1, ZLEVEL, world.maxx, world.maxy, ZLEVEL) diff --git a/code/datums/components/turfslip.dm b/code/datums/components/turfslip.dm new file mode 100644 index 00000000000..88e3aa675c3 --- /dev/null +++ b/code/datums/components/turfslip.dm @@ -0,0 +1,91 @@ +/datum/component/turfslip + var/mob/living/owner + var/slip_dist = TURFSLIP_WET + var/dirtslip = FALSE + +/datum/component/turfslip/Initialize() + if (!isliving(parent)) + return COMPONENT_INCOMPATIBLE + owner = parent + RegisterSignal(owner, COMSIG_MOVABLE_MOVED, PROC_REF(move_react)) + +/datum/component/turfslip/proc/start_slip(var/turf/simulated/start, var/is_dirt) + var/slip_stun = 6 + var/floor_type = "wet" + var/already_slipping = (slip_dist > 1) + + // Handle dirt slipping + dirtslip = is_dirt + if(dirtslip) + slip_stun = 10 + if(start.dirt > 50) + floor_type = "dirty" + else if(start.is_outdoors()) + floor_type = "uneven" + + // Proper sliding behavior + switch(start.wet) + if(TURFSLIP_LUBE) + floor_type = "slippery" + slip_dist = 99 //Skill issue. + slip_stun = 10 + dirtslip = FALSE + if(TURFSLIP_ICE) + floor_type = "icy" + slip_stun = 4 + slip_dist = rand(1,3) + dirtslip = FALSE + + // Only start the slip timer if we are not already sliding + if(!already_slipping) + owner.slip("the [floor_type] floor", slip_stun) + addtimer(CALLBACK(src, PROC_REF(next_slip)), 1) + +/datum/component/turfslip/proc/move_react(atom/source, atom/oldloc, direction, forced, list/old_locs, momentum_change) + SIGNAL_HANDLER + + // Can the mob slip? + if(QDELETED(owner) || isbelly(owner.loc)) + qdel(src) + return + + // Can the turf be slipped on? + var/turf/simulated/ground = get_turf(owner) + if(!ground || !ground.check_slipping(owner,dirtslip)) + qdel(src) + return + + addtimer(CALLBACK(src, PROC_REF(next_slip)), 1) + +/datum/component/turfslip/proc/next_slip() + // check tile for next slip + if(!step(owner, owner.dir) || dirtslip) // done sliding, failed to move, dirt also only slips once + qdel(src) + return + // Kill the slip if it's over + if(!--slip_dist) + qdel(src) + return + +/datum/component/turfslip/Destroy(force = FALSE) + UnregisterSignal(owner, COMSIG_MOVABLE_MOVED) + owner.inertia_dir = 0 + owner = null + slip_dist = 0 + . = ..() + + +//////////////////////////////////////////////////////////////////////////////////////// +// Helper proc +//////////////////////////////////////////////////////////////////////////////////////// +/turf/proc/check_slipping(var/mob/living/M) + return FALSE + +/turf/simulated/check_slipping(var/mob/living/M,var/dirtslip) + if(M.buckled) + return FALSE + if(!wet && !(dirtslip && (dirt > 50 || is_outdoors() == OUTDOORS_YES))) + return FALSE + if(wet == TURFSLIP_WET && M.m_intent == I_WALK) + return FALSE + return TRUE diff --git a/code/game/turfs/simulated.dm b/code/game/turfs/simulated.dm index 6cdaf331ad5..1ebff0ab9f1 100644 --- a/code/game/turfs/simulated.dm +++ b/code/game/turfs/simulated.dm @@ -1,6 +1,6 @@ /turf/simulated name = "station" - var/wet = 0 + var/wet = TURFSLIP_DRY var/image/wet_overlay = null //Mining resources (for the large drills). @@ -24,7 +24,7 @@ // This is not great. /turf/simulated/proc/wet_floor(var/wet_val = 1) - if(wet > 2) //Can't mop up ice + if(wet >= TURFSLIP_ICE) //Can't mop up ice return wet = wet_val if(wet_overlay) @@ -34,13 +34,13 @@ if(wet_cleanup_timer) deltimer(wet_cleanup_timer) wet_cleanup_timer = null - if(wet == 2) + if(wet == TURFSLIP_LUBE) wet_cleanup_timer = addtimer(CALLBACK(src, PROC_REF(wet_floor_finish)), 160 SECONDS, TIMER_STOPPABLE) else wet_cleanup_timer = addtimer(CALLBACK(src, PROC_REF(wet_floor_finish)), 40 SECONDS, TIMER_STOPPABLE) /turf/simulated/proc/wet_floor_finish() - wet = 0 + wet = TURFSLIP_DRY if(wet_cleanup_timer) deltimer(wet_cleanup_timer) wet_cleanup_timer = null @@ -51,14 +51,14 @@ /turf/simulated/proc/freeze_floor() if(!wet) // Water is required for it to freeze. return - wet = 3 // icy + wet = TURFSLIP_ICE if(wet_overlay) cut_overlay(wet_overlay) wet_overlay = null wet_overlay = image('icons/turf/overlays.dmi',src,"snowfloor") add_overlay(wet_overlay) spawn(5 MINUTES) - wet = 0 + wet = TURFSLIP_DRY if(wet_overlay) cut_overlay(wet_overlay) wet_overlay = null @@ -95,8 +95,8 @@ dirtoverlay.alpha = min((dirt - 50) * 5, 255) /turf/simulated/Entered(atom/A, atom/OL) + var/dirtslip = FALSE if (isliving(A)) - var/dirtslip = FALSE var/mob/living/M = A if(M.lying || M.flying || M.is_incorporeal() || !(M.flags & ATOM_INITIALIZED)) // Also ignore newly spawning mobs return ..() @@ -136,57 +136,11 @@ bloodDNA = null - var/turf_is_outdoors = is_outdoors() - if(src.wet || (dirtslip && (dirt > 50 || turf_is_outdoors == OUTDOORS_YES))) - if(M.buckled || (src.wet == 1 && M.m_intent == I_WALK)) - return - - var/slip_dist = 1 - var/slip_stun = 6 - var/floor_type = "wet" - if(dirtslip) - slip_stun = 10 - if(dirt > 50) - floor_type = "dirty" - else if(turf_is_outdoors) - floor_type = "uneven" - if(src.wet == 0 && M.m_intent == I_WALK) - return - switch(src.wet) - if(2) // Lube - floor_type = "slippery" - slip_dist = 4 - slip_stun = 10 - if(3) // Ice - floor_type = "icy" - slip_stun = 4 - slip_dist = rand(1,3) - - if(M.slip("the [floor_type] floor", slip_stun)) - addtimer(CALLBACK(src, PROC_REF(handle_slipping), M, slip_dist, dirtslip), 0) - else - M.inertia_dir = 0 - else - M.inertia_dir = 0 + if(check_slipping(M,dirtslip)) + var/datum/component/turfslip/TSC = M.LoadComponent(/datum/component/turfslip) + TSC.start_slip(src,dirtslip) ..() -/turf/simulated/proc/handle_slipping(var/mob/living/M, var/slip_dist, var/dirtslip) - PRIVATE_PROC(TRUE) - if(!M || !slip_dist) - return - if(isbelly(M.loc)) // Stop the slip if we're in a belly. - return - if(!step(M, M.dir) && !dirtslip) - return // done sliding, failed to move - // check tile for next slip - if(!dirtslip) - var/turf/simulated/ground = get_turf(M) - if(!istype(ground,/turf/simulated)) - return // stop sliding as it is impossible to be on wet terrain? - if(ground.wet != 2) - return // done sliding, not lubed - addtimer(CALLBACK(src, PROC_REF(handle_slipping), M, --slip_dist, dirtslip), 1) - //returns 1 if made bloody, returns 0 otherwise /turf/simulated/add_blood(mob/living/carbon/human/M as mob) if (!..()) diff --git a/code/modules/xenobio/items/extracts_vr.dm b/code/modules/xenobio/items/extracts_vr.dm index 75af8e6b935..4d84bcea95a 100644 --- a/code/modules/xenobio/items/extracts_vr.dm +++ b/code/modules/xenobio/items/extracts_vr.dm @@ -1524,7 +1524,7 @@ for(var/turf/simulated/T in trange(5, get_turf(holder.my_atom))) if(!istype(T)) continue - T.wet = 1 + T.wet = TURFSLIP_WET T.freeze_floor() ..() diff --git a/vorestation.dme b/vorestation.dme index 436e78845ad..8d71addd7e1 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -574,6 +574,7 @@ #include "code\datums\components\recursive_move.dm" #include "code\datums\components\resize_guard.dm" #include "code\datums\components\swarm.dm" +#include "code\datums\components\turfslip.dm" #include "code\datums\components\tethered_item.dm" #include "code\datums\components\animations\dizzy.dm" #include "code\datums\components\animations\jittery.dm"