• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

[JASS] Polar Projection without Locations?

Status
Not open for further replies.
Level 5
Joined
Sep 19, 2006
Messages
152
I've only been at this about a week, so please forgive my noobiness. Here's my first trigger, but I have a few problems. Firstly, I'd like the trigger to have no effect on FRIENDLY undead units, but don't know how to include that stipulation in the first portion of the trigger. Secondly, because of the Polar Pojection command near the middle of the trigger, I had to use Locations rather than (RealX, RealY). Does anyone know how to calculate the angle between 2 points using only 2 sets of RealX and RealY? Thanks for the feedback.
(In case you're wondering, "Wisdom" here is a substitute for "Agility".)
___________
DIVINE LIGHT
Channels the Paladin's devotion into a flash of brilliant light, healing friendly living units and repeling the enemy Undead. Each point of base Wisdom increases the amount healed by 25, while each point of Wisdom obtained from items increases this healing by 10.
Level 1 - Heals 100 life excluding the Wisdom bonus
Level 2 - Heals 150 life excluding the Wisdom bonus
Level 3 - Heals 200 life excluding the Wisdom bonus
Level 4 - Heals 250 life excluding the Wisdom bonus
Level 5 - Heals 300 life excluding the Wisdom bonus
Level 6 - Heals 350 life excluding the Wisdom bonus
Level 7 - Heals 400 life excluding the Wisdom bonus
Level 8 - Heals 450 life excluding the Wisdom bonus


function AbilityDivineLight_Condition01 takes nothing returns boolean
return GetAbilityName (GetSpellAbilityId()) == "Paladin - Divine Light"
endfunction

function AbilityDivineLight_Action01 takes nothing returns nothing
local unit DivineLightCastingUnit = GetSpellAbilityUnit()
local player DivineLightPlayer = GetOwningPlayer (DivineLightCastingUnit)
local integer DivineLightSpecialValueA = (((GetUnitAbilityLevelSwapped (GetSpellAbilityId(), DivineLightCastingUnit) *50) +50) + ((GetHeroStatBJ (bj_HEROSTAT_AGI, DivineLightCastingUnit, false) * 15) + (GetHeroStatBJ (bj_HEROSTAT_AGI, DivineLightCastingUnit, true) * 10)))
local integer DivineLightSpecialValueB = (GetUnitAbilityLevelSwapped (GetSpellAbilityId(), DivineLightCastingUnit) * 250) + 750
local real DivineLightTargetUnitMoveSpeed
local location DivineLightCastingUnitLocation = GetUnitLoc (DivineLightCastingUnit)
local real DivineLightCastingUnitX = GetUnitX (DivineLightCastingUnit)
local real DivineLightCastingUnitY = GetUnitY (DivineLightCastingUnit)
local group DivineLightTargetGroupA = CreateGroup()
local group DivineLightTargetGroupB = CreateGroup()
local unit DivineLightTargetUnit
local location DivineLightTargetUnitLocationA
local location DivineLightTargetUnitLocationB
call TriggerSleepAction (0.75)
call GroupEnumUnitsInRange (DivineLightTargetGroupA, DivineLightCastingUnitX, DivineLightCastingUnitY, 550.0, null)
loop
set DivineLightTargetUnit = FirstOfGroup (DivineLightTargetGroupA)
exitwhen DivineLightTargetUnit == null
if IsUnitAlly (DivineLightTargetUnit, DivineLightPlayer) then
call SetUnitLifeBJ (DivineLightTargetUnit, (GetUnitStateSwap (UNIT_STATE_LIFE, DivineLightTargetUnit) + (DivineLightSpecialValueA)))
elseif IsUnitEnemy (DivineLightTargetUnit, DivineLightPlayer) and IsUnitRace (DivineLightTargetUnit, RACE_UNDEAD) then
set DivineLightTargetUnitMoveSpeed = GetUnitMoveSpeed (DivineLightTargetUnit) +135
set DivineLightTargetUnitLocationA = GetUnitLoc(DivineLightTargetUnit)
set DivineLightTargetUnitLocationB = PolarProjectionBJ (DivineLightTargetUnitLocationA, DivineLightSpecialValueB, AngleBetweenPoints (DivineLightCastingUnitLocation, DivineLightTargetUnitLocationA))
call GroupAddUnit (DivineLightTargetGroupB, DivineLightTargetUnit)
call SetUnitMoveSpeed (DivineLightTargetUnit, DivineLightTargetUnitMoveSpeed)
call IssuePointOrderLoc (DivineLightTargetUnit, "move", DivineLightTargetUnitLocationB)
call RemoveLocation (DivineLightTargetUnitLocationA)
call RemoveLocation (DivineLightTargetUnitLocationB)
endif
call GroupRemoveUnit (DivineLightTargetGroupA, DivineLightTargetUnit)
set DivineLightTargetUnit = null
endloop
call TriggerSleepAction (2.0)
loop
set DivineLightTargetUnit = FirstOfGroup (DivineLightTargetGroupB)
exitwhen DivineLightTargetUnit == null
set DivineLightTargetUnitMoveSpeed = GetUnitMoveSpeed (DivineLightTargetUnit) -135
call SetUnitMoveSpeed (DivineLightTargetUnit, DivineLightTargetUnitMoveSpeed)
call GroupRemoveUnit (DivineLightTargetGroupB, DivineLightTargetUnit)
set DivineLightTargetUnit = null
endloop
call DestroyGroup (DivineLightTargetGroupA)
call DestroyGroup (DivineLightTargetGroupB)
call RemoveLocation (DivineLightCastingUnitLocation)
set DivineLightCastingUnit = null
endfunction

function InitTrig_AbilityDivineLight takes nothing returns nothing
set gg_trg_AbilityDivineLight = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ (gg_trg_AbilityDivineLight, EVENT_PLAYER_UNIT_SPELL_CAST )
call TriggerAddCondition (gg_trg_AbilityDivineLight, Condition (function AbilityDivineLight_Condition01))
call TriggerAddAction (gg_trg_AbilityDivineLight, function AbilityDivineLight_Action01)
endfunction
 
Level 12
Joined
Aug 3, 2005
Messages
745
For calculating angles
Here is a sample:

Code:
    local location l1 = ....
    local location l2 = ....
    local real x1 = GetLocationX(l1)
    local real y1 = GetLocationY(l1)
    local real x2 = GetLocationX(l2)
    local real y2 = GetLocationY(l2)
    local real angle = 57.29582 * Atan2(y2 - y1, x2 - x1)
 
DistantHaze use jass tags else it is almost unreadable..
After taking a look at some of the code i noticed LOTS of BJ functions and other stuff that could be removed including some leaks.
JASS:
function AbilityDivineLight_Condition01 takes nothing returns boolean
return GetAbilityName (GetSpellAbilityId()) == "Paladin - Divine Light"
endfunction
This condition i don't really get, why not just do like this:
JASS:
function AbilityDivineLight_Condition01 takes nothing returns boolean
return GetSpellAbilityId() == '<rawcode here>'
endfunction
 
Level 40
Joined
Dec 14, 2005
Messages
10,532
I've only been at this about a week, so please forgive my noobiness. Here's my first trigger, but I have a few problems. Firstly, I'd like the trigger to have no effect on FRIENDLY undead units, but don't know how to include that stipulation in the first portion of the trigger. Secondly, because of the Polar Pojection command near the middle of the trigger, I had to use Locations rather than (RealX, RealY). Does anyone know how to calculate the angle between 2 points using only 2 sets of RealX and RealY? Thanks for the feedback.
(In case you're wondering, "Wisdom" here is a substitute for "Agility".)
It's a simple polar coordinate conversion.

While Cartesian Coordinates work in (x,y), Polar coordinates work in (r,t) where r is the radius (a real), and t (which is actually the greek letter theta, not 't') is the angle, usually in radians.

Since you can construct a triangle from the polar coordinates with theta being, well, theta, and r being the hypotenuse, taking the trigonometric ratios

Sin t = Opposite/Hypotenuse
Cos t = Adjacent/Hypotenuse

where t is theta again, and the Hypotenuse is r, we are given

r * Sin t = Opposite
r * Cos t = Adjacent

finally, Opposite is the vertical height, which turns out to be our Y, and Adjacent is our horizontal length, which turns out to be our X.

X = r * Sin t
Y = r * Cos t

Next, to offset the point from a projection from the origin, you add on the old point's coordinates. Thus, we are given, with the restriction that t is in radians!,

newX = oldX + r * Cos( t )
newY = oldY + r * Sin( t )
 
Level 5
Joined
Sep 19, 2006
Messages
152
Diablo-dk, I don't know what jass tags are, and about BJ's I remember only that "they are bad". Do tell - I appreciate the replies.

PurplePoot, thanks for all the math. I haven't done such equations in probably 15 years, so my brain could certainly stand the work-out. At any rate, wouldn't determining the new X and new Y be something like:

Angle = 57.29582 * Atan2 (Real Y of moving unit - real Y of casting unit,
real X of moving unit - real X of casting unit)
Distance = Level of Spell Ability * 250 + 750

Since the moving unit moves opposite the direction of the caster, then the angle between the caster and the moving unit would be the same as the angle between the moving unit's new location and the moving unit's current location. The equation, then, would be something applying the 2 values above, almost a deconstruction of the Angle formula provided by Fulla. I don't really understand the Atan2 function (it doesn't even look familiar since my high school calculus days); so I don't really know what the new formula would be. If any here does, I'd greatly appreciate the feedback.

You guys rock!
 
Level 40
Joined
Dec 14, 2005
Messages
10,532
Atan2 is an extension on the Atan function. Here is a full definition.

Basically, Atan2 in a nutshell will calculate the angle from the origin to (x,y) :):Note: the parameters are y,x , however).

Thus, the angle from A to B is Atan2( deltaY, deltaX ), aka Atan2( By-Ay, Bx-Ax )

And bj_RADTODEG (and bj_DEGTORAD) are accessible, so you don't need to use 57.29582


As for JASS tags, just do the following;

  • type [code=jass]
  • add your JASS code
  • type [/code]

And it's done!
 
Jass tags is this:
JASS:
This is jass tags, it is written in jass code making it easily readable
It is done by wrapping [.jass] and [./jass] around your text without the ' . '
BJ stands for blizzard.j(blizzard jass). They are custom functions made by blizzard, but most of them can be replaced by a native function. BJs are bad because they usually use an unneccesary call, like this function:
JASS:
function SetItemPlayerBJ takes item whichItem, player whichPlayer, boolean changeColor returns nothing
    call SetItemPlayer(whichItem, whichPlayer, changeColor)
endfunction
As you can see this BJ function is practically useless, as it does the same as the native SetItemPlayer(). I suggest using JassShopPro or jasscraft for finding natives.
 
Level 13
Joined
Nov 22, 2006
Messages
1,260
Heh I know, I joined on wc3sear.ch because I wanted to comment some JASS code. I was on wc3campaigns, and now that it is closed, I came here :D (my profile transferred for wc3sear.ch to here)

DistantHaze, I also had long names for locals before because I named globals that way (e.g. <spellname> + <type>) so it was kind of a habit, because there can't be 2 globals with the same name, but you can have locals that have the same name (not in the same function, of course). It will save you a LOT of time, trust me, that's why you can code much faster in JASS than in GUI (in GUI you have to click a lot :p)
 
Level 5
Joined
Sep 19, 2006
Messages
152
I've made some corrections, but the Undead units don't always go in the intended directions, which lines of this are wrong and what should they be?

JASS:
function AbilityDivineLight_Condition01 takes nothing returns boolean
    return GetAbilityName (GetSpellAbilityId()) == "Paladin - Divine Light"
endfunction

function AbilityDivineLight_Action01 takes nothing returns nothing
    local unit DLCstr = GetSpellAbilityUnit()
    local unit DLTrgt
    local player DLPlyr = GetOwningPlayer (DLCstr)
    local integer DLCstrAgiT = GetHeroAgi (DLCstr, true) *10
    local integer DLCstrAgiF = GetHeroAgi (DLCstr, false) *15
    local integer DLSpellLvl = GetUnitAbilityLevel (DLCstr, GetSpellAbilityId()) 
    local integer DLSpecA = (DLSpellLvl *50) + DLCstrAgiF + DLCstrAgiT +50
    local integer DLSpecB = (DLSpellLvl * 250) +750
    local real DLCstrX = GetUnitX (DLCstr)
    local real DLCstrY = GetUnitY (DLCstr)
    local real DLTrgtX
    local real DLTrgtY
    local real DLSpecAngle
    local real DLTrgtNewX
    local real DLTrgtNewY
    local real DLTrgtSpd
    local group DLTrgtGrpA = CreateGroup()
    local group DLTrgtGrpB = CreateGroup()
    call TriggerSleepAction (0.75) 
    call GroupEnumUnitsInRange (DLTrgtGrpA, DLCstrX, DLCstrY, 550.0, null)
    loop
        set DLTrgt = FirstOfGroup (DLTrgtGrpA)
        exitwhen DLTrgt == null
        if IsUnitAlly (DLTrgt, DLPlyr) then
        call SetUnitState (DLTrgt, UNIT_STATE_LIFE, GetUnitState (DLTrgt, UNIT_STATE_LIFE) +DLSpecA)
        elseif IsUnitEnemy (DLTrgt, DLPlyr) and IsUnitRace (DLTrgt, RACE_UNDEAD) then 
        call GroupAddUnit (DLTrgtGrpB, DLTrgt)
        set DLTrgtSpd = GetUnitMoveSpeed (DLTrgt) +100
        call SetUnitMoveSpeed (DLTrgt, DLTrgtSpd)        
        set DLTrgtX = GetUnitX (DLTrgt)
        set DLTrgtY = GetUnitY (DLTrgt)
        set DLSpecAngle = bj_RADTODEG * Atan2 (DLCstrY - DLTrgtY, DLCstrX - DLTrgtX)
        set DLTrgtNewX = DLTrgtX + (DLSpecB * Cos(DLSpecAngle))
        set DLTrgtNewY = DLTrgtY + (DLSpecB * Sin(DLSpecAngle))
        call IssuePointOrder (DLTrgt, "move", DLTrgtNewX, DLTrgtNewY)
        endif
        call GroupRemoveUnit (DLTrgtGrpA, DLTrgt)
        set DLTrgt = null
    endloop
    call DestroyGroup (DLTrgtGrpA)    
    call TriggerSleepAction (3.0)    
    loop
        set DLTrgt = FirstOfGroup (DLTrgtGrpB)
        exitwhen DLTrgt == null
        set DLTrgtSpd = GetUnitMoveSpeed (DLTrgt) -100
        call SetUnitMoveSpeed (DLTrgt, DLTrgtSpd)
        call GroupRemoveUnit (DLTrgtGrpB, DLTrgt)
        set DLTrgt = null
    endloop
    call DestroyGroup (DLTrgtGrpB)
    set DLCstr = null     
endfunction
    
function InitTrig_AbilityDivineLight takes nothing returns nothing
    set gg_trg_AbilityDivineLight = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ (gg_trg_AbilityDivineLight, EVENT_PLAYER_UNIT_SPELL_CAST )
    call TriggerAddCondition (gg_trg_AbilityDivineLight, Condition (function AbilityDivineLight_Condition01))
    call TriggerAddAction (gg_trg_AbilityDivineLight, function AbilityDivineLight_Action01)
endfunction
 
Level 5
Joined
Sep 19, 2006
Messages
152
So aside changing the line from

set DLSpecAngle = bj_RADTODEG * Atan2 (DLCstrY - DLTrgtY, DLCstrX - DLTrgtX)

to

set DLSpecAngle = Atan2 (DLTrgtY - DLCstrY, DLTrgtX - DLCstrX),

does the rest of the trigger look "kosher"? If not, please let me know of any other corrections. Thanks, guys!
 
Level 13
Joined
Nov 22, 2006
Messages
1,260
I suppose with this loop you want to do "pick every unit in group" right? Then this is wrong (this is from the loop):

JASS:
set DLTrgt = null

This will affect only the first unit in group, because you set it to null and the loop will exit if that happens, the unit will set too null when you reach the last unit, that's how it works. Once the variable is set to null you can't use it in the rest of the function (so whenever you used it after that, it won't work). Best nullify variables in the end of the function.

Guys, correct me if I'm wrong, maybe I got this nullification all wrong
 
Status
Not open for further replies.
Top