ID:575013
 
(See the best response by Forum_account.)
Code:
mob
Move(atom/newLoc,Dir=0,override=0)
if(override)
return ..()
if(!src.isCrafting)
//------------------------------
//cardinal directional movement only
var/d = get_dir(src,newLoc)
var/is_diagonal = dir & (dir-1)
if(is_diagonal)
var/d1 = d & (NORTH|SOUTH)
var/d2 = d & (EAST|WEST)
if(prob(50))
var/t = d1
d1 = d2
d2 = t
dir = d1
if(step(src,d1))
return 1
dir = d2
if(step(src,d2))
return 1
return 0
else return ..()
//-----------------------------
return FALSE


Problem description:
Above is the Move() override I use. If you pay attention to the "override" argument I have, I will tell you it is for when I want movement to succeed regardless of anything. My problem is this override argument after using it once. For some reason, the argument is then permanently set to 1, thereby making it look like the player is jumping around instead of smoothly sliding around like normal.

I noticed this after loading from a savefile, and in my mob/Read() proc I use the override argument to set the player's location to wherever they were when saved. I used the override like this in case they load when there is already another dense object where they would load into.

To me, this sounds like a bug, but I do not want to jump to conclusions since there might be something I am missing. I never used to have this problem I don't think.
I fixed my problem by changing the override movement to the following instead of just return ..().
src.loc = newLoc
newLoc.Entered(src)
return 1
Calling ..() doesn't force the mob to move, it just runs the default behavior for Move(). If you want to force them to move, you'll need to set their loc directly (which you realized).

You could also override the turf/Enter() proc to make is allow mobs to enter when override has been set. Something like this:

turf
Enter(mob/m)
if(m.allow_all_moves)
return 1
else
return ..()

mob
var
allow_all_moves = 0

Move(turf/t, d = 0, override = 0)
allow_all_moves = override

if(allow_all_moves)
return ..()

// rest of the code here...

This should also cause the turf and area's Entered() procs to be called automatically.
That's another variable I would rather not have to keep track of. I'd rather force the movement and then call the appropriate Entered() proc directly (I'm a fan of micromanagement). That is still an interesting roundabout way of accomplishing that though. Never would have thought of it.
Best response
It's easy enough to call the Entered() proc, but you're also forgetting to call the Exited() proc from the turf you left and you're not checking to see if the mob changed to a different area (to call the proper Entered() and Exited() procs there). In the end, having one extra var can be less of a problem =)
And there's no way to loop through all areas and turfs in a given coordinate?

I could just do...
src.loc.loc.Exited(src)
src.loc.Exited(src)
src.loc = newLoc
newLoc.loc.Entered(src)
newLoc.Entered(src)

...since there are VERY few occurrences of movement ever being forced as such. And the only other time I would be writing all of that out again, would be to do it for the obj/Move() proc.
In response to Spunky_Girl
Spunky_Girl wrote:
And there's no way to loop through all areas and turfs in a given coordinate?

Any given coordinate will only ever have one turf and one area. (multiple turfs are blended together and use the variables of the topmost one).

However, if you want all of the obj's and mob's on a turf, as well as the turf and area of that location, here's a simple snippet for you.

proc/loop_through_xyz(x, y, z)
// displays the contents of a list of atoms at x y z
var l[]
var turf/t = locate(x,y,z)
l[1] = t.loc // l[1] = /area
l[2] = t // l[2] = /turf
for(var/obj/o in t)
l += o // add objects
for(var/mob/m in t)
l += m // add mobs

for(var/i in l)
world << i // Let's see what's in there.


On a more OP related note: If you're looking to over-ride it, would only setting the loc do what you want to accomplish, rather than mucking around in Entered() and the other movement procs? ie: if(override) {loc = NewLoc; return 1}. I also don't think I understand why you're even calling Entered() there.

Spunky_Girl wrote:
And the only other time I would be writing all of that out again, would be to do it for the obj/Move() proc.

If you're doing this for obj and mob movement, it might be best for your purposes to over-ride atom/movable/Move(), from which both are derived.
Your snippet does not help me at all. I never wanted a way loop through all atoms at a given spot. I could shorten your little snippet by a few lines by using your own comment regarding using atom/movable.
proc/get_atoms_at(x,y,z)
var/list/L = new
L += locate(x,y,z) //since it returns a turf...
L[2] = locate(L[1]) //since the location of a turf is an area
for(var/atom/movable/a in L[1])
L += a
for(var/atom/a in L)
world<<a


The reason you would want to call Entered() and Exited() would be to make sure they happen since setting loc directly will completely ignore them. I have areas and turfs where stuff happens on their Exited() and Entered().

I was also referring to a method to possibly shorten even further than doing direct calls by just looping through any area/turf at the give coordinate, saving one line. I was only wondering, but now that I think about it, it wouldn't make sense.
I was also referring to a method to possibly shorten even further than doing direct calls by just looping through any area/turf at the give coordinate, saving one line. I was only wondering, but now that I think about it, it wouldn't make sense.

You'd have to check that the area of the turf you're moving to is different than the one you're moving from (which I'm guessing is what you realized).
Yeah. I should probably post the modified code haha.
src.loc = newLoc
if(src.loc.loc != newLoc.loc)
src.loc.loc.Exited(src)
newLoc.loc.Entered(src)
src.loc.Exited(src)
newLoc.Entered(src)