Алгоритмы, Наработки и Способности
Способ реализации:
Прочее
Тип:
Способность
Версия Warcraft:
1.26
Spirit Breaker прямо из доты 6.83d
СПИСОК ИСПРАВЛЕНИЙ
ChargeOfDarkness :
Теперь можно изучать прямо во время разбега или перезарядки способности
EmpoweringHaste :
Теперь не сбивает текущий приказ и не проигрывает анимацию spell morph
(но сбивает ChargeOfDarkness)
Сделано на основе "Стремительность", вместо "Берсерк"!
NetherStrike :
При получении стана или если цель далеко убежит, то способность автоматически отменяется
Написано на vJass с define из cJass
Почти у каждой функции есть комментарий того, что делает функция
Все используемые абилки и т.д лежат в константах у каждой библиотеки
DotA
library DotA initializer DotaInit    
    
    
    globals
    
        hashtable udg_dotaHash  = InitHashtable()
        timer     udg_dotaTimer = CreateTimer()
        region    global_region //Регион в котором не будет работать отталкивание юнита от GreaterBash
        
    endglobals
    
    
    private function DotaInit takes nothing returns nothing
        set global_region = CreateRegion()
        //В регион надо добавлять области в которых не будет работать отталкивание юнита от GreaterBash
        //Пример:
        //call RegionAddRect( global_region, bj_mapInitialPlayableArea )
        call TimerStart( udg_dotaTimer, 99999.00, false, null )
    endfunction
    
endlibrary
DestroyTrigger
library DestroyTriggerEx initializer InitDestroyTrigger requires DotA


    globals
    
        private trigger array triggers
        private real    array time
        private integer       count = 0
    
    endglobals

    
    private function ErrorMsg takes nothing returns nothing
        //Выводит сообщение об ошибке
        local integer i = 0

        loop
            call DisplayTimedTextToPlayer(Player(i), 0, 0, 120, "|c00ff0303An internal checksum has failed|r" )
            set i = i+1
            exitwhen i == 12
        endloop

    endfunction

    function DestroyTriggerEx takes trigger trg returns nothing
        //Добавляет триггер в очередь для удаления
        call DisableTrigger( trg )
        set count = count+1
        set triggers[count] = trg
        set time[count] = TimerGetElapsed(udg_dotaTimer)+60
        if count > 8000 then
            call ErrorMsg()
        endif
    endfunction

    private function ClearQueue takes integer i returns nothing
        if i != count then
            set triggers[i] = triggers[count]
            set time[i] = time[count]
        endif
    
        set triggers[count] = null
        set time[count] = 0
        set count = count-1
    endfunction

    private function DestroyTrigger_Actions takes nothing returns boolean
        local real r = TimerGetElapsed(udg_dotaTimer)
        local integer i
    
        set i = 1
        loop
            exitwhen i > count
            if time[i] < r then
                if triggers[i] == null or IsTriggerEnabled(triggers[i]) == true then
                    call ErrorMsg()
                else
                    call DestroyTrigger( triggers[i] )
                endif
                call ClearQueue( i )
            else
                set i = i + 1
            endif
        endloop
    
        return false
    endfunction

    private function InitDestroyTrigger takes nothing returns nothing
        local trigger trg = CreateTrigger()
    
        call TriggerRegisterTimerEvent( trg, 15, true )
        call TriggerAddCondition( trg, Condition(function DestroyTrigger_Actions) )
    endfunction

endlibrary
Recycle
library Recycle initializer InitRecycle requires DotA
    
    
    globals
        
        private group   array groups
        private boolean array groupIsUsed
        private boolean       error              = false
        private integer       firstGroupHandleId = 0
        private integer       number             = 0
        private real          errorTime          = 0.
        private string        errorText          = ""
        
    endglobals
    
    
    private function Display takes nothing returns nothing
        call DisplayTimedTextToPlayer( GetEnumPlayer(), 0, 0, errorTime, errorText )
    endfunction

    private function DisplayError takes force f, real r, string s returns nothing
        set errorText = s
        set errorTime = r
        call ForForce( f, function Display )
    endfunction
    
    function RecycleGroup takes group g returns nothing
        //Функция очищает группу и делает её доступной для повторного использования
        local integer i = GetHandleId(g)-firstGroupHandleId
        if i < 0 or i > 120 then
            set error = true
        else
            call GroupClear( g )
            set groupIsUsed[i] = false
            set number = i
        endif
    endfunction

    function GetGroup takes nothing returns group
        //Возвращает доступную для использования группу
        local integer i = number

        loop
            exitwhen i == number-1
            if groupIsUsed[i] == false then
                set number = i+1
                if number == 120 then
                    set number = 0
                endif
                set groupIsUsed[i] = true
                return groups[i]
            endif
            set i = i+1
            if i == 120 then
                set i = 0
            endif
        endloop
        
        call DisplayError( bj_FORCE_ALL_PLAYERS, 5.00, "|c00ff0303CRITICAL ERROR: FOUND NO AVAILABLE GROUPS|r" )
        
        return CreateGroup()
    endfunction

    function RecycleCheck takes nothing returns boolean
        //Проверка на количество групп которые в данный момент используются
        local integer groupCount = 0
        local integer i = 0
        
        loop
            exitwhen i == 120
            if groupIsUsed[i] == true then
                set groupCount = groupCount+1
            endif
            set i = i+1
        endloop
        
        if groupCount > 100 or error then
            call DisplayError( bj_FORCE_ALL_PLAYERS, 5.00, I2S(groupCount) )
        endif
        
        return false
    endfunction

    private function InitRecycle takes nothing returns nothing
        local integer i = 0
        
        set number = 0
        set groups[i] = CreateGroup()
        set groupIsUsed[i] = false
        set i = i+1
        set firstGroupHandleId = GetHandleId( groups[0] )
        
        loop
            exitwhen i == 120
            set groups[i] = CreateGroup()
            set groupIsUsed[i] = false
            set i = i+1
        endloop
    endfunction
    
    
endlibrary
OtherFunctions
library OtherFunctions requires DotA, DestroyTriggerEx, Recycle


    globals
    
        private integer destroyedDestructables = 0 //Нужно для подсчета уничтоженных разрушаемых объектов
        
        define
            Spellcaster   = 'e00E' //Spellcaster
            PreloaderHero = 'H00Y' //Preloader Hero
            Marker        = 'A04R' //Marker
        enddefine
        
    endglobals

    
    function BlockAbility takes unit u returns boolean
        //Здесь нужно указывать все бафы которые могут блокировать одну направленную способность
        //Пример:
        //return GetUnitAbilityLevel(u, 'B0BI') > 0 or GetUnitAbilityLevel(u, 'BNss') > 0
        return false
    endfunction

    private function BashOn takes nothing returns boolean
        //Включает срабатывание GreaterBash при атаке юнита
        local trigger trg  = GetTriggeringTrigger()
        local integer trgH = GetHandleId( trg )
        
        call SaveInteger( udg_dotaHash, GetHandleId( LoadUnitHandle(udg_dotaHash, trgH, 14) ), LoadInteger(udg_dotaHash, trgH, 33 ), 2 )
        call FlushChildHashtable( udg_dotaHash, trgH )
        call DestroyTriggerEx( trg )
        set trg = null
        
        return false
    endfunction

    function BashOff takes unit u, integer i, real r returns nothing
        //Выключает срабатывание GreaterBash при атаке юнита (не влияет на GreaterBash от способностей)
        local trigger trg = CreateTrigger()
        
        call TriggerAddCondition( trg, Condition(function BashOn) )
        call TriggerRegisterTimerEvent( trg, r, false )
        call SaveInteger   ( udg_dotaHash, GetHandleId(u)   , i  , 1 )
        call SaveUnitHandle( udg_dotaHash, GetHandleId(trg) , 14 , u )
        call SaveInteger   ( udg_dotaHash, GetHandleId(trg) , 33 , i )
        
        set trg = null
    endfunction

    function IsDestructable takes destructable d returns boolean
        //Здесь нужно указывать все деревья и разрушаемые объекты, которые могут быть в карте
        return GetDestructableTypeId(d) == 'NTtc' or GetDestructableTypeId(d) == 'NTtw' or GetDestructableTypeId(d) == 'ATtr' or GetDestructableTypeId(d) == 'LTlt'
    endfunction

    function DamageToUnit takes unit attacker, unit target, integer i, real damage returns nothing
        //Нанесение урона
        if i == 0 then
            return
        endif
        if i == 1 then
            call UnitDamageTarget( attacker, target, damage, true, true, ATTACK_TYPE_NORMAL , DAMAGE_TYPE_FIRE   , WEAPON_TYPE_WHOKNOWS )
        elseif i == 2 then
            call UnitDamageTarget( attacker, target, damage, true, true, ATTACK_TYPE_HERO   , DAMAGE_TYPE_NORMAL , WEAPON_TYPE_WHOKNOWS )
        elseif i == 3 then
            call UnitDamageTarget( attacker, target, damage, true, true, ATTACK_TYPE_HERO   , DAMAGE_TYPE_MAGIC  , WEAPON_TYPE_WHOKNOWS )
        elseif i == 4 then
            call UnitDamageTarget( attacker, target, damage, true, true, ATTACK_TYPE_PIERCE , DAMAGE_TYPE_NORMAL , WEAPON_TYPE_WHOKNOWS )
        elseif i == 5 then
            call UnitDamageTarget( attacker, target, damage, true, true, ATTACK_TYPE_NORMAL , DAMAGE_TYPE_NORMAL , WEAPON_TYPE_WHOKNOWS )
        elseif i == 6 then
            call SetUnitState( target, UNIT_STATE_LIFE, RMaxBJ( GetUnitState(target, UNIT_STATE_LIFE)-damage, 1 ) )
            if GetUnitState( target, UNIT_STATE_LIFE ) < 2 then
                call UnitRemoveBuffs( target, true,true )
                //call UnitRemoveAbility( target, 'Aetl' )
                call UnitDamageTarget( CreateUnit(GetOwningPlayer(attacker), Spellcaster, 0, 0, 0), target, 100000000.00, true, false, ATTACK_TYPE_MELEE, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS )
            endif
        elseif i == 7 then
            //В этом if нужно указывать способности имея которые юнит получает больше магического урона
            //Оригинал:
            //if GetUnitAbilityLevel(target, 'Aetl') > 0 or GetUnitAbilityLevel(target, 'B01N') > 0 then
            if false then
                call UnitDamageTarget( attacker, target, damage, true, true, ATTACK_TYPE_HERO, DAMAGE_TYPE_MAGIC     , WEAPON_TYPE_WHOKNOWS )
            else
                call UnitDamageTarget( attacker, target, damage, true, true, ATTACK_TYPE_HERO, DAMAGE_TYPE_UNIVERSAL , WEAPON_TYPE_WHOKNOWS )
            endif
        elseif i == 8 then
            call UnitDamageTarget( attacker, target, damage, true, true, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_UNIVERSAL, WEAPON_TYPE_WHOKNOWS )
        endif
    endfunction

    function SafeRealX takes real x returns real
        //Чтобы X не выходила за пределы карты, иначе - вернет значение недалеко от границы игровой карты
        local real r = GetRectMinX(bj_mapInitialPlayableArea)+50
        
        if x < r then
            return r
        endif
        set r = GetRectMaxX(bj_mapInitialPlayableArea)-50
        if x > r then
            return r
        endif
        
        return x
    endfunction

    function SafeRealY takes real y returns real
        //Чтобы Y не выходила за пределы карты, иначе - вернет значение недалеко от границы игровой карты
        local real r = GetRectMinY(bj_mapInitialPlayableArea)+50
        
        if y < r then
            return r
        endif
        set r = GetRectMaxY(bj_mapInitialPlayableArea)-50
        if y > r then
            return r
        endif
        
        return y
    endfunction

    function AbilityInit takes integer i returns nothing
        local unit u = CreateUnit( Player(15), PreloaderHero, 0, 0, 270 )
        
        call UnitAddAbility( u, i )
        call UnitRemoveAbility( u, i )
        call RemoveUnit( u )
        
        set u = null
    endfunction

    function DistanceBetweenUnits takes unit u_1, unit u_2 returns real
        //Возвращает расстояние между координатами юнитов
        local real x1 = GetUnitX( u_1 )
        local real y1 = GetUnitY( u_1 )
        local real x2 = GetUnitX( u_2 )
        local real y2 = GetUnitY( u_2 )
        
        if u_1 == null or u_2 == null then
            return I2R(9999999999)
        else
            return SquareRoot( (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) )
        endif
        
        return 1.0
    endfunction

    function DistanceBetweenCoordinates takes real x1, real y1, real x2, real y2 returns real
        //Возвращает расстояние между координатами
        return SquareRoot(  ((x1-x2)*(x1-x2)) + ((y1-y2)*(y1-y2))  )
    endfunction

    function AngleBetweenUnits takes unit u_1, unit u_2 returns real
        //Возвращает угол между юнитами
        return bj_RADTODEG*Atan2( GetUnitY(u_2)-GetUnitY(u_1), GetUnitX(u_2)-GetUnitX(u_1) )
    endfunction

    function AnyUnitEvent takes trigger trg, playerunitevent whichEvent returns nothing
        local integer i = 0
        
        loop
            call TriggerRegisterPlayerUnitEvent( trg, Player(i), whichEvent, null )
            set i = i+1
            exitwhen i == 16
        endloop
    endfunction

    function KillDestructables_Actions takes nothing returns nothing
        if IsDestructable(GetEnumDestructable()) and IsDestructableAliveBJ(GetEnumDestructable()) then
            set destroyedDestructables = destroyedDestructables + 1
            call KillDestructable( GetEnumDestructable() )
        endif
    endfunction

    function KillDestructables takes real x, real y, real radius returns integer
        //Уничтожение деревьев или декораций, которые мешают
        //Например если отменить ChargeOfDarkness возле деревьев
        //Или юнит-цель в момент столкновения будет находиться возле деревьев
        local rect r = Rect( x-radius, y-radius, x+radius, y+radius )
        
        set destroyedDestructables = 0
        call EnumDestructablesInRect( r, null, function KillDestructables_Actions )
        call RemoveRect( r )
        
        set r = null
        //Возвращает количество уничтоженных разрушаемых объектов
        return destroyedDestructables
    endfunction

    function AddAbility takes unit u, integer i returns nothing
        call UnitAddAbility( u, i )
        call UnitMakeAbilityPermanent( u, true, i )
    endfunction

    function IfUnitExist takes unit u returns boolean
        //Проверка, существует юнит или он мертв
        return GetUnitTypeId(u) < 1 or IsUnitType(u, UNIT_TYPE_DEAD) == true
    endfunction

    function IfHaveStopBuff takes unit u returns boolean
        //Здесь нужно указывать все бафы имея которые ChargeOfDarkness сбивается
        //Пример:
        //return (GetUnitAbilityLevel(u, 'B00H') > 0) or (GetUnitAbilityLevel(u, 'BOhx') > 0)
        return false
    endfunction

    function IfHavePauseOrBuff takes unit u returns boolean
        //Проверка, находится ли юнит в паузе или имеет баф который останавливает применение способности
        return IfHaveStopBuff( u ) or IsUnitPaused( u )
    endfunction

    function Ancient_Exception takes unit u returns boolean
        //Юниты с классификацией "Древо" игнорируются поиском цели
        //Но эта функция делает исключение для некоторых юнитов с этой классификацией
        local integer i = GetUnitTypeId(u)
        
        //Пример:
        //return i == 'n004' or i == 'n01G' or i == 'n01C' or i == 'n018'
        return false
    endfunction

    function CheckUnit takes nothing returns boolean
        //Проверка на враждебность двух юнитов и на то чтобы GetFilterUnit() не был зданием или дамми юнитом
        return IsUnitEnemy(global_caster, GetOwningPlayer(GetFilterUnit()) ) and (GetUnitAbilityLevel( GetFilterUnit(), Marker ) == 0 and IsUnitType( GetFilterUnit(), UNIT_TYPE_STRUCTURE ) == false and IfUnitExist(GetFilterUnit()) == false) and (IsUnitType( GetFilterUnit() ,UNIT_TYPE_ANCIENT ) == false or Ancient_Exception(GetFilterUnit()))
    endfunction

endlibrary
SpellcasterRemove
library SpellcasterRemove initializer InitSpellcasterRemove requires OtherFunctions


    define
        
        Spellcaster = 'e00E' //Spellcaster
        
    enddefine


    private function SpellcasterRemove_Actions takes nothing returns nothing
        local unit u = GetEnteringUnit()
        
        //if GetUnitTypeId( GetEnteringUnit()) == 'e00E' or GetUnitTypeId(GetEnteringUnit()) == 'e022' then
        if GetUnitTypeId( u ) == Spellcaster then
            call ShowUnit( u, false )
            call SetUnitPathing( u, false )
            call SetUnitInvulnerable( u, true )
            call UnitApplyTimedLife( u, 'BTLF', 20.00 )
        endif
        
        set u = null
    endfunction
    
    private function InitSpellcasterRemove takes nothing returns nothing
        local trigger trg = CreateTrigger(  )
        
        call TriggerRegisterEnterRectSimple( trg, bj_mapInitialPlayableArea )
        call TriggerAddCondition( trg, Condition(function SpellcasterRemove_Actions) )
        
        set trg = null
    endfunction
    
    
endlibrary
ChargeOfDarkness
library ChargeOfDarkness initializer InitChargeOfDarkness requires OtherFunctions, GreaterBash


    globals
    
        private real find_distance   = 0.00 //Нужно для сравнивания расстояний, чтобы найти ближайшего юнита (если target умрет)
                unit global_caster   = null //Используется в FindFilter и CheckUnit(OtherFunctions)
        private unit foundUnit       = null //Ближайший юнит к умершему target, это нужно чтобы caster находил новую цель при разбеге (если target умрет)
        private unit darkness_caster = null
        private unit darkness_target = null
        private integer darkness_abilityLvl = 0 //Непонятная integer, нигде не используется
        private group   group_NotBash //Эта группа нужна чтобы на юнитов не накладывался GreaterBash, когда caster бежит

        define
            SwapAbilityContainer    = 'A003' //SwapAbilityContainer
            Cooldown                = 'A312' //Charge of Darkness (on cooldown)
            ChargeOfDarknessAbility = 'A1P8' //Charge of Darkness
            EmpoweringHasteAbility  = 'A004' //Empowering Haste
            NetherStrikeAbility     = 'A0G4' //Nether Strike
            NetherStrikeUpgrade     = 'A1D8' //Nether Strike Upgrade
            GreaterBashAbility      = 'A0G5' //Greater Bash
            AttributeBonus          = 'Aamk' //Attribute Bonus
            Marker                  = 'A04R' //Marker
            ChargeOfDarknessAddBuff = 'A24L' //Charge of Darkness Add Buff
            ChargeOfDarknessBuff    = 'B0ED' //Charge of Darkness (buff)
            SpellImmunity           = 'A179' //Spell Immunity
            Spellcaster             = 'e00E' //Spellcaster
            ChargeOfDarknessStun    = 'A0GS' //Charge of Darkness Stun
            GrandMagus              = 'E02X' //Grand Magus (Rubick)
            VisionDummy             = 'o00Q' //Vision Dummy
            Generic_Stun            = 'A0X6' //Generic_Stun
        enddefine
        
    endglobals
    
    
    private function Cooldown_Remove takes nothing returns boolean
        local trigger trg  = GetTriggeringTrigger()
        local integer trgH = GetHandleId   ( trg )
        local unit    u    = LoadUnitHandle( udg_dotaHash, trgH, 2 )
        
        call UnitRemoveAbility( u, Cooldown )
        call UnitRemoveAbility( u, SwapAbilityContainer )
        call FlushChildHashtable( udg_dotaHash, trgH )
        call DestroyTriggerEx( trg )
        
        set trg = null
        set u   = null
        
        return false
    endfunction

    private function Cooldown_Start takes unit u returns nothing
        //Эта функция запускает триггер который через 12 секунд уберет перезарядку у способности
        local trigger trg
        local integer trgH
        
        if IfUnitExist(u) == true then
            call UnitRemoveAbility( u, Cooldown )
            call UnitRemoveAbility( u, SwapAbilityContainer )
        else
            set trg  = CreateTrigger()
            set trgH = GetHandleId( trg )
            call TriggerRegisterDeathEvent( trg, u )
            call TriggerRegisterTimerEvent( trg, 12, false )
            call TriggerAddCondition( trg, Condition(function Cooldown_Remove) )
            call SaveUnitHandle( udg_dotaHash, trgH, 2, u )
        endif
        
        set trg = null
    endfunction

    private function ChargeOfDarkness_Bash takes nothing returns nothing
        //Если на пути кастера находятся юниты, то на них кидается GreaterBash
        //
        //Строки if IsUnitInGroup( GetEnumUnit(), group_NotBash ) == false then
        //call GroupAddUnit( group_NotBash, GetEnumUnit() )
        //Отвечают за то, чтобы GreaterBash повторно не кидался на юнитов
        if IsUnitInGroup( GetEnumUnit(), group_NotBash ) == false then
            call GroupAddUnit( group_NotBash, GetEnumUnit() )
            call GreaterBash( darkness_caster, GetEnumUnit(), false, true )
        endif
    endfunction

    private function OrderCheck takes integer i returns boolean
        //Проверка на приказ, это нужно чтобы ChargeOfDarkness не сбивался если менять вещи в инвентаре
        if i == ChargeOfDarknessAbility or i == EmpoweringHasteAbility or i == NetherStrikeAbility or i == NetherStrikeUpgrade or i == GreaterBashAbility or i == AttributeBonus then
            return true
        endif
        if i == 852002 or i == 852003 or i == 852004 or i == 852005 or i == 852006 or i == 852007 then
            return true
        endif
        if i > 1000000 then
            return true
        endif
        
        return false
    endfunction

    private function FindFilter takes nothing returns boolean
        //Функция поиска ближайшего юнита
        if (IsUnitEnemy( global_caster, GetOwningPlayer(GetFilterUnit()) ) and (GetUnitAbilityLevel( GetFilterUnit(), Marker ) == 0 and IsUnitType( GetFilterUnit(), UNIT_TYPE_STRUCTURE ) == false and IfUnitExist( GetFilterUnit() ) == false) and (IsUnitType( GetFilterUnit(), UNIT_TYPE_ANCIENT ) == false or Ancient_Exception(GetFilterUnit()) ) ) and IsUnitVisible( GetFilterUnit(), GetOwningPlayer(darkness_caster) ) == true then
            if DistanceBetweenUnits( darkness_target, GetFilterUnit() ) < find_distance then
                set find_distance = DistanceBetweenUnits( darkness_target, GetFilterUnit() )
                set foundUnit = GetFilterUnit()
            endif
        endif
        
        return false
    endfunction

    private function Find takes unit caster, unit target returns unit
        //Поиск ближайшей цели, если target умрет
        local group g = GetGroup()
        
        set global_caster   = caster
        set darkness_caster = caster
        set foundUnit       = null
        set find_distance   = 999999
        set darkness_target = target
        call GroupEnumUnitsInRange( g, GetUnitX(target), GetUnitY(target), 4000, Condition(function FindFilter) )
        call RecycleGroup( g )
        
        set g = null
        
        return foundUnit
    endfunction

    private function ChargeOfDarkness_Move takes nothing returns boolean
        //Главная функция, отвечает за движение, ручную остановку способности и прочее
        local trigger trg              = GetTriggeringTrigger()
        local integer trgH             = GetHandleId( trg )
        local unit    caster           = LoadUnitHandle( udg_dotaHash, trgH, 2 )
        local unit    target           = LoadUnitHandle( udg_dotaHash, trgH, 17 )
        local unit    dummy            = LoadUnitHandle( udg_dotaHash, trgH, 19 )
        local integer abilityLvl       = LoadInteger( udg_dotaHash, trgH, 5 )
        local real    moveReal         = (550+50*abilityLvl)*0.02
        local real    casterX          = LoadReal( udg_dotaHash, trgH, 23 )
        local real    casterY          = LoadReal( udg_dotaHash, trgH, 24 )
        local real    PolarProjectionX
        local real    PolarProjectionY
        local real    moveAngle
        local real    distanceBetweenCasterAndTarget
        local string  effectString
        local group   g
        
        if (GetTriggerEventId() == EVENT_WIDGET_DEATH and GetTriggerUnit() == caster) or GetTriggerEventId() == EVENT_UNIT_ISSUED_ORDER or GetTriggerEventId() == EVENT_UNIT_ISSUED_POINT_ORDER or GetTriggerEventId() == EVENT_UNIT_ISSUED_TARGET_ORDER or IfHavePauseOrBuff(caster) or LoadReal(udg_dotaHash, trgH, 442) < TimerGetElapsed(udg_dotaTimer) then
            if (GetTriggerEventId() != EVENT_UNIT_ISSUED_ORDER and GetTriggerEventId() != EVENT_UNIT_ISSUED_POINT_ORDER and GetTriggerEventId() != EVENT_UNIT_ISSUED_TARGET_ORDER) or ((GetTriggerEventId() == EVENT_UNIT_ISSUED_ORDER or GetTriggerEventId() == EVENT_UNIT_ISSUED_POINT_ORDER or GetTriggerEventId() == EVENT_UNIT_ISSUED_TARGET_ORDER) and OrderCheck(GetIssuedOrderId()) == false) then
                //Останавливает способность если юнит умер, получил паузу/сбивающий бафф, или отдал приказ (кроме приказа для смены положения предметов в инвентаре)
                call Cooldown_Start( caster )
                call DestroyEffect( LoadEffectHandle(udg_dotaHash, trgH, 175) )
                call DestroyEffect( LoadEffectHandle(udg_dotaHash, trgH, 176) )
                call DestroyEffect( LoadEffectHandle(udg_dotaHash, trgH, 177) )
                call UnitRemoveAbility( target, ChargeOfDarknessAddBuff )
                call UnitRemoveAbility( target, ChargeOfDarknessBuff )
                call RecycleGroup( LoadGroupHandle(udg_dotaHash, trgH, 187) )
                call FlushChildHashtable( udg_dotaHash, trgH )
                call DestroyTriggerEx( trg )
                call SetUnitTimeScale( caster, 1 )
                call KillUnit( dummy )
                call SetUnitPathing( caster, true )
                call SetUnitVertexColor( caster, 255, 255, 255, 255 )
                call UnitRemoveAbility( caster, SpellImmunity )
                call KillDestructables( GetUnitX(caster), GetUnitY(caster), 200 )
                if GetTriggerEventId() != EVENT_WIDGET_DEATH then
                    call ResetUnitAnimation( caster )
                endif
            endif
        elseif GetTriggerEventId() == EVENT_WIDGET_DEATH and GetTriggerUnit() == target then
            //Находит новую цель если target умирает
            set effectString = ""
            if IsPlayerAlly( GetLocalPlayer(), GetOwningPlayer(caster) ) then
                set effectString = "Abilities\\Spells\\Other\\HowlOfTerror\\HowlTarget.mdl"
            endif
            call UnitRemoveAbility( target, ChargeOfDarknessAddBuff )
            call UnitRemoveAbility( target, ChargeOfDarknessBuff )
            set target = Find( caster, target )
            if target != null then
                call SaveUnitHandle( udg_dotaHash, trgH, 17, target )
                call DestroyEffect( LoadEffectHandle(udg_dotaHash, trgH, 175) )
                call DestroyEffect( LoadEffectHandle(udg_dotaHash, trgH, 176) )
                call SaveEffectHandle( udg_dotaHash, trgH, 175, AddSpecialEffectTarget(effectString, target, "overhead") )
                call SaveEffectHandle( udg_dotaHash, trgH, 176, AddSpecialEffectTarget(effectString, target, "overhead") )
                call SaveReal( udg_dotaHash, trgH, 442, (TimerGetElapsed(udg_dotaTimer)+50)*1.0 )
                call TriggerRegisterDeathEvent( trg, target )
            else
                call Cooldown_Start( caster )
                call DestroyEffect( LoadEffectHandle(udg_dotaHash, trgH, 175) )
                call DestroyEffect( LoadEffectHandle(udg_dotaHash, trgH, 176) )
                call DestroyEffect( LoadEffectHandle(udg_dotaHash, trgH, 177) )
                call UnitRemoveAbility( target, ChargeOfDarknessAddBuff )
                call UnitRemoveAbility( target, ChargeOfDarknessBuff )
                call RecycleGroup( LoadGroupHandle(udg_dotaHash, trgH, 187) )
                call FlushChildHashtable( udg_dotaHash, trgH )
                call DestroyTriggerEx( trg )
                call SetUnitTimeScale( caster, 1 )
                call KillUnit( dummy )
                call SetUnitPathing( caster, true )
                call ResetUnitAnimation( caster )
                call SetUnitVertexColor( caster, 255, 255, 255, 255 )
                call UnitRemoveAbility( caster, SpellImmunity )
                call SetUnitPosition( caster, GetUnitX(caster), GetUnitY(caster) )
                call KillDestructables( GetUnitX(caster), GetUnitY(caster), 500 )
            endif
        else
            //Движение юнита или остановка по достижению цели
            set distanceBetweenCasterAndTarget = DistanceBetweenCoordinates( GetUnitX(caster), GetUnitY(caster), GetUnitX(target), GetUnitY(target) )
            if distanceBetweenCasterAndTarget < 100 then
                //Завершает ChargeOfDarkness
                call Cooldown_Start( caster )
                call DestroyEffect( LoadEffectHandle(udg_dotaHash, trgH, 175) )
                call DestroyEffect( LoadEffectHandle(udg_dotaHash, trgH, 176) )
                call DestroyEffect( LoadEffectHandle(udg_dotaHash, trgH, 177) )
                call UnitRemoveAbility( target, ChargeOfDarknessAddBuff )
                call UnitRemoveAbility( target, ChargeOfDarknessBuff )
                call RecycleGroup( LoadGroupHandle(udg_dotaHash, trgH, 187) )
                call FlushChildHashtable( udg_dotaHash, trgH )
                call DestroyTriggerEx( trg )
                call SetUnitTimeScale( caster, 1 )
                call KillUnit( dummy )
                set dummy = CreateUnit( GetOwningPlayer(target), Spellcaster, GetUnitX(target), GetUnitY(target), 0 )
                call UnitAddAbility( dummy, ChargeOfDarknessStun )
                call SetUnitAbilityLevel( dummy, ChargeOfDarknessStun, abilityLvl )
                call IssueTargetOrder( dummy, "thunderbolt", target )
                call SetUnitPathing( caster, true )
                call SetUnitVertexColor( caster, 255, 255, 255, 255 )
                call UnitRemoveAbility( caster, SpellImmunity )
                call SetUnitPosition( caster, GetUnitX(caster), GetUnitY(caster) )
                call KillDestructables( GetUnitX(caster), GetUnitY(caster), 200 )
                set darkness_abilityLvl = abilityLvl
                call IssueTargetOrder( caster, "attack", target )
            else
                //Перемещение кастера
                if GetTriggerEvalCount( trg ) == 1 then
                    call DisableTrigger( trg )
                    call IssueImmediateOrder( caster, "holdposition" )
                    call EnableTrigger( trg )
                endif
                if ModuloInteger( GetTriggerEvalCount(trg), 65 ) == 0 then
                    if GetUnitTypeId( caster ) == GrandMagus then
                        call SetUnitAnimationByIndex( caster, 1 )
                    else
                        call SetUnitAnimationByIndex( caster, 2 )
                    endif
                endif
                set moveAngle = AngleBetweenUnits( caster, target )*bj_DEGTORAD
                call SetUnitFacing( caster, moveAngle*bj_RADTODEG )
                set PolarProjectionX = casterX + moveReal*Cos(moveAngle)
                set PolarProjectionY = casterY + moveReal*Sin(moveAngle)
                call SetUnitX( caster, PolarProjectionX )
                call SetUnitY( caster, PolarProjectionY )
                call SetUnitX( dummy, GetUnitX(target) )
                call SetUnitY( dummy, GetUnitY(target) )
                call SaveReal( udg_dotaHash, trgH, 23, (PolarProjectionX)*1.0 )
                call SaveReal( udg_dotaHash, trgH, 24, (PolarProjectionY)*1.0 )
                set group_NotBash = LoadGroupHandle( udg_dotaHash, trgH, 187 )
                set g = GetGroup()
                set global_caster = caster
                set darkness_caster = caster
                call GroupEnumUnitsInRange( g, PolarProjectionX, PolarProjectionY, 325, Condition(function CheckUnit) )
                set darkness_abilityLvl = abilityLvl
                call ForGroup( g, function ChargeOfDarkness_Bash )
                call RecycleGroup( g )
                set g = null
                if distanceBetweenCasterAndTarget < 3000 and GetUnitAbilityLevel( target, ChargeOfDarknessAddBuff ) == 0 then
                endif
            endif
        endif
        
        set trg    = null
        set caster = null
        set target = null
        set dummy  = null
        
        return false
    endfunction

    private function ChargeOfDarkness_Actions takes nothing returns nothing
        //Старт способности ChargeOfDarkness
        local trigger trg          = CreateTrigger()
        local integer trgH         = GetHandleId( trg )
        local unit    caster       = GetTriggerUnit()
        local unit    target       = GetSpellTargetUnit()
        local unit    dummy        = CreateUnit( GetOwningPlayer(caster), VisionDummy, GetUnitX(target), GetUnitY(target), 0 )
        local integer abilityLvl   = GetUnitAbilityLevel( caster, ChargeOfDarknessAbility )
        local string  effectString = ""
        
        call AddAbility( caster, SwapAbilityContainer )
        call SetPlayerAbilityAvailable( GetOwningPlayer(caster), SwapAbilityContainer, false )

        call AddAbility( caster, Cooldown )
        
        if IsPlayerAlly( GetLocalPlayer(), GetOwningPlayer(caster) ) then
            set effectString = "Abilities\\Spells\\Other\\HowlOfTerror\\HowlTarget.mdl"
            call PingMinimapEx( GetUnitX(target), GetUnitY(target), 2, 255, 255, 255, false )
        endif
        
        call IssueTargetOrder( caster, "move", target )
        call SetUnitPathing( caster, false )
        
        //Здесь нужно настраивать для моделей номер анимации Walk
        //У Rubick это 1
        //У Barathrum это 2
        if GetUnitTypeId( caster ) == GrandMagus then
            call SetUnitAnimationByIndex( caster, 1 )
        else
            call SetUnitAnimationByIndex( caster, 2 )
        endif
        
        call SetUnitTimeScale( caster, 2.5 )
        call SetPlayerAbilityAvailable( GetOwningPlayer(caster), SpellImmunity, false )
        call SetUnitVertexColor( caster, 255, 255, 255, 100 )
        
        call SaveUnitHandle  ( udg_dotaHash, trgH, 2   , caster                                                                                )
        call SaveUnitHandle  ( udg_dotaHash, trgH, 17  , target                                                                                )
        call SaveUnitHandle  ( udg_dotaHash, trgH, 19  , dummy                                                                                 )
        call SaveInteger     ( udg_dotaHash, trgH, 5   , abilityLvl                                                                            )
        call SaveReal        ( udg_dotaHash, trgH, 442 ,(TimerGetElapsed(udg_dotaTimer)+50)*1.0                                                )
        call SaveReal        ( udg_dotaHash, trgH, 23  , GetUnitX(caster)*1.0                                                                  )
        call SaveReal        ( udg_dotaHash, trgH, 24  , GetUnitY(caster)*1.0                                                                  )
        call SaveEffectHandle( udg_dotaHash, trgH, 175 , AddSpecialEffectTarget(effectString,target,"overhead")                                )
        call SaveEffectHandle( udg_dotaHash, trgH, 176 , AddSpecialEffectTarget(effectString,target,"overhead")                                )
        call SaveEffectHandle( udg_dotaHash, trgH, 177 , AddSpecialEffectTarget("war3mapImported\\ShockwaveMissilePurple.mdx",caster,"origin") )
        call SaveGroupHandle ( udg_dotaHash, trgH, 187 , GetGroup()                                                                            )
        
        call TriggerRegisterTimerEvent( trg, 0.02, true                             )
        call TriggerRegisterDeathEvent( trg, caster                                 )
        call TriggerRegisterDeathEvent( trg, target                                 )
        call TriggerRegisterUnitEvent ( trg, caster, EVENT_UNIT_ISSUED_ORDER        )
        call TriggerRegisterUnitEvent ( trg, caster, EVENT_UNIT_ISSUED_POINT_ORDER  )
        call TriggerRegisterUnitEvent ( trg, caster, EVENT_UNIT_ISSUED_TARGET_ORDER )
        call TriggerAddCondition( trg, Condition(function ChargeOfDarkness_Move) )
        
        set trg    = null
        set caster = null
        set target = null
        set dummy  = null
    endfunction

    private function ChargeOfDarkness_Conditions takes nothing returns boolean
        if GetSpellAbilityId() == ChargeOfDarknessAbility and BlockAbility( GetSpellTargetUnit() ) == false then
            call ChargeOfDarkness_Actions()
        elseif GetSpellAbilityId() == ChargeOfDarknessAbility then
            call IssueImmediateOrder( GetTriggerUnit(), "stop" )
        endif
        
        return false
    endfunction

    private function InitChargeOfDarkness takes nothing returns nothing
        local trigger trg = CreateTrigger()
        
        call AnyUnitEvent( trg, EVENT_PLAYER_UNIT_SPELL_EFFECT )
        call TriggerAddCondition( trg, Condition(function ChargeOfDarkness_Conditions) )
        
        call AbilityInit( Generic_Stun )
    endfunction
    
endlibrary
NetherStrike
library NetherStrike initializer InitNetherStrike requires OtherFunctions, GreaterBash
    
    
    globals
        
        private unit strike_caster = null
        
        define
            SpellImmunity       = 'A179' //Spell Immunity
            NetherStrikeAbility = 'A0G4' //Nether Strike
            NetherStrikeUpgrade = 'A1D8' //Nether Strike Upgrade
        enddefine
        
    endglobals
    
    
    private function NetherStrike_Bash takes unit caster, unit target returns nothing
        //Вызывает GreaterBash
        local trigger trg
        local integer trgH
        local real    angle = Atan2( GetUnitY(target)-GetUnitY(caster), GetUnitX(target)-GetUnitX(caster) )
        local integer i     = 4
    
        call GreaterBash( caster, target, true, true )
    
        set trg = null
    endfunction

    private function BashForGroup takes nothing returns nothing
        call NetherStrike_Bash( strike_caster, GetEnumUnit() )
    endfunction

    private function NetherStrike_AlternativeBash takes unit caster, unit target returns nothing
        //Используется только если уровень NetherStrike равен 0
        local group g = GetGroup()
    
        set global_caster = caster
        set strike_caster = caster
        call GroupEnumUnitsInRange( g, GetUnitX(caster), GetUnitY(caster), 275, Condition(function CheckUnit) )
        call ForGroup( g, function BashForGroup )
        call RecycleGroup( g )
    
        set g = null
    endfunction

    private function NetherStrike_Move takes nothing returns boolean
        //Используется для прыжка кастера
        local trigger trg             = GetTriggeringTrigger()
        local integer trgH            = GetHandleId( trg )
        local unit    caster          = LoadUnitHandle( udg_dotaHash, trgH, 2 )
        local unit    target          = LoadUnitHandle( udg_dotaHash, trgH, 17 )
        local integer trgCount        = GetTriggerEvalCount( trg )
        local integer alpha
        local integer abilityLvl
        local real    angle
        local real    targetX         = LoadReal( udg_dotaHash, trgH, 23 )
        local real    targetY         = LoadReal( udg_dotaHash, trgH, 24 )
        local real    current_targetX = GetUnitX( target )
        local real    current_targetY = GetUnitY( target )
        local real    distance        = DistanceBetweenCoordinates( current_targetX, current_targetY, targetX, targetY )
        
        call SaveReal( udg_dotaHash, trgH, 23, current_targetX*1.0 )
        call SaveReal( udg_dotaHash, trgH, 24, current_targetY*1.0 )
        
        if GetTriggerEventId() == EVENT_UNIT_DEATH or trgCount == 200 or distance > 1800 then
            //Отменяет способность если target или caster умирают. Или если расстояние между ними становится больше 1800
            //Или если прошло 0.1 секунды с момента прыжка
            call SetUnitVertexColor( caster, 255, 255, 255, 255 )
            call UnitShareVision( target, GetOwningPlayer(caster), false )
            call UnitRemoveAbility( caster, SpellImmunity )
            call FlushChildHashtable( udg_dotaHash, trgH )
            call DestroyTriggerEx( trg )
        else
            //Меняет прозрачность юнита из расчета на кол-во срабатываний триггера
            if trgCount < 100 then
                set alpha = trgCount
            else
                set alpha = 200-trgCount
            endif
            call SetUnitVertexColor( caster, 255, 255, 255, 255*(100-alpha)/100 )
            if trgCount == 100 then
                //Прыжок юнита
                set abilityLvl = LoadInteger( udg_dotaHash, trgH, 5 )
                set angle = Atan2( GetUnitY(target)-GetUnitY(caster), GetUnitX(target)-GetUnitX(caster) )
                call SetUnitPosition( caster, GetUnitX(target)+80*Cos(angle), GetUnitY(target)+80*Sin(angle) )
                call SetUnitAnimation( caster, "attack" )
                call IssueTargetOrder( caster, "attack", target )
                if GetUnitAbilityLevel( caster, NetherStrikeAbility ) > 0 then
                    call NetherStrike_Bash( caster, target )
                else
                    call NetherStrike_AlternativeBash( caster, target )
                endif
                call DamageToUnit( caster, target, 1, 50+100*abilityLvl )
            endif
        endif
        
        set trg    = null
        set caster = null
        set target = null
        
        return false
    endfunction

    private function NetherStrike_Start takes nothing returns nothing
        //Срабатывает спустя время подготовки заклинания
        local trigger trg        = CreateTrigger()
        local integer trgH       = GetHandleId( trg )
        local unit    caster     = GetTriggerUnit()
        local unit    target     = GetSpellTargetUnit()
        local integer abilityLvl = GetUnitAbilityLevel( caster, NetherStrikeAbility )
        
        if abilityLvl == 0 then
            set abilityLvl = GetUnitAbilityLevel( caster, NetherStrikeUpgrade )
        endif
        
        call UnitShareVision( target, GetOwningPlayer(caster), true )
        call IssueImmediateOrder( caster, "halt" )
        call SaveUnitHandle( udg_dotaHash, trgH, 2  , caster               )
        call SaveUnitHandle( udg_dotaHash, trgH, 17 , target               )
        call SaveInteger   ( udg_dotaHash, trgH, 5  , abilityLvl           )
        call SaveReal      ( udg_dotaHash, trgH, 23 , GetUnitX(target)*1.0 )
        call SaveReal      ( udg_dotaHash, trgH, 24 , GetUnitY(target)*1.0 )
        call TriggerRegisterTimerEvent( trg, 0.001, true )
        call TriggerRegisterUnitEvent( trg, caster, EVENT_UNIT_DEATH )
        call TriggerRegisterUnitEvent( trg, target, EVENT_UNIT_DEATH )
        call TriggerAddCondition( trg, Condition(function NetherStrike_Move) )
        call SetPlayerAbilityAvailable( GetOwningPlayer(caster), SpellImmunity, false )
        
        set trg    = null
        set caster = null
        set target = null
    endfunction

    private function PlayAnimation takes nothing returns boolean
        //Проигрывание анимации
        local trigger trg    = GetTriggeringTrigger()
        local integer trgH   = GetHandleId( trg )
        local unit    caster = LoadUnitHandle( udg_dotaHash, trgH, 2 )
        
        call SetUnitAnimation( caster, "spell morph" )
        call FlushChildHashtable( udg_dotaHash, trgH )
        
        call DestroyTriggerEx( trg )
        
        set trg    = null
        set caster = null
        
        return false
    endfunction

    private function ShareVision takes nothing returns boolean
        local trigger trg    = GetTriggeringTrigger()
        local integer trgH   = GetHandleId( trg )
        local unit    caster = LoadUnitHandle( udg_dotaHash, trgH, 2  )
        local unit    target = LoadUnitHandle( udg_dotaHash, trgH, 17 )
        
        call UnitShareVision( target, GetOwningPlayer(caster), false )
        call FlushChildHashtable( udg_dotaHash, trgH )
        call DestroyTriggerEx( trg )

        
        set trg    = null
        set caster = null
        set target = null
        
        return false
    endfunction
    
    private function NetherStrike_Channel takes nothing returns nothing
        //Срабатывает когда кастер нажимает способность на цель
        local trigger trg    = CreateTrigger()
        local integer trgH   = GetHandleId(trg)
        local unit    caster = GetTriggerUnit()
        
        call SaveUnitHandle( udg_dotaHash, trgH, 2, caster )
        call TriggerRegisterTimerEvent( trg, 0., true )
        call TriggerAddCondition( trg, Condition(function PlayAnimation) )
        set trg  = CreateTrigger()
        set trgH = GetHandleId( trg )
        call SaveUnitHandle( udg_dotaHash, trgH, 2, caster )
        call SaveUnitHandle( udg_dotaHash, trgH, 17, GetSpellTargetUnit() )
        call TriggerRegisterTimerEvent( trg, 1., true )
        call TriggerAddCondition( trg, Condition(function ShareVision) )
        call UnitShareVision( GetSpellTargetUnit(), GetOwningPlayer(caster), true )
        
        set trg    = null
        set caster = null
    endfunction

    private function NetherStrike_Conditions takes nothing returns boolean
        if GetSpellAbilityId() == NetherStrikeAbility or GetSpellAbilityId() == NetherStrikeUpgrade then
            if BlockAbility(GetSpellTargetUnit()) == false then
                if GetTriggerEventId() == EVENT_PLAYER_UNIT_SPELL_EFFECT then
                    call NetherStrike_Start()
                elseif GetTriggerEventId() == EVENT_PLAYER_UNIT_SPELL_CHANNEL then
                    call NetherStrike_Channel()
                else
                    call IssueImmediateOrder( GetTriggerUnit(), "stop" )
                endif
            endif
        endif
        
        return false
    endfunction
    
    private function InitNetherStrike takes nothing returns nothing
        local trigger trg = CreateTrigger()
        
        call AnyUnitEvent( trg, EVENT_PLAYER_UNIT_SPELL_EFFECT  )
        call AnyUnitEvent( trg, EVENT_PLAYER_UNIT_SPELL_CHANNEL )
        call AnyUnitEvent( trg, EVENT_PLAYER_UNIT_SPELL_ENDCAST )
        call TriggerAddCondition( trg, Condition(function NetherStrike_Conditions) )
        
        set trg = null
    endfunction


endlibrary
EmpoweringHaste
library EmpoweringHaste initializer InitEmpoweringHaste requires OtherFunctions
    
    
    define
    
        EmpoweringHasteAbility = 'A004' //Empowering Haste
        EmpoweringHasteNormal  = 'A30W' //Empowering Haste Container - Normal
        EmpoweringHasteStrong  = 'A30H' //Empowering Haste Container - Strong
        EmpoweringHasteWeak    = 'A30P' //Empowering Haste Container - Weak
    
    enddefine
    
    
    private function EmpoweringHaste_Normal takes nothing returns boolean
        //Возвращение в нормальную скорость перемещения
        local trigger trg        = GetTriggeringTrigger()
        local integer trgH       = GetHandleId( trg )
        local unit    caster     = LoadUnitHandle( udg_dotaHash, trgH, 2 )
        local integer abilityLvl = GetUnitAbilityLevel( caster, EmpoweringHasteAbility )
    
        call UnitRemoveAbility( caster, EmpoweringHasteNormal )
        call UnitRemoveAbility( caster, EmpoweringHasteWeak )
        call AddAbility( caster, EmpoweringHasteNormal )
        call SetUnitAbilityLevel( caster, EmpoweringHasteNormal,abilityLvl )
        call FlushChildHashtable( udg_dotaHash, trgH )
        call DestroyTriggerEx( trg )
    
        set trg    = null
        set caster = null
    
        return false
    endfunction

    private function EmpoweringHaste_Weak takes nothing returns boolean
        //Изменение скорости на минимальную скорость перемещения
        local trigger trg        = GetTriggeringTrigger()
        local integer trgH       = GetHandleId( trg )
        local unit    caster     = LoadUnitHandle( udg_dotaHash, trgH, 2 )
        local integer abilityLvl = GetUnitAbilityLevel( caster, EmpoweringHasteAbility )
    
        call UnitRemoveAbility( caster, EmpoweringHasteNormal )
        call UnitRemoveAbility( caster, EmpoweringHasteStrong )
        call AddAbility( caster, EmpoweringHasteWeak )
        call SetUnitAbilityLevel( caster, EmpoweringHasteWeak, abilityLvl )
        call FlushChildHashtable( udg_dotaHash, trgH )
        call DestroyTriggerEx( trg )
        set trg  = CreateTrigger()
        set trgH = GetHandleId( trg )
        call TriggerRegisterTimerEvent( trg, 10, false )
        call TriggerAddCondition( trg, Condition(function EmpoweringHaste_Normal) )
        call SaveUnitHandle( udg_dotaHash, trgH, 2, caster )
    
        set trg    = null
        set caster = null
    
        return false
    endfunction

    private function EmpoweringHaste_Actions takes nothing returns nothing
        //Изменение скорости на максимальную скорость перемещения
        local trigger trg        = CreateTrigger()
        local integer trgH       = GetHandleId( trg )
        local unit    caster     = GetTriggerUnit()
        local integer abilityLvl = GetUnitAbilityLevel( caster, EmpoweringHasteAbility )
        
        call TriggerRegisterTimerEvent( trg, 6, false )
        call TriggerAddCondition( trg, Condition(function EmpoweringHaste_Weak) )
        call SaveUnitHandle( udg_dotaHash, trgH, 2, caster )
        call UnitRemoveAbility( caster, EmpoweringHasteNormal )
        call UnitRemoveAbility( caster, EmpoweringHasteWeak )
        call AddAbility( caster, EmpoweringHasteStrong )
        call SetUnitAbilityLevel( caster, EmpoweringHasteStrong, abilityLvl )
    
        set trg    = null
        set caster = null
    endfunction

    private function EmpoweringHaste_Conditions takes nothing returns boolean
        if GetSpellAbilityId() == EmpoweringHasteAbility then
            call EmpoweringHaste_Actions()
        endif
    
        return false
    endfunction

    private function PermanentBonus_Actions takes nothing returns nothing
        //Получение постоянного бонуса при изучении EmpoweringHaste
        local integer abilityLvl = GetUnitAbilityLevel( GetTriggerUnit(), EmpoweringHasteAbility )
    
        call SetPlayerAbilityAvailable( GetOwningPlayer(GetTriggerUnit()), EmpoweringHasteStrong, false )
        call SetPlayerAbilityAvailable( GetOwningPlayer(GetTriggerUnit()), EmpoweringHasteNormal, false )
        call SetPlayerAbilityAvailable( GetOwningPlayer(GetTriggerUnit()), EmpoweringHasteWeak, false )
        call AddAbility( GetTriggerUnit(), EmpoweringHasteNormal )
        call SetUnitAbilityLevel( GetTriggerUnit(), EmpoweringHasteNormal, abilityLvl )
    endfunction

    private function PermanentBonus_Conditions takes nothing returns boolean
        if GetLearnedSkill() == EmpoweringHasteAbility and IsUnitIllusion(GetTriggerUnit()) == false then
            call PermanentBonus_Actions()
        endif
    
        return false
    endfunction

    private function InitEmpoweringHaste takes nothing returns nothing
        local trigger trg = CreateTrigger()
    
        call AnyUnitEvent( trg, EVENT_PLAYER_HERO_SKILL )
        call TriggerAddCondition( trg, Condition(function PermanentBonus_Conditions) )
        set trg = CreateTrigger()
        call AnyUnitEvent( trg, EVENT_PLAYER_UNIT_SPELL_EFFECT )
        call TriggerAddCondition( trg, Condition(function EmpoweringHaste_Conditions) )
    
        set trg = null
    endfunction
    

endlibrary
GreaterBash
library GreaterBash initializer InitGreaterBash requires OtherFunctions

    
    define
        
        trgTime = 3 //Время удаления временного бонуса к скорости, который дается при срабатывании GreaterBash
        
        SpiritbashContainer = 'A24H' //Spiritbash Container
        SpiritbashBuff      = 'B0EC' //Spiritbash
        GreaterBashAbility  = 'A0G5' //Greater Bash
        Spellcaster         = 'e00E' //Spellcaster
        GreaterBashStun     = 'A1WQ' //Greater Bash Stun
        
    enddefine


    private function SpeedBonusRemove takes nothing returns boolean
        //Удаляет бонус к скорости
        local trigger trg      = GetTriggeringTrigger()
        local integer trgH     = GetHandleId( trg )
        local unit    attacker = LoadUnitHandle( udg_dotaHash, trgH, 2 )
        local real    time     = LoadReal( udg_dotaHash, GetHandleId(attacker), 685 )
        
        call FlushChildHashtable( udg_dotaHash, trgH )
        call DestroyTriggerEx( trg )
        if time < TimerGetElapsed(udg_dotaTimer) or GetTriggerEventId() == EVENT_WIDGET_DEATH then
            call SaveReal( udg_dotaHash, GetHandleId(attacker), 685, 0*1.0 )
            call UnitRemoveAbility( attacker, SpiritbashContainer )
            call UnitRemoveAbility( attacker, SpiritbashBuff )
        endif
    
        set trg      = null
        set attacker = null
    
        return false
    endfunction

    private function SpeedBonus takes unit u returns nothing
        //Добавляет бонус к скорости после срабатывания GreaterBash
        local trigger trg  = CreateTrigger()
        local integer trgH = GetHandleId( trg )
    
        call AddAbility( u, SpiritbashContainer )
        call SetPlayerAbilityAvailable( GetOwningPlayer(u), SpiritbashContainer, false )
        call SaveReal( udg_dotaHash, GetHandleId(u), 685, (TimerGetElapsed(udg_dotaTimer)+trgTime-0.01)*1.0)
        call TriggerRegisterTimerEvent( trg, trgTime, false )
        call TriggerRegisterDeathEvent( trg, u )
        call TriggerAddCondition( trg, Condition(function SpeedBonusRemove) )
        call SaveUnitHandle( udg_dotaHash, trgH, 2, u )
    
        set trg = null
    endfunction

    private function GreaterBash_Actions takes nothing returns boolean
        //Отталкивание юнита
        local trigger trg      = GetTriggeringTrigger()
        local integer trgH     = GetHandleId( trg )
        local unit    target   = LoadUnitHandle( udg_dotaHash, trgH, 17 )
        local unit    attacker = LoadUnitHandle( udg_dotaHash, trgH, 2 )
        local real    angle    = LoadReal( udg_dotaHash, trgH, 13 )
        local real    x        = GetUnitX( target )
        local real    y        = GetUnitY( target )
        local integer trgCount = GetTriggerEvalCount( trg )
        local real    r        = LoadReal( udg_dotaHash, trgH, 193 )
        local integer i        = LoadInteger( udg_dotaHash, trgH, 12 )
    
        if trgCount > 35 then
            call SaveReal( udg_dotaHash, trgH, 193, (r*0.98)*1.0 )
        endif
        if GetTriggerEventId() == EVENT_UNIT_DEATH or trgCount > i then
            call FlushChildHashtable( udg_dotaHash, trgH )
            call DestroyTriggerEx( trg )
        else
            call DestroyEffect( AddSpecialEffect("Abilities\\Spells\\Human\\FlakCannons\\FlakTarget.mdl", x, y) )
            call KillDestructables( x, y, 150 )
            set x = SafeRealX( x+r*Cos(angle) )
            set y = SafeRealY( y+r*Sin(angle) )
            if IsPointInRegion(global_region, x*1.0, y*1.0) == false then
                call SetUnitX( target, x )
                call SetUnitY( target, y )
            endif
            if trgCount == 1 and LoadBoolean(udg_dotaHash, trgH, 698) == false then
                call IssueTargetOrder( attacker, "attack", target )
            endif
        endif
    
        set trg      = null
        set target   = null
        set attacker = null
    
        return false
    endfunction

    function GreaterBash takes unit attacker, unit target, boolean b, boolean off returns nothing
        local trigger trg
        local integer trgH
        local real    angle      = Atan2( GetUnitY(target)-GetUnitY(attacker), GetUnitX(target)-GetUnitX(attacker) )
        local integer abilityLvl = GetUnitAbilityLevel( attacker, GreaterBashAbility )
        local unit    dummy
    
        if b then
        endif
        //Здесь нужно указывать все способности или бафы, имея которые не будет срабатывать GreaterBash
        //Оригинал:
        //if abilityLvl > 0 and GetUnitAbilityLevel(attacker, 'BNdo') == 0 then
        if abilityLvl > 0 then
            set dummy = CreateUnit( GetOwningPlayer(target), Spellcaster, GetUnitX(target), GetUnitY(target), 0 )
            call AddAbility( dummy, GreaterBashStun )
            call SetUnitAbilityLevel( dummy, GreaterBashStun, abilityLvl )
            if IssueTargetOrder( dummy, "thunderbolt", target ) then
                //Если можно кинуть стан на цель, значит сработает отталкивание юнита
                set trg  = CreateTrigger()
                set trgH = GetHandleId( trg )
                call DestroyEffect( AddSpecialEffectTarget("Abilities\\Weapons\\PhoenixMissile\\Phoenix_Missile_mini.mdl", attacker, "weapon") )
                call SaveUnitHandle( udg_dotaHash, trgH, 2   , attacker         )
                call SaveUnitHandle( udg_dotaHash, trgH, 17  , target           )
                call SaveReal      ( udg_dotaHash, trgH, 13  , angle*1.0        )
                call SaveReal      ( udg_dotaHash, trgH, 193 , 2*1.0            )
                call SaveBoolean   ( udg_dotaHash, trgH, 698 , off              )
                call SaveInteger   ( udg_dotaHash, trgH, 12  , 80+20*abilityLvl )
                call TriggerRegisterUnitEvent( trg,target, EVENT_UNIT_DEATH )
                call TriggerRegisterTimerEvent( trg, 0.01, true)
                call TriggerAddCondition( trg, Condition(function GreaterBash_Actions) )
                call DamageToUnit( attacker, target, 1, GetUnitMoveSpeed(attacker)*(0.16+0.06*abilityLvl) )
                call SpeedBonus( attacker )
            endif
            if off == false then
                call BashOff( attacker, 4276, 1.5 )
            endif
        endif
    
        set trg      = null
        set attacker = null
        set target   = null
        set dummy    = null
    endfunction

    private function GreaterBash_Conditions takes nothing returns boolean
        //Здесь дополнительная проверка чтобы GreaterBash при атаке не срабатывал повторно в течении 1.5 секунды
        if GetUnitAbilityLevel(GetAttacker(), GreaterBashAbility) > 0 and IsUnitIllusion(GetAttacker()) == false and IsUnitType(GetTriggerUnit(), UNIT_TYPE_STRUCTURE) == false and IsUnitEnemy(GetTriggerUnit(), GetOwningPlayer(GetAttacker()))and GetRandomInt(1, 100) <= 17 and ( LoadInteger(udg_dotaHash,GetHandleId(GetAttacker()), 4276) == 1 ) == false then
            call GreaterBash( GetAttacker(), GetTriggerUnit(), false, false )
        endif
    
        return false
    endfunction

    private function InitGreaterBash takes nothing returns nothing
        local trigger trg = CreateTrigger()
    
        call AnyUnitEvent( trg, EVENT_PLAYER_UNIT_ATTACKED )
        call TriggerAddCondition( trg, Condition(function GreaterBash_Conditions) )
    
        set trg = null
    endfunction


endlibrary
`
ОЖИДАНИЕ РЕКЛАМЫ...

Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
0
32
6 лет назад
0
Странновато изменил код, совсем минимум комментов, а так же ни слова про баги.
0
18
6 лет назад
Отредактирован Hodor
0
quq_CCCP:
Странновато изменил код
я кроме встраивания констант, ничего не менял (у меня уже есть готовый код с define)
0
12
6 лет назад
0
Благодарю за работу.Очень инетересно было поглядет и дотерские системы тоже. Как думаете за его ресайкл групп большие возможности, разве 120 групп хватает на всю игру?
0
18
6 лет назад
0
Daro группы очищаются и повторно используются
5
28
6 лет назад
Отредактирован nvc123
5
ClotPh:
nvc123, ятп, у фрога по удобному именно ему шаблону, чтобы именно у него голова кодить не болела
ты хоть сам понимаешь что написал?
дота собрана из множества куч говна сделанных разными людьми и держащихся на костылях
одно время некоторые пытались привести всё это в порядок но всё закончилось ещё несколькими костылями которые просто не позволяют всему этому говну сильно утекать
ибо переписать всю эту кучу говна займёт кучу времени
0
32
6 лет назад
Отредактирован quq_CCCP
0
ClotPh, фрог не кодер, ваще на гуи писал а его кодер переводил в jass, сравните разные способности героев и системы, вы удивитесь насколько они непохожи, реализация одних и тех же вещей бывает очень различной. У фрога был очень хороший кодер который в торопях делал переводил все в jass или исправлял баги фрога, как только фрог остался без кодера - он забил на доту для варкравта, ибо был совершенно не способен вносить изменения в карту.
UrsaBoss, что то невижу функции о переполнении массива триггеров, о Retalitation тоже не слова, в дота системе нету "Dummy_Control", удаляет спустя 20 сек. всех даммиков которые появились на карте, вспомни функцию нанесения урона, что там в 6 пункте?
тут радостные хомяки понакопируют, а потом будут плакать а че оно утечки, багует, и так далее....
0
21
6 лет назад
0
nvc123, и, что характерно, именно дота пришла к успеху )))
лучшие идеи именно у тех людей, которые не способны реализовать их без посторонней помощи
ну или без особой своей системы...
0
18
6 лет назад
0
quq_CCCP:
реализация одних и тех же вещей бывает очень различной
это я заметил) В одних местах очень сильно заметен перевод из гуи, а в других местах бывает есть лишние "(" и ")", сразу видно что разные люди работали над кодом.
quq_CCCP:
что то невижу функции о переполнении массива триггеров
Эта функция? (я её вырезал, она вроде на функционал не влияет)
function Func0033 takes nothing returns nothing
    local integer i = 0
    if boolean036 == false and boolean098 == false then
        loop
            call DisplayTimedTextToPlayer(Player(i), 0, 0, 120, "|c00ff0303An internal checksum has failed|r" )
            call DisplayTimedTextToPlayer(Player(i), 0, 0, 120, "|c00ff0303This might not be a serious glitch, but it is important for me to get it|r" )
            call DisplayTimedTextToPlayer(Player(i), 0, 0, 120, "|c00ff0303Please send me the replay for this game to IceFrog@gmail.com|r" )
            set i = i+1
            exitwhen i == 12
        endloop
    endif
endfunction
quq_CCCP:
в дота системе нету "Dummy_Control", удаляет спустя 20 сек. всех даммиков которые появились на карте
я нашел только 1 ярко выраженный гуи триггер, чтобы даммикам 'e00E' и 'e022' давать BTLF на 20 сек, я там убрал почти все BJ функции и оставил только для 'e00E' даммика
0
32
6 лет назад
0
UrsaBoss, ну ты еще забываешь про оптимизатор векса, и прочие тулы, векс есть в титрах карты.
Кстати, не забудь написать о багах.
0
18
6 лет назад
Отредактирован Hodor
0
quq_CCCP
Кстати, не забудь написать о багах.
например бара начинает бежать и иногда у него какое то время всё ещё играет stand?
0
32
6 лет назад
0
UrsaBoss, точно багов позлее не заметил?
Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.