Добавлен DazzleFirst
Имеется код для одной способности включающая в себя, как активный режим, так и пассивный.
Задача состоит в оптимизации кода, преимущественно для активного режима, где герой перемещается (SetUnitPosition) с мелкой периодичностью.
Использую JNGP.
Задача состоит в оптимизации кода, преимущественно для активного режима, где герой перемещается (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 может пикнуть москитов, остальное не пикает их, на то они и москиты...
Вот как выглядит нормальный фильтр без локалок и прочего
Фильтр просто ужас, ну кто так фильтры делает?
Проверка на '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.
Туча констант, тоже хорошо тока длят наработок, на деле ставь конкретные значения или юзай Difine vjass'a.
`
ОЖИДАНИЕ РЕКЛАМЫ...
Чтобы оставить комментарий, пожалуйста, войдите на сайт.
Поясняю, сия функция находится ниже чем отлов урона, далее сия функция требует целочисленную (index героя).
Запустить нативкой ExecuteFunc не выйдет, в силу требуемой целочисленной.
Ред. Clamp
Пассивно дает шанс при атаке нанести многократный урон и дает шанс избежать любой урон, а так же увеличивает добавку к ловкости за каждый уровень.
При использовании на время действия способности Герой приобретает максимальную скорость и телепортируется к случайному врагу, что находится в области действия. Если враг герой, то наносит доп. урон, иначе урон снижается.
При активации выбираем юнита, проверяем герой или нет и по результату проверки интовой переменной даём значение, равное нужному урону. Затем телепортируем и наносим урон из переменной.
SkillW_E_Func_GetUnitIndex - выдает порядковый номер героя из массива.
SkillW_E_Func_TargetActions - отвечает за отлов атаки и урона.
SkillW_E_Func_AreaActions - отвечает за поиск цели.
SkillW_E_Func_Periodic - отвечает за время действия и обнуления массива.
SkillW_E_Func_Condition - отвечает за использование способности.
Clamp:
По поводу скорости, дается аура (торнадо), что дает макс. скорость атаки и ходьбы.
Урон зависит от ловкости, тем самым здесь участвует система добавления характеристик, в данном случае атаки. Урон же, дается только на одну атаку, поэтому я и мучаюсь с этим отловом атаки и урона.
К тому же я кинул карту с героем, если кому угодно, может протестировать героя и поделиться своим впечатлением.
НО предупреждаю, что Третья способность еще не оптимизирована как мне хочется, в силу этого из-за нее во время теста могут быть лаги.
Ред. nvc123
а не плодить кучу триггеров с одинаковым событием
и не смотреть на то как они отбирают друг у друга процессорное время
Но как я определю нанес ли Герой урон атакованному? Ведь флудить в сия триггере
А так выходит сразу отлов атаки => отлов урона => уничтожение триггера и обнуление массива. Иль это медленней нежили создание системы по отлову атаки и урона?
Ред. nvc123
ты же сказал что событие атаки у тебя используется не только в этом триггере и не только во время этой способности
вот я и говорю что вместо нескольких триггеров с 1 событием лучше использовать 1 триггер с этим же событием
включать/выключать триггер это больший бред чем удаление
Ред. nvc123
учитывая вес триггера и то что триггеры это потоки получается неплохая экономия
в функции SkillW_A_Func_Adder переменная левел юзается только 1 раз а значит нафиг не нужна
также не стоит писать в условиях большой код (иногда бывает баг из за которого условие не успевает вернуть результат а действие уже проверяет результат условия)
когда твоего юнита атакуют то будет срабатывать 2 триггера и у обоих будут проверятся условия
вместо этого можно просто написать в действии триггера с общим событием атаки
а your code это код который ты собирался выполнять для этого юнита
не кажется что это проще чем создавать триггер ради 1 юнита
Ред. DazzleFirst
Это не бред, ибо на время действия способности создается один триггер на отлов атаки и урона именной одной взятой цели, а не нескольких, как ты мне предлагаешь. Ибо при включенной способности каждый атакованный будет проверятся, а скорость-то велика (менее 1 раза в 0.02), тем самым пойдет конкретная нагрузка с перезапусками логических и поиск цели в массивах. А с моим способом проверяется только единственный атакованный с запуском только одного массива, а потом удаление триггера, дабы триггер более не проверял атакованного или получившего урон и не нагружал варчик.
до этого ты говорил что да
Ред. DazzleFirst
Ред. Кет
Или сразу количество прошедего времени посчитать.
Ред. nvc123
DazzleFirst:
+ атаку по твоему юниту отлавливает N+1 раз
я же предлагаю отлавливать лишь 1 раз
т. к. у тебя более 1 пассивки то N>1
следовательно мой вариант выгоднее
ибо он требует в N раз меньше оперативной памяти и процессорного времени
SkillW_E_Func_Periodic - функция, что вызывается каждый период времени.
SkillW_E_Func_AreaActions - функция, что отвечает за поиск цели. Эту же функцию мне хочется вызывать после нанесения урона. В ней:
Первым делом функция срабатывает после того как цель способности (выбирается случайно в области действия) была атакована. Далее проверка на атакующего
Далее проверяем
Даем дополнительную атаку на один удар.
Даем способность, что уменьшает наносимый урон нашим Героем.
Если получивший урон и есть наша цель способности, нанесший урон и есть наш Герой, полученный урон не от способности, то
Надеюсь уже совсем хорошо пояснил, что за что отвечает. И понятно почему нужно отлавливать как атаку так и урон.
Теперь задача:
Как реализовать вызов функции SkillW_E_Func_AreaActions из функции SkillW_E_Func_TargetActions после уничтожение триггера в последней функции?
вместо этого можно у пасивки сделать проверку что скил включен и атакованый юнит == наш юнит
я всё правильно понял
это ты просто тупиш
И меня не евенты интересуют, а функции и их корешки...