Skip to content

Commit

Permalink
z movement
Browse files Browse the repository at this point in the history
  • Loading branch information
tichys committed Dec 31, 2023
1 parent 598ded5 commit e32fb57
Show file tree
Hide file tree
Showing 6 changed files with 171 additions and 20 deletions.
68 changes: 68 additions & 0 deletions code/__DEFINES/movement.dm
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,71 @@ GLOBAL_VAR_INIT(glide_size_multiplier, 1.0)
/// The whole result is then clamped to within the range above.
/// Not very readable but it works
#define DELAY_TO_GLIDE_SIZE(delay) (clamp(((32 / max((delay) / world.tick_lag, 1)) * GLOB.glide_size_multiplier), MIN_GLIDE_SIZE, MAX_GLIDE_SIZE))

///Similar to DELAY_TO_GLIDE_SIZE, except without the clamping, and it supports piping in an unrelated scalar
#define MOVEMENT_ADJUSTED_GLIDE_SIZE(delay, movement_disparity) (world.icon_size / ((delay) / world.tick_lag) * movement_disparity * GLOB.glide_size_multiplier)

//Movement loop priority. Only one loop can run at a time, this dictates that
// Higher numbers beat lower numbers
///Standard, go lower then this if you want to override, higher otherwise
#define MOVEMENT_DEFAULT_PRIORITY 10
///Very few things should override this
#define MOVEMENT_SPACE_PRIORITY 100
///Higher then the heavens
#define MOVEMENT_ABOVE_SPACE_PRIORITY (MOVEMENT_SPACE_PRIORITY + 1)

//Movement loop flags
///Should the loop act immediately following its addition?
#define MOVEMENT_LOOP_START_FAST (1<<0)
///Do we not use the priority system?
#define MOVEMENT_LOOP_IGNORE_PRIORITY (1<<1)
///Should we override the loop's glide?
#define MOVEMENT_LOOP_IGNORE_GLIDE (1<<2)

//Index defines for movement bucket data packets
#define MOVEMENT_BUCKET_TIME 1
#define MOVEMENT_BUCKET_LIST 2

/**
* currently_z_moving defines. Higher numbers mean higher priority.
* This one is for falling down open space from stuff such as deleted tile, pit grate...
*/
#define CURRENTLY_Z_FALLING 1
/// currently_z_moving is set to this in zMove() if 0.
#define CURRENTLY_Z_MOVING_GENERIC 2
/// This one is for falling down open space from movement.
#define CURRENTLY_Z_FALLING_FROM_MOVE 3
/// This one is for going upstairs.
#define CURRENTLY_Z_ASCENDING 4

/// Used when the grip on a pulled object shouldn't be broken.
#define FALL_RETAIN_PULL (1<<3)

/// Runs check_pulling() by the end of [/atom/movable/proc/zMove] for every movable that's pulling something. Should be kept enabled unless you know what you are doing.
#define ZMOVE_CHECK_PULLING (1<<0)
/// Checks if pulledby is nearby. if not, stop being pulled.
#define ZMOVE_CHECK_PULLEDBY (1<<1)
/// flags for different checks done in [/atom/movable/proc/can_z_move]. Should be self-explainatory.
#define ZMOVE_FALL_CHECKS (1<<2)
#define ZMOVE_CAN_FLY_CHECKS (1<<3)
#define ZMOVE_INCAPACITATED_CHECKS (1<<4)
/// Doesn't call zPassIn() and zPassOut()
#define ZMOVE_IGNORE_OBSTACLES (1<<5)
/// Gives players chat feedbacks if they're unable to move through z levels.
#define ZMOVE_FEEDBACK (1<<6)
/// Whether we check the movable (if it exists) the living mob is buckled on or not.
#define ZMOVE_ALLOW_BUCKLED (1<<7)
/// If the movable is actually ventcrawling vertically.
#define ZMOVE_VENTCRAWLING (1<<8)
#define TRAIT_MOVE_VENTCRAWLING "move_ventcrawling"
/// Includes movables that're either pulled by the source or mobs buckled to it in the list of moving movables.
#define ZMOVE_INCLUDE_PULLED (1<<9)

#define ZMOVE_CHECK_PULLS (ZMOVE_CHECK_PULLING|ZMOVE_CHECK_PULLEDBY)

/// Flags used in "Move Upwards" and "Move Downwards" verbs.
#define ZMOVE_FLIGHT_FLAGS (ZMOVE_CAN_FLY_CHECKS|ZMOVE_INCAPACITATED_CHECKS|ZMOVE_CHECK_PULLS|ZMOVE_ALLOW_BUCKLED)
/// Used when walking upstairs
#define ZMOVE_STAIRS_FLAGS (ZMOVE_CHECK_PULLEDBY|ZMOVE_ALLOW_BUCKLED)
/// Used for falling down open space.
#define ZMOVE_FALL_FLAGS (ZMOVE_FALL_CHECKS|ZMOVE_ALLOW_BUCKLED)
99 changes: 99 additions & 0 deletions code/game/atoms_movable.dm
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@
var/list/affected_dynamic_lights
///Highest-intensity light affecting us, which determines our visibility.
var/affecting_dynamic_lumi = 0
///is the mob currently ascending or descending through z levels?
var/currently_z_moving


/atom/movable/Initialize(mapload)
Expand Down Expand Up @@ -90,6 +92,103 @@
return
SSvis_overlays.add_vis_overlay(src, icon, icon_state, EMISSIVE_BLOCKER_LAYER, EMISSIVE_BLOCKER_PLANE, dir)

/*
* The core multi-z movement proc. Used to move a movable through z levels.
* If target is null, it'll be determined by the can_z_move proc, which can potentially return null if
* conditions aren't met (see z_move_flags defines in __DEFINES/movement.dm for info) or if dir isn't set.
* Bear in mind you don't need to set both target and dir when calling this proc, but at least one or two.
* This will set the currently_z_moving to CURRENTLY_Z_MOVING_GENERIC if unset, and then clear it after
* Forcemove().
*
*
* Args:
* * dir: the direction to go, UP or DOWN, only relevant if target is null.
* * target: The target turf to move the src to. Set by can_z_move() if null.
* * z_move_flags: bitflags used for various checks in both this proc and can_z_move(). See __DEFINES/movement.dm.
*/
/atom/movable/proc/zMove(dir, turf/target, z_move_flags = ZMOVE_FLIGHT_FLAGS)
if(!target)
target = canZMove(dir, get_turf(src), null, z_move_flags)
if(!target)
set_currently_z_moving(FALSE, TRUE)
return FALSE

var/list/moving_movs = get_z_move_affected(z_move_flags)

for(var/atom/movable/movable as anything in moving_movs)
movable.currently_z_moving = currently_z_moving || CURRENTLY_Z_MOVING_GENERIC
movable.forceMove(target)
movable.set_currently_z_moving(FALSE, TRUE)
// This is run after ALL movables have been moved, so pulls don't get broken unless they are actually out of range.
if(z_move_flags & ZMOVE_CHECK_PULLS)
for(var/atom/movable/moved_mov as anything in moving_movs)
if(z_move_flags & ZMOVE_CHECK_PULLEDBY && moved_mov.pulledby && (moved_mov.z != moved_mov.pulledby.z || get_dist(moved_mov, moved_mov.pulledby) > 1))
moved_mov.pulledby.stop_pulling()
if(z_move_flags & ZMOVE_CHECK_PULLING)
moved_mov.check_pulling(TRUE)
return TRUE

/// Sets the currently_z_moving variable to a new value. Used to allow some zMovement sources to have precedence over others.
/atom/movable/proc/set_currently_z_moving(new_z_moving_value, forced = FALSE)
if(forced)
currently_z_moving = new_z_moving_value
return TRUE
var/old_z_moving_value = currently_z_moving
currently_z_moving = max(currently_z_moving, new_z_moving_value)
return currently_z_moving > old_z_moving_value
/// Returns a list of movables that should also be affected when src moves through zlevels, and src.
/atom/movable/proc/get_z_move_affected(z_move_flags)
. = list(src)
if(buckled_mobs)
. |= buckled_mobs
if(!(z_move_flags & ZMOVE_INCLUDE_PULLED))
return
for(var/mob/living/buckled as anything in buckled_mobs)
if(buckled.pulling)
. |= buckled.pulling
if(pulling)
. |= pulling

/**
* Checks if the destination turf is elegible for z movement from the start turf to a given direction and returns it if so.
* Args:
* * direction: the direction to go, UP or DOWN, only relevant if target is null.
* * start: Each destination has a starting point on the other end. This is it. Most of the times the location of the source.
* * z_move_flags: bitflags used for various checks. See __DEFINES/movement.dm.
* * rider: A living mob in control of the movable. Only non-null when a mob is riding a vehicle through z-levels.
*/
/atom/movable/proc/canZMove(direction, turf/start, turf/destination, z_move_flags = ZMOVE_FLIGHT_FLAGS, mob/living/rider)
if(!start)
start = get_turf(src)
if(!start)
return FALSE
if(!direction)
if(!destination)
return FALSE
direction = get_dir_multiz(start, destination)
if(direction != UP && direction != DOWN)
return FALSE
if(!destination)
destination = get_step_multiz(start, direction)
if(!destination)
if(z_move_flags & ZMOVE_FEEDBACK)
to_chat(rider || src, span_warning("There's nowhere to go in that direction!"))
return FALSE
if(z_move_flags & ZMOVE_FALL_CHECKS && (throwing || (movement_type & (FLYING|FLOATING)) || !has_gravity(start)))
return FALSE
if(z_move_flags & ZMOVE_CAN_FLY_CHECKS && !(movement_type & (FLYING|FLOATING)) && has_gravity(start))
if(z_move_flags & ZMOVE_FEEDBACK)
if(rider)
to_chat(rider, span_warning("[src] is is not capable of flight."))
else
to_chat(src, span_warning("You are not Superman."))
return FALSE
if(!(z_move_flags & ZMOVE_IGNORE_OBSTACLES) && !(start.zPassOut(src, direction, destination) && destination.zPassIn(src, direction, start)))
if(z_move_flags & ZMOVE_FEEDBACK)
to_chat(rider || src, span_warning("You couldn't move there!"))
return FALSE
return destination //used by some child types checks and zMove()

/atom/movable/proc/can_zFall(turf/source, levels = 1, turf/target, direction)
if(!direction)
direction = DOWN
Expand Down
16 changes: 0 additions & 16 deletions code/modules/mob/mob_movement.dm
Original file line number Diff line number Diff line change
Expand Up @@ -434,20 +434,4 @@
if(zMove(DOWN, TRUE))
to_chat(src, "<span class='notice'>You move down.</span>")

/mob/proc/zMove(dir, feedback = FALSE)
if(dir != UP && dir != DOWN)
return FALSE
var/turf/target = get_step_multiz(src, dir)
if(!target)
if(feedback)
to_chat(src, "<span class='warning'>There's nothing in that direction!</span>")
return FALSE
if(!canZMove(dir, target))
if(feedback)
to_chat(src, "<span class='warning'>You couldn't move there!</span>")
return FALSE
forceMove(target)
return TRUE

/mob/proc/canZMove(direction, turf/target)
return FALSE
4 changes: 2 additions & 2 deletions tgui/public/tgui-panel.bundle.css

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion tgui/public/tgui-panel.bundle.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion tgui/public/tgui.bundle.js

Large diffs are not rendered by default.

0 comments on commit e32fb57

Please sign in to comment.