HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Crash Bug in an unrelated trigger

05-22-2007, 12:21 AM#1
Panto
Greetings.

I have a pair of triggers revolving around a summoned unit.

One of them crashes the game after the other runs more than once.

This trigger is running when the game crashes. It crashes immediately the second time that the unit attempts to cast the dummy spell that starts the trigger. However, this trigger ran fine without crashing numerous times before the second trigger was implemented.
If the beginning of the trigger seems funny, it's because it's designed to count how many units are raised from the dummy Animate Dead spell and then create only one unit in response to all the dead that were animated.

Collapse JASS:
//===============================
//   Functions
//===============================
function Trig_Patchwork_summon_Conditions takes nothing returns boolean
    local unit uCast = GetSummoningUnit()
    local unit uSummon = GetSummonedUnit()
    if (GetUnitTypeId(uCast) == 'O005') and (IsUnitType(uSummon, UNIT_TYPE_UNDEAD) == true) and (IsVoodoo(GetUnitTypeId(uSummon)) != true) then
        set uCast = null
        set uSummon = null
        return true
    endif
    set uCast = null
    set uSummon = null
    return false
endfunction

function Trig_Patchwork_summon_Actions takes nothing returns nothing
//== Locals =====================
    local integer iUndead = 0
    local integer iLoop = 0
    local unit uCast = GetSummoningUnit()
    local player pOwn = GetOwningPlayer(uCast)
    local unit uCreate = null
    local integer iLvl = GetUnitAbilityLevel(uCast, 'A034')
    local integer iRank = 0
    local real rXCast = GetUnitX(uCast)
    local real rYCast = GetUnitY(uCast)
    local real rFace = GetUnitFacing(uCast)
    local effect sfxSpawn = null

//== Actions ====================
    call SetUnitUserData(uCast, GetUnitUserData(uCast) + 1)
    call IssueImmediateOrder(uCast, "channel")

    call Pwait(0.25)

    set iUndead = GetUnitUserData(uCast)
    call SetUnitUserData(uCast, 0)

    if (iUndead != 0) then

        if (iLvl <= 1) then
            set uCreate = CreateUnit(pOwn, 'u006', rXCast, rYCast, rFace)
        elseif (iLvl == 2) then
            set uCreate = CreateUnit(pOwn, 'u007', rXCast, rYCast, rFace)
        elseif (iLvl == 3) then
            set uCreate = CreateUnit(pOwn, 'u008', rXCast, rYCast, rFace)
        else
            set uCreate = CreateUnit(pOwn, 'u009', rXCast, rYCast, rFace)
        endif

        set sfxSpawn = AddSpecialEffect("Objects\\Spawnmodels\\Undead\\UndeadDissipate\\UndeadDissipate.mdl", GetUnitX(uCreate), GetUnitY(uCreate))
        call UnitAddType(uCreate, UNIT_TYPE_SUMMONED)
        call UnitApplyTimedLife(uCreate, 'B00Y', (40.00 - 0.25))

        // Extra life
        set iLoop = 2
        loop
            exitwhen iLoop > iUndead
            call UnitAddAbility(uCreate, 'A03E')
            set iLoop = iLoop + 1
        endloop
    endif

//== Cleanup ====================
    set uCast = null
    set uCreate = null
    call Pwait(0.5)
    call DestroyEffect(sfxSpawn)
    set sfxSpawn = null
endfunction

//===============================
//   Events
//===============================
function InitTrig_Patchwork_summon takes nothing returns nothing
    set gg_trg_Patchwork_summon = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(gg_trg_Patchwork_summon, EVENT_PLAYER_UNIT_SUMMON)
    call TriggerAddCondition(gg_trg_Patchwork_summon, Condition( function Trig_Patchwork_summon_Conditions))
    call TriggerAddAction(gg_trg_Patchwork_summon, function Trig_Patchwork_summon_Actions)
endfunction

But apparently the trigger that's causing the crash is the next one. It does not seem to run when the game crashes, but nonetheless if "call KillUnit(uPick)" is commented out, the game doesn't crash anymore when that first trigger runs.

Collapse JASS:
//===============================
//   Functions
//===============================
function Trig_Patchwork_uncast_Conditions takes nothing returns boolean
    if (GetSpellAbilityId() == 'A032') then
        return true
    endif
    return false
endfunction

function Trig_Patchwork_uncast_Actions takes nothing returns nothing
//== Locals =====================
    local unit uHero = GetSpellAbilityUnit()
    local group gPatch = CreateGroup()
    local unit uPick = null
    local filterfunc filtLegal = Filter(function IsPatchwork)

//== Actions ====================
    // I guess just find all the Patchworks owned by the warlock's player and slay 'em
    call GroupEnumUnitsOfPlayer(gPatch, GetOwningPlayer(uHero), filtLegal)

    loop
        set uPick = FirstOfGroup(gPatch)
        exitwhen uPick == null

        call DisplayTimedTextToForce(GetPlayersAll(), 10.00, GetUnitName(uPick))
        call KillUnit(uPick)

        call GroupRemoveUnit(gPatch, uPick)
    endloop

//== Cleanup ====================
    set uHero = null
    call DestroyGroup(gPatch)
    set gPatch = null
endfunction

//===============================
//   Events
//===============================
function InitTrig_Patchwork_uncast takes nothing returns nothing
    set gg_trg_Patchwork_uncast = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(gg_trg_Patchwork_uncast, EVENT_PLAYER_UNIT_SPELL_ENDCAST)
    call TriggerAddCondition(gg_trg_Patchwork_uncast, Condition(function Trig_Patchwork_uncast_Conditions))
    call TriggerAddAction(gg_trg_Patchwork_uncast, function Trig_Patchwork_uncast_Actions)
endfunction

The applicable function from the Custom Script Code is this.

Collapse JASS:
function IsPatchwork takes nothing returns boolean
    local integer iId = GetUnitTypeId(GetFilterUnit())
    if ((iId == 'u006') or (iId == 'u007') or (iId == 'u008') or (iId == 'u009')) and (GetWidgetLife(GetFilterUnit()) > 0) then
        return true
    endif
    return false
endfunction

So, in short, any ideas?
05-22-2007, 12:41 AM#2
Pyrogasm
What if you replace that line with call RemoveUnit(uPick) or call ExplodeUnit(uPick)?

Additionally, you should know that this:
Collapse JASS:
    if (GetSpellAbilityId() == 'A032') then
        return true
    endif
    return false
Can be changed to return GetSpellAbilityId() == 'A032'. Likewise, IsPatchwork could be changed to this:
Collapse JASS:
function IsPatchwork takes nothing returns boolean
    local integer iId = GetUnitTypeId(GetFilterUnit())
    return ((iId == 'u006') or (iId == 'u007') or (iId == 'u008') or (iId == 'u009')) and (GetWidgetLife(GetFilterUnit()) > 0)
endfunction
Why use local unit uHero = GetSpellAbilityUnit() instead of GetTriggerUnit()?
05-22-2007, 02:14 AM#3
Panto
ExplodeUnitBJ() just sets the explode status of the unit and then calls KillUnit(). RemoveUnit() worked without crashing, however. So... I don't grasp why it's having problems Kill-ing the unit when that's not even the trigger that's being called.

I can add elements to the trigger to make Remove a viable alternative, but it's not the ideal solution. For the time being, this is what I'll do.
05-22-2007, 05:02 AM#4
Pyrogasm
What if you add a 0.01 second expiration timer to it instead of killing it?