, Гильдия «Черамор»

Заклинание: Молитва

» опубликован
» Способ реализации: Lua
» Тип: Способность
» 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


Просмотров: 709

» Лучшие комментарии


Rockmaf #1 - 5 месяцев назад 0
А способность сбивается?
NazarPunk #2 - 5 месяцев назад 1
Rockmaf:
А способность сбивается?
Да
KaneThaumaturge #3 - 5 месяцев назад 0
Да
А похищение магии совместимо?
NazarPunk #4 - 5 месяцев назад 0
А похищение магии совместимо?
Я свои способности на канале делаю для совместимости. И это обыкновенная channel способность.
прикреплены файлы
Bergi_Bear #5 - 5 месяцев назад 0
Очень забавное решение для муи проверки, что способность кастуется изпользовать булевый массив, где индекс массива = хендл юнита, я очень долго врубался
NazarPunk #6 - 5 месяцев назад 0
Bergi_Bear, раньше ж так на хэштаблицах делали, с приказами мороки намного больше.
Sergarr #7 - 5 месяцев назад 0
Интересно, в lua нету ограничения на размер массива, что ли?
NazarPunk #8 - 5 месяцев назад 7
Sergarr, для простоты можете считать, что в луа ассоциативные массивы. Хотя там таблицы))
a = {}     -- create a table and store its reference in `a'
k = "x"
a[k] = 10        -- new entry, with key="x" and value=10
a[20] = "great"  -- new entry, with key=20 and value="great"
print(a["x"])    --> 10
k = 20
print(a[k])      --> "great"
a["x"] = a["x"] + 1     -- increments entry "x"
print(a["x"])    --> 11
KaneThaumaturge #9 - 5 месяцев назад 0
Я свои способности на канале делаю для совместимости. И это обыкновенная channel способность.
А, я думал это бафф.
NazarPunk #10 - 5 месяцев назад (отредактировано ) 0
А, я думал это бафф.
Дык и бафф наложить можно, только стандартный канал этого не умеет(