Files
vgstation13/code/modules/multiz/falling.dm
ShiftyRail 409ae193c2 The Postman always ring twice (#30551)
* Revert "Revert "Revert "Lights out tonight (trouble in the Heartland) (#30526)" (#30527)" (#30529)"

This reverts commit 5ae655387f.

* fixes urgent problems

* fixes the problem with zooming out

* gliding

* on the beach

* suffer not the lag

* fixes mesons and fire
2021-09-07 09:58:07 +01:00

153 lines
4.0 KiB
Plaintext

////////////////////////////
//FALLING STUFF
//If atom stands under open space, it can prevent fall, or not
/atom/proc/can_prevent_fall(var/atom/movable/mover, var/turf/coming_from)
return (!Cross(mover, coming_from))
/atom/proc/get_gravity()
var/area/A = get_area(src)
if(istype(A))
return A.gravity
return 1
/atom
var/fall_lock = FALSE // Stops fall() being called during gravity spawn delay
var/zs_fallen = 0 // Gets reset if it hits something, for fall damage
//Holds fall checks that should not be overriden by children
/atom/movable/proc/fall()
if(fall_lock)
return
if(!isturf(loc))
return
var/turf/below = GetBelow(src)
if(!below)
return
var/turf/bottom = null
for(bottom = GetBelow(src); isopenspace(bottom); bottom = GetBelow(bottom))
if(istype(bottom,/turf/space))
return
var/turf/T = loc
if(!T.CanZPass(src, DOWN) || !below.CanZPass(src, DOWN))
return
var/gravity = get_gravity()
// No gravity in space, apparently.
if(!gravity) //Polaris uses a proc, has_gravity(), for this
return
fall_lock = TRUE
spawn(4 / gravity) // Now we use a delay of 4 ticks divided by the gravity.
fall_lock = FALSE
// We're in a new loc most likely, so check all this again
below = GetBelow(src)
if(!below)
return
bottom = null
for(bottom = GetBelow(src); isopenspace(bottom); bottom = GetBelow(bottom))
if(istype(bottom,/turf/space))
return
T = loc
if(!T.CanZPass(src, DOWN) || !below.CanZPass(src, DOWN))
return
gravity = get_gravity()
if(!gravity)
return
/*if(throwing) This was causing odd behavior where things wouldn't stop.
return*/
if(can_fall())
// We spawn here to let the current move operation complete before we start falling. fall() is normally called from
// Entered() which is part of Move(), by spawn()ing we let that complete. But we want to preserve if we were in client movement
// or normal movement so other move behavior can continue.
var/mob/M = src
var/is_client_moving = (ismob(M) && M.client && M.client.moving)
spawn(0)
if(is_client_moving) M.client.moving = 1
handle_fall(below)
if(is_client_moving) M.client.moving = 0
// TODO - handle fall on damage!
//For children to override
/atom/movable/proc/can_fall()
if(anchored)
return FALSE
return TRUE
/obj/effect/can_fall()
return FALSE
/obj/effect/decal/cleanable/can_fall()
return TRUE
// These didn't fall anyways but better to nip this now just incase.
/atom/movable/light/can_fall()
return FALSE
// Function handling going over open spaces, pre-extension to normal throw hit checks
/atom/movable/hit_check(var/speed, mob/user)
if(isopenspace(get_turf(src)))
src.fall()
. = ..()
// Actually process the falling movement and impacts.
/atom/movable/proc/handle_fall(var/turf/landing)
var/turf/oldloc = loc
// Check if there is anything in our turf we are standing on to prevent falling.
for(var/obj/O in loc)
if(!O.CanFallThru(src, landing))
return FALSE
// Supermatter dusting things falling on them
var/obj/machinery/power/supermatter/SM = locate(/obj/machinery/power/supermatter) in landing
if(SM)
forceMove(SM.loc)
SM.Consume(src)
// See if something in turf below prevents us from falling into it.
for(var/atom/A in landing)
if(!A.Cross(src, src.loc, 1, 0))
return FALSE
// TODO - Stairs should operate thru a different mechanism, not falling, to allow side-bumping.
// Now lets move there!
if(!Move(landing))
return 1
var/obj/structure/stairs/down_stairs = locate(/obj/structure/stairs) in landing
// Detect if we made a silent landing.
if(down_stairs)
return 1
if(isopenspace(oldloc))
oldloc.visible_message("\The [src] falls down through \the [oldloc]!", "You hear something falling through the air.")
zs_fallen++
// If the turf has density, we give it first dibs
if (landing.density && landing.CheckFall(src))
return
// First hit objects in the turf!
for(var/atom/movable/A in landing)
if(A != src && A.CheckFall(src))
return
// If none of them stopped us, then hit the turf itself
landing.CheckFall(src)