Имеется код для одной способности включающая в себя, как активный режим, так и пассивный.
Задача состоит в оптимизации кода, преимущественно для активного режима, где герой перемещается (SetUnitPosition) с мелкой периодичностью.
Использую JNGP.
Функции, что используются часто (в нестандартном коде карты)
globals
group FilterGroup=null
player FilterPlayer=null
boolean FilterVisible=false
boolean RegisterDamage=true
endglobals

function UnitDamageTargetEx takes unit u, unit t, real d, boolean a, boolean r, attacktype at, damagetype dt, weapontype wt returns nothing
set RegisterDamage=false
call UnitDamageTarget(u,t,d,a,r,at,dt,wt)
set RegisterDamage=true
endfunction

function GroupFilter takes nothing returns boolean
local boolean b=((not IsUnitType(GetFilterUnit(),UNIT_TYPE_DEAD)) and GetUnitAbilityLevel(GetFilterUnit(),'Aloc')==0)
if FilterGroup!=null then
    set b=(b and not IsUnitInGroup(GetFilterUnit(),FilterGroup))
endif
if FilterPlayer!=null then
    set b=(b and IsUnitEnemy(GetFilterUnit(),FilterPlayer))
    if FilterVisible then
        set b=(b and IsUnitVisible(GetFilterUnit(),FilterPlayer) and not IsUnitFogged(GetFilterUnit(),FilterPlayer))
    endif
endif
return b
endfunction

function TextTag takes string s, real sz, unit u, real ho, integer r, integer g, integer b, real xv, real yv, real f, real l returns nothing
local texttag tt=CreateTextTag()
call SetTextTagText(tt,s,sz)
call SetTextTagPos(tt,GetUnitX(u),GetUnitY(u),ho)
call SetTextTagColor(tt,r,g,b,255)
call SetTextTagVelocity(tt,xv,yv)
call SetTextTagVisibility(tt,true)
call SetTextTagFadepoint(tt,f)
call SetTextTagLifespan(tt,l)
call SetTextTagPermanent(tt,false)
call SetTextTagSuspended(tt,false)
set tt=null
set u=null
set s=null
endfunction
Сам триггер способности...
globals
constant integer Custom_SkillW_Ability='A001'
constant integer Custom_SkillW_Ability_B='A006'
constant integer Custom_SkillW_Buff_B='B000'
constant integer Custom_SkillW_Ability_C='A00O'
constant integer Custom_SkillW_Ability_D='A008
constant integer Custom_SkillW_Ability_E='A007'
constant integer Custom_SkillW_HeroID_A='N000'
constant integer Custom_SkillW_HeroID_B='N001'

constant real Custom_SkillW_A_Bonus_Base=.7
constant real Custom_SkillW_A_Bonus_PerLvl=.3

constant real Custom_SkillW_C_Chance_Evade_Base=10.
constant real Custom_SkillW_C_Chance_Evade_PerLvl=.0
constant real Custom_SkillW_C_Chance_Evade_Stat_Base=.01
constant real Custom_SkillW_C_Chance_Evade_Stat_PerLvl=.01
constant real Custom_SkillW_C_Chance_Crit_Base=10.
constant real Custom_SkillW_C_Chance_Crit_PerLvl=.0
constant real Custom_SkillW_C_Chance_Crit_Stat_Base=.01
constant real Custom_SkillW_C_Chance_Crit_Stat_PerLvl=.01
constant real Custom_SkillW_C_Multi_Crit_Min_Base=1.5
constant real Custom_SkillW_C_Multi_Crit_Min_PerLvl=.0
constant real Custom_SkillW_C_Multi_Crit_Max_Base=3.
constant real Custom_SkillW_C_Multi_Crit_Max_PerLvl=.0

integer Custom_SkillW_C_StringMaxer
string array Custom_SkillW_C_Strings

constant real Custom_SkillW_E_Interval=.0125
constant real Custom_SkillW_E_Time_A=3.
constant real Custom_SkillW_E_Time_B=.5
constant real Custom_SkillW_E_AoE_A=600.+25.
constant real Custom_SkillW_E_AoE_B=.0
constant real Custom_SkillW_E_Bonus_Dmg_Base=.0
constant real Custom_SkillW_E_Bonus_Dmg_PerLvl=.0
constant real Custom_SkillW_E_Bonus_Stat_Dmg_Base=1.
constant real Custom_SkillW_E_Bonus_Stat_Dmg_PerLvl=.0

trigger SkillW_A=CreateTrigger()
trigger SkillW_B=CreateTrigger()
trigger SkillW_C=CreateTrigger()
trigger SkillW_D=CreateTrigger()
trigger SkillW_E=CreateTrigger()

integer SkillW_A__MAX=0
unit array SkillW_A__Unit
real array SkillW_A__Bonus

integer SkillW_D__MAX=0
unit array SkillW_D__Source
unit array SkillW_D__Target
effect array SkillW_D__Effect
trigger array SkillW_D__Trigger

timer SkillW_E__Timer=CreateTimer()
integer SkillW_E__MAX=0
unit array SkillW_E__Unit
unit array SkillW_E__Target
real array SkillW_E__Time
real array SkillW_E__Area
trigger array SkillW_E__Trigger
real array SkillW_E__Bonus
endglobals

//===========================================================================
function SkillW_A_Func_GetUnitIndex takes unit u returns integer
local integer index=0
loop
    exitwhen index==SkillW_A__MAX
    if u==SkillW_A__Unit[index] then
        return index
    endif
    set index=index+1
endloop
set u=null
return -1
endfunction

function SkillW_A_Func_Adder takes unit u, integer index returns nothing
local real level=I2R(GetUnitAbilityLevel(u,Custom_SkillW_Ability))
local real r=I2R(GetHeroLevel(u))*(Custom_SkillW_A_Bonus_Base+Custom_SkillW_A_Bonus_PerLvl*(level-1))
call SetHeroAgi(u,GetHeroAgi(u,false)-R2I(SkillW_A__Bonus[index]),true)
call SetHeroAgi(u,GetHeroAgi(u,false)+R2I(r),true)
if GetLocalPlayer()==GetOwningPlayer(u) then
    call TextTag("+"+R2SW(r-SkillW_A__Bonus[index],1,1),.023,u,250.,0,255,0,-0.04,.0,2,3)
endif
set SkillW_A__Bonus[index]=r
set u=null
endfunction

function SkillW_A_Func_Condition takes nothing returns boolean
local integer index=SkillW_A_Func_GetUnitIndex(GetTriggerUnit())
if GetLearnedSkill()==Custom_SkillW_Ability and ( not IsUnitIllusion(GetTriggerUnit()) ) then
    if index==-1 then
        set index=SkillW_A__MAX
        set SkillW_A__Unit[SkillW_A__MAX]=GetTriggerUnit()
        set SkillW_A__Bonus[SkillW_A__MAX]=.0
        call TriggerRegisterUnitEvent(SkillW_B, GetTriggerUnit(), EVENT_UNIT_HERO_LEVEL)
        call TriggerRegisterUnitEvent(SkillW_C, GetTriggerUnit(), EVENT_UNIT_DAMAGED)
        call TriggerRegisterUnitEvent(SkillW_E, GetTriggerUnit(), EVENT_UNIT_SPELL_EFFECT)
        set SkillW_A__MAX=SkillW_A__MAX+1
    endif
    call SkillW_A_Func_Adder(GetTriggerUnit(),index)
    return true
endif
return false
endfunction
//===========================================================================
function SkillW_B_Func_Condition takes nothing returns boolean
local integer index=SkillW_A_Func_GetUnitIndex(GetTriggerUnit())
if GetUnitAbilityLevel(GetTriggerUnit(),Custom_SkillW_Ability)!=0 then
    call SkillW_A_Func_Adder(GetTriggerUnit(),index)
    return true
endif
return false
endfunction

//===========================================================================
function SkillW_C_Func_Condition takes nothing returns boolean
local real level=I2R(GetUnitAbilityLevel(GetTriggerUnit(),Custom_SkillW_Ability))
local real stat=I2R(GetHeroAgi(GetTriggerUnit(),true))
local real r=(Custom_SkillW_C_Chance_Evade_Base+Custom_SkillW_C_Chance_Evade_PerLvl*(level-1))+stat*(Custom_SkillW_C_Chance_Evade_Stat_Base+Custom_SkillW_C_Chance_Evade_Stat_PerLvl*(level-1))
if GetUnitAbilityLevel(GetTriggerUnit(),Custom_SkillW_Ability)!=0 and GetRandomReal(0.,100.)<=r and GetEventDamage()>1. and GetEventDamageSource()!=GetTriggerUnit() then
    call TextTag(Custom_SkillW_C_Strings[GetRandomInt(0,Custom_SkillW_C_StringMaxer)],0.022,GetTriggerUnit(),100.,255,0,0,.0,.06,1,2)
    call SetWidgetLife(GetTriggerUnit(),GetWidgetLife(GetTriggerUnit())+GetEventDamage())
    return true
endif
return false
endfunction

//===========================================================================
function SkillW_D_Func_GetTriggerIndex takes trigger t returns integer
    local integer index=0
    loop
        exitwhen index==SkillW_D__MAX
        if t==SkillW_D__Trigger[index] then
            set t=null
            return index
        endif
        set index=index+1
    endloop
    set t=null
    return -1
endfunction

function SkillW_D_Func_GetSourceIndex takes unit u returns integer
    local integer index=0
    loop
        exitwhen index==SkillW_D__MAX
        if u==SkillW_D__Source[index] then
            set u=null
            return index
        endif
        set index=index+1
    endloop
    set u=null
    return -1
endfunction

function SkillW_D_Func_Second takes nothing returns boolean
    local trigger tr=GetTriggeringTrigger()
    local unit u=GetEventDamageSource()
    local unit t=GetTriggerUnit()
    local real level=I2R(GetUnitAbilityLevel(u,Custom_SkillW_Ability))
    local real min=Custom_SkillW_C_Multi_Crit_Min_Base+Custom_SkillW_C_Multi_Crit_Min_PerLvl*(level-1)
    local real max=Custom_SkillW_C_Multi_Crit_Max_Base+Custom_SkillW_C_Multi_Crit_Max_PerLvl*(level-1)
    local real dmg=GetEventDamage()*GetRandomReal(min,max)
    local integer index=SkillW_D_Func_GetTriggerIndex(tr)
    local boolean b=false
    if GetTriggerEventId()==EVENT_UNIT_DAMAGED then
        if GetEventDamage()>1. and u==SkillW_D__Source[index] and t==SkillW_D__Target[index] and RegisterDamage then
            set b=true
            call DisableTrigger(tr)
            call QueueUnitAnimation( u, "stand, ready" )
            call TextTag(I2S(R2I(dmg))+"!",.023,u,0.,255,0,0,.0,.04,2,3)
            call UnitDamageTargetEx(u,t,dmg-GetEventDamage(),true,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_NORMAL,null)
            call DestroyEffect(AddSpecialEffectTarget( GetAbilityEffectById(Custom_SkillW_Ability,EFFECT_TYPE_MISSILE,1), t, "chest"))
        endif
    else
        set b=true
        call DisableTrigger(tr)
    endif
    if b then
        call DestroyTrigger(tr)
        call DestroyEffect(SkillW_D__Effect[index])
        set SkillW_D__MAX=SkillW_D__MAX-1
        set SkillW_D__Source[index]=SkillW_D__Source[SkillW_D__MAX]
        set SkillW_D__Target[index]=SkillW_D__Target[SkillW_D__MAX]
        set SkillW_D__Effect[index]=SkillW_D__Effect[SkillW_D__MAX]
        set SkillW_D__Trigger[index]=SkillW_D__Trigger[SkillW_D__MAX]
        set SkillW_D__Source[SkillW_D__MAX]=null
        set SkillW_D__Target[SkillW_D__MAX]=null
        set SkillW_D__Effect[SkillW_D__MAX]=null
        set SkillW_D__Trigger[SkillW_D__MAX]=null
    endif
    set t=null
    set u=null
    set tr=null
    return false
endfunction

function SkillW_D_Func_Condition takes nothing returns boolean
    local unit u=GetAttacker()
    local unit t=GetTriggerUnit()
    local integer index=SkillW_D_Func_GetSourceIndex(u)
    local real level=I2R(GetUnitAbilityLevel(u,Custom_SkillW_Ability))
    local real stat=I2R(GetHeroAgi(u,true))
    local real r=(Custom_SkillW_C_Chance_Crit_Base+Custom_SkillW_C_Chance_Crit_PerLvl*(level-1))+stat*(Custom_SkillW_C_Chance_Crit_Stat_Base+Custom_SkillW_C_Chance_Crit_Stat_PerLvl*(level-1))
    if level!=0 and (GetRandomReal(.0,100.)<=r or GetUnitTypeId(u)==Custom_SkillW_HeroID_B) and ( not IsUnitIllusion(GetAttacker()) ) and index==-1 then
        call SetUnitAnimation( u, "slam" )
        set SkillW_D__Source[SkillW_D__MAX]=u
        set SkillW_D__Target[SkillW_D__MAX]=t
        set SkillW_D__Trigger[SkillW_D__MAX]=CreateTrigger()
        set SkillW_D__Effect[SkillW_D__MAX]=AddSpecialEffectTarget( GetAbilityEffectById(Custom_SkillW_Ability,EFFECT_TYPE_MISSILE,0), u, "hand, left")
        call TriggerRegisterDeathEvent( SkillW_D__Trigger[SkillW_D__MAX], t)
        call TriggerRegisterUnitEvent( SkillW_D__Trigger[SkillW_D__MAX], t, EVENT_UNIT_DAMAGED)
        call TriggerRegisterDeathEvent( SkillW_D__Trigger[SkillW_D__MAX], u)
        call TriggerRegisterTimerEvent( SkillW_D__Trigger[SkillW_D__MAX], 2.,false)
        call TriggerAddCondition( SkillW_D__Trigger[SkillW_D__MAX], Condition( function SkillW_D_Func_Second) )
        set SkillW_D__MAX=SkillW_D__MAX+1
        set t=null
        set u=null
        return true
    endif
    set t=null
    set u=null
    return false
endfunction

//===========================================================================
function SkillW_E_Func_GetTriggerIndex takes trigger t returns integer
local integer index=0
loop
    exitwhen index==SkillW_E__MAX
    if t==SkillW_E__Trigger[index] then
        set t=null
        return index
    endif
    set index=index+1
endloop
set t=null
    return index
endfunction

function SkillW_E_Func_GetUnitIndex takes unit u returns integer
local integer index=0
loop
    exitwhen index==SkillW_E__MAX
    if u==SkillW_E__Unit[index] then
        set u=null
        return index
    endif
    set index=index+1
endloop
set u=null
    return index
endfunction

function SkillW_E_Func_TargetActions takes nothing returns boolean
local trigger tr=GetTriggeringTrigger()
local integer index=SkillW_E_Func_GetTriggerIndex(tr)
local unit u=SkillW_E__Unit[index]
local unit t=SkillW_E__Target[index]
local real stat=I2R(GetHeroAgi(u,true))
local real lvl=I2R(GetUnitAbilityLevel(u,Custom_SkillW_Ability)-1)
local real bd=(Custom_SkillW_E_Bonus_Dmg_Base+Custom_SkillW_E_Bonus_Dmg_PerLvl*lvl)+(stat*(Custom_SkillW_E_Bonus_Stat_Dmg_Base+Custom_SkillW_E_Bonus_Stat_Dmg_PerLvl*lvl))
local boolean b=false
if GetTriggerEventId()==EVENT_UNIT_ATTACKED then
    if GetTriggerUnit()==t and GetAttacker()==u then
        if IsUnitType(t,UNIT_TYPE_HERO) then
            set SkillW_E__Bonus[index]=bd
            set STATS_UNIT=u
            set STATS_VALUE=SkillW_E__Bonus[index]
            set STATS_ADDER=0
            call TriggerEvaluate(gg_trg_Stats)
        else
            call UnitAddAbility(u,Custom_SkillW_Ability_E)
            call SetUnitAbilityLevel(u,Custom_SkillW_Ability_E,R2I(lvl+1))
        endif
        call SetUnitAnimation( u, "slam" )
        call TriggerRegisterUnitEvent( SkillW_E__Trigger[index], t, EVENT_UNIT_DAMAGED)
    else
        call DisableTrigger(tr)
        set b=true
    endif
elseif GetTriggerEventId()==EVENT_UNIT_DAMAGED then
    if GetTriggerUnit()==t and GetEventDamageSource()==u and RegisterDamage then
        call DisableTrigger(tr)
        set b=true
    endif
else
    call DisableTrigger(tr)
    set b=true
endif
if b then
    call UnitRemoveAbility(u,Custom_SkillW_Ability_E)
    set STATS_UNIT=u
    set STATS_VALUE=-SkillW_E__Bonus[index]
    set STATS_ADDER=0
    call TriggerEvaluate(gg_trg_Stats)
    set SkillW_E__Target[index]=null
    call DestroyTrigger(tr)
    set SkillW_E__Trigger[index]=null
endif
set tr=null
set u=null
set t=null
    return false
endfunction

function SkillW_E_Func_AreaActions takes integer index returns nothing
local group g=CreateGroup()
local player p=GetOwningPlayer(SkillW_E__Unit[index])
local unit t
local real x=GetUnitX(SkillW_E__Unit[index])
local real y=GetUnitY(SkillW_E__Unit[index])
local real angle
local integer i=0
set FilterPlayer=p
set FilterVisible=true
call GroupEnumUnitsInRange(g,x,y,SkillW_E__Area[index],Filter(function GroupFilter))
set FilterPlayer=null
set FilterVisible=false
loop
    set t=FirstOfGroup(g)
    exitwhen t==null
    if GetRandomInt(0,i)==0 then
        set i=i+1
        set SkillW_E__Target[index]=t
    endif
    call GroupRemoveUnit(g,t)
endloop
if SkillW_E__Target[index]!=null then
    if GetUnitTypeId(SkillW_E__Unit[index])==Custom_SkillW_HeroID_A then
        call UnitAddAbility(SkillW_E__Unit[index],Custom_SkillW_Ability_C)
        call UnitRemoveAbility(SkillW_E__Unit[index],Custom_SkillW_Ability_C)
    endif
    call SetUnitPathing(SkillW_E__Unit[index],false)
    call SetUnitTimeScale( SkillW_E__Unit[index], 3)
    set angle=GetRandomReal(.0,bj_PI*2)
    set x=GetUnitX(SkillW_E__Target[index])+50*Cos(angle)
    set y=GetUnitY(SkillW_E__Target[index])+50*Sin(angle)
    call DestroyTrigger(SkillW_E__Trigger[index])
    call SetUnitPosition(SkillW_E__Unit[index],x,y)
    call SetUnitFacing(SkillW_E__Unit[index],bj_RADTODEG*Atan2(GetUnitY(SkillW_E__Target[index])-GetUnitY(SkillW_E__Unit[index]),GetUnitX(SkillW_E__Target[index])-GetUnitX(SkillW_E__Unit[index])))
    call IssueInstantTargetOrder(SkillW_E__Unit[index],"attack",SkillW_E__Target[index],SkillW_E__Target[index])
    set SkillW_E__Trigger[index]=CreateTrigger()
    call TriggerRegisterDeathEvent( SkillW_E__Trigger[index], SkillW_E__Target[index])
    call TriggerRegisterUnitEvent( SkillW_E__Trigger[index], SkillW_E__Target[index], EVENT_UNIT_ATTACKED)
    call TriggerRegisterDeathEvent( SkillW_E__Trigger[index], SkillW_E__Unit[index])
    call TriggerRegisterTimerEvent( SkillW_E__Trigger[index], 0.25, false)
    call TriggerAddCondition( SkillW_E__Trigger[index], Condition( function SkillW_E_Func_TargetActions) )
else
    if GetUnitTypeId(SkillW_E__Unit[index])==Custom_SkillW_HeroID_B then
        call UnitAddAbility(SkillW_E__Unit[index],Custom_SkillW_Ability_D)
        call UnitRemoveAbility(SkillW_E__Unit[index],Custom_SkillW_Ability_D)
    endif
    call SetUnitPathing(SkillW_E__Unit[index],true)
    call SetUnitTimeScale( SkillW_E__Unit[index], 1)
endif
call DestroyGroup(g)
set p=null
set t=null
set g=null
endfunction

function SkillW_E_Func_Periodic takes nothing returns nothing
local integer index=0
loop
    exitwhen index==SkillW_E__MAX
    if SkillW_E__Time[index]>.0 and (not IsUnitType(SkillW_E__Unit[index],UNIT_TYPE_DEAD)) then
        set SkillW_E__Time[index]=SkillW_E__Time[index]-Custom_SkillW_E_Interval
        if SkillW_E__Target[index]==null then
            call SkillW_E_Func_AreaActions(index)
        endif
    else
        call UnitRemoveAbility(SkillW_E__Unit[index],Custom_SkillW_Ability_E)
        set STATS_UNIT=SkillW_E__Unit[index]
        set STATS_VALUE=-SkillW_E__Bonus[index]
        set STATS_ADDER=0
        call TriggerEvaluate(gg_trg_Stats)
        if GetUnitTypeId(SkillW_E__Unit[index])==Custom_SkillW_HeroID_B then
            call UnitAddAbility(SkillW_E__Unit[index],Custom_SkillW_Ability_D)
            call UnitRemoveAbility(SkillW_E__Unit[index],Custom_SkillW_Ability_D)
        endif
        call SetUnitPathing(SkillW_E__Unit[index],true)
        call SetUnitTimeScale( SkillW_E__Unit[index], 1)
        call TriggerExecute(SkillW_E__Trigger[index])
        call SetUnitAnimation( SkillW_E__Unit[index], "stand" )
        set SkillW_E__MAX=SkillW_E__MAX-1
        set SkillW_E__Unit[index]=SkillW_E__Unit[SkillW_E__MAX]
        set SkillW_E__Time[index]=SkillW_E__Time[SkillW_E__MAX]
        set SkillW_E__Area[index]=SkillW_E__Area[SkillW_E__MAX]
        set SkillW_E__Target[index]=SkillW_E__Target[SkillW_E__MAX]
        set SkillW_E__Trigger[index]=SkillW_E__Trigger[SkillW_E__MAX]
        set SkillW_E__Unit[SkillW_E__MAX]=null
        set SkillW_E__Target[SkillW_E__MAX]=null
        set SkillW_E__Trigger[SkillW_E__MAX]=null
        set SkillW_E__Time[SkillW_E__MAX]=.0
        set SkillW_E__Area[SkillW_E__MAX]=.0
        set index=index-1
        if SkillW_E__MAX==0 then
            call PauseTimer(SkillW_E__Timer)
        endif
    endif
    set index=index+1
endloop
endfunction

function SkillW_E_Func_Condition takes nothing returns boolean
local unit u=GetTriggerUnit()
local integer level=GetUnitAbilityLevel(u,Custom_SkillW_Ability)
local real time=Custom_SkillW_E_Time_A-Custom_SkillW_E_Time_B+(Custom_SkillW_E_Time_B*level)
if GetSpellAbilityId()==Custom_SkillW_Ability then
    if SkillW_E__MAX==0 then
        call TimerStart(SkillW_E__Timer,Custom_SkillW_E_Interval,true,function SkillW_E_Func_Periodic)
    endif
    set BuffSystem_TARGET=u
    set BuffSystem_ID_Ability=Custom_SkillW_Ability_B
    set BuffSystem_ID_Buff=Custom_SkillW_Buff_B
    set BuffSystem_TIME=time
    call TriggerEvaluate(gg_trg_BuffSystem)
    set SkillW_E__Unit[SkillW_E__MAX]=u
    set SkillW_E__Time[SkillW_E__MAX]=time
    set SkillW_E__Area[SkillW_E__MAX]=Custom_SkillW_E_AoE_A-Custom_SkillW_E_AoE_B+(Custom_SkillW_E_AoE_B*level)
    set SkillW_E__Target[SkillW_E__MAX]=null
    set SkillW_E__Trigger[SkillW_E__MAX]=null
    set SkillW_E__MAX=SkillW_E__MAX+1
    set u=null
    return true
endif
set u=null
    return false
endfunction

function SkillW_Func_Init takes nothing returns nothing
local unit u=CreateUnit(Player(15),'u000',0,0,0)
local integer index=0
set Custom_SkillW_C_Strings[0]="Не прошел"
set Custom_SkillW_C_Strings[1]="Увернулся"
set Custom_SkillW_C_Strings[2]="Что-то не так"
set Custom_SkillW_C_Strings[3]="Прошло мимо"
set Custom_SkillW_C_Strings[4]="Забавно..."
set Custom_SkillW_C_StringMaxer=4
loop
    call TriggerRegisterPlayerUnitEvent(SkillW_A,Player(index),EVENT_PLAYER_HERO_SKILL,null)
    call TriggerRegisterPlayerUnitEvent(SkillW_D,Player(index),EVENT_PLAYER_UNIT_ATTACKED,null)
    call SetPlayerAbilityAvailable(Player(index),Custom_SkillW_Ability_E,false)
    set index=index+1
    exitwhen index==16
endloop
call UnitAddAbility(u,Custom_SkillW_Ability)
call UnitAddAbility(u,Custom_SkillW_Ability_B)
call UnitAddAbility(u,Custom_SkillW_Ability_C)
call UnitAddAbility(u,Custom_SkillW_Ability_D)
call UnitAddAbility(u,Custom_SkillW_Ability_E)
call RemoveUnit(u)
set u=null
call TriggerAddCondition(SkillW_A, Condition(function SkillW_A_Func_Condition))
call TriggerAddCondition(SkillW_B, Condition(function SkillW_B_Func_Condition))
call TriggerAddCondition(SkillW_C, Condition(function SkillW_C_Func_Condition))
call TriggerAddCondition(SkillW_D, Condition(function SkillW_D_Func_Condition))
call TriggerAddCondition(SkillW_E, Condition(function SkillW_E_Func_Condition))
endfunction
Custom Stats System v1.0 (not full)
globals
constant real Custom_STATS_RegenInterval=0.125

unit STATS_UNIT=null
real STATS_VALUE=.0
integer STATS_ADDER=0

integer STATS__MAX=0
trigger array STATS__TRIGGER
unit array STATS__UNIT
real array STATS__DMG
real array STATS__AS
real array STATS__DEF
real array STATS__RHP
real array STATS__RMP
real array STATS__HP
real array STATS__MP
endglobals

//===========================================================================
function Stats_Func_Adder takes unit u, integer value, string stat returns nothing
local integer i=0
local integer ii=0
local boolean b=false

if stat=="dmg" then
    loop
        call UnitMakeAbilityPermanent(u,false,STATS_DMG_Ability[i])
        call UnitRemoveAbility(u,STATS_DMG_Ability[i])
        exitwhen i==STATS_DMG_MaxInteger
        set i=i+1
    endloop

    if value>STATS_DMG_MaxValue then
        set value=STATS_DMG_MaxValue
    elseif value<-STATS_DMG_MaxValue then
        set value=-STATS_DMG_MaxValue
    endif

    if value<0 then
        set b=true
        set value=-value
    endif

    if value>0 then
        loop
            exitwhen i<0
            set ii=value/STATS_DMG_Integer[i]
            if ii>0 then
                if b then
                    call UnitAddAbility(u,STATS_DMG_Ability[i])
                    call SetUnitAbilityLevel(u,STATS_DMG_Ability[i],2)
                else
                    call UnitAddAbility(u,STATS_DMG_Ability[i])
                endif
                call UnitMakeAbilityPermanent(u,true,STATS_DMG_Ability[i])
            endif
            set value=value-(ii*STATS_DMG_Integer[i])
            set i=i-1
        endloop
    endif
    
endif
set stat=null
set u=null
endfunction

//===========================================================================
function Stats_Func_GetUnitIndex takes unit u returns integer
local integer index=0
loop
    exitwhen index==STATS__MAX
    if u==STATS__UNIT[index] then
        set u=null
        return index
    endif
    set index=index+1
endloop
set u=null
return -1
endfunction

function Stats_Func_GetTriggerIndex takes trigger t returns integer
local integer index=0
loop
    exitwhen index==STATS__MAX
    if t==STATS__TRIGGER[index] then
        set t=null
        return index
    endif
    set index=index+1
endloop
set t=null
call DisplayTimedTextToPlayer(Player(0),0,0,10.,"|cffff0000ОШИБКА! Искомый триггер не находится в цикле!|r")
return -1
endfunction

function Stats_Func_Regen takes unit u, real rh, real rm returns boolean
local real hp=GetWidgetLife(u)
local real mp=GetUnitState(u,UNIT_STATE_MANA)
if rh>.0 then
    set hp=hp+rh
elseif rh<.0 then
    if (hp-1)>-rh then
        set hp=hp+rh
    else
        set hp=1
    endif
endif
if rm>0. then
    set mp=mp+rm
elseif rm<.0 then
    if mp>-rm then
        set mp=mp+rm
    else
        set mp=0
    endif
endif
call SetWidgetLife(u,hp)
call SetUnitState(u,UNIT_STATE_MANA, mp)
set u=null
return true
endfunction


function Stats_Func_Checker takes nothing returns boolean
local trigger t=GetTriggeringTrigger()
local boolean b=false
local integer index=Stats_Func_GetTriggerIndex(t)

if index!=-1 then
    if GetTriggerEventId()==EVENT_UNIT_DEATH and not IsUnitType(STATS__UNIT[index],UNIT_TYPE_HERO) then
        set b=true
        call DisableTrigger(t)
    else
        if STATS__DMG[index]==0 and STATS__DEF[index]==0 and STATS__AS[index]==0 and STATS__RHP[index]==.0 and STATS__RMP[index]==.0 and STATS__HP[index]==.0 and STATS__MP[index]==.0 then
            set b=true
            call DisableTrigger(t)
        else
            if (STATS__RHP[index]!=0. or STATS__RMP[index]!=0) and (not IsUnitType(STATS__UNIT[index],UNIT_TYPE_DEAD)) then
                call Stats_Func_Regen(STATS__UNIT[index], STATS__RHP[index]*Custom_STATS_RegenInterval, STATS__RMP[index]*Custom_STATS_RegenInterval)
            endif
        endif
    endif
else
    set b=true
    call DisableTrigger(t)
endif

if b then
    call DestroyTrigger(t)
    call Stats_Func_Adder(STATS__UNIT[index],R2I(-STATS__DMG[index]),"dmg")
    call Stats_Func_Adder(STATS__UNIT[index],R2I(-STATS__DEF[index]),"def")
    call Stats_Func_Adder(STATS__UNIT[index],R2I(-STATS__AS[index]),"as")
    set STATS__RHP[index]=.0
    set STATS__RMP[index]=.0
    
    set STATS__MAX=STATS__MAX-1
    set STATS__UNIT[index]=STATS__UNIT[STATS__MAX]
    set STATS__TRIGGER[index]=STATS__TRIGGER[STATS__MAX]
    
    set STATS__DMG[index]=STATS__DMG[STATS__MAX]
    set STATS__DEF[index]=STATS__DEF[STATS__MAX]
    set STATS__AS[index]=STATS__AS[STATS__MAX]
    set STATS__RHP[index]=STATS__RHP[STATS__MAX]
    set STATS__RMP[index]=STATS__RMP[STATS__MAX]
    set STATS__MP[index]=STATS__MP[STATS__MAX]
    set STATS__HP[index]=STATS__HP[STATS__MAX]
    
    set STATS__UNIT[STATS__MAX]=null
    set STATS__TRIGGER[STATS__MAX]=null
    
    set STATS__DMG[STATS__MAX]=.0
    set STATS__DEF[STATS__MAX]=.0
    set STATS__AS[STATS__MAX]=.0
    set STATS__RHP[STATS__MAX]=.0
    set STATS__RMP[STATS__MAX]=.0
    set STATS__MP[STATS__MAX]=.0
    set STATS__HP[STATS__MAX]=.0
endif

set t=null
return false
endfunction

function Stats_Func_Main takes nothing returns boolean
local unit u=STATS_UNIT
local integer index=Stats_Func_GetUnitIndex(u)

if index==-1 then
    set index=STATS__MAX
    set STATS__UNIT[STATS__MAX]=u
    set STATS__TRIGGER[STATS__MAX]=CreateTrigger()
    call TriggerRegisterUnitEvent(STATS__TRIGGER[STATS__MAX],u,EVENT_UNIT_DEATH)
    call TriggerRegisterTimerEvent(STATS__TRIGGER[STATS__MAX],Custom_STATS_RegenInterval,true)
    call TriggerAddCondition(STATS__TRIGGER[STATS__MAX],Condition(function Stats_Func_Checker))
    set STATS__MAX=STATS__MAX+1
endif

if STATS_ADDER==0 then
set STATS__DMG[index]=STATS__DMG[index]+STATS_VALUE
call Stats_Func_Adder(STATS__UNIT[index],R2I(STATS__DMG[index]),"dmg")
endif

set STATS_UNIT=null
set STATS_VALUE=.0
set STATS_ADDER=0
set u=null
return true
endfunction

function STATS_Func_Init takes nothing returns nothing
set gg_trg_Stats=CreateTrigger()
call TriggerAddCondition(gg_trg_Stats, Condition( function Stats_Func_Main))
endfunction
Мое желание оптимизировать на сколько возможно. Увеличение до 0.03125 сек. периода так же входит в оптимизацию, но не могу додумать, как без периода запустить по повторной функцию на поиск цели.
Добавлю еще часть от системы добавления характеристик. На случай возникновения вопроса о системе.
Custom Stats System v1.0 (DMG part)
globals
integer STATS_DMG_MaxValue=0
integer STATS_DMG_MaxInteger=0

integer array STATS_DMG_Ability
integer array STATS_DMG_Integer
endglobals

function STATS_DMG_Func_Init takes nothing returns nothing
local integer index=1
local unit u=CreateUnit(Player(15),'hpea',0,0,0)
set STATS_DMG_Ability[0]='A009'
set STATS_DMG_Ability[1]='A00A'
set STATS_DMG_Ability[2]='A00B'
set STATS_DMG_Ability[3]='A00C'
set STATS_DMG_Ability[4]='A00D'
set STATS_DMG_Ability[5]='A00E'
set STATS_DMG_Ability[6]='A00F'
set STATS_DMG_Ability[7]='A00G'
set STATS_DMG_Ability[8]='A00H'
set STATS_DMG_Ability[9]='A00I'
set STATS_DMG_Ability[10]='A00J'
set STATS_DMG_Ability[11]='A00K'
set STATS_DMG_MaxInteger=11
set STATS_DMG_Integer[0]=1
set STATS_DMG_MaxValue=1
loop
set STATS_DMG_Integer[index]=STATS_DMG_Integer[index-1]*2
set STATS_DMG_MaxValue=STATS_DMG_MaxValue+STATS_DMG_Integer[index]
exitwhen index==STATS_DMG_MaxInteger
set index=index+1
endloop
loop
call UnitAddAbility(u,STATS_DMG_Ability[index])
exitwhen index==0
set index=index-1
endloop
call RemoveUnit(u)
set u=null
endfunction

Кто заинтересован способностью теперь может скачать и протестировать карту с героем.
В карте примере участвуют еще две способности, которые в дальнейшем тоже подвергнутся оптимизации.

SetUnitPosition довольно тяжелая операци, юзайте SetUnitX\Y в конце полета юзай SetUnitPosition для того чтобы юнит не залетел в непроходимое место.
Фильтр просто ужас, ну кто так фильтры делает?
Проверка на 'Aloc', я в ужасе на кой черт проверять на дамми если GropEnumUnitsInRange\Rect не выделяет москитов, тока EnumOfPlayer может пикнуть москитов, остальное не пикает их, на то они и москиты...
Вот как выглядит нормальный фильтр без локалок и прочего
function EnemyFilter takes nothing returns boolean
    set bj_lastFilterUnit = GetFilterUnit( )
    return GetUnitState( bj_lastFilterUnit, UNIT_STATE_LIFE ) > 0.405 and IsUnitEnemy( bj_lastFilterUnit, bj_groupEnumOwningPlayer ) and not( IsUnitType( bj_lastFilterUnit, UNIT_TYPE_MAGIC_IMMUNE ) or IsUnitType( bj_lastFilterUnit, UNIT_TYPE_MECHANICAL ) or IsUnitInvulnerable( bj_lastFilterUnit ) )
endfunction
UnitDamageTargetEx - красиво но нафиг ненужно обводить в отдельную функцию с тучей аргументов + жутко неудобно, 100500 аргументов у функции и фиг знает за что какой от вечает, прямо так UnitDamageTarget, без отдельной функции.
Туча констант, тоже хорошо тока длят наработок, на деле ставь конкретные значения или юзай Difine vjass'a.
`
ОЖИДАНИЕ РЕКЛАМЫ...

Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
28
Buulichkaa, ну если ктото уже юзает её то надо использовать структуры для того чтобы хранить в ней несколько значений
в общем так можно избежать ненужных конфликтов/костылей
4
С юзердатой как-то не по себе...
А по поводу массива целочисленной с индексом боевых единиц - подобие хештаблицы. Читал как-то на хейве, что хештаблицы медленней чем массивы, в силу этого решил начирикать код для способностей.
Но мне до сих пор интересно... читал разок на сия сайте, что уничтожение триггера - хреновая вещь. Но до сих пор не было такого замечания. Далее никто ничего не промолвил про имитацию атаки. Неужто там везде так хорошо?
nvc123:
DazzleFirst, вот тебе имба способ
создаёшь массив интежеров в котором хранятся индексы юнитов
обращение к массиву через хэндл
Отдельное спасибо за такой способ. Как-то своим мозга не смог сообразить.
28
что хештаблицы медленней чем массивы
в 1,5 раза
то есть 2 обращения к массиву медленнее чем 1 обращение к хэшу
DazzleFirst:
уничтожение триггера
не оптимально
создавать триггер ради того чтобы его уничтожить
зачем?
4
создавать триггер ради того чтобы его уничтожить
Так и есть, ибо реагировать на событие EVENT_UNIT_DAMAGED или EVENT_UNIT_ATTACKED может только триггер, а он нужен только единожды - на один удар.
28
EVENT_UNIT_ATTACKED
мало вероятно что ты отлавливаешь лишь 1 атакующего юнита за всю игру
DazzleFirst:
EVENT_UNIT_DAMAGED
единожды за всю игру или единожды для 1 юнита
32
Триггерам можно добавлять 100500 событий и постоянно менять условия и действия, но это муторно, годится для навороченой системы отлова физ урона 1 на всю карту и тому подобное где триггерные баши и криты будут у 100500 юнитов.
Просто удаляем и усе.
4
nvc123: единожды для 1 юнита
quq_CCCP:
навороченной системы отлова физ урона
Что-то подобное хотел сделать, но не вышло из-за уделенного времени, ибо я студентик которых еще поискать надо - ленивый до чертиков.
nvc123:
мало вероятно что ты отлавливаешь лишь 1 атакующего юнита за всю игру
Запамятовал... Верно, многих отлавливаю, но в случае активного режима способности проделывается как раз-таки отлов только одного.
То есть, сначала периодическая функция проверяет есть ли в массиве выбранный враг, если нет, то вызывает функцию SkillW_E_Func_AreaActions, что в свою очередь ищет этого врага и по новой запускает триггер на отлов атаки и урона от Героя. Если триггер на отлов был запущен иначе, чем отлов, то триггер уничтожается и обнуляется, в иных случаях действует по заданному сценарию.
Вот весь секрет триггера на отлов урона и атаки.
30
DazzleFirst, xgm.guru/p/wc3/catch-dmg
При наличии понимания работы варкрафта система пишется за час ленивого написания.
4
Clamp:
DazzleFirst, xgm.guru/p/wc3/catch-dmg
При наличии понимания работы варкрафта система пишется за час ленивого написания.
С этим спора нет. Подобие этому я делал и выходило довольно не плохо, но у меня были утечки и я тупо удалил весь код не разбираясь где утечки.
Так же как-то пробовал из хейва от дядьки Bribe брать систему отлова урона, но там много чего, что мне не нужно, ибо мне нужно отловить чисто урон от атаки. В силу этого не обойтись без еще одного события EVENT_UNIT_ATTACKED и дополнительной логической, которая будет во время любого урона, кроме атаки менять свое значение.
32
Особо можешь нестаратся, их уже как грязи вот на хайве видел забавную систему определания типа урона там все на 1 триггер, сделано + проверки чтобы 1 и тому же юниту 100500 ивентов не напихать, через скока то ивентов триггеру удаляют и создают новый добовляя в него ивенты на всех живых, при дамаге цели добовляют скилл на отрец маг резист, и проверяют дмг больше или меньше 0.00, с помощью дамиков так же отлавливаю сплеш атаки с чистым дмг.
30
С этим спора нет. Подобие этому я делал и выходило довольно не плохо, но у меня были утечки и я тупо удалил весь код не разбираясь где утечки.
Так же как-то пробовал из хейва от дядьки Bribe брать систему отлова урона, но там много чего, что мне не нужно, ибо мне нужно отловить чисто урон от атаки. В силу этого не обойтись без еще одного события EVENT_UNIT_ATTACKED и дополнительной логической, которая будет во время любого урона, кроме атаки менять свое значение.
По моей ссылке нет ни утечек, ни лишних событий, и вообще вся система в 30 строк с табуляцией умещается. Попробуй =)
Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.