Кел'Тузад из Heroes of the Storm

» опубликован
» Способ реализации: Jass
» Тип: Способность
» Версия Warcraft: 1.29+
Наработка героя Кел'Тузада из игры Heroes of the Storm. Способности MUI. Критика приветствуется.
» Список изменений:
» 1.3
Глобальное обновление: добавлены официальные характеристики урона, здоровья, скорости восстановления и т.д. Теперь требуется версия Warcraft 1.29+
"Ледяной взрыв" теперь корректно летит до трупа.
Изменение "Цепей Кел'Тузада": ускорение притягивание к зданиям, дамми цепей заменены на молнию с текстурой цепей, притягивание больше не работает вплотную.
Исправлен баг, когда область "Смерть и разложение" смещалась в сторону (дамми).
Небольшие изменения в скриптах.
Исправлено описание способности "Цепи Кел'Тузада" при имеющейся цели с эффектом "Цепей".
Бар "Цепей Кел'Тузада" стал локальным.
Замена модели "Ледового шипа".
» 1.2.2
Небольшая переработка "Цепей Кел'Тузада": ускорено притягивание, оглушение срабатывает при притягивании вместо того, чтобы срабатывать при попадании "Цепями".
Снаряды теперь летят от героя до указанной точки (ранее от героя + некоторое расстояние).
Небольшая работа над эффектами.
» 1.2.1
Немного переделана пауза у "Ледового шипа".
Эффект молнии возвращен (нет, у меня не биополярное расстройство :D).
Правка быстрого притягивания Цепей.
Оптимизация скриптов.
Добавлена модель Лича (спасибо Daro).
» 1.2
Кел'Тузад изменен (не полностью) в связи с последним обновлением:
Добавлена новая способность – Ледовый шип.
Иконки заменены на "родные" из HotS.
Перезарядка и затраты маны из HotS.
Заменен и исправлен эффект молнии.
Исправление эффектов.
Исправлены мелкие ошибки.
Удалены лишние баффы.
Убрана тень дамми снаряда способности "Смерть и разложение" [Q].
» 1.1.4
Смерть и разложение теперь вновь взрывается там, где она попадает по цели, а не в местоположение цели.
Исправление начального местоположения Ледяного взрыва.
Ледяной взрыв немного уменьшен.
Внедрение в юнита числа handle заменен на массив, который его вбирает по номеру массива юнита (Цепи Кел'Тузада).
Правка Цепей Кел'Тузада в MUI.
Добавлено видео последней версии наработки.
Убрана анимация у способности "Владыка холодной тьмы".
» 1.1.3
Цепями теперь можно притягивать и зданием, если оно носит на себе цепь.
Комментарий: из-за моей невнимательности и игры в "пробном" режиме за Кел'Тузада я не заметил баг, из-за которого цепи застревали в здании, а значит, и не притягивали к себе союзную цель.
Ледяной взрыв больше не восстанавливается при смерти запомненной цели, если снаряд еще не долетел до нее, вместо этого он продолжает лететь до трупа.
Изменение скорости и высоты Ледяного взрыва, теперь как в HotS (полет по наклонной + ускорение). Спасибо за помощь одному очень хорошему человечку.
Мелкие правки.
» 1.1
Заменено триггерное замедление и обездвиживание на War'овское.
Чуть изменен принцип Цепей, визуально ничего не поменялось.
Способности применяются мгновенно, как и в HotS.
Глобальные переменные вынесены в триггер объявления глобальных переменных: копировать глобальные переменные теперь не нужно.
Исправлено применение способности "Смерть и разложение".
Удалены лишние скрипты.
» 1.0
Первая версия.
Инструкция по импорту:
  1. скопировать импортируемые модели, удалив лишний путь "war3mapImported\", заклинания, способности, после юнитов.
  2. скопировать код и в нем изменить равкод юнитов и применяемых способностей. (например: 'A000' на тот, что в РО (редакторе объектов). Название и равкод переменных можно посмотреть с помощью сочетания клавиш Ctrl + D.
  3. триггерно создавать/нанимать/и т.д. Кел'Тузадов. Главное – войти в в игровую зону.
Описание:
  • Смерть и разложение: "После паузы в 0,5 сек. запускает сферу, которая взрывается, попав в первую цель на своем пути, и наносит 150 (+2.5% за уровень) ед. урона противникам в области действия. После взрыва остается область разложения, которая существует 2 сек. и каждые 0,5 сек. наносит попавшим в нее противникам 82 (+2.5% за уровень) ед. урона."
  • Кольцо льда: "Создает кольцо, которое после паузы в 1 сек. взрывается, наносит противникам в области действия 180 (+2.5% за уровень) ед. урона и замедляет их на 35% на 2,5 сек. Обездвиживает противников, находящихся в эпицентре, на 1 сек."
  • Цепи Кел'Тузада: "Запускает цепь, наносящую первому герою или строению на своем пути 97 (+2.5% за уровень) ед. урона. В течение 4 сек. после попадания эту способность можно использовать повторно, чтобы запустить цепь во второго противника, притянуть обе цели друг к другу и оглушить их на 0,5 сек."
    "Выпускает новую цепь от первой цели. Если вторая цель попадает в героя или здание, наносит 97 (+2,5% за уровень) урона и притягивает обе цели друг к другу."
    Примечание: В MUI носящий цепь и притягиваемый юниты не могут быть сцеплены повторно в течение 4 секунд или пока герой-владелец не воспользуется Цепями еще раз, для цепей нужна "свежая" цель.
  • Владыка холодной тьмы:
    (!)Задача: каждый раз, когда Кел'Тузад обездвиживает героев "Кольцом льда" или попадает в них "Цепями Кел'Тузада", он получает 1 ед. "Чумы".
    (!)Награда: после накопления 15 ед. "Чумы" Кел'Тузад получает способность "Ледовый шип".
    (!)Награда: после накопления 30 ед. "Чумы" сила способностей повышается на 75%.
    Примечание: способность применяемая и не сбивает приказ (сделано для того, чтобы узнать, сколько Кел'Тузад накопил "Чумы").
  • Ледовый шип (дополнительная способность): "При использовании создает шип, который взрывается после паузы в 4 сек. и наносит 61 (+2.5% за уровень) ед. урона противникам поблизости. «Цепи Кел'Тузада» могут воздействовать на шип. Выполните задачу, чтобы использовать."
    Примечание: в обновлении 36.2 Кел'Тузад утратил способность прикреплять цепи к зданиям и наоборот взамен на новую способность "Ледовый шип". В своей наработке я оставил эту возможность, ибо она слишком крутая.
  • Ледяной взрыв (1 ульт): "Выпускает во вражеского героя ледяной заряд, который наносит 115 (+2.5% за уровень) ед. урона цели и 275 (+2.5% за уровень) ед. урона противникам в области поражения. Обездвиживает всех пораженных противников на 1,5 сек."
  • Прорыв тьмы (2 ульт): "Создает в любой точке поля боя энергетический разлом, который после паузы в 1,5 сек. взрывается и наносит 360 (+2.5% за уровень) ед. урона находящимся в ней героям."
» Код
» Смерть и разложение
function DaD_Cond takes nothing returns boolean
    return GetSpellAbilityId()=='ADaD'
endfunction

function DaD_Rect takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer h = GetHandleId(t)
    local unit caster = LoadUnitHandle(Hash,h,1)
    local unit dummy = LoadUnitHandle(Hash,h,2)
    local real xRect = LoadReal(Hash,h,3)
    local real yRect = LoadReal(Hash,h,4)
    local real Frect = 125
    local unit enemy
    local real time = LoadReal(Hash,h,5)
    local effect e = LoadEffectHandle(Hash,h,6)
    local integer data = GetUnitUserData(caster)
    local real damage = DamageDaDRect[0][data]
    local player PlayerEnemy
    local player PlayerCaster = GetOwningPlayer(caster)
    local group G = CreateGroup()
    set time = time + 0.5
    call SaveReal(Hash,h,5,time)
    if GetUnitAbilityLevel(caster, 'SPAS') == 3 then
        set damage = damage + (damage * 0.75)
    endif
    call GroupEnumUnitsInRange(G, xRect, yRect, Frect, null)
        loop
            set enemy = FirstOfGroup(G)
            set PlayerEnemy = GetOwningPlayer(enemy)
            if IsPlayerEnemy(PlayerEnemy, PlayerCaster) and GetWidgetLife( enemy ) >.405 then
                call UnitDamageTarget( caster, enemy, damage, true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_DEATH, null )
            endif
            call GroupRemoveUnit(G,enemy)
            exitwhen enemy == null
        endloop

        if time >= 2 then
            call DestroyEffect(e)
            call RemoveUnit(dummy)
            call FlushChildHashtable(Hash,h)
            call PauseTimer(t)
            call DestroyTimer (t)
        endif
    call GroupClear(G)
    call DestroyGroup(G)
    set t = null
    set caster = null
    set dummy = null
    set e = null
    set G = null
endfunction

function DaD_Move takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer h = GetHandleId(t)
    local unit dad = LoadUnitHandle(Hash,h,1)
    local unit caster = LoadUnitHandle(Hash,h,2)
    local real face = GetUnitFacing(dad)
    local real path = LoadReal(Hash,h,'Path')
    local group G = CreateGroup()
    local unit enemy
    local player PlayerEnemy
    local player PlayerCaster = GetOwningPlayer(caster)
    local integer data = GetUnitUserData(caster)
    local real damage = DamageDaD[0][data]
    local real distance = 600.00
    local real x = GetUnitX(dad) + 10 * Cos(face* bj_DEGTORAD)
    local real y = GetUnitY(dad) + 10 * Sin(face* bj_DEGTORAD)
    local real obl = 60.00
    local boolean b = false
    call SetUnitX(dad, x)
    call SetUnitY(dad, y)
    if GetUnitAbilityLevel(caster, 'SPAS') == 3 then
        set damage = damage + (damage * 0.75)
    endif
    set path = path + 10.00
    call SaveReal(Hash,h,'Path', path)
    call GroupEnumUnitsInRange(G, x, y, obl, null)
        loop
            set enemy = FirstOfGroup(G)
            set PlayerEnemy = GetOwningPlayer(enemy)
            if (IsPlayerEnemy(PlayerEnemy, PlayerCaster)) and GetWidgetLife( enemy ) >.405 then
                set b = true
                call UnitDamageTarget( caster, enemy, damage, true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_DEATH, null )
            endif
            call GroupRemoveUnit(G,enemy)
            exitwhen enemy == null or b == true
        endloop

    call GroupClear(G)
    call DestroyGroup(G)
        
    if b == true then
        local timer k = CreateTimer()
        local integer g = GetHandleId(k)
        local unit dummy = CreateUnit( PlayerCaster, 'h002', x, y, 0 )
        local string str = "Abilities\\Spells\\Undead\\DeathandDecay\\DeathandDecayDamage.mdl"
        local effect e = AddSpecialEffect(str,x,y)
        call RemoveUnit(dad)
        call SaveUnitHandle(Hash,g,1,caster)
        call SaveUnitHandle(Hash,g,2,dummy)
        call SaveEffectHandle(Hash,g,6,e)
        call SaveReal(Hash,g,3,x)
        call SaveReal(Hash,g,4,y)
        call FlushChildHashtable(Hash,h)
        call PauseTimer(t)
        call DestroyTimer(t)
        TimerStart(k,0.5,true,function DaD_Rect)
        set dummy = null
        set k = null
        set e = null
    endif

    if path >= distance then
        call RemoveUnit(dad)
        call FlushChildHashtable(Hash,h)
        call PauseTimer(t)
        call DestroyTimer(t)
    endif
    
    set t = null
    set dad = null
    set caster = null
    set G = null
endfunction

function DaD_Cast takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer h = GetHandleId(t)
    local unit caster = LoadUnitHandle(Hash,h,2)
    local player PlayerCaster = GetOwningPlayer(caster)
    local real X1 = LoadReal(Hash,h,3)
    local real X2 = GetUnitX(caster)
    local real Y1 = LoadReal(Hash,h,4)
    local real Y2 = GetUnitY(caster)
    local real angle = Atan2(Y1 - Y2, X1 - X2)
    local real x = X2 + 1 * Cos(angle)
    local real y = Y2 + 1 * Sin(angle)
    local unit dad = CreateUnit( PlayerCaster, 'h001', x, y, angle*bj_RADTODEG )
    local effect e = LoadEffectHandle(Hash,h,5)
    local boolean spell = GetUnitCurrentOrder(caster) == 852089
    call SetUnitPropWindow(dad, 0)
    if spell == true and IsUnitType(caster, UNIT_TYPE_STUNNED) == false or GetWidgetLife( caster ) >.405  then
        local timer k = CreateTimer()
        local integer i = GetHandleId(k)
        call SetUnitX(dad, x)
        call SetUnitY(dad, y)
        call SaveUnitHandle(Hash,i,1,dad)
        call SaveUnitHandle(Hash,i,2,caster)
        call TimerStart(k,.01,true,function DaD_Move)
        set k = null
    endif
    call DestroyEffect(e)
    call FlushChildHashtable(Hash,h)
    call PauseTimer(t)
    call DestroyTimer(t)
    set t = null
    set dad = null
    set caster = null
    set e = null
endfunction

function DaD takes nothing returns nothing
    local timer t = CreateTimer()
    local integer h = GetHandleId(t)
    local unit caster = GetTriggerUnit()
    local real X1 = GetSpellTargetX()
    local real Y1 = GetSpellTargetY()
    local string eff1 = "Abilities\\Spells\\Items\\OrbCorruption\\OrbCorruptionMissile.mdl"
    local string attach = "hand"
    local effect e = AddSpecialEffectTarget(eff1, caster, attach)
    call SetUnitAnimationByIndex(caster,5)
    call QueueUnitAnimation(caster,"stand")
    call SaveUnitHandle(Hash,h,2,caster)
    call SaveReal(Hash,h,3,X1)
    call SaveReal(Hash,h,4,Y1)
    call SaveEffectHandle(Hash,h,5,e)
    call TimerStart(t,.5,false,function DaD_Cast)
    set e = null
    set t = null
    set caster = null
endfunction
» Кольцо льда
function RoI_Cond takes nothing returns boolean
    return GetSpellAbilityId()=='ARoI'
endfunction

function RoI_Slowdown takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer h = GetHandleId(t)
    local unit caster = LoadUnitHandle(Hash,h,1)
    local player PlayerEnemy
    local player PlayerCaster = GetOwningPlayer(caster)
    local real x
    local real y
    local real face
    local integer data = GetUnitUserData(caster)
    local real damage = DamageRoI[0][data]
    local integer n = GetUnitUserData(caster)
    local unit enemy = GetEnumUnit()
    local effect e
    
        if GetUnitAbilityLevel(caster, 'SPAS') == 3 then
            set damage = damage + (damage * 0.75)
        endif

            set PlayerEnemy = GetOwningPlayer(enemy)
            if IsPlayerEnemy(PlayerEnemy, PlayerCaster) and GetWidgetLife( enemy ) >.405 then
                call UnitDamageTarget( caster, enemy, damage, true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_COLD, null )
                set x = GetUnitX(enemy)
                set y = GetUnitY(enemy)
                set face = GetUnitFacing(enemy)
                if GetWidgetLife(enemy) > .405 then
                    local unit dummy = CreateUnit(PlayerCaster,'h006',x,y,face)
                    call IssueTargetOrder(dummy,"slow",enemy)
                    call UnitApplyTimedLife(dummy, 'BTFL', 0.1 )
                    call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Undead\\FrostNova\\FrostNovaTarget.mdl​", enemy, "origin"))
                    set dummy = null
                endif
            endif
    
    set t = null
    set caster = null
    set enemy = null
    set e = null

endfunction

function RoI_Rect takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer h = GetHandleId(t)
    local unit caster = LoadUnitHandle(Hash,h,1)
    local integer n = GetUnitUserData(caster)
    local integer c = QuestKelThuzad[n]
    local real xRect = LoadReal(Hash,h,2)
    local real yRect = LoadReal(Hash,h,3)
    local real Frect = 200
    local unit enemy
    local effect e = LoadEffectHandle(Hash,h,4)
    local integer data = GetUnitUserData(caster)
    local real damage = DamageRoI[0][data]
    local player PlayerEnemy
    local player PlayerCaster = GetOwningPlayer(caster)
    local group G = CreateGroup()
    call DestroyEffect(AddSpecialEffect("Abilities\\Spells\\Undead\\FreezingBreath\\FreezingBreathMissil​e.mdl", xRect, yRect))
    call DestroyEffect(AddSpecialEffect("Abilities\\Weapons\\LichMissile\\LichMissile.mdl", xRect, yRect))
    if GetUnitAbilityLevel(caster, 'SPAS') == 3 then
        set damage = damage + (damage * 0.75)
    endif
    call GroupEnumUnitsInRange(G, xRect, yRect, Frect, null)
    call ForGroup(G, function RoI_Slowdown)
    call GroupEnumUnitsInRange(G, xRect, yRect, Frect/2, null)
        loop
            set enemy = FirstOfGroup(G)
            set PlayerEnemy = GetOwningPlayer(enemy)
            if IsPlayerEnemy(PlayerEnemy, PlayerCaster) and GetWidgetLife( enemy ) >.405 then
                local real x = GetUnitX(enemy)
                local real y = GetUnitY(enemy)
                local real face = GetUnitFacing(enemy)
                local unit dummy = CreateUnit(PlayerCaster,'h006',x,y,face)
                call UnitRemoveAbility(dummy,'A003')
                call IssueTargetOrder(dummy,"entanglingroots",enemy)
                call UnitApplyTimedLife(dummy, 'BTFL', 0.1 )
                set dummy = null
                call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Undead\\FrostNova\\FrostNovaTarget.mdl​", enemy, "origin"))
                

                if IsUnitType(enemy, UNIT_TYPE_HERO) == true
                if QuestKelThuzad[n] < 15 and QuestKelThuzad[n] != -1 then
                    set QuestKelThuzad[n] = QuestKelThuzad[n] + 1
                endif
                    
                        if QuestKelThuzad[n] >= 15 and QuestKelThuzad[n] < 30 then
                            call BlzUnitDisableAbility( caster, 'AISK', false, false )
                            call SetUnitAbilityLevel( caster, 'AISK', 2 )
                            call SetUnitAbilityLevel( caster, 'SPAS', 2 )
                            set QuestKelThuzad[n] = QuestKelThuzad[n] + 1
                        endif
                        
                            if QuestKelThuzad[n] >= 30 then
                                set QuestKelThuzad[n] = -1
                                call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Human\\ReviveHuman\\ReviveHuman.mdl&qu​ot;, caster, "origin"))
                                call SetUnitAbilityLevel( caster, 'SPAS', 3 )
                            endif
                endif
            endif
            call GroupRemoveUnit(G,enemy)
            exitwhen enemy == null
        endloop

    if c != QuestKelThuzad[n] then
        call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Other\\TalkToMe\\TalkToMe.mdl", caster, "overhead"))
    endif

    call DestroyEffect(e)
    call GroupClear(G)
    call DestroyGroup(G)
    call FlushChildHashtable(Hash,h)
    call PauseTimer(t)
    call DestroyTimer(t)
    set t = null
    set caster = null
    set e = null
    set G = null
endfunction

function RoI takes nothing returns nothing
    local timer t = CreateTimer()
    local integer h = GetHandleId(t)
    local unit caster = GetTriggerUnit()
    local real X1 = GetSpellTargetX()
    local real Y1 = GetSpellTargetY()
    local string eff = "Shiva'sEnchantment.mdx"
    local effect e = AddSpecialEffect(eff, X1, Y1)
    call SaveUnitHandle(Hash,h,1,caster)
    call SaveReal(Hash,h,2,X1)
    call SaveReal(Hash,h,3,Y1)
    call SaveEffectHandle(Hash,h,4,e)
    call TimerStart(t,1,false,function RoI_Rect)
    set e = null
    set t = null
    set caster = null
endfunction
» Цепи Кел'Тузада
» Способность
function CoK_Cond takes nothing returns boolean
    return GetSpellAbilityId()=='ACoK'
endfunction

function CoK_MoveChain takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer h = GetHandleId(t)
    local unit caster = LoadUnitHandle(Hash,h,1)
    local unit chained = LoadUnitHandle(Hash,h,2)
    local unit enemy = LoadUnitHandle(Hash,h,3)
    local unit cok = LoadUnitHandle(Hash,h,7)
    local lightning chain = LoadLightningHandle(Hash,h,4)
    local integer data = GetUnitUserData(caster)
    local real damage = DamageCoK[0][data]
    local player PlayerCaster = GetOwningPlayer(caster)
    local real X1 = GetUnitX(enemy)
    local real Y1 = GetUnitY(enemy)
    local real X2 = GetUnitX(chained)
    local real Y2 = GetUnitY(chained)
    local real angle = Atan2(Y1 - Y2, X1 - X2)
    local real dist = SquareRoot((X2 - X1) * (X2 - X1) + (Y2 - Y1) * (Y2 - Y1))
    local real x1 = 0
    local real y1 = 0
    local real x2 = 0
    local real y2 = 0
    local real time = LoadReal(Hash,h,5)
    
    if time >= 0.1 or dist <= 120 then
    
    local boolean ifBool = IsUnitType(enemy, UNIT_TYPE_STRUCTURE) == true and GetUnitTypeId(chained) == 'hISK'
    local boolean elseBool = IsUnitType(chained, UNIT_TYPE_STRUCTURE) == true and GetUnitTypeId(enemy) == 'hISK'
    
    if IsUnitType(chained, UNIT_TYPE_STUNNED) == false or IsUnitType(enemy, UNIT_TYPE_STUNNED) == false then

        if IsUnitType(chained, UNIT_TYPE_STRUCTURE) == false then
            local unit dummyChained = CreateUnit( PlayerCaster, 'h006', X2, Y2, angle )
            call IssueTargetOrder(dummyChained,"thunderbolt",chained)
            call UnitApplyTimedLife(dummyChained, 'BTFL', 0.1 )
            set dummyChained = null
        endif

        if IsUnitType(enemy, UNIT_TYPE_STRUCTURE) == false then
            local unit dummyEnemy = CreateUnit( PlayerCaster, 'h006', X1, Y1, angle )
            call IssueTargetOrder(dummyEnemy,"thunderbolt",enemy)
            call UnitApplyTimedLife(dummyEnemy, 'BTFL', 0.1 )
            set dummyEnemy = null
        endif

    endif
    
    if dist <= 120 or enemy == null or chained == null or ifBool == true or elseBool == true then
        local integer i = GetUnitUserData(caster)
        local integer n = ChainedData[i]
        local unit dummy = LoadUnitHandle(Hash,n,3)
        local effect e = LoadEffectHandle(Hash,n,6)
        
        local real faceEnemy = GetUnitFacing(enemy)*-1
        local real xEnemy = GetUnitX(enemy) * Cos(faceEnemy* bj_DEGTORAD)
        local real yEnemy = GetUnitY(enemy) * Sin(faceEnemy* bj_DEGTORAD)
        local unit dummyEnemy = CreateUnit( PlayerCaster, 'h006', xEnemy, yEnemy, faceEnemy )

        local real faceChained = GetUnitFacing(chained)*-1
        local real xChained = GetUnitX(chained) * Cos(faceChained* bj_DEGTORAD)
        local real yChained = GetUnitY(chained) * Sin(faceChained* bj_DEGTORAD)
        local unit dummyChained = CreateUnit( PlayerCaster, 'h006', xChained, yChained, faceChained )
        
        call UnitRemoveAbility(chained, 'B001')
        call UnitRemoveAbility(enemy, 'B001')
            
        call UnitApplyTimedLife(dummyEnemy, 'BTFL', 0.1 )
        call UnitApplyTimedLife(dummyChained, 'BTFL', 0.1 )
        
        call IssueTargetOrder(dummyEnemy,"thunderbolt",enemy)
        call IssueTargetOrder(dummyChained,"thunderbolt",chained)
        
        if GetUnitAbilityLevel(caster, 'SPAS') == 3 then
            set damage = damage + (damage * 0.75)
        endif
        
        call PauseUnit(enemy, false)
        call PauseUnit(chained, false)
        call DestroyLightning(chain)
        call KillUnit(dummy)
        call RemoveUnit(cok)
        call DestroyEffect(e)
        call UnitDamageTarget( caster, enemy, damage, true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_NORMAL, null )
        call FlushChildHashtable(Hash,n)
        call FlushChildHashtable(Hash,h)
        call PauseTimer(t)
        call DestroyTimer(t)
        set dummyEnemy = null
        set dummyChained = null
        set dummy = null
        set e = null
        
    else
        if IsUnitType(chained, UNIT_TYPE_STRUCTURE) == false and GetUnitTypeId(chained) != 'hISK' then
            set x2 = X2 + 10 * Cos(angle)
            set y2 = Y2 + 10 * Sin(angle)
            call SetUnitX(chained, x2)
            call SetUnitY(chained, y2)
        else
            set x2 = X2 + 20 * Cos(angle)
            set y2 = Y2 + 20 * Sin(angle)
        endif

        if IsUnitType(enemy, UNIT_TYPE_STRUCTURE) == false and GetUnitTypeId(enemy) != 'hISK' then
            set x1 = X1 - 10 * Cos(angle)
            set y1 = Y1 - 10 * Sin(angle)
            call SetUnitX(enemy, x1)
            call SetUnitY(enemy, y1)
        else
            set x1 = X1 - 20 * Cos(angle)
            set y1 = Y1 - 20 * Sin(angle)
        endif
    
        call SetUnitX(cok, x1)
        call SetUnitY(cok, y1)
        
        call MoveLightningEx(chain, true, x1, y1, 75 + GetUnitFlyHeight(enemy), x2, y2, 75 + GetUnitFlyHeight(chained))
    endif
    
    else
        if GetUnitPropWindow( cok ) * bj_DEGTORAD <= 0 then
            call SetUnitPropWindow(cok, GetUnitDefaultPropWindow( cok ) * bj_DEGTORAD)
        endif

        call SetUnitX(cok, X1)
        call SetUnitY(cok, Y1)
        call MoveLightningEx(chain, true, X1, Y1, 75 + GetUnitFlyHeight(enemy), X2, Y2, 75 + GetUnitFlyHeight(chained))
        set time = time + 0.01
        call SaveReal(Hash,h,5,time)
    endif
    
    set chain = null
    set cok = null
    set t = null
    set caster = null
    set chained = null
    set enemy = null
endfunction

function CoK_Move takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer h = GetHandleId(t)
    local unit cok = LoadUnitHandle(Hash,h,1)
    local unit caster = LoadUnitHandle(Hash,h,2)
    local lightning chainCoC = LoadLightningHandle(Hash,h,6)
    local real z = GetUnitFlyHeight(cok)
    local real face = GetUnitFacing(cok)
    local integer path = LoadInteger(Hash,h,'Path')
    local group G = CreateGroup()
    local unit enemy
    local player PlayerEnemy
    local player PlayerCaster = GetOwningPlayer(caster)
    
    local real distance = 550.00
    local real X2 = LoadReal(Hash,h,4) + 3 * Cos(face* bj_DEGTORAD)
    local real Y2 = LoadReal(Hash,h,5) + 3 * Sin(face* bj_DEGTORAD)
    local real x = GetUnitX(cok) + 15 * Cos(face* bj_DEGTORAD)
    local real y = GetUnitY(cok) + 15 * Sin(face* bj_DEGTORAD)
    local real X = GetUnitX(cok) - 50 * Cos(face* bj_DEGTORAD)
    local real Y = GetUnitY(cok) - 50 * Sin(face* bj_DEGTORAD)
    local real obl = 80.00
    local boolean b = false
    local integer n = GetUnitUserData(caster)
    local integer c = QuestKelThuzad[n]
    local real damage = DamageCoK[0][n]
    local integer j
    local boolean unitBool
    set path = path + 20
    
    call SaveInteger(Hash,h,'Path', path)
    call SaveReal(Hash,h,4,X2)
    call SaveReal(Hash,h,5,Y2)
    call SetUnitX(cok, x)
    call SetUnitY(cok, y)
    
    call MoveLightningEx(chainCoC, true, X2, Y2, z, X, Y, z)

    if GetUnitAbilityLevel(caster, 'SPAS') == 3 then
        set damage = damage + (damage * 0.75)
    endif

    call GroupEnumUnitsInRange(G, x, y, obl, null)
        loop
            set enemy = FirstOfGroup(G)
            set PlayerEnemy = GetOwningPlayer(enemy)
            set unitBool = (IsUnitType(enemy, UNIT_TYPE_HERO) == true or IsUnitType(enemy, UNIT_TYPE_STRUCTURE) == true or GetUnitTypeId(enemy) == 'hISK') and (enemy != Chained[n] and GetUnitAbilityLevel(enemy, 'B001') <= 0)

            if (Chained[n] == null and GetUnitTypeId(enemy) == 'hISK') then
                local unit dummy = CreateUnit(PlayerCaster,'h006',x,y,face)
                call IssueTargetOrder(dummy,"unholyfrenzy",enemy)
                call UnitApplyTimedLife(dummy, 'BTFL', 0.1 )
                set Chained[n] = FirstOfGroup(G)
                set b = true
                set dummy = null
            else
                if (Chained[n] == null and GetWidgetLife(enemy) > .405 and IsPlayerEnemy(PlayerEnemy, PlayerCaster) and GetUnitAbilityLevel(enemy, 'B006') <= 0 and unitBool == true) then
                    local unit dummy = CreateUnit(PlayerCaster,'h006',x,y,face)
                    call IssueTargetOrder(dummy,"unholyfrenzy",enemy)
                    call UnitApplyTimedLife(dummy, 'BTFL', 0.1 )
                    set Chained[n] = FirstOfGroup(G)
                    call UnitDamageTarget( caster, enemy, damage, true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_NORMAL, null )
                    set dummy = null
                endif
            endif
            
            if Chained[n] != null then
                if unitBool == true then
                    if IsPlayerEnemy(PlayerEnemy, PlayerCaster) or GetUnitTypeId(enemy) == 'hISK' then
                        set b = true
                    endif
                else
                    if (GetWidgetLife(enemy) > .405 and IsPlayerEnemy(PlayerEnemy, PlayerCaster) and GetUnitAbilityLevel(enemy, 'B006') <= 0 and unitBool == true) then
                        set b = true
                        call UnitDamageTarget( caster, enemy, damage, true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_NORMAL, null )
                        if GetWidgetLife(enemy) > .405 and Chained[n] == null then
                            local unit dummy = CreateUnit(PlayerCaster,'h006',x,y,face)
                            call IssueTargetOrder(dummy,"unholyfrenzy",enemy)
                            call UnitApplyTimedLife(dummy, 'BTFL', 0.1 )
                            set Test[n] = false
                            set dummy = null
                        endif
                    endif
                endif
            endif

            call GroupRemoveUnit(G,enemy)
            exitwhen enemy == null or b == true
        endloop

    if Chained[n] == null then
        set Test[n] = false
    endif

    call GroupClear(G)
    call DestroyGroup(G)

    if b == true then
        call SetUnitPropWindow(cok, 0)
        
        if Test[n] == true then
        
            if IsUnitType(enemy, UNIT_TYPE_STRUCTURE) == false or IsUnitType(Chained[n], UNIT_TYPE_STRUCTURE) == false then
        
            local timer k = CreateTimer()
            local integer v = GetHandleId(k)
            
            local real faceChained = GetUnitFacing(Chained[n])*-1
            local real xChained = GetUnitX(Chained[n])
            local real yChained = GetUnitY(Chained[n])
            
            local real faceEnemy = GetUnitFacing(enemy)*-1
            local real xEnemy = GetUnitX(enemy)
            local real yEnemy = GetUnitY(enemy)
            
            call MoveLightningEx(chainCoC, true, xChained, yChained, 75 + GetUnitFlyHeight(Chained[n]), xEnemy, yEnemy, 75 + GetUnitFlyHeight(enemy))
            
            call SetUnitAbilityLevel( caster, 'ACoK', 1 )

            if GetUnitTypeId(Chained[n]) != 'hISK' then
                call PauseUnit(Chained[n], false)
            else
                call PauseUnit(Chained[n], true)
            endif
            
            if GetUnitTypeId(enemy) != 'hISK' then
                call PauseUnit(enemy, false)
            else
                call PauseUnit(enemy, true)
            endif

            if IsUnitType(enemy, UNIT_TYPE_HERO) == true then
                
                if QuestKelThuzad[n] < 15 and QuestKelThuzad[n] != -1 then
                            set QuestKelThuzad[n] = QuestKelThuzad[n] + 1
                        endif
                    
                                if QuestKelThuzad[n] >= 15 and QuestKelThuzad[n] < 30 then
                                    call BlzUnitDisableAbility( caster, 'AISK', false, false )
                                    call SetUnitAbilityLevel( caster, 'AISK', 2 )
                                    call SetUnitAbilityLevel( caster, 'SPAS', 2 )
                                    set QuestKelThuzad[n] = QuestKelThuzad[n] + 1
                                endif
                        
                                    if QuestKelThuzad[n] >= 30 then
                                        set QuestKelThuzad[n] = -1
                                        call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Human\\ReviveHuman\\ReviveHuman.mdl&qu​ot;, caster, "origin"))
                                        call SetUnitAbilityLevel( caster, 'SPAS', 3 )
                                    endif
                
            endif
        
                if c != QuestKelThuzad[n] then
                    call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Other\\TalkToMe\\TalkToMe.mdl", caster, "overhead"))
                endif
            
            call SaveUnitHandle(Hash,v,1,caster)
            call SaveUnitHandle(Hash,v,2,Chained[n])
            call SaveUnitHandle(Hash,v,3,enemy)
            call SaveLightningHandle(Hash,v,4,chainCoC)
            call SaveUnitHandle(Hash,v,7,cok)
            
            set Chained[n] = null
            set Test[n] = false
            set ChainedData[n] = 0
            
            call TimerStart(k,0.01,true,function CoK_MoveChain)
            
            call FlushChildHashtable(Hash,h)
            call PauseTimer(t)
            call DestroyTimer(t)
            
            set k = null
            set enemy = null
        else
            local integer data = ChainedData[n]
            local unit dummy = LoadUnitHandle(Hash,data,3)
            local effect e = LoadEffectHandle(Hash,data,6)
            
            call DestroyLightning(chainCoC)
            call SetUnitAbilityLevel( caster, 'ACoK', 2 )
            call PauseUnit(enemy, false)
            call PauseUnit(Chained[n], false)
            
            call RemoveUnit(dummy)
            call DestroyEffect(e)
            call FlushChildHashtable(Hash,data)
            
            set ChainedData[n] = 0
            set Chained[n] = null
            set dummy = null
            set e = null
        endif
        else
            local string str = "Abilities\\Spells\\Undead\\FrostArmor\\FrostArmorTarget.mdl"
            local effect e
            local real xChain = GetUnitX(Chained[n])
            local real yChain = GetUnitY(Chained[n])
            
            if GetUnitTypeId(Chained[n]) != 'hISK' and IsUnitType(Chained[n], UNIT_TYPE_STRUCTURE) == false
                set e  = AddSpecialEffectTarget(str,Chained[n],"chest")
            else
                set str = "Abilities\\Spells\\Undead\\DarkSummoning\\DarkSummonMissile.mdl"
                set e = AddSpecialEffect(str,xChain,yChain)
            endif
            
            call RemoveUnit(cok)
            call DestroyLightning(chainCoC)

            call UnitRemoveAbility( caster, 'ACoK' )
            call UnitAddAbility( caster, 'ACoK' )
            call SetUnitAbilityLevel( caster, 'ACoK', 2 )
            call SaveUnitHandle(Hash,h,1,Chained[n])
            call SaveEffectHandle(Hash,h,6,e)
            set Test[n] = true
            set j = CoK_Update()
            set ChainedData[n] = j
            call FlushChildHashtable(Hash,h)
            call PauseTimer(t)
            call DestroyTimer(t)
            
            set e = null
            set enemy = null
        endif
            
    endif

    if path >= distance and b == false then
        
        local integer i = -1
        
        call SaveInteger(Hash,h,20,i)
        call PauseUnit(Chained[n], false)
        CoK_DummyMoveToCaster()
        
        call SetUnitAbilityLevel( caster, 'ACoK', 1 )
        call RemoveUnit(cok)
        call DestroyLightning(chainCoC)
        
        call FlushChildHashtable(Hash,h)
        call PauseTimer(t)
        call DestroyTimer(t)
    endif
    
    set chainCoC = null
    set t = null
    set cok = null
    set caster = null
    set G = null
endfunction


function CoK takes nothing returns nothing
    local timer t = CreateTimer()
    local integer h = GetHandleId(t)
    local unit caster = GetTriggerUnit()
    local player PlayerCaster = GetOwningPlayer(caster)
    local integer n = GetUnitUserData(caster)
    local real X1 = GetSpellTargetX()
    local real Y1 = GetSpellTargetY()
    local real X2 = GetUnitX(Chained[n])
    local real Y2 = GetUnitY(Chained[n])
    local unit u
    local lightning chainCoC
        
    if Chained[n] == null then
        set X2 = GetUnitX(caster)
        set Y2 = GetUnitY(caster)
    endif

    local real angle = Atan2(Y1 - Y2, X1 - X2)
    local real x = X2 + 1 * Cos(angle)
    local real y = Y2 + 1 * Sin(angle)
    local unit cok
    
    if Chained[n] == null then
        set cok = CreateUnit( PlayerCaster, 'h005', x, y, angle*bj_RADTODEG )
        set u = caster
    else
        set cok = CreateUnit( PlayerCaster, 'h007', x, y, angle*bj_RADTODEG )
        set u = Chained[n]
    endif
    
    set chainCoC = AddLightningEx("COKT", true, X2, Y2, 75 + GetUnitFlyHeight(u), x, y, 75 + GetUnitFlyHeight(cok))
    call SaveUnitHandle(Hash,h,1,cok)
    call SaveUnitHandle(Hash,h,2,caster)
    call SaveReal(Hash,h,4,X2)
    call SaveReal(Hash,h,5,Y2)
    call SaveLightningHandle(Hash,h,6,chainCoC)
    call TimerStart(t,.01,true,function CoK_Move)
    set cok = null
    set t = null
    set caster = null
    set chainCoC = null
    set u = null
endfunction
» Дополнительно (скопировать до блока "Способность")
function CoK_DummyMoveToCaster takes nothing returns integer
    local timer t = GetExpiredTimer()
    local integer h = GetHandleId(t)
    local unit caster = LoadUnitHandle(Hash,h,2)
    local unit array dummy
    local effect e = LoadEffectHandle(Hash,h,6)
    local real time = LoadReal(Hash,h,4)
    local integer i = LoadInteger(Hash,h,20)
    local integer n = GetUnitUserData(caster)
    local integer numb = 0
    local integer c = ChainedData[n]
    local real x = GetUnitX(caster)
    local real y = GetUnitY(caster)
    set time = time + 0.01
    call SaveReal(Hash,h,4,time)
    
    if time < 4 and GetWidgetLife (Chained[n]) >.405 and i != -1 then
        loop
        exitwhen (numb == 11)
            set dummy[numb] = LoadUnitHandle(Hash,h,3+numb)
            call SetUnitX(dummy[numb], x)
            call SetUnitY(dummy[numb], y)
            set dummy[numb] = null
        set numb = numb + 1
        endloop
    else

        loop
        exitwhen (numb == 11)
            set dummy[numb] = LoadUnitHandle(Hash,h,3+numb)
            call KillUnit(dummy[numb])
            set dummy[numb] = null
        set numb = numb + 1
        endloop

        call SetUnitAbilityLevel( caster, 'ACoK', 1 )
        call PauseUnit(Chained[n], false)
        set ChainedData[n] = 0
        set Test[n] = false
        set Chained[n] = null
        call DestroyEffect(e)
        call FlushChildHashtable(Hash,h)
        call PauseTimer(t)
        call DestroyTimer(t)
    endif

    set t = null
    set e = null
    set caster = null
    
    return h
endfunction

function CoK_Update takes nothing returns integer

    local timer t = GetExpiredTimer()
    local integer h = GetHandleId(t)
    local unit caster = LoadUnitHandle(Hash,h,2)
    local unit chained = LoadUnitHandle(Hash,h,1)
    local effect e = LoadEffectHandle(Hash,h,6)
    local integer i = LoadInteger(Hash,h,20)
    local integer j
    
    local integer n = GetUnitUserData(caster)
    local integer c = QuestKelThuzad[n]

    local real x = GetUnitX(caster)
    local real y = GetUnitY(caster)
    local player PlayerCaster = GetOwningPlayer(caster)
    local real face = GetUnitFacing(caster)

    local timer f = CreateTimer()
    local integer v = GetHandleId(f)

    local unit array dummy

    local integer rav = 'h00A'
    local integer ln = 0
    loop
	exitwhen (ln == 11)
        if (ln == GetPlayerId(PlayerCaster) and GetLocalPlayer() == PlayerCaster) then
            rav = 'h000'
        endif
    set dummy[ln] = CreateUnit( Player(ln), rav, x, y, face )
    call SetUnitTimeScale( dummy[ln], 0.25 )
    call SetUnitScale( dummy[ln], 1.5, 0.5, 1 )
    call SaveUnitHandle(Hash,v,3+ln,dummy[ln])
        set rav = 'h00A'
    set dummy[ln] = null
	set ln = ln + 1
    endloop
    set j = v

    call SaveUnitHandle(Hash,v,2,caster)
    call SaveEffectHandle(Hash,v,6,e)
    call SaveInteger(Hash,v,20,i)
    set i = 0
    call SaveInteger(Hash,h,20,i)
    call TimerStart(f,0.01,true,function CoK_DummyMoveToCaster)

    if chained != null then
        if IsUnitType(chained, UNIT_TYPE_STRUCTURE) == false then
            if QuestKelThuzad[n] < 15 and QuestKelThuzad[n] != -1 then
                            set QuestKelThuzad[n] = QuestKelThuzad[n] + 1
                        endif
                    
                                if QuestKelThuzad[n] >= 15 and QuestKelThuzad[n] < 30 then
                                    call BlzUnitDisableAbility( caster, 'AISK', false, false )
                                    call SetUnitAbilityLevel( caster, 'AISK', 2 )
                                    call SetUnitAbilityLevel( caster, 'SPAS', 2 )
                                    set QuestKelThuzad[n] = QuestKelThuzad[n] + 1
                                endif
                        
                                    if QuestKelThuzad[n] >= 30 then
                                        set QuestKelThuzad[n] = -1
                                        call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Human\\ReviveHuman\\ReviveHuman.mdl&qu​ot;, caster, "origin"))
                                        call SetUnitAbilityLevel( caster, 'SPAS', 3 )
                                    endif
        
            if c != QuestKelThuzad[n] then
                call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Other\\TalkToMe\\TalkToMe.mdl", caster, "overhead"))
            endif

        endif
    endif

    call FlushChildHashtable(Hash,h)
    call PauseTimer(t)
    call DestroyTimer(t)
    
    set chained = null
    set f = null
    set e = null
    set t = null
    set caster = null

return j

endfunction
» Ледовый шип
» Создание
function ISK_Cond takes nothing returns boolean
    return GetSpellAbilityId()=='AISK'
endfunction

function ISK_Animation takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer h = GetHandleId(t)
    local unit isk = LoadUnitHandle(Hash,h,1)
    call SetUnitAnimation(isk, "death")
    call FlushChildHashtable(Hash,h)
    call PauseTimer(t)
    call DestroyTimer(t)
    set t = null
    set isk = null
endfunction

function ISK_Create takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer h = GetHandleId(t)
    local unit caster = LoadUnitHandle(Hash,h,1)
    local player PlayerCaster = GetOwningPlayer(caster)
    local real X1 = LoadReal(Hash,h,2)
    local real X2 = GetUnitX(caster)
    local real Y1 = LoadReal(Hash,h,3)
    local real Y2 = GetUnitY(caster)
    local real angle = Atan2(Y1 - Y2, X1 - X2)
    local unit isk = CreateUnit( PlayerCaster, 'hISK', X1, Y1, angle*bj_RADTODEG )
    local integer data = GetUnitUserData(caster)

    call SetUnitUserData(isk, data)
    call UnitApplyTimedLife(isk, 'BTFL', 4 )
    call SaveUnitHandle(Hash,h,1,isk)
    call TimerStart(t, 2.8, false, function ISK_Animation)
    set t = null
    set isk = null
    set caster = null
endfunction

function ISK takes nothing returns nothing
    local timer t = CreateTimer()
    local integer h = GetHandleId(t)
    local unit caster = GetTriggerUnit()
    local real X1 = GetSpellTargetX()
    local real Y1 = GetSpellTargetY()
    call DestroyEffect(AddSpecialEffect("Abilities\\Spells\\Human\\SpellSteal\\SpellStealTarget.mdl"​;, X1, Y1))
    call SaveUnitHandle(Hash,h,1,caster)
    call SaveReal(Hash,h,2,X1)
    call SaveReal(Hash,h,3,Y1)
    call TimerStart(t,1,false,function ISK_Create)
    set t = null
    set caster = null
endfunction
» Взрыв
function Trig_ISK_Conditions takes nothing returns boolean
    return GetUnitTypeId(GetTriggerUnit()) == 'hISK'
endfunction

function Trig_ISK_Actions takes nothing returns nothing
    local unit isk = GetTriggerUnit()
    local player PlayerCaster = GetOwningPlayer(isk)
    local real x = GetUnitX(isk)
    local real y = GetUnitY(isk)
    local group G = CreateGroup()
    local player PlayerEnemy
    local unit enemy
    local integer data = GetUnitUserData(isk)
    local real damage = DamageISK[0][data]
    call DestroyEffect(AddSpecialEffect("Abilities\\Spells\\Undead\\FreezingBreath\\FreezingBreathMissil​e.mdl", x, y))
    call GroupEnumUnitsInRange(G, x, y, 150, null)
        loop
            set enemy = FirstOfGroup(G)
            set PlayerEnemy = GetOwningPlayer(enemy)
            if IsPlayerEnemy(PlayerEnemy, PlayerCaster) and GetWidgetLife( enemy ) >.405 then
                call UnitDamageTarget( isk, enemy, damage, true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_DEMOLITION, null )
            endif
            call GroupRemoveUnit(G,enemy)
            exitwhen enemy == null
        endloop
    call GroupClear(G)
    call DestroyGroup(G)
    set G = null
    set isk = null
endfunction
» Ледяной взрыв
function IceBlast_Cond takes nothing returns boolean
    return GetSpellAbilityId()=='AKIB'
endfunction

function IceBlast_Slowdown takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer h = GetHandleId(t)
    local unit caster = LoadUnitHandle(Hash,h,1)
    local player PlayerEnemy
    local player PlayerCaster = GetOwningPlayer(caster)
    local real x = 0
    local real y = 0
    local real face
    local integer data = GetUnitUserData(caster)
    local real damage = DamageKIBRect[0][data]
    local integer n = GetUnitUserData(caster)
    local unit enemy = GetEnumUnit()
    local effect e
    
        if GetUnitAbilityLevel(caster, 'SPAS') == 3 then
            set damage = damage + (damage * 0.75)
        endif

            set PlayerEnemy = GetOwningPlayer(enemy)
            if IsPlayerEnemy(PlayerEnemy, PlayerCaster) and GetWidgetLife( enemy ) >.405 and IsUnitType(enemy, UNIT_TYPE_STRUCTURE) == false then
                call UnitDamageTarget( caster, enemy, damage, true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_COLD, null )
                set x = GetUnitX(enemy)
                set y = GetUnitY(enemy)
                set face = GetUnitFacing(enemy)
                if GetWidgetLife(enemy) > .405 then
                    local unit dummy = CreateUnit(PlayerCaster,'h006',x,y,face)
                    call UnitRemoveAbility(dummy,'A002')
                    call IssueTargetOrder(dummy,"entanglingroots",enemy)
                    call UnitApplyTimedLife(dummy, 'BTFL', 0.1 )
                    call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Undead\\FrostNova\\FrostNovaTarget.mdl​", enemy, "origin"))
                    set dummy = null
                endif
            endif
    
    set t = null
    set caster = null
    set enemy = null
    set e = null

endfunction

function IceBlast_Move takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer h = GetHandleId(t)
    local unit iceblast = LoadUnitHandle(Hash,h,1)
    local unit target = LoadUnitHandle(Hash,h,2)
    local unit caster = LoadUnitHandle(Hash,h,3)
    local real X1 = GetUnitX(iceblast)
    local real X2
    local real Y1 = GetUnitY(iceblast)
    local real Y2
    local real angle
    local player PlayerCaster = GetOwningPlayer(caster)
    local integer data = GetUnitUserData(caster)
    local real damageLow = DamageKIB[0][data]
    local real dist
    local boolean b = false
    local group G = CreateGroup()
    local real speed = LoadReal(Hash,h,4)
    local real x
    local real y
    set speed = speed + 0.05
    call SaveReal(Hash,h,4,speed)
    
    if GetWidgetLife(target) >.405 then
        set X2 = GetUnitX(target)
        set Y2 = GetUnitY(target)
    else
        set X2 = LoadReal(Hash,h,5)
        set Y2 = LoadReal(Hash,h,6)
    endif
    
    set angle = Atan2(Y2 - Y1, X2 - X1)
    set dist = SquareRoot((X2 - X1) * (X2 - X1) + (Y2 - Y1) * (Y2 - Y1))
    set x = GetUnitFlyHeight(iceblast) / dist + speed
    set y = GetUnitFlyHeight(iceblast) / dist + speed

    call SetUnitFacing(iceblast, angle*bj_RADTODEG)
    call SetUnitFlyHeight(iceblast,GetUnitFlyHeight(iceblast) / dist + 75, 250)
    call SetUnitX(iceblast, X1 + x * Cos(angle))
    call SetUnitY(iceblast, Y1 + y * Sin(angle))
    
    if GetUnitAbilityLevel(caster, 'SPAS') == 3 then
        set damageLow = damageLow + (damageLow * 0.75)
    endif

        if dist <= 75 then
            set b = true
            call KillUnit(iceblast)
            call GroupEnumUnitsInRange(G, X1, Y1, 300, null)
            call GroupRemoveUnit(G,target)
            ForGroup(G, function IceBlast_Slowdown)
        endif

    call GroupClear(G)
    call DestroyGroup(G)
    
    if b == true then
        if GetWidgetLife(target) >.405 then
            set x = GetUnitX(target)
            set y = GetUnitY(target)
        else
            set x = LoadReal(Hash,h,5)
            set y = LoadReal(Hash,h,6)
        endif

        local real face = GetUnitFacing(target)
        local unit dummy = CreateUnit(PlayerCaster,'h006',x,y,face)

        if GetUnitAbilityLevel(caster, 'SPAS') == 3 then
            set damageLow = damageLow + (damageLow * 0.75)
        endif

        call GroupEnumUnitsInRange(G, x, y, 300, null)
        call ForGroup(G, function IceBlast_Slowdown)
        call UnitDamageTarget( caster, target, damageLow, true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_COLD, null )
    
        if GetWidgetLife (target) > .405 then
            call UnitRemoveAbility(dummy,'A002')
            call IssueTargetOrder(dummy,"entanglingroots",target)
            call UnitApplyTimedLife(dummy, 'BTFL', 0.1 )
        else
            call RemoveUnit(dummy)
        endif
    
        call GroupClear(G)
        call DestroyGroup(G)
    
        call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Undead\\FrostNova\\FrostNovaTarget.mdl​", target, "origin"))
        IceBlast_Slowdown()
        call FlushChildHashtable(Hash,h)
        call PauseTimer(t)
        call DestroyTimer(t)
        
        set dummy = null
    else
        call SaveReal(Hash,h,5, X2)
        call SaveReal(Hash,h,6, Y2)
    endif
    
    set t = null
    set iceblast = null
    set caster = null
    set target = null
    set G = null
endfunction

function IceBlast_Create takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer h = GetHandleId(t)
    local unit iceblast = LoadUnitHandle(Hash,h,1)
    local unit target = LoadUnitHandle(Hash,h,2)
    local unit caster = LoadUnitHandle(Hash,h,3)
    local real X2
    local real Y2
    
    if GetWidgetLife(target) >.405 then
        set X2 = GetUnitX(target)
        set Y2 = GetUnitY(target)
    else
        set X2 = LoadReal(Hash,h,5)
        set Y2 = LoadReal(Hash,h,6)
    endif
    
    local timer k = CreateTimer()
    local integer i = GetHandleId(k)
    call SaveUnitHandle(Hash,i,1,iceblast)
    call SaveUnitHandle(Hash,i,2,target)
    call SaveUnitHandle(Hash,i,3,caster)
    call SaveReal(Hash,i,5,X2)
    call SaveReal(Hash,i,6,Y2)
    call TimerStart(k,.01,true,function IceBlast_Move)

    call PauseTimer(t)
    call DestroyTimer(t)
    set k = null
    set t = null
    set iceblast = null
    set caster = null
    set target = null
endfunction

function IceBlast takes nothing returns nothing
    local unit caster = GetTriggerUnit()
    local unit target = GetSpellTargetUnit()
    local timer t = CreateTimer()
    local integer h = GetHandleId(t)
    local player PlayerCaster = GetOwningPlayer(caster)
    local real X1 = GetUnitX(caster)
    local real X2 = GetUnitX(target)
    local real Y1 = GetUnitY(caster)
    local real Y2 = GetUnitY(target)
    local real angle = Atan2(Y2 - Y1, X2 - X1)
    local real dist = SquareRoot((X2 - X1) * (X2 - X1) + (Y2 - Y1) * (Y2 - Y1))
    local unit iceblast = CreateUnit( PlayerCaster, 'h004', X1 - 60 * Cos(angle), Y1 - 60 * Sin(angle), angle*bj_RADTODEG )
    call DestroyEffect(AddSpecialEffectTarget("Abilities\\Weapons\\ColdArrow\\ColdArrowMissile.mdl"​, caster, "overhead")) //Abilities\\Spells\\Other\\FrostBolt\\FrostBoltMissile.mdl
    call SetUnitPathing( iceblast, false )
    call SetUnitFlyHeight(iceblast, 250, 10000)
    call SaveUnitHandle(Hash,h,1,iceblast)
    call SaveUnitHandle(Hash,h,2,target)
    call SaveUnitHandle(Hash,h,3,caster)
    call SaveReal(Hash,h,5,X2)
    call SaveReal(Hash,h,6,Y2)
    call TimerStart(t,1,false,function IceBlast_Create)
    set t = null
    set iceblast = null
    set caster = null
    set target = null
endfunction
» Прорыв тьмы
function KBD_Cond takes nothing returns boolean
    return GetSpellAbilityId()=='AKBD'
endfunction

function KBD_Rect takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer h = GetHandleId(t)
    local unit caster = LoadUnitHandle(Hash,h,1)
    local real xRect = LoadReal(Hash,h,3)
    local real yRect = LoadReal(Hash,h,4)
    local real Frect = 150
    local unit enemy
    local real time = LoadReal(Hash,h,5)
    local effect e = LoadEffectHandle(Hash,h,2)
    local integer data = GetUnitUserData(caster)
    local real damage = DamageKBD[0][data]
    local player PlayerEnemy
    local player PlayerCaster = GetOwningPlayer(caster)
    local group G = CreateGroup()
    if GetUnitAbilityLevel(caster, 'SPAS') == 3 then
        set damage = damage + (damage * 0.75)
    endif

    call GroupEnumUnitsInRange(G, xRect, yRect, Frect, null)
        loop
            set enemy = FirstOfGroup(G)
            set PlayerEnemy = GetOwningPlayer(enemy)
            if IsPlayerEnemy(PlayerEnemy, PlayerCaster) and IsUnitType(enemy, UNIT_TYPE_HERO) == true and GetWidgetLife( enemy ) >.405 then
                call UnitDamageTarget( caster, enemy, damage, true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_DEATH, null )
            endif
            call GroupRemoveUnit(G,enemy)
            exitwhen enemy == null
        endloop

    call DestroyEffect(AddSpecialEffect("AquaSpike.mdx", xRect, yRect))
    call DestroyEffect(e)
    call GroupClear(G)
    call DestroyGroup(G)
    call FlushChildHashtable(Hash,h)
    call PauseTimer(t)
    call DestroyTimer (t)
    set t = null
    set caster = null
    set e = null
    set G = null
endfunction

function KBD takes nothing returns nothing
    local timer t = CreateTimer()
    local integer h = GetHandleId(t)
    local unit caster = GetTriggerUnit()
    local real X1 = GetSpellTargetX()
    local real Y1 = GetSpellTargetY()
    local effect e = AddSpecialEffect("RingOfIce.mdx", X1, Y1)
    call SaveUnitHandle(Hash,h,1,caster)
    call SaveEffectHandle(Hash,h,2,e)
    call SaveReal(Hash,h,3,X1)
    call SaveReal(Hash,h,4,Y1)
    call TimerStart(t,1.5,false,function KBD_Rect)
    set e = null
    set t = null
    set caster = null
endfunction
» Владыка холодной тьмы
function SPAS_Cond takes nothing returns boolean
	return GetSpellAbilityId() == 'SPAS'
endfunction

function SPAS takes nothing returns nothing
    local unit caster = GetTriggerUnit()
    local integer n = GetUnitUserData(caster)
    local integer i = udg_QuestKelThuzad[n]
    if i == -1 then
        call DisplayTimedTextToPlayer( GetOwningPlayer(caster), 0, 0, 1.5, "Накоплено |c0000FF40Чумы:|r " + "30/30" )
    else
        call DisplayTimedTextToPlayer( GetOwningPlayer(caster), 0, 0, 1.5, "Накоплено |c0000FF40Чумы:|r " + I2S(i) + "/30" )
    endif
    call UnitRemoveAbility(caster, 'BKEL')
    set caster = null
endfunction
» Инициализация героя
function KelThuzad_Start takes nothing returns nothing
    local unit u = GetTriggerUnit()
    local integer n = GetUnitUserData( u )
        if GetUnitTypeId(u) == 'UKel' then
            if n <= 0 then
                set NumberOfKelThuzad = NumberOfKelThuzad + 1
                set LifeRegen[0][NumberOfKelThuzad] = 0.03
                set ManaRegen[0][NumberOfKelThuzad] = 0.03
                set Life[0][NumberOfKelThuzad] = GetUnitState(u, UNIT_STATE_MAX_LIFE)
                set Mana[0][NumberOfKelThuzad] = GetUnitState(u, UNIT_STATE_MAX_MANA)
                set DamageDaD[0][NumberOfKelThuzad] = 150
                set DamageDaDRect[0][NumberOfKelThuzad] = 82
                set DamageRoI[0][NumberOfKelThuzad] = 180
                set DamageCoK[0][NumberOfKelThuzad] = 97
                set DamageKIB[0][NumberOfKelThuzad] = 115
                set DamageKIBRect[0][NumberOfKelThuzad] = 275
                set DamageKBD[0][NumberOfKelThuzad] = 360
                set DamageISK[0][NumberOfKelThuzad] = 61
                set Damage[0][NumberOfKelThuzad] = BlzGetUnitBaseDamage(u, 1)
                call SetUnitUserData( u, NumberOfKelThuzad )
                set DamageDaD[0][NumberOfKelThuzad] = DamageDaD[0][NumberOfKelThuzad] + (DamageDaD[0][NumberOfKelThuzad] * 0.025)
                set DamageDaDRect[0][NumberOfKelThuzad] = DamageDaDRect[0][NumberOfKelThuzad] + (DamageDaDRect[0][NumberOfKelThuzad] * 0.025)
                set DamageRoI[0][NumberOfKelThuzad] = DamageRoI[0][NumberOfKelThuzad] + (DamageRoI[0][NumberOfKelThuzad] * 0.025)
                set DamageCoK[0][NumberOfKelThuzad] = DamageCoK[0][NumberOfKelThuzad] + (DamageCoK[0][NumberOfKelThuzad] * 0.025)
                set DamageKIB[0][NumberOfKelThuzad] = DamageKIB[0][NumberOfKelThuzad] + (DamageKIB[0][NumberOfKelThuzad] * 0.025)
                set DamageKIBRect[0][NumberOfKelThuzad] = DamageKIB[0][NumberOfKelThuzad] + (DamageKIB[0][NumberOfKelThuzad] * 0.025)
                set DamageKBD[0][NumberOfKelThuzad] = DamageKBD[0][NumberOfKelThuzad] + (DamageKBD[0][NumberOfKelThuzad] * 0.025)
                set DamageISK[0][NumberOfKelThuzad] = DamageISK[0][NumberOfKelThuzad] + (DamageISK[0][NumberOfKelThuzad] * 0.025)
                set QuestKelThuzad[NumberOfKelThuzad] = 0
                call BlzUnitDisableAbility( u, 'AISK', true, false )
                set KelThuzad[NumberOfKelThuzad] = u
            endif
        endif
    set u = null
endfunction
» Регенерация
function Trig_Regen_Actions takes nothing returns nothing
    local integer n = 0
    loop
        set n = n + 1
        call SetUnitState( KelThuzad[n], UNIT_STATE_LIFE, GetUnitState(KelThuzad[n], UNIT_STATE_LIFE) + LifeRegen[0][n])
        call SetUnitState( KelThuzad[n], UNIT_STATE_MANA, GetUnitState(KelThuzad[n], UNIT_STATE_MANA) + ManaRegen[0][n])
    exitwhen n == NumberOfKelThuzad or NumberOfKelThuzad == 0
    endloop
endfunction
» Повышение уровня
function Trig_LvlUp_Conditions takes nothing returns boolean
    return GetUnitTypeId(GetTriggerUnit()) == 'UKel'
endfunction

function Trig_LvlUp_Actions takes nothing returns nothing
    local unit u = GetTriggerUnit()
    local integer data = GetUnitUserData(u)
    set Life[0][data] = Life[0][data] + (Life[0][data] * 0.04) + 0.5
    set Mana[0][data] = Mana[0][data] + 10
    set Damage[0][data] = Damage[0][data] + (Damage[0][data] * 0.04)
    set DamageDaD[0][data] = DamageDaD[0][data] + (DamageDaD[0][data] * 0.025)
    set DamageDaDRect[0][data] = DamageDaDRect[0][data] + (DamageDaDRect[0][data] * 0.025)
    set DamageRoI[0][data] = DamageRoI[0][data] + (DamageRoI[0][data] * 0.025)
    set DamageCoK[0][data] = DamageCoK[0][data] + (DamageCoK[0][data] * 0.025)
    set DamageKIB[0][data] = DamageKIB[0][data] + (DamageKIB[0][data] * 0.025)
    set DamageKIBRect[0][data] = DamageKIB[0][data] + (DamageKIB[0][data] * 0.025)
    set DamageKBD[0][data] = DamageKBD[0][data] + (DamageKBD[0][data] * 0.025)
    set DamageISK[0][data] = DamageISK[0][data] + (DamageISK[0][data] * 0.025)
    set LifeRegen[0][data] = LifeRegen[0][data] + (LifeRegen[0][data] * 0.04 )
    set ManaRegen[0][data] = ManaRegen[0][data] + (ManaRegen[0][data] * 0.04 )
    call BlzSetUnitMaxHP( u, R2I(Life[0][data]))
    call BlzSetUnitMaxMana( u, R2I(Mana[0][data]))
    call BlzSetUnitBaseDamage( u, R2I(Damage[0][data]), 1 )
    set u = null
endfunction
» Визуальное исправление анимаций при мгновенном применении способностей
function Trig_AnimationSpell_Conditions takes nothing returns boolean
	return GetUnitTypeId(GetTriggerUnit()) == 'UKel'
endfunction

function Trig_AnimationSpell_Actions takes nothing returns nothing
    local unit caster = GetTriggerUnit()
    local integer abil = GetSpellAbilityId()
    if abil != 'ADaD' and abil != 'SPAS' then
        call SetUnitAnimation(caster,"spell")
        QueueUnitAnimation(caster,"stand")
    endif
    set caster = null
endfunction
Отдельная благодарность nvc123
Примечание: видео версии 1.1.4.



Просмотров: 1 602

Naadir #1 - 1 год назад 2
Видео неинформативно, но выглядит эпично.
Atesla #2 - 1 год назад 0
Naadir, что, по твоему мнению, будет информативным для подобных наработок? Мне интересно твое мнение.
GetLocalPlayer #3 - 1 год назад 2
Слишком много вражеских юнитов, среди атак которых не разобрать, где способности. Демонстрацию нужно разделить на несколько этапов, где способности тестируются на пассивных противниках. Уже после можно озадачиться рубиловом.
Atesla #4 - 1 год назад 0
GetLocalPlayer, впрочем, соглашусь. В скором времени обновлю как саму наработку (с замедлением косяк, ибо упор был в основном на "Цепи"), так и видео.
Daro #5 - 1 год назад (отредактировано ) 0
Наработку героя нужно перенести в другой раздел на сайте, я чисто случайно увидел.Сначала хотел похватить то, что выполнено без всяких структур и либ.Но потом увидел баг с цепями и молнией, которая появляется в центре карты.На скилле Q мешается тень от дамика.На скилле R- задержка и опускание высоты дамика выглядят убого, также медленно смещение рывками.
Ну и на последок раз уж делаете героев из {оста , то не помешали бы и их модели загрузить.
Atesla #6 - 1 год назад 0
Daro, с удовольствием бы вытянул модель с анимациями, если бы умел. А так приходится делать на том, что имеем. Вскоре обновлю с исправлением вышеупомянутых замечаний, а также добавлю кое-что новое. :)
Daro #7 - 1 год назад 0
У меня есть вот такая модель.Эффекты еще проработай получше.
На счет кода я еще не вчитывлся, скажу что лучше оставить как раз именно на таком джассе без структур.По коду еще можно чуть сократить.Мне понравилось , что квест сделан через CV юнита, за это плюс. IceBlast переделай на 1 таймер и тригг , без лишних разделений на функции
прикреплены файлы
Atesla #8 - 1 год назад 0
Daro, какие именно эффекты, на твое мнение, стоит улучшить?
Таймер один, не знаю, где ты нашел еще...
Daro, через CV я сделал, потому что с помощью этого можно инициализировать и все остальное, в CV лишь находится номер юнита, а дальше свободная площадка для скриптования...