Имеется код для одной способности включающая в себя, как активный режим, так и пассивный.
Задача состоит в оптимизации кода, преимущественно для активного режима, где герой перемещается (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.
`
ОЖИДАНИЕ РЕКЛАМЫ...

Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
0
4
9 лет назад
0
quq_CCCP, это и есть системы от Bribe и от Nestharus. Причем у последнего раза в три круче, насколько я знаю.
Clamp, прикол в том, что твоя система не ловит урон от атаки, она ловит любой урон.
Дядьки, есть еще предложения как повысить производительность способности, кроме переделки системы отлова атаки?
0
30
9 лет назад
Отредактирован Clamp
0
DazzleFirst, о, сейчас тебе надо приготовиться и сесть: СЕЙЧАС БУДЕТ КРУТОЙ ТУЛТИП!
Вводится глобальная булевая переменная IS_SPELL_DAMAGE, а в абилках пишешь что-то типа такого:
IS_SPELL_DAMAGE = true
DoSomeDmg(...)
IS_SPELL_DAMAGE = false
При срабатывании события на нанесение урона из абилки в триггере можно проверять стейт IS_SPELL_DAMAGE, он будет иметь значение true. Дальше, думаю, справишься сам.
0
4
9 лет назад
0
Clamp, ты кажись меня совсем ребенком считаешь. Сия фокус мной уже давно используется.
0
30
9 лет назад
Отредактирован Clamp
0
DazzleFirst, тогда что за предъява "твоя система не определяет урон от способностей"? Она регистрирует урон, а определять всё, что тебе нужно относительно него - уже другая сфера задач.

системы отлова атаки?
Я не претендую на абсолютный авторитет, но системы ловли урона "по событию атаки" - яркий пример костыльно-ориентированной разработки, так как имеет множество допущений (например, что снаряд попадёт в цель не позже, чем через N секунд после начала атаки) и архитектурно неправильна.
0
4
9 лет назад
0
Clamp, спору нет. Тогда тебе задачка, как сделать, чтобы функция на поиск цели (SkillW_E_Func_AreaActions) запустилась по повторной после того как Герой нанесет урон выбранной цели?
Поясняю, сия функция находится ниже чем отлов урона, далее сия функция требует целочисленную (index героя).
Запустить нативкой ExecuteFunc не выйдет, в силу требуемой целочисленной.
0
30
9 лет назад
Отредактирован Clamp
0
DazzleFirst, я не читал твой код, опиши механику работы способности на словах, пожалуйста.
0
4
9 лет назад
0
Из РО.
Пассивно дает шанс при атаке нанести многократный урон и дает шанс избежать любой урон, а так же увеличивает добавку к ловкости за каждый уровень.
При использовании на время действия способности Герой приобретает максимальную скорость и телепортируется к случайному врагу, что находится в области действия. Если враг герой, то наносит доп. урон, иначе урон снижается.
Вот, вроде бы, все описано как есть.
0
30
9 лет назад
0
Ну с пассивной частью, я думаю, проблем нет, как и со скоростью при активации (абила сапога с 522 скоростью).
При активации выбираем юнита, проверяем герой или нет и по результату проверки интовой переменной даём значение, равное нужному урону. Затем телепортируем и наносим урон из переменной.
Или я проглядел какой-то подводный камень?
0
4
9 лет назад
0
SkillW_E_Func_GetTriggerIndex - выдает порядковый номер триггера из массива.
SkillW_E_Func_GetUnitIndex - выдает порядковый номер героя из массива.
SkillW_E_Func_TargetActions - отвечает за отлов атаки и урона.
SkillW_E_Func_AreaActions - отвечает за поиск цели.
SkillW_E_Func_Periodic - отвечает за время действия и обнуления массива.
SkillW_E_Func_Condition - отвечает за использование способности.
Clamp:
Или я проглядел какой-то подводный камень?
Причина в том что Герой меняется на Героя имеющего перезарядку атаки =0.00, тем самым атака зависит только от анимации, но этот сменный не имеет скорости ходьбы, дабы отрубить кнопку Move, иначе игрок мог запросто нажимать ПКМ и тем самым сбивать атаку сменного героя.
По поводу скорости, дается аура (торнадо), что дает макс. скорость атаки и ходьбы.
Урон зависит от ловкости, тем самым здесь участвует система добавления характеристик, в данном случае атаки. Урон же, дается только на одну атаку, поэтому я и мучаюсь с этим отловом атаки и урона.
Вроде бы пояснил, что мог.
К тому же я кинул карту с героем, если кому угодно, может протестировать героя и поделиться своим впечатлением.
НО предупреждаю, что Третья способность еще не оптимизирована как мне хочется, в силу этого из-за нее во время теста могут быть лаги.
0
30
9 лет назад
0
По твоему первому описанию абилка просто наносит урон один раз и перемещает героя, а не накручивает на него кучу странной ненужной лабуды.
Окей, сейчас подумаем.
0
4
9 лет назад
0
Я кажись не правильно объясняю... поэтому совет будет один, протестировать. Может тогда поймешь чего я хочу.
Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.