HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Random TriggerSleepAction() Bug

08-31-2008, 10:49 PM#1
Karawasa
In Element TD there are these Undead creeps that have reincarnation. When they revive, I need certain things done to get them working. I register them when they spawn:

Collapse JASS:
function SpawnCreep takes integer j returns nothing
    local unit u
    local real hp
   
    if i > 0 then
        set u = CreateUnit(udg_CreepPlayers[j],udg_Spawns[udg_Level - 1],udg_SpawnX[j],udg_SpawnY[j],270.)
        //call SetUnitUserData( u, GetConvertedPlayerId(GetEnumPlayer()) )
        set udg_CreepOwner[GetUnitIndex(u)] = Player(j)
        call UnitAddAbility(u,udg_Spawn_HP[udg_Level - 1])
        set hp = ((udg_Difficulty[j]-1)*.125)+.50
        call SetWidgetLife(u,GetUnitState(u,UNIT_STATE_MAX_LIFE)*hp)
        call SetUnitMaxState(u,UNIT_STATE_MAX_LIFE,GetWidgetLife(u))
        call SetUnitLifePercentBJ(u,100.)
        
        call SetUnitAbilityLevel(u,'A00V',udg_Difficulty[j])
        call SetUnitAbilityLevel(u,'A01R',udg_Level)
        
        if udg_Extreme_Mode_On == true then
            call UnitAddAbility(u,'A03N')
        endif
           
        if IsUnitType(u, UNIT_TYPE_UNDEAD) == true then
            call TriggerRegisterUnitLifeEvent( gg_trg_Undead_Reincarnate, u, GREATER_THAN_OR_EQUAL, 0.405 )
        endif
           
        if IsUnitType(u, UNIT_TYPE_MECHANICAL) == true then
            call TriggerRegisterUnitManaEvent( gg_trg_Mechanical_Activate, u, GREATER_THAN_OR_EQUAL, 12.00 )
            call SetUnitState(u,UNIT_STATE_MANA,GetRandomReal(0.,12.))
        endif
           
        call IssuePointOrder(u,"move",udg_LeakX[j],udg_LeakY[j])           
       
        set u = null
    endif
endfunction

This detects when they resurrect, and then I do the following:

Collapse JASS:
function Trig_Undead_Reincarnate_Conditions takes nothing returns boolean
    if GetUnitAbilityLevel(GetTriggerUnit(),'A00U') == 0 then
        return false
    endif
    return true
endfunction

function Trig_Undead_Reincarnate_Actions takes nothing returns nothing
    local unit u
    local integer i
    
    set i = GetPlayerId(udg_CreepOwner[GetUnitUserData(GetTriggerUnit())])
    set u = GetTriggerUnit()
    
    call UnitRemoveAbility(u,'A00U')
    call SetUnitLifePercentBJ(u,33.33)
    call TriggerSleepAction(0.0)
    call IssuePointOrder(u,"move",udg_LeakX[i],udg_LeakY[i])
    
    set u = null
endfunction

//===========================================================================
function InitTrig_Undead_Reincarnate takes nothing returns nothing
    set gg_trg_Undead_Reincarnate = CreateTrigger()
    call TriggerAddCondition( gg_trg_Undead_Reincarnate, Condition( function Trig_Undead_Reincarnate_Conditions ) )
    call TriggerAddAction( gg_trg_Undead_Reincarnate, function Trig_Undead_Reincarnate_Actions )
endfunction

The bug lies with TriggerSleepAction() in my opinion. Resurrected Undead creeps will rarely and randomly not receive the order to move, but all the actions prior to TriggerSleepAction() work fine.

Any help would be much appreciated.
08-31-2008, 11:00 PM#2
moyack
the values in the array variables udg_LeakX[], udg_LeakY[] changes during the game? if so then TSA is the evil in your code.
09-01-2008, 12:17 AM#3
Karawasa
Quote:
Originally Posted by moyack
the values in the array variables udg_LeakX[], udg_LeakY[] changes during the game? if so then TSA is the evil in your code.

No, those two array variables do not ever change.
09-01-2008, 12:21 AM#4
moyack
One question....
Collapse JASS:
function InitTrig_Undead_Reincarnate takes nothing returns nothing
    set gg_trg_Undead_Reincarnate = CreateTrigger()
// where is the event setting? when it's going to run the actions??
    call TriggerAddCondition( gg_trg_Undead_Reincarnate, Condition( function Trig_Undead_Reincarnate_Conditions ) )
    call TriggerAddAction( gg_trg_Undead_Reincarnate, function Trig_Undead_Reincarnate_Actions )
endfunction
09-01-2008, 12:24 AM#5
Karawasa
Quote:
Originally Posted by moyack
One question....
Collapse JASS:
function InitTrig_Undead_Reincarnate takes nothing returns nothing
    set gg_trg_Undead_Reincarnate = CreateTrigger()
// where is the event setting? when it's going to run the actions??
    call TriggerAddCondition( gg_trg_Undead_Reincarnate, Condition( function Trig_Undead_Reincarnate_Conditions ) )
    call TriggerAddAction( gg_trg_Undead_Reincarnate, function Trig_Undead_Reincarnate_Actions )
endfunction

Collapse JASS:
if IsUnitType(u, UNIT_TYPE_UNDEAD) == true then
            call TriggerRegisterUnitLifeEvent( gg_trg_Undead_Reincarnate, u, GREATER_THAN_OR_EQUAL, 0.405 )
        endif
09-01-2008, 02:10 AM#6
Ammorth
set the issue order to a boolean (returns true if it worked, false if it doesn't) and see what the outcome was. It could be the unit fails the order within the pathing engine, or you could be double-ordering the unit.
09-01-2008, 02:26 AM#7
Karawasa
Quote:
Originally Posted by Ammorth
set the issue order to a boolean (returns true if it worked, false if it doesn't) and see what the outcome was. It could be the unit fails the order within the pathing engine, or you could be double-ordering the unit.

This bug only started to happen after I added the TriggerSleepAction().

Previously I had coded this with a PolledWait2(5) when the unit died, but this caused a lot of lag. Now I detect when it resurrects.

The problem is that without the TriggerSleepAction(), the move order never successfully happens. There is no possibility of double-order.
09-01-2008, 04:03 AM#8
DioD
Code:
blabla nothing nothing

    if not IssuePointOrder(global unit,"move",udg_LeakX[global integer],udg_LeakY[global integer]) then
call KillUnit(global unit)
endif

end


function Trig_Undead_Reincarnate_Actions takes nothing returns nothing
    local unit u
    local integer i
    
    set i = GetPlayerId(udg_CreepOwner[GetUnitUserData(GetTriggerUnit())])
    set u = GetTriggerUnit()
    
    call UnitRemoveAbility(u,'A00U')
    call SetUnitLifePercentBJ(u,33.33)

set someglobal integer = i
set someglobal unit = u
call TimerStart(anytimer,0,false function blabla)
    
    set u = null
endfunction
09-03-2008, 08:31 PM#9
Karawasa
Someone tried this approach over at TH. The end result is that the move order never gets issued to any unit.

Collapse JASS:
globals
    trigger gg_trg_Undead_Reincarnate
    real array udg_LeakX
    real array udg_LeakY
    player array udg_CreepOwner
    timer zerotimer = CreateTimer()
    
    integer N = -1
    unit array s_unit
endglobals

function Callback takes nothing returns nothing
    local integer i = N
    local integer id
    loop
        exitwhen i < 0
        set id = GetPlayerId(udg_CreepOwner[GetUnitUserData(s_unit[i])]) // I'm assuming this doesn't randomly change in Actions
        call IssuePointOrder(s_unit[i],"move",udg_LeakX[i],udg_LeakY[i])
        set i = i-1
    endloop
    set N = -1
endfunction

function Trig_Undead_Reincarnate_Conditions takes nothing returns boolean
    return GetUnitAbilityLevel(GetTriggerUnit(),'A00U') > 0
endfunction

function Trig_Undead_Reincarnate_Actions takes nothing returns nothing
    local unit u = GetTriggerUnit()
    
    call UnitRemoveAbility(u,'A00U')
    call SetUnitLifePercentBJ(u,33.33)
    set N = N+1
    set s_unit[N] = u
    call TimerStart(zerotimer, 0., false, function Callback)
    
    set u = null
endfunction

function InitTrig_Undead_Reincarnate takes nothing returns nothing
    set gg_trg_Undead_Reincarnate = CreateTrigger()
    call TriggerAddCondition( gg_trg_Undead_Reincarnate, Condition( function Trig_Undead_Reincarnate_Conditions ) )
    call TriggerAddAction( gg_trg_Undead_Reincarnate, function Trig_Undead_Reincarnate_Actions )
endfunction

This timer method does not work. Any other ideas?
09-03-2008, 08:47 PM#10
moyack
Karawasa, I don't have WC3 in this moment, but I think this code can be improved, so I need that you do a small test for me. Resurrected units (using resurrection ability) trigger the summoning event when they revive, if this work with the resurrection ability too, you can cast them with this event, get the summoned unit and order it to move in that moment, avoiding completely the evil TSA.

Collapse JASS:
function Trig_Undead_Reincarnate_Conditions takes nothing returns boolean
    return GetUnitAbilityLevel(GetTriggerUnit(),'A00U') > 0
endfunction

function Trig_Undead_Reincarnate_Actions takes nothing returns nothing
    local unit u = GetSummonedUnit()
    local integer i = GetPlayerId(udg_CreepOwner[GetUnitUserData(u)])
    
    call UnitRemoveAbility(u,'A00U')
    call SetUnitLifePercentBJ(u,33.33)
    //call TriggerSleepAction(0.0)
    call IssuePointOrder(u,"move",udg_LeakX[i],udg_LeakY[i])
    
    set u = null
endfunction


function InitTrig_Undead_Reincarnate takes nothing returns nothing
    set gg_trg_Undead_Reincarnate = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Undead_Reincarnate, EVENT_PLAYER_UNIT_SUMMON )
    call TriggerAddCondition( gg_trg_Undead_Reincarnate, Condition( function Trig_Undead_Reincarnate_Conditions ) )
    call TriggerAddAction( gg_trg_Undead_Reincarnate, function Trig_Undead_Reincarnate_Actions )
endfunction

I hope this can be a solution.
09-03-2008, 10:04 PM#11
Strilanc
I'm assuming you've put BJDebugMsg all over the place and confirmed all the code is running when expected? If not, do that. For all we know the event might not be firing.
09-04-2008, 11:52 PM#12
Karawasa
Yes, I have confirmed that everything works except the part after the TSA(i.e. the move).

@moyack: I tried that, but it never fires :(.
09-04-2008, 11:54 PM#13
moyack
One question.... what is the exact purpose of the TSA, why to wait to give the order??
09-05-2008, 03:16 AM#14
Karawasa
Quote:
Originally Posted by moyack
One question.... what is the exact purpose of the TSA, why to wait to give the order??

Without the TSA the move order never gets carried out on reincarnation. The two other calls always work though(as neither is a command order). Thus I believe the TSA delays the command order until the unit is ready to receive orders(immediately after reincarnating is too soon I guess).
09-05-2008, 04:58 AM#15
Deaod
have you tried changing the timeout of the timer to 0.2?