Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

scuffed diagonal movement #4419

Closed
wants to merge 12 commits into from
32 changes: 32 additions & 0 deletions code/__DEFINES/movement.dm
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,35 @@
#define PASS_FLAGS_FLAME (PASS_AROUND|PASS_UNDER|PASS_MOB_THRU|PASS_THROUGH|PASS_OVER_FIRE)
#define PASS_FLAGS_SMOKE (PASS_HIGH_OVER|PASS_AROUND|PASS_UNDER|PASS_MOB_THRU|PASS_THROUGH)
#define PASS_FLAGS_CRAWLER (PASS_TYPE_CRAWLER|PASS_UNDER)

/// The minimum for glide_size to be clamped to.
#define MIN_GLIDE_SIZE 1
/// The maximum for glide_size to be clamped to.
/// This shouldn't be higher than the icon size, and generally you shouldn't be changing this, but it's here just in case.
#define MAX_GLIDE_SIZE 32

/// Compensating for time dilation
GLOBAL_VAR_INIT(glide_size_multiplier, 1.0)

///Broken down, here's what this does:
/// divides the world icon_size (32) by delay divided by ticklag to get the number of pixels something should be moving each tick.
/// The division result is given a min value of 1 to prevent obscenely slow glide sizes from being set
/// Then that's multiplied by the global glide size multiplier. 1.25 by default feels pretty close to spot on. This is just to try to get byond to behave.
/// The whole result is then clamped to within the range above.
/// Not very readable but it works
#define DELAY_TO_GLIDE_SIZE(delay) (clamp(((world.icon_size / max((delay) / world.tick_lag, 1)) * GLOB.glide_size_multiplier), MIN_GLIDE_SIZE, MAX_GLIDE_SIZE))

///True if the dir is north or south, false therwise
#define NSCOMPONENT(d) (d&(NORTH|SOUTH))
///True if the dir is east/west, false otherwise
#define EWCOMPONENT(d) (d&(EAST|WEST))
///Flips the dir for north/south directions
#define NSDIRFLIP(d) (d^(NORTH|SOUTH))
///Flips the dir for east/west directions
#define EWDIRFLIP(d) (d^(EAST|WEST))

//Diagonal movement is split into two cardinal moves
/// The first step of the diagnonal movement
#define FIRST_DIAG_STEP 1
/// The second step of the diagnonal movement
#define SECOND_DIAG_STEP 2
1 change: 1 addition & 0 deletions code/controllers/subsystem/time_track.dm
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ SUBSYSTEM_DEF(time_track)
time_dilation_avg_fast = MC_AVERAGE_FAST(time_dilation_avg_fast, time_dilation_current)
time_dilation_avg = MC_AVERAGE(time_dilation_avg, time_dilation_avg_fast)
time_dilation_avg_slow = MC_AVERAGE_SLOW(time_dilation_avg_slow, time_dilation_avg)
GLOB.glide_size_multiplier = (current_byondtime - last_tick_byond_time) / (current_realtime - last_tick_realtime)
else
first_run = FALSE
last_tick_realtime = current_realtime
Expand Down
26 changes: 25 additions & 1 deletion code/game/atoms_movable.dm
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
/atom/movable
layer = OBJ_LAYER
appearance_flags = TILE_BOUND|PIXEL_SCALE|LONG_GLIDE
glide_size = 8
var/last_move_dir = null
var/anchored = FALSE
var/drag_delay = 3 //delay (in deciseconds) added to mob's move_delay when pulling it.
Expand Down Expand Up @@ -31,6 +33,11 @@
///Highest-intensity light affecting us, which determines our visibility.
var/affecting_dynamic_lumi = 0

var/moving_diagonally

/// Whether this atom should have its dir automatically changed when it moves. Setting this to FALSE allows for things such as directional windows to retain dir on moving without snowflake code all of the place.
var/set_dir_on_move = TRUE

//===========================================================================
/atom/movable/Destroy(force)
for(var/atom/movable/I in contents)
Expand Down Expand Up @@ -235,8 +242,9 @@
*/
/atom/movable/proc/abstract_move(atom/new_loc)
var/atom/old_loc = loc
var/direction = get_dir(old_loc, new_loc)
loc = new_loc
Moved(old_loc)
Moved(old_loc, direction, TRUE)

//called when a mob tries to breathe while inside us.
/atom/movable/proc/handle_internal_lifeform(mob/lifeform_inside_me)
Expand Down Expand Up @@ -355,3 +363,19 @@
set_light_range(range)
set_light_power(power)
set_light_color(color)

/atom/movable/proc/set_glide_size(target = 8)
SEND_SIGNAL(src, COMSIG_MOVABLE_UPDATE_GLIDE_SIZE, target)
glide_size = target

/mob/set_glide_size(target)
. = ..()

if(pulling)
pulling.set_glide_size(target)

/obj/set_glide_size(target)
. = ..()

if(buckled_mob)
buckled_mob.set_glide_size(target)
2 changes: 0 additions & 2 deletions code/game/objects/items.dm
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,6 @@
var/map_specific_decoration = FALSE
/// color of the blood on us if there's any.
var/blood_color = ""
/// taken from blood.dm
appearance_flags = KEEP_TOGETHER
/// lets us know if the item is an objective or not
var/is_objective = FALSE

Expand Down
15 changes: 10 additions & 5 deletions code/game/objects/structures/stool_bed_chair_nest/bed.dm
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,12 @@

update_icon()

/obj/structure/bed/set_glide_size(target)
. = ..()

if(buckled_bodybag)
buckled_bodybag.set_glide_size(target)

//Unsafe proc
/obj/structure/bed/proc/do_buckle_bodybag(obj/structure/closet/bodybag/B, mob/user)
B.visible_message(SPAN_NOTICE("[user] buckles [B] to [src]!"))
Expand Down Expand Up @@ -115,11 +121,10 @@
return 0

/obj/structure/bed/proc/handle_buckled_bodybag_movement(NewLoc, direct)
if(!(direct & (direct - 1))) //Not diagonal move. the obj's diagonal move is split into two cardinal moves and those moves will handle the buckled bodybag's movement.
if(!buckled_bodybag.Move(NewLoc, direct))
forceMove(buckled_bodybag.loc)
last_move_dir = buckled_bodybag.last_move_dir
return 0
if(!buckled_bodybag.Move(NewLoc, direct))
forceMove(buckled_bodybag.loc)
last_move_dir = buckled_bodybag.last_move_dir
return 0
return 1

/obj/structure/bed/roller/BlockedPassDirs(atom/movable/mover, target_dir)
Expand Down
2 changes: 1 addition & 1 deletion code/game/turfs/turf.dm
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@
return FALSE

// if we are thrown, moved, dragged, or in any other way abused by code - check our diagonals
if(!mover.move_intentionally)
if(!mover.move_intentionally || (fdir == NORTHEAST || fdir == NORTHWEST || fdir == SOUTHEAST || fdir == SOUTHWEST))
// Check objects in adjacent turf EAST/WEST
if(fd1 && fd1 != fdir)
T = get_step(mover, fd1)
Expand Down
15 changes: 4 additions & 11 deletions code/modules/keybindings/bindings_atom.dm
Original file line number Diff line number Diff line change
@@ -1,33 +1,26 @@
// You might be wondering why this isn't client level. If focus is null, we don't want you to move.
// Only way to do that is to tie the behavior into the focus's keyLoop().

// You might be wondering why this isn't client level. If focus is null, we don't want you to move.
// Only way to do that is to tie the behavior into the focus's keyLoop().
/atom/movable/keyLoop(client/user)
var/movement_dir = NONE
for(var/_key in user.keys_held)
if(user.movement_keys[_key])
movement_dir = user.movement_keys[_key]

if(!movement_dir)
return

/*
movement_dir = movement_dir | user.movement_keys[_key]
if(user.next_move_dir_add)
movement_dir |= user.next_move_dir_add
if(user.next_move_dir_sub)
movement_dir &= ~user.next_move_dir_sub*/
movement_dir &= ~user.next_move_dir_sub
// Sanity checks in case you hold left and right and up to make sure you only go up
if((movement_dir & NORTH) && (movement_dir & SOUTH))
movement_dir &= ~(NORTH|SOUTH)
if((movement_dir & EAST) && (movement_dir & WEST))
movement_dir &= ~(EAST|WEST)

movement_dir = turn(movement_dir, -dir2angle(user.dir)) //By doing this we ensure that our input direction is offset by the client (camera) direction

// This is called from Subsystem, and as such usr is unset.
// You hopefully don't it but it might go against legacy code expectations.
usr = user.mob
if(user.movement_locked)
keybind_face_direction(movement_dir)
else
user.Move(get_step(src, movement_dir), movement_dir)

23 changes: 16 additions & 7 deletions code/modules/mob/dead/observer/observer.dm
Original file line number Diff line number Diff line change
Expand Up @@ -435,26 +435,35 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
ghost.can_reenter_corpse = FALSE
nest.ghost_of_buckled_mob = ghost

/mob/dead/observer/Move(atom/newloc, direct)
/mob/dead/observer/Move(atom/newloc, direct, glide_size_override = 32)
following = null
var/area/last_area = get_area(loc)
if(updatedir)
setDir(direct)//only update dir if we actually need it, so overlays won't spin on base sprites that don't have directions of their own

if(glide_size_override)
set_glide_size(glide_size_override)

if(newloc)
abstract_move(newloc)
else
abstract_move(get_turf(src)) //Get out of closets and such as a ghost
var/turf/destination = get_turf(src)

if((direct & NORTH) && y < world.maxy)
y++
destination = get_step(destination, NORTH)

else if((direct & SOUTH) && y > 1)
y--
destination = get_step(destination, SOUTH)

if((direct & EAST) && x < world.maxx)
x++
destination = get_step(destination, EAST)

else if((direct & WEST) && x > 1)
x--
destination = get_step(destination, WEST)

abstract_move(destination)

var/turf/new_turf = locate(x, y, z)
var/turf/new_turf = get_turf(src)
if(!new_turf)
return

Expand Down
1 change: 0 additions & 1 deletion code/modules/mob/living/carbon/human/human_defines.dm
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,6 @@
//Taken from update_icons
var/list/overlays_standing[TOTAL_LAYERS]
var/hardcore = FALSE //If TRUE, removes the body upon unrevivable death (for WO)
appearance_flags = KEEP_TOGETHER | TILE_BOUND
throw_range = 4 // Humans can't be thrown that far

var/datum/action/human_action/activable/selected_ability
Expand Down
27 changes: 19 additions & 8 deletions code/modules/mob/living/living.dm
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@

return

/mob/living/Move(NewLoc, direct)
/mob/living/Move(NewLoc, direct, glide_size_override)
if (buckled && buckled.loc != NewLoc) //not updating position
if (!buckled.anchored)
return buckled.Move(NewLoc, direct)
Expand Down Expand Up @@ -204,7 +204,7 @@
else if(get_dist(src, pulling) > 1 || ((pull_dir - 1) & pull_dir)) //puller and pullee more than one tile away or in diagonal position
var/pulling_dir = get_dir(pulling, T)
pulling.Move(T, pulling_dir) //the pullee tries to reach our previous position
if(pulling && get_dist(src, pulling) > 1) //the pullee couldn't keep up
if(pulling && get_dist(src, pulling) > 1 && !moving_diagonally) //the pullee couldn't keep up
stop_pulling()
else
var/mob/living/pmob = pulling
Expand All @@ -213,7 +213,7 @@
if(!(flags_atom & DIRLOCK))
setDir(turn(direct, 180)) //face the pullee

if(pulledby && get_dist(src, pulledby) > 1)//separated from our puller and not in the middle of a diagonal move.
if(pulledby && get_dist(src, pulledby) > 1 && !moving_diagonally)//separated from our puller and not in the middle of a diagonal move.
pulledby.stop_pulling()

if (s_active && !( s_active in contents ) && get_turf(s_active) != get_turf(src)) //check !( s_active in contents ) first so we hopefully don't have to call get_turf() so much.
Expand Down Expand Up @@ -315,6 +315,9 @@
if(.)
reset_view(destination)

#define SWAPPING 1
#define PHASING 2

/mob/living/Collide(atom/movable/AM)
if(buckled || now_pushing)
return
Expand Down Expand Up @@ -371,13 +374,15 @@
return

if(!L.buckled && !L.anchored)
var/mob_swap
var/mob_swap = NONE
//the puller can always swap with its victim if on grab intent
if(L.pulledby == src && a_intent == INTENT_GRAB)
mob_swap = 1
mob_swap = SWAPPING
//restrained people act if they were on 'help' intent to prevent a person being pulled from being separated from their puller
else if((L.is_mob_restrained() || L.a_intent == INTENT_HELP) && (is_mob_restrained() || a_intent == INTENT_HELP))
mob_swap = 1
mob_swap = SWAPPING
if(moving_diagonally && (get_dir(src, L) in GLOB.cardinals) && get_step(src, dir).Enter(src, loc))
mob_swap = PHASING
if(mob_swap)
//switch our position with L
if(loc && !loc.Adjacent(L.loc))
Expand All @@ -389,8 +394,11 @@
L.add_temp_pass_flags(PASS_MOB_THRU)
add_temp_pass_flags(PASS_MOB_THRU)

L.Move(oldloc)
Move(oldLloc)
if(moving_diagonally)
moving_diagonally = FALSE
if(mob_swap == SWAPPING)
L.Move(oldloc)

remove_temp_pass_flags(PASS_MOB_THRU)
L.remove_temp_pass_flags(PASS_MOB_THRU)
Expand All @@ -400,11 +408,14 @@

now_pushing = FALSE

if(!(L.status_flags & CANPUSH))
if(!(L.status_flags & CANPUSH) || moving_diagonally)
return

..()

#undef SWAPPING
#undef PHASING

/mob/living/launch_towards(datum/launch_metadata/LM)
if(src)
SEND_SIGNAL(src, COMSIG_MOB_MOVE_OR_LOOK, TRUE, dir, dir)
Expand Down
1 change: 0 additions & 1 deletion code/modules/mob/mob_defines.dm
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,6 @@

can_block_movement = TRUE

appearance_flags = TILE_BOUND
var/mouse_icon = null

///the mob's tgui player panel
Expand Down
24 changes: 22 additions & 2 deletions code/modules/mob/mob_movement.dm
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@
next_move_dir_add = 0
next_move_dir_sub = 0

var/old_move_delay = next_movement

next_movement = world.time + world.tick_lag

if(!direct)
Expand All @@ -124,7 +126,6 @@
return

if(isobserver(mob)) //Ghosts are snowflakes unfortunately
next_movement = world.time + move_delay
return mob.Move(n, direct)

if(SEND_SIGNAL(mob, COMSIG_CLIENT_MOB_MOVE, n, direct) & COMPONENT_OVERRIDE_MOVE)
Expand Down Expand Up @@ -197,8 +198,27 @@
if(mob.confused)
mob.Move(get_step(mob, pick(cardinal)))
else

var/new_glide_size = DELAY_TO_GLIDE_SIZE(move_delay * ( (NSCOMPONENT(direct) && EWCOMPONENT(direct)) ? sqrt(2) : 1 ) )
mob.set_glide_size(new_glide_size) // set it now in case of pulled objects

//If the move was recent, count using old_move_delay
//We want fractional behavior and all
if(old_move_delay + world.tick_lag > world.time)
//Yes this makes smooth movement stutter if add_delay is too fractional
//Yes this is better then the alternative
next_movement = old_move_delay
else
next_movement = world.time

. = ..()

if((direct & (direct - 1)) && mob.loc == n) //moved diagonally successfully
move_delay *= sqrt(2)

var/after_glide = DELAY_TO_GLIDE_SIZE(move_delay)
mob.set_glide_size(after_glide)

if (mob.tile_contents)
mob.tile_contents = list()
if(.)
Expand All @@ -208,7 +228,7 @@
mob.update_clone()
mob.move_intentionally = FALSE
moving = FALSE
next_movement = world.time + move_delay
next_movement += move_delay
return

///Process_Spacemove
Expand Down
Loading