• 🏆 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!

[Trigger] Help, function causes fatal error

Status
Not open for further replies.
Level 7
Joined
Oct 21, 2008
Messages
234
Hi there!
since weeks this trigger, designed for a area spell, causes fatal errors (access violation) in random situations. The error appears when only one unit is in range, cant get more information out of it, it seems very random.

Could someone help me plz? :cry:


JASS:
function UnitEnemyNS takes nothing returns boolean
    if GetUnitState(GetFilterUnit(),UNIT_STATE_LIFE)<= 0 or IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) or GetUnitAbilityLevel(GetEnumUnit(),'Avul')>0 or GetUnitAbilityLevel(GetEnumUnit(),'Aloc')>0 then
        return false
    endif
    return IsPlayerEnemy(GetOwningPlayer(GetFilterUnit()), GetOwningPlayer(udg_tmpUnit))
endfunction


function Trig_Sandstorm_Actions takes nothing returns nothing
    local unit uCaster = GetTriggerUnit()
    local location tmpLocation = GetSpellTargetLoc()
    local real tx = GetLocationX(tmpLocation)
    local real ty = GetLocationY(tmpLocation)
    local real x
    local real y
    local real angle
    local real dist
    local integer i = 0
    local integer j = 0
    local integer n
    local group g = CreateGroup()
    local unit u
    local integer abilvl = GetUnitAbilityLevel(uCaster,'A05Q')
    local real dmg = I2R(abilvl+3)*10+I2R(GetHeroStr(uCaster,true))/2.0
    call RemoveLocation( tmpLocation )
    set tmpLocation = null

    loop
        exitwhen i > 20
        call CameraNoise(300, tx, ty)

        set angle = GetRandomReal(0,2*bj_PI)
        set dist = GetRandomReal(64, 256.00)
        set x = tx+Cos(angle)*dist
        set y = ty+Sin(angle)*dist
        call DestroyEffect(AddSpecialEffect("Objects\\Spawnmodels\\Undead\\ImpaleTargetDust\\ImpaleTargetDust.mdl",x,y))
        set angle = GetRandomReal(0,2*bj_PI)
        set dist = GetRandomReal(64, 256.00)
        set x = tx+Cos(angle)*dist
        set y = ty+Sin(angle)*dist
        call DestroyEffect(AddSpecialEffect("Objects\\Spawnmodels\\Undead\\ImpaleTargetDust\\ImpaleTargetDust.mdl",x,y))
        
        call GroupClear(g)
        set udg_tmpUnit = uCaster
        call GroupEnumUnitsInRange(g,tx,ty,256.0,Condition(function UnitEnemyNS))
        set u = null
        set n = CountUnitsInGroup(g)
        if n>0 then
            set n = GetRandomInt(1,n)
            set j=1
            loop
                exitwhen j>=n
                call GroupRemoveUnit(g,FirstOfGroup(g))
                set j=j+1
            endloop
            set u = FirstOfGroup(g)

            //call UnitDamageTarget(uCaster,u,dmg,true,false,ATTACK_TYPE_MAGIC, DAMAGE_TYPE_MAGIC, WEAPON_TYPE_WHOKNOWS)
            call DestroyEffect(AddSpecialEffect("Abilities\\Spells\\Undead\\Impale\\ImpaleHitTarget.mdl",GetUnitX(u),GetUnitY(u)))
        endif
        
        call TriggerSleepAction( 0.50 )
        set i = i+1
    endloop
    
    call DestroyGroup(g)
    set g = null
endfunction
 
Level 10
Joined
Mar 31, 2009
Messages
732
JASS:
            loop
                exitwhen j>=n
                call GroupRemoveUnit(g,FirstOfGroup(g))
                set j=j+1
            endloop
            set u = FirstOfGroup(g)
u is always going to be null, because you remove everything from the group during that loop, then try to take the next unit.
 
Level 7
Joined
Oct 21, 2008
Messages
234
No.
JASS:
set n = CountUnitsInGroup(g)
        if n>0 then
            set n = GetRandomInt(1,n)

As you can see n is the limited by the number of units in the group.

JASS:
            loop
                exitwhen j>=n
                call GroupRemoveUnit(g,FirstOfGroup(g))
                set j=j+1
            endloop
The loop: it ends before the last unit is reached, even if n is the last unit.


Edit the problem even occurs, when using the first of the group (0 units in group checked).
 
Level 10
Joined
Mar 31, 2009
Messages
732
Ah, I see. My bad.
It is a bit strange. I ran through your code and didn't see anything wrong.

You said that its happening when only one unit is in range. I suggest adding some debug lines with some waits, and keeping in mind what the last debug message was you saw before the game crashed.
 
Level 7
Joined
Oct 21, 2008
Messages
234
It stops at "wait" which is pretty uncommon. I replaced the main ability, now it works. It seems that "monsoon" is bugged. Guess it depens on the time, as in this case the error pops up in the first loop. while it crashed in 2nd or 3rd before. Monsoon, which is channeled, wont follow the spell after some seconds.
JASS:
function Trig_Sandstorm_Actions takes nothing returns nothing
    local unit uCaster = GetTriggerUnit()
    local location tmpLocation = GetSpellTargetLoc()
    local real tx = GetLocationX(tmpLocation)
    local real ty = GetLocationY(tmpLocation)
    local integer i = 0
    local group g = CreateGroup()
    local unit u
    local integer abilvl = GetUnitAbilityLevel(uCaster,'A05Q')
    local real dmg = I2R(abilvl+3)*10+I2R(GetHeroStr(uCaster,true))/2.0
    call RemoveLocation( tmpLocation )
    set tmpLocation = null
    
    call Print("init")
    call TriggerSleepAction( 0.40 )

    loop
        call Print("loop")        
        call TriggerSleepAction( 0.40 )
        exitwhen i > 20
        call Print("exitwhen i > 20")
        call TriggerSleepAction( 0.40 )
        
        call GroupClear(g)
        call Print("GroupClear(g)")
        call TriggerSleepAction( 0.40 )
        set udg_tmpUnit = uCaster
        call Print("udg_tmpUnit = uCaster")
        call TriggerSleepAction( 0.40 )
        call GroupEnumUnitsInRange(g,tx,ty,256.0,Condition(function UnitEnemyNS))
        call Print("GroupEnumUnitsInRange")
        call TriggerSleepAction( 0.40 )
        set u = FirstOfGroup(g)
        call Print("u = FirstOfGroup(g)")
        call TriggerSleepAction( 0.40 )
        call UnitDamageTarget(uCaster,u,dmg,true,false,ATTACK_TYPE_MAGIC, DAMAGE_TYPE_MAGIC, WEAPON_TYPE_WHOKNOWS)
        call Print("UnitDamageTarget")
        call TriggerSleepAction( 0.40 )
        call Print("wait")        
        call TriggerSleepAction( 0.40 )
        call Print("i = i+1")
        call TriggerSleepAction( 0.40 )
        set i = i+1
    endloop
    
    call Print("DestroyGroup(g)")        
    call TriggerSleepAction( 0.40 )
    
    call DestroyGroup(g)
    set g = null
endfunction
 
Status
Not open for further replies.
Top