На то что не вынес LoadInteger значение в переменную не обращай внимания.
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'
set CastX = LoadReal( HT, TimerId, 'cstX' )
set CastY = LoadReal( HT, TimerId, 'cstY' )
call SaveInteger( HT, TimerId, 'time', LoadInteger( HT, TimerId, 'time' ) + 1 )
if LoadInteger( HT, TimerId, 'time' ) >= 8 then //Условие: 8 = 0.8 = время полёта эффекта (задержка перед уроном вначале)
call GroupEnumUnitsInRange( Group, CastX, CastY, Blizzard_Range, null ) //Выделяет юнитов в области Blizzard_Range (константа равная 300)
call ForGroup( Group, function Blizzard_Group ) //Тут происходит вызов действия для группы
call GroupClear( Group ) //Очистка группы от всех юнитов
endif //Конец условия
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)
else
//Если выложу спелл - закоменчу.
if LoadInteger( HT, TimerId, 'time' ) < 23 then
if GetRandomInt( 0, 1 ) == 0 then
call DestroyEffect( AddSpecialEffect( "Rain of Fire.mdx", GetRandomReal( CastX - Blizzard_Range / 2, CastX + Blizzard_Range / 2 ), GetRandomReal( CastY - Blizzard_Range / 2, CastY + Blizzard_Range / 2 ) ) )
else
call DestroyEffect( AddSpecialEffect( "Rain of Fire Fel.mdx", GetRandomReal( CastX - Blizzard_Range / 2, CastX + Blizzard_Range / 2 ), GetRandomReal( CastY - Blizzard_Range / 2, CastY + Blizzard_Range / 2 ) ) )
endif
endif
endif //Конец условия
endfunction //Конец функции
function Blizzard_Actions takes nothing returns nothing //Функция когда герой или юнит применяет способность
if GetSpellAbilityId() == Blizzard_Id then //Условие если способность равна Blizzard_Id (константа равная равкоду Бурана 'A000')
//CTRL + D в редакторе объектов что-бы узнать равкод чего либо
set CastX = GetSpellTargetX()
set CastY = GetSpellTargetY()
set Timer = CreateTimer()
set TimerId = GetHandleId( Timer )
//Сохранения в хэш-таблицу по родительскому ключу TimerId
call SaveUnitHandle( HT, TimerId, 'cstr', GetTriggerUnit() ) //Сохраняется применяющий способность герой или юнит по дочернему ключу 'cstr'
call SaveReal( HT, TimerId, 'cstX', CastX ) //Сохраняется точка применения способности X по дочернему ключу 'cstX'
call SaveReal( HT, TimerId, 'cstY', CastY ) //Сохраняется точка применения способности Y по дочернему ключу 'cstY'
call SaveInteger( HT, TimerId, 'time', 0 )
call TimerStart( Timer, 0.1, true, function Blizzard_Timer ) //Запуск таймера Timer периодичностью в 1 секунду к которому привязана функция Blizzard_Timer (3 аргумент отвечает за периодичность)
endif //Конец условия
endfunction //Конец функции
nazarpunk, ну тут у тебя в спелле моментальный эффект удара, а у меня пока долетит... Мне теперь что-ли 2 таймера запускать (один для эффекта, а другой для всего остального) ?
nazarpunk, вот, сделал всё максимально близко к твоему способу за исключением нескольких моментов:
exitwhen внизу
в функции каста в проверку на способность сразу вставил код вместо return
не записываю в функции каста координаты каста в переменные CastX, CastY, а сразу записываю в хэш-таблицу
с выгрузкой координат каста также, не записываю в переменные, а сразу выгружаю в GroupEnum
OrderId( "blizzard" ) оставил для ясности (если бы код выходил за рамки пособия - то пожалуйста)
все 3 if-а собрал в один if, имхо это правильный вариант (моя задача показать новичкам как правильно сделать, а не как улучшить читаемость кода до небес), насчёт читаемости безспорно твой вариант лучше.
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 = 300
endglobals
native UnitAlive takes unit id returns boolean
function Blizzard_Group takes nothing returns nothing
set Target = GetEnumUnit()
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 )
endif
endfunction
function Blizzard_Timer takes nothing returns nothing
set Timer = GetExpiredTimer()
set TimerId = GetHandleId( Timer )
set Caster = LoadUnitHandle( HT, TimerId, 'cstr' )
call GroupEnumUnitsInRange( Group, LoadReal( HT, TimerId, 'cstX' ), LoadReal( HT, TimerId, 'cstY' ), Blizzard_Range, null )
call ForGroup( Group, function Blizzard_Group )
call GroupClear( Group )
if GetUnitCurrentOrder( Caster ) != OrderId( "blizzard" ) then
call PauseTimer( Timer )
call DestroyTimer( Timer )
call FlushChildHashtable( HT, TimerId )
endif
endfunction
function Blizzard_Actions takes nothing returns nothing
if GetSpellAbilityId() == Blizzard_Id then
set Timer = CreateTimer()
set TimerId = GetHandleId( Timer )
call SaveUnitHandle( HT, TimerId, 'cstr', GetTriggerUnit() )
call SaveReal( HT, TimerId, 'cstX', GetSpellTargetX() )
call SaveReal( HT, TimerId, 'cstY', GetSpellTargetY() )
call TimerStart( Timer, 1, true, function Blizzard_Timer )
endif
endfunction
function InitTrig_Blizzard takes nothing returns nothing
local trigger t = CreateTrigger()
local integer i = 0
loop
call TriggerRegisterPlayerUnitEvent( t, Player( i ), EVENT_PLAYER_UNIT_SPELL_EFFECT, null )
set i = i + 1
exitwhen i == bj_MAX_PLAYER_SLOTS
endloop
call TriggerAddAction( t, function Blizzard_Actions )
set t = null
endfunction
IzobretatelBoom, ставить exitwhen в самом низу также норм идея. Читается - читается! Ищется - ищется! Не проводиться лишняя итерация цикла - не проводится!
» WarCraft 3 / [JASS] - Буран
Ред. LastUchiha
» WarCraft 3 / [JASS] - Буран
» WarCraft 3 / [JASS] - Буран
Ред. LastUchiha
» WarCraft 3 / [JASS] - Буран
» WarCraft 3 / [JASS] - Буран
Ред. LastUchiha
» WarCraft 3 / [JASS] - Буран
Ред. LastUchiha
» WarCraft 3 / [JASS] - Буран
Ред. LastUchiha
» WarCraft 3 / [JASS] - Буран
» WarCraft 3 / [JASS] - Буран
» WarCraft 3 / [JASS] - Буран
» WarCraft 3 / [JASS] - Буран
» WarCraft 3 / [JASS] - Буран
Ред. LastUchiha
» WarCraft 3 / [JASS] - Буран
Прокрутить к ресурсу
» WarCraft 3 / [JASS] - Буран
Ред. LastUchiha
» WarCraft 3 / [JASS] - Буран
Ред. LastUchiha
» WarCraft 3 / [JASS] - Буран
» WarCraft 3 / [JASS] - Буран
Ред. LastUchiha
» WarCraft 3 / [JASS] - Буран
» WarCraft 3 / [JASS] - Буран
» WarCraft 3 / [JASS] - Буран
» WarCraft 3 / [JASS] - Буран
» WarCraft 3 / [JASS] - Буран
Ред. LastUchiha
» WarCraft 3 / [JASS] - Буран
» WarCraft 3 / [JASS] - Буран
» WarCraft 3 / [JASS] - Буран