• 🏆 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] Trigger crashing game

Status
Not open for further replies.
Level 6
Joined
Aug 2, 2007
Messages
23
Hi.
I'm having a problem with this trigger that I don't know how to solve. It keeps crashig the game.
The trigger is an ability that casts multiple Entangling Roots in an area.

Here is my trigger:
JASS:
function Trig_Entangling_Roots_Conditions takes nothing returns boolean
    return (GetSpellAbilityId() == 'A00A')
endfunction

function EnemiesInRange_func takes nothing returns boolean
    return (IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(GetTriggerUnit())) == true) and (GetUnitState(GetFilterUnit(), UNIT_STATE_LIFE) > 0.405) and (IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) == false) and (IsUnitType(GetFilterUnit(), UNIT_TYPE_GROUND) == true)
endfunction

function Trig_Entangling_Roots_Actions takes nothing returns nothing
    local integer i = GetUnitAbilityLevel(GetTriggerUnit(), 'A00A')
    local location loc = GetSpellTargetLoc()
    local real x = GetLocationX(loc)
    local real y = GetLocationY(loc)
    local unit u = CreateUnit(GetOwningPlayer(GetTriggerUnit()), 'h005', x, y, 270)
    local unit t
    local real range = 400
    local group g = CreateGroup()
    
    
    if (i == 2) then
        set range = 450
    elseif (i == 3) then
        set range = 500
    elseif (i == 4) then
        set range = 600
    endif
    
    call UnitAddAbility(u, 'A00B')
    call SetUnitAbilityLevel(u, 'A00B', i)
    call UnitApplyTimedLife(u, 'BTLF', 10)
    
    call GroupEnumUnitsInRange(g, x, y, range, Filter(function EnemiesInRange_func))
    if (CountUnitsInGroup(g) > 0) then
        loop
            exitwhen CountUnitsInGroup(g) == 0
            
            set t = FirstOfGroup(g)
            call GroupRemoveUnit(g, t)
            call IssueTargetOrder(u, "entanglingroots", t)
            set t = null
        endloop
    endif
        
    call DestroyGroup(g)
    call RemoveLocation(loc)
    set loc = null
    set g = null
    set u = null
endfunction

//===========================================================================
function InitTrig_Entangling_Roots takes nothing returns nothing
    local trigger Entangling_Roots = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( Entangling_Roots, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( Entangling_Roots, Condition( function Trig_Entangling_Roots_Conditions ) )
    call TriggerAddAction( Entangling_Roots, function Trig_Entangling_Roots_Actions )
endfunction

I've tried a lot of different things. I found out that it works, if I add a 0.5 second wait in the loop. -But then it casts very slow. I want this to be instant. (Almost like Rooftrellen's ulti in DotA.) If the wait is 0.4 sec or below, the game crashes.
I believe the crash is caused by an endless loop, but I have no idea why or how to fix it.

I've tested the ability without the trigger, it works as it is supposed to (doing nothing). I've also tested 'A00B' (Entangling Roots), it also works. -It costs 1 mana, my dummy unit has 5000, it has 99999 cast range and 0 cooldown.

Help appriciated. =)
 
Level 17
Joined
Jun 17, 2007
Messages
1,433
If I'm not mistaken, your problem is caused by the odd way you designed your loop. Use this instead:

JASS:
loop
    set t = FirstOfGroup(g)
    exitwhen t == null
    call GroupRemoveUnit(g, t)
    call IssueTargetOrder(u, "entanglingroots", t)
endloop
You also don't need to null the local unit within the loop. Set it to null at the end of your function instead.

Another tip. Ideally, the range of your level would increase by equal increments, instead of quite random increments. Instead of something long like this:
JASS:
    if (i == 2) then
        set range = 450
    elseif (i == 3) then
        set range = 500
    elseif (i == 4) then
        set range = 600
    endif
You could easilly simplify it into:
JASS:
set range = level * 50. + 400.
Which would return 450 at level one, 500 at level two, and 550 at level three.
 
Level 6
Joined
Aug 2, 2007
Messages
23
Nothing odd about my loop. It works with other triggers.
Either way, I figured it couldn't hurt to try, so I tried it like this:

JASS:
function Trig_Entangling_Roots_Conditions takes nothing returns boolean
    return (GetSpellAbilityId() == 'A00A')
endfunction

function EnemiesInRange_func takes nothing returns boolean
    return (IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(GetTriggerUnit())) == true) and (GetUnitState(GetFilterUnit(), UNIT_STATE_LIFE) > 0.405) and (IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) == false) and (IsUnitType(GetFilterUnit(), UNIT_TYPE_GROUND) == true)
endfunction

function Trig_Entangling_Roots_Actions takes nothing returns nothing
    local integer i = GetUnitAbilityLevel(GetTriggerUnit(), 'A00A')
    local location loc = GetSpellTargetLoc()
    local real x = GetLocationX(loc)
    local real y = GetLocationY(loc)
    local unit u
    local unit t
    local real range = i * 50 + 400
    local group g = CreateGroup()
    
    
    call GroupEnumUnitsInRange(g, x, y, range, Filter(function EnemiesInRange_func))
    if (CountUnitsInGroup(g) > 0) then
        loop
            set t = FirstOfGroup(g)
            exitwhen t == null
            
            set u = CreateUnit(GetOwningPlayer(GetTriggerUnit()), 'h005', x, y, 270)
            call UnitAddAbility(u, 'A00B')
            call SetUnitAbilityLevel(u, 'A00B', i)
            call UnitApplyTimedLife(u, 'BTLF', 3)
            call GroupRemoveUnit(g, t)
            call IssueTargetOrder(u, "entanglingroots", t)
        endloop
    endif
    
    call DestroyGroup(g)
    call RemoveLocation(loc)
    set loc = null
    set g = null
    set u = null
    set t = null
endfunction

//===========================================================================
function InitTrig_Entangling_Roots takes nothing returns nothing
    local trigger Entangling_Roots = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( Entangling_Roots, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( Entangling_Roots, Condition( function Trig_Entangling_Roots_Conditions ) )
    call TriggerAddAction( Entangling_Roots, function Trig_Entangling_Roots_Actions )
endfunction

But it still crashes.. =(
 
Level 6
Joined
Aug 19, 2006
Messages
187
Nothing odd about my loop. It works with other triggers.
Either way, I figured it couldn't hurt to try, so I tried it like this:

JASS:
function Trig_Entangling_Roots_Conditions takes nothing returns boolean
    return (GetSpellAbilityId() == 'A00A')
endfunction

function EnemiesInRange_func takes nothing returns boolean
    return (IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(GetTriggerUnit())) == true) and (GetUnitState(GetFilterUnit(), UNIT_STATE_LIFE) > 0.405) and (IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) == false) and (IsUnitType(GetFilterUnit(), UNIT_TYPE_GROUND) == true)
endfunction

function RootSpell takes unit whichunit return nothing
    local unit u
    set u = CreateUnit(GetOwningPlayer(GetTriggerUnit()), 'h005', x, y, 270)
    call UnitAddAbility(u, 'A00B')
    call SetUnitAbilityLevel(u, 'A00B', i)
    call UnitApplyTimedLife(u, 'BTLF', 3)
    call IssueTargetOrder(u, "entanglingroots", whichunit)
    set u = null
endfunction

function Trig_Entangling_Roots_Actions takes nothing returns nothing
    local integer i = GetUnitAbilityLevel(GetTriggerUnit(), 'A00A')
    local location loc = GetSpellTargetLoc()
    local real x = GetLocationX(loc)
    local real y = GetLocationY(loc)
    local unit u
    local real range = i * 50 + 400
    local group g = CreateGroup()
    
    
    call GroupEnumUnitsInRange(g, x, y, range, Filter(function EnemiesInRange_func))
    loop
       exitwhen FirstOfGroup(g) == null
                call RootSpell(FirstOfGroup(g))
                call GroupRemoveUnit(g,FirstOfGroup(g))
    endloop  
    
    call DestroyGroup(g)
    call RemoveLocation(loc)
    set loc = null
    set g = null
    set u = null
endfunction

//===========================================================================
function InitTrig_Entangling_Roots takes nothing returns nothing
    local trigger Entangling_Roots = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( Entangling_Roots, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( Entangling_Roots, Condition( function Trig_Entangling_Roots_Conditions ) )
    call TriggerAddAction( Entangling_Roots, function Trig_Entangling_Roots_Actions )
endfunction

But it still crashes.. =(


that would be my idea, soo i needed to edit some things now it should be right
 
Level 17
Joined
Jun 17, 2007
Messages
1,433
Nothing odd about my loop. It works with other triggers.
Either way, I figured it couldn't hurt to try, so I tried it like this:

JASS:
function Trig_Entangling_Roots_Conditions takes nothing returns boolean
    return (GetSpellAbilityId() == 'A00A')
endfunction

function EnemiesInRange_func takes nothing returns boolean
    return (IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(GetTriggerUnit())) == true) and (GetUnitState(GetFilterUnit(), UNIT_STATE_LIFE) > 0.405) and (IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) == false) and (IsUnitType(GetFilterUnit(), UNIT_TYPE_GROUND) == true)
endfunction

function Trig_Entangling_Roots_Actions takes nothing returns nothing
    local integer i = GetUnitAbilityLevel(GetTriggerUnit(), 'A00A')
    local location loc = GetSpellTargetLoc()
    local real x = GetLocationX(loc)
    local real y = GetLocationY(loc)
    local unit u
    local unit t
    local real range = i * 50 + 400
    local group g = CreateGroup()
    
    
    call GroupEnumUnitsInRange(g, x, y, range, Filter(function EnemiesInRange_func))
    if (CountUnitsInGroup(g) > 0) then
        loop
            set t = FirstOfGroup(g)
            exitwhen t == null
            
            set u = CreateUnit(GetOwningPlayer(GetTriggerUnit()), 'h005', x, y, 270)
            call UnitAddAbility(u, 'A00B')
            call SetUnitAbilityLevel(u, 'A00B', i)
            call UnitApplyTimedLife(u, 'BTLF', 3)
            call GroupRemoveUnit(g, t)
            call IssueTargetOrder(u, "entanglingroots", t)
        endloop
    endif
    
    call DestroyGroup(g)
    call RemoveLocation(loc)
    set loc = null
    set g = null
    set u = null
    set t = null
endfunction

//===========================================================================
function InitTrig_Entangling_Roots takes nothing returns nothing
    local trigger Entangling_Roots = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( Entangling_Roots, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( Entangling_Roots, Condition( function Trig_Entangling_Roots_Conditions ) )
    call TriggerAddAction( Entangling_Roots, function Trig_Entangling_Roots_Actions )
endfunction
But it still crashes.. =(
The fact that your loop is working is nothing compared to the inefficiency of it. Please remove the if statement and the unneeded range variable.

You could also try using a null boolexpr
JASS:
    call GroupEnumUnitsInRange(g, x, y, range, null)
And see if it still crashes the game.
 
Level 6
Joined
Aug 2, 2007
Messages
23
I re-made it just like you said, like this:

JASS:
function Trig_Entangling_Roots_Conditions takes nothing returns boolean
    return (GetSpellAbilityId() == 'A00A')
endfunction

function EnemiesInRange_func takes nothing returns boolean
    return (IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(GetTriggerUnit())) == true) and (GetUnitState(GetFilterUnit(), UNIT_STATE_LIFE) > 0.405) and (IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) == false) and (IsUnitType(GetFilterUnit(), UNIT_TYPE_GROUND) == true)
endfunction

function RootSpell_func takes unit whichunit returns nothing
    local integer i = GetUnitAbilityLevel(GetTriggerUnit(), 'A00A')
    local real x = GetUnitX(whichunit)
    local real y = GetUnitY(whichunit)
    local unit u = CreateUnit(GetOwningPlayer(GetTriggerUnit()), 'h005', x, y, 270)
    
    call UnitAddAbility(u, 'A00B')
    call SetUnitAbilityLevel(u, 'A00B', i)
    call UnitApplyTimedLife(u, 'BTLF', 3)
    call IssueTargetOrder(u, "entanglingroots", whichunit)
    
    set u = null
endfunction


function Trig_Entangling_Roots_Actions takes nothing returns nothing
    local integer i = GetUnitAbilityLevel(GetTriggerUnit(), 'A00A')
    local location loc = GetSpellTargetLoc()
    local real x = GetLocationX(loc)
    local real y = GetLocationY(loc)
    local real range = i * 50 + 400
    local group g = CreateGroup()
    
    
    call GroupEnumUnitsInRange(g, x, y, range, null)
    loop
        exitwhen FirstOfGroup(g) == null
        call RootSpell_func(FirstOfGroup(g))
        call GroupRemoveUnit(g,FirstOfGroup(g))
    endloop
    
    call DestroyGroup(g)
    call RemoveLocation(loc)
    set loc = null
    set g = null
endfunction

//===========================================================================
function InitTrig_Entangling_Roots takes nothing returns nothing
    local trigger Entangling_Roots = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( Entangling_Roots, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( Entangling_Roots, Condition( function Trig_Entangling_Roots_Conditions ) )
    call TriggerAddAction( Entangling_Roots, function Trig_Entangling_Roots_Actions )
endfunction

-Still crashes.

I tried using null as filter in the GroupEnumUnitsInRange function.
-Still crashes.

=(
 
Level 6
Joined
Aug 2, 2007
Messages
23
EDIT:
The problem has been solved.
It was nothing wrong with the trigger (except maybe a bit inefficient), the problem was the ability and it's buffs.
I realized this when I made a new test ability and ordered it to run the trigger, which then worked.

Thank you everyone for trying to help. =)
 
Last edited:
Status
Not open for further replies.
Top