ID:1549356
 
(See the best response by Ter13.)
Code:
        Thrust(mob/M as mob in oview(5))
set category="Hakuda"
if(ismob(M) in get_dir(src,src.dir))
if(get_dist(src,M)>3)
if(src.bowequipped==1||src.wearingclothes["zanpakutou"]==1)
usr<<"Please unequip your weapon first."
return
flick("punch",usr)
var/damage=M.Hit(usr,round((usr.CStr-M.CEnd/0.75),1))
range()<<"[usr.Name] punched [M] for [damage]!"
usr.DeathCheck(M)
else return
else return


Problem description: I'm trying to set up a technique to be used at the end of a dash that unleashes pent-up momentum to extend the range of the attack by several tiles based on the rank of the ability.

To simplify, I want to be able to hit a mob multiple tiles away in a single direction, as well as hitting any other mobs that also happen to be in those 2-4 tiles in front of the user. What happens in the code above is... Well, nothing. It's purely my attempt to get things to work, and I've hit a roadblock.

Thrust(dist as num)
var/turf/current_tile = locate(x,y,z)
var/list/damage_these = new

for(var/x = 1, x <= dist, x++)
current_tile = get_step(current_tile, dir)

for(var/mob/M in current_tile)
if(!damage_these.Find(M)) damage_these.Add(M)


for(var/mob/target in damage_these)
//damage them


This way may not necessarily be the best way, but it should get your head thinking on how one might accomplish it.
Best response
Look up bounds() in the reference. You don't need to use pixel movement to use bounds().

var/list/l
switch(dir)
if(NORTH)
l = bounds(src,0,TILE_HEIGHT,0,(dist - 1) * TILE_HEIGHT)
if(SOUTH)
l = bounds(src,0,dist * -TILE_HEIGHT,0,(dist - 1) * TILE_HEIGHT)
if(EAST)
l = bounds(src,TILE_WIDTH,0,(dist - 1) * TILE_WIDTH,0)
if(WEST)
l = bounds(src,dist * -TILE_WIDTH,0,(dist - 1) * TILE_WIDTH,0)

for(var/mob/M in l)
//deal damage


@Koshigia, you want to use "in list" rather than ".Find()" when you don't need to know the position of the element. Also, notice how this approach doesn't require two consecutive loops?

This approach, unfortunately, won't work for diagonal directions, so you will have to fall back to something more like Koshigia's approach for that.
Thanks for the catch about "in list" and Find().

There could possibly be other reasons for doing it the way I posted as well, such as hitting mobs in sequence (not sure if the internals of bounds allow for this), adding delays between damaging mobs in subsequent tiles, etc. Loops aren't necessarily your enemy here. Maybe you see something that I do not?
As always, Ter to the rescue.

I got it to work flawlessly, though I had to do a bit of minor alterations to your code to get it to properly work.
        Thrust()
set category="Hakuda"
var/list/l
switch(src.dir)
if(NORTH)
l=bounds(src,0,32,0,0)
if(SOUTH)
l=bounds(src,0,-32,0,0)
if(EAST)
l=bounds(src,32,0,0,0)
if(WEST)
l=bounds(src,-32,0,0,0)
for(var/mob/M in l)
var/damage=M.Hit(usr,round((usr.CStr-M.CEnd/0.75),1))
range()<<"[usr.Name] punched [M] for [damage]!"
usr.DeathCheck(M)


Now, this works for the tiles immediately next to the player. I assume that I'll need to define a new list for those mobs that are in tiles further away, correct?
No. The reason I used bounds at all was so I could get all the tiles within the range at once.

If you want to get the tiles one at a time, Koshigia's example would be better.
#define TILE_WIDTH 32
#define TILE_HEIGHT 32

mob
proc
Thrust(dist=4) //you can change the argument to change the distance
set category="Hakuda"
var/list/l
switch(src.dir)
if(NORTH)
l = bounds(src,0,TILE_HEIGHT,0,(dist - 1) * TILE_HEIGHT)
if(SOUTH)
l = bounds(src,0,dist * -TILE_HEIGHT,0,(dist - 1) * TILE_HEIGHT)
if(EAST)
l = bounds(src,TILE_WIDTH,0,(dist - 1) * TILE_WIDTH,0)
if(WEST)
l = bounds(src,dist * -TILE_WIDTH,0,(dist - 1) * TILE_WIDTH,0)
for(var/mob/M in l)
var/damage=M.Hit(usr,round((usr.CStr-M.CEnd/0.75),1))
range()<<"[usr.Name] punched [M] for [damage]!"
usr.DeathCheck(M)
Getting them all at once only works if, say, there was only one rank to the skill. Different skill levels would affect the amount of tiles that could be hit, up to a max of four (probably).

-Posted this after you did, will check it out first.-
That makes more sense. When I placed your version in to begin with, it gave me a ton of compilation errors because I didn't have the '#define's or an actual value assigned to dist.

To account for varying ranks of skill, I would simply need a formula for dist relative to the change in skill level, yes? I suppose damage would work the same way too.
To account for varying ranks of skill, I would simply need a formula for dist relative to the change in skill level, yes? I suppose damage would work the same way too.

Absolutely. Since I have no idea how your game works, I figured you'd be able to do that on your own.

As for the #defines, I prefer not to write specific code that requires changes later on. It's easier to change the value of a #define, than to change a thousand specific numbers implemented in your code.
Right right. Got it, thanks for the help :)