HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

triggered spell effect crash

02-06-2008, 11:46 PM#1
SockSquirrelMouthwash
I modified my roommate Castlemaster's snow storm spell as so:

Define weathereffect array I'll use for the snowstorm effect
Collapse JASS:
globals
    weathereffect array shatterfx
endglobals

Whenever the snowstorm starts, begin this number
Collapse JASS:
private function ShatterAction takes nothing returns nothing
    local unit caster = GetTriggerUnit()
    local real x = GetUnitX(caster)
    local real y = GetUnitY(caster)
    local rect area = Rect(x, y-707, x+707, y)
    local integer t    
    local integer lvl = GetUnitAbilityLevel(caster, GetSpellAbilityId())
    local integer fxnum = 0
    
    loop
        if shatterfx[fxnum] == null then
            call AddWeatherEffectSaveLast(area, 'SNbs')
            set shatterfx[fxnum] = GetLastCreatedWeatherEffect()
            call EnableWeatherEffect(shatterfx[fxnum], true)
        endif
        
        exitwhen shatterfx[fxnum] != null
        set fxnum = fxnum + 1
    endloop

    set t = ST_StartNew(2, true, function FrostInfliction)
    call ST_SetUnit1(t, caster)
    call ST_SetInt1(t, lvl)
    call ST_SetInt2(t, fxnum)
    call ST_SetReal1(t, x)
    call ST_SetReal2(t, y)
     
    call RemoveRect(area) 
    set area = null 
    set caster = null
endfunction

The timer that runs as a result. It will stop whenever the shut off conditions (ran out of mana or the toggle ability is turned off) are met.
Collapse JASS:
private function FrostFilter takes nothing returns boolean
    return (GetUnitState(GetFilterUnit(), UNIT_STATE_LIFE) > 0 )
endfunction

private function FrostInfliction takes nothing returns nothing
    local integer t = ST_GetExpiredTimer()
    local integer level = ST_GetInt1(t)
    local integer weather = ST_GetInt2(t)
    local unit cast = ST_GetUnit1(t)
    local unit u
    local group g = CreateGroup()
    local real x = ST_GetReal1(t)
    local real y = ST_GetReal2(t)
    local real targetx
    local real targety
    
    if GetUnitUserData(cast) == 0 then
        call ST_Destroy(t)
        call EnableWeatherEffect(shatterfx[weather], false)
        call RemoveWeatherEffectBJ(shatterfx[weather])
        set shatterfx[weather] = null
    elseif GetUnitState(cast, UNIT_STATE_MANA) <= 2 and GetUnitUserData(cast) == 1 then
        call ST_Destroy(t)
        call SetUnitUserData(cast, 0)
        call EnableWeatherEffect(shatterfx[weather], false)
        call RemoveWeatherEffectBJ(shatterfx[weather])
        set shatterfx[weather] = null
        call IssueImmediateOrder(cast, "unimmolation")
    else
    //call PlaySoundOnUnitBJ( gg_snd_FrostArmorTarget1, 100, cast )

    call GroupEnumUnitsInRange(g,x,y,1000.00, null)
    
    loop
        set u = FirstOfGroup(g)
        exitwhen u == null
        set targetx = GetUnitX(u)
        set targety = GetUnitY(u)
        if IsUnitEnemy(u, GetOwningPlayer(cast)) and (GetUnitState(u, UNIT_STATE_LIFE) > 0 ) then
            if (GetUnitAbilityLevel(u,'B00C') > 0) then
                call UnitRemoveAbility(u,'B00C')
                call CasterCastAbility(GetOwningPlayer(cast), 'A02O', "cripple", u, false) // Level 2 Slow
            elseif (GetUnitAbilityLevel(u,'B00E') > 0) then
                call UnitRemoveAbility(u,'B00E')
                call CasterCastAbility(GetOwningPlayer(cast), 'A02R', "cripple", u, false) // Level 3 Slow
            elseif (GetUnitAbilityLevel(u,'B00H') > 0) then
                call UnitRemoveAbility(u,'B00H')
                call CasterCastAbility(GetOwningPlayer(cast), 'A02G', "thunderbolt", u, false) // Stun
            elseif (GetUnitAbilityLevel(u,'B00G') > 0) then 
                call UnitRemoveAbility(u,'B00G')
                call DamageUnitsInAOEEx( cast, 30, targetx, targety, 150, false, DamageTypes(ATTACK_TYPE_MAGIC, DAMAGE_TYPE_NORMAL)) // Shatter
                call SpecialEffectTarget( "Abilities\\Spells\\Undead\\FrostNova\\FrostNovaTarget.mdl", u, "origin", 2)
            else
                call CasterCastAbility(GetOwningPlayer(cast), 'A02H', "cripple", u, false) // Level 1 Slow
            endif
        endif
        call GroupRemoveUnit(g,u)
    endloop

    call DestroyGroup(g)
    
    endif
    set g = null
    set cast = null
endfunction
As far as I know, after testing over and over again, everything works perfectly as I want it to. Now what I want it to do is for it to work on a larger scale, like say.... 7 or more going on at once. When I do try 15 it eventually will crash WC3. I'm wondering what it is in the function(s) that causes this crash.

Thanks in advance!
02-07-2008, 02:20 AM#2
Pyrogasm
Does it work after 15 or so individual casts without having them going on at once? Or does it only crash if 15 are going at the same time?

Try debugging the indexes of arrays; sometimes integers flip out and give you stuff like -2935259327501958975235.
02-07-2008, 02:25 AM#3
SockSquirrelMouthwash
Quote:
Originally Posted by Pyrogasm
Does it work after 15 or so individual casts without having them going on at once? Or does it only crash if 15 are going at the same time?

Try debugging the indexes of arrays; sometimes integers flip out and give you stuff like -2935259327501958975235.

I'll give it a shot. I'll get back to you on the 15 or more going on all at once bit.
UPDATE: Forget all at once, for some reason after a few runs of the code the game will crash, duno why, having trouble tracking the source

I have another problem that kinda popped up now, sometimes the weather effect will play and sometimes it will not. Like I"ll toggle the ability for one tower and a few others will not display the weather effect (but still have the main stuff functioning), or another time it'll be like 2-3 towers with weather effect and the rest no weather effect.

UPDATE: In addition to this, I setup a text to tell me what indexes have been taken like: "Player 1's index 0 created"..."Player 2's index 1 created"... etc. But when I ran the map, I see something like this: "Player 1's index 0 created" "Player 2's index 0 created" "Player 3's index 1 created" - which seems to happen when the function runs twice when two different buildings cast the ability simultaneously

I updated that code here:
Collapse JASS:
private function ShatterAction takes nothing returns nothing
    local unit caster = GetTriggerUnit()
    local real x = GetUnitX(caster)
    local real y = GetUnitY(caster)
    local rect area = Rect(x, y-707, x+707, y)
    local integer t    
    local integer lvl = GetUnitAbilityLevel(caster, GetSpellAbilityId())
    local integer fxnum = 0
    local integer truedat = 0
    local integer i = GetPlayerId(GetOwningPlayer(caster))+1
    
    loop
        if shatterfx[fxnum] == null then
            call AddWeatherEffectSaveLast(area, 'SNbs')
            set shatterfx[fxnum] = GetLastCreatedWeatherEffect()
            call EnableWeatherEffect(shatterfx[fxnum], true)
            set truedat = 1
        endif
        
        exitwhen truedat == 1
        set fxnum = fxnum + 1
    endloop

    // Debug msg
    call DisplayTimedTextToPlayer( Player(0), 0, 0, 1, udg_playernames[i]+" index: "+I2S(fxnum)+" created" )

    set t = ST_StartNew(2, true, function FrostInfliction)
    call ST_SetUnit1(t, caster)
    call ST_SetInt1(t, lvl)
    call ST_SetInt2(t, fxnum)
    call ST_SetReal1(t, x)
    call ST_SetReal2(t, y)
     
    call RemoveRect(area) 
    set area = null 
    set caster = null
endfunction

Update: I looked at the error message whenever WC3 crashed, it's along the lines of some memory that could not be 'read'...
02-08-2008, 01:17 AM#4
SockSquirrelMouthwash
*Bump*

Well I tried commenting out everything related to the weather effects and checked to see if it would not crash. Turns out it still crashed! I rechecked the code and saw that I didn't set u = null in:

Collapse JASS:
private function FrostFilter takes nothing returns boolean
    return GetUnitAbilityLevel(GetFilterUnit(),'B007') > 0
endfunction

private function FrostInfliction takes nothing returns nothing
    local integer t = ST_GetExpiredTimer()
    local integer level = ST_GetInt1(t)
    local unit cast = ST_GetUnit1(t)
    local unit u
    local group g = CreateGroup()
    local real x = ST_GetReal1(t)
    local real y = ST_GetReal2(t)
    local real targetx
    local real targety
    local integer i = GetPlayerId(GetOwningPlayer(cast))+1
    
    if GetUnitAbilityLevel(cast,'B00I') > 0 then
    call PlaySoundOnUnitBJ( gg_snd_FrostArmorTarget1, 100, cast )
    call GroupEnumUnitsInRange(g,x,y,1000.00, Condition(function FrostFilter))
    
    loop
        set u = FirstOfGroup(g)
        exitwhen u == null
        set targetx = GetUnitX(u)
        set targety = GetUnitY(u)
        if IsUnitEnemy(u, GetOwningPlayer(cast)) and (GetUnitState(u, UNIT_STATE_LIFE) > 0 ) then
            if (GetUnitAbilityLevel(u,'B00C') > 0) then
                call UnitRemoveAbility(u,'B00C')
                call CasterCastAbility(GetOwningPlayer(cast), 'A02O', "cripple", u, false) // Level 2 Slow
            elseif (GetUnitAbilityLevel(u,'B00E') > 0) then
                call UnitRemoveAbility(u,'B00E')
                call CasterCastAbility(GetOwningPlayer(cast), 'A02R', "cripple", u, false) // Level 3 Slow
            elseif (GetUnitAbilityLevel(u,'B00H') > 0) then
                call UnitRemoveAbility(u,'B00H')
                call CasterCastAbility(GetOwningPlayer(cast), 'A02G', "thunderbolt", u, false) // Stun
            elseif (GetUnitAbilityLevel(u,'B00G') > 0) then 
                call UnitRemoveAbility(u,'B00G')
                call DamageUnitsInAOEEx( cast, 20, targetx, targety, 100, false, DamageTypes(ATTACK_TYPE_MAGIC, DAMAGE_TYPE_NORMAL)) // Shatter
                call SpecialEffectTarget( "Abilities\\Spells\\Undead\\FrostNova\\FrostNovaTarget.mdl", u, "origin", 2)
            else
                call CasterCastAbility(GetOwningPlayer(cast), 'A02H', "cripple", u, false) // Level 1 Slow
            endif
        endif
        call GroupRemoveUnit(g,u)
    endloop
    
    call DestroyGroup(g)
    
    else
        call ST_Destroy(t)
    endif
    
    set u = null
    set g = null
    set cast = null
endfunction

Tried it again but still crashed. Hmmmm I'm sure there's something I'm missing and it's right in front of me. Getting kinda frustrating
02-08-2008, 01:26 AM#5
TaintedReality
Just start commenting blocks out until you find what crashes.
02-08-2008, 02:09 AM#6
SockSquirrelMouthwash
Quote:
Originally Posted by TaintedReality
Just start commenting blocks out until you find what crashes.

Alright I think I found out the source - I commented out all of the "call CasterCastAbility(...)" and ran the map and experienced no crashes whatsoever. Which leaves me to ask if there's a way Vexorian's Spellcaster system can be configured for this fairly large load of CasterCastAbility. Any suggestions?
02-08-2008, 04:02 AM#7
TaintedReality
Not really sure why that would cause a crash. Can you post the CasterCastAbility function? If anything it would just not successfully cast all of the abilities, but I don't think calling it a bunch of times would cause it to crash.
02-11-2008, 11:49 AM#8
SockSquirrelMouthwash
Quote:
Originally Posted by TaintedReality
Not really sure why that would cause a crash. Can you post the CasterCastAbility function? If anything it would just not successfully cast all of the abilities, but I don't think calling it a bunch of times would cause it to crash.

Hmmm when I took a second look at the castercastability function I noticed that the last field,
Collapse JASS:
call CasterCastAbility(GetOwningPlayer(cast), 'A02O', "cripple", u, false) 
asks if the unit should be recycled immediately upon casting or wait until finished casting and then recycled. Once I set the field to true (recycle immediately), the crashes went away