mirror of
https://github.com/yogstation13/Yogstation.git
synced 2025-02-26 09:04:50 +00:00
105 lines
4.3 KiB
Plaintext
105 lines
4.3 KiB
Plaintext
/*
|
|
Adjacency proc for determining touch range
|
|
|
|
This is mostly to determine if a user can enter a square for the purposes of touching something.
|
|
Examples include reaching a square diagonally or reaching something on the other side of a glass window.
|
|
|
|
This is calculated by looking for border items, or in the case of clicking diagonally from yourself, dense items.
|
|
This proc will NOT notice if you are trying to attack a window on the other side of a dense object in its turf. There is a window helper for that.
|
|
|
|
Note that in all cases the neighbor is handled simply; this is usually the user's mob, in which case it is up to you
|
|
to check that the mob is not inside of something
|
|
*/
|
|
/atom/proc/Adjacent(atom/neighbor) // basic inheritance, unused
|
|
return 0
|
|
|
|
// Not a sane use of the function and (for now) indicative of an error elsewhere
|
|
/area/Adjacent(var/atom/neighbor)
|
|
CRASH("Call to /area/Adjacent(), unimplemented proc")
|
|
|
|
|
|
/*
|
|
Adjacency (to turf):
|
|
* If you are in the same turf, always true
|
|
* If you are vertically/horizontally adjacent, ensure there are no border objects
|
|
* If you are diagonally adjacent, ensure you can pass through at least one of the mutually adjacent square.
|
|
* Passing through in this case ignores anything with the LETPASSTHROW pass flag, such as tables, racks, and morgue trays.
|
|
*/
|
|
/turf/Adjacent(atom/neighbor, atom/target = null, atom/movable/mover = null)
|
|
var/turf/T0 = get_turf(neighbor)
|
|
|
|
if(T0 == src) //same turf
|
|
return TRUE
|
|
|
|
if(get_dist(src, T0) > 1 || z != T0.z) //too far
|
|
return FALSE
|
|
|
|
// Non diagonal case
|
|
if(T0.x == x || T0.y == y)
|
|
// Check for border blockages
|
|
return T0.ClickCross(get_dir(T0,src), border_only = 1, target_atom = target, mover = mover) && src.ClickCross(get_dir(src,T0), border_only = 1, target_atom = target, mover = mover)
|
|
|
|
// Diagonal case
|
|
var/in_dir = get_dir(T0,src) // eg. northwest (1+8) = 9 (00001001)
|
|
var/d1 = in_dir&3 // eg. north (1+8)&3 (0000 0011) = 1 (0000 0001)
|
|
var/d2 = in_dir&12 // eg. west (1+8)&12 (0000 1100) = 8 (0000 1000)
|
|
|
|
for(var/d in list(d1,d2))
|
|
if(!T0.ClickCross(d, border_only = 1, target_atom = target, mover = mover))
|
|
continue // could not leave T0 in that direction
|
|
|
|
var/turf/T1 = get_step(T0,d)
|
|
if(!T1 || T1.density)
|
|
continue
|
|
if(!T1.ClickCross(get_dir(T1,src), border_only = 0, target_atom = target, mover = mover) || !T1.ClickCross(get_dir(T1,T0), border_only = 0, target_atom = target, mover = mover))
|
|
continue // couldn't enter or couldn't leave T1
|
|
|
|
if(!src.ClickCross(get_dir(src,T1), border_only = 1, target_atom = target, mover = mover))
|
|
continue // could not enter src
|
|
|
|
return 1 // we don't care about our own density
|
|
|
|
return 0
|
|
|
|
/*
|
|
Adjacency (to anything else):
|
|
* Must be on a turf
|
|
*/
|
|
/atom/movable/Adjacent(var/atom/neighbor)
|
|
if(neighbor == loc)
|
|
return TRUE
|
|
if(!isturf(loc))
|
|
return FALSE
|
|
if(loc.Adjacent(neighbor,target = neighbor, mover = src))
|
|
return TRUE
|
|
return FALSE
|
|
|
|
// This is necessary for storage items not on your person.
|
|
/obj/item/Adjacent(var/atom/neighbor, var/recurse = 1)
|
|
if(neighbor == loc)
|
|
return 1
|
|
if(isitem(loc))
|
|
if(recurse > 0)
|
|
return loc.Adjacent(neighbor,recurse - 1)
|
|
return 0
|
|
return ..()
|
|
|
|
/*
|
|
This checks if you there is uninterrupted airspace between that turf and this one.
|
|
This is defined as any dense ON_BORDER_1 object, or any dense object without LETPASSTHROW.
|
|
The border_only flag allows you to not objects (for source and destination squares)
|
|
*/
|
|
/turf/proc/ClickCross(target_dir, border_only, target_atom = null, atom/movable/mover = null)
|
|
for(var/obj/O in src)
|
|
if((mover && O.CanPass(mover,get_step(src,target_dir))) || (!mover && !O.density))
|
|
continue
|
|
if(O == target_atom || O == mover || (O.pass_flags & LETPASSTHROW)) //check if there's a dense object present on the turf
|
|
continue // LETPASSTHROW is used for anything you can click through (or the firedoor special case, see above)
|
|
|
|
if( O.flags_1&ON_BORDER_1) // windows are on border, check them first
|
|
if( O.dir & target_dir || O.dir & (O.dir-1) ) // full tile windows are just diagonals mechanically
|
|
return 0 //O.dir&(O.dir-1) is false for any cardinal direction, but true for diagonal ones
|
|
else if( !border_only ) // dense, not on border, cannot pass over
|
|
return 0
|
|
return 1
|