# Throwers - how to they aim when I move? (Why do they hit me?)

#1

I noticed in backwood brawl that I was not able to evade projectiles from throwers.
Even if i moved constantly at 90° angle to the direction to the thrower, all of their arrows seem to hit me.

my direction of movement
^
I
I
X-----------------------x Thrower (at max shooting distance (approx 15 meters +/-)
me

I tried to move with moveXY, about 3…6 meters per movement. After each movement, I re-calculated direction in order to keep 90°-course.

When the arrow was fired, I usually move 2 or 3 meters before it hits me, but it was apparenty fired in an angle that reflected my future position.

So my question is: Is the hit already determined at the time when the arrow was shot and the course is calculated afterward, so that the arrow really does hit?

Or does the thrower look at my velocity & direction at shooting time and calculates that for its shootin-direction?

Is there a way to evade the arrows by moving (irregulary)? Was I too straight to set a course for 3…6 meters?

(I was in fact a little disappointed that I basically needed armor and good weapons in order to succeed)

Is there a way to beat throwers (without just overpowering them?)

Regards!

4 Likes
#2

Yes, throwers predict your future position.
So, if you want to avoid arrow
You should change move direction after shot

4 Likes
#3

Wow, that’s great (should have figured out that myself, but I did not really believe they were that good at such low levels ) Thank you very much!

Regards

3 Likes
#4

Yup, here’s some of the code from the `combat.Missile` Component (you can see this in the Components list in the level editor):

``````  findInterception: (from, to, targetVelocity, speed, useZ) ->
diff = Vector.subtract(to, from)
a = targetVelocity.dot(targetVelocity) - speed * speed
b = 2 * targetVelocity.dot(diff)
c = diff.dot(diff)
d = b * b - 4 * a * c
t = 0
unless d < 0 or a is 0
t0 = (-b - Math.sqrt(d)) / (2 * a)
t1 = (-b + Math.sqrt(d)) / (2 * a)
t = if t0 < 0 then t1 else (if t1 < 0 then t0 else Math.min(t0, t1))
if t <= 0 then t = @lifespan ? 3
{pos: Vector.add(to, Vector.multiply(targetVelocity, t, useZ), useZ), time: t}

launch: (shooter, launchType='attack') ->
@launchType = launchType
@setExists true
@shooter = shooter
@pos = Vector.add @shooter.pos, {x: 0, y: 0, z: @pos.z}, true  # Physical pos as offset to shooter pos, but only in z dimension
@pos.z = Math.min @pos.z, @depth / 2 + 1  # Make sure we start at least a meter off the ground
targetPos = @shooter.getTargetPos().copy()
targetPos.z = 0 if @shootsAtGround
if @leadsShots and @shooter.target?.velocity?.magnitude() > 0
if @flightTime
else
interception = @findInterception @pos, targetPos, @shooter.target.velocity, @maxSpeed, not @shootsAtGround
targetPos = interception.pos
@flightTime = interception.time
unless @shootsAtGround or @shooter.target.maintainsElevation?()
# Account for gravity when leading target z. TODO: this doesn't work properly.
targetPos.z = Math.max((if @shooter.target.depth then @shooter.target.depth / 2 else 0), targetPos.z - @world.gravity * @flightTime * @flightTime / 2)
@setTargetPos targetPos