ID:2347607
 
Code:
                for(var/mob/M in oview(15))
if(M == dragonRush_target && M.dead)
dragonRush_target = null
return
else if(M == dragonRush_target)
var/O
if(get_dir(src,M)==EAST||get_dir(src,M)==SOUTHEAST||get_dir(src,M)==NORTHEAST)
O = locate(M.x -1, M.y, M.z)
else if(get_dir(src,M)==WEST||get_dir(src,M)==SOUTHWEST||get_dir(src,M)==NORTHWEST)
O = locate(M.x +1, M.y, M.z)
walk_towards(src, O, 0, 0.5)


Problem description:
Above, is a quick test I tried to run.. My game is a sidescroller, and I'm trying to make walk_towards() focus on a specific location of the target. So, if walk_towards() is active. I want it to position the reference in front/behind of the of the target, whilst bumping into them. But I can't think of any solutions to this.

Both your if and your else statements are checking to see if M is equal to dragonRush_target, so what your loop is doing is closer to this:
for(var/mob/M in oview(15))
if(M == dragonRush_target)
if(M.dead)
dragonRush_target = null
return
else
var/O
if(get_dir(src,M)==EAST||get_dir(src,M)==SOUTHEAST||get_dir(src,M)==NORTHEAST)
O = locate(M.x -1, M.y, M.z)
else if(get_dir(src,M)==WEST||get_dir(src,M)==SOUTHWEST||get_dir(src,M)==NORTHWEST)
O = locate(M.x +1, M.y, M.z)
walk_towards(src, O, 0, 0.5)


See how the loop goes through every atom in view, but only does something if the atom is dragonRush_target? This is like looping through all your friends in your contacts list and calling them to ask "Are you Bob?" Just call Bob instead:
var/mob/M = dragonRush_target
if(M.dead)
dragonRush_target = null
return
else
var/O
if(get_dir(src,M)==EAST||get_dir(src,M)==SOUTHEAST||get_dir(src,M)==NORTHEAST)
O = locate(M.x -1, M.y, M.z)
else if(get_dir(src,M)==WEST||get_dir(src,M)==SOUTHWEST||get_dir(src,M)==NORTHWEST)
O = locate(M.x +1, M.y, M.z)
walk_towards(src, O, 0, 0.5)


Now notice that we return immediately if dragonRush_target is dead, so we don't need the "else" statement - that code will only ever run if the "return" statement doesn't.
var/mob/M = dragonRush_target
if(M.dead)
dragonRush_target = null
return
var/O
if(get_dir(src,M)==EAST||get_dir(src,M)==SOUTHEAST||get_dir(src,M)==NORTHEAST)
O = locate(M.x -1, M.y, M.z)
else if(get_dir(src,M)==WEST||get_dir(src,M)==SOUTHWEST||get_dir(src,M)==NORTHWEST)
O = locate(M.x +1, M.y, M.z)
walk_towards(src, O, 0, 0.5)


Now let's look at your get_dir statements. Instead of calling get_dir 6 times, we could call it once and store it in a variable like "directionToTarget" and then compare that to the directions. Also, notice that each direction has something in common, either EAST or WEST. BYOND uses bit flags to represent directions, so we can do something called "bit masking" to test if the direction has the EAST (or WEST) bit ON (or OFF). The statement (dir & EAST) will be true if dir is EAST, NORTHEAST, or SOUTHEAST. You can do the same with any of the other three directions.
var/mob/M = dragonRush_target
if(M.dead)
dragonRush_target = null
return
var/O
var/dirToTarget = get_dir(src, M)
if(dirToTarget & EAST)
O = locate(M.x -1, M.y, M.z)
else if(dirToTarget & WEST)
O = locate(M.x +1, M.y, M.z)
walk_towards(src, O, 0, 0.5)


Now that that's cleaned up, we can see what's going on more clearly. Using M as a variable also becomes redundant - why not just use the variable we already have, dragonRush_target? Also, what does O represent? Variables should be named something that tells the programmer what they represent.
// Cancel out if target is dead
if(dragonRush_target.dead)
dragonRush_target = null
return
// Find the goal that we want to move towards
var/turf/goal
var/directionToTarget = get_dir(src, dragonRush_target)
if(directionToTarget & EAST)
goal = get_step(dragonRush_target, WEST)
else if(directionToTarget & WEST
goal = get_step(dragonRush_target, EAST)
// Move towards it.
walk_towards(src, goal, 0, 0.5)


Now the only functional difference between what I've posted and what you posted originally is that yours wouldn't do anything if M (dragonRush_target) wasn't in oview(15), because it looped through everything in oview asking "are you dragonRush_target?" What we can do is check if dragonRush_target is within view, and cancel out if it isn't.
// Cancel out if target is dead
if(dragonRush_target.dead)
dragonRush_target = null
return
// Cancel out if target isn't in view
if(!(dragonRush_target in oview(15)))
return
// Find the goal that we want to move towards
var/turf/goal
var/directionToTarget = get_dir(src, dragonRush_target)
if(directionToTarget & EAST)
goal = get_step(dragonRush_target, WEST)
else if(directionToTarget & WEST
goal = get_step(dragonRush_target, EAST)
// Move towards it.
if(goal)
walk_towards(src, goal, 0, 0.5)


This cleans up the code and make's it spend less processor time, but it doesn't fix any errors. When you execute this code, it should walk the src directly to the goal. If that's not happening, you should tell us what is happening instead.
In response to IainPeregrine
Thanks! I might actually go and clean up some of my code from those tips.

Also, your change (the bottom one). This works smoother than mine, but the only issue I encountered with mine and so far with yours. Is that I want it to call Bump() when the pursuer gets to their target.
I don't use the walk functions often if at all, so I'm not an expert in that area, but as far as I recall and from what I'm reading in the reference, the walk procs will walk you /to/ a target, but not /into/ a target. You'll need to write your own code to handle that.

My first idea is to change where the goal is. Instead of walking to a spot directly in front of the target, walk to a spot directly /in back/ of the target. Just switch out EAST and WEST in those get_step calls above. That way the object will try to move through the target to get to the goal position, bumping them in the process.