When a pixloc is read from an atom, 516 is currently returning the following:
(x-1) * icon_size + step_x (y-1) * icon_size + step_y
I believe this is problematic for the same reason that pixlocs were added to alleviate: Calculating the position of an object's bounding box is unnecessarily difficult to do out of the box.
If bound_x/y are set on object A, setting object B's pixloc to A's pixloc will result in the objects being in different places.
In order to move one object's bounding box over another's, you need to do:
//Example A
A.pixloc = bound_pixloc(B,SOUTHWEST) - vector(A.bound_x, A.bound_y)
When we're placing an object in the world, we don't always know its bound_x and y. new/obj(pixloc) will vary based on the bound_x/y of the type being created. The only way we can check that before we create one is with initial, leading to the pattern for placing an object exactly at the bottom left corner of a target's bounds to be:
//Example B
var/obj/B = new/obj(bound_pixloc(target,SOUTHWEST) - vector(/obj::bound_x,/obj::bound_y))
Developers don't want to think about something's x:step_x+bound_x,y:step_y+bound_y offsets. As far as we're concerned, a movable atom is its bounding box, and the appearance that "rides" with that bounding box is aftermarket. The way that the engine needs to think about these objects for the purposes of their relationship with the view sending algorithm is at odds with how the user wants to think about objects' locations in the world. It's why Kaiocode and my movement library both exist.
The current approach is useful if you want to figure out where the atom's visual extents are, but that pattern is used far less frequently, and only for more advanced systems than trying to figure out where the bounding box is. 99 times out of 100 that we're going to access a pixloc, we're doing it to figure out where the bounding box is in the world. For new users, it will be much easier to make pixlocs correspond to bounds.
If pixlocs are changed to return the following:
(x-1) * icon_size + step_x + bound_x (y-1) * icon_size + step_y + bound_y
And then when assigned to the movable, being relative to the bounds, they would be much easier to use.
This is the result:
//Example A
A.pixloc = bound_pixloc(B,SOUTHWEST)
//Example B
var/obj/B = new/obj(bound_pixloc(target,SOUTHWEST))
I prepared a test environment to demonstrate the deficiencies.
Directions:
- F: Change mob bounds / icon (1,1 to 32,32 / 33,33 to 64,64)
- Click turf: Move teleport target
- Q: Teleport to target
- Mouse Hover turf: set hover target
- E: Place hover marker with bound_xy, Shift+E uses pixel_w/z
- R: Make marker circle with bound_xy, Shift+R uses pixel_w/z
- R: Make marker circle with bound_xy, Shift+R uses pixel_w/z
global.janked can be set on line 30 of the code. When it is 1, the problems will be present.
When it is 0, it will be using less intuitive code to avoid the problems.
Your statpanel will show you info about your mob's position in the world, pixlocs, etc.
Check the warnings in the compiler log to get detailed into and instructions on each issue.