Всем доброго времени суток! Пишу заклинание на jass на основе канала. Задумка следующая: повелитель ужаса кастует пустышку, воспроизводя необходимую анимацию, затем цель поднимается в воздух и там взрывается. Однако проблема с воспроизведением анимации кастера. Указанная анимация начинает воспроизводится и тут же прерывается, буквально спустя секунду. И как бы я не пытался и так и эдак настроить канал, ничего не помогает. Делаю время подготовки не 0, а N секунд, к примеру 3, он сначала ждет эти 3 секунды, потом происходит ровно то же самое, дерганье: анимация начинает проигрываться и сбивается, затем срабатывает код заклинания. Хорошо, я решил в коде задать нужную анимацию кастеру, выждать необходимое время, затем применить заклинание и тут начались удивительные вещи. Изначально хотел сделать без коллбэка, просто используя PolledWait:
function SetUnitZ takes unit target, real value returns nothing
local location targetLocation = GetUnitLoc(target)
call UnitAddAbility(target, 'Aave')
call SetUnitFlyHeight(target, value - GetLocationZ(targetLocation), 100)
call SetUnitAnimationByIndex(target, 5)
call UnitRemoveAbility(target, 'Aave')
call RemoveLocation(targetLocation)
set targetLocation = null
endfunction
function AnnihilationActions takes nothing returns nothing
local unit target = GetSpellTargetUnit()
local unit caster = GetSpellAbilityUnit()
call SetUnitAnimation(caster, "spell slam")
call PolledWait(3)
call SetUnitZ(target, 400)
call SetUnitExploded(target, true)
call KillUnit(target)
set target = null
set caster = null
endfunction
function InitTrig_Annihilation_Conditions takes nothing returns boolean
if (GetUnitAbilityLevel(GetSpellAbilityUnit(), udg_Annihilation) > 0) then
call AnnihilationActions()
endif
return false
endfunction
//===========================================================================
function InitTrig_Annihilation takes nothing returns nothing
set gg_trg_Annihilation = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(gg_trg_Annihilation, EVENT_PLAYER_UNIT_SPELL_CHANNEL)
call TriggerAddCondition(gg_trg_Annihilation, Condition(function InitTrig_Annihilation_Conditions))
endfunction
После применения способности, игра просто доходит до ожидания, вызывает его и все. Можно ждать бесконечно, остальной код не будет исполнен. Окей, я привык, что некоторые вещи в варкрафте не работают просто потому что, как например функция DisplayTextToForce в скриптах AI. Хорошо, я решил сделать свой таймер и свой цикл(далее буду приводить только необходимый код, без прочей мишуры триггера):
function AnnihilationActions takes nothing returns nothing
local unit target = GetSpellTargetUnit()
local unit caster = GetSpellAbilityUnit()
local timer spellDurationTimer = CreateTimer()
call SetUnitAnimation(caster, "spell slam")
call TimerStart(spellDurationTimer, 3, false, null)
loop
exitwhen TimerGetRemaining(spellDurationTimer) <= 0
endloop
call DestroyTimer(spellDurationTimer)
set spellDurationTimer = null
call SetUnitZ(target, 400)
call SetUnitExploded(target, true)
call KillUnit(target)
set target = null
set caster = null
endfunction
Результат тот же, до кода, следующего после цикла, исполнение не доходит. Ладно, я сдался и написал коллбэк, хотя я в упор не понимаю в чем тут дело и хотел бы узнать, что происходит. Теперь это работает, но лишь отчасти:
function ExecuteCast takes nothing returns nothing
local timer spellDurationTimer = GetExpiredTimer()
local integer timerHandle = GetHandleId(spellDurationTimer)
local unit target = LoadUnitHandle(udg_Hash, timerHandle, 0)
local unit caster = LoadUnitHandle(udg_Hash, timerHandle, 1)
call ResetUnitAnimation(caster)
call SetUnitExploded(target, true)
call KillUnit(target)
call DestroyTimer(spellDurationTimer)
set spellDurationTimer = null
endfunction
function AnnihilationActions takes nothing returns nothing
local unit target = GetSpellTargetUnit()
local unit caster = GetSpellAbilityUnit()
local timer spellDurationTimer = CreateTimer()
local integer timerHandle = GetHandleId(spellDurationTimer)
call SaveUnitHandle(udg_Hash, timerHandle, 0, target)
call SaveUnitHandle(udg_Hash, timerHandle, 1, caster)
call SetUnitAnimationByIndex(caster, 11)
call SetUnitZ(target, 400)
call TimerStart(spellDurationTimer, 5, false, function ExecuteCast)
set target = null
set caster = null
endfunction
Дредлорда как колбасило при касте, так и колбасит, анимацию он отказывается адекватно воспроизводить, хотя я перепробовал SetUnitAnimation, QueueUnitAnimation и SetUnitAnimationByIndex. И еще есть одна проблемка, с которой я пока не могу справиться, почему то при взрыве юнит мгновенно оказывается на земле, а я добиваюсь, чтобы его разорвало именно в воздухе. Буду рад вашим советам.
Принятый ответ
TriggerSleepAction нельзя вызвать в кондишенах, только в действиях. Либо юзай экзекют, либо не юзай вейтПосле применения способности, игра просто доходит до ожидания, вызывает его и все. Можно ждать бесконечно, остальной код не будет исполнен.
Ты таким образом себе оп лимит сломал, ведь в первую же долю секунды цикл обрабатывает 25к+ действийРезультат тот же, до кода, следующего после цикла, исполнение не доходит.
Таймером создаёшь нулевую задержку, устанавливаешь нужную анимацию, а дальше уже либо периодиком проверяешь приказ и отменяешь анимацию, либо через время просто отменяешь анимацию. Это основы гуи, не то что джасс)Дредлорда как колбасило при касте, так и колбасит, анимацию он отказывается адекватно
вот так решается первый вариант
function InitTrig_Annihilation_Conditions takes nothing returns boolean
if (GetUnitAbilityLevel(GetSpellAbilityUnit(), udg_Annihilation) > 0) then
call ExecuteFunc( "AnnihilationActions" )
endif
return false
endfunction
и так второй
function ExecuteCast takes nothing returns nothing
local timer spellDurationTimer = GetExpiredTimer()
local integer timerHandle = GetHandleId(spellDurationTimer)
local unit target = LoadUnitHandle(udg_Hash, timerHandle, 0)
local unit caster = LoadUnitHandle(udg_Hash, timerHandle, 1)
call ResetUnitAnimation(caster)
call SetUnitExploded(target, true)
call KillUnit(target)
call DestroyTimer(spellDurationTimer)
set spellDurationTimer = null
endfunction
function SetAnim takes nothing returns nothing
local timer t = GetExpiredTimer( )
call SetUnitAnimation( LoadUnitHandle( H, GetHandleId( t ), 1 ), "channel" )
call TimerStart(t, 5, false, function ExecuteCast)
set t = null
endfunction
function AnnihilationActions takes nothing returns nothing
local unit target = GetSpellTargetUnit()
local unit caster = GetSpellAbilityUnit()
local timer spellDurationTimer = CreateTimer()
local integer timerHandle = GetHandleId(spellDurationTimer)
call SaveUnitHandle(udg_Hash, timerHandle, 0, target)
call SaveUnitHandle(udg_Hash, timerHandle, 1, caster)
call SetUnitAnimationByIndex(caster, 11)
call SetUnitZ(target, 400)
call TimerStart(spellDurationTimer, 0.00, false, function SetAnim)
set target = null
set caster = null
set spellDurationTimer = null
endfunction
`
ОЖИДАНИЕ РЕКЛАМЫ...
Чтобы оставить комментарий, пожалуйста, войдите на сайт.
Vlod, спасибо за ваше время. Я ориентировался на огненный столб, у которого время подготовки не 0 и чародей крови воспроизводит анимацию без проблем.
Ред. Meddin
Ну и написать код на отмену заклинания и на случай оглушения, если только он не входит в случай отмены, это сейчас и пробую реализовать. Сдается мне, что я напрасно привязал заклинание к событию EVENT_PLAYER_UNIT_SPELL_CHANNEL, нужно было использовать все же EVENT_PLAYER_UNIT_SPELL_FINISH...
Ред. Meddin