• 🏆 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!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[JASS] a little question

Status
Not open for further replies.
Level 11
Joined
Apr 6, 2008
Messages
760
i posted this spell in the "spell section" in it got "Non-approved Still in moderation queue" just want to figure out why since i havnt been doing jass for so long time(like 1 month), is it the whole code, just stupid line or something that is bad/wrong. i have gone thru this code like 10 times and i cant find something(and yes im very stuborn) :/

JASS:
//==========================SETUP STARTS========================//
constant function Missle_SpellId takes nothing returns integer
    return 'A000'
endfunction

constant function Missle_DummyId takes nothing returns integer
    return 'h000'
endfunction

constant function Missle_SFX takes nothing returns string
    return "Abilities\\Spells\\Human\\Thunderclap\\ThunderClapCaster.mdl"
endfunction

constant function Missle_DmgArea takes nothing returns real
    return 300.
endfunction

constant function Missle_Dmg takes nothing returns real
    return 100.
endfunction

constant function MissleMaxDist takes nothing returns real
    return 2000.
endfunction

constant function MissleMoveSpd takes nothing returns real
    return 30.
endfunction

function Missle_dmg takes integer lvl returns real
   return 100.*lvl //make your forumla here 
endfunction
//==========================SETUP ENDS==========================//
function Missle_Conds takes nothing returns boolean
    return GetSpellAbilityId() == Missle_SpellId()
endfunction

function MisslePreLoad takes nothing returns nothing
    call Preload(Missle_SFX())
    call RemoveUnit(CreateUnit(Player(15),Missle_DummyId(),0,0,0))
endfunction

function MPick_Conds takes nothing returns boolean
    return GetWidgetLife(GetFilterUnit()) > .405 and not IsUnitType(GetFilterUnit(),UNIT_TYPE_STRUCTURE) and IsUnitEnemy(GetFilterUnit(),GetOwningPlayer(GetHandleUnit(GetExpiredTimer(),"c")))
endfunction    

function Missle_End takes nothing returns nothing
    local trigger trig = GetTriggeringTrigger()
    local timer Loop = GetHandleTimer(trig,"Loop") 
    
    call PauseTimer(Loop)
    call DestroyTimer(Loop)
    call DestroyTrigger(trig) 
    call FlushHandleLocals(Loop)
    call FlushHandleLocals(trig)
    
    set trig = null
    set Loop = null
endfunction

function Missle_Move takes nothing returns nothing
    local timer Mtimer = GetExpiredTimer()
    local unit c = GetHandleUnit(Mtimer,"c")
    local unit dum = GetHandleUnit(Mtimer,"dum")
    local group g
    local real dist = GetHandleReal(Mtimer,"dist")+30
    local real angle = GetHandleReal(Mtimer,"angle")
    local unit d
    
    call SetHandleReal(Mtimer,"dist",dist) 
    call SetUnitX(dum,(GetUnitX(dum) + MissleMoveSpd() * Cos(angle * bj_DEGTORAD)))
    call SetUnitY(dum,(GetUnitY(dum) + MissleMoveSpd()  * Sin(angle * bj_DEGTORAD)))
    
    if CountUnitsInGroup(GetUnitsInRangeOfLocMatching(60.,GetUnitLoc(dum),Filter(function MPick_Conds))) > 0 then
        call DestroyEffect(AddSpecialEffect(Missle_SFX(),GetUnitX(dum),GetUnitY(dum)))
        set g = CreateGroup()
        call GroupEnumUnitsInRange(g,GetUnitX(dum),GetUnitY(dum),Missle_DmgArea(),Filter(function MPick_Conds))
        loop
            set d = FirstOfGroup(g)
            exitwhen d == null
            call GroupRemoveUnit(g,d)
            call UnitDamageTarget(c,d,Missle_dmg(GetUnitAbilityLevel(c,Missle_SpellId())),false,false,null,null,null)
            call RemoveUnit(dum)
            call FlushHandleLocals(Mtimer)
            call PauseTimer(Mtimer)
            call DestroyTimer(Mtimer)
            set d = null
        endloop
    endif
        
    if dist >= MissleMaxDist() and not IsUnitType(dum,UNIT_TYPE_DEAD) then
        call KillUnit(dum)
        call FlushHandleLocals(Mtimer)
        call PauseTimer(Mtimer)
        call DestroyTimer(Mtimer)
    endif
       
    set c = null
    set dum = null
    set g = null
    set Mtimer = null
endfunction     

function Missle_Actions takes nothing returns nothing
    local timer Loop = GetExpiredTimer()
    local unit c = GetHandleUnit(Loop,"c")
    local real x = GetHandleReal(Loop,"x")
    local real y = GetHandleReal(Loop,"y")
    local real angle = GetHandleReal(Loop,"angle")
    local timer Mtimer = CreateTimer()
    local unit dum = CreateUnit(GetOwningPlayer(c),Missle_DummyId(),(x + 75 * Cos(angle * bj_DEGTORAD)),(y + 75  * Sin(angle * bj_DEGTORAD)),angle)
    
    call PauseUnit(dum,true)
    
    call SetHandleHandle(Mtimer,"c",c)
    call SetHandleHandle(Mtimer,"dum",dum)
    call SetHandleReal(Mtimer,"angle",angle)

    call TimerStart(Mtimer,.035,true,function Missle_Move)
    
    set c = null
    set dum = null
    set Loop = null
    set Mtimer = null
endfunction
    
function Missle_Act takes nothing returns nothing
    local trigger trig = CreateTrigger()
    local timer Loop = CreateTimer()
    local unit c = GetTriggerUnit()
    local real x = GetUnitX(c)
    local real y = GetUnitY(c)
    local location = GetSpellTargetLoc()
    local real tx = GetLocationX(loc)
    local real ty = GetLocationY(loc)
    local real angle = Atan2((ty-y),(tx-x))*57.29583
        
    call SetHandleHandle(Loop,"c",c)
    call SetHandleReal(Loop,"x",x)
    call SetHandleReal(Loop,"y",y)
    call SetHandleReal(Loop,"angle",angle)
    call SetHandleHandle(trig,"Loop",Loop)
    
    call TriggerRegisterUnitEvent(trig,c, EVENT_UNIT_SPELL_ENDCAST)
    call TriggerAddAction(trig, function Missle_End)
    
    call TimerStart(Loop,1.,true,function Missle_Actions)
    
    call Removelocation(loc)
    set loc = null
    set trig = null
    set Loop = null
    set c = null
endfunction  
    
function InitTrig_Missle takes nothing returns nothing
    local trigger t = CreateTrigger()
    local integer a = 0
    loop
        call TriggerRegisterPlayerUnitEventSimple(t,Player(a),EVENT_PLAYER_UNIT_SPELL_EFFECT)
        set a = a + 1
        exitwhen a == 16
    endloop
    
    call TriggerAddAction(t, function Missle_Act)
    call TriggerAddCondition(t, Filter(function Missle_Conds))
    call MisslePreLoad()
endfunction
 

Attachments

  • Missle.w3x
    36.3 KB · Views: 64
Last edited:
Level 40
Joined
Dec 14, 2005
Messages
10,532
i posted this spell in the "spell section" in it got "Non-approved Still in moderation queue" just want to figure out why since i havnt been doing jass for so long time(like 1 month), is it the whole code, just stupid line or something that is bad/wrong. i have gone thru this code like 10 times and i cant find something(and yes im very stuborn) :
The spells section moderation is pretty much dead at the moment, I have enough on my hands with the forums and all the other spell moderators have resigned or are inactive. (Except I think Ghan_04 and DSG occasionally moderate a spell or two)
 
Level 40
Joined
Dec 14, 2005
Messages
10,532
Anyway, I never got why people create all those stupid callbacks just to "make it more comfortable to setup".
Its better to just use Globals for it. Faster (I think), and much more readable (unless you are a noob and you don't use JNGP :D).
JESP outdates Grimoire :p

Your code isn't that bad. However, note that you leak GetSpellTargetLoc() twice, and you really should look into JNGP. (JassNewGenPack)

EDIT: Oh, I see (your last post). Are you using a cracked version of wc3, or a mac, or what? And a stack of arrays would still be preferrable to handles, which are rather unstable.
 
Level 5
Joined
Oct 27, 2007
Messages
158
i posted this spell in the "spell section" in it got "Non-approved Still in moderation queue" just want to figure out why since i havnt been doing jass for so long time(like 1 month), is it the whole code, just stupid line or something that is bad/wrong. i have gone thru this code like 10 times and i cant find something(and yes im very stuborn) :/

JASS:
//==========================SETUP STARTS========================//
//Using functions to return constants is imo utter nonsense.
//You can simply create global constants and use them everywhere
//And it'll still be easy to setup.

constant function Missle_SpellId takes nothing returns integer
    return 'A000'
endfunction

constant function Missle_DummyId takes nothing returns integer
    return 'h000'
endfunction

constant function Missle_SFX takes nothing returns string
    return "Abilities\\Spells\\Human\\Thunderclap\\ThunderClapCaster.mdl"
endfunction

constant function Missle_DmgArea takes nothing returns real
    return 300.
endfunction

constant function Missle_Dmg takes nothing returns real
    return 100.
endfunction

constant function MissleMaxDist takes nothing returns real
    return 2000.
endfunction

constant function MissleMoveSpd takes nothing returns real
    return 30.
endfunction

function Missle_dmg takes integer lvl returns real
   return 100.*lvl //make your forumla here 
endfunction
//==========================SETUP ENDS==========================//
function Missle_Conds takes nothing returns boolean
    return GetSpellAbilityId() == Missle_SpellId()
endfunction

function MisslePreLoad takes nothing returns nothing
    call Preload(Missle_SFX())
    // Define round reals by putting a point to mark it as a real.
    call RemoveUnit(CreateUnit(Player(15),Missle_DummyId(),0,0,0))
endfunction

function MPick_Conds takes nothing returns boolean
    return GetWidgetLife(GetFilterUnit()) > .405 and not IsUnitType(GetFilterUnit(),UNIT_TYPE_STRUCTURE) and IsUnitEnemy(GetFilterUnit(),GetOwningPlayer(GetHandleUnit(GetExpiredTimer(),"c")))
endfunction    

function Missle_End takes nothing returns nothing
    local trigger trig = GetTriggeringTrigger()
    local timer Loop = GetHandleTimer(trig,"Loop") 
    
    call PauseTimer(Loop)
    call DestroyTimer(Loop)
    call DestroyTrigger(trig) 
    call FlushHandleLocals(Loop)
    call FlushHandleLocals(trig)
    
    set trig = null
    set Loop = null
endfunction

function Missle_Move takes nothing returns nothing
    local timer Mtimer = GetExpiredTimer()
    local unit c = GetHandleUnit(Mtimer,"c")
    local unit dum = GetHandleUnit(Mtimer,"dum")
    local group g
    local real dist = GetHandleReal(Mtimer,"dist")+30 //real, you should add a .
    local real angle = GetHandleReal(Mtimer,"angle")
    local unit d
    
    call SetHandleReal(Mtimer,"dist",dist) 
    // You use GetUnitX, GetUnitY for the same unit more than once.
    // Fastest is to set them to two real coordinate values.
    call SetUnitX(dum,(GetUnitX(dum) + MissleMoveSpd() * Cos(angle * bj_DEGTORAD)))
    call SetUnitY(dum,(GetUnitY(dum) + MissleMoveSpd()  * Sin(angle * bj_DEGTORAD)))
    // You leak a location here and a handle.
    // The BJ rangeoflocmatching leaks a group handle.
    // You should use GroupEnumUnitsInRange
    // After that you can simply load the first unit of the group and if it isn't
    // null you can exit and you have done the CountUnitsInGroup faster.
    // There is no need to do the same enumeration twice, since you use the same filter.
    // The iterations will stop when there are zero units in the group or when all units are processed.
    if CountUnitsInGroup(GetUnitsInRangeOfLocMatching(60.,GetUnitLoc(dum),Filter(function MPick_Conds))) > 0 then
        call DestroyEffect(AddSpecialEffect(Missle_SFX(),GetUnitX(dum),GetUnitY(dum)))
        set g = CreateGroup()
        call GroupEnumUnitsInRange(g,GetUnitX(dum),GetUnitY(dum),Missle_DmgArea(),Filter(function MPick_Conds))
        loop
            set d = FirstOfGroup(g)
            exitwhen d == null
            call GroupRemoveUnit(g,d)
            call UnitDamageTarget(c,d,Missle_dmg(GetUnitAbilityLevel(c,Missle_SpellId())),false,false,null,null,null)
            // Shouldn't you remove dum only once, since I don't see dum recreated anywhere.
            call RemoveUnit(dum)
            call FlushHandleLocals(Mtimer)
            call PauseTimer(Mtimer)
            call DestroyTimer(Mtimer)
            // You don't need to null d, it'll be always null when iterations are done. If this loop won't run still no harm done, because d had no handles assigned.
            set d = null
        endloop
    endif
        
    if dist >= MissleMaxDist() and not IsUnitType(dum,UNIT_TYPE_DEAD) then
        call KillUnit(dum)
        call FlushHandleLocals(Mtimer)
        call PauseTimer(Mtimer)
        call DestroyTimer(Mtimer)
    endif
       
    set c = null
    set dum = null
    set g = null
    set Mtimer = null
endfunction     

function Missle_Actions takes nothing returns nothing
    local timer Loop = GetExpiredTimer()
    local unit c = GetHandleUnit(Loop,"c")
    local real x = GetHandleReal(Loop,"x")
    local real y = GetHandleReal(Loop,"y")
    local real angle = GetHandleReal(Loop,"angle")
    local timer Mtimer = CreateTimer()
    //  two reals again that need a .
    local unit dum = CreateUnit(GetOwningPlayer(c),Missle_DummyId(),(x + 75 * Cos(angle * bj_DEGTORAD)),(y + 75  * Sin(angle * bj_DEGTORAD)),angle)
    
    call PauseUnit(dum,true)
    
    call SetHandleHandle(Mtimer,"c",c)
    call SetHandleHandle(Mtimer,"dum",dum)
    call SetHandleReal(Mtimer,"angle",angle)

    call TimerStart(Mtimer,.035,true,function Missle_Move)
    
    set c = null
    set dum = null
    set Loop = null
    set Mtimer = null
endfunction
    
function Missle_Act takes nothing returns nothing
    local trigger trig = CreateTrigger()
    local timer Loop = CreateTimer()
    local unit c = GetTriggerUnit()
    local real x = GetUnitX(c)
    local real y = GetUnitY(c)
    local location = GetSpellTargetLoc()
    local real tx = GetLocationX(loc)
    local real ty = GetLocationY(loc)
    local real angle = Atan2((ty-y),(tx-x))*57.29583
        
    call SetHandleHandle(Loop,"c",c)
    call SetHandleReal(Loop,"x",x)
    call SetHandleReal(Loop,"y",y)
    call SetHandleReal(Loop,"angle",angle)
    call SetHandleHandle(trig,"Loop",Loop)
    
    call TriggerRegisterUnitEvent(trig,c, EVENT_UNIT_SPELL_ENDCAST)
    call TriggerAddAction(trig, function Missle_End)
    
    call TimerStart(Loop,1.,true,function Missle_Actions)
    
    call Removelocation(loc)
    set loc = null
    set trig = null
    set Loop = null
    set c = null
endfunction  
    
function InitTrig_Missle takes nothing returns nothing
    local trigger t = CreateTrigger()
    local integer a = 0
    loop
        call 
// No need to call BJ simple, just use TriggerRegisterPlayerUnitEvent
// Only extra argument you need to give is a filter, which is null in this case.
// Try to avoid BJ calls when it can save exec time or prevent leaks.
TriggerRegisterPlayerUnitEventSimple(t,Player(a),EVENT_PLAYER_UNIT_SPELL_EFFECT)
        set a = a + 1
        exitwhen a == 16
    endloop
    
    call TriggerAddAction(t, function Missle_Act)
    call TriggerAddCondition(t, Filter(function Missle_Conds))
    call MisslePreLoad()
endfunction
// In this case you won't need to destroy the trigger, but it's good habit to null t
// This will prevent a handle leak if you ever need to destroy a trigger at some time.


Code doesn't look bad at all. I've made some comments where you could make some optimizations.
 
Level 5
Joined
Oct 27, 2007
Messages
158
About TriggerRegisterPlayerUnitEventSimple, just use TriggerRegisterAnyUnitEventBJ.

Reals don't need . except in returns.


An integer is not a real, therefore for every integer value you enter in a real value a conversion to real is made. It's good programming behavior to always enter a . if using round real numbers.
 
Level 11
Joined
Apr 6, 2008
Messages
760
small things u dont really think off if u dont go thru it properly and jass newgen dont wanna work on my comp(well i can start it but it seems like WE is not modded, like structs and other things dont work)

this is what i came up with, but there was somethings i didnt understand..

JASS:
function MisslePreLoad takes nothing returns nothing
    call Preload(Missle_SFX())
    // Define round reals by putting a point to mark it as a real.
    call RemoveUnit(CreateUnit(Player(15),Missle_DummyId(),0,0,0))
endfunction

JASS:
// two reals again that need a .
    local unit dum = CreateUnit(GetOwningPlayer(c),Missle_DummyId(),(x + 75 * Cos(angle * bj_DEGTORAD)),(y + 75 * Sin(angle * bj_DEGTORAD)),angle)

and my code

JASS:
function Missle_Conds takes nothing returns boolean
    return GetSpellAbilityId() == Missle_SpellId()
endfunction

function MisslePreLoad takes nothing returns nothing
    call Preload(Missle_SFX())
    call RemoveUnit(CreateUnit(Player(15),Missle_DummyId(),0,0,0))
endfunction

function MPick_Conds takes nothing returns boolean
    return GetWidgetLife(GetFilterUnit()) > .405 and not IsUnitType(GetFilterUnit(),UNIT_TYPE_STRUCTURE) and IsUnitEnemy(GetFilterUnit(),GetOwningPlayer(GetHandleUnit(GetExpiredTimer(),"c")))
endfunction    

function Missle_End takes nothing returns nothing
    local trigger trig = GetTriggeringTrigger()
    local timer Loop = GetHandleTimer(trig,"Loop") 
    
    call PauseTimer(Loop)
    call FlushHandleLocals(Loop)
    call FlushHandleLocals(trig)    
    call DestroyTimer(Loop)
    call DestroyTrigger(trig) 
    
    set trig = null
    set Loop = null
endfunction

function Missle_Move takes nothing returns nothing
    local timer Mtimer = GetExpiredTimer()
    local unit c = GetHandleUnit(Mtimer,"c")
    local unit dum = GetHandleUnit(Mtimer,"dum")
    local group g = CreateGroup() 
    local real dist = GetHandleReal(Mtimer,"dist")+30
    local real angle = GetHandleReal(Mtimer,"angle")
    local real x = (GetUnitX(dum) + MissleMoveSpd() * Cos(angle * bj_DEGTORAD))
    local real y = (GetUnitY(dum) + MissleMoveSpd()  * Sin(angle * bj_DEGTORAD))
    local unit d
    
    call SetHandleReal(Mtimer,"dist",dist) 
    call SetUnitX(dum,x)
    call SetUnitY(dum,y)
    // does MPick_Conds function leak?
    call GroupEnumUnitsInRange(g,x,y,60.,Filter(function MPick_Conds))
    set d = FirstOfGroup(g)
    
    if  d == null then
    else
        call DestroyEffect(AddSpecialEffect(Missle_SFX(),x,y))
        call GroupEnumUnitsInRange(g,x,y,Missle_DmgArea(),Filter(function MPick_Conds))
        loop
            set d = FirstOfGroup(g)
            exitwhen d == null
            call GroupRemoveUnit(g,d)
            call UnitDamageTarget(c,d,Missle_dmg(GetUnitAbilityLevel(c,Missle_SpellId())),false,false,null,null,null)
            call RemoveUnit(dum)
            call FlushHandleLocals(Mtimer)
            call PauseTimer(Mtimer)
            call DestroyTimer(Mtimer)
        endloop
    endif
        
    if dist >= MissleMaxDist() then
        call KillUnit(dum)
        call FlushHandleLocals(Mtimer)
        call PauseTimer(Mtimer)
        call DestroyTimer(Mtimer)
    endif
    
    call DestroyGroup(g)
    set g = null    
    set c = null
    set dum = null
    set g = null
    set Mtimer = null
endfunction     

function Missle_Actions takes nothing returns nothing
    local timer Loop = GetExpiredTimer()
    local unit c = GetHandleUnit(Loop,"c")
    local real x = GetHandleReal(Loop,"x")
    local real y = GetHandleReal(Loop,"y")
    local real angle = GetHandleReal(Loop,"angle")
    local timer Mtimer = CreateTimer()
    local unit dum = CreateUnit(GetOwningPlayer(c),Missle_DummyId(),(x + 75 * Cos(angle * bj_DEGTORAD)),(y + 75  * Sin(angle * bj_DEGTORAD)),angle)
    
    call PauseUnit(dum,true)
    
    call SetHandleHandle(Mtimer,"c",c)
    call SetHandleHandle(Mtimer,"dum",dum)
    call SetHandleReal(Mtimer,"angle",angle)

    call TimerStart(Mtimer,.035,true,function Missle_Move)
    
    set c = null
    set dum = null
    set Loop = null
    set Mtimer = null
endfunction
    
function Missle_Act takes nothing returns nothing
    local trigger trig = CreateTrigger()
    local timer Loop = CreateTimer()
    local unit c = GetTriggerUnit()
    local real x = GetUnitX(c)
    local real y = GetUnitY(c)
    local location loc = GetSpellTargetLoc()
    local real tx = GetLocationX(loc)
    local real ty = GetLocationY(loc)
    local real angle = Atan2((ty-y),(tx-x))*57.29583

    call SetHandleHandle(Loop,"c",c)
    call SetHandleReal(Loop,"x",x)
    call SetHandleReal(Loop,"y",y)
    call SetHandleReal(Loop,"angle",angle)
    call SetHandleHandle(trig,"Loop",Loop)

    call TriggerRegisterUnitEvent(trig,c, EVENT_UNIT_SPELL_ENDCAST)
    call TriggerAddAction(trig, function Missle_End)

    call TimerStart(Loop,1.,true,function Missle_Actions)

    call RemoveLocation(loc)
    set loc = null
    set trig = null
    set Loop = null
    set c = null
endfunction  
    
function InitTrig_Missle takes nothing returns nothing
    local trigger t = CreateTrigger()
    local integer a = 0
    loop
        call TriggerRegisterPlayerUnitEvent(t,Player(a),EVENT_PLAYER_UNIT_SPELL_EFFECT,null)
        set a = a + 1
        exitwhen a == 16
    endloop
    
    call TriggerAddAction(t, function Missle_Act)
    call TriggerAddCondition(t, Filter(function Missle_Conds))
    call MisslePreLoad()
    set t = null
endfunction

well gonna sleep now i think it 04:30 here we talk more tomorrow and thx im learning a lot<3 ^^
 
Level 5
Joined
Oct 27, 2007
Messages
158
this is what i came up with, but there was somethings i didnt understand..

JASS:
function MisslePreLoad takes nothing returns nothing
    call Preload(Missle_SFX())
    // Define round reals by putting a point to mark it as a real.
    // You should avoid integers being converted to reals, by always entering round real numbers as 0., 1. , 2. , 3. etc.
    call RemoveUnit(CreateUnit(Player(15),Missle_DummyId(),0.,0.,0.))
endfunction
JASS:
// two reals again that need a .
    local unit dum = CreateUnit(GetOwningPlayer(c),Missle_DummyId(),(x + 75. * Cos(angle * bj_DEGTORAD)),(y + 75. * Sin(angle * bj_DEGTORAD)),angle)
and my code

JASS:
function Missle_Conds takes nothing returns boolean
    return GetSpellAbilityId() == Missle_SpellId()
endfunction

function MisslePreLoad takes nothing returns nothing
    call Preload(Missle_SFX())
    call RemoveUnit(CreateUnit(Player(15),Missle_DummyId(),0.,0.,0.))
endfunction

function MPick_Conds takes nothing returns boolean
// Better do this since you call GetFilterUnit() three times
    local unit u = GetFilterUnit()
    local boolean ok = GetWidgetLife(u) > .405 and not IsUnitType(u,UNIT_TYPE_STRUCTURE) and IsUnitEnemy(u,GetOwningPlayer(GetHandleUnit(GetExpiredTimer(),"c")))
    set u = null
    return ok
endfunction    

function Missle_End takes nothing returns nothing
    local trigger trig = GetTriggeringTrigger()
    local timer Loop = GetHandleTimer(trig,"Loop") 
    
    call PauseTimer(Loop)
    call FlushHandleLocals(Loop)
    call FlushHandleLocals(trig)    
    call DestroyTimer(Loop)
    call DestroyTrigger(trig) 
    
    set trig = null
    set Loop = null
endfunction

function Missle_Move takes nothing returns nothing
    local timer Mtimer = GetExpiredTimer()
    local unit c = GetHandleUnit(Mtimer,"c")
    local unit dum = GetHandleUnit(Mtimer,"dum")
    local group g = CreateGroup() 
    local real dist = GetHandleReal(Mtimer,"dist")+30.
    local real angle = GetHandleReal(Mtimer,"angle")
    local real x = (GetUnitX(dum) + MissleMoveSpd() * Cos(angle * bj_DEGTORAD))
    local real y = (GetUnitY(dum) + MissleMoveSpd()  * Sin(angle * bj_DEGTORAD))
    local unit d
    
    call SetHandleReal(Mtimer,"dist",dist) 
    call SetUnitX(dum,x)
    call SetUnitY(dum,y)
    // Why do you remove dummy unit in the group iteration loop?
    // There's a chance dummy won't be removed if group contains no units.
    //call RemoveUnit(dum) ????
    // does MPick_Conds function leak?
    // No, but you could optimize it.
    call GroupEnumUnitsInRange(g,x,y,60.,Filter(function MPick_Conds))
    // This would be better. Try to always put most likely executed code at the start of if statements.
    if  FirstOfGroup(g) != null then
        call DestroyEffect(AddSpecialEffect(Missle_SFX(),x,y))
        //I think enumerates doesn't clear the group of previous enumerations.
        //Not enterily sure, but easy to test in your code.
        call GroupClear(g)
        call GroupEnumUnitsInRange(g,x,y,Missle_DmgArea(),Filter(function MPick_Conds))
        loop
            set d = FirstOfGroup(g)
            exitwhen d == null
            call GroupRemoveUnit(g,d)
            call UnitDamageTarget(c,d,Missle_dmg(GetUnitAbilityLevel(c,Missle_SpellId())),false,false,null,null,null)
        endloop
        // Shouldn't the cleanup be here? If there are multiple units this will be run multiple times
        call FlushHandleLocals(Mtimer)
        call PauseTimer(Mtimer)
        call DestroyTimer(Mtimer)
    endif
        
// What if the dummy unit is removed and you try to kill it?
// Are you sure this isn't meant as an elseif condition if the previous condition is false?
    if dist >= MissleMaxDist() then
        call KillUnit(dum)
        call FlushHandleLocals(Mtimer)
        call PauseTimer(Mtimer)
        call DestroyTimer(Mtimer)
    endif
    
    call DestroyGroup(g)
    set g = null    
    set c = null
    set dum = null
    set Mtimer = null
endfunction     

function Missle_Actions takes nothing returns nothing
    local timer Loop = GetExpiredTimer()
    local unit c = GetHandleUnit(Loop,"c")
    local real x = GetHandleReal(Loop,"x")
    local real y = GetHandleReal(Loop,"y")
    local real angle = GetHandleReal(Loop,"angle")
    local timer Mtimer = CreateTimer()
    local unit dum = CreateUnit(GetOwningPlayer(c),Missle_DummyId(),(x + 75. * Cos(angle * bj_DEGTORAD)),(y + 75.  * Sin(angle * bj_DEGTORAD)),angle)
    
    call PauseUnit(dum,true)
    
    call SetHandleHandle(Mtimer,"c",c)
    call SetHandleHandle(Mtimer,"dum",dum)
    call SetHandleReal(Mtimer,"angle",angle)

    call TimerStart(Mtimer,.035,true,function Missle_Move)
    
    set c = null
    set dum = null
    set Loop = null
    set Mtimer = null
endfunction
    
function Missle_Act takes nothing returns nothing
    local trigger trig = CreateTrigger()
    local timer Loop = CreateTimer()
    local unit c = GetTriggerUnit()
    local real x = GetUnitX(c)
    local real y = GetUnitY(c)
    local location loc = GetSpellTargetLoc()
    local real tx = GetLocationX(loc)
    local real ty = GetLocationY(loc)
    local real angle = Atan2((ty-y),(tx-x))*57.29583

    call SetHandleHandle(Loop,"c",c)
    call SetHandleReal(Loop,"x",x)
    call SetHandleReal(Loop,"y",y)
    call SetHandleReal(Loop,"angle",angle)
    call SetHandleHandle(trig,"Loop",Loop)

    call TriggerRegisterUnitEvent(trig,c, EVENT_UNIT_SPELL_ENDCAST)
    call TriggerAddAction(trig, function Missle_End)

    call TimerStart(Loop,1.,true,function Missle_Actions)

    call RemoveLocation(loc)
    set loc = null
    set trig = null
    set Loop = null
    set c = null
endfunction  
    
function InitTrig_Missle takes nothing returns nothing
    local trigger t = CreateTrigger()
    local integer a = 0
    loop
        call TriggerRegisterPlayerUnitEvent(t,Player(a),EVENT_PLAYER_UNIT_SPELL_EFFECT,null)
        set a = a + 1
        exitwhen a == 16
    endloop
    
    call TriggerAddAction(t, function Missle_Act)
    call TriggerAddCondition(t, Filter(function Missle_Conds))
    call MisslePreLoad()
    set t = null
endfunction
well gonna sleep now i think it 04:30 here we talk more tomorrow and thx im learning a lot<3 ^^


Same here :wink:

I made some more comments in the quoted part.
 
Last edited:
Level 5
Joined
Oct 27, 2007
Messages
158
mine filter or drone's? and yes im using cracked wc3 but downloading iso file atm (2hours left :<)
hope that will make my JNGP working :D


The filter is fine! The only thing that could be done is optimize it a little. There's no need to call GetFilterUnit three times when you can set it to a local unit type handle. Set boolean value, null handle and return boolean.

Btw... what's up with the dum(my) unit? Why are you trying to remove it in the loop?
 
Status
Not open for further replies.
Top