Простое заклинание для новичков. Добавляет к стандартному Бурану дополнительный AOE урон раз в секунду. Код намеренно упрощён из-за обучающего характера материала. Более продвинутую версию можете посмотреть по следущей ссылке.
Видео
Код
//1. Обнуление глобалок не имеет смысла (только если вы уверены что она не будет больше вызыватся, тогда ради перфекционизма можно обнулить)
//2. Обнулять локальные переменные нужно обязательно, можно не обнулять integer, real, string (тут сам не знаю)
//3. Спелл сделан без кастомных функций, попытался более менее разъяснить о функциях для новичков, если где-то какая то ошибка, просьба отписать о ней)
//4. Итерация (повторение) - повторение таймера или цикла (тут таймер повторяется раз в 1 секунду, то есть раз в 1 секунду происходит итерация таймера)
globals //Начало глобальных переменных
hashtable HT = InitHashtable() //Создаётся хэш-таблица
group Group = CreateGroup() //Создаём группу, которую будем использовать для моментальной выборки юнитов
unit Caster //Создаётся переменная для кастеров
unit Target //Создаётся переменная для целей
timer Timer //Создаётся переменная для таймеров
integer TimerId //Создаётся переменная для хэндл-айди таймеров
//Константы для удобства изменения параметров способности
constant integer Blizzard_Id = 'A000' //Равкод способности
constant real Blizzard_Range = 300 //Область воздействия способности
constant real Blizzard_Damage = 30 //Урон способности
endglobals //Конец глобальных переменных
native UnitAlive takes unit id returns boolean //Объявляется функция с проверкой на то что юнит жив, если не объявить, то и юзать не получится
function Blizzard_Group takes nothing returns nothing //Функция группы (фильтрация и нанесение урона)
set Target = GetEnumUnit() //В переменную Target записывается выбираемый из группы юнит
if UnitAlive( Target ) and IsUnitEnemy( Target, GetOwningPlayer( Caster ) ) and not IsUnitType( Target, UNIT_TYPE_STRUCTURE ) then //Условие на то что юнит жив, юнит враг, юнит не структура
call UnitDamageTarget( Caster, Target, Blizzard_Damage, true, false, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_UNKNOWN, WEAPON_TYPE_WHOKNOWS ) //Наносит 300 урона отфильтрованным юнитам (врагам)
endif //Конец условия
endfunction
function Blizzard_Timer takes nothing returns nothing //Функция для таймера
set Timer = GetExpiredTimer() //В Timer записывается истекающий таймер
set TimerId = GetHandleId( Timer ) //в TimerId записывается хэндл-айди истекающего таймера
set Caster = LoadUnitHandle( HT, TimerId, 'cstr' ) //В Caster выгружается значение из хэш-таблицы которые мы сохранили под родительским ключем Timer-а (TimerId) и под дочерним ключем 'cstr'
//Ниже в двух функциях LoadReal мы таким же образом выгружаем наши значения из хэш-таблицы но уже под другими дочерними ключами
call GroupEnumUnitsInRange( Group, LoadReal( HT, TimerId, 'cstX' ), LoadReal( HT, TimerId, 'cstY' ), Blizzard_Range, null ) //Выделяет юнитов в области Blizzard_Range (константа равная 300) и их добавление в группу
call ForGroup( Group, function Blizzard_Group ) //Тут происходит вызов действия для группы
call GroupClear( Group ) //Очистка группы от всех юнитов
if GetUnitCurrentOrder( Caster ) != OrderId( "blizzard" ) then //Условие на то что наш герой перестал применять Буран
//if GetUnitCurrentOrder( Caster ) != 0xd0079 then - этот вариант работает быстрее, так как использует id приказа без лишней возни со строками (без OrderId)
call PauseTimer( Timer ) //Остановка таймера (таймер нужно остановить перед удалением так как иногда случается баг что итерация таймера происходит ещё раз)
call DestroyTimer( Timer ) //Удаление таймера
call FlushChildHashtable( HT, TimerId ) //Очистка хэш-таблицы по родительскому ключу (хэндл-айди Timer-а - TimerId)
endif //Конец условия
endfunction //Конец функции
function Blizzard_Actions takes nothing returns nothing //Функция когда герой или юнит применяет способность
if GetSpellAbilityId() == Blizzard_Id then //Условие если способность равна Blizzard_Id (константа равная равкоду Бурана 'A000')
//CTRL + D в редакторе объектов что-бы узнать равкод чего либо
set Timer = CreateTimer() //Создание таймера и его запись в переменную Timer
set TimerId = GetHandleId( Timer ) //Получение хэндл-айди Timer-а и его запись в переменную TimerId
//Сохранения в хэш-таблицу по родительскому ключу TimerId
call SaveUnitHandle( HT, TimerId, 'cstr', GetTriggerUnit() ) //Сохраняется применяющий способность герой или юнит по дочернему ключу 'cstr'
call SaveReal( HT, TimerId, 'cstX', GetSpellTargetX() ) //Сохраняется точка применения способности X по дочернему ключу 'cstX'
call SaveReal( HT, TimerId, 'cstY', GetSpellTargetY() ) //Сохраняется точка применения способности Y по дочернему ключу 'cstY'
call TimerStart( Timer, 1.0, true, function Blizzard_Timer ) //Запуск таймера Timer периодичностью в 1 секунду к которому привязана функция Blizzard_Timer (3 аргумент отвечает за периодичность)
endif //Конец условия
endfunction //Конец функции
function InitTrig_Blizzard takes nothing returns nothing //Функция инициализации триггера (из функции main вызывается InitCustomTriggers() которая вызывает инициализацию всех триггеров на карте)
local trigger t = CreateTrigger() //Создание триггера
local integer i = 0 //Объявление целочисленной переменной
loop //Начало цикла
call TriggerRegisterPlayerUnitEvent( t, Player( i ), EVENT_PLAYER_UNIT_SPELL_EFFECT, null ) //Регистрирует событие применения способности для игрока i (изначально 0, 0 = 1 игрок, и т.д.)
set i = i + 1 //Добавление 1 к i
exitwhen i == bj_MAX_PLAYER_SLOTS //Условие выхода из цикла, тут вместо bj константы должно быть указано макс. кол-во игроков на карте
endloop //Конец цикла
call TriggerAddAction( t, function Blizzard_Actions ) //В триггер добавляется функция с действиями при применения способности
set t = null //Обнуляется локальная переменная
call FogEnable( false ) //Это для видимости на всю карту (удалить)
call FogMaskEnable( false ) //Это для видимости на всю карту (удалить)
endfunction //Конец функции
Ред. nazarpunk
Ред. LastUchiha
Ред. nazarpunk
Ред. LastUchiha
Ред. LastUchiha
Ред. nazarpunk
Ред. LastUchiha
Ред. nazarpunk
Ред. nazarpunk
2
3 - Рандом сработал, через 8 тиков на нужно нанести урон. Значит i = 8 + 3 = 11. Сохраняем на 11 тик координаты.
4
5 - Рандом сработал, через 8 тиков на нужно нанести урон. Значит i = 8 + 5 = 13. Сохраняем на 13 тик координаты.
6
7 - Кастер прервал заклинание, но i=13, а 7 < 13, пишем флаг, что плодить плямбы больше не нужно и продолжаем тикать
8
9
10
11 - В этой ячейке есть координаты, наносим урон
12
13 - В этой ячейке есть координаты, наносим урон, заодно прерываем заклинание ибо есть флаг и 13 >= 13
Ред. LastUchiha
Вместо этого не умножаю на два, а просто вместо единицы прибавляю 100 для уверенности.
Также если перестать кастовать буран после 16 тика, урона не будет. Тут я не могу догадаться как сделать.
Ред. nazarpunk
Ред. nazarpunk
Ред. LastUchiha
за запятую в конце предложения тоже лайк
Те кому хочется разных клевых механик может с таких наработок взять разве что идею и мб глянуть как именно сделан спел, а дальше с 0 сделают под себя.
Короче не такая уж это и бессмысленная затея.
Ред. LastUchiha
Ред. LastUchiha