HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Why this chain shadow strike leaks?

12-07-2006, 07:22 PM#1
GALLED
Hello. here is my code:

Collapse JASS:
function Trig_Daga_Conditions takes nothing returns boolean
    return ( GetSpellAbilityId() == 'A0D6' )
endfunction

function Trig_Daga_Actions takes nothing returns nothing
local unit u = GetTriggerUnit()
local unit prev
local unit target = GetSpellTargetUnit()
local integer l = GetUnitAbilityLevel(u,'A0D6')
local integer targetnum=1+(l*2)
local real x
local real y
local group alltarget = CreateGroup()
local group g
local unit j
local integer cur=0
local integer dmg=0
local unit d
local timer t
set prev = u
loop
    set cur=cur+1
    exitwhen cur>targetnum
    call GroupAddUnit(alltarget,target)
    set x = GetUnitX(prev) 
    set y = GetUnitY(prev)
    set dmg = ((targetnum - l)*(l-1))+cur
    set d = CreateUnit(GetOwningPlayer(u),dunit(),x,y,0)
    call UnitAddAbility(d,'A0D4')
    call SetUnitAbilityLevel(d,'A0D4',dmg)
    call IssueTargetOrder(d,"shadowstrike",target)
    call UnitApplyTimedLife(d,'BTLF', 1.5)
    set t  =CreateTimer()        
    call TimerStart(t,5,false,null)
    loop
        exitwhen (GetUnitAbilityLevel(target,'B02J')>0) or (GetUnitState(target,UNIT_STATE_LIFE)<=0.405) or (TimerGetRemaining(t)<=0)
        call TriggerSleepAction(0.18)
    endloop
    call DestroyTimer(t)
    if (GetUnitAbilityLevel(target,'B02J')<=0) and (GetUnitState(target,UNIT_STATE_LIFE)>0.405) then
        set cur = targetnum+1            
    endif
    if(cur<targetnum)then
    set prev = target
    set x = GetUnitX(prev) 
    set y = GetUnitY(prev)
    set g = CreateGroup()
    call GroupEnumUnitsInRange(g,x,y,700,null)
    loop
        set target = FirstOfGroup(g)
        call GroupRemoveUnit(g,target)
        exitwhen((IsUnitAlly(target,GetOwningPlayer(u))==false) and (GetUnitState(target, UNIT_STATE_LIFE) > 0.405) and (IsUnitType(target, UNIT_TYPE_STRUCTURE)==false) and (IsUnitInGroup(target,alltarget)==false) and (IsUnitType(target,UNIT_TYPE_MAGIC_IMMUNE)==false) ) or target==null
    endloop
    if (target==null) then
        set cur = targetnum+1            
    endif    
    call DestroyGroup(g)
    set d = CreateUnit(GetOwningPlayer(u),dunit(),x,y,0)
    call UnitAddAbility(d,'A0D4')
    call SetUnitAbilityLevel(d,'A0D4',dmg)
    call IssueTargetOrder(d,"shadowstrike",target)
    call UnitApplyTimedLife(d,'BTLF', 1.5) 
    endif
endloop
set t = null
set u = null
set prev = null
set target = null
call DestroyGroup(alltarget)
set alltarget = null
set g = null
set j = null
set d = null
endfunction

//===========================================================================
function InitTrig_Daga takes nothing returns nothing
    set gg_trg_Daga = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Daga, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Daga, Condition( function Trig_Daga_Conditions ) )
    call TriggerAddAction( gg_trg_Daga, function Trig_Daga_Actions )
endfunction

And this leaks the first time, why??

Thanks in advance
12-07-2006, 07:28 PM#2
Vexorian
You mean it lags? And if it only lags the first time it is mostly an ability/model loading issue
12-07-2006, 08:32 PM#3
wyrmlord
Quote:
Originally Posted by GALLED
Collapse JASS:
call TriggerSleepAction(0.18)

Just letting you know, the minimum time TriggerSleepAction can do is .27 (I think, I know it's somewhere around there) If your spell is lagging the first time, you should probably preload all the models used in the spell, a good place to do this is in the InitTrig function. Example:
Collapse JASS:
call Preload("") //Put the file path for each model inside quotes.

So for this function, you'd probably want to preload the missle art that is used in Shadow Strike. I don't have WE open right now so I can't give you the exact path, but remember to make sure to type each \ in the filepath as \\
12-07-2006, 08:43 PM#4
GALLED
Ah ok!

So triggersleepaction to 0.27 and preload the model.

Well... now the code is here and yet leaks the first time (and a big lag!!)...

Collapse JASS:
//--------------------------------------------------------------------
//Configuracion del spell
//--------------------------------------------------------------------
constant function daga_spell takes nothing returns integer
    return 'A0D6' //rawcode de la habilidad
endfunction

constant function daga_dummy takes nothing returns integer
    return 'A0D4' //rawcode de la habilidad
endfunction

constant function daga_buff takes nothing returns integer
    return 'B02J' //rawcode de la habilidad
endfunction

function Trig_Daga_Conditions takes nothing returns boolean
    return ( GetSpellAbilityId() == daga_spell() )
endfunction

function Trig_Daga_Actions takes nothing returns nothing
local unit u = GetTriggerUnit()
local unit prev
local unit target = GetSpellTargetUnit()
local integer l = GetUnitAbilityLevel(u,daga_spell())
local integer targetnum=1+(l*2)
local real x
local real y
local group alltarget = CreateGroup()
local group g
local unit j
local integer cur=0
local integer dmg=0
local unit d
local timer t
set prev = u
loop
    set cur=cur+1
    exitwhen cur>targetnum
    call GroupAddUnit(alltarget,target)
    set x = GetUnitX(prev) 
    set y = GetUnitY(prev)
    set dmg = ((targetnum - l)*(l-1))+cur
    set d = CreateUnit(GetOwningPlayer(u),dunit(),x,y,0)
    call UnitAddAbility(d,daga_dummy())
    call SetUnitAbilityLevel(d,daga_dummy(),dmg)
    call IssueTargetOrder(d,"shadowstrike",target)
    call UnitApplyTimedLife(d,'BTLF', 1.5)
    set t  =CreateTimer()        
    call TimerStart(t,5,false,null)
    loop
        exitwhen (GetUnitAbilityLevel(target,daga_buff())>0) or (GetUnitState(target,UNIT_STATE_LIFE)<=0.405) or (TimerGetRemaining(t)<=0)
        call TriggerSleepAction(0.27)
    endloop
    call DestroyTimer(t)
    if (GetUnitAbilityLevel(target,daga_buff())<=0) and (GetUnitState(target,UNIT_STATE_LIFE)>0.405) then
        set cur = targetnum+1            
    endif
    if(cur<targetnum)then
    set prev = target
    set x = GetUnitX(prev) 
    set y = GetUnitY(prev)
    set g = CreateGroup()
    call GroupEnumUnitsInRange(g,x,y,700,null)
    loop
        set target = FirstOfGroup(g)
        call GroupRemoveUnit(g,target)
        exitwhen((IsUnitAlly(target,GetOwningPlayer(u))==false) and (GetUnitState(target, UNIT_STATE_LIFE) > 0.405) and (IsUnitType(target, UNIT_TYPE_STRUCTURE)==false) and (IsUnitInGroup(target,alltarget)==false) and (IsUnitType(target,UNIT_TYPE_MAGIC_IMMUNE)==false) ) or target==null
    endloop
    if (target==null) then
        set cur = targetnum+1            
    endif    
    call DestroyGroup(g)
    set d = CreateUnit(GetOwningPlayer(u),dunit(),x,y,0)
    call UnitAddAbility(d,daga_dummy())
    call SetUnitAbilityLevel(d,daga_dummy(),dmg)
    call IssueTargetOrder(d,"shadowstrike",target)
    call UnitApplyTimedLife(d,'BTLF', 1.5) 
    endif
endloop
set t = null
set u = null
set prev = null
set target = null
call DestroyGroup(alltarget)
set alltarget = null
set g = null
set j = null
set d = null
endfunction

//===========================================================================
function InitTrig_Daga takes nothing returns nothing
    set gg_trg_Daga = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Daga, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Daga, Condition( function Trig_Daga_Conditions ) )
    call TriggerAddAction( gg_trg_Daga, function Trig_Daga_Actions )
    call Preload("Abilities\\Spells\\NightElf\\CorrosiveBreath\\CorrosiveBreathMissile.mdl")
endfunction
12-07-2006, 08:55 PM#5
wyrmlord
You can just do TriggerSleepAction at 0. Basically if you give the function a value lower than its minimum, it will wait the minimum time instead of its normal time. I just use 0 whenever I want to use the minimum time.
12-07-2006, 09:07 PM#6
moyack
Quote:
Originally Posted by wyrmlord
Just letting you know, the minimum time TriggerSleepAction can do is .27 (I think, I know it's somewhere around there)
Actually is 0.1, you can check it by the bj_POLLED_WAIT_INTERVAL constant.

Quote:
Originally Posted by GALLED
Well... now the code is here and yet leaks the first time (and a big lag!!)...
Ahhh, your lag is caused by the dummy unit, in order to fix it, add to the InitTrig_Daga function these lines:

Collapse JASS:
function InitTrig_Daga takes nothing returns nothing
    local unit d = CreateUnit(Player(15),dunit(),0,0,0)
    call RemoveUnit(d)
    set gg_trg_Daga = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Daga, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Daga, Condition( function Trig_Daga_Conditions ) )
    call TriggerAddAction( gg_trg_Daga, function Trig_Daga_Actions )
    call Preload("Abilities\\Spells\\NightElf\\CorrosiveBreath\\CorrosiveBreathMissile.mdl")
    set d = null
endfunction
12-07-2006, 09:32 PM#7
GALLED
Well.. i'm put in the code the last post's sugerency and nothing... the leak is there like a fucking virus or something :(
12-07-2006, 09:35 PM#8
PandaMine
Yes its called first cast lag whenever you use a model that hasn't been loaded/used before. You need to Proload the model as moyack has said (or have the game lag the first time you cast the spell). Its propably smarter though to preload the model in a sperate trigger that fire at map initiation and then destroy the trigger when it fires, since once the model is preloaded you no longer need the trigger (you should also preload all other models in that trigger)
12-08-2006, 03:11 AM#9
GALLED
Well i'm uselessly trying to preload the model in the map inicialization. So i'm created (despairly) this function that can make me avoid the lag:

Collapse JASS:
function preload_ability_1 takes integer hab, string order returns nothing
local unit u = CreateUnit(Player(0),'Hpal',0,0,0) 
local unit v = CreateUnit(Player(6),'nfro',0,0,0)
call UnitAddAbility(u,hab)
call SetUnitAbilityLevel(u,hab,1)
call IssueTargetOrder(u,order,v)
call TriggerSleepAction(0.1)
call RemoveUnit(u)
call RemoveUnit(v)
set u = null
set v = null
endfunction
12-08-2006, 04:07 AM#10
PipeDream
Quote:
Actually is 0.1, you can check it by the bj_POLLED_WAIT_INTERVAL constant.

bj_POLLED_WAIT_INTERVAL is just the minimum argument that the Blizzard.j PolledWait() call TriggerSleepAction() with. There's no minimum time; the behavior of TriggerSleepAction is random and dependent on context. For rule of thumb I'd say Wyrmlord's .27 is a reasonable guess.

Some measurements I did awhile ago ended up with this for averages:

x axis is argument to TriggerSleepAction, y axis is average actual delay, over a hundredish trials in single player.
---
Are you still getting first cast lag?
12-08-2006, 07:24 AM#11
PandaMine
So were the trials done with the exact same script over and over again or in different situations?
12-09-2006, 11:44 PM#12
GALLED
Quote:
Originally Posted by PipeDream
bj_POLLED_WAIT_INTERVAL is just the minimum argument that the Blizzard.j PolledWait() call TriggerSleepAction() with. There's no minimum time; the behavior of TriggerSleepAction is random and dependent on context. For rule of thumb I'd say Wyrmlord's .27 is a reasonable guess.

Some measurements I did awhile ago ended up with this for averages:

x axis is argument to TriggerSleepAction, y axis is average actual delay, over a hundredish trials in single player.
---
Are you still getting first cast lag?

Well i'm call the function that i'm write above in the Map Inicialization and I has no lag. But it's so rare, because i'm make a similar spell (chain acidbomb) and i have no first cast lag.
12-10-2006, 07:02 AM#13
xombie
Lol, this is kind of pointless now but I did a rough test (it could be different in more extreme situations) but I got a more consistant return of 0.200 for TriggerSleepAction. What I did was create a timer that would run every 0.01 seconds, and if a boolean 'b' was false, it would set a real to 0.00. If 'b' was true, it would add 0.01 to the real, hence adding 0.01 to a real every 0.01 seconds at a designated period. I set the boolean equal to TRUE (to initiate the counting) and then did a TriggerSleepAction(0) and then set the boolean to FALSE, stopping the counter. In most results, the real ended up at 0.200, assuming that setting the boolean to FALSE after the sleep action was instant. (I had absolutly nothing in the map, but it did show as inconsistant, so don't rely on TriggerSleepAction ever!)

Update: After further trials of TriggerSleepAction( 0.1 and higher ) I found that it gets even less consistant. Wow, does this function ever suck! Further analysis showed that PolledWait is no better. Please for the love of GOD, never use these functions if you care about your babies!
12-10-2006, 07:15 AM#14
PipeDream
yep. the only appropriate use of TriggerSleepAction is TriggerSleepAction(0.), and even then chances are you're probably just being lazy. PolledWait for larger times is OK too, although you'll want to have the skip time at 0.

I've seen one map where TriggerSleepAction now and then would bug out around the thirty minute mark into the game and stop working. It would always return immediately, resulting in hilarity.