HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Checking if unit is facing unit

09-03-2009, 07:46 PM#1
Tyrande_ma3x
Well, not exactly. What I am trying to do is detect when a certain unit type (Footman to be exact) gets damaged and see if the damage comes from in front of the Footman so I can block it. I'm doing that by comparing the angle between the damager and damaged unit and checking if the footman is facing that angle. If he is, then heal him for a maximum of 7. The problem is that it will block damage only if the footman is facing north and he gets damaged in front. If I turn him south and attack him directly in the face, it does nothing. I'm pretty sure it is because of my math but I'm really bad at it and can't really fix it...
Collapse JASS:
scope DefensiveStance initializer Init 

globals
    private constant integer UID_FOOTMAN = 'h006'
    private constant real ANGLE = (90. * 0.5) // it is actually 90 but since it's spread in 2 directions, it has to be halved 
endglobals

private function OnDamage takes nothing returns boolean
    local unit cast = GetEventDamageSource()
    local unit targ = GetTriggerUnit()
    local real ang
    local real face 
    local real damage = GetEventDamage()
    local real life
    call BJDebugMsg("hello?..")
    if GetUnitTypeId(targ) == UID_FOOTMAN then
        call BJDebugMsg("passed footman check..")
        set ang = Atan2(GetWidgetY(cast) - GetWidgetY(targ), GetWidgetX(cast) - GetWidgetX(targ)) * bj_RADTODEG
        set face = GetUnitFacing(targ)
        if (ang > face - ANGLE and ang < face + ANGLE) or (ang < face + ANGLE and ang > face - ANGLE) then // check if damage can be blocked if damaged in front
            if damage > 7. then // can reduce a maximum of 7
                set damage = 7.
            endif
            set life = GetWidgetLife(targ)
            call BJDebugMsg(R2S(life))
            call BJDebugMsg(R2S(life + damage))
            call SetWidgetLife(targ, GetWidgetLife(targ) + damage + damage)
        endif
    endif
    set cast = null
    set targ = null
    return false
endfunction

private function Init takes nothing returns nothing
    call AddOnDamageFunc(Condition(function OnDamage))
endfunction

endscope
09-03-2009, 08:00 PM#2
Bobo_The_Kodo
Collapse JASS:
//! textmacro Modulo takes VAR, PA, PB
    set $VAR$ = $PA$ - I2S(R2I($PA$/$PB$)) * $PB$
    if $VAR$ < 0 then
        set $VAR$ = $VAR$ + $PB$
    endif
//! endtextmacro

    function GetAngleDifference takes real a1, real a2 returns real
     local real x
        //! runtextmacro Modulo("a1","a1","bj_PI*2")
        //! runtextmacro Modulo("a2","a2","bj_PI*2")
        if a1>a2 then
            set x=a1
            set a1=a2
            set a2=x
        endif
        set x=a2-bj_PI*2
        if a2-a1 > a1-x then
            set a2=x
        endif
        set x=a1-a2
        if (x<0) then
            return -x
        endif
     return x
    endfunction

You would do if GetAngleDifference(face,ang) <= ANGLE then Uses radians ofc
09-03-2009, 08:19 PM#3
Tyrande_ma3x
Thanks, but this thing can't actually compile when it's using string conversion ... Says "bad types for binary operator"
09-03-2009, 08:22 PM#4
Bobo_The_Kodo
Collapse JASS:
//! textmacro Modulo takes VAR, PA, PB
    set $VAR$ = ($PA$) - I2R(R2I(($PA$)/($PB$))) * ($PB$)
    if $VAR$ < 0 then
        set $VAR$ = ($VAR$) + ($PB$)
    endif
//! endtextmacro

    function GetAngleDifference takes real a1, real a2 returns real
     local real x
        //! runtextmacro Modulo("a1","a1","bj_PI*2")
        //! runtextmacro Modulo("a2","a2","bj_PI*2")
        if a1>a2 then
            set x=a1
            set a1=a2
            set a2=x
        endif
        set x=a2-bj_PI*2
        if a2-a1 > a1-x then
            set a2=x
        endif
        set x=a1-a2
        if (x<0) then
            return -x
        endif
     return x
    endfunction
my bad
09-03-2009, 08:22 PM#5
Silvenon
Ugh, angles are tricky little bastards (for people who don't know how to handle them properly, like me).

Here's a function that I made:

Collapse JASS:
    function IsUnitInCone takes unit u1, unit u2, real w returns boolean
        local real x1 = GetUnitX(u1)
        local real y1 = GetUnitY(u1)
        local real x2 = GetUnitX(u2)
        local real y2 = GetUnitY(u2)
        local real a1 = GetUnitFacing(u1) * bj_DEGTORAD
        local real a2 = Atan2(y2 - y1, x2 - x1)
        local real r = a1 + bj_PI
        local real d
        
        if a1 < 0 then
            set a1 = 2 * bj_PI + a1
        endif
        
        if a2 < 0 then
            set a2 = 2 * bj_PI + a2
        endif
        
        set d = a2 - a1
        
        if d < 0 then
            set d = -d
        endif
        
        if r > 2 * bj_PI then
            set r = r - 2 * bj_PI
        endif
        
        if d > r then
            set d = 2 * bj_PI - d
        endif
        
        return d <= w/2
    endfunction

I probably did a lot of unnecessary things, but it seems to work.

Zoom (requires log in)

Here's something from BlinkBoy:

Quote:
Originally Posted by BlinkBoy;1290315
Well I also have my shares:

IsPointinCone:

Jass:
Collapse JASS:
function IsPointInCone takes real x1, real y1, real x2, real y2, real f, real a returns boolean
    return Cos(Atan2(y2-y1,x2-x1)-f) > Cos(a)
endfunction

cJass:
Collapse JASS:
bool IsPointInCone(float x1,float y1,float x2,float y2,float f,float a) { 
    return Cos(Atan2(y2-y1,x2-x1)-f) > Cos(a); 
}



Pretty much this function helps detect if a point is within the cone facing of other point. The function takes both points, the facing of the center point (imagine it as unit facing)[in the image the facing is 0º] and takes the angle of the cone axi. This last angle must range from 0 to pi. In the example the angle is 45º|PI/4 but the covered zone is 90º. Have that in mind.

I hope that helps.
Attached Images
File type: jpgUntitled-1.jpg (194.3 KB)
09-03-2009, 08:29 PM#6
Tyrande_ma3x
Thanks, both. Got it working.
09-04-2009, 05:00 AM#7
TheWye
dude.. silvenon.. you deserve a +rep for the pics