mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-20 12:35:33 +01:00
[MIRROR] multiz movement refactor redux [MDB IGNORE] (#9925)
* multiz movement refactor redux (#62132) * multiz movement refactor redux Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com>
This commit is contained in:
@@ -72,3 +72,8 @@
|
||||
#define COMSIG_MOVABLE_CHANGE_DUCT_LAYER "movable_change_duct_layer"
|
||||
///Called when a movable is teleported from `do_teleport()`: (destination, channel)
|
||||
#define COMSIG_MOVABLE_TELEPORTED "movable_teleported"
|
||||
|
||||
/// from /mob/living/can_z_move, sent to whatever the mob is buckled to. Only ridable movables should be ridden up or down btw.
|
||||
#define COMSIG_BUCKLED_CAN_Z_MOVE "ridden_pre_can_z_move"
|
||||
#define COMPONENT_RIDDEN_STOP_Z_MOVE 1
|
||||
#define COMPONENT_RIDDEN_ALLOW_Z_MOVE 2
|
||||
|
||||
@@ -489,11 +489,6 @@ GLOBAL_LIST_INIT(pda_styles, sort_list(list(MONO, VT, ORBITRON, SHARE)))
|
||||
//Misc text define. Does 4 spaces. Used as a makeshift tabulator.
|
||||
#define FOURSPACES " "
|
||||
|
||||
// possible bitflag return values of intercept_zImpact(atom/movable/AM, levels = 1) calls
|
||||
#define FALL_INTERCEPTED (1<<0) //Stops the movable from falling further and crashing on the ground
|
||||
#define FALL_NO_MESSAGE (1<<1) //Used to suppress the "[A] falls through [old_turf]" messages where it'd make little sense at all, like going downstairs.
|
||||
#define FALL_STOP_INTERCEPTING (1<<2) //Used in situations where halting the whole "intercept" loop would be better, like supermatter dusting (and thus deleting) the atom.
|
||||
|
||||
|
||||
// Play time / EXP
|
||||
#define PLAYTIME_HARDCORE_RANDOM 120
|
||||
|
||||
@@ -14,3 +14,53 @@ 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))
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
||||
/// possible bitflag return values of [atom/proc/intercept_zImpact] calls
|
||||
/// Stops the movable from falling further and crashing on the ground. Example: stairs.
|
||||
#define FALL_INTERCEPTED (1<<0)
|
||||
/// Suppresses the "[movable] falls through [old_turf]" message because it'd make little sense in certain contexts like climbing stairs.
|
||||
#define FALL_NO_MESSAGE (1<<1)
|
||||
/// Used when the whole intercept_zImpact forvar loop should be stopped. For example: when someone falls into the supermatter and becomes dust.
|
||||
#define FALL_STOP_INTERCEPTING (1<<2)
|
||||
/// 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)
|
||||
/// 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)
|
||||
|
||||
@@ -195,10 +195,9 @@ SUBSYSTEM_DEF(throwing)
|
||||
if (callback)
|
||||
callback.Invoke()
|
||||
|
||||
if(!thrownthing.zfalling) // I don't think you can zfall while thrown but hey, just in case.
|
||||
if(!thrownthing.currently_z_moving) // I don't think you can zfall while thrown but hey, just in case.
|
||||
var/turf/T = get_turf(thrownthing)
|
||||
if(T && thrownthing.has_gravity(T))
|
||||
T.zFall(thrownthing)
|
||||
T?.zFall(thrownthing)
|
||||
|
||||
if(thrownthing)
|
||||
SEND_SIGNAL(thrownthing, COMSIG_MOVABLE_THROW_LANDED, src)
|
||||
|
||||
@@ -71,10 +71,8 @@
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
for(var/t in get_adjacent_open_turfs(living_guy))
|
||||
var/turf/the_turf = t
|
||||
|
||||
if(the_turf.zPassOut(living_guy, DOWN) && living_guy.can_zFall(the_turf))
|
||||
for(var/turf/the_turf as anything in get_adjacent_open_turfs(living_guy))
|
||||
if(the_turf.zPassOut(living_guy, DOWN) && living_guy.can_z_move(DOWN, the_turf, z_move_flags = ZMOVE_FALL_FLAGS))
|
||||
to_chat(living_guy, span_warning("A malevolent force guides you towards the edge..."))
|
||||
living_guy.throw_at(the_turf, 1, 10, force = MOVE_FORCE_EXTREMELY_STRONG)
|
||||
if(!permanent)
|
||||
|
||||
@@ -63,6 +63,7 @@
|
||||
RegisterSignal(parent, COMSIG_MOVABLE_BUCKLE, .proc/vehicle_mob_buckle)
|
||||
RegisterSignal(parent, COMSIG_MOVABLE_MOVED, .proc/vehicle_moved)
|
||||
RegisterSignal(parent, COMSIG_MOVABLE_BUMP, .proc/vehicle_bump)
|
||||
RegisterSignal(parent, COMSIG_BUCKLED_CAN_Z_MOVE, .proc/riding_can_z_move)
|
||||
|
||||
/**
|
||||
* This proc handles all of the proc calls to things like set_vehicle_dir_layer() that a type of riding datum needs to call on creation
|
||||
@@ -128,9 +129,12 @@
|
||||
|
||||
vehicle_moved(source, null, new_dir)
|
||||
|
||||
/// Check to see if we have all of the necessary bodyparts and not-falling-over statuses we need to stay onboard
|
||||
/datum/component/riding/proc/ride_check(mob/living/rider)
|
||||
return
|
||||
/**
|
||||
* Check to see if we have all of the necessary bodyparts and not-falling-over statuses we need to stay onboard.
|
||||
* If not and if consequences is TRUE, well, there'll be consequences.
|
||||
*/
|
||||
/datum/component/riding/proc/ride_check(mob/living/rider, consequences = TRUE)
|
||||
return TRUE
|
||||
|
||||
/datum/component/riding/proc/handle_vehicle_offsets(dir)
|
||||
var/atom/movable/AM = parent
|
||||
@@ -246,3 +250,8 @@
|
||||
else
|
||||
qdel(O)
|
||||
return TRUE
|
||||
|
||||
/// Extra checks before buckled.can_z_move can be called in mob/living/can_z_move()
|
||||
/datum/component/riding/proc/riding_can_z_move(atom/movable/movable_parent, direction, turf/start, turf/destination, z_move_flags, mob/living/rider)
|
||||
SIGNAL_HANDLER
|
||||
return COMPONENT_RIDDEN_ALLOW_Z_MOVE
|
||||
|
||||
@@ -47,21 +47,21 @@
|
||||
rider.log_message("started riding [living_parent]", LOG_ATTACK, color="pink")
|
||||
|
||||
// this applies to humans and most creatures, but is replaced again for cyborgs
|
||||
/datum/component/riding/creature/ride_check(mob/living/rider)
|
||||
/datum/component/riding/creature/ride_check(mob/living/rider, consequences = TRUE)
|
||||
. = TRUE
|
||||
var/mob/living/living_parent = parent
|
||||
|
||||
var/kick_us_off
|
||||
if(living_parent.body_position != STANDING_UP) // if we move while on the ground, the rider falls off
|
||||
kick_us_off = TRUE
|
||||
. = FALSE
|
||||
// for piggybacks and (redundant?) borg riding, check if the rider is stunned/restrained
|
||||
else if((ride_check_flags & RIDER_NEEDS_ARMS) && (HAS_TRAIT(rider, TRAIT_RESTRAINED) || rider.incapacitated(TRUE, TRUE)))
|
||||
kick_us_off = TRUE
|
||||
. = FALSE
|
||||
// for fireman carries, check if the ridden is stunned/restrained
|
||||
else if((ride_check_flags & CARRIER_NEEDS_ARM) && (HAS_TRAIT(living_parent, TRAIT_RESTRAINED) || living_parent.incapacitated(TRUE, TRUE)))
|
||||
kick_us_off = TRUE
|
||||
. = FALSE
|
||||
|
||||
if(!kick_us_off)
|
||||
return TRUE
|
||||
if(. || !consequences)
|
||||
return
|
||||
|
||||
rider.visible_message(span_warning("[rider] falls off of [living_parent]!"), \
|
||||
span_warning("You fall off of [living_parent]!"))
|
||||
@@ -158,6 +158,20 @@
|
||||
proc_holder.remove_ranged_ability()
|
||||
proc_holder.action.Unshare(rider)
|
||||
|
||||
/datum/component/riding/creature/riding_can_z_move(atom/movable/movable_parent, direction, turf/start, turf/destination, z_move_flags, mob/living/rider)
|
||||
if(!(z_move_flags & ZMOVE_CAN_FLY_CHECKS))
|
||||
return COMPONENT_RIDDEN_ALLOW_Z_MOVE
|
||||
if(!can_be_driven)
|
||||
if(z_move_flags & ZMOVE_FEEDBACK)
|
||||
to_chat(rider, "<span class='notice'>[movable_parent] cannot be driven around. Unbuckle from [movable_parent.p_them()] first.<span>")
|
||||
return COMPONENT_RIDDEN_STOP_Z_MOVE
|
||||
if(!ride_check(rider, FALSE))
|
||||
if(z_move_flags & ZMOVE_FEEDBACK)
|
||||
to_chat(rider, "<span class='warning'>You're unable to ride [movable_parent] right now!</span>")
|
||||
return COMPONENT_RIDDEN_STOP_Z_MOVE
|
||||
return COMPONENT_RIDDEN_ALLOW_Z_MOVE
|
||||
|
||||
|
||||
///////Yes, I said humans. No, this won't end well...//////////
|
||||
/datum/component/riding/creature/human
|
||||
can_be_driven = FALSE
|
||||
@@ -259,12 +273,12 @@
|
||||
/datum/component/riding/creature/cyborg
|
||||
can_be_driven = FALSE
|
||||
|
||||
/datum/component/riding/creature/cyborg/ride_check(mob/living/user)
|
||||
/datum/component/riding/creature/cyborg/ride_check(mob/living/user, consequences = TRUE)
|
||||
var/mob/living/silicon/robot/robot_parent = parent
|
||||
if(!iscarbon(user))
|
||||
return
|
||||
var/mob/living/carbon/carbonuser = user
|
||||
if(!carbonuser.usable_hands)
|
||||
return TRUE
|
||||
. = user.usable_hands
|
||||
if(!. && consequences)
|
||||
Unbuckle(user)
|
||||
to_chat(user, span_warning("You can't grab onto [robot_parent] with no hands!"))
|
||||
|
||||
|
||||
@@ -9,6 +9,29 @@
|
||||
. = ..()
|
||||
RegisterSignal(parent, COMSIG_RIDDEN_DRIVER_MOVE, .proc/driver_move)
|
||||
|
||||
/datum/component/riding/vehicle/riding_can_z_move(atom/movable/movable_parent, direction, turf/start, turf/destination, z_move_flags, mob/living/rider)
|
||||
if(!(z_move_flags & ZMOVE_CAN_FLY_CHECKS))
|
||||
return COMPONENT_RIDDEN_ALLOW_Z_MOVE
|
||||
|
||||
if(!keycheck(rider))
|
||||
if(z_move_flags & ZMOVE_FEEDBACK)
|
||||
to_chat(rider, "<span class='warning'>[movable_parent] has no key inserted!</span>")
|
||||
return COMPONENT_RIDDEN_STOP_Z_MOVE
|
||||
if(HAS_TRAIT(rider, TRAIT_INCAPACITATED))
|
||||
if(z_move_flags & ZMOVE_FEEDBACK)
|
||||
to_chat(rider, "<span class='warning'>You cannot operate [movable_parent] right now!</span>")
|
||||
return COMPONENT_RIDDEN_STOP_Z_MOVE
|
||||
if(ride_check_flags & RIDER_NEEDS_LEGS && HAS_TRAIT(rider, TRAIT_FLOORED))
|
||||
if(z_move_flags & ZMOVE_FEEDBACK)
|
||||
to_chat(rider, "<span class='warning'>You can't seem to manage that while unable to stand up enough to move [movable_parent]...</span>")
|
||||
return COMPONENT_RIDDEN_STOP_Z_MOVE
|
||||
if(ride_check_flags & RIDER_NEEDS_ARMS && HAS_TRAIT(rider, TRAIT_HANDS_BLOCKED))
|
||||
if(z_move_flags & ZMOVE_FEEDBACK)
|
||||
to_chat(rider, "<span class='warning'>You can't seem to hold onto [movable_parent] to move it...</span>")
|
||||
return COMPONENT_RIDDEN_STOP_Z_MOVE
|
||||
|
||||
return COMPONENT_RIDDEN_ALLOW_Z_MOVE
|
||||
|
||||
/datum/component/riding/vehicle/driver_move(atom/movable/movable_parent, mob/living/user, direction)
|
||||
if(!COOLDOWN_FINISHED(src, vehicle_move_cooldown))
|
||||
return COMPONENT_DRIVER_BLOCK_MOVE
|
||||
|
||||
@@ -69,6 +69,9 @@
|
||||
source.movement_type &= ~flag
|
||||
if((old_state & (FLOATING|FLYING)) && !(source.movement_type & (FLOATING|FLYING)))
|
||||
stop_floating(source)
|
||||
var/turf/pitfall = source.loc //Things that don't fly fall in open space.
|
||||
if(istype(pitfall))
|
||||
pitfall.zFall(source)
|
||||
SEND_SIGNAL(source, COMSIG_MOVETYPE_FLAG_DISABLED, flag, old_state)
|
||||
|
||||
/// Called when the TRAIT_NO_FLOATING_ANIM trait is added to the movable. Stops it from bobbing up and down.
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
#define HOLORECORD_MAX_LENGTH 200
|
||||
|
||||
/mob/camera/ai_eye/remote/holo/setLoc()
|
||||
/mob/camera/ai_eye/remote/holo/setLoc(turf/destination, force_update = FALSE)
|
||||
. = ..()
|
||||
var/obj/machinery/holopad/H = origin
|
||||
H?.move_hologram(eye_user, loc)
|
||||
|
||||
+2
-2
@@ -1785,8 +1785,8 @@
|
||||
filter_data = null
|
||||
filters = null
|
||||
|
||||
/atom/proc/intercept_zImpact(atom/movable/hitting_atom, levels = 1)
|
||||
. |= SEND_SIGNAL(src, COMSIG_ATOM_INTERCEPT_Z_FALL, hitting_atom, levels)
|
||||
/atom/proc/intercept_zImpact(list/falling_movables, levels = 1)
|
||||
. |= SEND_SIGNAL(src, COMSIG_ATOM_INTERCEPT_Z_FALL, falling_movables, levels)
|
||||
|
||||
/// Sets the custom materials for an item.
|
||||
/atom/proc/set_custom_materials(list/materials, multiplier = 1)
|
||||
|
||||
+135
-47
@@ -56,9 +56,9 @@
|
||||
var/grab_state = 0
|
||||
var/throwforce = 0
|
||||
var/datum/component/orbiter/orbiting
|
||||
var/can_be_z_moved = TRUE
|
||||
|
||||
var/zfalling = FALSE
|
||||
///is the mob currently ascending or descending through z levels?
|
||||
var/currently_z_moving
|
||||
|
||||
/// Either FALSE, [EMISSIVE_BLOCK_GENERIC], or [EMISSIVE_BLOCK_UNIQUE]
|
||||
var/blocks_emissive = FALSE
|
||||
@@ -167,20 +167,9 @@
|
||||
if(emissive_block)
|
||||
. += emissive_block
|
||||
|
||||
/atom/movable/proc/can_zFall(turf/source, levels = 1, turf/target, direction)
|
||||
if(!direction)
|
||||
direction = DOWN
|
||||
if(!source)
|
||||
source = get_turf(src)
|
||||
if(!source)
|
||||
return FALSE
|
||||
if(!target)
|
||||
target = get_step_multiz(source, direction)
|
||||
if(!target)
|
||||
return FALSE
|
||||
return !(movement_type & FLYING) && has_gravity(source) && !throwing
|
||||
|
||||
/atom/movable/proc/onZImpact(turf/impacted_turf, levels)
|
||||
/atom/movable/proc/onZImpact(turf/impacted_turf, levels, message = TRUE)
|
||||
if(message)
|
||||
visible_message("<span class='danger'>[src] crashes into [impacted_turf]!</span>")
|
||||
var/atom/highest = impacted_turf
|
||||
for(var/atom/hurt_atom as anything in impacted_turf.contents)
|
||||
if(!hurt_atom.density)
|
||||
@@ -191,23 +180,94 @@
|
||||
INVOKE_ASYNC(src, .proc/SpinAnimation, 5, 2)
|
||||
return TRUE
|
||||
|
||||
//For physical constraints to travelling up/down.
|
||||
/atom/movable/proc/can_zTravel(turf/destination, direction)
|
||||
var/turf/current_turf = get_turf(src)
|
||||
if(!current_turf)
|
||||
return FALSE
|
||||
/*
|
||||
* 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 = can_z_move(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
|
||||
|
||||
/// 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/can_z_move(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(current_turf, destination)
|
||||
direction = get_dir_multiz(start, destination)
|
||||
if(direction != UP && direction != DOWN)
|
||||
return FALSE
|
||||
if(!destination)
|
||||
destination = get_step_multiz(src, direction)
|
||||
destination = get_step_multiz(start, direction)
|
||||
if(!destination)
|
||||
if(z_move_flags & ZMOVE_FEEDBACK)
|
||||
to_chat(rider || src, "<span class='warning'>There's nowhere to go in that direction!</span>")
|
||||
return FALSE
|
||||
return current_turf.zPassOut(src, direction, destination) && destination.zPassIn(src, direction, current_turf)
|
||||
|
||||
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 class='notice'>[src] is is not capable of flight.<span>")
|
||||
else
|
||||
to_chat(src, "<span class='notice'>You are not Superman.<span>")
|
||||
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 class='warning'>You couldn't move there!</span>")
|
||||
return FALSE
|
||||
return destination //used by some child types checks and zMove()
|
||||
|
||||
/atom/movable/vv_edit_var(var_name, var_value)
|
||||
var/static/list/banned_edits = list("step_x" = TRUE, "step_y" = TRUE, "step_size" = TRUE, "bounds" = TRUE)
|
||||
@@ -336,23 +396,22 @@
|
||||
var/mob/living/pulled_mob = moving_atom
|
||||
set_pull_offsets(pulled_mob, grab_state)
|
||||
|
||||
/atom/movable/proc/check_pulling()
|
||||
/**
|
||||
* Checks if the pulling and pulledby should be stopped because they're out of reach.
|
||||
* If z_allowed is TRUE, the z level of the pulling will be ignored.This is to allow things to be dragged up and down stairs.
|
||||
*/
|
||||
/atom/movable/proc/check_pulling(only_pulling = FALSE, z_allowed = FALSE)
|
||||
if(pulling)
|
||||
var/atom/movable/pullee = pulling
|
||||
if(pullee && get_dist(src, pullee) > 1)
|
||||
if(get_dist(src, pulling) > 1 || (z != pulling.z && !z_allowed))
|
||||
stop_pulling()
|
||||
return
|
||||
if(!isturf(loc))
|
||||
else if(!isturf(loc))
|
||||
stop_pulling()
|
||||
return
|
||||
if(pullee && !isturf(pullee.loc) && pullee.loc != loc) //to be removed once all code that changes an object's loc uses forceMove().
|
||||
log_game("DEBUG:[src]'s pull on [pullee] wasn't broken despite [pullee] being in [pullee.loc]. Pull stopped manually.")
|
||||
else if(pulling && !isturf(pulling.loc) && pulling.loc != loc) //to be removed once all code that changes an object's loc uses forceMove().
|
||||
log_game("DEBUG:[src]'s pull on [pulling] wasn't broken despite [pulling] being in [pulling.loc]. Pull stopped manually.")
|
||||
stop_pulling()
|
||||
return
|
||||
if(pulling.anchored || pulling.move_resist > move_force)
|
||||
else if(pulling.anchored || pulling.move_resist > move_force)
|
||||
stop_pulling()
|
||||
return
|
||||
if(pulledby && moving_diagonally != FIRST_DIAG_STEP && get_dist(src, pulledby) > 1) //separated from our puller and not in the middle of a diagonal move.
|
||||
if(!only_pulling && pulledby && moving_diagonally != FIRST_DIAG_STEP && (get_dist(src, pulledby) > 1 || z != pulledby.z)) //separated from our puller and not in the middle of a diagonal move.
|
||||
pulledby.stop_pulling()
|
||||
|
||||
|
||||
@@ -457,7 +516,7 @@
|
||||
var/atom/movable/pullee = pulling
|
||||
var/turf/current_turf = loc
|
||||
if(!moving_from_pull)
|
||||
check_pulling()
|
||||
check_pulling(z_allowed = TRUE)
|
||||
if(!loc || !newloc)
|
||||
return FALSE
|
||||
var/atom/oldloc = loc
|
||||
@@ -524,18 +583,26 @@
|
||||
|
||||
if(!loc || (loc == oldloc && oldloc != newloc))
|
||||
last_move = 0
|
||||
set_currently_z_moving(FALSE, TRUE)
|
||||
return
|
||||
|
||||
if(. && pulling && pulling == pullee && pulling != moving_from_pull) //we were pulling a thing and didn't lose it during our move.
|
||||
if(pulling.anchored)
|
||||
stop_pulling()
|
||||
else
|
||||
var/pull_dir = get_dir(src, pulling)
|
||||
//puller and pullee more than one tile away or in diagonal position and whatever the pullee is pulling isn't already moving from a pull as it'll most likely result in an infinite loop a la ouroborus.
|
||||
if(!pulling.pulling?.moving_from_pull && (get_dist(src, pulling) > 1 || (moving_diagonally != SECOND_DIAG_STEP && ((pull_dir - 1) & pull_dir))))
|
||||
pulling.moving_from_pull = src
|
||||
pulling.Move(current_turf, get_dir(pulling, current_turf), glide_size) //the pullee tries to reach our previous position
|
||||
pulling.moving_from_pull = null
|
||||
if(!pulling.pulling?.moving_from_pull)
|
||||
var/pull_dir = get_dir(pulling, src)
|
||||
var/target_turf = current_turf
|
||||
|
||||
// Pulling things down/up stairs. zMove() has flags for check_pulling and stop_pulling calls.
|
||||
// You may wonder why we're not just forcemoving the pulling movable and regrabbing it.
|
||||
// The answer is simple. forcemoving and regrabbing is ugly and breaks conga lines.
|
||||
if(pulling.z != z)
|
||||
target_turf = get_step(pulling, get_dir(pulling, current_turf))
|
||||
|
||||
if(target_turf != current_turf || (moving_diagonally != SECOND_DIAG_STEP && ISDIAGONALDIR(pull_dir)) || get_dist(src, pulling) > 1)
|
||||
pulling.move_from_pull(src, target_turf, glide_size)
|
||||
check_pulling()
|
||||
|
||||
|
||||
@@ -549,8 +616,20 @@
|
||||
if(set_dir_on_move)
|
||||
setDir(direct)
|
||||
if(. && has_buckled_mobs() && !handle_buckled_mob_movement(loc, direct, glide_size_override)) //movement failed due to buckled mob(s)
|
||||
return FALSE
|
||||
. = FALSE
|
||||
|
||||
if(currently_z_moving)
|
||||
if(. && loc == newloc)
|
||||
var/turf/pitfall = get_turf(src)
|
||||
pitfall.zFall(src, falling_from_move = TRUE)
|
||||
else
|
||||
set_currently_z_moving(FALSE, TRUE)
|
||||
|
||||
/// Called when src is being moved to a target turf because another movable (puller) is moving around.
|
||||
/atom/movable/proc/move_from_pull(atom/movable/puller, turf/target_turf, glide_size_override)
|
||||
moving_from_pull = puller
|
||||
Move(target_turf, get_dir(src, target_turf), glide_size_override)
|
||||
moving_from_pull = null
|
||||
|
||||
/**
|
||||
* Called after a successful Move(). By this point, we've already moved.
|
||||
@@ -586,7 +665,6 @@
|
||||
|
||||
return TRUE
|
||||
|
||||
|
||||
// Make sure you know what you're doing if you call this, this is intended to only be called by byond directly.
|
||||
// You probably want CanPass()
|
||||
/atom/movable/Cross(atom/movable/crossed_atom)
|
||||
@@ -704,6 +782,15 @@
|
||||
anchored = anchorvalue
|
||||
SEND_SIGNAL(src, COMSIG_MOVABLE_SET_ANCHORED, anchorvalue)
|
||||
|
||||
/// 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
|
||||
|
||||
/atom/movable/proc/forceMove(atom/destination)
|
||||
. = FALSE
|
||||
if(destination)
|
||||
@@ -719,7 +806,8 @@
|
||||
move_stacks++
|
||||
var/atom/oldloc = loc
|
||||
if(destination)
|
||||
if(pulledby)
|
||||
///zMove already handles whether a pull from another movable should be broken.
|
||||
if(pulledby && !currently_z_moving)
|
||||
pulledby.stop_pulling()
|
||||
var/same_loc = oldloc == destination
|
||||
var/area/old_area = get_area(oldloc)
|
||||
@@ -924,7 +1012,7 @@
|
||||
|
||||
/atom/movable/proc/handle_buckled_mob_movement(newloc, direct, glide_size_override)
|
||||
for(var/mob/living/buckled_mob as anything in buckled_mobs)
|
||||
if(!buckled_mob.Move(newloc, direct, glide_size_override))
|
||||
if(buckled_mob.loc != newloc && !buckled_mob.Move(newloc, direct, glide_size_override))
|
||||
Move(buckled_mob.loc, direct)
|
||||
last_move = buckled_mob.last_move
|
||||
inertia_dir = last_move
|
||||
|
||||
@@ -209,13 +209,7 @@
|
||||
return eye_user.client
|
||||
return null
|
||||
|
||||
/mob/camera/ai_eye/remote/xenobio/canZMove(direction, turf/target)
|
||||
var/area/new_area = get_area(target)
|
||||
if(new_area && new_area.name == allowed_area || new_area && (new_area.area_flags & XENOBIOLOGY_COMPATIBLE))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/mob/camera/ai_eye/remote/setLoc(destination)
|
||||
/mob/camera/ai_eye/remote/setLoc(turf/destination, force_update = FALSE)
|
||||
if(eye_user)
|
||||
destination = get_turf(destination)
|
||||
if (destination)
|
||||
@@ -315,7 +309,7 @@
|
||||
return
|
||||
var/mob/living/user_mob = target
|
||||
var/mob/camera/ai_eye/remote/remote_eye = user_mob.remote_control
|
||||
if(remote_eye.zMove(UP, FALSE))
|
||||
if(remote_eye.zMove(UP))
|
||||
to_chat(user_mob, span_notice("You move upwards."))
|
||||
else
|
||||
to_chat(user_mob, span_notice("You couldn't move upwards!"))
|
||||
@@ -330,7 +324,7 @@
|
||||
return
|
||||
var/mob/living/user_mob = target
|
||||
var/mob/camera/ai_eye/remote/remote_eye = user_mob.remote_control
|
||||
if(remote_eye.zMove(DOWN, FALSE))
|
||||
if(remote_eye.zMove(DOWN))
|
||||
to_chat(user_mob, span_notice("You move downwards."))
|
||||
else
|
||||
to_chat(user_mob, span_notice("You couldn't move downwards!"))
|
||||
|
||||
@@ -138,7 +138,7 @@
|
||||
* buckled_mob - The mob to be unbuckled
|
||||
* force - TRUE if we should ignore buckled_mob.can_buckle_to
|
||||
*/
|
||||
/atom/movable/proc/unbuckle_mob(mob/living/buckled_mob, force = FALSE)
|
||||
/atom/movable/proc/unbuckle_mob(mob/living/buckled_mob, force = FALSE, can_fall = TRUE)
|
||||
if(!isliving(buckled_mob))
|
||||
CRASH("Non-living [buckled_mob] thing called unbuckle_mob() for source.")
|
||||
if(buckled_mob.buckled != src)
|
||||
@@ -157,12 +157,17 @@
|
||||
UnregisterSignal(src, COMSIG_MOVABLE_SET_ANCHORED)
|
||||
SEND_SIGNAL(src, COMSIG_MOVABLE_UNBUCKLE, buckled_mob, force)
|
||||
|
||||
var/turf/location = buckled_mob.loc
|
||||
if(istype(location) && !buckled_mob.zfalling)
|
||||
location.zFall(buckled_mob)
|
||||
if(can_fall)
|
||||
var/turf/location = buckled_mob.loc
|
||||
if(istype(location) && !buckled_mob.currently_z_moving)
|
||||
location.zFall(buckled_mob)
|
||||
|
||||
post_unbuckle_mob(.)
|
||||
|
||||
if(!QDELETED(buckled_mob) && !buckled_mob.currently_z_moving && isturf(buckled_mob.loc)) // In the case they unbuckled to a flying movable midflight.
|
||||
var/turf/pitfall = buckled_mob.loc
|
||||
pitfall?.zFall(buckled_mob)
|
||||
|
||||
/atom/movable/proc/on_set_anchored(atom/movable/source, anchorvalue)
|
||||
SIGNAL_HANDLER
|
||||
for(var/_buckled_mob in buckled_mobs)
|
||||
|
||||
@@ -93,7 +93,7 @@
|
||||
/obj/item/storage/box/mime/Moved(oldLoc, dir)
|
||||
if (iscarbon(oldLoc))
|
||||
alpha = 0
|
||||
..()
|
||||
return ..()
|
||||
|
||||
//Disk boxes
|
||||
|
||||
|
||||
@@ -164,7 +164,7 @@
|
||||
if(..())
|
||||
buckled_mob.pixel_y += 13
|
||||
|
||||
/obj/structure/bonfire/unbuckle_mob(mob/living/buckled_mob, force=FALSE)
|
||||
/obj/structure/bonfire/unbuckle_mob(mob/living/buckled_mob, force = FALSE, can_fall = TRUE)
|
||||
if(..())
|
||||
buckled_mob.pixel_y -= 13
|
||||
|
||||
|
||||
@@ -118,7 +118,7 @@
|
||||
return INITIALIZE_HINT_QDEL
|
||||
return ..()
|
||||
|
||||
/mob/camera/ai_eye/remote/base_construction/setLoc(destination)
|
||||
/mob/camera/ai_eye/remote/base_construction/setLoc(turf/destination, force_update = FALSE)
|
||||
var/area/curr_area = get_area(destination)
|
||||
//Only move if we're in the allowed area. If no allowed area is defined, then we're free to move wherever.
|
||||
if(!linked_console.allowed_area || istype(curr_area, linked_console.allowed_area))
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
|
||||
//BUCKLE HOOKS
|
||||
|
||||
/obj/machinery/deployable_turret/unbuckle_mob(mob/living/buckled_mob,force = FALSE)
|
||||
/obj/machinery/deployable_turret/unbuckle_mob(mob/living/buckled_mob, force = FALSE, can_fall = TRUE)
|
||||
playsound(src,'sound/mecha/mechmove01.ogg', 50, TRUE)
|
||||
for(var/obj/item/I in buckled_mob.held_items)
|
||||
if(istype(I, /obj/item/gun_control))
|
||||
|
||||
@@ -77,21 +77,9 @@
|
||||
return
|
||||
show_fluff_message(going_up, user)
|
||||
|
||||
|
||||
var/turf/T = get_turf(ladder)
|
||||
var/atom/movable/AM
|
||||
if(user.pulling)
|
||||
AM = user.pulling
|
||||
AM.forceMove(T)
|
||||
user.forceMove(T)
|
||||
if(AM)
|
||||
user.start_pulling(AM)
|
||||
|
||||
//reopening ladder radial menu ahead
|
||||
T = get_turf(user)
|
||||
var/obj/structure/ladder/ladder_structure = locate() in T
|
||||
if (ladder_structure)
|
||||
ladder_structure.use(user)
|
||||
var/turf/target = get_turf(ladder)
|
||||
user.zMove(target = target, z_move_flags = ZMOVE_CHECK_PULLEDBY|ZMOVE_ALLOW_BUCKLED|ZMOVE_INCLUDE_PULLED)
|
||||
ladder.use(user) //reopening ladder radial menu ahead
|
||||
|
||||
/obj/structure/ladder/proc/use(mob/user, is_ghost=FALSE)
|
||||
if (!is_ghost && !in_range(src, user))
|
||||
|
||||
@@ -64,9 +64,10 @@
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(leaving == src)
|
||||
return // Let's not block ourselves.
|
||||
return //Let's not block ourselves.
|
||||
|
||||
if(!isobserver(leaving) && isTerminator() && direction == dir)
|
||||
leaving.set_currently_z_moving(CURRENTLY_Z_ASCENDING)
|
||||
INVOKE_ASYNC(src, .proc/stair_ascend, leaving)
|
||||
leaving.Bump(src)
|
||||
return COMPONENT_ATOM_BLOCK_EXIT
|
||||
@@ -80,23 +81,20 @@
|
||||
icon_state = "stairs[isTerminator() ? "_t" : null]"
|
||||
return ..()
|
||||
|
||||
/obj/structure/stairs/proc/stair_ascend(atom/movable/AM)
|
||||
/obj/structure/stairs/proc/stair_ascend(atom/movable/climber)
|
||||
var/turf/checking = get_step_multiz(get_turf(src), UP)
|
||||
if(!istype(checking))
|
||||
return
|
||||
if(!checking.zPassIn(AM, UP, get_turf(src)))
|
||||
if(!checking.zPassIn(climber, UP, get_turf(src)))
|
||||
return
|
||||
var/turf/target = get_step_multiz(get_turf(src), (dir|UP))
|
||||
if(istype(target) && !target.can_zFall(AM, null, get_step_multiz(target, DOWN))) //Don't throw them into a tile that will just dump them back down.
|
||||
if(isliving(AM))
|
||||
var/mob/living/L = AM
|
||||
var/pulling = L.pulling
|
||||
if(pulling)
|
||||
L.pulling.forceMove(target)
|
||||
L.forceMove(target)
|
||||
L.start_pulling(pulling)
|
||||
else
|
||||
AM.forceMove(target)
|
||||
if(istype(target) && !climber.can_z_move(DOWN, target, z_move_flags = ZMOVE_FALL_FLAGS)) //Don't throw them into a tile that will just dump them back down.
|
||||
climber.zMove(target = target, z_move_flags = ZMOVE_STAIRS_FLAGS)
|
||||
/// Moves anything that's being dragged by src or anything buckled to it to the stairs turf.
|
||||
climber.pulling?.move_from_pull(climber, loc, climber.glide_size)
|
||||
for(var/mob/living/buckled as anything in climber.buckled_mobs)
|
||||
buckled.pulling?.move_from_pull(buckled, loc, buckled.glide_size)
|
||||
|
||||
|
||||
/obj/structure/stairs/vv_edit_var(var_name, var_value)
|
||||
. = ..()
|
||||
@@ -132,10 +130,10 @@
|
||||
if(T && !istype(T))
|
||||
T.ChangeTurf(/turf/open/openspace, flags = CHANGETURF_INHERIT_AIR)
|
||||
|
||||
/obj/structure/stairs/intercept_zImpact(atom/movable/AM, levels = 1)
|
||||
/obj/structure/stairs/intercept_zImpact(list/falling_movables, levels = 1)
|
||||
. = ..()
|
||||
if(isTerminator())
|
||||
. |= FALL_INTERCEPTED | FALL_NO_MESSAGE
|
||||
if(levels == 1 && isTerminator()) // Stairs won't save you from a steep fall.
|
||||
. |= FALL_INTERCEPTED | FALL_NO_MESSAGE | FALL_RETAIN_PULL
|
||||
|
||||
/obj/structure/stairs/proc/isTerminator() //If this is the last stair in a chain and should move mobs up
|
||||
if(terminator_mode != STAIR_TERMINATOR_AUTOMATIC)
|
||||
|
||||
@@ -32,12 +32,49 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr
|
||||
/turf/open/openspace/Initialize(mapload) // handle plane and layer here so that they don't cover other obs/turfs in Dream Maker
|
||||
. = ..()
|
||||
overlays += GLOB.openspace_backdrop_one_for_all //Special grey square for projecting backdrop darkness filter on it.
|
||||
RegisterSignal(src, COMSIG_ATOM_CREATED, .proc/on_atom_created)
|
||||
return INITIALIZE_HINT_LATELOAD
|
||||
|
||||
/turf/open/openspace/LateInitialize()
|
||||
. = ..()
|
||||
AddElement(/datum/element/turf_z_transparency, FALSE)
|
||||
|
||||
/turf/open/openspace/ChangeTurf(path, list/new_baseturfs, flags)
|
||||
UnregisterSignal(src, COMSIG_ATOM_CREATED)
|
||||
return ..()
|
||||
|
||||
/**
|
||||
* Prepares a moving movable to be precipitated if Move() is successful.
|
||||
* This is done in Enter() and not Entered() because there's no easy way to tell
|
||||
* if the latter was called by Move() or forceMove() while the former is only called by Move().
|
||||
*/
|
||||
/turf/open/openspace/Enter(atom/movable/movable, atom/oldloc)
|
||||
. = ..()
|
||||
if(.)
|
||||
//higher priority than CURRENTLY_Z_FALLING so the movable doesn't fall on Entered()
|
||||
movable.set_currently_z_moving(CURRENTLY_Z_FALLING_FROM_MOVE)
|
||||
|
||||
///Makes movables fall when forceMove()'d to this turf.
|
||||
/turf/open/openspace/Entered(atom/movable/movable)
|
||||
. = ..()
|
||||
if(movable.set_currently_z_moving(CURRENTLY_Z_FALLING))
|
||||
zFall(movable, falling_from_move = TRUE)
|
||||
/**
|
||||
* Drops movables spawned on this turf only after they are successfully initialized.
|
||||
* so flying mobs, qdeleted movables and things that were moved somewhere else during
|
||||
* Initialize() won't fall by accident.
|
||||
*/
|
||||
/turf/open/openspace/proc/on_atom_created(datum/source, atom/created_atom)
|
||||
SIGNAL_HANDLER
|
||||
if(ismovable(created_atom))
|
||||
//Drop it only when it's finished initializing, not before.
|
||||
addtimer(CALLBACK(src, .proc/zfall_if_on_turf, created_atom), 0 SECONDS)
|
||||
|
||||
/turf/open/openspace/proc/zfall_if_on_turf(atom/movable/movable)
|
||||
if(QDELETED(movable) || movable.loc != src)
|
||||
return
|
||||
zFall(movable)
|
||||
|
||||
/turf/open/openspace/can_have_cabling()
|
||||
if(locate(/obj/structure/lattice/catwalk, src))
|
||||
return TRUE
|
||||
|
||||
@@ -172,7 +172,7 @@
|
||||
if(!arrived || src != arrived.loc)
|
||||
return
|
||||
|
||||
if(destination_z && destination_x && destination_y && !(arrived.pulledby || !arrived.can_be_z_moved))
|
||||
if(destination_z && destination_x && destination_y && !arrived.pulledby && !arrived.currently_z_moving)
|
||||
var/tx = destination_x
|
||||
var/ty = destination_y
|
||||
var/turf/DT = locate(tx, ty, destination_z)
|
||||
@@ -191,21 +191,13 @@
|
||||
ty--
|
||||
DT = locate(tx, ty, destination_z)
|
||||
|
||||
var/atom/movable/pulling = arrived.pulling
|
||||
var/atom/movable/puller = arrived
|
||||
arrived.forceMove(DT)
|
||||
arrived.zMove(null, DT, ZMOVE_ALLOW_BUCKLED)
|
||||
|
||||
while (pulling != null)
|
||||
var/next_pulling = pulling.pulling
|
||||
|
||||
var/turf/T = get_step(puller.loc, turn(puller.dir, 180))
|
||||
pulling.can_be_z_moved = FALSE
|
||||
pulling.forceMove(T)
|
||||
puller.start_pulling(pulling)
|
||||
pulling.can_be_z_moved = TRUE
|
||||
|
||||
puller = pulling
|
||||
pulling = next_pulling
|
||||
var/atom/movable/current_pull = arrived.pulling
|
||||
while (current_pull)
|
||||
var/turf/target_turf = get_step(current_pull.pulledby.loc, REVERSE_DIR(current_pull.pulledby.dir)) || current_pull.pulledby.loc
|
||||
current_pull.zMove(null, target_turf, ZMOVE_ALLOW_BUCKLED)
|
||||
current_pull = current_pull.pulling
|
||||
|
||||
|
||||
/turf/open/space/MakeSlippery(wet_setting, min_wet_time, wet_time_to_add, max_wet_time, permanent)
|
||||
|
||||
+44
-28
@@ -260,38 +260,56 @@ GLOBAL_LIST_EMPTY(station_turfs)
|
||||
/turf/proc/zAirOut(direction, turf/source)
|
||||
return FALSE
|
||||
|
||||
/turf/proc/zImpact(atom/movable/A, levels = 1, turf/prev_turf)
|
||||
/// Precipitates a movable (plus whatever buckled to it) to lower z levels if possible and then calls zImpact()
|
||||
/turf/proc/zFall(atom/movable/falling, levels = 1, force = FALSE, falling_from_move = FALSE)
|
||||
var/turf/target = get_step_multiz(src, DOWN)
|
||||
if(!target)
|
||||
return FALSE
|
||||
var/isliving = isliving(falling)
|
||||
if(!isliving && !isobj(falling))
|
||||
return
|
||||
if(isliving)
|
||||
var/mob/living/falling_living = falling
|
||||
//relay this mess to whatever the mob is buckled to.
|
||||
if(falling_living.buckled)
|
||||
falling = falling_living.buckled
|
||||
if(!falling_from_move && falling.currently_z_moving)
|
||||
return
|
||||
if(!force && !falling.can_z_move(DOWN, src, target, ZMOVE_FALL_FLAGS))
|
||||
falling.set_currently_z_moving(FALSE, TRUE)
|
||||
return FALSE
|
||||
|
||||
// So it doesn't trigger other zFall calls. Cleared on zMove.
|
||||
falling.set_currently_z_moving(CURRENTLY_Z_FALLING)
|
||||
|
||||
falling.zMove(null, target, ZMOVE_CHECK_PULLEDBY)
|
||||
target.zImpact(falling, levels, src)
|
||||
return TRUE
|
||||
|
||||
///Called each time the target falls down a z level possibly making their trajectory come to a halt. see __DEFINES/movement.dm.
|
||||
/turf/proc/zImpact(atom/movable/falling, levels = 1, turf/prev_turf)
|
||||
var/flags = NONE
|
||||
var/mov_name = A.name
|
||||
var/list/falling_movables = falling.get_z_move_affected()
|
||||
var/list/falling_mov_names
|
||||
for(var/atom/movable/falling_mov as anything in falling_movables)
|
||||
falling_mov_names += falling_mov.name
|
||||
for(var/i in contents)
|
||||
var/atom/thing = i
|
||||
flags |= thing.intercept_zImpact(A, levels)
|
||||
flags |= thing.intercept_zImpact(falling_movables, levels)
|
||||
if(flags & FALL_STOP_INTERCEPTING)
|
||||
break
|
||||
if(prev_turf && !(flags & FALL_NO_MESSAGE))
|
||||
prev_turf.visible_message(span_danger("[mov_name] falls through [prev_turf]!"))
|
||||
if(flags & FALL_INTERCEPTED)
|
||||
return
|
||||
if(zFall(A, levels + 1))
|
||||
for(var/mov_name in falling_mov_names)
|
||||
prev_turf.visible_message(span_danger("[mov_name] falls through [prev_turf]!"))
|
||||
if(!(flags & FALL_INTERCEPTED) && zFall(falling, levels + 1))
|
||||
return FALSE
|
||||
A.visible_message(span_danger("[A] crashes into [src]!"))
|
||||
A.onZImpact(src, levels)
|
||||
return TRUE
|
||||
|
||||
/turf/proc/can_zFall(atom/movable/A, levels = 1, turf/target)
|
||||
SHOULD_BE_PURE(TRUE)
|
||||
return zPassOut(A, DOWN, target) && target.zPassIn(A, DOWN, src)
|
||||
|
||||
/turf/proc/zFall(atom/movable/A, levels = 1, force = FALSE)
|
||||
var/turf/target = get_step_multiz(src, DOWN)
|
||||
if(!target || (!isobj(A) && !ismob(A)))
|
||||
return FALSE
|
||||
if(!force && (!can_zFall(A, levels, target) || !A.can_zFall(src, levels, target, DOWN)))
|
||||
return FALSE
|
||||
A.zfalling = TRUE
|
||||
A.forceMove(target)
|
||||
A.zfalling = FALSE
|
||||
target.zImpact(A, levels, src)
|
||||
for(var/atom/movable/falling_mov as anything in falling_movables)
|
||||
if(!(flags & FALL_RETAIN_PULL))
|
||||
falling_mov.stop_pulling()
|
||||
if(!(flags & FALL_INTERCEPTED))
|
||||
falling_mov.onZImpact(src, levels)
|
||||
if(falling_mov.pulledby && (falling_mov.z != falling_mov.pulledby.z || get_dist(falling_mov, falling_mov.pulledby) > 1))
|
||||
falling_mov.pulledby.stop_pulling()
|
||||
return TRUE
|
||||
|
||||
/turf/proc/handleRCL(obj/item/rcl/C, mob/user)
|
||||
@@ -361,14 +379,12 @@ GLOBAL_LIST_EMPTY(station_turfs)
|
||||
|
||||
|
||||
/turf/open/Entered(atom/movable/arrived, atom/old_loc, list/atom/old_locs)
|
||||
..()
|
||||
. = ..()
|
||||
//melting
|
||||
if(isobj(arrived) && air && air.temperature > T0C)
|
||||
var/obj/O = arrived
|
||||
if(O.obj_flags & FROZEN)
|
||||
O.make_unfrozen()
|
||||
if(!arrived.zfalling)
|
||||
zFall(arrived)
|
||||
|
||||
// A proc in case it needs to be recreated or badmins want to change the baseturfs
|
||||
/turf/proc/assemble_baseturfs(turf/fake_baseturf_type)
|
||||
|
||||
@@ -106,8 +106,7 @@ GLOBAL_LIST_EMPTY(blob_nodes)
|
||||
if(blobstrain.effectdesc)
|
||||
to_chat(src, "The <b><font color=\"[blobstrain.color]\">[blobstrain.name]</b></font> strain [blobstrain.effectdesc]")
|
||||
|
||||
/mob/camera/blob/can_zFall(turf/source, levels)
|
||||
// Prevent blob from falling through zlevels
|
||||
/mob/camera/blob/can_z_move(direction, turf/start, turf/destination, z_move_flags = NONE, mob/living/rider)
|
||||
return FALSE
|
||||
|
||||
/mob/camera/blob/proc/is_valid_turf(turf/T)
|
||||
|
||||
@@ -134,6 +134,9 @@ the new instance inside the host to be updated to the template's stats.
|
||||
follow_next(Dir & NORTHWEST)
|
||||
last_move_tick = world.time
|
||||
|
||||
/mob/camera/disease/can_z_move(direction, turf/start, turf/destination, z_move_flags = NONE, mob/living/rider)
|
||||
return FALSE
|
||||
|
||||
/mob/camera/disease/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, list/message_mods = list())
|
||||
. = ..()
|
||||
var/atom/movable/to_follow = speaker
|
||||
|
||||
@@ -98,7 +98,7 @@
|
||||
update_openspace()
|
||||
var/turf/T = get_turf(src)
|
||||
for(var/atom/movable/AM in T)
|
||||
if(!AM.zfalling)
|
||||
if(!AM.currently_z_moving)
|
||||
T.zFall(AM)
|
||||
|
||||
/obj/structure/pitgrate/proc/reset_plane()
|
||||
|
||||
@@ -1,2 +1,11 @@
|
||||
/mob/dead/observer/canZMove(direction, turf/target)
|
||||
return TRUE
|
||||
/mob/dead/observer/up()
|
||||
set name = "Move Upwards"
|
||||
set category = "IC"
|
||||
|
||||
if(zMove(UP, z_move_flags = ZMOVE_FEEDBACK))
|
||||
to_chat(src, "<span class='notice'>You move upwards.</span>")
|
||||
|
||||
/mob/dead/observer/can_z_move(direction, turf/start, turf/destination, z_move_flags = NONE, mob/living/rider)
|
||||
z_move_flags |= ZMOVE_IGNORE_OBSTACLES //observers do not respect these FLOORS you speak so much of.
|
||||
return ..()
|
||||
|
||||
|
||||
@@ -41,9 +41,10 @@
|
||||
QDEL_LAZYLIST(diseases)
|
||||
return ..()
|
||||
|
||||
/mob/living/onZImpact(turf/T, levels)
|
||||
/mob/living/onZImpact(turf/T, levels, message = TRUE)
|
||||
if(!isgroundlessturf(T))
|
||||
ZImpactDamage(T, levels)
|
||||
message = FALSE
|
||||
return ..()
|
||||
|
||||
/mob/living/proc/ZImpactDamage(turf/T, levels)
|
||||
@@ -836,9 +837,10 @@
|
||||
lying_angle_on_movement(direct)
|
||||
if (buckled && buckled.loc != newloc) //not updating position
|
||||
if (!buckled.anchored)
|
||||
return buckled.Move(newloc, direct, glide_size)
|
||||
else
|
||||
return FALSE
|
||||
buckled.moving_from_pull = moving_from_pull
|
||||
. = buckled.Move(newloc, direct, glide_size)
|
||||
buckled.moving_from_pull = null
|
||||
return
|
||||
|
||||
var/old_direction = dir
|
||||
var/turf/T = loc
|
||||
@@ -848,12 +850,9 @@
|
||||
|
||||
. = ..()
|
||||
|
||||
if(pulledby && moving_diagonally != FIRST_DIAG_STEP && get_dist(src, pulledby) > 1 && (pulledby != moving_from_pull))//separated from our puller and not in the middle of a diagonal move.
|
||||
pulledby.stop_pulling()
|
||||
else
|
||||
if(isliving(pulledby))
|
||||
var/mob/living/L = pulledby
|
||||
L.set_pull_offsets(src, pulledby.grab_state)
|
||||
if(moving_diagonally != FIRST_DIAG_STEP && isliving(pulledby))
|
||||
var/mob/living/L = pulledby
|
||||
L.set_pull_offsets(src, pulledby.grab_state)
|
||||
|
||||
if(active_storage && !(CanReach(active_storage.parent,view_only = TRUE)))
|
||||
active_storage.close(src)
|
||||
@@ -1565,15 +1564,15 @@
|
||||
return L
|
||||
|
||||
/mob/living/forceMove(atom/destination)
|
||||
stop_pulling()
|
||||
if(buckled && !HAS_TRAIT(src, TRAIT_CANNOT_BE_UNBUCKLED))
|
||||
buckled.unbuckle_mob(src, force = TRUE)
|
||||
if(has_buckled_mobs())
|
||||
unbuckle_all_mobs(force = TRUE)
|
||||
if(!currently_z_moving)
|
||||
stop_pulling()
|
||||
if(buckled && !HAS_TRAIT(src, TRAIT_CANNOT_BE_UNBUCKLED))
|
||||
buckled.unbuckle_mob(src, force = TRUE)
|
||||
if(has_buckled_mobs())
|
||||
unbuckle_all_mobs(force = TRUE)
|
||||
. = ..()
|
||||
if(.)
|
||||
if(client)
|
||||
reset_perspective()
|
||||
if(. && client)
|
||||
reset_perspective()
|
||||
|
||||
|
||||
/mob/living/proc/update_z(new_z) // 1+ to register, null to unregister
|
||||
|
||||
@@ -58,10 +58,48 @@
|
||||
return
|
||||
remove_movespeed_modifier(/datum/movespeed_modifier/bulky_drag)
|
||||
|
||||
/mob/living/canZMove(dir, turf/target)
|
||||
/**
|
||||
* We want to relay the zmovement to the buckled atom when possible
|
||||
* and only run what we can't have on buckled.zMove() or buckled.can_z_move() here.
|
||||
* This way we can avoid esoteric bugs, copypasta and inconsistencies.
|
||||
*/
|
||||
/mob/living/zMove(dir, turf/target, z_move_flags = ZMOVE_FLIGHT_FLAGS)
|
||||
if(buckled)
|
||||
return buckled.can_zTravel(target, dir) && (buckled.movement_type & FLYING | FLOATING)
|
||||
return can_zTravel(target, dir) && (movement_type & FLYING | FLOATING)
|
||||
if(buckled.currently_z_moving)
|
||||
return FALSE
|
||||
if(!(z_move_flags & ZMOVE_ALLOW_BUCKLED))
|
||||
buckled.unbuckle_mob(src, force = TRUE, can_fall = FALSE)
|
||||
else
|
||||
if(!target)
|
||||
target = can_z_move(dir, get_turf(src), null, z_move_flags, src)
|
||||
if(!target)
|
||||
return FALSE
|
||||
return buckled.zMove(dir, target, z_move_flags) // Return value is a loc.
|
||||
return ..()
|
||||
|
||||
/mob/living/can_z_move(direction, turf/start, turf/destination, z_move_flags = ZMOVE_FLIGHT_FLAGS, mob/living/rider)
|
||||
if(z_move_flags & ZMOVE_INCAPACITATED_CHECKS && incapacitated())
|
||||
if(z_move_flags & ZMOVE_FEEDBACK)
|
||||
to_chat(rider || src, "<span class='warning'>[rider ? src : "You"] can't do that right now!</span>")
|
||||
return FALSE
|
||||
if(!buckled || !(z_move_flags & ZMOVE_ALLOW_BUCKLED))
|
||||
return ..()
|
||||
switch(SEND_SIGNAL(buckled, COMSIG_BUCKLED_CAN_Z_MOVE, direction, start, destination, z_move_flags, src))
|
||||
if(COMPONENT_RIDDEN_ALLOW_Z_MOVE) // Can be ridden.
|
||||
return buckled.can_z_move(direction, start, destination, z_move_flags, src)
|
||||
if(COMPONENT_RIDDEN_STOP_Z_MOVE) // Is a ridable but can't be ridden right now. Feedback messages already done.
|
||||
return FALSE
|
||||
else
|
||||
if(!(z_move_flags & ZMOVE_CAN_FLY_CHECKS) && !buckled.anchored)
|
||||
return buckled.can_z_move(direction, start, destination, z_move_flags, src)
|
||||
if(z_move_flags & ZMOVE_FEEDBACK)
|
||||
to_chat(src, "<span class='notice'>Unbuckle from [buckled] first.<span>")
|
||||
return FALSE
|
||||
|
||||
/mob/set_currently_z_moving(value)
|
||||
if(buckled)
|
||||
return buckled.set_currently_z_moving(value)
|
||||
return ..()
|
||||
|
||||
/mob/living/keybind_face_direction(direction)
|
||||
if(stat > SOFT_CRIT)
|
||||
|
||||
@@ -999,12 +999,15 @@
|
||||
set name = "Move Upwards"
|
||||
set category = "IC"
|
||||
|
||||
if(zMove(UP, TRUE))
|
||||
if(eyeobj.zMove(UP, z_move_flags = ZMOVE_FEEDBACK))
|
||||
to_chat(src, span_notice("You move upwards."))
|
||||
|
||||
/mob/living/silicon/ai/zMove(dir, feedback = FALSE)
|
||||
. = eyeobj.zMove(dir, feedback)
|
||||
/mob/living/silicon/ai/down()
|
||||
set name = "Move Down"
|
||||
set category = "IC"
|
||||
|
||||
if(eyeobj.zMove(DOWN, z_move_flags = ZMOVE_FEEDBACK))
|
||||
to_chat(src, span_notice("You move down."))
|
||||
|
||||
/// Proc to hook behavior to the changes of the value of [aiRestorePowerRoutine].
|
||||
/mob/living/silicon/ai/proc/setAiRestorePowerRoutine(new_value)
|
||||
|
||||
@@ -101,24 +101,14 @@
|
||||
if(ai.master_multicam)
|
||||
ai.master_multicam.refresh_view()
|
||||
|
||||
//it uses setLoc not forceMove, talks to the sillycone and not the camera mob
|
||||
/mob/camera/ai_eye/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(ai, span_warning("There's nowhere to go in that direction!"))
|
||||
return FALSE
|
||||
if(!canZMove(dir, target))
|
||||
if(feedback)
|
||||
to_chat(ai, span_warning("You couldn't move there!"))
|
||||
return FALSE
|
||||
setLoc(target, TRUE)
|
||||
return TRUE
|
||||
/mob/camera/ai_eye/zMove(dir, turf/target, z_move_flags = NONE, recursions_left = 1, list/falling_movs)
|
||||
. = ..()
|
||||
if(.)
|
||||
setLoc(loc, force_update = TRUE)
|
||||
|
||||
/mob/camera/ai_eye/canZMove(direction, turf/target) //cameras do not respect these FLOORS you speak so much of
|
||||
return TRUE
|
||||
/mob/camera/ai_eye/can_z_move(direction, turf/start, turf/destination, z_move_flags = NONE, mob/living/rider)
|
||||
z_move_flags |= ZMOVE_IGNORE_OBSTACLES //cameras do not respect these FLOORS you speak so much of
|
||||
return ..()
|
||||
|
||||
/mob/camera/ai_eye/Move()
|
||||
return
|
||||
|
||||
@@ -132,7 +132,7 @@ GLOBAL_DATUM(ai_camera_room_landmark, /obj/effect/landmark/ai_multicam_room)
|
||||
if(screen?.ai)
|
||||
return screen.ai.client
|
||||
|
||||
/mob/camera/ai_eye/pic_in_pic/setLoc(turf/destination)
|
||||
/mob/camera/ai_eye/pic_in_pic/setLoc(turf/destination, force_update = FALSE)
|
||||
if (destination)
|
||||
abstract_move(destination)
|
||||
else
|
||||
|
||||
@@ -510,13 +510,20 @@
|
||||
|
||||
var/turf/current_turf = get_turf(src)
|
||||
var/turf/above_turf = SSmapping.get_turf_above(current_turf)
|
||||
var/ventcrawling_mob = HAS_TRAIT(src, TRAIT_MOVE_VENTCRAWLING)
|
||||
|
||||
if(can_zFall(above_turf, 1, current_turf, DOWN) && !ventcrawling_mob) //Will be fall down if we go up?
|
||||
to_chat(src, "<span class='notice'>You are not Superman.<span>")
|
||||
var/ventcrawling_flag = HAS_TRAIT(src, TRAIT_MOVE_VENTCRAWLING) ? ZMOVE_VENTCRAWLING : 0
|
||||
if(!above_turf)
|
||||
to_chat(src, "<span class='warning'>There's nowhere to go in that direction!</span>")
|
||||
return
|
||||
|
||||
if(zMove(UP, TRUE, ventcrawling_mob))
|
||||
if(can_z_move(DOWN, above_turf, current_turf, ZMOVE_FALL_FLAGS|ventcrawling_flag)) //Will we fall down if we go up?
|
||||
if(buckled)
|
||||
to_chat(src, "<span class='notice'>[buckled] is is not capable of flight.<span>")
|
||||
else
|
||||
to_chat(src, "<span class='notice'>You are not Superman.<span>")
|
||||
return
|
||||
|
||||
if(zMove(UP, z_move_flags = ZMOVE_FLIGHT_FLAGS|ZMOVE_FEEDBACK|ventcrawling_flag))
|
||||
to_chat(src, span_notice("You move upwards."))
|
||||
|
||||
///Moves a mob down a z level
|
||||
@@ -524,44 +531,10 @@
|
||||
set name = "Move Down"
|
||||
set category = "IC"
|
||||
|
||||
var/ventcrawling_mob = HAS_TRAIT(src, TRAIT_MOVE_VENTCRAWLING)
|
||||
|
||||
if(zMove(DOWN, TRUE, ventcrawling_mob))
|
||||
var/ventcrawling_flag = HAS_TRAIT(src, TRAIT_MOVE_VENTCRAWLING) ? ZMOVE_VENTCRAWLING : 0
|
||||
if(zMove(DOWN, z_move_flags = ZMOVE_FLIGHT_FLAGS|ZMOVE_FEEDBACK|ventcrawling_flag))
|
||||
to_chat(src, span_notice("You move down."))
|
||||
|
||||
/mob/can_zFall(turf/source, levels, turf/target, direction)
|
||||
if(buckled)
|
||||
return buckled.can_zFall(source, levels, target, direction)
|
||||
return ..()
|
||||
|
||||
///Move a mob between z levels, if it's valid to move z's on this turf
|
||||
/mob/proc/zMove(dir, feedback = FALSE, ventcrawling = FALSE)
|
||||
if(dir != UP && dir != DOWN)
|
||||
return FALSE
|
||||
if(incapacitated())
|
||||
if(feedback)
|
||||
to_chat(src, span_warning("You can't do that right now!"))
|
||||
return FALSE
|
||||
var/turf/target = get_step_multiz(src, dir)
|
||||
if(!target)
|
||||
if(feedback)
|
||||
to_chat(src, span_warning("There's nowhere to go in that direction!"))
|
||||
return FALSE
|
||||
if(!canZMove(dir, target) && !ventcrawling)
|
||||
if(feedback)
|
||||
to_chat(src, span_warning("You couldn't move there!"))
|
||||
return FALSE
|
||||
if(!ventcrawling) //let this be handled in atmosmachinery.dm
|
||||
return Move(target)
|
||||
else
|
||||
var/obj/machinery/atmospherics/pipe = loc
|
||||
pipe.relaymove(src, dir)
|
||||
return TRUE
|
||||
|
||||
/// Can this mob move between z levels
|
||||
/mob/proc/canZMove(direction, turf/target)
|
||||
return FALSE
|
||||
|
||||
/mob/abstract_move(atom/destination)
|
||||
var/turf/new_turf = get_turf(destination)
|
||||
if(is_secret_level(new_turf.z) && !client?.holder)
|
||||
|
||||
@@ -417,7 +417,7 @@
|
||||
|
||||
//BUCKLE HOOKS
|
||||
|
||||
/obj/machinery/power/emitter/prototype/unbuckle_mob(mob/living/buckled_mob,force = 0)
|
||||
/obj/machinery/power/emitter/prototype/unbuckle_mob(mob/living/buckled_mob, force = FALSE, can_fall = TRUE)
|
||||
playsound(src,'sound/mecha/mechmove01.ogg', 50, TRUE)
|
||||
manual = FALSE
|
||||
for(var/obj/item/item in buckled_mob.held_items)
|
||||
|
||||
@@ -1085,9 +1085,10 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
|
||||
playsound(get_turf(src), 'sound/effects/supermatter.ogg', 50, TRUE)
|
||||
Consume(hit_object)
|
||||
|
||||
/obj/machinery/power/supermatter_crystal/intercept_zImpact(atom/movable/hit_object, levels)
|
||||
/obj/machinery/power/supermatter_crystal/intercept_zImpact(list/falling_movables, levels)
|
||||
. = ..()
|
||||
Bumped(hit_object)
|
||||
for(var/atom/movable/hit_object as anything in falling_movables)
|
||||
Bumped(hit_object)
|
||||
. |= FALL_STOP_INTERCEPTING | FALL_INTERCEPTED
|
||||
|
||||
/obj/machinery/power/supermatter_crystal/proc/Consume(atom/movable/consumed_object)
|
||||
|
||||
@@ -10,13 +10,21 @@
|
||||
allowed_area = A.name
|
||||
. = ..()
|
||||
|
||||
/mob/camera/ai_eye/remote/xenobio/setLoc(destination)
|
||||
/mob/camera/ai_eye/remote/xenobio/setLoc(turf/destination, force_update = FALSE)
|
||||
var/area/new_area = get_area(destination)
|
||||
if(new_area && new_area.name == allowed_area || new_area && (new_area.area_flags & XENOBIOLOGY_COMPATIBLE))
|
||||
return ..()
|
||||
else
|
||||
return
|
||||
|
||||
/mob/camera/ai_eye/remote/xenobio/can_z_move(direction, turf/start, turf/destination, z_move_flags = NONE, mob/living/rider)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
var/area/new_area = get_area(.)
|
||||
if(new_area.name != allowed_area && !(new_area.area_flags & XENOBIOLOGY_COMPATIBLE))
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/computer/camera_advanced/xenobio
|
||||
name = "Slime management console"
|
||||
desc = "A computer used for remotely handling slimes."
|
||||
|
||||
@@ -304,7 +304,7 @@
|
||||
src.origin = origin
|
||||
return ..()
|
||||
|
||||
/mob/camera/ai_eye/remote/shuttle_docker/setLoc(destination)
|
||||
/mob/camera/ai_eye/remote/shuttle_docker/setLoc(turf/destination, force_update = FALSE)
|
||||
. = ..()
|
||||
var/obj/machinery/computer/camera_advanced/shuttle_docker/console = origin
|
||||
console.checkLandingSpot()
|
||||
|
||||
@@ -651,7 +651,7 @@ GLOBAL_LIST_EMPTY(vending_products)
|
||||
to_chat(user, span_notice("You insert [I] into [src]'s input compartment."))
|
||||
loaded_items++
|
||||
|
||||
/obj/machinery/vending/unbuckle_mob(mob/living/buckled_mob, force=FALSE)
|
||||
/obj/machinery/vending/unbuckle_mob(mob/living/buckled_mob, force = FALSE, can_fall = TRUE)
|
||||
if(!force)
|
||||
return
|
||||
. = ..()
|
||||
|
||||
Reference in New Issue
Block a user