mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-08-28 22:47:59 +01:00
Fix jetpacks and speedbikes (#28222)
* Fix jetpacks * All mobs LONG_GLIDE * Don't disturb the drift loop on Z level changes. * Fix speedbikes
This commit is contained in:
@@ -22,8 +22,8 @@
|
||||
#define MOVEMENT_LOOP_IGNORE_GLIDE (1<<2)
|
||||
///Should we not update our movables dir on move?
|
||||
#define MOVEMENT_LOOP_NO_DIR_UPDATE (1<<3)
|
||||
///Is the loop moving the movable outside its control, like it's an external force? e.g. footsteps won't play if enabled.
|
||||
#define MOVEMENT_LOOP_OUTSIDE_CONTROL (1<<4)
|
||||
///Controls how the loop will set momentum_change in its Move call.
|
||||
#define MOVEMENT_LOOP_NO_MOMENTUM_CHANGE (1<<4)
|
||||
|
||||
// Movement loop status flags
|
||||
/// Has the loop been paused, soon to be resumed?
|
||||
@@ -54,12 +54,13 @@
|
||||
#define ACTIVE_MOVEMENT_OLDLOCS 4
|
||||
|
||||
/// The arguments of this macro correspond directly to the argument order of /atom/movable/proc/Moved
|
||||
#define SET_ACTIVE_MOVEMENT(_old_loc, _direction, _forced, _oldlocs) \
|
||||
#define SET_ACTIVE_MOVEMENT(_old_loc, _direction, _forced, _oldlocs, _momentum_change) \
|
||||
active_movement = list( \
|
||||
_old_loc, \
|
||||
_direction, \
|
||||
_forced, \
|
||||
_oldlocs, \
|
||||
_momentum_change, \
|
||||
)
|
||||
|
||||
/// Finish any active movements
|
||||
|
||||
@@ -206,7 +206,7 @@
|
||||
|
||||
/datum/move_loop/move/move()
|
||||
var/atom/old_loc = moving.loc
|
||||
moving.Move(get_step(moving, direction), direction, FALSE, !(flags & MOVEMENT_LOOP_NO_DIR_UPDATE))
|
||||
moving.Move(get_step(moving, direction), direction, FALSE, !(flags & MOVEMENT_LOOP_NO_DIR_UPDATE), !(flags & MOVEMENT_LOOP_NO_MOMENTUM_CHANGE))
|
||||
// We cannot rely on the return value of Move(), we care about teleports and it doesn't
|
||||
// Moving also can be null on occasion, if the move deleted it and therefor us
|
||||
return old_loc != moving?.loc ? MOVELOOP_SUCCESS : MOVELOOP_FAILURE
|
||||
|
||||
@@ -5,10 +5,6 @@
|
||||
var/atom/inertia_last_loc
|
||||
var/old_dir
|
||||
var/datum/move_loop/move/drifting_loop
|
||||
///Should we ignore the next glide rate input we get?
|
||||
///This is to some extent a hack around the order of operations
|
||||
///Around COMSIG_MOVELOOP_POSTPROCESS. I'm sorry lad
|
||||
var/ignore_next_glide = FALSE
|
||||
///Have we been delayed? IE: active, but not working right this second?
|
||||
var/delayed = FALSE
|
||||
var/block_inputs_until
|
||||
@@ -19,7 +15,7 @@
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
. = ..()
|
||||
|
||||
var/flags = MOVEMENT_LOOP_OUTSIDE_CONTROL
|
||||
var/flags = MOVEMENT_LOOP_NO_MOMENTUM_CHANGE
|
||||
if(instant)
|
||||
flags |= MOVEMENT_LOOP_START_FAST
|
||||
var/atom/movable/movable_parent = parent
|
||||
@@ -61,8 +57,6 @@
|
||||
if(SEND_SIGNAL(parent, COMSIG_MOVABLE_DRIFT_VISUAL_ATTEMPT) & DRIFT_VISUAL_FAILED)
|
||||
return
|
||||
|
||||
// Ignore the next glide because it's literally just us
|
||||
ignore_next_glide = TRUE
|
||||
var/atom/movable/movable_parent = parent
|
||||
movable_parent.set_glide_size(MOVEMENT_ADJUSTED_GLIDE_SIZE(visual_delay, SSspacedrift.visual_delay))
|
||||
if(ismob(parent))
|
||||
@@ -74,7 +68,7 @@
|
||||
mob_parent.client?.visual_delay = MOVEMENT_ADJUSTED_GLIDE_SIZE(visual_delay, SSspacedrift.visual_delay)
|
||||
|
||||
/datum/component/drift/proc/newtonian_impulse(datum/source, inertia_direction)
|
||||
SIGNAL_HANDLER
|
||||
SIGNAL_HANDLER // COMSIG_MOVABLE_NEWTONIAN_MOVE
|
||||
var/atom/movable/movable_parent = parent
|
||||
inertia_last_loc = movable_parent.loc
|
||||
if(drifting_loop)
|
||||
@@ -84,32 +78,28 @@
|
||||
return COMPONENT_MOVABLE_NEWTONIAN_BLOCK
|
||||
|
||||
/datum/component/drift/proc/drifting_start()
|
||||
SIGNAL_HANDLER
|
||||
SIGNAL_HANDLER // COMSIG_MOVELOOP_START
|
||||
var/atom/movable/movable_parent = parent
|
||||
inertia_last_loc = movable_parent.loc
|
||||
RegisterSignal(movable_parent, COMSIG_MOVABLE_MOVED, PROC_REF(handle_move))
|
||||
// We will use glide size to intuit how long to delay our loop's next move for
|
||||
// This way you can't ride two movements at once while drifting, since that'd be dumb as fuck
|
||||
RegisterSignal(movable_parent, COMSIG_MOVABLE_UPDATED_GLIDE_SIZE, PROC_REF(handle_glidesize_update))
|
||||
// If you stop pulling something mid drift, I want it to retain that momentum
|
||||
RegisterSignal(movable_parent, COMSIG_ATOM_NO_LONGER_PULLING, PROC_REF(stopped_pulling))
|
||||
|
||||
/datum/component/drift/proc/drifting_stop()
|
||||
SIGNAL_HANDLER
|
||||
SIGNAL_HANDLER // COMSIG_MOVELOOP_STOP
|
||||
var/atom/movable/movable_parent = parent
|
||||
movable_parent.inertia_moving = FALSE
|
||||
ignore_next_glide = FALSE
|
||||
UnregisterSignal(movable_parent, list(COMSIG_MOVABLE_MOVED, COMSIG_MOVABLE_UPDATED_GLIDE_SIZE, COMSIG_ATOM_NO_LONGER_PULLING))
|
||||
|
||||
/datum/component/drift/proc/before_move(datum/source)
|
||||
SIGNAL_HANDLER
|
||||
SIGNAL_HANDLER // COMSIG_MOVELOOP_PREPROCESS_CHECK
|
||||
var/atom/movable/movable_parent = parent
|
||||
movable_parent.inertia_moving = TRUE
|
||||
old_dir = movable_parent.dir
|
||||
delayed = FALSE
|
||||
|
||||
/datum/component/drift/proc/after_move(datum/source, result, visual_delay)
|
||||
SIGNAL_HANDLER
|
||||
SIGNAL_HANDLER // COMSIG_MOVELOOP_POSTPROCESS
|
||||
if(result == MOVELOOP_FAILURE)
|
||||
qdel(src)
|
||||
return
|
||||
@@ -122,15 +112,14 @@
|
||||
return
|
||||
|
||||
inertia_last_loc = movable_parent.loc
|
||||
ignore_next_glide = TRUE
|
||||
|
||||
/datum/component/drift/proc/loop_death(datum/source)
|
||||
SIGNAL_HANDLER
|
||||
SIGNAL_HANDLER // COMSIG_PARENT_QDELETING
|
||||
drifting_loop = null
|
||||
UnregisterSignal(parent, COMSIG_MOVABLE_NEWTONIAN_MOVE) // We won't block a component from replacing us anymore
|
||||
|
||||
/datum/component/drift/proc/handle_move(datum/source, old_loc)
|
||||
SIGNAL_HANDLER
|
||||
/datum/component/drift/proc/handle_move(datum/source, old_loc, movement_dir, forced, list/old_locs, momentum_change)
|
||||
SIGNAL_HANDLER // COMSIG_MOVABLE_MOVED
|
||||
// This can happen, because signals once sent cannot be stopped
|
||||
if(QDELETED(src))
|
||||
return
|
||||
@@ -138,33 +127,19 @@
|
||||
if(!isturf(movable_parent.loc))
|
||||
qdel(src)
|
||||
return
|
||||
if(movable_parent.inertia_moving)
|
||||
return
|
||||
if(!movable_parent.Process_Spacemove(drifting_loop.direction, continuous_move = TRUE))
|
||||
return
|
||||
qdel(src)
|
||||
// If we experience a momentum change that's not a result of changing Z levels, delay the drifting loop so we don't double-move.
|
||||
if(momentum_change && !HAS_TRAIT(movable_parent, TRAIT_CURRENTLY_Z_MOVING))
|
||||
drifting_loop.pause_for(movable_parent.inertia_move_delay)
|
||||
|
||||
/// We're going to take the passed in glide size
|
||||
/// and use it to manually delay our loop for that period
|
||||
/// to allow the other movement to complete
|
||||
/datum/component/drift/proc/handle_glidesize_update(datum/source, old_glide_size)
|
||||
SIGNAL_HANDLER
|
||||
// If we aren't drifting, or this is us, fuck off
|
||||
var/atom/movable/movable_parent = parent
|
||||
if(!drifting_loop || movable_parent.inertia_moving)
|
||||
if(!movable_parent.inertia_moving)
|
||||
qdel(src)
|
||||
return
|
||||
// If we are drifting, but this set came from the moveloop itself, drop the input
|
||||
// I'm sorry man
|
||||
if(ignore_next_glide)
|
||||
ignore_next_glide = FALSE
|
||||
return
|
||||
var/glide_delay = round(world.icon_size / movable_parent.glide_size, 1) * world.tick_lag
|
||||
drifting_loop.pause_for(glide_delay)
|
||||
delayed = TRUE
|
||||
if(movable_parent.Process_Spacemove(drifting_loop.direction, continuous_move = TRUE))
|
||||
qdel(src)
|
||||
|
||||
/// If we're pulling something and stop, we want it to continue at our rate and such
|
||||
/datum/component/drift/proc/stopped_pulling(datum/source, atom/movable/was_pulling)
|
||||
SIGNAL_HANDLER
|
||||
SIGNAL_HANDLER // COMSIG_ATOM_NO_LONGER_PULLING
|
||||
// This does mean it falls very slightly behind, but otherwise they'll potentially run into us
|
||||
var/next_move_in = drifting_loop.timer - world.time + world.tick_lag
|
||||
was_pulling.newtonian_move(drifting_loop.direction, start_delay = next_move_in)
|
||||
@@ -187,6 +162,7 @@
|
||||
RegisterSignal(parent, COMSIG_MOB_CLIENT_PRE_MOVE, PROC_REF(allow_final_movement))
|
||||
|
||||
/datum/component/drift/proc/allow_final_movement(datum/source)
|
||||
SIGNAL_HANDLER // COMSIG_MOB_CLIENT_PRE_MOVE
|
||||
// Some things want to allow movement out of spacedrift, we should let them
|
||||
if(SEND_SIGNAL(parent, COMSIG_MOVABLE_DRIFT_BLOCK_INPUT) & DRIFT_ALLOW_INPUT)
|
||||
return
|
||||
|
||||
@@ -73,7 +73,9 @@
|
||||
if(!turf_check(next, current))
|
||||
to_chat(user, "<span class='warning'>[movable_parent] cannot go onto [next]!</span>")
|
||||
return
|
||||
if(GLOB.move_manager.processing_on(user, SSspacedrift) || !isturf(movable_parent.loc))
|
||||
if(GLOB.move_manager.processing_on(user, SSspacedrift) && !override_allow_spacemove)
|
||||
return
|
||||
if(!isturf(movable_parent.loc))
|
||||
return
|
||||
|
||||
step(movable_parent, direction)
|
||||
|
||||
+17
-10
@@ -235,7 +235,7 @@
|
||||
/// Here's where we rewrite how byond handles movement except slightly different.
|
||||
/// To be removed on step_ conversion.
|
||||
/// All this work to prevent a second bump.
|
||||
/atom/movable/Move(atom/newloc, direction, glide_size_override = 0, update_dir = TRUE)
|
||||
/atom/movable/Move(atom/newloc, direction, glide_size_override = 0, update_dir = TRUE, momentum_change = TRUE)
|
||||
. = FALSE
|
||||
if(!newloc || newloc == loc)
|
||||
return
|
||||
@@ -287,7 +287,7 @@
|
||||
var/area/oldarea = get_area(oldloc)
|
||||
var/area/newarea = get_area(newloc)
|
||||
|
||||
SET_ACTIVE_MOVEMENT(oldloc, direction, FALSE, old_locs)
|
||||
SET_ACTIVE_MOVEMENT(oldloc, direction, FALSE, old_locs, momentum_change)
|
||||
loc = newloc
|
||||
|
||||
. = TRUE
|
||||
@@ -310,7 +310,7 @@
|
||||
|
||||
RESOLVE_ACTIVE_MOVEMENT
|
||||
|
||||
/atom/movable/Move(atom/newloc, direct = 0, glide_size_override = 0, update_dir = TRUE)
|
||||
/atom/movable/Move(atom/newloc, direct = 0, glide_size_override = 0, update_dir = TRUE, momentum_change = TRUE)
|
||||
var/atom/movable/pullee = pulling
|
||||
var/turf/current_turf = loc
|
||||
if(!loc || !newloc)
|
||||
@@ -325,7 +325,7 @@
|
||||
|
||||
if(loc != newloc)
|
||||
if(!IS_DIR_DIAGONAL(direct)) //Cardinal move
|
||||
. = ..(newloc, direct)
|
||||
. = ..(newloc, direct, momentum_change = momentum_change)
|
||||
else //Diagonal move, split it into cardinal moves
|
||||
moving_diagonally = FIRST_DIAG_STEP
|
||||
var/first_step_dir = 0
|
||||
@@ -334,22 +334,24 @@
|
||||
var/direct_NS = direct & (NORTH | SOUTH)
|
||||
var/direct_EW = direct & (EAST | WEST)
|
||||
var/first_step_target = get_step(src, direct_NS)
|
||||
step(src, direct_NS)
|
||||
// .() is rarely seen (for good reason), but it calls the same proc we're in.
|
||||
// We cant' avoid it here, because oour overloading of Move() makes it call the wrong one.
|
||||
. = .(first_step_target, direct_NS, glide_size_override, FALSE, momentum_change)
|
||||
if(loc == first_step_target)
|
||||
first_step_dir = direct_NS
|
||||
moving_diagonally = SECOND_DIAG_STEP
|
||||
. = step(src, direct_EW)
|
||||
. = .(newloc, direct_EW, glide_size_override, FALSE, momentum_change)
|
||||
else if(loc == oldloc)
|
||||
first_step_target = get_step(src, direct_EW)
|
||||
step(src, direct_EW)
|
||||
. = .(first_step_target, direct_EW, glide_size_override, FALSE, momentum_change)
|
||||
if(loc == first_step_target)
|
||||
first_step_dir = direct_EW
|
||||
moving_diagonally = SECOND_DIAG_STEP
|
||||
. = step(src, direct_NS)
|
||||
. = .(newloc, direct_NS, glide_size_override, FALSE, momentum_change)
|
||||
if(first_step_dir != 0)
|
||||
if(!. && set_dir_on_move && update_dir)
|
||||
setDir(first_step_dir)
|
||||
Moved(oldloc, first_step_dir)
|
||||
Moved(oldloc, first_step_dir, FALSE, null, TRUE)
|
||||
else if(!inertia_moving)
|
||||
newtonian_move(direct)
|
||||
if(client_mobs_in_contents)
|
||||
@@ -520,7 +522,7 @@
|
||||
var/atom/oldloc = loc
|
||||
var/is_multi_tile = bound_width > world.icon_size || bound_height > world.icon_size
|
||||
|
||||
SET_ACTIVE_MOVEMENT(oldloc, NONE, TRUE, null)
|
||||
SET_ACTIVE_MOVEMENT(oldloc, NONE, TRUE, null, TRUE)
|
||||
|
||||
if(destination)
|
||||
if(pulledby && !HAS_TRAIT(src, TRAIT_CURRENTLY_Z_MOVING))
|
||||
@@ -658,6 +660,11 @@
|
||||
|
||||
return TRUE
|
||||
|
||||
/mob/newtonian_move(direction, instant = FALSE, start_delay = 0)
|
||||
if(buckled)
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
//called when src is thrown into hit_atom
|
||||
/atom/movable/proc/throw_impact(atom/hit_atom, throwingdatum)
|
||||
set waitfor = FALSE
|
||||
|
||||
@@ -144,13 +144,7 @@
|
||||
|
||||
var/diagonal_factor = 1
|
||||
if(IS_DIR_DIAGONAL(direct))
|
||||
// For some reason, LONG_GLIDE mobs need to slow down here, but other mobs need to speed up.
|
||||
// I'd expect one or the other to change, not both.
|
||||
// If you can figure out why, please update this comment.
|
||||
if(mob.appearance_flags & LONG_GLIDE)
|
||||
diagonal_factor = sqrt(2)
|
||||
else
|
||||
diagonal_factor = 1 / sqrt(2)
|
||||
diagonal_factor = sqrt(2)
|
||||
mob.set_glide_size(DELAY_TO_GLIDE_SIZE(add_delay * diagonal_factor)) // set it now in case of pulled objects
|
||||
|
||||
//If the move was recent, count using old_move_delay
|
||||
@@ -187,28 +181,21 @@
|
||||
|
||||
. = ..()
|
||||
|
||||
var/new_glide_size = 0
|
||||
// Only adjust for diagonal movement if the move was *actually* diagonal
|
||||
if(mob.loc == new_loc)
|
||||
// Similar to the glide size calculation above, LONG_GLIDE mobs need to slow down and other mobs speed up.
|
||||
// Unline before, we also want to calculate the new movement delay, which is increased for LONG_GLIDE mobs, and unchanged for other mobs.
|
||||
mob.last_movement = world.time
|
||||
if(IS_DIR_DIAGONAL(direct) && (mob.appearance_flags & LONG_GLIDE))
|
||||
if(IS_DIR_DIAGONAL(direct))
|
||||
add_delay *= sqrt(2)
|
||||
|
||||
if(visual_delay)
|
||||
new_glide_size = visual_delay
|
||||
else
|
||||
new_glide_size = DELAY_TO_GLIDE_SIZE(add_delay)
|
||||
|
||||
if(IS_DIR_DIAGONAL(direct) && !(mob.appearance_flags & LONG_GLIDE))
|
||||
new_glide_size *= sqrt(2)
|
||||
|
||||
mob.set_glide_size(new_glide_size)
|
||||
else if(visual_delay)
|
||||
mob.set_glide_size(visual_delay)
|
||||
var/new_glide_size = 0
|
||||
if(visual_delay)
|
||||
new_glide_size = visual_delay
|
||||
else
|
||||
mob.set_glide_size(DELAY_TO_GLIDE_SIZE(add_delay))
|
||||
new_glide_size = DELAY_TO_GLIDE_SIZE(add_delay)
|
||||
|
||||
mob.set_glide_size(new_glide_size)
|
||||
|
||||
move_delay += add_delay
|
||||
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
density = TRUE
|
||||
layer = MOB_LAYER
|
||||
animate_movement = SLIDE_STEPS
|
||||
// We probably shouldn't ever be setting this. LONG_GLIDE makes diagonal movement faster, because you move at full speed on both axes. However, we have manual changes scatterd around that undo this, and re-establish euclidian movement. Yes, that's exactly as silly as it sounds.
|
||||
// Still, for the moment, we should at least make all mobs behave the same way that carbons do.
|
||||
appearance_flags = LONG_GLIDE
|
||||
pressure_resistance = 8
|
||||
throwforce = 10
|
||||
var/datum/mind/mind
|
||||
|
||||
Reference in New Issue
Block a user