diff --git a/code/__DEFINES/movement_defines.dm b/code/__DEFINES/movement_defines.dm index cb76916dc0e..0742f43f946 100644 --- a/code/__DEFINES/movement_defines.dm +++ b/code/__DEFINES/movement_defines.dm @@ -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 diff --git a/code/controllers/subsystem/movement/movement_types.dm b/code/controllers/subsystem/movement/movement_types.dm index 308aeb7ec80..a7b6c56ee77 100644 --- a/code/controllers/subsystem/movement/movement_types.dm +++ b/code/controllers/subsystem/movement/movement_types.dm @@ -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 diff --git a/code/datums/components/drift.dm b/code/datums/components/drift.dm index f4e22b9fe94..57abadf8a77 100644 --- a/code/datums/components/drift.dm +++ b/code/datums/components/drift.dm @@ -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 diff --git a/code/datums/components/riding/riding_vehicle.dm b/code/datums/components/riding/riding_vehicle.dm index 28fa51947ee..7f35a266bf3 100644 --- a/code/datums/components/riding/riding_vehicle.dm +++ b/code/datums/components/riding/riding_vehicle.dm @@ -73,7 +73,9 @@ if(!turf_check(next, current)) to_chat(user, "[movable_parent] cannot go onto [next]!") 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) diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index a23242705db..0085e0be658 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -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 diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index 6742548c247..d10218ad2d1 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -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 diff --git a/code/modules/mob/mob_vars.dm b/code/modules/mob/mob_vars.dm index 03d9b375faa..b598fe566e7 100644 --- a/code/modules/mob/mob_vars.dm +++ b/code/modules/mob/mob_vars.dm @@ -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