Добавлен , опубликован
Алгоритмы, Наработки и Способности
Способ реализации:
Lua
Тип:
Способность
Версия Warcraft:
Reforged
» MUI: да
» Импорт: иконка
» Утечки: нет
» Требования: нет
» Идея: Bergi_Bear
Герой указывает способность на себя или любую другую союзную единицу и восстанавливает ей здоровье в размере: Интеллект * уровень способности.
Длительность: 10/15/20

Скриншот

Технические подробности

Перенос в свою карту
Триггеры
  • Pray
Способности
  • Молитва 'SPry'
Импорт
  • ReplaceableTextures\CommandButtons\BTNSpellPray.blp
  • ReplaceableTextures\CommandButtonsDisabled\DISBTNSpellPray.blp
Настройка
local ABILITY_ID = AbilityId('SPry')
local TIMER_PERIOD = 0.0625 --> 1/16
local DISTANCE = {800, 900, 1000}

local EFFECT_CASTER = {
    {'Abilities\\Spells\\Orc\\AncestralSpirit\\AncestralSpiritCaster.mdl','origin'},
    {'Abilities\\Spells\\Items\\StaffOfSanctuary\\Staff_Sanctuary_Target.mdl','chest'}
}    
local EFFECT_TARGET = {
    {'Abilities\\Spells\\Orc\\SpiritLink\\SpiritLinkZapTarget.mdl','origin'},
    {'Abilities\\Spells\\NightElf\\Rejuvenation\\RejuvenationTarget.mdl','chest'}
Код
//! beginusercode
do
    -- На момент патча 1.31 эта функция всегда возвращает 0. Поэтому создадим её локальный аналог.
    local function AbilityId(id)
        return id:byte(1) * 0x1000000 + id:byte(2) * 0x10000 + id:byte(3) * 0x100 + id:byte(4)
    end

    -- Настройки
    local ABILITY_ID = AbilityId('SPry')
    local TIMER_PERIOD = 0.0625 --> 1/16
    local DISTANCE = {800, 900, 1000}
    local EFFECT_CASTER = {
        {'Abilities\\Spells\\Orc\\AncestralSpirit\\AncestralSpiritCaster.mdl','origin'},
        {'Abilities\\Spells\\Items\\StaffOfSanctuary\\Staff_Sanctuary_Target.mdl','chest'}
    }    
    local EFFECT_TARGET = {
        {'Abilities\\Spells\\Orc\\SpiritLink\\SpiritLinkZapTarget.mdl','origin'},
        {'Abilities\\Spells\\NightElf\\Rejuvenation\\RejuvenationTarget.mdl','chest'}
    }
    
    -- Заклинание
    local IS_CHANNEL = {}

    --[[Polar: xgm.guru/p/wc3/polar]]
        local function DistanceBetweenXY(xa, ya, xb, yb)
            local dx = xb - xa
            local dy = yb - ya
            return math.sqrt(dx*dx + dy*dy)
        end
        local function DistanceBetweenWidgets(targetA, targetB)
            local dx = GetWidgetX(targetB) - GetWidgetX(targetA)
            local dy = GetWidgetY(targetB) - GetWidgetY(targetA)
            return math.sqrt(dx*dx + dy*dy)
        end
    --[[endPolar]]

    local function addEffectTarget(effect, target)
        return AddSpecialEffectTarget(effect[1], target, effect[2])
    end

    local t = CreateTrigger()
    for i = 0, bj_MAX_PLAYER_SLOTS - 1, 1 do
        TriggerRegisterPlayerUnitEvent(t, Player(i), EVENT_PLAYER_UNIT_SPELL_EFFECT)
    end
    TriggerAddCondition(t, Condition(function() return GetSpellAbilityId() == ABILITY_ID end))
    TriggerAddAction(t, function()
        local caster = GetTriggerUnit()
        local key = GetHandleId(caster)
        local target = GetSpellTargetUnit()

        if GetWidgetLife(target) == BlzGetUnitMaxHP(target)
        then
            IssueImmediateOrderById(caster, 851972) --> stop
            return
        end

        local level = GetUnitAbilityLevel(caster, ABILITY_ID)
        local effects = {}

        for i, e in ipairs(EFFECT_CASTER) do
            table.insert(effects, addEffectTarget(e, caster))
        end

        for i, e in ipairs(EFFECT_TARGET) do
            table.insert(effects, addEffectTarget(e, target))
        end

        IS_CHANNEL[key] = true

        TimerStart(CreateTimer(), TIMER_PERIOD, true, function()
            local isMaxDistance = DistanceBetweenWidgets(caster, target) >= DISTANCE[level]
            local isMaxHP = GetWidgetLife(target) == BlzGetUnitMaxHP(target)
            if
                not IS_CHANNEL[key]
                or 
                isMaxDistance
                or
                isMaxHP
                or
                not UnitAlive(caster)
                or
                not UnitAlive(target)
            then
                if
                    (
                        isMaxDistance
                        or
                        isMaxHP
                    )
                    and
                    UnitAlive(caster)
                then
                    IssueImmediateOrderById(caster, 851972) --> stop
                end

                for i, e in ipairs(effects) do
                    DestroyEffect(e)
                end

                DestroyTimer(GetExpiredTimer())
                return
            end
            local heal = GetHeroInt(caster, true)*level/(1/TIMER_PERIOD)
            SetWidgetLife(target, GetWidgetLife(target) + heal)
        end)

    end)

    t = CreateTrigger()
    for i = 0, bj_MAX_PLAYER_SLOTS - 1, 1 do
        TriggerRegisterPlayerUnitEvent(t, Player(i), EVENT_PLAYER_UNIT_SPELL_ENDCAST)
    end
    TriggerAddCondition(t, Condition(function() return GetSpellAbilityId() == ABILITY_ID end))
    TriggerAddAction(t, function()
        IS_CHANNEL[GetHandleId(GetTriggerUnit())] = false
    end)
end
//! endusercode
`
ОЖИДАНИЕ РЕКЛАМЫ...

Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
0
12
5 лет назад
0
А способность сбивается?
2
29
5 лет назад
2
Rockmaf:
А способность сбивается?
Да
0
19
5 лет назад
0
Да
А похищение магии совместимо?
0
29
5 лет назад
0
А похищение магии совместимо?
Я свои способности на канале делаю для совместимости. И это обыкновенная channel способность.
Загруженные файлы
0
32
5 лет назад
0
Очень забавное решение для муи проверки, что способность кастуется изпользовать булевый массив, где индекс массива = хендл юнита, я очень долго врубался
0
29
5 лет назад
0
Bergi_Bear, раньше ж так на хэштаблицах делали, с приказами мороки намного больше.
0
12
5 лет назад
0
Интересно, в lua нету ограничения на размер массива, что ли?
Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.