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

Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
4
Рано утром мудренее...
Вот и утро наступило. Прочитал по новой, что ты хотел сказать и понял.
Да, существует такой бажок, однако, если использовать пустую боевую единицу, что будет атаковать, то все предметы и пассивные способности надо будет передавать этой пустышке, но тем самым не будет бага. Это еще не рассматривая характеристики основы и баффов и т.д. и т.п.
Так что это не вариант использовать пустышку ради исправления всего лишь одной атаки.
Загруженные файлы
28
первое что бросилось в глаза это поиск юнита в массиве
если размер массив <3 то ещё ладно но если 3 и более то выгоднее будет юзать хэш/структуры
4
Помимо этой способности имеется еще две и порой в них тоже ищется через массив...
Спасибо, учту.
28
DazzleFirst, вот тебе имба способ
создаёшь массив интежеров в котором хранятся индексы юнитов
обращение к массиву через хэндл
int GetIndex(unit u){
	return indexes[GetHandleId(u)-FIRST_HANDLE_UNIT];
}
где indexes массив индексов а FIRST_HANDLE_UNIT константа равная хэндлу первого юнита в игре
она всегда одинаковая так что просто на тестовой мапе поставь юнита и выведи на экран его хэндл
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 юнитов.
Просто удаляем и усе.
Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.