16

» WarCraft 3 / [JASS] - Буран

nazarpunk, пришлось включить мозги...
На то что не вынес 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 //Конец функции
Загруженные файлы
16

» WarCraft 3 / [JASS] - Буран

KaneThaumaturge, я понял, у меня уже был случай перезаписи, но там в кастомной функции перезаписывало)
16

» WarCraft 3 / [JASS] - Буран

KaneThaumaturge, а, ну тут уже зависит от пользователя и того что он хочет реализовать.
16

» WarCraft 3 / [JASS] - Буран

KaneThaumaturge, при правильном использовании ведь не словить (ну только если действий не особо много)?
16

» WarCraft 3 / [JASS] - Буран

nazarpunk, ну тут у тебя в спелле моментальный эффект удара, а у меня пока долетит... Мне теперь что-ли 2 таймера запускать (один для эффекта, а другой для всего остального) ?
16

» WarCraft 3 / [JASS] - Буран

nazarpunk, так а про итерацию, вынести к комментам в начале триггера?
16

» WarCraft 3 / [JASS] - Буран

nazarpunk, вот, сделал всё максимально близко к твоему способу за исключением нескольких моментов:
  1. exitwhen внизу
  2. в функции каста в проверку на способность сразу вставил код вместо return
  3. не записываю в функции каста координаты каста в переменные CastX, CastY, а сразу записываю в хэш-таблицу
  4. с выгрузкой координат каста также, не записываю в переменные, а сразу выгружаю в GroupEnum
  5. OrderId( "blizzard" ) оставил для ясности (если бы код выходил за рамки пособия - то пожалуйста)
  6. все 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
16

» WarCraft 3 / [JASS] - Буран

IzobretatelBoom, ставить exitwhen в самом низу также норм идея. Читается - читается! Ищется - ищется! Не проводиться лишняя итерация цикла - не проводится!
16

» WarCraft 3 / [JASS] - Буран

nazarpunk, а это ну для чего ? Ну то есть почему exitwhen выше и i = -1? Лишний раз срабатывает i = i + 1!
Загруженные файлы
16

» WarCraft 3 / [JASS] - Буран

nazarpunk, понял, и почему бы не использовать фильтр как отдельную функцию которая будет проставлена в GroupEnum ? Лишняя функция чи шо ?
16

» WarCraft 3 / [JASS] - Буран

nazarpunk, почему 3 условия стоят отдельно друг от друга ?
Загруженные файлы