• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!

[vJASS] Calculate Knockback Angle

Status
Not open for further replies.
Level 17
Joined
Feb 11, 2011
Messages
1,860
Status: SOLVED!

I am making a spell for my map that is similar to Barathrum's charge (from DotA). Everything works fine except the knockback angle for the units that the hero runs past. I have a diagram to explain better:

knockbackangle.jpg


Explanation
I want the targets to be knocked back at right angles to the direction of movement of the caster.
My current function is:
JASS:
set D.angle = bj_RADTODEG * Atan2(GetUnitY(D.target) - GetUnitY(D.caster), GetUnitX(D.target) - GetUnitX(D.caster))
However, this is inaccurate.

How would I calculate the correct angle? Please use degrees because I have never worked with radians before.

Thanks!
 
Last edited:
Level 18
Joined
Jan 21, 2006
Messages
2,552
JASS:
set D.angle = bj_RADTODEG * Atan2(GetUnitY(D.target) - GetUnitY(D.caster), GetUnitX(D.target) - GetUnitX(D.caster))

That isn't inaccurate. That is an equation for the angle between two points.

The diagram you posted suggests you're trying to do something different though. It looks more like you're trying to get the angle from an imaginary line which the caster is moving along and targets that are close-to that line.
 
Level 17
Joined
Feb 11, 2011
Messages
1,860
I want the nearby units to be knocked back at right angles to the caster.

For example, if the caster is moving vertically upwards, nearby enemies will either be knocked back towards 0 or 180 degrees, depending on which side of the caster the units are.
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
Well first you need to determine the angle of motion of the caster. This will be what you are using to compare which side of the caster it is on.

Let's say, for example, the caster is moving at a 30° angle.

The target encountered is at an angle of 220° from the caster. That is roughly south-west (little more to the west).

In order for the target to be on one side of the caster, it would have to be less than 30° but greater than 220°. In order for the target to be on the other side, it would have to be greater than 30° but less than 220°.

A problem that may arise however is that Blizzard doesn't use angles from 0 to 360, instead it goes from 0 to 180 and then -180 to 0.

If you need help to convert these scales just ask. You'll probably have to do a little bit of math to use boolean operators like less than and greater than because it doesn't really make sense to compare angles in terms of which is less than or greater than, because it goes in a circle.
 
Level 10
Joined
May 28, 2011
Messages
455
Hmm. Barathrums Charge of Darkness doesnt really work as shown in the graph diagram...

It is actually knockback enemy units encountered.

Here is what i would do...
1st - Check angle of caster...
2nd - For every interval of timer... Pick every unit in range of the caster position...
3rd - Get angle of the caster to the picked unit... Knockback the enemy offset toward the angle.

So instead of knockback the enemy units perpendicular to the caster path, the enemy units is knock away from caster.
 
Level 17
Joined
Feb 11, 2011
Messages
1,860
Perhaps the diagram did not explain clearly.

For the purpose of this example we will say the caster moves in a straight line heading NORTH. Any enemy unit that comes within 200 range of the caster will get knocked back. A unit on the left of the caster would get knocked back towards WEST and an enemy on the right would get knocked back towards EAST.

The problem I am having is determining the angle that the targets are knocked back towards. I have got everything else to work.
 
Level 29
Joined
Mar 10, 2009
Messages
5,016
1) when the caster reaches every 200 range, pick every unit and save it's
handle to a hashtable, this is needed so that the unit is not going to be
picked again with the same spell...
2) Set the knockback distance...
3) Set all the unit's angle from caster using your method...
4) Set the unit's x&y...
5) Set real variable "distx = 0"...
6) Set the speed...

then in the loop;

JASS:
if .distance > .distx then //you may need to add more conditions though
   set .distx = .distx + SPEED
   call SetUnitX(.u,. x + distx*Cos(.angle))
   call SetUnitY(.u, .y + distx*Sin(.angle))
else
   //end spell and remove the saved handle
endif
 
Level 29
Joined
Mar 10, 2009
Messages
5,016
I've made a hastable of that one before, now I made a struct version...
this is just a guide and really not perfect but it works...

JASS:
/*
=====KnockbackSystem: by Mckill2009

REQUIRES:
- TimedLoop by Vexorian ([url]http://www.wc3c.net/showthread.php?t=105515[/url])
- TerrainPathability by Rising_Dusk ([url]http://www.wc3c.net/showthread.php?t=103862[/url])
*/

library KnockbackSystem uses TimedLoop, TerrainPathability
  
struct KS
    unit caster
    unit target  
    real distance
    real distx
    real angle
    real speed
    real xTarget
    real yTarget
    
    private method onTimedLoop takes nothing returns boolean
        if .distance > .distx and not IsUnitType(.target, UNIT_TYPE_DEAD) and IsTerrainWalkable(GetUnitX(.target), GetUnitY(.target)) then            
            set .distx = .distx + .speed
            call SetUnitX(.target, .xTarget+.distx*Cos(.angle))
            call SetUnitY(.target, .yTarget+.distx*Sin(.angle))
        else
            call PauseUnit(.target, false)
            call SetUnitPathing(.target, true)
            return false
        endif
        return true
    endmethod
    
    implement TimedLoop
    
    static method create takes unit caster, unit target, real speed, real distance, real angle, real xTar, real yTar returns thistype
        local thistype this = thistype.allocate()
        local real x = GetUnitX(caster)
        local real y = GetUnitY(caster)        
        set .xTarget = xTar
        set .yTarget = yTar
        set .caster = caster
        set .target = target
        set .angle = angle
        if distance<=0 then
            set .distance = SquareRoot((.xTarget-x) * (.xTarget-x) + (.yTarget-y) * (.yTarget-y)) 
        else
            set .distance = distance
        endif
        set .distx = 0
        set .speed = speed
        call .startTimedLoop()
        return this
    endmethod
    
    static method knockUnit takes unit caster, unit target, real speed, real distance, real angle1 returns nothing
        local real x1 = GetUnitX(target)
        local real y1 = GetUnitY(target)
        local real angle
        if angle1==0 then
            set angle = GetUnitFacing(caster)*bj_DEGTORAD
        else
            set angle = Atan2(GetUnitY(target) - GetUnitY(caster), GetUnitX(target) - GetUnitX(caster))
        endif
        call PauseUnit(target, true)
        call SetUnitPathing(target, false)
        call thistype.create(caster, target, speed, distance, angle, x1, y1)    
    endmethod

endstruct

endlibrary
 
Last edited:
Level 18
Joined
Jan 21, 2006
Messages
2,552
the angle is oviously the "set .angle = Atan2(......"...

He wants right angles. That means, lets say the caster is moving at a 0° angle, that any target in the bottom-left or bottom-right quadrants (anything from -180° to -0°) will be knocked back at an angle of 270°.

It's not that hard to simply determine the angle between the two units, but the point here is we're using that angle (along with the movement direction of the caster) to determine which side of the caster the target is on, with respect to the direction of movement.

I've got to go to University, but I'll try to make something up for this. Just requires a little bit of thinking that's all.
 
Level 29
Joined
Mar 10, 2009
Messages
5,016
I want the targets to be knocked back at right angles to the direction of movement of the caster.

well I've edited my post and added 'angle', if it's 0 then the units will be knocked
back to the facing(direction when caster moves), else it will be knocked from
the angle of point XY of the caster and XY of target...the problem is pick units
in front of the caster...
 
Level 6
Joined
Jun 18, 2011
Messages
147
This hurts my brain.

I was thinking to determine whether the target was left or right of the caster using the facing angle of the caster somehow, but its sooo hard.

Edit: I will sleep on it, and try to think of something. I doubt I will, though. I mainly just wanted to subscribe, cuz I thought it was interesting :)

Maybe if you could use the plus or minus sign... I dunno. Berb looks like he is good at this, so I'll let him do it :p

I'd be really interested to see how you are testing this, haha.
 
Last edited:
Level 18
Joined
Jan 21, 2006
Messages
2,552
Well this is what I've got so far and it seems to work but its not very optimized. I'm trying to think of a trick that may reduce the amount of comparisons that need to be made.

JASS:
private function Convert360 takes real angle returns real
	local integer f = R2I(angle)/360
	if (f < 0) then
		set angle = angle + 360*(f+1)
	else
		set angle = angle - 360*f
	endif
	return angle
endfunction

function GetKnockbackAngle takes real primary, real angleBetween returns real
	set primary = Convert360(primary)
	set angleBetween = Convert360(angleBetween)

	if (primary <= 180) then
		if ((angleBetween < primary) or (angleBetween > (primary+180))) then
			return primary - 90.0 // on the right
		else
			return primary + 90.0 // on the left
		endif
	else
		if ((angleBetween > primary) or (angleBetween < (primary-180))) then
			return primary + 90.0 // on the left
		else
			return primary - 90.0 // on the right
		endif
	endif
endfunction
 
Level 17
Joined
Feb 11, 2011
Messages
1,860
Thanks! Would I set the angle as follows:
JASS:
set D.angle = GetKnockbackAngle(GetUnitFacing(D.caster), Atan2(GetUnitY(D.target) - GetUnitY(D.caster), GetUnitX(D.target) - GetUnitX(D.caster)))
Is this correct?

EDIT: I tested the above formula, and it is not too accurate. E.g. if the caster is heading north, units on the right of the caster are knocked towards west, when it should be towards east.
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
It should take both angles in terms of degrees. Right now it looks like you give the facing angle of the caster in degrees but you give the angle between the two units as radians. You have to multiply the Atan2(...) by bj_RADTODEG.

I tested it with a primary angle of 90 and an angle between the two as 45. The knockback angle was calculated to be 0, which is to due east (which is correct).

From the looks of it you may be using the angle from the target to caster, but you need to use the angle from the caster to target. Inverting this will make a big difference.
 
Level 17
Joined
Feb 11, 2011
Messages
1,860
Okay, thanks. It seems to work except that the units are knocked in the opposite directions to those that they are meant to be knocked in.

EDIT: Oh. Is this correct then set D.angle = GetKnockbackAngle(GetUnitFacing(D.caster), (bj_RADTODEG * Atan2(GetUnitY(D.caster) - GetUnitY(D.target), GetUnitX(D.caster) - GetUnitX(D.target))))?
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
I think it should be Atan2(GetUnitY(D.target)-GetUnitY(D.caster),...) but you will need to multiply by bj_RADTODEG.

Just to make sure, print out the values that you are passing to the function and examine them to make sure they make sense. I tested the function with parameters 90, -20 and it returned the correct angle, which should be (and was) 0.
 
Level 10
Joined
May 28, 2011
Messages
455
In other word. The knockback angle is perpendicular to the caster path.

Its easy if you detect the encountered unit position which is either left or right.

then get the path angle or facing angle of caster.

then -+90 depend on the position detected.

Btw, i do understand the diagram. It is not the same as Barathrum's Charge of Darkness.
 
Level 17
Joined
Feb 11, 2011
Messages
1,860
Level 10
Joined
May 28, 2011
Messages
455
Please show me how

It involves with angle.

if angle between caster and encountered unit greater than caster's path angle and less then caster's path + 180 degree then the encountered unit is on the left side.

else. its on the right side.

However, to code it is not easy as that. There is some problem such as. let say the angle is 350. and angle between caster and encountered unit on the left is 50 degree. so. if ( 50 > 350 and 50 < 350 + 180) will eventually false thus produces logic error. Ill try to get the solution for the condition part without using rad.

Obviously for me. From my imagination, when barathrum knock his target with massive unit around the target. Every unit except the target is knockback toward angle between bara and the particular unit. So it will look like bara knock them. Doesnt it look awkward if the units is knockback perpendicular to bara's path at that moment. Doesnt look like bara knock them but doing primal roar.

Have you test the angle with angle between caster and encountered unit?? @@!
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
Read both side of area. problem solve :)

That's incredibly inadequate a description. I don't even know what you're talking about.

Please show me how

I already showed you how. I was trying to help you debug whatever problems you seemed to be having (the function was returning the correct angles for me, so the problem is on your implementation), but you seemed to immediately be distracted by someone else' identical description to what I had given you.

My first request was that you print the values that are being passed to the function, and you haven't responded to me regarding that. If you're not going to try to do anything yourself, then I'm afraid nobody here is going to be able to help you.
 
Level 6
Joined
Jun 18, 2011
Messages
147
Berb...

Sorry, no offense, but don't get impatient.

Maybe this won't always be the case, but here is a for instance.

Maybe, many other people are subscribed to the thread and the more help and guidance you give increases the number of people that can understand how to use it.

btw, are you suurree it works?

Good work thus far.

I'm not even gonna try to understand this right now, so don't mind me.
 
Level 17
Joined
Feb 11, 2011
Messages
1,860
I already showed you how. I was trying to help you debug whatever problems you seemed to be having (the function was returning the correct angles for me, so the problem is on your implementation), but you seemed to immediately be distracted by someone else' identical description to what I had given you.

My first request was that you print the values that are being passed to the function, and you haven't responded to me regarding that. If you're not going to try to do anything yourself, then I'm afraid nobody here is going to be able to help you.

Sorry man. It must be that I am implementing it wrong somehow. I print the values:
primary: 90
angle between: 45


It returns the unit being on the right and would therefore be knocked towards 0 (correct). Here is my whole script. Perhaps you can spot something wrong.

JASS:
scope Forward

    globals
        private constant real KNOCK_DISTANCE = 300
        private constant real KNOCK_DURATION = 1.5
        
        private real KNOCK_INVERVAL_DISTANCE = KNOCK_DISTANCE / KNOCK_DURATION * 0.03
    endglobals

    public struct KnockbackData
        unit target
        unit caster
        real angle
        real DistLeft
        
        method destroy takes nothing returns nothing
            set .target = null
            set .caster = null
            call .deallocate()
        endmethod
        
        static method Knock_Effects takes nothing returns nothing
            local timer t = GetExpiredTimer()
            local thistype D = GetTimerData(t)
            if D.DistLeft > 0 then
                call DestroyEffect(AddSpecialEffectTarget("Abilities\\Weapons\\FlyingMachine\\FlyingMachineImpact.mdl", D.target, "chest"))
            else
                call ReleaseTimer(t)
            endif
            set t = null
        endmethod
        
        static method Timer_Actions takes nothing returns nothing
            local timer t = GetExpiredTimer()
            local thistype D = GetTimerData(t)
            local real x
            local real y
            if D.DistLeft > 0 then
                set x = GetUnitX(D.target) + KNOCK_INVERVAL_DISTANCE * Cos(D.angle)
                set y = GetUnitY(D.target) + KNOCK_INVERVAL_DISTANCE * Sin(D.angle)
                if not IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY) then
                    call SetUnitX(D.target, x)
                    call SetUnitY(D.target, y)
                    set D.DistLeft = D.DistLeft - KNOCK_INVERVAL_DISTANCE
                else
                    call ReleaseTimer(t)
                    call PauseUnit(D.target, false)
                    call SetUnitPathing(D.target, true)
                    call D.destroy()
                endif
            else
                call ReleaseTimer(t)
                call PauseUnit(D.target, false)
                call SetUnitPathing(D.target, true)
                call D.destroy()
            endif
            set t = null
        endmethod
        
        static method Actions takes unit target, unit caster returns thistype
            local thistype D = thistype.allocate()
            local timer t = NewTimer()
            local timer t2 = NewTimer()
            local real extra
            set D.target = target
            set D.caster = caster
            set D.DistLeft = KNOCK_DISTANCE
            set D.angle = GetKnockbackAngle(GetUnitFacing(D.caster), (bj_RADTODEG * (Atan2(GetUnitY(D.target) - GetUnitY(D.caster), GetUnitX(D.target) - GetUnitX(D.caster)))))
            call PauseUnit(D.target, true)
            call SetUnitPathing(D.target, false)
            call SetTimerData(t, D)
            call TimerStart(t, 0.03, true, function thistype.Timer_Actions)
            call SetTimerData(t2, D)
            call TimerStart(t2, 0.3, true, function thistype.Knock_Effects)
            set t = null
            set t2 = null
            return D
        endmethod
        
    endstruct

    public struct ForwardData
        unit caster
        unit target
        real DistLeft
        real angle
        real xoffset
        real yoffset
        effect overhead
        effect lefthand
        effect righthand
        group KnockedUnits = CreateGroup()
    
        method destroy takes nothing returns nothing
            set .caster = null
            set .target = null
            call DestroyEffect(.overhead)
            call DestroyEffect(.lefthand)
            call DestroyEffect(.righthand)
            set .overhead = null
            set .lefthand = null
            set .righthand = null
            call DestroyGroup(.KnockedUnits)
            set .KnockedUnits = null
            call .deallocate()
        endmethod
    
        static method Timer_Actions takes nothing returns nothing
            local timer t = GetExpiredTimer()
            local thistype D = GetTimerData(t)
            local real x
            local real y
            local real xdist
            local real ydist
            local unit dummy
            local unit u
            if D.DistLeft > 128 then
                set x = GetUnitX(D.caster) + D.xoffset
                set y = GetUnitY(D.caster) + D.yoffset
                call SetUnitX(D.caster, x)
                call SetUnitY(D.caster, y)
                set xdist = x - GetUnitX(D.target)
                set ydist = y - GetUnitY(D.target)
                set D.DistLeft = SquareRoot(xdist * xdist + ydist * ydist)
                set D.angle = Atan2(GetUnitY(D.target) - y, GetUnitX(D.target) - x)
                call GroupEnumUnitsInRange(bj_lastCreatedGroup, x, y, 150, null)
                loop
                    set u = FirstOfGroup(bj_lastCreatedGroup)
                    exitwhen u == null
                    if not IsUnitInGroup(u, D.KnockedUnits) /*
                    */and IsUnitEnemy(u, GetOwningPlayer(D.caster))/*
                    */and not IsUnitType(u, UNIT_TYPE_MAGIC_IMMUNE)/*
                    */and not IsUnitType(u, UNIT_TYPE_DEAD)/*
                    */and not IsUnit(u, D.target) then
                        call GroupAddUnit(D.KnockedUnits, u)
                        call KnockbackData.Actions(u, D.caster)
                    endif
                    call GroupRemoveUnit(bj_lastCreatedGroup, u)
                endloop
            else
                call ReleaseTimer(t)
                call SetUnitPathing(D.caster, true)
                call PauseUnit(D.caster, false)
                call SetUnitAnimation(D.caster, "stand")
                call D.destroy()
                set dummy = CreateUnit(GetOwningPlayer(D.caster), 'h001', x, y, 0)
                call RemoveGuardPosition(dummy)
                call UnitAddAbility(dummy, 'A000')
                call IssueTargetOrder(dummy, "thunderbolt", D.target)
                call UnitApplyTimedLife(dummy, 'BTLF', 1)
                call DestroyEffect(D.overhead)
                call DestroyEffect(D.lefthand)
                call DestroyEffect(D.righthand)
                call IssueTargetOrder(D.caster, "attack", D.target)
                call SetUnitMoveSpeed(D.caster, GetUnitDefaultMoveSpeed(D.caster))
                set dummy = null
            endif
            set t = null
        endmethod
    
        static method create takes nothing returns thistype
            local thistype D = thistype.allocate()
            local real xdist
            local real ydist
            local timer t = NewTimer()
            local real movespeed            
            set D.caster = GetTriggerUnit()
            set D.target = GetSpellTargetUnit()
            set xdist = GetUnitX(D.caster) - GetUnitX(D.target)
            set ydist = GetUnitY(D.caster) - GetUnitY(D.target)
            set D.DistLeft = SquareRoot(xdist*xdist + ydist*ydist)
            set movespeed = 50 * GetUnitAbilityLevel(D.caster, 'A001') + 15
            call SetUnitMoveSpeedX(D.caster, GetUnitMoveSpeedX(D.caster) + movespeed)
            call SetUnitPathing(D.caster, false)
            call PauseUnit(D.caster, true)
            call SetUnitAnimationByIndex(D.caster, 6)
            set D.angle = Atan2(GetUnitY(D.target) - GetUnitY(D.caster), GetUnitX(D.target) - GetUnitX(D.caster))
            set D.xoffset = 10 * Cos(D.angle)
            set D.yoffset = 10 * Sin(D.angle)
            set D.overhead = AddSpecialEffectTarget("Abilities\\Spells\\Orc\\Bloodlust\\BloodlustTarget.mdl", D.caster, "overhead")
            set D.lefthand = AddSpecialEffectTarget("Abilities\\Spells\\Orc\\Bloodlust\\BloodlustTarget.mdl", D.caster, "hand,left")
            set D.righthand = AddSpecialEffectTarget("Abilities\\Spells\\Orc\\Bloodlust\\BloodlustTarget.mdl", D.caster, "hand,right")
            call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\NightElf\\BattleRoar\\RoarCaster.mdl", D.caster, "origin"))
            call SetTimerData(t, D)
            call TimerStart(t, 0.03, true, function thistype.Timer_Actions)
            set t = null
            return D
        endmethod
        
        static method Conditions takes nothing returns boolean
            if GetSpellAbilityId() == 'A001' then
                call thistype.create()
            endif
            return false
        endmethod
        
        static method onInit takes nothing returns nothing
            local trigger t = CreateTrigger()
            call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
            call TriggerAddCondition(t, Condition(function thistype.Conditions))
            set t = null
        endmethod
    
    endstruct
    
endscope
JASS:
library Angle

    private function Convert360 takes real angle returns real
        local integer f = R2I(angle)/360
        if (f < 0) then
            set angle = angle + 360*(f+1)
        else
            set angle = angle - 360*f
        endif
        return angle
    endfunction

    function GetKnockbackAngle takes real primary, real angleBetween returns real
        
        call BJDebugMsg("Caster facing: " + R2S(primary))
        call BJDebugMsg("Angle between: " + R2S(angleBetween))
        
        set primary = Convert360(primary)
        set angleBetween = Convert360(angleBetween)

        if (primary <= 180) then
            if ((angleBetween < primary) or (angleBetween > (primary+180))) then
                call BJDebugMsg("Right")
                call BJDebugMsg(R2S(primary - 90))
                return primary - 90.0 // on the right
            else
                call BJDebugMsg("Left")
                call BJDebugMsg(R2S(primary + 90))
                return primary + 90.0 // on the left
            endif
        else
            if ((angleBetween > primary) or (angleBetween < (primary-180))) then
                call BJDebugMsg("Left")
                call BJDebugMsg(R2S(primary + 90))
                return primary + 90.0 // on the left
            else
                call BJDebugMsg("Right")
                call BJDebugMsg(R2S(primary - 90))
                return primary - 90.0 // on the right
            endif
        endif
    endfunction

endlibrary
 
Level 10
Joined
May 28, 2011
Messages
455
That's incredibly inadequate a description. I don't even know what you're talking about.

Coz its a cheat of solving the problem. it is not recommended. -_- why would i bother to explain.

but you seemed to immediately be distracted by someone else' identical description to what I had given you

If it is identical. then it is not distraction. Different people understand by different way.

Agree. totally right. in order to solve the problem, you need to experiment it urself...
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
Sorry man. It must be that I am implementing it wrong somehow. I print the values:
primary: 90
angle between: 45

It returns the unit being on the right and would therefore be knocked towards 0 (correct). Here is my whole script. Perhaps you can spot something wrong.

I don't get it. You've achieved the correct results, so what is the problem?

Coz its a cheat of solving the problem. it is not recommended. -_- why would i bother to explain.

It involves with angle.

if angle between caster and encountered unit greater than caster's path angle and less then caster's path + 180 degree then the encountered unit is on the left side.

else. its on the right side.

However, to code it is not easy as that. There is some problem such as. let say the angle is 350. and angle between caster and encountered unit on the left is 50 degree. so. if ( 50 > 350 and 50 < 350 + 180) will eventually false thus produces logic error. Ill try to get the solution for the condition part without using rad.

How is this a "cheat"? Just sounds like a really bad description of something you put a minimal amount of thought into.
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
It looks like your implementation is correct.

JASS:
                set x = GetUnitX(D.target) + KNOCK_INVERVAL_DISTANCE * Cos(D.angle)
                set y = GetUnitY(D.target) + KNOCK_INVERVAL_DISTANCE * Sin(D.angle)

Except this. You're doing Cos(D.angle) when D.angle is a measurement of degrees, not radians. The Cos function (and the Sin function) both take radian arguments. You will have to multiply by bj_DEGTORAD to use those values.

Since you only really use D.angle for this purpose, you can change (from the Actions function):

JASS:
            set D.target = target
            set D.caster = caster
            set D.DistLeft = KNOCK_DISTANCE
            set D.angle = GetKnockbackAngle(GetUnitFacing(D.caster), (bj_RADTODEG * (Atan2(GetUnitY(D.target) - GetUnitY(D.caster), GetUnitX(D.target) - GetUnitX(D.caster)))))

To this:

JASS:
            set D.target = target
            set D.caster = caster
            set D.DistLeft = KNOCK_DISTANCE
            set D.angle = bj_DEGTORAD * GetKnockbackAngle(GetUnitFacing(D.caster), (bj_RADTODEG * (Atan2(GetUnitY(D.target) - GetUnitY(D.caster), GetUnitX(D.target) - GetUnitX(D.caster)))))

Then you can use Cos and Sin as you have been.
 
Level 10
Joined
May 28, 2011
Messages
455
How is this a "cheat"? Just sounds like a really bad description of something you put a minimal amount of thought into.

The cheat is the read both side of area. not that. That is just funny if i put minimal amount of thought into since you say my comment is identical and repeated yours.

Btw, i dont read your code though. what if this case happen, the angle between caster and encountered unit is exactly the same as the caster's angle. which mean the unit is not on the left or right of the caster.
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
The cheat is the read both side of area. not that. That is just funny if i put minimal amount of thought into since you say my comment is identical and repeated yours

When I said that I wasn't talking about you. I was talking about a post or two before yours. I even quoted it. I didn't quote you.

Btw, i dont read your code though. what if this case happen, the angle between caster and encountered unit is exactly the same as the caster's angle. which mean the unit is not on the left or right of the caster.

The author of the thread did not state what he wanted in this particular case. I'm sure that he's knowledgeable enough to manage those base cases.
 
Level 10
Joined
May 28, 2011
Messages
455
When I said that I wasn't talking about you. I was talking about a post or two before yours. I even quoted it. I didn't quote you.

Misunderstood. Whatever it is. You did great job helping him.

The author of the thread did not state what he wanted in this particular case. I'm sure that he's knowledgeable enough to manage those base cases.

Thats correct. Just add a case that will happen in game.
 
Status
Not open for further replies.
Top