ID:195087
 
//  Title: Turf Borders
// Credit to: Hiead
// Contributed by: Hiead

/*
This snippet was written to show an example of how one
can apply imaginary "borders" to turfs, disallowing movable
atoms from entering or exiting from specific directions.

For example, a turf with NORTH and EAST borders:
borders = NORTH|EAST

will not allow movable atoms to enter from a NORTH, EAST,
or NORTHEAST direction, and it will prevent movable atoms
from exiting in a NORTH, EAST, or NORTHEAST direction.
*/


turf/var/borders = 0 // bit-flagged value determining directional

atom/movable/Move(nLoc, nDir)
if(nDir)
// We need to split the dir into segments because otherwise,
// if we just flagged against the original dir,
// it would block movement when traveling NORTHEAST even if
// NORTH and EAST were not included as borders
var/d1 = nDir
var/d2 = 0
if(d1 & NORTH && d1 != NORTH)
d2 = d1 ^ NORTH
d1 = NORTH

else if(d1 & SOUTH && d1 != SOUTH)
d2 = d1 ^ SOUTH
d1 = SOUTH

if(isturf(loc)) // If not a turf, it won't have our borders!
var/turf/currLoc = loc
if(currLoc.borders & d1 && (d2 ? currLoc.borders & d2 : TRUE))
return FALSE

if(isturf(nLoc))
var/turf/newLoc = nLoc
if(newLoc.borders & turn(d1, 180) \
&& (d2 ? newLoc.borders & turn(d2, 180) : TRUE))

return FALSE
. = ..()

///*
// Testing Code/Sample Implementation:

turf/limited_exit/borders = EAST|NORTH|WEST

//*/


Hiead
An alternative would be to change the turf's Enter()/Exit()

e.g.
turf
var/borders = 0

Enter(atom/movable/atom)
if(atom.dir & borders)
return 0

return ..()

Exit(atom/movable/atom)
if(atom.dir & borders)
return 0

return ..()


This way, you'll avoid extra checks each time you move... =)
In response to DivineO'peanut
DivineO'peanut wrote:
An alternative would be to change the turf's Enter()/Exit()

e.g.
> turf
> var/borders = 0
>
> Enter(atom/movable/atom)
> if(atom.dir & borders)
> return 0
>
> return ..()
>
> Exit(atom/movable/atom)
> if(atom.dir & borders)
> return 0
>
> return ..()
>

This way, you'll avoid extra checks each time you move... =)

Well, I wrote it the way I did so that the checks wouldn't be dependent on dir, because I for some reason put it in my mind that dir could be changed (or, eh, not changed) during movement before Enter/Exit is called. I suppose it is probably consistent that those will be called while the atom's dir is that of the movement, so using Enter and Exit would probably be just as safe.

Also, note that your if(atom.dir & borders) isn't the same as my check; if you notice my comments, you'll see that there are different effects of checking if(borders & NORTH && borders & EAST) than checking if(borders & NORTHEAST).

Hiead
Very handy snippet, but I have a few comments. I hope you won't take offense at my tampering!

> atom/movable/Move(nLoc, nDir)
> if(nDir)

The nDir may not correspond to the direction of movement. For instance some movement systems allow you to strafe sideways and backwards or move completely independently of your facing. Most of my projects use the Dir argument to keep the mob facing the correct direction when they teleport to far off turfs.

I would check if nLoc and loc are turfs at the beginning, then see if they are at a distance of 1 before proceeding with the border check. If so, nDir should be set to get_dir(loc, nLoc).

You don't really need to split the component directions out of the original. You want to see if the turf's border completely occludes the direction of movement. You can just check
        if((T.borders & nDir) == nDir)



The full proc with my changes:
//  Title: Turf Borders
// Credit to: Hiead (modified by Shadowdarke)
// Contributed by: Hiead

/*
This snippet was written to show an example of how one
can apply imaginary "borders" to turfs, disallowing movable
atoms from entering or exiting from specific directions.

For example, a turf with NORTH and EAST borders:
borders = NORTH|EAST

will not allow movable atoms to enter from a NORTH, EAST,
or NORTHEAST direction, and it will prevent movable atoms
from exiting in a NORTH, EAST, or NORTHEAST direction.
*/


turf/var/borders = 0 // bit-flagged value determining directional

atom/movable/Move(nLoc)
if(isturf(loc) && isturf(nLoc) && get_dist(loc, nLoc) == 1)
var/nDir = get_dir(loc, nLoc)

var/turf/T = loc
if((T.borders & nDir) == nDir)
return FALSE

T = nLoc
nDir = turn(nDir,180)
if((T.borders & nDir) == nDir)
return FALSE
. = ..()

///*
// Testing Code/Sample Implementation:

turf/limited_exit/borders = EAST|NORTH|WEST

//*/