ID:1837985
 
(See the best response by Lummox JR.)
So currently im working on a game with a map of 800x800. I can't quite figure it out, but I am trying to make it so that players are allowed to move across a map as if it were "round." Basically relocating the mob on a per x and per y basis. So mob walks across 400,800,1 and ends up on the other side of the map of the coordinates 400,1,1. Walks across 800,40,1 and ends up at 1,40,1. Any suggestions before i rage quit my life.
I also tried to do it using turfs if anyone can get any ideas surrounding turfs, all suggestions welcome.
You could use turf/Entered() and move stuff to the other side there. You could also have objects spawn on those turfs and do it on those object's Crossed() proc.
One of my longstanding wish list features is being able to connect maps on the edges so that this could be seamless, in which case get_step() would likely work like you hope.

Overriding turf/Entered() on the border turfs is your best option right now. It'll be the easiest way to implement this. When anything steps onto the turf, relocate it to the opposite edge of the map but just inside the border.

As for get_step(), you can't rely on the built-in pathfinding or even get_dir() to work across the map edge, so you'll have to roll your own if you go thay way. get_dir() is easiest, because you can simply compare x,y and look for differences over 400.

get_dir2(atom/A, atom/B)
var/dx = B.x - A.x
var/dy = B.y - A.y
. = 0
if(dx) . |= (dx>0) ? EAST : WEST
if(dy) . |= (dy>0) ? NORTH : SOUTH
if(abs(dx) > world.maxx/2) . ^= (EAST|WEST)
if(abs(dy) > world.maxy/2) . ^= (NORTH|SOUTH)
What if we want to move across y and just bound x and if we wanted to move acoss x, we bound y. And we manipulate mob.step between min and max x, y. Any ideas generated from that? So if we enter turf/portal and dir is N we bound x and step to min y. If we enter turf/portal and dir is S we bound x and step to max y. Vice versa with east and west dir. Any more ideas??
Tried using enter proc

Turf/Environment
Portal
Enter (mob/m, turf/portal)
Var d = get_dir (src, m)
If (is_cardinal (d))
If(NORTH)
Var x = 0
//belongs under var = 0 Usr.Move(x,world.maxy/1,1)

If(SOUTH)
Var x = 0
Usr.move(x,world.maxy,1)
If(EAST)
Var y = 0
Usr.move(world.maxx/1,y,1)
If(WEST)
Var y =0
Usr.move(world.maxx, y,1)


not sure if im close at all. There were no compiling issues however thry code had no effect to the turf at all nor did it cause any problems during gameplay. Any more advice, ideas, brain transplants?
Best response
Lots of problems:

1) You should wrap your code in <dm> ... </dm> tags to preserve indentation.

2) Capitalizing each line is a syntax error.

3) You would not use the var keyword when changing a var, and also the var you want to change would be m.x or m.y, not x/y alone (which is interpreted as src.x/y, src being the turf).

4) usr has no place in Enter(), because this is a proc, not a verb. You'd want to use m, not usr.

5) Enter() is really the wrong place to handle this. You should handle it in Entered() instead, and change the entering atom's loc directly instead of calling Move(). Instead of using get_dir(), just base your x/y changes on the turf's position.

6) Even if calling Move() were the right idea, it doesn't take coordinates directly like Move(x,y,z). You'd want to move to the turf returned by locate(x,y,z). Move() takes four parameters: the new loc, the dir used for moving, and step_x/y.
The capitalizations were a result of auto correct from my phone. I will definitely look into it further and report back later
 mob/Move()
if(src.x == world.maxx)
src.x = 2
if(src.x == 1)
src.x = world.maxx - 1
if(src.y == world.maxy)
src.y = 2
if(src.y == 1)
src.y = world.maxy - 1
.=..()


according to Nadrew and Raekwon, this works.
In response to Mikeche
That's not even close? That code doesn't even use the parameters to determine which way the user is trying to move or anything. You can't just teleport them to the other side as they may not even try to teleport across at all, and just walk away from the edge of the map.

Here's the code heavily commented for use.

mob//The player.
Move(New_Location,Direction,Step_X,Step_Y)//When they try to move.
if(!New_Location)//If it has not been determined where your going to be yet, such as going into nothing at the edge of the map for example.
var//Let's figure out where to put you.
New_X=x//Initialize this with your current X, you may not move across X so it'd be bad to put you no-where.
New_Y=y//Initialize this with your current Y, you may not move across Y so it'd be bad to put you no-where.
if(Direction&NORTH&&y==world.maxy)//If your moving NORTH and your at the top side of the map.
New_Y=1//Move you to the bottom side of the map.
if(Direction&SOUTH&&y==1)//If your moving SOUTH and your at the bottom side of the map.
New_Y=world.maxy//Move you to the top side of the map.
if(Direction&EAST&&x==world.maxx)//If your moving EAST and your at the right side of the map.
New_X=1//Move you to the left side of the map.
if(Direction&WEST&&x==1)//If your moving WEST and your at the left side of the map.
New_X=world.maxx//Move you to the right side of the map.
New_Location=locate(New_X,New_Y,z)//Set the location to the new coordinates.
//It maybe desirable to teleport the user across the map even with obstacles in the way, this code allows obstacles to block your path from across the map.
//If this is undesired behavior, and you want to always move them across the map, un-comment the code below.
/*loc=locate(New_X,New_Y,z)
return*/

//And make sure to comment out "New_Location=locate(New_X,New_Y,z)" as it'd just be useless code at this point.
..()//Allows you to move, this must be called to allow you to move normally, and to allow you to move across the map.


EDIT: Here's the code without comments, but please read the last few comments before ..() as those are important and determine if you want the player to teleport across the map even if there are obstacles in the way on the other side.

mob
Move(New_Location,Direction,Step_X,Step_Y)
if(!New_Location)
var
New_X=x
New_Y=y
if(Direction&NORTH&&y==world.maxy)
New_Y=1
if(Direction&SOUTH&&y==1)
New_Y=world.maxy
if(Direction&EAST&&x==world.maxx)
New_X=1
if(Direction&WEST&&x==1)
New_X=world.maxx
New_Location=locate(New_X,New_Y,z)
..()


In my code it allows you to also go across the map diagonally even though most people will only go NORTH/SOUTH/EAST/WEST at least it supports the diagonals.

NOTE: Step_X & Step_Y defined in the code aren't really needed either, you could remove those, I put them there simply because they are part of what is passed to move as per the reference.
With some further thought it maybe required to change the second to last line with New_Location=Locate(New_X,New_Y,z) to the following code:

            if(New_X!=x||New_Y!=y)
New_Location=locate(New_X,New_Y,z)


Someone like Lummox or someone may have to chime in on that though.

The reason I think it may be needed is ..() may be doing something by default when "New Loc" is null and you attempted to move in a direction, such as the Bump() behavior.

I'm not entirely sure if anything would be effected or not really, they'd know for sure, but if you have problems related to Bump() or just to be safe, you may go ahead and include those lines in place of what's there until there's word from them or others that might know if it would affect any other behavior otherwise.
Yeesh, you really need some whitespace in there. I'd at least put it around the binary logic operators, and for readability you should always have 1) a tab or space before // and 2) a space after the // for a comment.

As a matter of habit I also always put parentheses around any bitwise operators, because I've been burned by precedence issues in various languages.
In response to Lummox JR
Lol, yea, I went crazy especially on the commenting, that's why I just put in the un-commented version as part of an edit.

Anyways as far as things go will setting the location like I did affect any procs being called or would it be required to do as in my previous post, and only to set the location if it has changed to avoid messing with things like Bump()?
Well, you don't need to check the location change manually like that. The correct approach would be to call ..() first and use its return value. If it returned nonzero, then a move did proceed.

As I recall, though, the edge of the screen doesn't behave the way I once thought it did, and I'm not sure it'll even try to call Move() when you move offscreen that way. A more common approach for this is to have a buffer of special turfs around the edge (they don't need to literally be special turfs, as long as Move() does the check) that will transport a player to the other side of the map.
In response to Lummox JR
I tested the code before I posted, Move() is being called in those cases when your at the edge of the map and attempt to move off of it.

Although special turfs might still be required in cases where you have multiple z-levels that aren't the same size as one another, since BYOND makes the size of all z-levels uniform even if loaded from completely separate map files of different sizes.
That's very similar to what my friend Jacob843 and I came up with. We spent the entire Sunday on it and came up with this...

proc/ocean_transport(mob/humanoid/mob, turf/ocean, dir, new_z) spawn
if(istype(src, /mob/title)) return

var sx = 0, sy = 0
switch(turn(dir, 180))
if(NORTH) sy = -mob.bound_y
if(SOUTH) sy = tile_height - mob.bound_y - mob.bound_height
if(EAST) sx = -mob.bound_x
if(WEST) sx = tile_width - mob.bound_x - mob.bound_width
var tmpX, tmpY
tmpX = ocean.x
tmpY = ocean.y
if(ocean.x > 798)
tmpX = 3
else if(ocean.x < 3)
tmpX = 798
else
tmpX = ocean.x
if(ocean.y > 798)
tmpY = 3
else if(ocean.y < 3)
tmpY = 798
else
tmpY = ocean.y
mob.set_loc(get_step(locate(tmpX, tmpY, new_z), dir), sx, sy)

if(is_humanoid(mob))
mob.pulling_cart && mob.pulling_cart.set_loc(mob.loc, mob.step_x, mob.step_y)
mob.mount && mob.mount.set_loc(mob.loc, mob.step_x, mob.step_y)

turf/Environment
Ocean/Portal
Entered(mob/m, atom/oldloc)
usr << "You are entering the PvP Zone, roleplaying rules are NOT enforced! Players can freely kill and conquer territories!"
var d = get_dir(src, m) || get_dir(src, oldloc)
if(is_cardinal(d))
if(istype(m) || istype(m, /obj/Built/Boat))
ocean_transport(m, src, d, 4)

Ocean/Portal2
Entered(mob/m, atom/oldloc)
usr << "<b>You are leaving the PvP Zone, roleplaying rules enforced!</b>"
var d = get_dir(src, m) || get_dir(src, oldloc)
if(is_cardinal(d))
if(istype(m) || istype(m, /obj/Built/Boat))
ocean_transport(m, src, d, 1)


if you wanted to keep the same Z just specify in ocean_transport()
In response to Mikeche
Some parts of this code look vaguely familiar.
Well duh it's straight from hazordhu, this is what this entire post is about, you don't remember the Skype message I sent you?