ID:2602560
 
Kind of solved making step size 32 makes it work fine. Anything else and it doesn't. I guess it's a bug with pixel movement or something. Still doesn't explain it working for the first location.

Code:
mob/npc
var/list/schedule

New()
..()
schedule = new
schedule += locate(1,1,1)
schedule += locate(9,9,1)
sleep(10); src.routine()


proc/routine()
for(var/i = 1, i <= src.schedule.len, i++)
while(src.loc != src.schedule[i] && src.loc)
sleep(01);step_to(src, src.schedule[i]); world << "[src.x], [src.y]"
sleep(50); return src.loc ? src.routine() : 0


Problem description:
Working on making NPCs follow a schedule. Starting with just the bare bones of it and already encountering an issue. The NPC will move to the first location fine. Then, as soon as it reaches said location it will head toward the second. This is all intended, the problem is the NPC will never enter the second location. Once it gets one tile away in this instance 8,8,1 step_to() will just continue to be called without the NPC moving. I have checked this location for a hidden obstacle none exists. I've also changed this location to several different ones and the same thing happens. Once the NPC gets within one tile, it stops and step_to() is called indefinitely. I've also put a debug message in the Bump() proc even though I don't think step_to() ever calls Bump(). Since how I understand it is, it checks a location for a dense atom before calling Move(). This turns up no results. I'm not sure what else to try at this point.

[Edit]
The NPC doesn't stop moving as soon as they enter a location one step away from the destination. Because of the pixel movement they are still taking steps toward the destination (9,9,1) while a tile away (8,8,1). They only actually stop moving right before the final step to enter the destination. I thought I would clarify that. So, it's not that step_to() is some how having the "min" argument changed.
It's not a bug with pixel movement. An atom between multiple tiles' loc var will always be the turf the bottom left of the atom's bounds occupies. Once your mob touches 9,9 its loc will still be 8,8 because the top of the bounds reaches 9,9 first. This is why it works one way and not the other - in this case stepping down makes the bottom left enter 1,1 first, which changes loc to that turf. step_to() has a return value of whether or not a step actually occurred, which you can make use of in your while() conditions as one way to solve this problem.

routine()
for(var/i = 1, i <= length(schedule), i++)
while(loc && step_to(src, schedule[i]))
sleep(1)
sleep(50)
return loc ? routine() : 0
Okay, so the step_to() trg variable isn't based on x, y location. It's based on the contents of the x, y location. This makes so much more sense now.
In response to Ulterior Motives
It's based on the distance between the bounds of both atoms, but you were combining it with what is essentially a contents check on a specific turf. But since the bounds could overlap without the turf necessarily being the "true" loc, the while condition was repeatedly true (loc != schedule[i]), constantly calling step_to() which was failing because the bounds were already overlapped, basically creating an infinite loop.
In response to Ulterior Motives
Ulterior Motives wrote:
Okay, so the step_to() trg variable isn't based on x, y location. It's based on the contents of the x, y location. This makes so much more sense now.

Trg is just an object on the map, it doesn't have to be a turf. It could be a movable object, and step_to will always go toward it (if possible) even if it's location has changed.

Also, you really don't need all those src.(variable) in your code. In the same way that you wrote schedule instead of src.schedule, you can shorten the rest of them. Furthermore, you have sleep(01) which I think was supposed to be sleep(10)?
mob/npc
var/list/schedule

New()
..()
schedule = new
schedule += locate(1,1,1)
schedule += locate(9,9,1)
sleep(10); routine()


proc/routine()
for(var/i = 1, i <= schedule.len, i++)
while(loc != schedule[i] && loc)
sleep(01);step_to(src, schedule[i]); world << "[x], [y]"
sleep(50); return loc ? routine() : 0
I know trg can be multiple things, but in this case it is a target at locate xyz. I just figured movement was still handled the same as it used to be. In that the NPC would be added to the turf's contents when it's loc was that of the turf. I should have read the updated "contents" reference. Would have saved me a ton of time testing things. lol


Sleep(01) is correct though it is the same as sleep(1). I just like using two digit numbers in my sleep and spawn procs. I might not need to use src, but I started learning DM in 2000 and have done it since then. I doubt I could break the habit.
In response to Ulterior Motives
Ulterior Motives wrote:
I know trg can be multiple things, but in this case it is a target at locate xyz. I just figured movement was still handled the same as it used to be. In that the NPC would be added to the turf's contents when it's loc was that of the turf. I should have read the updated "contents" reference. Would have saved me a ton of time testing things. lol

Locate(x,y,z) returns the turf at those coordinates. So if you were to set a variable T = locate(1,1,1), then T will be a reference to the turf at 1,1,1. I find it's often helpful to send things to the output to make sure you know what's actually going on. Locate() can return other types of objects too, but in the coordinate form it always just gives you a turf.

As far as contents goes, yes it was changed so that turfs will list objects in their contents if they overlap at all. So this:

RootAbyss wrote:
But since the bounds could overlap without the mob necessarily being in the contents of the turf

and this:

RootAbyss wrote:
An atom between multiple tiles will always be in the contents of the turf the bottom left of the atom's bounds occupies.

...are not correct! Atom between turfs will appear in all turf's contents that it overlaps!

In response to Magicsofa
Magicsofa wrote:
As far as contents goes, yes it was changed so that turfs will list objects in their contents if they overlap at all. So this:

RootAbyss wrote:
But since the bounds could overlap without the mob necessarily being in the contents of the turf

and this:

RootAbyss wrote:
An atom between multiple tiles will always be in the contents of the turf the bottom left of the atom's bounds occupies.

...are not correct! Atom between turfs will appear in all turf's contents that it overlaps!

Looking back, I did word some of it in a weird way, and I edited my posts to clear some things up. However, those quotes are both correct. The reference says it should be in all turf's contents, but unless this code is somehow lying that isn't actually the case.
I guess the second quote was not strictly incorrect, because the atom will appear in the bottom-left turf's contents. I had assumed you meant that it will only be in that turf's contents.

Try this test:
mob/verb/locs_test()
for(var/turf/T in locs)
for(var/atom/A in T)
world << A


This will output your name for as many tiles as you are overlapping.

I'm learning something new here though because I thought the if(src in T) test would have worked the same, but it doesn't. I'm not really sure why that is. I was thinking it might have something to do with the verb src setting. Perhaps the test if(src in T) is actually testing if src has access to T's verbs. In that case, I think the default behavior is to only get verbs from your singular loc, not all locs. I am quite fuzzy on this situation though so I would like confirmation from someone else. Using the verb src setting to give actions to the player is a pretty outdated way of doing things, from the old days when right-clicking to bring up context menus was more common.