diff --git a/code/controllers/subsystem/movement/newtonian_movement.dm b/code/controllers/subsystem/movement/newtonian_movement.dm index 41db87d722b..e4143669678 100644 --- a/code/controllers/subsystem/movement/newtonian_movement.dm +++ b/code/controllers/subsystem/movement/newtonian_movement.dm @@ -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) diff --git a/code/datums/components/jetpack.dm b/code/datums/components/jetpack.dm index 1a44da7eb6d..c7ff096029b 100644 --- a/code/datums/components/jetpack.dm +++ b/code/datums/components/jetpack.dm @@ -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 diff --git a/code/datums/drift_handler.dm b/code/datums/drift_handler.dm index dc47f28819b..dcf0771d8a5 100644 --- a/code/datums/drift_handler.dm +++ b/code/datums/drift_handler.dm @@ -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 diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index f19a3991ca3..743bdad8c45 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -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