Здравствуйте. Сделал простое окно таймера и оно работает. Чтобы не вызывать отдельные события по истечению таймера вчерез другой триггер, сделал внутри ожидание через wait ex. Таймеор и окно работает, но иногда по истечению времени окно не закрывается и висит еще лишние секунд 15, в чем моя ошибка?
unction Trig_ReadyTime_Actions takes nothing returns nothing

local real Timerivan
local timer IvanTimer
local timerdialog IvanWindow
set Timerivan = 60.00
set IvanTimer = CreateTimer()
IvanTimer=bj_lastStartedTimer
call StartTimerBJ( IvanTimer, false, Timerivan )
call CreateTimerDialogBJ( IvanTimer, ( "Следующая волна:" ) )
set IvanWindow = bj_lastCreatedTimerDialog
call TimerDialogDisplayForPlayerBJ( true,IvanWindow, GetOwningPlayer(udg_Hero[1] ))
call TimerDialogDisplayForPlayerBJ( true,IvanWindow, GetOwningPlayer(udg_Hero[2] ))
call TimerDialogDisplayForPlayerBJ( true,IvanWindow, GetOwningPlayer(udg_Hero[3] ))
call TimerDialogDisplayForPlayerBJ( true,IvanWindow, GetOwningPlayer(udg_Hero[4] ))
call TimerDialogDisplayForPlayerBJ( true,IvanWindow, GetOwningPlayer(udg_Hero[5] ))
call TimerDialogDisplayBJ( true,IvanWindow )
call WAIT_EX(60.)
call TimerDialogDisplayBJ( false,IvanWindow )
call DestroyTimerDialogBJ( IvanWindow )
call TriggerExecute( gg_trg_Wawe )
set IvanTimer =null
set IvanWindow=null
endfunction
===========================================================================
function InitTrig_ReadyTime takes nothing returns nothing
set gg_trg_ReadyTime = CreateTrigger( )
call TriggerAddAction( gg_trg_ReadyTime, function Trig_ReadyTime_Actions )
endfunction

По сути тут мы проверяем каждые 0.1 сек, когда там таймер завершится (с помощью call TriggerSleepAction(0.1)), и дальше закрываем окно. Все локально, в одном коде без дополнительных событий. Не сказать, что прямо оптимизированно и точно, но для твоей задачи сгодится. Если надо более точное время - ставишь не 0.1 а 0.01 или 0.05 к примеру.
`
ОЖИДАНИЕ РЕКЛАМЫ...
28
Отобрази проблему на отдельной карте и скинь сюда
25
wait и таймер могут завершиться немного с разным временем, даже если ты поставил одинаковое число. Лучше делай по событию "таймер истек" действия по закрытию окна, а не через wait.
Так-же мне показалось много странного в коде. Ты сам сможешь объяснить каждую строку, зачем она нужна, вот тут к примеру:
set IvanTimer = CreateTimer()
IvanTimer=bj_lastStartedTimer
Мне кажется тут есть лишние строки кода, но мб чего-то не помню и надо потестить.

А чтобы потестить - скинь карту с примером :)
Ответы (14)
21
konvan5, Вот и срабатывает рассинхрон!
А на переодическое событие "таймер истекает", если с другого триггера это фиговая идея, мне кажется, потому что оно само по себе может не срабатывать, у меня сто раз так было. Поэтому ожидание и запихнул в таймер
25
SсRealm, как это может не сработать? Если таймер запущен то событие будет запущено :D
21
konvan5, я же для этого и сделал таймер и окно таймере через локалку, если сделать его снова глобальным то старые окна не будут перезаписываться и начнут висеть потому что глобальная то не создается отдельным потоком и варик как всегда не поймет, какое окно удалить, а которое оставить.
Ну напишу я set IvanTimer= udg_IvanTimer но это создаст ту же проблему(
25
SсRealm, ну с таким подходом, естественно, локальные переменные смысла делать нет, используй глобалки. Ты же не планируешь 100 таймеров одновременно запускать.
21
konvan5, конечно планирую. А запустить переодическое событие таймера если оно локальное то вообще никак.
21
konvan5, даже три окна в глобалке висят на веки вечные. Мы отвлеклись от темы, да, скорее всего зависает из за рассинхрона с вейтом
28
konvan5, он не совсем понимает о чём говорит и что вообще в коде происходит
14
даже три окна в глобалке висят на веки вечные
ты сейчас про CreateTimerDialogBJ ?
делай в глобалку - timerdialog td=null , тогда окно будет удаляться
даже если в глобалку напишешь timerdialog td - то не будет удаляться, надо с null
local timerdialog IvanWindow
вот у тебя и в локалке без null

у тебя даже нет
call PauseTimer(t)
call DestroyTimerDialog(td)
как ты там их вообще останавливаешь
и да, окно и таймер не связаны, т.е. после удаления только окна - таймер продолжит тикать

твои
set IvanTimer =null
set IvanWindow=null
вообще ничего не делают относительно удаления таймерных объектов
кури коменты тут xgm.guru/p/wc3/Kak-obnulit-dannyy-tip-peremennoy-iXc/comments/vi...
21
host_pi, function WAIT_EX takes real s returns nothing
local timer t = CreateTimer()
call TimerStart(t,s,false,null)
loop
call TriggerSleepAction(s)
exitwhen TimerGetRemaining(t) == 0.
endloop
call DestroyTimer(t)
set t = null
endfunction
Таймер отдельно умирает, он через wait ex. сделан.
21
host_pi, Нет никакого рассинхрона. Сам ты там что -то куришь. Волны идут, герои воскрешаются. Как минимум, это полноценная замена обычному вейту. Ну, а как иначе? Создавать таймеры по отдельности?
23
SсRealm, неправильный wait ex, нужно такой юзать. Проверял его и с паузой, и секундомером, всё ок.
function WAIT_EX takes real r returns nothing
local timer t = CreateTimer()
    call TimerStart( t, r, false, null )

    loop
    exitwhen TimerGetElapsed(t) == r
            call TriggerSleepAction( 1.00 )
    endloop

    call DestroyTimer(t)
    set t = null
endfunction
28
host_pi, function WAIT_EX takes real s returns nothing
local timer t = CreateTimer()
call TimerStart(t,s,false,null)
loop
call TriggerSleepAction(s)
exitwhen TimerGetRemaining(t) == 0.
endloop
call DestroyTimer(t)
set t = null
endfunction
Таймер отдельно умирает, он через wait ex. сделан.
Что это за бред..
Ответы (25)
21
rsfghd,Вот отсюда взял, мне же и насоветовали, заменяет вейт. У меня работает, как там с паузой, не знаю! xgm.guru/p/100/Taymer-vmesto-veyt-DPM/comments
25
SсRealm Ты похоже не очень понял, что там писали или зачем это писали😅
21
konvan5, Да и пофигу! Главное - работает.
Как не зайдешь на ХГМ - все все на свете знают, а я всегда не прав. Пойду дальше делать карту. Всем спасибо, вопрос закрыт.
25
SсRealm, я думаю ты просто запутался в своей реализации, начал использовать разные инструменты, смешав их в одну кучу, и в итоге не получается так как ты хочешь. Может тогда опишешь изначальную цель, что ты хочешь получить (четко и понятно по порядку).
В идеале еще предоставишь карту, как у тебя работает. Можешь вынести весь нужный код в отдельную пустую карту, чтобы мы могли потестить твой случай и сказать в чем ты не прав, ибо по скринам не всегда понятно, что у тебя пошло не так ибо может быть ты не всю информацию нам предоставляешь.
28
konvan5, Да и пофигу! Главное - работает.
Как не зайдешь на ХГМ - все все на свете знают, а я всегда не прав. Пойду дальше делать карту. Всем спасибо, вопрос закрыт.
Обиделся в общем. Ты в джассе на уровне новичка, тебе пытаются помочь более грамотные люди, но вместо того, чтобы принять критику и сказать прямо "исправьте пожалуйста мой код, он работать должен так-то", после чего подчеркнуть какие-то новые возможности для себя, ты решаешь уйти практически ни с чем. Не ленись и черпай информацию откуда только можно, тем более, когда тебе её могут максимально лаконично предоставить люди, которые понимают что кодят
21
konvan5,
Тестовая карта. Через 10 сек появляется волна и она то задерживается после таймера, то нет. После частого запуска варика( проверки карты ) ошибка с задержкой таймера перед первой волной повторяется. Если тестить отдельный таймер по той же схеме, то с воскрешением героев ошибки нет
Загруженные файлы
25
SсRealm, у тебя действия в инициализации запускаются. Из-за этого могут быть сдвиги какие-то. Как то-же окно таймера в инициализации, как помню, не создается.
Поэтому запускай триггер по событию "время прошло". Хотя бы 0.01 сек ставишь и уже не в инициализации запускаешь триггер.
Типа так:
Если что, действия инициализации происходят во время загрузки карты (в конце в основном).
Загруженные файлы
25
Хотя не, причина похоже не в этом, сейчас подумаем теперь над твоим кодом...
25
Как минимум если поставить задержку в 1 секунду, такой проблемы я не вижу.
Загруженные файлы
21
SсRealm, у тебя действия в инициализации запускаются. Из-за этого могут быть сдвиги какие-то. Как то-же окно таймера в инициализации, как помню, не создается.
Поэтому запускай триггер по событию "время прошло". Хотя бы 0.01 сек ставишь и уже не в инициализации запускаешь триггер.
Типа так:
Если что, действия инициализации происходят во время загрузки карты (в конце в основном).
В оригинале у меня там стоит юнит входит в область и триггер выключается, это просто пример
25
SсRealm, а еще, тебе же надо дождаться окончания таймера, почему бы вместо вейта не использовать ожидание окончания таймера как УЖЕ сделано в вейте? :D
Без отдельного триггера с событием.
21
konvan5, Если я уберу вейт, то таймер вовсе не появляется. Отчет проходит без отображения таймера
25
SсRealm, вот как раз проблема внутри вейта... просто таймер и действие TriggerSleepAction с указанием одного и того-же времени на самом деле могут ждать разное время. Одно привязывается к игровому времени а второе к системному.
К примеру если у тебя карта лагает, время может замедлятся/ ускорятся внутри игры, а вот системное будет стабильное. Помню уже были подобные проблемы со временем.
25
SсRealm, в итоге, подставив реализацию вейта и немного переделав, получится вот такой код:
function Trig_ReadyTime_Actions takes nothing returns nothing
    local timerdialog IvanWindow
    local real Timerivan
    local timer IvanTimer 
    set Timerivan = 10.00 
    set IvanTimer  = CreateTimer()
    call StartTimerBJ( IvanTimer, false, Timerivan )
    call CreateTimerDialogBJ( IvanTimer, ( "Следующая волна:" ) )
    set IvanWindow = bj_lastCreatedTimerDialog
    call TimerDialogDisplayForPlayerBJ( true, IvanWindow, GetOwningPlayer(udg_Hero[1] ))
    call TimerDialogDisplayForPlayerBJ( true, IvanWindow, GetOwningPlayer(udg_Hero[2] ))
    call TimerDialogDisplayForPlayerBJ( true, IvanWindow, GetOwningPlayer(udg_Hero[3] ))
    call TimerDialogDisplayForPlayerBJ( true, IvanWindow, GetOwningPlayer(udg_Hero[4] ))
    call TimerDialogDisplayForPlayerBJ( true, IvanWindow, GetOwningPlayer(udg_Hero[5] ))
    loop
        call TriggerSleepAction(0.1)
        exitwhen TimerGetRemaining(IvanTimer) == 0.
    endloop
    call TimerDialogDisplayBJ( false, IvanWindow )
    call DestroyTimerDialogBJ( IvanWindow )
    call DestroyTimer(IvanTimer)
    set IvanTimer = null
    set IvanWindow = null
    call TriggerExecute( gg_trg_Wawe )
endfunction
Некоторые вещи я тебе тут убрал лишние и добавил уничтожение таймера.
25
По сути тут мы проверяем каждые 0.1 сек, когда там таймер завершится (с помощью call TriggerSleepAction(0.1)), и дальше закрываем окно. Все локально, в одном коде без дополнительных событий. Не сказать, что прямо оптимизированно и точно, но для твоей задачи сгодится. Если надо более точное время - ставишь не 0.1 а 0.01 или 0.05 к примеру.
Принятый ответ
21
konvan5, Знаешь, спасибо. Если твой вариант окажется рабочим, то я же могу переменную integer использовать вместо числа в твоем варианте?
Давно была идея, чтобы игроки докупали время перерыва, если им это необходимо. В wait ex это сделать было бы проблематично, а тут вполне можно попробовать))😊
21
konvan5, Проверил, пока работает. Если какие - то косяки появятся, я напишу сюда или в личку.
25
SсRealm, кстати, только сейчас заметил, схожую тему выше показал EugeAl, но у меня будет еще более точная проверка за счет меньшего слипа + интегрирован сразу же в твой код с твоим таймером, то есть не придется создавать второй параллельный таймер, как если бы ты юзал этот вейт.
38
SсRealm, вейт нельзя использовать в цикле - у него копится погрешность в рамках одного подпотока события
23
ScorpioT1000, так тут суть цикла не только в вейте, вейт только задержку делает чтоб код не запускался раньше времени, и какая у него будет погрешность - неважно, ведь цикл и продолжение дальнейшего кода привязаны именно к таймеру. Если игрок сделает паузу - вейт пусть работает, если будет работать, главное что таймер встанет и всё будет ок. Конечно, поток обрубится, но для того и есть локалки ) Что же насчет погрешности +-0,5 сек, это не критично )
38
EugeAl, там будет не 0.5 сек, там будут копиться секунды с каждым новым вызовом. Я даже не в цикле имел проблемы с ним при создании различных синематиков
25
ScorpioT1000, поэтому идеально для такого использовать таймеры вместе с событиями окончания таймера в отдельных триггерах/функциях.
23
ScorpioT1000, так ведь вейты все маленькие, максимум по 1 секунде. Больше не нужно. Или игра собирает лишнюю задержку со всех вейтов в потоке и суммирует её?
Не в цикле, без доп таймера - там другое, там только вейт управляет ходом скрипта, там может быть. Потому и нужен управляющий таймер с циклом вейтов
38
EugeAl, как будто бы суммирует какую-то погрешность, точно не проверял
23
ScorpioT1000, Ну это тогда плоховато, конечно, если так
Чтобы оставить комментарий, пожалуйста, войдите на сайт.