diff --git a/code/modules/client/client_defines.dm b/code/modules/client/client_defines.dm index 02ebb8dca8641..b8ef5ffc8ab80 100644 --- a/code/modules/client/client_defines.dm +++ b/code/modules/client/client_defines.dm @@ -121,5 +121,9 @@ /// Messages currently seen by this client var/list/seen_messages + /// The direction we WANT to move, based off our keybinds + /// Will be udpated to be the actual direction later on + var/intended_direction = NONE + show_popup_menus = TRUE // right click menu no longer shows up control_freak = CONTROL_FREAK_MACROS diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index 438aa2bfc463a..44d5b59bc31dd 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -867,6 +867,7 @@ winset(src, "default-[REF(key)]", "parent=default;name=[key];command=[msay]") else winset(src, "default-[REF(key)]", "parent=default;name=[key];command=") + calculate_move_dir() /client/proc/change_view(new_size) if(isnull(new_size)) diff --git a/code/modules/keybindings/bindings_atom.dm b/code/modules/keybindings/bindings_atom.dm index c0ad4d84b96cb..a6366581488f7 100644 --- a/code/modules/keybindings/bindings_atom.dm +++ b/code/modules/keybindings/bindings_atom.dm @@ -1,18 +1,32 @@ // 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) - if(user?.keys_held["Ctrl"]) + // Clients don't go null randomly. They do go null unexpectedly though, when they're poked in particular ways + // keyLoop is called by a for loop over mobs. We're guarenteed that all the mobs have clients at the START + // But the move of one mob might poke the client of another, so we do this + if(!user) + return FALSE + if(user.keys_held["Ctrl"]) return - var/movement_dir = NONE - for(var/_key in user.keys_held) - 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) + var/movement_dir = user.intended_direction | user.next_move_dir_add + // If we're not movin anywhere, we aren't movin anywhere + // Safe because nothing adds to movement_dir after this moment + if(!movement_dir) + // No input == our removal would have done nothing + // So we can safely forget about it + user.next_move_dir_sub = NONE + return FALSE + if(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) - user?.Move(get_step(src, movement_dir), movement_dir) + user.Move(get_step(src, movement_dir), movement_dir) + +/client/proc/calculate_move_dir() + var/movement_dir = NONE + for(var/_key in keys_held) + movement_dir |= movement_keys[_key] + intended_direction = movement_dir diff --git a/code/modules/keybindings/bindings_client.dm b/code/modules/keybindings/bindings_client.dm index f00969509aa2a..6bdc27cf3271e 100644 --- a/code/modules/keybindings/bindings_client.dm +++ b/code/modules/keybindings/bindings_client.dm @@ -43,8 +43,10 @@ //the time a key was pressed isn't actually used anywhere (as of 2019-9-10) but this allows easier access usage/checking keys_held[_key] = world.time var/movement = movement_keys[_key] - if(!(next_move_dir_sub & movement) && !keys_held["Ctrl"]) - next_move_dir_add |= movement + if(movement) + calculate_move_dir() + if(!keys_held["Ctrl"] && !(next_move_dir_sub & movement)) + next_move_dir_add |= movement // Client-level keybindings are ones anyone should be able to do at any time // Things like taking screenshots, hitting tab, and adminhelps. @@ -86,8 +88,10 @@ keys_held -= _key var/movement = movement_keys[_key] - if(!(next_move_dir_add & movement)) - next_move_dir_sub |= movement + if(movement) + calculate_move_dir() + if(!keys_held["Ctrl"] && !(next_move_dir_add & movement)) + next_move_dir_sub |= movement // We don't do full key for release, because for mod keys you // can hold different keys and releasing any should be handled by the key binding specifically diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index 178a83ab4f69b..bfeade60f5d96 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -65,8 +65,8 @@ /client/Move(atom/newloc, direction, glide_size_override) if(world.time < move_delay) //do not move anything ahead of this check please return FALSE - next_move_dir_add = 0 - next_move_dir_sub = 0 + next_move_dir_add = NONE + next_move_dir_sub = NONE var/old_move_delay = move_delay move_delay = world.time + world.tick_lag //this is here because Move() can now be called mutiple times per tick if(!mob?.loc)