• 🏆 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] Spell - Grease, stops when running "TimerStart", why?

Status
Not open for further replies.
As in the headline, why does the function stop running at "TimerStart"? The actions in the callback-function are not yet complete, and doesn't currently work, will this stop the function from continuing..?

The functions:
JASS:
function GreaseActionFunction takes nothing returns nothing
    call CreateNUnitsAtLoc(1, 'h001', GetOwningPlayer(GetTriggerUnit()), GetSpellTargetLoc(), bj_UNIT_FACING)
    call UnitApplyTimedLifeBJ(10.00, 'BTLF', GetLastCreatedUnit())
    call UnitAddAbilityBJ('Aslo', GetLastCreatedUnit())
    call IssueTargetOrderBJ(GetLastCreatedUnit(), "slow", GetEnumUnit())
endfunction

function GreaseTimerFunction takes nothing returns nothing
    call ForGroupBJ(GetUnitsInRectAll(RectFromCenterSizeBJ(GetSpellTargetLoc(), 300.00, 300.00)), function GreaseActionFunction)
endfunction

function GreaseFunction takes nothing returns nothing
    local unit c = GetTriggerUnit()
    local location t = GetSpellTargetLoc()
    local effect array effect1
    local timer timer1
    set bj_forLoopAIndex = 1
    set bj_forLoopAIndexEnd = 20
    loop
        exitwhen bj_forLoopAIndex > bj_forLoopAIndexEnd
        call AddSpecialEffectLocBJ(GetRandomLocInRect(RectFromCenterSizeBJ(t, 300.00, 300.00)), "Abilities\\Spells\\Undead\\PlagueCloud\\PlagueCloudCaster.mdl")
        set effect1[GetForLoopIndexA()] = GetLastCreatedEffectBJ()
        set bj_forLoopAIndex = bj_forLoopAIndex + 1
    endloop
    call TimerStart(timer1, 1.00, true, function GreaseTimerFunction)
    set timer1 = null
    call TriggerSleepAction((6.00 + (2.00 * I2R(GetUnitLevel(c)))))
    set bj_forLoopAIndex = 1
    set bj_forLoopAIndexEnd = 20
    loop
        exitwhen bj_forLoopAIndex > bj_forLoopAIndexEnd
        call DestroyEffectBJ(effect1[GetForLoopIndexA()])
        set bj_forLoopAIndex = bj_forLoopAIndex + 1
    endloop
    call DestroyTimer(timer1)
    call RemoveLocation(t)
endfunction
 
Level 19
Joined
Nov 16, 2006
Messages
2,165
Me too, but listen up you're using BJ's, those are not good and are also used by the GUI part.
You'll need to get rid of them, Get the Warcraft 3 NewGen, it will help you a lot.

And for the second part,
your timer.
JASS:
    call TimerStart(timer1, 1.00, true, function GreaseTimerFunction)
    set timer1 = null

You instantly nullify it, which means you're deleting all of the data it should use (if I'm correct).
 
Level 19
Joined
Nov 16, 2006
Messages
2,165
Let me give it a try, hold on some minuts :)
Edit I am sorry, I need to help on something else.
But this is an example you can use for your functions above:
JASS:
function GreaseActionFunction takes nothing returns nothing
    local unit dum = GetTriggerUnit()
    local unit dummy
    local unit enemy = GetSpellTargetUnit()
    local real x = GetUnitX(dum)
    local real y = GetUnitY(dum)
    local player owner = GetOwningPlayer(dum)
    set dummy = CreateUnit(owner,'h001',x,y,0.)
    call UnitApplyTimedLife(dummy,'BTLF',10.)
    call UnitAddAbility(dummy,'Aslo')
    call IssueTargetOrder(dummy,"slow",enemy)
    set dum = null
    set dummy = null
    set enemy = null
    set owner = null
endfunction
Your loops should be like this :
JASS:
loop
set i = i+1
    exitwhen  i > 10 // your number
    actions
endloop

try placing
JASS:
set timer1 = null
below your wait.

Your group and some few other BJ functions should be converted into non-bj.
 
Level 8
Joined
Aug 6, 2008
Messages
451
The reason why we null local handle variables, is that when some object is removed its hande id cant be recycled if there is some local pointing to it.

JASS:
set owner = null
This is not needed, because players are never removed.

Nulling a local timer variable has no effect to timers functionality ( you are only modifying a pointer, not the object itself ), so you can null it as soon as you have started your timer.

edit. But if you do this, you end up trying to destroy null.
JASS:
call DestroyTimer(timer1) // timer1 == null

Also, CreaseActionFunction is not gonna work, because you can only use functions like GetTriggerUnit() and GetSpellTargetLoc() in triggeractions and conditions.

You have not posted your whole trigger, but I can guess that your triggeraction is function GreaseFunction.

You have a line like this in your InitTrig:

JASS:
call TriggerAddAction(yourtrigger, function GreaseFunction)
?
 
Level 14
Joined
Nov 23, 2008
Messages
187
You instantly nullify it, which means you're deleting all of the data it should use (if I'm correct).
False.
JASS:
set timer1 = null
will only nullify the reference to the object.

The real problem is in that he hasn't even created that damn timer :)
JASS:
// . . .
function GreaseFunction takes nothing returns nothing
    local unit c = GetTriggerUnit()
    local location t = GetSpellTargetLoc()
    local effect array effect1
    // --->>
    local timer timer1 = CreateTimer()
    // <<---
    set bj_forLoopAIndex = 1
    set bj_forLoopAIndexEnd = 20
    loop
        exitwhen bj_forLoopAIndex > bj_forLoopAIndexEnd
        call AddSpecialEffectLocBJ(GetRandomLocInRect(RectFromCenterSizeBJ(t, 300.00, 300.00)), "Abilities\\Spells\\Undead\\PlagueCloud\\PlagueCloudCaster.mdl")
        set effect1[GetForLoopIndexA()] = GetLastCreatedEffectBJ()
        set bj_forLoopAIndex = bj_forLoopAIndex + 1
    endloop
    call TimerStart(timer1, 1.00, true, function GreaseTimerFunction)
    // >> no need to have that thing here
    //set timer1 = null
    call TriggerSleepAction((6.00 + (2.00 * I2R(GetUnitLevel(c)))))
    set bj_forLoopAIndex = 1
    set bj_forLoopAIndexEnd = 20
    loop
        exitwhen bj_forLoopAIndex > bj_forLoopAIndexEnd
        call DestroyEffectBJ(effect1[GetForLoopIndexA()])
        // cleaning up handle references
        set effect1[GetForLoopIndexA()] = null
        set bj_forLoopAIndex = bj_forLoopAIndex + 1
    endloop
    call DestroyTimer(timer1)
    call RemoveLocation(t)
    // cleaning up all handle references
    set timer1 = null
    set t = null
    set c = null
endfunction

By the way, there are a bunch of leaks.
 
Auch :p Didn't know you had to put "CreateTimer() there :S Thansk =) +rep

Well, it still doesn't work :S But now it's a different issue, since it now takes the functions after the timer ;)
It's like this:
JASS:
function GreaseActionFunction takes nothing returns nothing
    local unit d
    local group g = CreateGroup()
    call GroupAddGroup(GetUnitsInRectAll(RectFromCenterSizeBJ(GetSpellTargetLoc(), 300.00, 300.00)), g)
    call CreateNUnitsAtLoc(1, 'h001', GetOwningPlayer(GetTriggerUnit()), GetSpellTargetLoc(), bj_UNIT_FACING)
    set d = GetLastCreatedUnit()
    call UnitApplyTimedLifeBJ(10.00, 'BTLF', d)
    call UnitAddAbilityBJ('A017', d)
    set bj_forLoopAIndex = 1
    set bj_forLoopAIndexEnd = CountUnitsInGroup(g)
    loop
        exitwhen bj_forLoopAIndex > bj_forLoopAIndexEnd
        call IssueTargetOrderBJ(d, "slow", FirstOfGroup(g))
        call GroupRemoveUnit(g, FirstOfGroup(g))
        call DisplayTextToForce(GetPlayersAll(), "TRIGSTR_194")
        set bj_forLoopAIndex = bj_forLoopAIndex + 1
    endloop
endfunction

function GreaseFunction takes nothing returns nothing
    local unit c = GetTriggerUnit()
    local location t = GetSpellTargetLoc()
    local effect array effect1
    local timer timer1 = CreateTimer()
    local rect rect1 = RectFromCenterSizeBJ(t, 300.00, 300.00)
    set bj_forLoopAIndex = 1
    set bj_forLoopAIndexEnd = 20
    loop
        exitwhen bj_forLoopAIndex > bj_forLoopAIndexEnd
        call AddSpecialEffectLocBJ(GetRandomLocInRect(rect1), "Abilities\\Spells\\Undead\\PlagueCloud\\PlagueCloudCaster.mdl")
        set effect1[GetForLoopIndexA()] = GetLastCreatedEffectBJ()
        set bj_forLoopAIndex = bj_forLoopAIndex + 1
    endloop
    call TimerStart(timer1, 1.00, true, function GreaseActionFunction)
    set timer1 = null
    call TriggerSleepAction((6.00 + (2.00 * I2R(GetUnitLevel(c)))))
    set bj_forLoopAIndex = 1
    set bj_forLoopAIndexEnd = 20
    loop
        exitwhen bj_forLoopAIndex > bj_forLoopAIndexEnd
        call DestroyEffectBJ(effect1[GetForLoopIndexA()])
        set bj_forLoopAIndex = bj_forLoopAIndex + 1
    endloop
    call DestroyTimer(timer1)
    call RemoveLocation(t)
endfunction

and the init-trigger:
  • Grease Copy 2
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Grease
    • Actions
      • Custom script: call GreaseFunction()
Why doesn't this work..? It's pissing me off :S
It creates the special effects and destroys them, but it doesn't cast the spell on units :(
 
Last edited:
Level 8
Joined
Aug 6, 2008
Messages
451
Does GetSpellTargetLoc work in timer callbacks anyway?

Can I use it in a callback, if not, what else could I use..?

I already answered this:
Also, CreaseActionFunction is not gonna work, because you can only use functions like GetTriggerUnit() and GetSpellTargetLoc() in triggeractions and conditions.

You need to use globals. If you want it MUI, you should use global arrays ( or structs ).
 
Status
Not open for further replies.
Top