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.
  • Ghan Ghan:
    Howdy
  • Ghan Ghan:
    Still lurking
    +3
  • The Helper The Helper:
    I am great and it is fantastic to see you my friend!
    +1
  • The Helper The Helper:
    If you are new to the site please check out the Recipe and Food Forum https://www.thehelper.net/forums/recipes-and-food.220/
  • Monovertex Monovertex:
    How come you're so into recipes lately? Never saw this much interest in this topic in the old days of TH.net
  • Monovertex Monovertex:
    Hmm, how do I change my signature?
  • tom_mai78101 tom_mai78101:
    Signatures can be edit in your account profile. As for the old stuffs, I'm thinking it's because Blizzard is now under Microsoft, and because of Microsoft Xbox going the way it is, it's dreadful.
  • The Helper The Helper:
    I am not big on the recipes I am just promoting them - I use the site as a practice place promoting stuff
    +2
  • Monovertex Monovertex:
    @tom_mai78101 I must be blind. If I go on my profile I don't see any area to edit the signature; If I go to account details (settings) I don't see any signature area either.
  • The Helper The Helper:
    You can get there if you click the bell icon (alerts) and choose preferences from the bottom, signature will be in the menu on the left there https://www.thehelper.net/account/preferences
  • The Helper The Helper:
    I think I need to split the Sci/Tech news forum into 2 one for Science and one for Tech but I am hating all the moving of posts I would have to do
  • The Helper The Helper:
    What is up Old Mountain Shadow?
  • The Helper The Helper:
    Happy Thursday!
    +1
  • Varine Varine:
    Crazy how much 3d printing has come in the last few years. Sad that it's not as easily modifiable though
  • Varine Varine:
    I bought an Ender 3 during the pandemic and tinkered with it all the time. Just bought a Sovol, not as easy. I'm trying to make it use a different nozzle because I have a fuck ton of Volcanos, and they use what is basically a modified volcano that is just a smidge longer, and almost every part on this thing needs to be redone to make it work
  • Varine Varine:
    Luckily I have a 3d printer for that, I guess. But it's ridiculous. The regular volcanos are 21mm, these Sovol versions are about 23.5mm
  • Varine Varine:
    So, 2.5mm longer. But the thing that measures the bed is about 1.5mm above the nozzle, so if I swap it with a volcano then I'm 1mm behind it. So cool, new bracket to swap that, but THEN the fan shroud to direct air at the part is ALSO going to be .5mm to low, and so I need to redo that, but by doing that it is a little bit off where it should be blowing and it's throwing it at the heating block instead of the part, and fuck man
  • Varine Varine:
    I didn't realize they designed this entire thing to NOT be modded. I would have just got a fucking Bambu if I knew that, the whole point was I could fuck with this. And no one else makes shit for Sovol so I have to go through them, and they have... interesting pricing models. So I have a new extruder altogether that I'm taking apart and going to just design a whole new one to use my nozzles. Dumb design.
  • Varine Varine:
    Can't just buy a new heatblock, you need to get a whole hotend - so block, heater cartridge, thermistor, heatbreak, and nozzle. And they put this fucking paste in there so I can't take the thermistor or cartridge out with any ease, that's 30 dollars. Or you can get the whole extrudor with the direct driver AND that heatblock for like 50, but you still can't get any of it to come apart
  • Varine Varine:
    Partsbuilt has individual parts I found but they're expensive. I think I can get bits swapped around and make this work with generic shit though
  • Ghan Ghan:
    Heard Houston got hit pretty bad by storms last night. Hope all is well with TH.
  • The Helper The Helper:
    Power back on finally - all is good here no damage
    +2
  • V-SNES V-SNES:
    Happy Friday!
    +1

      The Helper Discord

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top