Library's function's loop fails to execute more than once?

Tinki3

Special Member
Reaction score
418
The function "Meat_Shield_Run" (right at the bottom), does not
seem to be working properly - its loop only loops once, when it should
clearly be looping more than once, if I may say.

The function is called once from another library.
Have I missed something here?

JASS:
library MeatShield uses QuickFunctions

globals
    private constant integer Toxic_Sheep_Projec_ID = 'o005'
    private constant integer Toxicness_Projec_ID = 'o006'
    private constant real Sheep_Speed = 15
    private constant real Toxicness_Speed = 25
    private constant real Max_Range = 600
    private constant real AoE = 90
    private constant string SFX = "Objects\\Spawnmodels\\NightElf\\EntBirthTarget\\EntBirthTarget.mdl"
    private constant string SFX2 = "Objects\\Spawnmodels\\Demon\\DemonLargeDeathExplode\\DemonLargeDeathExplode.mdl"
    private constant integer Toxic_No = 10
    private integer index
    private integer Chance_Sheep
    private real Dmg
endglobals

private struct Toxic_dat
    unit array Toxics[Toxic_No]
    real array cos[Toxic_No]
    real array sin[Toxic_No]
    trigger array trig[Toxic_No]
    triggeraction array ta[Toxic_No]
    real dist = 0
    integer i = 0
    
    method onDestroy takes nothing returns nothing
        set .i = 1
        loop
            exitwhen .i > Toxic_No
            call KillUnit(.Toxics[.i])
            call TriggerRemoveAction(.trig[.i], .ta[.i])
            call FlushHandleLocals(.trig[.i])
            call DestroyTrigger(.trig[.i])
            set .i = .i + 1
        endloop
    endmethod
endstruct

private struct Sheep_dat
    unit sheep
    unit toxic
    real dist = 0
    real cos
    real sin
    
    method onDestroy takes nothing returns nothing
        call DestroyEffect(AddSpecialEffect(SFX, GetUnitX(.sheep), GetUnitY(.sheep)))
        call DestroyEffect(AddSpecialEffect(SFX2, GetUnitX(.sheep), GetUnitY(.sheep)))
        call KillUnit(.sheep)
        call KillUnit(.toxic)
    endmethod
endstruct

private function Trigger_Callback takes nothing returns nothing
    local trigger t = GetTriggeringTrigger()
    local Toxic_dat D = Toxic_dat(GetHandleInt(t, "D"))
    local unit x = GetTriggerUnit()
    local integer i = 1
    
    loop
        exitwhen i > Toxic_No
        if AreTheyEnemies(x, D.Toxics<i>) then
            call UnitDamageTarget(D.Toxics<i>, x, Dmg, false, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_NORMAL, null)
        endif 
        set i = i + 1
    endloop
    
    set t = null
    set x = null
endfunction

private function Spit_Toxics takes nothing returns nothing
    local timer T = GetExpiredTimer()
    local Toxic_dat D = Toxic_dat(GetHandleInt(T, &quot;D&quot;))
    local integer i = 1
    local real X
    local real Y
    local real PX
    local real PY
    
    if D.dist &gt; 0 then
        set D.dist = D.dist - Toxicness_Speed
        loop
            exitwhen i &gt; Toxic_No
            set X = GetUnitX(D.Toxics<i>)
            set Y = GetUnitY(D.Toxics<i>)
            set PX = X + Toxicness_Speed * D.cos<i>
            set PY = Y + Toxicness_Speed * D.sin<i>
            call SetUnitPosition(D.Toxics<i>, PX, PY)
        endloop
    else
        call D.destroy()
        call FlushHandleLocals(T)
        call PauseTimer(T)
        call DestroyTimer(T)
    endif
    
    set T = null
endfunction

private function Throw_Toxic_Sheep_Periodic takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local Sheep_dat d = Sheep_dat(GetHandleInt(t, &quot;d&quot;))
    local real X = GetUnitX(d.sheep)
    local real Y = GetUnitY(d.sheep)
    local real PX = X + Sheep_Speed * d.cos
    local real PY = Y + Sheep_Speed * d.sin
    local integer i = 1
    local real ang = 0
    local Toxic_dat D
    local timer T
    
    if d.dist &gt; 0 then
        set d.dist = d.dist - Sheep_Speed
        call SetUnitPosition(d.sheep, PX, PY)
        call SetUnitPosition(d.toxic, PX, PY)
    else
        set D = Toxic_dat.create()
        set T = CreateTimer()
        set D.dist = 475
        loop
            exitwhen i &gt; Toxic_No
            set ang = (360/Toxic_No * i) * bj_DEGTORAD
            set D.cos<i> = Cos(ang)
            set D.sin<i> = Sin(ang)
            set D.Toxics<i> = CreateUnit(Player(11), Toxicness_Projec_ID, X + 150 * D.cos<i>, Y + 150 * D.sin<i>, ang * bj_RADTODEG)
            set D.trig<i> = CreateTrigger()
            call TriggerRegisterUnitInRange(D.trig<i>, D.Toxics<i>, AoE, null)
            set D.ta<i> = TriggerAddAction(D.trig<i>, function Trigger_Callback)
            set i = i + 1
        endloop
        set i = 1
        loop
            exitwhen i &gt; Toxic_No
            call SetHandleInt(D.trig<i>, &quot;D&quot;, D)
            set i = i + 1
        endloop
        call SetHandleInt(T, &quot;D&quot;, D)
        call TimerStart(T, 0.03, true, function Spit_Toxics)
        call d.destroy()
        call FlushHandleLocals(t)
        call PauseTimer(t)
        call DestroyTimer(t)
        set T = null
    endif
    
    set t = null
endfunction

private function Throw_Toxic_Sheep takes nothing returns nothing
     local Sheep_dat d = Sheep_dat.create()     
     local real X = GetUnitX(b)
     local real Y = GetUnitY(b)
     local real r = GetRandomReal(235, 335) * bj_DEGTORAD
     local timer t = CreateTimer()
     
     call IssueImmediateOrder(b, &quot;stop&quot;)
     call SetUnitAnimation(b, &quot;attack&quot;)
     call SetUnitFacing(b, r * bj_RADTODEG)
     
     set d.sheep = CreateUnit(Player(11), Toxic_Sheep_Projec_ID, X, Y, r * bj_RADTODEG)
     set d.toxic = CreateUnit(Player(11), Toxicness_Projec_ID, X, Y, r * bj_RADTODEG)
     set d.cos = Cos(r)
     set d.sin = Sin(r)
     set d.dist = Max_Range
     
     call SetHandleInt(t, &quot;d&quot;, d)
     call TimerStart(t, 0.03, true, function Throw_Toxic_Sheep_Periodic)     
     call TriggerSleepAction(1.3)
     
     if RectContainsCoords(gg_rct_Boss_Check_1, X, Y) then
         call IssuePointOrder(b, &quot;move&quot;, GetRectCenterX(gg_rct_Run_Point_1), GetRectCenterY(gg_rct_Run_Point_1)) 
     elseif RectContainsCoords(gg_rct_Boss_Check_2, X, Y) then
         call IssuePointOrder(b, &quot;move&quot;, GetRectCenterX(gg_rct_End_of_Path), GetRectCenterY(gg_rct_End_of_Path)) 
     endif
     
     set t = null
endfunction

function Meat_Shield_Run takes nothing returns nothing    
    set Finished_Boss_Level = false
    set index = 0   
    set Chance_Sheep = udg_Difficulty_Level * 13
    set Dmg = (udg_Difficulty_Level * 30) / Toxic_No
    
    loop
        exitwhen index &gt; 1000  
        if GetWidgetLife(b) &lt; 0.405 or b == null then
            set Finished_Boss_Level = true
            set index = 1001
        endif
        if GetRandomInt(1, 100) &lt;= Chance_Sheep and GetWidgetLife(b) &gt; 0.405 then
            call Throw_Toxic_Sheep()
        endif
        call TriggerSleepAction(1.5)
        set index = index + 1
    endloop
endfunction
    
endlibrary</i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i>


Here is the other library trigger:

The line that calls the Meat_Shield_Run function is inside the function Drop_Hostiles, in one of the "If" blocks.
JASS:
library MainSpawn uses MeatShield

globals
    private constant real Interval = 10
    private constant integer Boss_Spawn_Amount = 1
    private constant real Fly_Decrease = 21
    private constant real Timer_Interval = 0.03
    private constant real Wave_Interval = 33
    private constant real Level_Interval = 45
    private constant integer Wave_Amount = 3
    private constant string SFX = &quot;Abilities\\Spells\\Orc\\WarStomp\\WarStompCaster.mdl&quot;
    private constant string SFX2 = &quot;Objects\\Spawnmodels\\Undead\\ImpaleTargetDust\\ImpaleTargetDust.mdl&quot;
    unit b
    private unit array u 
    private boolean done = false
    private boolean Boss_Lvl = false
    private boolean Run_Trigger = true
    private timer t = CreateTimer()
    boolean Finished_Boss_Level = false
endglobals

private function Drop_Hostiles takes nothing returns nothing
    local integer index = 1
    local real fh 
    local location l
 
    if done == false then
        if Boss_Lvl == false then
            loop
                exitwhen index &gt; udg_Spawn_Amount
                set fh = GetUnitFlyHeight(u[index])
                if fh &gt; Fly_Decrease then
                    call SetUnitFlyHeight(u[index], fh - Fly_Decrease, 99999)
                else
                    if GetUnitUserData(u[index]) != 1 then
                        call SetUnitUserData(u[index], 1)
                        set l = Location(GetRandomReal(GetRectMinX(gg_rct_Run_Point_1), GetRectMaxX(gg_rct_Run_Point_1)), GetRandomReal(GetRectMinY(gg_rct_Run_Point_1), GetRectMaxY(gg_rct_Run_Point_1)))
                        call PauseUnit(u[index], false)
                        call SetUnitInvulnerable(u[index], false)
                        call IssuePointOrderLoc(u[index], &quot;move&quot;, l)
                        call SetUnitFlyHeight(u[index], 0, 99999)
                        call DestroyEffect(AddSpecialEffect(SFX, GetUnitX(u[index]), GetUnitY(u[index])))
                        call DestroyEffect(AddSpecialEffect(SFX2, GetUnitX(u[index]), GetUnitY(u[index])))
                        call RemoveLocation(l)
                    endif
                endif
                set index = index + 1
            endloop
        else
            set fh = GetUnitFlyHeight(b)
            if fh &gt;= Fly_Decrease then
                call SetUnitFlyHeight(b, fh - Fly_Decrease, 99999)
            else
                call PauseTimer(t)
                call PauseUnit(b, false)
                call SetUnitInvulnerable(b, false)
                call DestroyEffect(AddSpecialEffect(SFX, GetUnitX(b), GetUnitY(b)))
                call DestroyEffect(AddSpecialEffect(SFX2, GetUnitX(b), GetUnitY(b)))
                call SetUnitFlyHeight(b, 0, 99999)
                call IssuePointOrder(b, &quot;move&quot;, GetRectCenterX(gg_rct_Run_Point_1), GetRectCenterY(gg_rct_Run_Point_1)) 
                if udg_Current_Level == 4 then
                    call Meat_Shield_Run()
                elseif udg_Current_Level == 8 then
                elseif udg_Current_Level == 12 then
                elseif udg_Current_Level == 16 then
                elseif udg_Current_Level == 20 then
                endif
                set udg_Current_Level = udg_Current_Level + 1
                loop
                    exitwhen Finished_Boss_Level == true
                    call TriggerSleepAction(1)
                endloop
                set Boss_Lvl = false
                set Finished_Boss_Level = false
                call DisplayTimedTextToForce(bj_FORCE_ALL_PLAYERS, 15, &quot;Level &quot; + &quot;|cff32cd32&quot; + I2S(R2I(udg_Current_Level))+ &quot;|r&quot; + &quot; starting in approximately &quot; + I2S(R2I(Level_Interval)) + &quot; seconds.&quot;)   
                call TriggerSleepAction(Level_Interval)
                set Run_Trigger = true
            endif
        endif
    else
        set done = false
        call TriggerSleepAction(udg_Creation_Interval / 2)
        call PauseTimer(t)
    endif
    
    set l = null
endfunction

private function Start_Spawn takes nothing returns nothing
    local integer index = 1
    local integer index2 = 1
    local location l 
    
    if Run_Trigger == true then
        set Run_Trigger = false
        call DisplayTimedTextToForce( bj_FORCE_ALL_PLAYERS, 15, &quot;|cff32cd32Level &quot; + I2S(R2I(udg_Current_Level))+ &quot;|r&quot; + &quot;: &quot; + udg_Level_String[udg_Current_Level])  
        if udg_Current_Level != 4 and udg_Current_Level != 8 and udg_Current_Level != 12 and udg_Current_Level != 16 and udg_Current_Level != 20 then
            loop
                exitwhen index2 &gt; Wave_Amount
                loop
                    exitwhen index &gt; udg_Spawn_Amount
                    set l = Location(GetRandomReal(GetRectMinX(gg_rct_Spawn), GetRectMaxX(gg_rct_Spawn)), GetRandomReal(GetRectMinY(gg_rct_Spawn), GetRectMaxY(gg_rct_Spawn)))
                    set u[index] = CreateUnitAtLoc(Player(11), udg_Hostiles[udg_Current_Level], l, 270)
                    call PauseUnit(u[index], true)
                    call SetUnitInvulnerable(u[index], true)
                    call TimerStart(t, Timer_Interval, true, function Drop_Hostiles)
                    set index = index + 1
                    if index &gt; udg_Spawn_Amount then
                        set done = true
                    endif
                    call RemoveLocation(l)
                    call TriggerSleepAction(udg_Creation_Interval)
               endloop 
               set index = 1
               call TriggerSleepAction(Wave_Interval)
               set index2 = index2 + 1
            endloop
        else
            set Boss_Lvl = true
            set l = Location(GetRandomReal(GetRectMinX(gg_rct_Spawn), GetRectMaxX(gg_rct_Spawn)), GetRandomReal(GetRectMinY(gg_rct_Spawn), GetRectMaxY(gg_rct_Spawn)))
            set b = CreateUnitAtLoc(Player(11), udg_Hostiles[udg_Current_Level], l, 270)
            call PauseUnit(b, true)
            call SetUnitInvulnerable(b, true)
            call TimerStart(t, Timer_Interval, true, function Drop_Hostiles)
            call RemoveLocation(l)
        endif
    endif
 
    if index2 &gt; Wave_Amount then
        set index2 = 1
        set udg_Current_Level = udg_Current_Level + 1
        call DisplayTimedTextToForce( bj_FORCE_ALL_PLAYERS, 15, &quot;Level &quot; + &quot;|cff32cd32&quot; + I2S(R2I(udg_Current_Level))+ &quot;|r&quot; + &quot; starting in approximately &quot; + I2S(R2I(Level_Interval)) + &quot; seconds.&quot;)   
        call TriggerSleepAction(Level_Interval)
        set Run_Trigger = true  
    endif
 
    set l = null
endfunction

function InitTrig_Main_Spawn takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterTimerEvent(t, Interval, true)
    call TriggerAddAction(t, function Start_Spawn)
    set t = null
endfunction

endscope
 

Cohadar

master of fugue
Reaction score
209
what is b?
where did you set b?
why are you using handle wars?

EDIT: jeez it is Tom. o_O
Back from the dead :)
 

Vexorian

Why no custom sig?
Reaction score
187
You are calling Meat_Shield_Run from "a scope" that isn't too descriptive. Something is telling me you are calling it from a place that cannot have waits.

b is a horribly short name for something that isn't a local.
 

Tinki3

Special Member
Reaction score
418
> My only guess here is that b isn't set

My apologies for not explaining what "b" is.
"b" is a global, non-private unit that is set in the scope in the other trigger.
I am only using 1 unit for "b", at a time, so that's why it is set into a global ("b" is a boss unit).

I have added the scope trigger (that is still under-construction), to my 1st post.

> why are you using handle wars?

Always have, probably always will.
Though, I am very curious to know if there is another, similar system which
I can use that will speed up my code?

@ Vexorian, again, my apologies for not posting the code for the scope trigger.

> b is a horribly short name for something that isn't a local

May I ask what you are implying here?

I was wondering, would it be necessary to convert the scope trigger to a library?
 

Silvenon

New Member
Reaction score
19
Always have, probably always will.
Though, I am very curious to know if there is another, similar system which
I can use that will speed up my code?

Cohadar's ABC.

May I ask what you are implying here?

Vex's right, it's bad to name a global that way, you can name it capital B (that's what I always do), or Boss or whatever you want. Just not b, otherwise it can very, very easily interfere with some of your systems, triggers etc.

Again, a useless post (I usually make them, get used to it :))
 

Magentix

if (OP.statement == false) postCount++;
Reaction score
107
JASS:
function Meat_Shield_Run takes nothing returns nothing    
    set Finished_Boss_Level = false
    set index = 0   
    set Chance_Sheep = udg_Difficulty_Level * 13
    set Dmg = (udg_Difficulty_Level * 30) / Toxic_No
    
    loop
        exitwhen index &gt; 1000  
        if GetWidgetLife(b) &lt; 0.405 or b == null then
            call BJDebugMsg(&quot;loop forced to end by setting index to 1001&quot;)
            set Finished_Boss_Level = true
            set index = 1001
        endif
        if GetRandomInt(1, 100) &lt;= Chance_Sheep and GetWidgetLife(b) &gt; 0.405 then
            call Throw_Toxic_Sheep()
        endif
        call TriggerSleepAction(1.5)
        set index = index + 1
    endloop
endfunction


Try this one to check if somehow your if-statement doesn't clear out as true?
If you see the message, your loop is correct, but your condition isn't.


JASS:
or b == null then


What if b isn't recognized due to the combination of scope vs library?
I suggest declaring b outside the scope, in its own globals block
 

Tinki3

Special Member
Reaction score
418
> Cohadar's ABC

Anything else?
I'm not really a fan of ABC due to its current attachment limitations.
Though, I might resort to it since units, triggers and timers would be the only things I need to attach to.
PUI works with ABC to attach to units doesn't it?

> Try this one to check if somehow your if-statement doesn't clear out as true?

Ok, I'll try that, even though I've done something similar before, I think.

> What if b isn't recognized due to the combination of scope vs library?
> I suggest declaring b outside the scope, in its own globals block

Or, would changing the scope to a library help any?

Thanks for your input guys.
 

Trollvottel

never aging title
Reaction score
262
>Anything else?

yeah timer tickers from cohadar ^^
its very easy and short i like it

/edit:
and i think theres hsas but i never used it
 

Tinki3

Special Member
Reaction score
418
Ok, so.

The loop only executing once thing seemed to be a library-related issue.
That's fixed - I've moved the loop out of the library it was in, and put it in a seperate trigger, that doesn't use a library or anything.

The loop is at least "looping" more than once, now, hooray.
But, I get this error when the Throw_Toxic_Sheep_Periodic function is ran:
erroryc8.jpg


Here is my triggers currently:
Main spawn trigger. This is where the "AAA_Actions_AAA" function is executed from.
JASS:
library MainSpawn

globals
    private constant real Interval = 10
    private constant integer Boss_Spawn_Amount = 1
    private constant real Fly_Decrease = 21
    private constant real Timer_Interval = 0.03
    private constant real Wave_Interval = 33
    private constant real Level_Interval = 35
    private constant integer Wave_Amount = 3
    private constant string SFX = &quot;Abilities\\Spells\\Orc\\WarStomp\\WarStompCaster.mdl&quot;
    private constant string SFX2 = &quot;Objects\\Spawnmodels\\Undead\\ImpaleTargetDust\\ImpaleTargetDust.mdl&quot;
    private unit array u 
    private boolean done = false
    private boolean Boss_Lvl = false
    private boolean Run_Trigger = true
    private timer t = CreateTimer()
    boolean Finished_Boss_Level = false
    unit Boss
endglobals

private function Drop_Hostiles takes nothing returns nothing
    local integer index = 1
    local real fh 
    local location l
 
    if done == false then
        if Boss_Lvl == false then
            loop
                exitwhen index &gt; udg_Spawn_Amount
                set fh = GetUnitFlyHeight(u[index])
                if fh &gt; Fly_Decrease then
                    call SetUnitFlyHeight(u[index], fh - Fly_Decrease, 99999)
                else
                    if GetUnitUserData(u[index]) != 1 then
                        call SetUnitUserData(u[index], 1)
                        set l = Location(GetRandomReal(GetRectMinX(gg_rct_Run_Point_1), GetRectMaxX(gg_rct_Run_Point_1)), GetRandomReal(GetRectMinY(gg_rct_Run_Point_1), GetRectMaxY(gg_rct_Run_Point_1)))
                        call PauseUnit(u[index], false)
                        call SetUnitInvulnerable(u[index], false)
                        call IssuePointOrderLoc(u[index], &quot;move&quot;, l)
                        call SetUnitFlyHeight(u[index], 0, 99999)
                        call DestroyEffect(AddSpecialEffect(SFX, GetUnitX(u[index]), GetUnitY(u[index])))
                        call DestroyEffect(AddSpecialEffect(SFX2, GetUnitX(u[index]), GetUnitY(u[index])))
                        call RemoveLocation(l)
                    endif
                endif
                set index = index + 1
            endloop
        else
            set fh = GetUnitFlyHeight(Boss)
            if fh &gt;= Fly_Decrease then
                call SetUnitFlyHeight(Boss, fh - Fly_Decrease, 99999)
            else
                call PauseTimer(t)
                call PauseUnit(Boss, false)
                call SetUnitInvulnerable(Boss, false)
                call DestroyEffect(AddSpecialEffect(SFX, GetUnitX(Boss), GetUnitY(Boss)))
                call DestroyEffect(AddSpecialEffect(SFX2, GetUnitX(Boss), GetUnitY(Boss)))
                call SetUnitFlyHeight(Boss, 0, 99999)
                call IssuePointOrder(Boss, &quot;move&quot;, GetRectCenterX(gg_rct_Run_Point_1), GetRectCenterY(gg_rct_Run_Point_1)) 
                call ExecuteFunc(&quot;AAA_Actions_AAA&quot;)
                loop
                    exitwhen Finished_Boss_Level == true
                    call TriggerSleepAction(1)
                endloop
                set udg_Current_Level = udg_Current_Level + 1
                set Boss_Lvl = false
                set Finished_Boss_Level = false
                call DisplayTimedTextToForce(bj_FORCE_ALL_PLAYERS, 15, &quot;Level &quot; + &quot;|cff32cd32&quot; + I2S(R2I(udg_Current_Level))+ &quot;|r&quot; + &quot; starting in approximately &quot; + I2S(R2I(Level_Interval)) + &quot; seconds.&quot;)   
                call TriggerSleepAction(Level_Interval)
                set Run_Trigger = true
            endif
        endif
    else
        set done = false
        call TriggerSleepAction(udg_Creation_Interval / 2)
        call PauseTimer(t)
    endif
    
    set l = null
endfunction

private function Start_Spawn takes nothing returns nothing
    local integer index = 1
    local integer index2 = 1
    local location l 
    
    if Run_Trigger == true then
        set Run_Trigger = false
        call DisplayTimedTextToForce( bj_FORCE_ALL_PLAYERS, 15, &quot;|cff32cd32Level &quot; + I2S(R2I(udg_Current_Level))+ &quot;|r&quot; + &quot;: &quot; + udg_Level_String[udg_Current_Level])  
        if udg_Current_Level != 4 and udg_Current_Level != 8 and udg_Current_Level != 12 and udg_Current_Level != 16 and udg_Current_Level != 20 then
            loop
                exitwhen index2 &gt; Wave_Amount
                loop
                    exitwhen index &gt; udg_Spawn_Amount
                    set l = Location(GetRandomReal(GetRectMinX(gg_rct_Spawn), GetRectMaxX(gg_rct_Spawn)), GetRandomReal(GetRectMinY(gg_rct_Spawn), GetRectMaxY(gg_rct_Spawn)))
                    set u[index] = CreateUnitAtLoc(Player(11), udg_Hostiles[udg_Current_Level], l, 270)
                    call PauseUnit(u[index], true)
                    call SetUnitInvulnerable(u[index], true)
                    call TimerStart(t, Timer_Interval, true, function Drop_Hostiles)
                    set index = index + 1
                    if index &gt; udg_Spawn_Amount then
                        set done = true
                    endif
                    call RemoveLocation(l)
                    call TriggerSleepAction(udg_Creation_Interval)
               endloop 
               set index = 1
               call TriggerSleepAction(Wave_Interval)
               set index2 = index2 + 1
            endloop
        else
            set Boss_Lvl = true
            set l = Location(GetRandomReal(GetRectMinX(gg_rct_Spawn), GetRectMaxX(gg_rct_Spawn)), GetRandomReal(GetRectMinY(gg_rct_Spawn), GetRectMaxY(gg_rct_Spawn)))
            set Boss = CreateUnitAtLoc(Player(11), udg_Hostiles[udg_Current_Level], l, 270)
            call PauseUnit(Boss, true)
            call SetUnitInvulnerable(Boss, true)
            call TimerStart(t, Timer_Interval, true, function Drop_Hostiles)
            call RemoveLocation(l)
        endif
    endif
 
    if index2 &gt; Wave_Amount then
        set index2 = 1
        set udg_Current_Level = udg_Current_Level + 1
        call DisplayTimedTextToForce( bj_FORCE_ALL_PLAYERS, 15, &quot;Level &quot; + &quot;|cff32cd32&quot; + I2S(R2I(udg_Current_Level))+ &quot;|r&quot; + &quot; starting in approximately &quot; + I2S(R2I(Level_Interval)) + &quot; seconds.&quot;)   
        call TriggerSleepAction(Level_Interval)
        set Run_Trigger = true  
    endif
 
    set l = null
endfunction

function InitTrig_Main_Spawn takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterTimerEvent(t, Interval, true)
    call TriggerAddAction(t, function Start_Spawn)
    set t = null
endfunction

endlibrary

The library/system for the 1st boss.
This is where the error is.
JASS:
library MeatShield uses QuickFunctions

globals
    private constant integer Toxic_Sheep_Projec_ID = &#039;o005&#039;
    private constant integer Toxicness_Projec_ID = &#039;o006&#039;
    private constant real Sheep_Speed = 15
    private constant real Toxicness_Speed = 25
    private constant real Max_Range = 600
    private constant real AoE = 90
    private constant string SFX = &quot;Objects\\Spawnmodels\\NightElf\\EntBirthTarget\\EntBirthTarget.mdl&quot;
    private constant string SFX2 = &quot;Objects\\Spawnmodels\\Demon\\DemonLargeDeathExplode\\DemonLargeDeathExplode.mdl&quot;
    private constant integer Toxic_No = 10
    private real Dmg
endglobals

private struct Toxic_dat
    unit array Toxics[Toxic_No]
    real array cos[Toxic_No]
    real array sin[Toxic_No]
    trigger array trig[Toxic_No]
    triggeraction array ta[Toxic_No]
    real dist = 0
    integer i = 0
    
    method onDestroy takes nothing returns nothing
        set .i = 1
        loop
            exitwhen .i &gt; Toxic_No
            call KillUnit(.Toxics[.i])
            call TriggerRemoveAction(.trig[.i], .ta[.i])
            call FlushHandleLocals(.trig[.i])
            call DestroyTrigger(.trig[.i])
            set .i = .i + 1
        endloop
    endmethod
endstruct

private struct Sheep_dat
    unit sheep
    unit toxic
    real dist = 0
    real cos
    real sin
    
    method onDestroy takes nothing returns nothing
        call DestroyEffect(AddSpecialEffect(SFX, GetUnitX(.sheep), GetUnitY(.sheep)))
        call DestroyEffect(AddSpecialEffect(SFX2, GetUnitX(.sheep), GetUnitY(.sheep)))
        call KillUnit(.sheep)
        call KillUnit(.toxic)
    endmethod
endstruct

private function Trigger_Callback takes nothing returns nothing
    local trigger t = GetTriggeringTrigger()
    local Toxic_dat D = Toxic_dat(GetHandleInt(t, &quot;D&quot;))
    local unit x = GetTriggerUnit()
    local integer i = 1
    
    loop
        exitwhen i &gt; Toxic_No
        if AreTheyEnemies(x, D.Toxics<i>) then
            call UnitDamageTarget(D.Toxics<i>, x, Dmg, false, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_NORMAL, null)
        endif 
        set i = i + 1
    endloop
    
    set t = null
    set x = null
endfunction

private function Spit_Toxics takes nothing returns nothing
    local timer T = GetExpiredTimer()
    local Toxic_dat D = Toxic_dat(GetHandleInt(T, &quot;D&quot;))
    local integer i = 1
    local real X
    local real Y
    local real PX
    local real PY
    
    if D.dist &gt; 0 then
        set D.dist = D.dist - Toxicness_Speed
        loop
            exitwhen i &gt; Toxic_No
            set X = GetUnitX(D.Toxics<i>)
            set Y = GetUnitY(D.Toxics<i>)
            set PX = X + Toxicness_Speed * D.cos<i>
            set PY = Y + Toxicness_Speed * D.sin<i>
            call SetUnitPosition(D.Toxics<i>, PX, PY)
        endloop
    else
        call D.destroy()
        call FlushHandleLocals(T)
        call PauseTimer(T)
        call DestroyTimer(T)
    endif
    
    set T = null
endfunction

private function Throw_Toxic_Sheep_Periodic takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local Sheep_dat d = Sheep_dat(GetHandleInt(t, &quot;d&quot;))
    local real X = GetUnitX(d.sheep)
    local real Y = GetUnitY(d.sheep)
    local real PX = X + Sheep_Speed * d.cos
    local real PY = Y + Sheep_Speed * d.sin
    local integer I = 1
    local real ang = 0
    local Toxic_dat D
    local timer T
    
    if d.dist &gt; 0 then
        set d.dist = d.dist - Sheep_Speed
        call SetUnitPosition(d.sheep, PX, PY)
        call SetUnitPosition(d.toxic, PX, PY)
    else
        set D = Toxic_dat.create()
        set T = CreateTimer()
        set D.dist = 475
        loop
            exitwhen I &gt; Toxic_No
            set ang = (360/Toxic_No * I) * bj_DEGTORAD
            set D.cos<i> = Cos(ang)
            set D.sin<i> = Sin(ang)
            set D.Toxics<i> = CreateUnit(Player(11), Toxicness_Projec_ID, X + 150 * D.cos<i>, Y + 150 * D.sin<i>, ang * bj_RADTODEG)
            set D.trig<i> = CreateTrigger()
            call TriggerRegisterUnitInRange(D.trig<i>, D.Toxics<i>, AoE, null)
            set D.ta<i> = TriggerAddAction(D.trig<i>, function Trigger_Callback)
            set I = I + 1
        endloop
        set I = 1
        loop
            exitwhen I &gt; Toxic_No
            call SetHandleInt(D.trig<i>, &quot;D&quot;, D)
            set I = I + 1
        endloop
        call SetHandleInt(T, &quot;D&quot;, D)
        call TimerStart(T, 0.03, true, function Spit_Toxics)
        call d.destroy()
        call FlushHandleLocals(t)
        call PauseTimer(t)
        call DestroyTimer(t)
        set T = null
    endif
    
    set t = null
endfunction

function Throw_Toxic_Sheep takes nothing returns nothing
     local Sheep_dat d = Sheep_dat.create()     
     local real X = GetUnitX(Boss)
     local real Y = GetUnitY(Boss)
     local real r = GetRandomReal(235, 335) * bj_DEGTORAD
     local timer t = CreateTimer()
     
     set Dmg = (udg_Difficulty_Level * 30) / Toxic_No
     
     call IssueImmediateOrder(Boss, &quot;stop&quot;)
     call SetUnitAnimation(Boss, &quot;attack&quot;)
     call SetUnitFacing(Boss, r * bj_RADTODEG)
     
     set d.sheep = CreateUnit(Player(11), Toxic_Sheep_Projec_ID, X, Y, r * bj_RADTODEG)
     set d.toxic = CreateUnit(Player(11), Toxicness_Projec_ID, X, Y, r * bj_RADTODEG)
     set d.cos = Cos(r)
     set d.sin = Sin(r)
     set d.dist = Max_Range
     
     call SetHandleInt(t, &quot;d&quot;, d)
     call TimerStart(t, 0.03, true, function Throw_Toxic_Sheep_Periodic)     
     call TriggerSleepAction(1.3)
     
     if RectContainsCoords(gg_rct_Boss_Check_1, X, Y) then
         call IssuePointOrder(Boss, &quot;move&quot;, GetRectCenterX(gg_rct_Run_Point_1), GetRectCenterY(gg_rct_Run_Point_1)) 
     elseif RectContainsCoords(gg_rct_Boss_Check_2, X, Y) then
         call IssuePointOrder(Boss, &quot;move&quot;, GetRectCenterX(gg_rct_End_of_Path), GetRectCenterY(gg_rct_End_of_Path)) 
     endif
     
     set t = null
endfunction
    
endlibrary</i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i>


Starts the MeatShield library.
JASS:
function AAA_Actions_AAA takes nothing returns nothing
    local integer i = 1
    local integer chance
    
    if udg_Current_Level == 4 then
        set chance = udg_Difficulty_Level * 13
        loop
            exitwhen i &gt; 1000  
            if GetWidgetLife(Boss) &lt; 0.405 or Boss == null then
                set Finished_Boss_Level = true
                set i = 1001
            endif
            if GetRandomInt(1, 100) &lt;= chance and GetWidgetLife(Boss) &gt; 0.405 then
                call Throw_Toxic_Sheep()
            endif
            call TriggerSleepAction(1.5)
            set i = i + 1
        endloop
    elseif udg_Current_Level == 8 then
    elseif udg_Current_Level == 12 then
    elseif udg_Current_Level == 16 then
    elseif udg_Current_Level == 20 then
    endif
endfunction

function InitTrig_Start_Boss_Functions takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerAddAction(t, function AAA_Actions_AAA)
    set t = null
endfunction

This trigger, also, might have something to do with the error:
JASS:
library StandardArrowProjectile uses QuickFunctions

private struct dat
    unit a
    real cos
    real sin
    real dmg
    real dist = 0
    real maxrange
    real speed
    real AoE
    string SFX
    trigger T
    triggeraction ta
    boolean hit = false
    
    method onDestroy takes nothing returns nothing
        call DestroyEffect(AddSpecialEffect(.SFX, GetUnitX(.a), GetUnitY(.a)))
        call FlushHandleLocals(.T)
        call TriggerRemoveAction(.T, .ta)
        call DestroyTrigger(.T)
        call KillUnit(.a)
    endmethod
endstruct

private function Damage_Enemy takes nothing returns nothing
    local trigger t = GetTriggeringTrigger()
    local dat d = dat(GetHandleInt(t, &quot;d&quot;))
    local unit x = GetTriggerUnit()
    
    if AreTheyEnemies(x, d.a) and d.hit == false then
        call UnitDamageTarget(d.a, x, d.dmg, false, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_NORMAL, null)
        set d.dist = d.maxrange + 1
        set d.hit = true
    endif
    
    set t = null
    set x = null
endfunction

private function Move_Arrow takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local dat d = dat(GetHandleInt(t, &quot;d&quot;))
    local real AX
    local real AY
    local real PX
    local real PY

    if d.dist &lt; d.maxrange then
        set AX = GetUnitX(d.a)
        set AY = GetUnitY(d.a)
        set PX = AX + d.speed * d.cos
        set PY = AY + d.speed * d.sin
        call SetUnitPosition(d.a, PX, PY)
        set d.dist = d.dist + d.speed
    else
        call d.destroy()
        call FlushHandleLocals(t)
        call PauseTimer(t)
        call DestroyTimer(t)
    endif
    
    set t = null
endfunction

function Cast_Standard_Arrow takes integer Spell_ID, integer Projec_ID, unit u, location l, real Multiplier, real AoE, real speed, real maxrange, string SFX returns nothing
    local real UX = GetUnitX(u)
    local real UY = GetUnitY(u)
    local real LX = GetLocationX(l)
    local real LY = GetLocationY(l)
    local dat d = dat.create()
    local timer t = CreateTimer()
    local real ang = 0
    
    set ang = Atan2(LY-UY, LX-UX)
    set d.cos = Cos(ang)
    set d.sin = Sin(ang)
    set d.a = CreateUnit(GetOwningPlayer(u), Projec_ID, UX, UY, ang * bj_RADTODEG)
    set d.dmg = GetHeroStr(u, true) * Multiplier
    set d.maxrange = maxrange
    set d.speed = speed
    set d.AoE = AoE
    set d.SFX = SFX
    set d.T = CreateTrigger()
    call TriggerRegisterUnitInRange(d.T, d.a, AoE, null)
    set d.ta = TriggerAddAction(d.T, function Damage_Enemy)
    
    call SetHandleInt(t, &quot;d&quot;, d)
    call SetHandleInt(d.T, &quot;d&quot;, d)
    call TimerStart(t, 0.03, true, function Move_Arrow)
    
    set t = null
endfunction

endlibrary
The reason why I'm posting all these triggers, is because I'm not sure as to what's causing the problem.
 

Cohadar

master of fugue
Reaction score
209
> b is a horribly short name for something that isn't a local

May I ask what you are implying here?

There is a programming rule that says:
Names shorter than 4 characters are to be used only for array indexes.

If you have named your variable FINAL_BOSS or something noone would have to guess wtf is b?

=========================================================
JASS:
call SetHandleInt(t, &quot;d&quot;, d) ~ call SetTimerStructA(t, d)
local Sheep_dat d = Sheep_dat(GetHandleInt(t, &quot;d&quot;)) ~ local Sheep_dat d = GetTimerStructA(t)
call FlushHandleLocals(t) ~ ClearTimerStructA(t)

call SetHandleInt(D.trig<i>, &quot;D&quot;, D)  ~ call SetTriggerStructA(D.trig<i>, D)
// and so on....
</i></i>


Limitations or not, when your ass is in deep shit, there is nothing like ABC error messages to pull you out.
 

Cohadar

master of fugue
Reaction score
209
Well if ABC did not give you any errors that means that your attachments are fine.

So something else is wrong,
and by looking at that error message I can only guess that onDestroy method is not initialized!!??

Seems like an error in jasshelper. :eek:
What version are you using?

Can you extract all those trouble triggers in a demo map and attach it.
I would like to debug this myself.
 

Cohadar

master of fugue
Reaction score
209
> What version are you using?

0.9.9.3, still.

> Can you extract all those trouble triggers in a demo map and attach it

Just the triggers?
Anything else?
Sure.

Put some units in the map so I can actually test this.
And 0.9.9.3 is like really old version...

EDIT:
Put the boss and that toxic sheep, they are making trouble..
 

Hatebreeder

So many apples
Reaction score
381
I saw alot of things, that made me curious.
First of all I have seen Scopes, where the part under the //===============
isn't public. (I think they must be public to initiate the function before the trigger fires)
I will look though if I find more things that look fishy...

BTW, I am new to (v)Jass if I say something wrong, then someone, correct me...
 

Cohadar

master of fugue
Reaction score
209
There were no errors when I run the game?

I guess you simply need to update jasshelper.
 

Tinki3

Special Member
Reaction score
418
> I guess you simply need to update jasshelper

Ok, cool, thought so.

Thanks for your time.

> I will look though if I find more things that look fishy

It's not fishy, the function can work like that, and it doesn't need to be public.
The trigger works, btw, it's just that something internal was bugged.
Probably JASSHelper, as Cohadar said.
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top