• 🏆 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!
  • 🏆 Hive's 6th HD Modeling Contest: Mechanical is now open! Design and model a mechanical creature, mechanized animal, a futuristic robotic being, or anything else your imagination can tinker with! 📅 Submissions close on June 30, 2024. Don't miss this opportunity to let your creativity shine! Enter now and show us your mechanical masterpiece! 🔗 Click here to enter!

Vjass System Review

Status
Not open for further replies.
Level 10
Joined
Jan 21, 2007
Messages
576
Alright so I am currently making a system that my map's spells will be based on and am looking for criticism on it. It contains dummy recycling and functions, custom projectiles (can be stopped in place by a heroes shield and then continue on when no longer blocked), a over-time system etc. etc.

Basically whatever any of you have time to look over and can give me feedback on how to optimize would be great.

Map updated to v3.1!
Code attached!




JASS:
library CWmain initializer init

globals
    constant integer FREEZE = 'A005'
    unit Unit
    group Group = CreateGroup() //Global juggle group
    real X     //Global juggle X coord (real)
    real Y     //Global juggle Y coord (real)
    real Real //Global juggle real
    real array FreezeAoe
endglobals
//
//==============================FILTERS
//
//Filter 1 - Allows enemy ground units and air units.
function Filter1 takes nothing returns boolean
    return (IsUnitEnemy(GetFilterUnit(),GetOwningPlayer(Unit)) == true)
endfunction

//Filter 2 - Allows missile freezers.
function Filter2 takes nothing returns boolean
    if GetUnitAbilityLevel(GetFilterUnit(),FREEZE) == 1 and IsUnitInRangeXY(GetFilterUnit(), X,Y,Real) == true then
        return true
    else
        return false
    endif
endfunction
//
//==============================CALLBACKSS
//
//Callback 1 - Removes nonenemy non freezers or to far away units.
function Callback1 takes nothing returns nothing
    if GetUnitAbilityLevel(GetEnumUnit(),FREEZE) == 0 or IsUnitInRangeXY(GetEnumUnit(), X,Y,FreezeAoe[GetUnitAbilityLevel(GetEnumUnit(),'A005')]) == false then
        call GroupRemoveUnit(Group,GetEnumUnit())
    endif
endfunction
//Callback 2 - Damages unit
function Callback2 takes nothing returns nothing
    call UnitDamageTarget(Unit,GetEnumUnit(),Real,false,true,ATTACK_TYPE_CHAOS,DAMAGE_TYPE_UNIVERSAL,WEAPON_TYPE_WHOKNOWS)
endfunction
//
//==============================INIT
//
private function init takes nothing returns nothing
set FreezeAoe[1] = 190
endfunction

endlibrary
JASS:
library CWdummy
globals
real GRAVEX = 3000
real GRAVEY = 2750
integer DIT   = 0
integer DAT   = 0
integer DT    = 0
unit    array DI
unit    array DA
Dummy   array DUMS
endglobals

struct Dummy
effect de
unit d
method onDestroy takes nothing returns nothing
    call DestroyEffect(.de)
    call SetUnitX(.d,GRAVEX)
    call SetUnitY(.d,GRAVEY)
endmethod
endstruct

function CDummy takes player p, real x, real y, string e returns unit
        local Dummy d
        local unit u
        local integer i = 0
        if DI[0] == null then
            set d = Dummy.create()
            set DA[DAT] = CreateUnit(p,'h000',x,y,0)
            set d.d = DA[DAT]
            set u = DA[DAT]
            call SetUnitX(u,x)
            call SetUnitY(u,y)
            set d.de = AddSpecialEffectTarget(e,u,"origin")
            set DAT = DAT + 1
        else
            set d = Dummy.create()
            set u = DI[0]
            set d.d = u
            set d.de = AddSpecialEffectTarget(e,u,"origin")
            call SetUnitOwner(u,p, true)
            call SetUnitX(u,x)
            call SetUnitY(u,y)
            loop
                exitwhen i >= DIT
                set DI[i] = DI[i+1]
                set i = i + 1
            endloop
            set DIT = DIT - 1
        endif
        set DUMS[DT] = d
        set DT = DT + 1
        call ShowUnit(u,true)
        return u
endfunction

function SetDummyHomingTarget takes unit u, unit target returns nothing
    call SetUnitLookAt(u, "Bone_Head", target, 0., 0., 0.)
endfunction

function ClearDummy takes unit u returns nothing
    local integer i = 0
    local Dummy d
    loop
        exitwhen i >= DT
        if DUMS[i].d == u then
            set d = DUMS[i]
            set DUMS[i] = DUMS[DT-1]
            set DT = DT - 1
            call d.destroy()
        endif
        set i = i + 1
    endloop
endfunction

function RecDummy takes unit u returns nothing
    local integer i = 0
    set DI[DIT] = u
    call SetUnitFlyHeight(u,50,0.)
    loop
        exitwhen i >= DAT
        if DA[i] == u then
            loop
                exitwhen i >= DAT
                set DA[i] = DA[i+1]
                set i = i + 1
            endloop
            set DAT = DAT - 1
        endif
        set i = i + 1
    endloop
    set DIT = DIT + 1
    call ClearDummy(u)
endfunction

function Cast takes unit c, integer ID, unit t, string str, integer l returns nothing
    local unit u = CDummy(GetOwningPlayer(c), GetUnitX(t),GetUnitY(t),"")
    call UnitAddAbility(u,ID)
    call SetUnitAbilityLevel(u,ID,l)
    call IssueTargetOrder(u,str,t)
    call RecDummy(u)
endfunction

endlibrary
JASS:
library CWovertime initializer Init requires CWstatlib
globals
    private Xot array XOTS
    private integer       total = 0
    private real LowestInterval = .01
endglobals
function CreateXot takes unit Caster, unit Target, real Amnt, real Interval, real Dur, string SpecEfec, string AttachPoint, attacktype AttackType, real Angle,string Flag, boolean Stacks,integer X, integer Level returns nothing
        local Xot xot
        local integer i = 0
        local boolean cont = true
        loop
            exitwhen i >= total or cont == false
            set xot = XOTS[i]
            if xot.Target == Target then
                if Flag == Flag then
                    if Stacks then
                        set xot             = Xot.create()
                        set xot.Target      = Target
                        set xot.Caster      = Caster
                        set xot.Amnt        = Amnt
                        set xot.Interval    = Interval
                        set xot.Dur         = Dur
                        set xot.SpecEfec    = SpecEfec
                        set xot.AttachPoint = AttachPoint
                        set xot.Flag        = Flag
                        set xot.Angle       = Angle
                        set xot.X           = X
                        set xot.Level       = Level
                        set XOTS[total]     = xot
                        if total == 0 then
                            call TimerStart(Xot.Tim, LowestInterval, true, function Xot.Loop)
                        endif
                        set total = total + 1
                        set cont = false
                    else
                        set xot.Target      = Target
                        set xot.Caster      = Caster
                        set xot.Amnt        = Amnt
                        set xot.Interval    = Interval
                        set xot.Dur         = Dur
                        set xot.SpecEfec    = SpecEfec
                        set xot.AttachPoint = AttachPoint
                        set xot.Flag        = Flag
                        set xot.Angle       = Angle
                        set xot.X           = X
                        set xot.Level       = Level
                        set cont = false
                    endif
                endif
            endif
            set i = i + 1
        endloop
        if cont then
            set xot             = Xot.create()
            set xot.Target      = Target
            set xot.Caster      = Caster
            set xot.Amnt        = Amnt
            set xot.Interval    = Interval
            set xot.Dur         = Dur
            set xot.SpecEfec    = SpecEfec
            set xot.AttachPoint = AttachPoint
            set xot.Flag        = Flag
            set xot.Angle       = Angle
            set xot.X           = X
            set xot.Level       = Level
            set XOTS[total]     = xot
            if total == 0 then
                call TimerStart(Xot.Tim, LowestInterval, true, function Xot.Loop)
            endif
            set total = total + 1
        endif
endfunction
struct Xot
unit       Target
integer      X
unit         Caster
real         Amnt
real         Interval
real         Dur
real         CurrentWait = 0
real         Angle
string       SpecEfec
string       AttachPoint
string       Flag
attacktype   AttackType
boolean      Stacks
integer      Level
static timer Tim         = null
static method Loop takes nothing returns nothing
    local Xot xot
    local integer i = 0
    local real angle
    loop
        exitwhen i >= total
        set xot = XOTS[i]
        if GetWidgetLife(xot.Target) >= 0 then
            set xot.Dur = xot.Dur-LowestInterval
            set xot.CurrentWait = xot.CurrentWait+LowestInterval
            if xot.Dur >=0 then //Main loop
                if xot.CurrentWait >= xot.Interval then
                    if xot.X == 1 then //Generic Damage (with effect)
                        call UnitDamageTarget(xot.Caster, xot.Target, xot.Amnt, false, false, xot.AttackType, DAMAGE_TYPE_NORMAL,WEAPON_TYPE_WHOKNOWS)
                        call DestroyEffect(AddSpecialEffectTarget(xot.SpecEfec, xot.Target, xot.AttachPoint))
                    endif
                    if xot.X == 2 then //Generic Heal (with effect)
                        call SetWidgetLife(xot.Target,GetWidgetLife(xot.Target)+xot.Amnt)
                        call DestroyEffect(AddSpecialEffectTarget(xot.SpecEfec, xot.Target, xot.AttachPoint))
                    endif
                    if xot.X == 3 then //Effectively a wait
                        
                    endif
                    set xot.CurrentWait = 0
                    if xot.X == 4 then //Straddle unit with dummy
                        call SetUnitX(xot.Caster,GetUnitX(xot.Target))
                        call SetUnitY(xot.Caster,GetUnitY(xot.Target))
                    endif
                endif
            else //Last tick then destruction
                if xot.X == 1 then //Generic Damage (with effect)
                    call UnitDamageTarget(xot.Caster, xot.Target, xot.Amnt, false, false, xot.AttackType, DAMAGE_TYPE_NORMAL,WEAPON_TYPE_WHOKNOWS)
                    call DestroyEffect(AddSpecialEffectTarget(xot.SpecEfec, xot.Target, xot.AttachPoint))
                endif
                if xot.X == 2 then //Generic Heal (with effect)
                    call SetWidgetLife(xot.Target,GetWidgetLife(xot.Target)+xot.Amnt)
                    call DestroyEffect(AddSpecialEffectTarget(xot.SpecEfec, xot.Target, xot.AttachPoint))
                endif
                if xot.X == 3 then //Specific spell, cast after wait.
                    call Cast(xot.Caster, 'A002', xot.Target, "entanglingroots", xot.Level)
                    call CreateXot(xot.Caster,xot.Target,((100*xot.Level)/((1+.5*xot.Level)/.5))+GetStat(xot.Caster,"SP")/(4-xot.Level),.5,(1+.5*xot.Level),"","chest",ATTACK_TYPE_MAGIC,0,"Germ",true,1,xot.Level)
                endif
                if xot.X == 4 then //Straddle unit with dummy, recycle
                    call SetUnitX(xot.Caster,GetUnitX(xot.Target))
                    call SetUnitY(xot.Caster,GetUnitY(xot.Target))
                    call RecDummy(xot.Caster)
                endif
                set XOTS[i] = XOTS[total-1]
                set total = total - 1
                call xot.destroy()
            endif
        else
            set XOTS[i] = XOTS[total-1]
            set total = total - 1
            call xot.destroy()
        endif
            set i = i + 1
    endloop
    if total == 0 then
        call PauseTimer(xot.Tim)
    endif
endmethod
method onDestroy takes nothing returns nothing
    set this.Target      = null
    set this.Caster      = null
    set this.Amnt        = 0
    set this.Interval    = 0
    set this.Dur         = 0
    set this.CurrentWait = 0
    set this.SpecEfec    = ""
    set this.AttachPoint = ""
    set this.Flag        = ""
    set this.AttackType  = null
    set this.Angle       = 0
    set this.Level       = 0
endmethod
endstruct

function RemoveXot takes unit u returns nothing
    local integer i = 0
    local Xot xot
    loop
        exitwhen i >= total
        if XOTS[i].Target == u then
            set xot = XOTS[i]
            set XOTS[i] = XOTS[total-1]
            set total = total - 1
            call xot.destroy()
        endif
        set i = i + 1
    endloop
endfunction

function IsUnitAffectedBy takes unit u, string flag returns boolean
    local integer i = 0
    local Xot xot
    loop
        exitwhen i >= total
        if XOTS[i].Target == u then
            set xot = XOTS[i]
            if xot.Flag == flag then
                return true
            endif
        endif
        set i = i + 1
    endloop
    return false
endfunction
private function Init takes nothing returns nothing
    set Xot.Tim = CreateTimer()
endfunction
endlibrary
JASS:
library CWonhit requires CWovertime

function Hit takes unit t, unit c, integer i, integer l, real dmg, real aoerng, integer abil, string orderID returns nothing
    local group g = CreateGroup()
    //Event ID 1 - Spell > Specific > Germinate: Slows the target and starts the 5(4,3) second countdown for the spell effects.
    if i == 1 then
        call Cast(c, 'A001', t, "slow", l)
        call CreateXot(c,t,0,1,6-1*l,"","",ATTACK_TYPE_MAGIC,0,"GermWait",true,3,l)
    endif
    //Event ID 2 - Spell > Generic: Causes the projectile to deal damage.
    if i == 2 then
        if aoerng > 0 then
            set Unit = c
            set Real = dmg
            call GroupEnumUnitsInRange(g,GetUnitX(t),GetUnitY(t),aoerng, Condition(function Filter1))
            call ForGroup(g,function Callback2)
        else
            call UnitDamageTarget(c,t,dmg,false,true,ATTACK_TYPE_CHAOS,DAMAGE_TYPE_UNIVERSAL,WEAPON_TYPE_WHOKNOWS)
        endif
    endif
    if i == 3 then
        call Cast(c, abil, t, orderID, l)
    endif
endfunction

endlibrary
JASS:
library CWprojectile initializer Init requires CWmain CWonhit
//==============================================================================================================================
globals
    private projectile array PROS
    private integer total = 0
    private real Interval = .03
endglobals
//==============================================================================================================================

struct projectile
unit         m       //Missile
unit         c       //Caster
string       mdl     //Model String
unit         t       //Target
real         sp      //Speed
integer      ID      //Event Id
real         d       //Distance Between m and t
integer      Level   //Level
real         dmg     //Damage done
real         aoe     //Aoe
integer      abil    //Ability ID
string       orderID //Order ID
static timer Tim         = null

method onDestroy takes nothing returns nothing
    call RecDummy(.m)
    set .m     = null
    set .t     = null
    set .mdl   = null
endmethod

static method Loop takes nothing returns nothing
    local projectile p
    local integer i = 0
    local integer i2 = 0
    local real difference
    local real ABP
    local real z1
    local real z2
    loop
        exitwhen i >= total
        set p = PROS[i]
        if GetWidgetLife(p.t) <= 0 then
            call DestroyEffect(AddSpecialEffectTarget(p.mdl,p.t,"origin"))
            call p.destroy()
            set total = total - 1
            set PROS[i] = PROS[total]
        else
            set i2 = 0
            set X = GetUnitX(p.m)
            set Y = GetUnitY(p.m)
            call GroupClear(Group)
            loop
                exitwhen i2 == DAT
                call GroupAddUnit(Group,DA[i2])
                set i2 = i2 + 1
            endloop
            call ForGroup(Group,function Callback1)
            if CountUnitsInGroup(Group) <= 0 then
                set ABP = Atan2(GetUnitY(p.t) - GetUnitY(p.m), GetUnitX(p.t) - GetUnitX(p.m))
                set p.d = DistanceBetweenPoints(Location(GetUnitX(p.m),GetUnitY(p.m)),Location(GetUnitX(p.t),GetUnitY(p.t)))
                if p.d < p.sp+1 then
                    call SetUnitX(p.m, GetUnitX(p.t))
                    call SetUnitY(p.m, GetUnitY(p.t))
                    set p.d = 0
                else
                    call SetUnitX(p.m, GetUnitX(p.m) + p.sp * Cos(ABP))
                    call SetUnitY(p.m, GetUnitY(p.m) + p.sp * Sin(ABP))
                    set p.d = p.d - p.sp
                endif
                set z1 = GetUnitFlyHeight(p.m) + GetLocationZ(Location(GetUnitX(p.m),GetUnitY(p.m)))
                set z2 = GetUnitFlyHeight(p.t) + GetLocationZ(Location(GetUnitX(p.t),GetUnitY(p.t)))
                if (z1 > z2) then
                    if z1 - p.sp < z2 then
                        call SetUnitFlyHeight(p.m,z2,0.)
                    else
                        call SetUnitFlyHeight(p.m,GetUnitFlyHeight(p.m) - p.sp,0.)
                    endif
                elseif (z2 > z1) then
                    if z1 + p.sp > z2 then
                        call SetUnitFlyHeight(p.m,z2,0.)
                    else
                        call SetUnitFlyHeight(p.m,GetUnitFlyHeight(p.m) + p.sp,0.)
                    endif
                endif
                if GetUnitFlyHeight(p.m) < 50 then
                    call SetUnitFlyHeight(p.m,50,0.)
                endif
                if (p.d <= 10.00 or p.d <= p.sp+1) then
                    if (z1 == z2 or z1 == z2 + 50) and z1 == 99199 then
                        call Hit(p.t, p.c, p.ID, p.Level, p.dmg, p.aoe,p.abil,p.orderID)
                        call DestroyEffect(AddSpecialEffectTarget(p.mdl,p.t,"origin"))
                        call p.destroy()
                        set total = total - 1
                        set PROS[i] = PROS[total]
                    endif
                endif
            endif
            set i = i + 1
        endif
    endloop
    if total == 0 then
        call PauseTimer(p.Tim)
    endif
endmethod
endstruct
//==============================================================================================================================
function CreateP takes unit caster, string mdl, real scale, unit target, real speed, integer EffectID, integer Level, real dmg, real aoe, integer abil, string orderID returns nothing
        local projectile p
        set p           = projectile.create()
        set p.m         = CDummy(GetOwningPlayer(caster), GetUnitX(caster),GetUnitY(caster),mdl)
        set p.t         = target
        set p.mdl       = mdl
        set p.c         = caster
        set p.sp        = speed
        set p.aoe       = aoe
        set p.ID        = EffectID
        set p.Level     = Level
        set p.dmg       = dmg
        set p.abil      = abil
        set p.orderID   = orderID
        call SetUnitScale(p.m, scale * 0.01, scale * 0.01, scale * 0.01)
        call SetDummyHomingTarget(p.m, target)
        set PROS[total] = p
        if total == 0 then
            call TimerStart(projectile.Tim, Interval, true, function projectile.Loop)
        endif
        set total = total + 1
endfunction
//==============================================================================================================================
function KillP takes unit u returns nothing
    local integer i = 0
    local projectile p
    loop
        exitwhen i >= total
        if PROS[i].m == u then
            set p = PROS[i]
            set total = total - 1
            set PROS[i] = PROS[total]
            call p.destroy()
        endif
        set i = i + 1
    endloop
endfunction
function Init takes nothing returns nothing
    set projectile.Tim = CreateTimer()
endfunction

endlibrary

 

Attachments

  • Clockwork_v3.1.w3x
    70.4 KB · Views: 61
Last edited:
Level 14
Joined
Nov 18, 2007
Messages
1,084
I think more people will review this system if you can post the code.

Edit:
CWmain:

  • Make a constant for the ability 'A005' (It is a system and should easily be configured by users.) Same applies to other abilities used by the system.
CWdummy:

  • Instead of GetUnitState(p.t, UNIT_STATE_LIFE) <= 0 use GetWidgetLife(p.t) Applies to every other instances of this.
  • Try to avoid using BJ's unless it would be useless to inline them. Applies to every other instances of this.
  • Don't use locations; use coordinates instead. Applies to every other instance of you using locations except for GetLocationZ.
  • Use radians instead of degrees. Applies to every other instances of this.
CWstatlib

  • Instead of SetUnitState(Set.U,UNIT_STATE_LIFE,GetUnitState(Set.U,UNIT_STATE_LIFE)+Set.LGen) use SetWidgetLife(Set.U,GetWidgetLife(Set.U)+Set.LGen). Applies to every other instances.

CWonhit

  • FirstOfGroup loops are slower than using the filter directly or ForGroup.
I don't like your indenting for some of the code. :p
What are you doing with the empty init functions?
Add more documentation?
Make more things configurable. (Like damage)

So far I've only skimmed the code. Will edit again when I actually see the visual effects.

Edit:
Seemed okay. Lags only if there's a lot of missiles at once but clears up when they're gone.
Why do the missiles seemingly get destroyed at the grave area though?
I don't understand what's happening when you target the missiles at the Blood Mage. Is it because of the shield?
If it is a shield, shouldn't the missiles get destroyed? As of now, the missiles just follow the Blood Mage aimlessly.
Edit: Now I understand what it does... Though I think it would have been better if your example was a Shield buff.

Edit:
Missiles should not take up food. Since they're just missiles, you may also want to consider making them owned by Player(15).
 
Last edited:
Level 10
Joined
Jan 21, 2007
Messages
576
I think more people will review this system if you can post the code.

Edit:
CWmain:

  • Make a constant for the ability 'A005' (It is a system and should easily be configured by users.) Same applies to other abilities used by the system.
Done.

CWdummy:

  • Instead of GetUnitState(p.t, UNIT_STATE_LIFE) <= 0 use GetWidgetLife(p.t) Applies to every other instances of this.
  • Try to avoid using BJ's unless it would be useless to inline them. Applies to every other instances of this.
  • Don't use locations; use coordinates instead. Applies to every other instance of you using locations except for GetLocationZ.
  • Use radians instead of degrees. Applies to every other instances of this.
Done.

CWstatlib

  • Instead of SetUnitState(Set.U,UNIT_STATE_LIFE,GetUnitState(Set.U,UNIT_STATE_LIFE)+Set.LGen) use SetWidgetLife(Set.U,GetWidgetLife(Set.U)+Set.LGen). Applies to every other instances.
Done.

CWonhit

  • FirstOfGroup loops are slower than using the filter directly or ForGroup.
I don't like your indenting for some of the code. :p
What are you doing with the empty init functions?
Add more documentation?
Make more things configurable. (Like damage)

Fixed the FirstOfGroups, which indenting =p? I might document it when it is optimized more. Configuration can be added when it is optimized more. (So I don't have to keep changing things).

So far I've only skimmed the code. Will edit again when I actually see the visual effects.

Edit:
Seemed okay. Lags only if there's a lot of missiles at once but clears up when they're gone.
Why do the missiles seemingly get destroyed at the grave area though?
I don't understand what's happening when you target the missiles at the Blood Mage. Is it because of the shield?
If it is a shield, shouldn't the missiles get destroyed? As of now, the missiles just follow the Blood Mage aimlessly.
Edit: Now I understand what it does... Though I think it would have been better if your example was a Shield buff.


That is there effect getting destroyed not them. His shield freezes missiles (was just testing it out), it is best not to actually shoot missiles at him because they will never hit him lol, but shoot missiles at a peasant with him in between you and the target.

Edit:
Missiles should not take up food. Since they're just missiles, you may also want to consider making them owned by Player(15).
They took up food so I could easily see if they were being recycled, fixed.

EDIT: Starts to get laggy at about 47-49 active homing missile.
 
Last edited:
Level 14
Joined
Nov 18, 2007
Messages
1,084
Fixed the FirstOfGroups, which indenting =p?
I mainly meant CWdummy.
It's just my opinion, but I don't like seeing variables so close to the left side. :p
but shoot missiles at a peasant with him in between you and the target.
Oh. That was pretty neat, though I think it would look better if the missile bounced off and disappeared or went around the mage instead of just getting frozen in mid-air. (That's just my biased opinion.)
 
Level 10
Joined
Jan 21, 2007
Messages
576
Ah, indented the globals (which is what I think you were refering to). Also, I have gotten pretty advanced in jass but I have yet to know what people mean when they say "unless it would be useless to inline them". What do you/they mean by inline?

And if anything I would just make it kill the missiles when they hit that shield.
 
Level 14
Joined
Nov 18, 2007
Messages
1,084
Also, I have gotten pretty advanced in jass but I have yet to know what people mean when they say "unless it would be useless to inline them". What do you/they mean by inline?

And if anything I would just make it kill the missiles when they hit that shield.
Since I'm sort of suck with words I'll just provide an example.
Here's a BJ:
JASS:
function AcosBJ takes real degrees returns real
If you look at that function in the "Function List" of the Trigger Editor, you'll see that it actually is just doing
JASS:
Acos(degrees) * bj_RADTODEG
By inlining, you would use that instead. (Or even inline bj_RADTODEG to 57.29577951)

I agree that killing the missiles would be a better alternative.

Edit: More about inlining.
Don't use DistanceBetweenPoints since you're forced to create (and leak) a location. As you already have coordinates, just use them instead.
What DistanceBetweenPoints actually does:
JASS:
function DistanceBetweenPoints takes location locA, location locB returns real
    local real dx = GetLocationX(locB) - GetLocationX(locA)
    local real dy = GetLocationY(locB) - GetLocationY(locA)
    return SquareRoot(dx * dx + dy * dy)
endfunction
 
Level 10
Joined
Jan 21, 2007
Messages
576
Ah, then yea I already knew about that just didn't match about face to name I guess =p. I will update that in a little while.
 
Status
Not open for further replies.
Top