mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-29 08:08:49 +01:00
Fourth! Time's the Charm: Actually fixes jetpack race conditions this time around (#88492)
## About The Pull Request A) Queue time can be null and it'll be valid for hotstarting loops B) Pushoffs working even when you're moving feels much better C) Jetpacks were having race issues with drift handlers because those were also using comsigs which is a remnant of old code back when they were components. Handlers should fire last, post-comsigs. D) We should not be hard-blocking jetpack movement when doing final slowdown step. Like really. ## Why It's Good For The Game Jetpacks ACTUALLY don't suck this time around. ## Changelog 🆑 qol: Jetpacks should ACTUALLY feel better now /🆑
This commit is contained in:
@@ -39,7 +39,7 @@ MOVEMENT_SUBSYSTEM_DEF(newtonian_movement)
|
||||
|
||||
/datum/controller/subsystem/movement/newtonian_movement/proc/fire_moveloop(datum/move_loop/loop)
|
||||
// Loop isn't even running right now
|
||||
if(!(loop.status & MOVELOOP_STATUS_QUEUED) || isnull(loop.queued_time))
|
||||
if(!(loop.status & MOVELOOP_STATUS_QUEUED))
|
||||
return
|
||||
// Drop the loop, process it, and if its still valid - queue it again
|
||||
dequeue_loop(loop)
|
||||
|
||||
@@ -110,6 +110,7 @@
|
||||
RegisterSignal(user, COMSIG_MOVABLE_PRE_MOVE, PROC_REF(pre_move_react))
|
||||
RegisterSignal(user, COMSIG_MOB_CLIENT_MOVE_NOGRAV, PROC_REF(on_client_move))
|
||||
RegisterSignal(user, COMSIG_MOB_ATTEMPT_HALT_SPACEMOVE, PROC_REF(on_pushoff))
|
||||
RegisterSignal(user, COMSIG_MOVABLE_DRIFT_BLOCK_INPUT, PROC_REF(on_input_block))
|
||||
last_stabilization_tick = world.time
|
||||
START_PROCESSING(SSnewtonian_movement, src)
|
||||
if (effect_type)
|
||||
@@ -164,6 +165,17 @@
|
||||
var/max_drift_force = MOVE_DELAY_TO_DRIFT(user.cached_multiplicative_slowdown)
|
||||
user.drift_handler.stabilize_drift(user.client.intended_direction ? dir2angle(user.client.intended_direction) : null, user.client.intended_direction ? max_drift_force : 0, stabilization_force * (seconds_per_tick * 1 SECONDS))
|
||||
|
||||
/datum/component/jetpack/proc/on_input_block(mob/source)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if (!should_trigger(source))
|
||||
return
|
||||
|
||||
if (!check_on_move.Invoke(TRUE))
|
||||
return
|
||||
|
||||
return DRIFT_ALLOW_INPUT
|
||||
|
||||
/datum/component/jetpack/proc/on_client_move(mob/source, list/move_args)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
@@ -179,11 +191,10 @@
|
||||
var/max_drift_force = MOVE_DELAY_TO_DRIFT(source.cached_multiplicative_slowdown)
|
||||
var/applied_force = drift_force
|
||||
var/move_dir = source.client.intended_direction
|
||||
// We're not moving anywhere, try to see if we can simulate pushing off a wall
|
||||
if (isnull(source.drift_handler))
|
||||
var/atom/movable/backup = source.get_spacemove_backup(move_dir, FALSE)
|
||||
if (backup && !(backup.dir & move_dir))
|
||||
applied_force = max_drift_force
|
||||
// Try to see if we can simulate pushing off a wall
|
||||
var/atom/movable/backup = source.get_spacemove_backup(move_dir, FALSE, include_floors = TRUE)
|
||||
if (backup && !(backup.dir & move_dir))
|
||||
applied_force = max_drift_force
|
||||
|
||||
// We don't want to force the loop to fire before stabilizing if we're going to, otherwise its effects will be delayed until the next tick which is jank
|
||||
var/force_stabilize = FALSE
|
||||
|
||||
@@ -36,7 +36,6 @@
|
||||
RegisterSignal(drifting_loop, COMSIG_MOVELOOP_PREPROCESS_CHECK, PROC_REF(before_move))
|
||||
RegisterSignal(drifting_loop, COMSIG_MOVELOOP_POSTPROCESS, PROC_REF(after_move))
|
||||
RegisterSignal(drifting_loop, COMSIG_QDELETING, PROC_REF(loop_death))
|
||||
RegisterSignal(parent, COMSIG_MOB_ATTEMPT_HALT_SPACEMOVE, PROC_REF(attempt_halt))
|
||||
if(drifting_loop.status & MOVELOOP_STATUS_RUNNING)
|
||||
drifting_start(drifting_loop) // There's a good chance it'll autostart, gotta catch that
|
||||
|
||||
@@ -208,28 +207,28 @@
|
||||
if(world.time < block_inputs_until)
|
||||
return COMSIG_MOB_CLIENT_BLOCK_PRE_MOVE
|
||||
|
||||
/datum/drift_handler/proc/attempt_halt(mob/source, movement_dir, continuous_move, atom/backup)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if ((backup.density || !backup.CanPass(source, get_dir(backup, source))) && (get_dir(source, backup) == movement_dir || source.loc == backup.loc))
|
||||
/datum/drift_handler/proc/attempt_halt(movement_dir, continuous_move, atom/backup)
|
||||
if ((backup.density || !backup.CanPass(parent, get_dir(backup, parent))) && (get_dir(parent, backup) == movement_dir || parent.loc == backup.loc))
|
||||
if (drift_force >= INERTIA_FORCE_THROW_FLOOR)
|
||||
source.throw_at(backup, 1, floor(1 + (drift_force - INERTIA_FORCE_THROW_FLOOR) / INERTIA_FORCE_PER_THROW_FORCE), spin = FALSE)
|
||||
return
|
||||
parent.throw_at(backup, 1, floor(1 + (drift_force - INERTIA_FORCE_THROW_FLOOR) / INERTIA_FORCE_PER_THROW_FORCE), spin = FALSE)
|
||||
return FALSE
|
||||
|
||||
if (drift_force < INERTIA_FORCE_SPACEMOVE_GRAB || isnull(drifting_loop))
|
||||
return
|
||||
return FALSE
|
||||
|
||||
if (!isnull(source.client) && source.client.intended_direction)
|
||||
if ((source.client.intended_direction & movement_dir) && !(get_dir(source, backup) & movement_dir))
|
||||
return
|
||||
if (ismob(parent))
|
||||
var/mob/source_user = parent
|
||||
if (!isnull(source_user.client) && source_user.client.intended_direction)
|
||||
if ((source_user.client.intended_direction & movement_dir) && !(get_dir(source_user, backup) & movement_dir))
|
||||
return FALSE
|
||||
|
||||
if (drift_force <= INERTIA_FORCE_SPACEMOVE_REDUCTION / source.inertia_force_weight)
|
||||
glide_to_halt(get_loop_delay(source))
|
||||
return COMPONENT_PREVENT_SPACEMOVE_HALT
|
||||
if (drift_force <= INERTIA_FORCE_SPACEMOVE_REDUCTION / parent.inertia_force_weight)
|
||||
glide_to_halt(get_loop_delay(parent))
|
||||
return TRUE
|
||||
|
||||
drift_force -= INERTIA_FORCE_SPACEMOVE_REDUCTION / source.inertia_force_weight
|
||||
drifting_loop.set_delay(get_loop_delay(source))
|
||||
return COMPONENT_PREVENT_SPACEMOVE_HALT
|
||||
drift_force -= INERTIA_FORCE_SPACEMOVE_REDUCTION / parent.inertia_force_weight
|
||||
drifting_loop.set_delay(get_loop_delay(parent))
|
||||
return TRUE
|
||||
|
||||
/datum/drift_handler/proc/get_loop_delay(atom/movable/movable)
|
||||
return (DEFAULT_INERTIA_SPEED / ((1 - INERTIA_SPEED_COEF) + drift_force * INERTIA_SPEED_COEF)) * movable.inertia_move_multiplier
|
||||
|
||||
@@ -281,6 +281,9 @@
|
||||
if (SEND_SIGNAL(src, COMSIG_MOB_ATTEMPT_HALT_SPACEMOVE, movement_dir, continuous_move, backup) & COMPONENT_PREVENT_SPACEMOVE_HALT)
|
||||
return FALSE
|
||||
|
||||
if (drift_handler?.attempt_halt(movement_dir, continuous_move, backup))
|
||||
return FALSE
|
||||
|
||||
if(continuous_move || !istype(backup) || !movement_dir || backup.anchored)
|
||||
return TRUE
|
||||
|
||||
@@ -300,8 +303,9 @@
|
||||
/**
|
||||
* Finds a target near a mob that is viable for pushing off when moving.
|
||||
* Takes the intended movement direction as input, alongside if the context is checking if we're allowed to continue drifting
|
||||
* If include_floors is TRUE, includes floors *with gravity*
|
||||
*/
|
||||
/mob/get_spacemove_backup(moving_direction, continuous_move)
|
||||
/mob/get_spacemove_backup(moving_direction, continuous_move, include_floors = FALSE)
|
||||
var/atom/secondary_backup
|
||||
var/list/priority_dirs = (moving_direction in GLOB.cardinals) ? GLOB.cardinals : GLOB.diagonals
|
||||
for(var/atom/pushover as anything in range(1, get_turf(src)))
|
||||
@@ -309,13 +313,15 @@
|
||||
continue
|
||||
if(isarea(pushover))
|
||||
continue
|
||||
var/is_priority = pushover.loc == loc || (get_dir(src, pushover) in priority_dirs)
|
||||
if(isturf(pushover))
|
||||
var/turf/turf = pushover
|
||||
if(isspaceturf(turf))
|
||||
continue
|
||||
if(!turf.density && !mob_negates_gravity())
|
||||
continue
|
||||
if (get_dir(src, pushover) in priority_dirs)
|
||||
if (!include_floors || !turf.has_gravity())
|
||||
continue
|
||||
if (is_priority)
|
||||
return pushover
|
||||
secondary_backup = pushover
|
||||
continue
|
||||
@@ -343,13 +349,13 @@
|
||||
if(moving_direction == get_dir(src, pushover)) // Can't push "off" of something that you're walking into
|
||||
continue
|
||||
if(rebound.anchored)
|
||||
if (get_dir(src, rebound) in priority_dirs)
|
||||
if (is_priority)
|
||||
return rebound
|
||||
secondary_backup = rebound
|
||||
continue
|
||||
if(pulling == rebound)
|
||||
continue
|
||||
if (get_dir(src, rebound) in priority_dirs)
|
||||
if (is_priority)
|
||||
return rebound
|
||||
secondary_backup = rebound
|
||||
return secondary_backup
|
||||
|
||||
Reference in New Issue
Block a user