ID:1543263
 
Not Feasible
Applies to:Dream Seeker
Status: Not Feasible

Implementing this feature is not possible now or in the foreseeable future
Is there a reason why directly editing the x/y vars of an object, causing it to end up in a different area, does not call area/Entered()?

It causes the object to end up in the area's contents list, so why does it bypass Enter/Entered?

If this feature won't be added, does anyone know of a workaround for this?
Write your own modifier proc?
atom/movable/proc/set_loc(x=src.x,y=src.y,z=src.z)
var/turf/t = locate(x,y,z)
if(t)
loc = t
t.loc.Entered(src)


[edit] woops, noticed you said area.entered. altered snippet.
Setting the x,y,z coordinates or loc var directly have never called Enter(ed)/Exit(ed), by design.

If you want those to be taken into account, you should use Move().
This is a major mistake I see a lot of BYOND developers make. Generally speaking, a lot of code is written given the assumption that a player will always exit an area after entering it, or that a player will always be moving by their own power on a call to Move().

In practice, I strongly recommend avoiding assignment of loc, the manual changing of x,y,z, and the manual changing of step_x/step_y. This invariably leads to problems. Instead, I recommend the use of something like this:

#define MOVE_SELF 1 //moving under own power
#define MOVE_FORCE 2 //force the move to succeed no matter what
#define MOVE_TELEPORT 4 //this isn't a contiguous move
#define MOVE_PHYSICAL 8 //not moving under own power, but doesn't need to succeed

atom/movable
Move(atom/NewLoc,Dir=0,step_x=0,step_y=0,move_type=MOVE_SELF)
var/atom/ol = src.loc
var/odir = src.dir
var/osx = src.step_x
var/osy = src.step_y
. = ..()
if(.)
Moved(ol,odir,osx,osy,move_type)
proc
Moved(atom/oloc,odir=0,osx=0,osy=0,move_type=MOVE_SELF)


Now, there's some age-old wisdom floating around the forums that if you modify Move(), you are going to wind up with massive CPU overhead and your game's going to be broken. This logic was spread even by Forum_Account back in the day, and it's... Well, just wrong.

Yes, calling Move() takes a bit longer than just setting the loc manually. Yes, subsequent calls to Enter()/Exit() are going to take a bit. Yes, Cross()/Uncross() takes a little time. However, the trick is to use as much built-in behavior as possible, and write your code as an extension thereof, not as a total replacement. Also, ensuring your branching logic is only tested where it needs to be, and there are no redundant branches is of the utmost importance.

In the end, though, writing compact, modular, and simplistic code like you see me share on these forums a lot of the time? It takes planning and forethought. You need to ensure that other functions are going to be able to know when events are going on around them that they are going to need access to, and if you are just setting X/Y values, you have to rely on polling for updates every frame later on instead of detecting changes as they occur.
Thanks. Yea too bad my code already has like 9999 instances of directly setting the x/y/loc variables. I am not looking forward to going in and changing those all to Move()
Lummox JR resolved issue (Not Feasible)
Directly changing x, y, or z is akin to directly changing loc. This does not call Move() by design, and therefore does not call Exited(), Entered(), etc. also by design.

A simple two-way teleporter clarifies why we would never want to change this behavior. Each one has an Entered() proc that sends the atom that just stepped on them to the other end, via changing loc directly. If the loc change triggered another Entered() call, you'd have an infinite recursion, forcing some kind of hack job to change that.

In other words, this would hugely change the behavior of existing games. But even if those were given legacy support, it's still not a good idea. There needs to be a way to bypass all the built-in movement stuff, and the current method of simply not calling Move() is ideal for that. If you don't want to call Move() (because among other reasons, maybe you have a concern about it being blocked), then I suggest you roll your own loc-changing proc that always forces the move and calls Exited/Entered() on the areas and/or turfs yourself.