Legacy GM Solved! Determining attack quadrant (front, side, back)

andulvar

Member
For some reason this seems like a simple thing, but I'm having trouble with an elegant solution. If I have an object facing a particular direction 0-359, and another object attacks that object I'd like to get the attack direction relative to the attacked object to be able to apply modifiers for hitting weak areas like sides and backs.

I'd like to write a function that just takes in the defending object and attacking object as parameters, looks at the defending object image_angle and the relative direction of the attacker to the defender to determine if its a front, side or back angle of attack.

Originally I tried this, but then realized I need to take into the fact that when facing direction 0, the frontal arc will be between 0-75, and 295-359 so I was going to need to add a lot of conditions. I would like a more formulaic method though and for some reason I can't think of anything.
Code:
var _attacker = argument0
var _defender = argument1;

var d_dir = 0
var a_dir = 0
var quad_front_start = 0
var quad_front_end = 0
var quad_side_start = 0
var quad_side_end = 0
var quad_back = 0
var quad = "front"

//get defender direction
d_dir = _defender.image_angle

//get attacker direction in relation to defender
a_dir = point_direction( _defender.x, _defender.y, _attacker.x, _attacker.y)

quad_front_start = d_dir-75
quad_front_end = d_dir+75
quad_side_start = d_dir-160
quad_side_end = d_dir+160

  
//determine which quadrant the attack is coming from
if(a_dir > quad_front_start && a_dir < quad_front_end)
{
    quad = "front"
  
}
else
{
    if(a_dir > quad_side_start && a_dir < quad_side_end)
    {
        quad = "side"
    }
    else
    {
        quad = "back"
    }
}

//determine which attack bonus to apply
switch(quad)
{
    case "front":
                    show_debug_message("front attack!")
                    return "front"

    case "side":
                    show_debug_message("side attack!")
                    return "side"

    case "back":
                    show_debug_message("back attack!")
                    return "back"
 
    default: 
                show_debug_message("Error: No attack angle found")
                return "front"
              
}
 
Last edited:

Alexx

Member
There is a function you can use that may be your friend in this case:
Code:
angle_difference
See manual entry here

(if you use abs on the returned value, you can reduce the number of condition checks needed)

You can then check the angle is within a given range and set your quad value as required.
 
Last edited:

andulvar

Member
If anyone was curious about the final function code:
Code:
var _attacker = argument0;
var _defender = argument1;
var d_dir = 0;
var a_dir = 0;
var quad_front_arc = 0;
var quad_side_arc = 0;
var att_angle = 0;

//get defender direction
d_dir = _defender.image_angle

//get attacker direction in relation to defender
a_dir = point_direction( _defender.x, _defender.y, _attacker.x, _attacker.y)

//set quadrant front and side arc limits
//=================
quad_front_arc = 85  //(-85 to 85 = 170 degree arc)
quad_side_arc = 145
 
//determine which quadrant the attack is coming from
att_angle = abs(angle_difference(d_dir, a_dir))

if(att_angle<quad_front_arc)
{
    show_debug_message("front attack!")
    return "front"
}
else if (att_angle<quad_side_arc))
{
    show_debug_message("side attack!")
    return "side"
}
else
{
    show_debug_message("back attack!")
    return "back"
}
 
Last edited:
T

Timothy

Guest
Just nitpicking, but your last 2 lines of code are not even reachable... so its pointless to even have it there. Also abs() isn't exactly cheap... i would store the result in a var.
 

andulvar

Member
Just nitpicking, but your last 2 lines of code are not even reachable... so its pointless to even have it there. Also abs() isn't exactly cheap... i would store the result in a var.
You are correct, however I do a lot of iterating and it's a personal practice I have to keep an error in functions just in case I change something later. But that's not really relevant here, removed.

i would store the result in a var.
Fair comment, updated function.
 
Top