ID:814392
 
Applies to:DM Language
Status: Open

Issue hasn't been assigned a status value.
I would like to see a new built-in feature that will allow me to determine what side of a bounding box is overlapping. This may be confusing, so here is an example:

Say X is a mob, and Y is something it is not supposed to be on. Now, if I run a check and see that X is overlapping Y via bounds_dist(), then I can catch X...but I can't do much about it. My first thought would be to modify it's step_x and step_y to shove it off, but I don't know which way to shove it. If X is overlapping Y's right side by 3 pixels, I want add 3 to X's step_x. I have no good way of figuring out that information, though.

This is why I would like something along the lines of bounds_side(a, b) (Although I'm not the best name-maker around), that will tell me which side of b a is overlapping.
Here is a quick example of a workaround for this, but it is much more bulky than need-be:
atom/proc
shove_off(atom/b) // Shove src off of b.
var/d = 0
var/list/l
var/atom/movable/a = src
d = abs(bounds_dist(a, b)) // They are overlapping, which means bounds_dist() will be negative - lets make it positive

l = obounds(a, d, 0) // check to the right (EAST)
if(!(b in l))
a.step_x += d
return

l = obounds(a, 0, d) // check up (NORTH)
if(!(b in l))
a.step_y += d
return

l = obounds(a, -d, 0) // check to the left (WEST)
if(!(b in l))
a.step_x -= d
return

l = obounds(a, 0, -d) // check down (SOUTH)
if(!(b in l))
a.step_y -= d
return

l = obounds(a, d, d) // check right and up (NORTHEAST)
if(!(b in l))
a.step_x += d
a.step_y += d
return

l = obounds(a, -d, -d) // check left and down (SOUTHWEST)
if(!(b in l))
a.step_x -= d
a.step_y -= d
return

l = obounds(a, -d, d) // check left and up (NORTHWEST)
if(!(b in l))
a.step_x -= d
a.step_y += d
return

l = obounds(a, d, -d) // check right and down (SOUTHEAST)
if(!(b in l))
a.step_x += d
a.step_y -= d
return
It's only bulkier than need-be because of the way you're programming it. There's already a way easier and more clean way of going about this. Here's an incomplete example:
proc/bounds_side(atom/movable/case, atom/movable/check)

if(check in obounds(case, case.bound_width, case.bound_height))

var/real_x = check.real_x()
if(global.in_between(case.real_x(), real_x, real_x + check.bound_width))
. |= WEST
// Etc...

return .

else return 0

atom/movable/proc

// Assumes world.icon_size is a numeric literal.
real_x() return src.x * world.icon_size + step_x
real_y() return src.y * world.icon_size + step_y

proc
in_between(x, min, max) return ((x >= min) && (x <= max))

I'd be more than happy to assist you, given you repost this in the Developers Help section. There just isn't a need for this feature, and I'd be more than happy to assist my skinny little buddy if you repost :). I'll even complete the code I've provided for you, if you repost. This information does belong in there, hence why I haven't posted a complete example; just a demonstration.