diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index 1a2001dbc1..95b6d0c214 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -194,160 +194,6 @@
stop_pulling()
return
-////////////////////////////////////////
-// 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, direct=0)
- . = FALSE
- if(!newloc || newloc == loc)
- return
-
- if(!direct)
- direct = get_dir(src, newloc)
- setDir(direct)
-
- if(!loc.Exit(src, newloc))
- return
-
- if(!newloc.Enter(src, src.loc))
- return
-
- // Past this is the point of no return
- var/atom/oldloc = loc
- var/area/oldarea = get_area(oldloc)
- var/area/newarea = get_area(newloc)
- loc = newloc
- . = TRUE
- oldloc.Exited(src, newloc)
- if(oldarea != newarea)
- oldarea.Exited(src, newloc)
-
- for(var/i in oldloc)
- if(i == src) // Multi tile objects
- continue
- var/atom/movable/thing = i
- thing.Uncrossed(src)
-
- newloc.Entered(src, oldloc)
- if(oldarea != newarea)
- newarea.Entered(src, oldloc)
-
- for(var/i in loc)
- if(i == src) // Multi tile objects
- continue
- var/atom/movable/thing = i
- thing.Crossed(src)
-//
-////////////////////////////////////////
-
-/atom/movable/Move(atom/newloc, direct)
- var/atom/movable/pullee = pulling
- var/turf/T = loc
- if(pulling)
- if(pullee && get_dist(src, pullee) > 1)
- stop_pulling()
-
- if(pullee && pullee.loc != loc && !isturf(pullee.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.")
- stop_pulling()
- if(!loc || !newloc)
- return FALSE
- var/atom/oldloc = loc
-
- if(loc != newloc)
- if (!(direct & (direct - 1))) //Cardinal move
- . = ..()
- else //Diagonal move, split it into cardinal moves
- moving_diagonally = FIRST_DIAG_STEP
- var/first_step_dir
- // The `&& moving_diagonally` checks are so that a forceMove taking
- // place due to a Crossed, Bumped, etc. call will interrupt
- // the second half of the diagonal movement, or the second attempt
- // at a first half if step() fails because we hit something.
- if (direct & NORTH)
- if (direct & EAST)
- if (step(src, NORTH) && moving_diagonally)
- first_step_dir = NORTH
- moving_diagonally = SECOND_DIAG_STEP
- . = step(src, EAST)
- else if (moving_diagonally && step(src, EAST))
- first_step_dir = EAST
- moving_diagonally = SECOND_DIAG_STEP
- . = step(src, NORTH)
- else if (direct & WEST)
- if (step(src, NORTH) && moving_diagonally)
- first_step_dir = NORTH
- moving_diagonally = SECOND_DIAG_STEP
- . = step(src, WEST)
- else if (moving_diagonally && step(src, WEST))
- first_step_dir = WEST
- moving_diagonally = SECOND_DIAG_STEP
- . = step(src, NORTH)
- else if (direct & SOUTH)
- if (direct & EAST)
- if (step(src, SOUTH) && moving_diagonally)
- first_step_dir = SOUTH
- moving_diagonally = SECOND_DIAG_STEP
- . = step(src, EAST)
- else if (moving_diagonally && step(src, EAST))
- first_step_dir = EAST
- moving_diagonally = SECOND_DIAG_STEP
- . = step(src, SOUTH)
- else if (direct & WEST)
- if (step(src, SOUTH) && moving_diagonally)
- first_step_dir = SOUTH
- moving_diagonally = SECOND_DIAG_STEP
- . = step(src, WEST)
- else if (moving_diagonally && step(src, WEST))
- first_step_dir = WEST
- moving_diagonally = SECOND_DIAG_STEP
- . = step(src, SOUTH)
- if(moving_diagonally == SECOND_DIAG_STEP)
- if(!.)
- setDir(first_step_dir)
- else if (!inertia_moving)
- inertia_next_move = world.time + inertia_move_delay
- newtonian_move(direct)
- moving_diagonally = 0
- return
-
- if(!loc || (loc == oldloc && oldloc != newloc))
- last_move = 0
- return
-
- if(.)
- Moved(oldloc, direct)
- if(. && pulling && pulling == pullee) //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
- if(get_dist(src, pulling) > 1 || (moving_diagonally != SECOND_DIAG_STEP && ((pull_dir - 1) & pull_dir)))
- pulling.Move(T, get_dir(pulling, T)) //the pullee tries to reach our previous position
- if(pulling && get_dist(src, pulling) > 1) //the pullee couldn't keep up
- stop_pulling()
- 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.
- pulledby.stop_pulling()
-
-
- last_move = direct
- setDir(direct)
- if(. && has_buckled_mobs() && !handle_buckled_mob_movement(loc,direct)) //movement failed due to buckled mob(s)
- return FALSE
-
-//Called after a successful Move(). By this point, we've already moved
-/atom/movable/proc/Moved(atom/OldLoc, Dir, Forced = FALSE)
- SEND_SIGNAL(src, COMSIG_MOVABLE_MOVED, OldLoc, Dir, Forced)
- if (!inertia_moving)
- inertia_next_move = world.time + inertia_move_delay
- newtonian_move(Dir)
- if (length(client_mobs_in_contents))
- update_parallax_contents()
-
- return TRUE
-
/atom/movable/Destroy(force)
QDEL_NULL(proximity_monitor)
QDEL_NULL(language_holder)
@@ -372,143 +218,6 @@
orbiting.end_orbit(src)
orbiting = null
-// 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/AM)
- . = TRUE
- SEND_SIGNAL(src, COMSIG_MOVABLE_CROSS, AM)
- return CanPass(AM, AM.loc, TRUE)
-
-//oldloc = old location on atom, inserted when forceMove is called and ONLY when forceMove is called!
-/atom/movable/Crossed(atom/movable/AM, oldloc)
- SEND_SIGNAL(src, COMSIG_MOVABLE_CROSSED, AM)
-
-/atom/movable/Uncross(atom/movable/AM, atom/newloc)
- . = ..()
- if(SEND_SIGNAL(src, COMSIG_MOVABLE_UNCROSS, AM) & COMPONENT_MOVABLE_BLOCK_UNCROSS)
- return FALSE
- if(isturf(newloc) && !CheckExit(AM, newloc))
- return FALSE
-
-/atom/movable/Uncrossed(atom/movable/AM)
- SEND_SIGNAL(src, COMSIG_MOVABLE_UNCROSSED, AM)
-
-/atom/movable/Bump(atom/A)
- if(!A)
- CRASH("Bump was called with no argument.")
- SEND_SIGNAL(src, COMSIG_MOVABLE_BUMP, A)
- . = ..()
- if(!QDELETED(throwing))
- throwing.hit_atom(A)
- . = TRUE
- if(QDELETED(A))
- return
- A.Bumped(src)
-
-/atom/movable/proc/forceMove(atom/destination)
- . = FALSE
- if(destination)
- . = doMove(destination)
- else
- CRASH("No valid destination passed into forceMove")
-
-/atom/movable/proc/moveToNullspace()
- return doMove(null)
-
-/atom/movable/proc/doMove(atom/destination)
- . = FALSE
- if(destination)
- if(pulledby)
- pulledby.stop_pulling()
- var/atom/oldloc = loc
- var/same_loc = oldloc == destination
- var/area/old_area = get_area(oldloc)
- var/area/destarea = get_area(destination)
-
- loc = destination
- moving_diagonally = 0
-
- if(!same_loc)
- if(oldloc)
- oldloc.Exited(src, destination)
- if(old_area && old_area != destarea)
- old_area.Exited(src, destination)
- for(var/atom/movable/AM in oldloc)
- AM.Uncrossed(src)
- var/turf/oldturf = get_turf(oldloc)
- var/turf/destturf = get_turf(destination)
- var/old_z = (oldturf ? oldturf.z : null)
- var/dest_z = (destturf ? destturf.z : null)
- if (old_z != dest_z)
- onTransitZ(old_z, dest_z)
- destination.Entered(src, oldloc)
- if(destarea && old_area != destarea)
- destarea.Entered(src, oldloc)
-
- for(var/atom/movable/AM in destination)
- if(AM == src)
- continue
- AM.Crossed(src, oldloc)
-
- Moved(oldloc, NONE, TRUE)
- . = TRUE
-
- //If no destination, move the atom into nullspace (don't do this unless you know what you're doing)
- else
- . = TRUE
- if (loc)
- var/atom/oldloc = loc
- var/area/old_area = get_area(oldloc)
- oldloc.Exited(src, null)
- if(old_area)
- old_area.Exited(src, null)
- loc = null
-
-/atom/movable/proc/onTransitZ(old_z,new_z)
- SEND_SIGNAL(src, COMSIG_MOVABLE_Z_CHANGED, old_z, new_z)
- for (var/item in src) // Notify contents of Z-transition. This can be overridden IF we know the items contents do not care.
- var/atom/movable/AM = item
- AM.onTransitZ(old_z,new_z)
-
-/atom/movable/proc/setMovetype(newval)
- movement_type = newval
-
-//Called whenever an object moves and by mobs when they attempt to move themselves through space
-//And when an object or action applies a force on src, see newtonian_move() below
-//Return 0 to have src start/keep drifting in a no-grav area and 1 to stop/not start drifting
-//Mobs should return 1 if they should be able to move of their own volition, see client/Move() in mob_movement.dm
-//movement_dir == 0 when stopping or any dir when trying to move
-/atom/movable/proc/Process_Spacemove(movement_dir = 0)
- if(has_gravity(src))
- return 1
-
- if(pulledby)
- return 1
-
- if(throwing)
- return 1
-
- if(!isturf(loc))
- return 1
-
- if(locate(/obj/structure/lattice) in range(1, get_turf(src))) //Not realistic but makes pushing things in space easier
- return 1
-
- return 0
-
-
-/atom/movable/proc/newtonian_move(direction) //Only moves the object if it's under no gravity
- if(!loc || Process_Spacemove(0))
- inertia_dir = 0
- return 0
-
- inertia_dir = direction
- if(!direction)
- return 1
- inertia_last_loc = loc
- SSspacedrift.processing[src] = src
- return 1
-
/atom/movable/proc/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
set waitfor = 0
SEND_SIGNAL(src, COMSIG_MOVABLE_IMPACT, hit_atom, throwingdatum)
@@ -610,17 +319,6 @@
SSthrowing.currentrun[src] = TT
TT.tick()
-/atom/movable/proc/handle_buckled_mob_movement(newloc,direct)
- for(var/m in buckled_mobs)
- var/mob/living/buckled_mob = m
- if(!buckled_mob.Move(newloc, direct))
- forceMove(buckled_mob.loc)
- last_move = buckled_mob.last_move
- inertia_dir = last_move
- buckled_mob.inertia_dir = last_move
- return 0
- return 1
-
/atom/movable/proc/force_pushed(atom/movable/pusher, force = MOVE_FORCE_DEFAULT, direction)
return FALSE
diff --git a/code/game/atoms_movement.dm b/code/game/atoms_movement.dm
new file mode 100644
index 0000000000..f862b87b7a
--- /dev/null
+++ b/code/game/atoms_movement.dm
@@ -0,0 +1,306 @@
+// File for movement procs for atom/movable
+
+
+////////////////////////////////////////
+// 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, direct=0)
+ . = FALSE
+ if(!newloc || newloc == loc)
+ return
+
+ if(!direct)
+ direct = get_dir(src, newloc)
+ setDir(direct)
+
+ if(!loc.Exit(src, newloc))
+ return
+
+ if(!newloc.Enter(src, src.loc))
+ return
+
+ // Past this is the point of no return
+ var/atom/oldloc = loc
+ var/area/oldarea = get_area(oldloc)
+ var/area/newarea = get_area(newloc)
+ loc = newloc
+ . = TRUE
+ oldloc.Exited(src, newloc)
+ if(oldarea != newarea)
+ oldarea.Exited(src, newloc)
+
+ for(var/i in oldloc)
+ if(i == src) // Multi tile objects
+ continue
+ var/atom/movable/thing = i
+ thing.Uncrossed(src)
+
+ newloc.Entered(src, oldloc)
+ if(oldarea != newarea)
+ newarea.Entered(src, oldloc)
+
+ for(var/i in loc)
+ if(i == src) // Multi tile objects
+ continue
+ var/atom/movable/thing = i
+ thing.Crossed(src)
+//
+////////////////////////////////////////
+
+/atom/movable/Move(atom/newloc, direct)
+ var/atom/movable/pullee = pulling
+ var/turf/T = loc
+ if(pulling)
+ if(pullee && get_dist(src, pullee) > 1)
+ stop_pulling()
+
+ if(pullee && pullee.loc != loc && !isturf(pullee.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.")
+ stop_pulling()
+ if(!loc || !newloc)
+ return FALSE
+ var/atom/oldloc = loc
+
+ if(loc != newloc)
+ if (!(direct & (direct - 1))) //Cardinal move
+ . = ..()
+ else //Diagonal move, split it into cardinal moves
+ moving_diagonally = FIRST_DIAG_STEP
+ var/first_step_dir
+ // The `&& moving_diagonally` checks are so that a forceMove taking
+ // place due to a Crossed, Bumped, etc. call will interrupt
+ // the second half of the diagonal movement, or the second attempt
+ // at a first half if step() fails because we hit something.
+ if (direct & NORTH)
+ if (direct & EAST)
+ if (step(src, NORTH) && moving_diagonally)
+ first_step_dir = NORTH
+ moving_diagonally = SECOND_DIAG_STEP
+ . = step(src, EAST)
+ else if (moving_diagonally && step(src, EAST))
+ first_step_dir = EAST
+ moving_diagonally = SECOND_DIAG_STEP
+ . = step(src, NORTH)
+ else if (direct & WEST)
+ if (step(src, NORTH) && moving_diagonally)
+ first_step_dir = NORTH
+ moving_diagonally = SECOND_DIAG_STEP
+ . = step(src, WEST)
+ else if (moving_diagonally && step(src, WEST))
+ first_step_dir = WEST
+ moving_diagonally = SECOND_DIAG_STEP
+ . = step(src, NORTH)
+ else if (direct & SOUTH)
+ if (direct & EAST)
+ if (step(src, SOUTH) && moving_diagonally)
+ first_step_dir = SOUTH
+ moving_diagonally = SECOND_DIAG_STEP
+ . = step(src, EAST)
+ else if (moving_diagonally && step(src, EAST))
+ first_step_dir = EAST
+ moving_diagonally = SECOND_DIAG_STEP
+ . = step(src, SOUTH)
+ else if (direct & WEST)
+ if (step(src, SOUTH) && moving_diagonally)
+ first_step_dir = SOUTH
+ moving_diagonally = SECOND_DIAG_STEP
+ . = step(src, WEST)
+ else if (moving_diagonally && step(src, WEST))
+ first_step_dir = WEST
+ moving_diagonally = SECOND_DIAG_STEP
+ . = step(src, SOUTH)
+ if(moving_diagonally == SECOND_DIAG_STEP)
+ if(!.)
+ setDir(first_step_dir)
+ else if (!inertia_moving)
+ inertia_next_move = world.time + inertia_move_delay
+ newtonian_move(direct)
+ moving_diagonally = 0
+ return
+
+ if(!loc || (loc == oldloc && oldloc != newloc))
+ last_move = 0
+ return
+
+ if(.)
+ Moved(oldloc, direct)
+
+ if(. && pulling && pulling == pullee) //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
+ if(get_dist(src, pulling) > 1 || (moving_diagonally != SECOND_DIAG_STEP && ((pull_dir - 1) & pull_dir)))
+ pulling.Move(T, get_dir(pulling, T)) //the pullee tries to reach our previous position
+ if(pulling && get_dist(src, pulling) > 1) //the pullee couldn't keep up
+ stop_pulling()
+ 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.
+ pulledby.stop_pulling()
+
+ last_move = direct
+ setDir(direct)
+ if(. && has_buckled_mobs() && !handle_buckled_mob_movement(loc,direct)) //movement failed due to buckled mob(s)
+ return FALSE
+
+/atom/movable/proc/handle_buckled_mob_movement(newloc,direct)
+ for(var/m in buckled_mobs)
+ var/mob/living/buckled_mob = m
+ if(!buckled_mob.Move(newloc, direct))
+ forceMove(buckled_mob.loc)
+ last_move = buckled_mob.last_move
+ inertia_dir = last_move
+ buckled_mob.inertia_dir = last_move
+ return FALSE
+ return TRUE
+
+//Called after a successful Move(). By this point, we've already moved
+/atom/movable/proc/Moved(atom/OldLoc, Dir, Forced = FALSE)
+ SEND_SIGNAL(src, COMSIG_MOVABLE_MOVED, OldLoc, Dir, Forced)
+ if (!inertia_moving)
+ inertia_next_move = world.time + inertia_move_delay
+ newtonian_move(Dir)
+ if (length(client_mobs_in_contents))
+ update_parallax_contents()
+
+ 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/AM)
+ . = TRUE
+ SEND_SIGNAL(src, COMSIG_MOVABLE_CROSS, AM)
+ return CanPass(AM, AM.loc, TRUE)
+
+//oldloc = old location on atom, inserted when forceMove is called and ONLY when forceMove is called!
+/atom/movable/Crossed(atom/movable/AM, oldloc)
+ SEND_SIGNAL(src, COMSIG_MOVABLE_CROSSED, AM)
+
+/atom/movable/Uncross(atom/movable/AM, atom/newloc)
+ . = ..()
+ if(SEND_SIGNAL(src, COMSIG_MOVABLE_UNCROSS, AM) & COMPONENT_MOVABLE_BLOCK_UNCROSS)
+ return FALSE
+ if(isturf(newloc) && !CheckExit(AM, newloc))
+ return FALSE
+
+/atom/movable/Uncrossed(atom/movable/AM)
+ SEND_SIGNAL(src, COMSIG_MOVABLE_UNCROSSED, AM)
+
+/atom/movable/Bump(atom/A)
+ if(!A)
+ CRASH("Bump was called with no argument.")
+ SEND_SIGNAL(src, COMSIG_MOVABLE_BUMP, A)
+ . = ..()
+ if(!QDELETED(throwing))
+ throwing.hit_atom(A)
+ . = TRUE
+ if(QDELETED(A))
+ return
+ A.Bumped(src)
+
+/atom/movable/proc/onTransitZ(old_z,new_z)
+ SEND_SIGNAL(src, COMSIG_MOVABLE_Z_CHANGED, old_z, new_z)
+ for (var/item in src) // Notify contents of Z-transition. This can be overridden IF we know the items contents do not care.
+ var/atom/movable/AM = item
+ AM.onTransitZ(old_z,new_z)
+
+/atom/movable/proc/setMovetype(newval)
+ movement_type = newval
+
+///////////// FORCED MOVEMENT /////////////
+
+/atom/movable/proc/forceMove(atom/destination)
+ . = FALSE
+ if(destination)
+ . = doMove(destination)
+ else
+ CRASH("No valid destination passed into forceMove")
+
+/atom/movable/proc/moveToNullspace()
+ return doMove(null)
+
+/atom/movable/proc/doMove(atom/destination)
+ . = FALSE
+ if(destination)
+ if(pulledby)
+ pulledby.stop_pulling()
+ var/atom/oldloc = loc
+ var/same_loc = oldloc == destination
+ var/area/old_area = get_area(oldloc)
+ var/area/destarea = get_area(destination)
+
+ loc = destination
+ moving_diagonally = 0
+
+ if(!same_loc)
+ if(oldloc)
+ oldloc.Exited(src, destination)
+ if(old_area && old_area != destarea)
+ old_area.Exited(src, destination)
+ for(var/atom/movable/AM in oldloc)
+ AM.Uncrossed(src)
+ var/turf/oldturf = get_turf(oldloc)
+ var/turf/destturf = get_turf(destination)
+ var/old_z = (oldturf ? oldturf.z : null)
+ var/dest_z = (destturf ? destturf.z : null)
+ if (old_z != dest_z)
+ onTransitZ(old_z, dest_z)
+ destination.Entered(src, oldloc)
+ if(destarea && old_area != destarea)
+ destarea.Entered(src, oldloc)
+
+ for(var/atom/movable/AM in destination)
+ if(AM == src)
+ continue
+ AM.Crossed(src, oldloc)
+
+ Moved(oldloc, NONE, TRUE)
+ . = TRUE
+
+ //If no destination, move the atom into nullspace (don't do this unless you know what you're doing)
+ else
+ . = TRUE
+ if (loc)
+ var/atom/oldloc = loc
+ var/area/old_area = get_area(oldloc)
+ oldloc.Exited(src, null)
+ if(old_area)
+ old_area.Exited(src, null)
+ loc = null
+
+//Called whenever an object moves and by mobs when they attempt to move themselves through space
+//And when an object or action applies a force on src, see newtonian_move() below
+//Return 0 to have src start/keep drifting in a no-grav area and 1 to stop/not start drifting
+//Mobs should return 1 if they should be able to move of their own volition, see client/Move() in mob_movement.dm
+//movement_dir == 0 when stopping or any dir when trying to move
+/atom/movable/proc/Process_Spacemove(movement_dir = 0)
+ if(has_gravity(src))
+ return 1
+
+ if(pulledby)
+ return 1
+
+ if(throwing)
+ return 1
+
+ if(!isturf(loc))
+ return 1
+
+ if(locate(/obj/structure/lattice) in range(1, get_turf(src))) //Not realistic but makes pushing things in space easier
+ return 1
+
+ return 0
+
+/atom/movable/proc/newtonian_move(direction) //Only moves the object if it's under no gravity
+ if(!loc || Process_Spacemove(0))
+ inertia_dir = 0
+ return 0
+
+ inertia_dir = direction
+ if(!direction)
+ return 1
+ inertia_last_loc = loc
+ SSspacedrift.processing[src] = src
+ return 1
diff --git a/code/modules/mob/living/carbon/human/human_mobility.dm b/code/modules/mob/living/carbon/human/human_mobility.dm
new file mode 100644
index 0000000000..c9074e5797
--- /dev/null
+++ b/code/modules/mob/living/carbon/human/human_mobility.dm
@@ -0,0 +1,42 @@
+/mob/living/carbon/human/resist_a_rest(automatic = FALSE, ignoretimer = FALSE)
+ if(!resting || stat || attemptingstandup)
+ return FALSE
+ if(ignoretimer)
+ set_resting(FALSE, FALSE)
+ return TRUE
+ else if(!CHECK_MOBILITY(src, MOBILITY_MOVE))
+ to_chat(src, "You are unable to stand up right now.")
+ else
+ var/totaldelay = 3 //A little bit less than half of a second as a baseline for getting up from a rest
+ if(getStaminaLoss() >= STAMINA_SOFTCRIT)
+ to_chat(src, "You're too exhausted to get up!")
+ return FALSE
+ attemptingstandup = TRUE
+ var/health_deficiency = max((maxHealth - (health - getStaminaLoss()))*0.5, 0)
+ if(!has_gravity())
+ health_deficiency = health_deficiency*0.2
+ totaldelay += health_deficiency
+ var/standupwarning = "[src] and everyone around them should probably yell at the dev team"
+ switch(health_deficiency)
+ if(-INFINITY to 10)
+ standupwarning = "[src] stands right up!"
+ if(10 to 35)
+ standupwarning = "[src] tries to stand up."
+ if(35 to 60)
+ standupwarning = "[src] slowly pushes [p_them()]self upright."
+ if(60 to 80)
+ standupwarning = "[src] weakly attempts to stand up."
+ if(80 to INFINITY)
+ standupwarning = "[src] struggles to stand up."
+ var/usernotice = automatic ? "You are now getting up. (Auto)" : "You are now getting up."
+ visible_message("[standupwarning]", usernotice, vision_distance = 5)
+ if(do_after(src, totaldelay, target = src, required_mobility_flags = MOBILITY_RESIST))
+ set_resting(FALSE, TRUE)
+ attemptingstandup = FALSE
+ return TRUE
+ else
+ visible_message("[src] falls right back down.", "You fall right back down.")
+ attemptingstandup = FALSE
+ if(has_gravity())
+ playsound(src, "bodyfall", 20, 1)
+ return FALSE
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index e26d65adee..1bd35bb867 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -550,30 +550,6 @@
var/obj/item/item = i
SEND_SIGNAL(item, COMSIG_ITEM_WEARERCROSSED, AM)
-/mob/living/Move(atom/newloc, direct)
- if (buckled && buckled.loc != newloc) //not updating position
- if (!buckled.anchored)
- return buckled.Move(newloc, direct)
- else
- return 0
-
- var/old_direction = dir
- var/turf/T = loc
-
- if(pulling)
- update_pull_movespeed()
-
- . = ..()
-
- 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.
- pulledby.stop_pulling()
-
- if(active_storage && !(CanReach(active_storage.parent,view_only = TRUE)))
- active_storage.close(src)
-
- if(lying && !buckled && prob(getBruteLoss()*200/maxHealth))
- makeTrail(newloc, T, old_direction)
-
/mob/living/proc/makeTrail(turf/target_turf, turf/start, direction)
if(!has_gravity())
return
@@ -1115,42 +1091,6 @@
return LINGHIVE_LINK
return LINGHIVE_NONE
-/mob/living/forceMove(atom/destination)
- stop_pulling()
- if(buckled)
- buckled.unbuckle_mob(src, force = TRUE)
- if(has_buckled_mobs())
- unbuckle_all_mobs(force = TRUE)
- . = ..()
- if(.)
- if(client)
- reset_perspective()
- update_mobility() //if the mob was asleep inside a container and then got forceMoved out we need to make them fall.
-
-/mob/living/proc/update_z(new_z) // 1+ to register, null to unregister
- if(isnull(new_z) && audiovisual_redirect)
- return
- if (registered_z != new_z)
- if (registered_z)
- SSmobs.clients_by_zlevel[registered_z] -= src
- if (client || audiovisual_redirect)
- if (new_z)
- SSmobs.clients_by_zlevel[new_z] += src
- for (var/I in length(SSidlenpcpool.idle_mobs_by_zlevel[new_z]) to 1 step -1) //Backwards loop because we're removing (guarantees optimal rather than worst-case performance), it's fine to use .len here but doesn't compile on 511
- var/mob/living/simple_animal/SA = SSidlenpcpool.idle_mobs_by_zlevel[new_z][I]
- if (SA)
- SA.toggle_ai(AI_ON) // Guarantees responsiveness for when appearing right next to mobs
- else
- SSidlenpcpool.idle_mobs_by_zlevel[new_z] -= SA
-
- registered_z = new_z
- else
- registered_z = null
-
-/mob/living/onTransitZ(old_z,new_z)
- ..()
- update_z(new_z)
-
/mob/living/MouseDrop(mob/over)
. = ..()
var/mob/living/user = usr
diff --git a/code/modules/mob/living/living_mobility.dm b/code/modules/mob/living/living_mobility.dm
index af9db25011..6222ee4ab7 100644
--- a/code/modules/mob/living/living_mobility.dm
+++ b/code/modules/mob/living/living_mobility.dm
@@ -47,48 +47,8 @@
resist_a_rest()
/mob/living/proc/resist_a_rest(automatic = FALSE, ignoretimer = FALSE) //Lets mobs resist out of resting. Major QOL change with combat reworks.
- if(!resting || stat || attemptingstandup)
- return FALSE
- if(ignoretimer)
- set_resting(FALSE, FALSE)
- return TRUE
- else if(!CHECK_MOBILITY(src, MOBILITY_MOVE))
- to_chat(src, "You are unable to stand up right now.")
- else
- var/totaldelay = 3 //A little bit less than half of a second as a baseline for getting up from a rest
- if(getStaminaLoss() >= STAMINA_SOFTCRIT)
- to_chat(src, "You're too exhausted to get up!")
- return FALSE
- attemptingstandup = TRUE
- var/health_deficiency = max((maxHealth - (health - getStaminaLoss()))*0.5, 0)
- if(!has_gravity())
- health_deficiency = health_deficiency*0.2
- totaldelay += health_deficiency
- var/standupwarning = "[src] and everyone around them should probably yell at the dev team"
- switch(health_deficiency)
- if(-INFINITY to 10)
- standupwarning = "[src] stands right up!"
- if(10 to 35)
- standupwarning = "[src] tries to stand up."
- if(35 to 60)
- standupwarning = "[src] slowly pushes [p_them()]self upright."
- if(60 to 80)
- standupwarning = "[src] weakly attempts to stand up."
- if(80 to INFINITY)
- standupwarning = "[src] struggles to stand up."
- var/usernotice = automatic ? "You are now getting up. (Auto)" : "You are now getting up."
- visible_message("[standupwarning]", usernotice, vision_distance = 5)
- if(do_after(src, totaldelay, target = src, required_mobility_flags = MOBILITY_RESIST))
- set_resting(FALSE, TRUE)
- attemptingstandup = FALSE
- return TRUE
- else
- visible_message("[src] falls right back down.", "You fall right back down.")
- attemptingstandup = FALSE
- if(has_gravity())
- playsound(src, "bodyfall", 20, 1)
- return FALSE
-
+ set_resting(FALSE, TRUE)
+ return TRUE
//Updates canmove, lying and icons. Could perhaps do with a rename but I can't think of anything to describe it.
//Robots, animals and brains have their own version so don't worry about them
diff --git a/code/modules/mob/living/living_movement.dm b/code/modules/mob/living/living_movement.dm
index 7e5fb4ec7f..c5f48880ba 100644
--- a/code/modules/mob/living/living_movement.dm
+++ b/code/modules/mob/living/living_movement.dm
@@ -58,4 +58,64 @@
remove_movespeed_modifier(MOVESPEED_ID_PRONE_DRAGGING)
/mob/living/canZMove(dir, turf/target)
- return can_zTravel(target, dir) && (movement_type & FLYING)
\ No newline at end of file
+ return can_zTravel(target, dir) && (movement_type & FLYING)
+
+/mob/living/Move(atom/newloc, direct)
+ if (buckled && buckled.loc != newloc) //not updating position
+ if (!buckled.anchored)
+ return buckled.Move(newloc, direct)
+ else
+ return 0
+
+ var/old_direction = dir
+ var/turf/T = loc
+
+ if(pulling)
+ update_pull_movespeed()
+
+ . = ..()
+
+ 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.
+ pulledby.stop_pulling()
+
+ if(active_storage && !(CanReach(active_storage.parent,view_only = TRUE)))
+ active_storage.close(src)
+
+ if(lying && !buckled && prob(getBruteLoss()*200/maxHealth))
+ makeTrail(newloc, T, old_direction)
+
+/mob/living/forceMove(atom/destination)
+ stop_pulling()
+ if(buckled)
+ buckled.unbuckle_mob(src, force = TRUE)
+ if(has_buckled_mobs())
+ unbuckle_all_mobs(force = TRUE)
+ . = ..()
+ if(.)
+ if(client)
+ reset_perspective()
+ update_mobility() //if the mob was asleep inside a container and then got forceMoved out we need to make them fall.
+
+/mob/living/proc/update_z(new_z) // 1+ to register, null to unregister
+ if(isnull(new_z) && audiovisual_redirect)
+ return
+ if (registered_z != new_z)
+ if (registered_z)
+ SSmobs.clients_by_zlevel[registered_z] -= src
+ if (client || audiovisual_redirect)
+ if (new_z)
+ SSmobs.clients_by_zlevel[new_z] += src
+ for (var/I in length(SSidlenpcpool.idle_mobs_by_zlevel[new_z]) to 1 step -1) //Backwards loop because we're removing (guarantees optimal rather than worst-case performance), it's fine to use .len here but doesn't compile on 511
+ var/mob/living/simple_animal/SA = SSidlenpcpool.idle_mobs_by_zlevel[new_z][I]
+ if (SA)
+ SA.toggle_ai(AI_ON) // Guarantees responsiveness for when appearing right next to mobs
+ else
+ SSidlenpcpool.idle_mobs_by_zlevel[new_z] -= SA
+
+ registered_z = new_z
+ else
+ registered_z = null
+
+/mob/living/onTransitZ(old_z,new_z)
+ ..()
+ update_z(new_z)
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index 136ba5af27..d4f520a611 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -655,65 +655,6 @@
/mob/living/silicon/robot/regenerate_icons()
return update_icons()
-/mob/living/silicon/robot/update_icons()
- cut_overlays()
- icon_state = module.cyborg_base_icon
- //Citadel changes start here - Allows modules to use different icon files, and allows modules to specify a pixel offset
- icon = (module.cyborg_icon_override ? module.cyborg_icon_override : initial(icon))
- if(laser)
- add_overlay("laser")//Is this even used??? - Yes borg/inventory.dm
- if(disabler)
- add_overlay("disabler")//ditto
-
- if(sleeper_g && module.sleeper_overlay)
- add_overlay("[module.sleeper_overlay]_g[sleeper_nv ? "_nv" : ""]")
- if(sleeper_r && module.sleeper_overlay)
- add_overlay("[module.sleeper_overlay]_r[sleeper_nv ? "_nv" : ""]")
- if(stat == DEAD && module.has_snowflake_deadsprite)
- icon_state = "[module.cyborg_base_icon]-wreck"
-
- if(module.cyborg_pixel_offset)
- pixel_x = module.cyborg_pixel_offset
- //End of citadel changes
-
- if(module.cyborg_base_icon == "robot")
- icon = 'icons/mob/robots.dmi'
- pixel_x = initial(pixel_x)
- if(stat != DEAD && !(IsUnconscious() ||IsStun() || IsKnockdown() || IsParalyzed() || low_power_mode)) //Not dead, not stunned.
- if(!eye_lights)
- eye_lights = new()
- if(lamp_intensity > 2)
- eye_lights.icon_state = "[module.special_light_key ? "[module.special_light_key]":"[module.cyborg_base_icon]"]_l"
- else
- eye_lights.icon_state = "[module.special_light_key ? "[module.special_light_key]":"[module.cyborg_base_icon]"]_e[is_servant_of_ratvar(src) ? "_r" : ""]"
- eye_lights.icon = icon
- add_overlay(eye_lights)
-
- if(opened)
- if(wiresexposed)
- add_overlay("ov-opencover +w")
- else if(cell)
- add_overlay("ov-opencover +c")
- else
- add_overlay("ov-opencover -c")
- if(hat)
- var/mutable_appearance/head_overlay = hat.build_worn_icon(state = hat.icon_state, default_layer = 20, default_icon_file = 'icons/mob/head.dmi')
- head_overlay.pixel_y += hat_offset
- add_overlay(head_overlay)
- update_fire()
-
- if(client && stat != DEAD && module.dogborg == TRUE)
- if(resting)
- if(sitting)
- icon_state = "[module.cyborg_base_icon]-sit"
- if(bellyup)
- icon_state = "[module.cyborg_base_icon]-bellyup"
- else if(!sitting && !bellyup)
- icon_state = "[module.cyborg_base_icon]-rest"
- cut_overlays()
- else
- icon_state = "[module.cyborg_base_icon]"
-
/mob/living/silicon/robot/proc/self_destruct()
if(emagged)
if(mmi)
@@ -1268,20 +1209,6 @@
for(var/i in connected_ai.aicamera.stored)
aicamera.stored[i] = TRUE
-/mob/living/silicon/robot/lay_down()
- . = ..()
- update_mobility()
-
-/mob/living/silicon/robot/update_mobility()
- . = ..()
- if(client && stat != DEAD && dogborg == FALSE)
- if(resting)
- cut_overlays()
- icon_state = "[module.cyborg_base_icon]-rest"
- else
- icon_state = "[module.cyborg_base_icon]"
- update_icons()
-
/mob/living/silicon/robot/proc/rest_style()
set name = "Switch Rest Style"
set category = "Robot Commands"
diff --git a/code/modules/mob/living/silicon/robot/robot_mobility.dm b/code/modules/mob/living/silicon/robot/robot_mobility.dm
index 61333d553a..c5863b523f 100644
--- a/code/modules/mob/living/silicon/robot/robot_mobility.dm
+++ b/code/modules/mob/living/silicon/robot/robot_mobility.dm
@@ -11,4 +11,5 @@
mobility_flags = newflags
update_transform()
update_action_buttons_icon()
+ update_icons()
return mobility_flags
diff --git a/code/modules/mob/living/silicon/robot/update_icons.dm b/code/modules/mob/living/silicon/robot/update_icons.dm
new file mode 100644
index 0000000000..8d40e35706
--- /dev/null
+++ b/code/modules/mob/living/silicon/robot/update_icons.dm
@@ -0,0 +1,59 @@
+/// this is bad code
+/mob/living/silicon/robot/update_icons()
+ cut_overlays()
+ icon_state = module.cyborg_base_icon
+ //Citadel changes start here - Allows modules to use different icon files, and allows modules to specify a pixel offset
+ icon = (module.cyborg_icon_override ? module.cyborg_icon_override : initial(icon))
+ if(laser)
+ add_overlay("laser")//Is this even used??? - Yes borg/inventory.dm
+ if(disabler)
+ add_overlay("disabler")//ditto
+
+ if(sleeper_g && module.sleeper_overlay)
+ add_overlay("[module.sleeper_overlay]_g[sleeper_nv ? "_nv" : ""]")
+ if(sleeper_r && module.sleeper_overlay)
+ add_overlay("[module.sleeper_overlay]_r[sleeper_nv ? "_nv" : ""]")
+ if(stat == DEAD && module.has_snowflake_deadsprite)
+ icon_state = "[module.cyborg_base_icon]-wreck"
+
+ if(module.cyborg_pixel_offset)
+ pixel_x = module.cyborg_pixel_offset
+ //End of citadel changes
+
+ if(module.cyborg_base_icon == "robot")
+ icon = 'icons/mob/robots.dmi'
+ pixel_x = initial(pixel_x)
+ if(stat != DEAD && !(IsUnconscious() ||IsStun() || IsKnockdown() || IsParalyzed() || low_power_mode)) //Not dead, not stunned.
+ if(!eye_lights)
+ eye_lights = new()
+ if(lamp_intensity > 2)
+ eye_lights.icon_state = "[module.special_light_key ? "[module.special_light_key]":"[module.cyborg_base_icon]"]_l"
+ else
+ eye_lights.icon_state = "[module.special_light_key ? "[module.special_light_key]":"[module.cyborg_base_icon]"]_e[is_servant_of_ratvar(src) ? "_r" : ""]"
+ eye_lights.icon = icon
+ add_overlay(eye_lights)
+
+ if(opened)
+ if(wiresexposed)
+ add_overlay("ov-opencover +w")
+ else if(cell)
+ add_overlay("ov-opencover +c")
+ else
+ add_overlay("ov-opencover -c")
+ if(hat)
+ var/mutable_appearance/head_overlay = hat.build_worn_icon(state = hat.icon_state, default_layer = 20, default_icon_file = 'icons/mob/head.dmi')
+ head_overlay.pixel_y += hat_offset
+ add_overlay(head_overlay)
+ update_fire()
+
+ if(client && stat != DEAD && module.dogborg == TRUE)
+ if(resting)
+ if(sitting)
+ icon_state = "[module.cyborg_base_icon]-sit"
+ if(bellyup)
+ icon_state = "[module.cyborg_base_icon]-bellyup"
+ else if(!sitting && !bellyup)
+ icon_state = "[module.cyborg_base_icon]-rest"
+ cut_overlays()
+ else
+ icon_state = "[module.cyborg_base_icon]"
diff --git a/code/modules/mob/living/silicon/silicon_mobility.dm b/code/modules/mob/living/silicon/silicon_mobility.dm
deleted file mode 100644
index 8e89242f94..0000000000
--- a/code/modules/mob/living/silicon/silicon_mobility.dm
+++ /dev/null
@@ -1,4 +0,0 @@
-/mob/living/silicon/resist_a_rest()
- if(!resting)
- return FALSE
- return set_resting(FALSE)
diff --git a/tgstation.dme b/tgstation.dme
index 7ea28a8dae..69eac2b236 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -2220,6 +2220,7 @@
#include "code\modules\mob\living\carbon\human\human_defense.dm"
#include "code\modules\mob\living\carbon\human\human_defines.dm"
#include "code\modules\mob\living\carbon\human\human_helpers.dm"
+#include "code\modules\mob\living\carbon\human\human_mobility.dm"
#include "code\modules\mob\living\carbon\human\human_movement.dm"
#include "code\modules\mob\living\carbon\human\inventory.dm"
#include "code\modules\mob\living\carbon\human\life.dm"
@@ -2268,7 +2269,6 @@
#include "code\modules\mob\living\silicon\say.dm"
#include "code\modules\mob\living\silicon\silicon.dm"
#include "code\modules\mob\living\silicon\silicon_defense.dm"
-#include "code\modules\mob\living\silicon\silicon_mobility.dm"
#include "code\modules\mob\living\silicon\silicon_movement.dm"
#include "code\modules\mob\living\silicon\ai\ai.dm"
#include "code\modules\mob\living\silicon\ai\ai_defense.dm"
@@ -2306,6 +2306,7 @@
#include "code\modules\mob\living\silicon\robot\robot_modules.dm"
#include "code\modules\mob\living\silicon\robot\robot_movement.dm"
#include "code\modules\mob\living\silicon\robot\say.dm"
+#include "code\modules\mob\living\silicon\robot\update_icons.dm"
#include "code\modules\mob\living\simple_animal\animal_defense.dm"
#include "code\modules\mob\living\simple_animal\astral.dm"
#include "code\modules\mob\living\simple_animal\constructs.dm"