[JASS]
как сделать 3 разных действия с одной периодичностью по таймеру?
Алгоритм:
запуск тригера - из чата
остановка тригера - тоже из чата
действие1 через 0.3 сек (итого 0,3)
действие2 через 0.3 сек (итого 0,6)
действие3 через 0.3 сек (итого 0,9)
действие1 через 0.3 сек (итого 1,2)
действие2 через 0.3 сек (итого 1,5)
действие3 через 0.3 сек (итого 1,8)
итд
набросал корявый код, нерабочий конечно:
globals
integer Go=0
integer N=0
endglobals

function Test_Act takes nothing returns nothing
local integer i=GetPlayerId(GetTriggerPlayer())
if ModuloInteger(N,3)==1 then
//0.3
call BJDebugMsg("111 "+I2S(i))
elseif ModuloInteger(N,3)==2 then
//0.6
call BJDebugMsg("222 "+I2S(i))
elseif ModuloInteger(N,3)==3 then
//0.9
call BJDebugMsg("333 "+I2S(i))
endif
set N=N+1
endfunction

function Test_Init takes nothing returns nothing
local integer i=GetPlayerId(GetTriggerPlayer())
local trigger t=CreateTrigger()
local timer time=CreateTimer()
If Go=0 then
set Go=1
call EnableTrigger(t)
else
set Go=0
call DisableTrigger(t)
call PauseTimer(time)
endif
//ver1
call TriggerRegisterTimerEventPeriodic(t, 0.3)
call TriggerAddAction(t, function Test_Act)
//ver2
call TimerStart(time, 0.3, true, function Test_Act)
endfunction

function Event takes nothing returns nothing
local string s=StringCase(GetEventPlayerChatString(),false)
if s=="-t" then
call Test_Init()
endif
endfunction
`
ОЖИДАНИЕ РЕКЛАМЫ...

Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
0
8
1 год назад
Отредактирован Poma
0
Важна ли синхронизация срабатываний между игроками? Для каждого игрока свой таймер/триггер, callback один на всех. При запуске таймера в таблицу на ID таймера/триггера записывается нужный игрок, при срабатывании он же читается.
1
13
1 год назад
Отредактирован Borodach
1
globals
integer PLAYERS=12
integer array N
timer array Ti
timer array TIME
integer array GO
endglobals

function OnPeriodic takes nothing returns nothing
local integer i=1
loop
exitwhen i>PLAYERS
if GO[i]==1 then
call BJDebugMsg("timer  i "+I2S(i)+"__GO[i] "+I2S(GO[i])+"__N [i] "+I2S(N[i])+"__Name "+GetPlayerName(Player(i-1)))
set GO[i] = 0
endif
set i = i + 1
endloop

endfunction

function Start takes nothing returns nothing
local string s=StringCase(GetEventPlayerChatString(),false)
local integer i=GetPlayerId(GetTriggerPlayer())+1
if s=="-g" then
set GO[i] = 1
endif
endfunction

function Start_init takes nothing returns nothing
local trigger t=CreateTrigger()
local integer i=1
loop
exitwhen i>PLAYERS
call TriggerRegisterPlayerChatEvent(t,Player(i-1),"-",false)
call TriggerAddAction(t, function Start)
set i=i+1
endloop
set TIME = CreateTimer()
call TimerStart(TIME, 0.3, true, function OnPeriodic)
endfunction

Смысл примерно таков для цыкла

Или каждому свой таймер
function Start_init takes nothing returns nothing
local trigger t=CreateTrigger()
local integer i=1
loop
exitwhen i>PLAYERS
call TriggerRegisterPlayerChatEvent(t,Player(i-1),"-",false)
call TriggerAddAction(t, function Start)
set TIME[i] = CreateTimer()
call TimerStart(TIME[i], 0.3, true, function OnPeriodic)
set i=i+1
endloop

endfunction
0
14
1 год назад
Отредактирован host_pi
0
у меня выше с таймерами алгоритмика хромала (если несколько раз отправить -g - то чаще тикало, таймеры накладывались)
у nazarpunk алгоритмика хорошая и рабочая
вот что получилось для 4х игроков на таймерах:
(из них у 1го игрока идёт общий подсчёт действий, у остальных без подсчёта)
globals
integer PLAYERS=12
integer array GO
integer array N
timer array Ti
endglobals

function OnPeriodic_4 takes nothing returns nothing
local integer i=4
set N[i]=N[i]+1
if N[i]==1 then
call BJDebugMsg("Action 1: "+GetPlayerName(Player(i-1)))
elseif N[i]==2 then
call BJDebugMsg("Action 2: "+GetPlayerName(Player(i-1)))
elseif N[i]==3 then
call BJDebugMsg("Action 3: "+GetPlayerName(Player(i-1)))
set N[i]=0
endif
endfunction
function OnPeriodic_3 takes nothing returns nothing
local integer i=3
set N[i]=N[i]+1
if N[i]==1 then
call BJDebugMsg("Action 1: "+GetPlayerName(Player(i-1)))
elseif N[i]==2 then
call BJDebugMsg("Action 2: "+GetPlayerName(Player(i-1)))
elseif N[i]==3 then
call BJDebugMsg("Action 3: "+GetPlayerName(Player(i-1)))
set N[i]=0
endif
endfunction
function OnPeriodic_2 takes nothing returns nothing
local integer i=2
set N[i]=N[i]+1
if N[i]==1 then
call BJDebugMsg("Action 1: "+GetPlayerName(Player(i-1)))
elseif N[i]==2 then
call BJDebugMsg("Action 2: "+GetPlayerName(Player(i-1)))
elseif N[i]==3 then
call BJDebugMsg("Action 3: "+GetPlayerName(Player(i-1)))
set N[i]=0
endif
endfunction
function OnPeriodic_1 takes nothing returns nothing
local integer i=1
set N[i]=N[i]+1
if ModuloInteger(N[i],3)==1 then
call BJDebugMsg(I2S(N[i])+" Action 1: "+GetPlayerName(Player(i-1)))
elseif ModuloInteger(N[i],3)==2 then
call BJDebugMsg(I2S(N[i])+" Action 2: "+GetPlayerName(Player(i-1)))
elseif ModuloInteger(N[i],3)==0 then
call BJDebugMsg(I2S(N[i])+" Action 3: "+GetPlayerName(Player(i-1)))
//set N[i]=0
endif
endfunction

function GOO takes nothing returns nothing
local integer i=GetPlayerId(GetTriggerPlayer())+1
if GO[i]==0 then
set GO[i]=1
set Ti[i]=CreateTimer()
else
set GO[i]=0
call PauseTimer(Ti[i])
call DestroyTimer(Ti[i])
call BJDebugMsg("STOP: "+GetPlayerName(Player(i-1)))
endif
set N[i]=0
if GO[i]==1 and i==1 then
call TimerStart(Ti[i], 1, true, function OnPeriodic_1)
elseif GO[i]==1 and i==2 then
call TimerStart(Ti[i], 1, true, function OnPeriodic_2)
elseif GO[i]==1 and i==3 then
call TimerStart(Ti[i], 1, true, function OnPeriodic_3)
elseif GO[i]==1 and i==4 then
call TimerStart(Ti[i], 1, true, function OnPeriodic_4)
endif
endfunction

function Start takes nothing returns nothing
local string s=StringCase(GetEventPlayerChatString(),false)
if s=="-g" then
call GOO()
endif
endfunction

function Start_init takes nothing returns nothing
local trigger t=CreateTrigger()
local integer i=1
loop
exitwhen i>PLAYERS
call TriggerRegisterPlayerChatEvent(t,Player(i-1),"-",false)
set i=i+1
endloop
call TriggerAddAction(t,function Start)
endfunction

call Start_init()
Смысл примерно таков для цыкла
в первом твоём коде:
ты загнал таймер сразу в Start_init
хотя эта функция вообще за чат отвечает, как и Start
т.е. до твоей правки они были универсальны, а после твоей правки стали бесполезно-громоздки, т.к. получился отдельный большой тригер-чата исключительно под таймер
+ если я правильно прочитал твой код в Start_init - то при старте карты у тебя включится таймер в бэк режиме, оттягивая на себя ресурсы просто так
+ у нас с панком команда из чата работает как вкл/выкл, как и было заявлено в первом посте. а у тебя получается она является стартующей. т.е. она только вкл
+ дебаг:
:39: Index missing for array variable TIME
:40: Index missing for array variable TIME
надо заменить
"timer array TIME" на "timer TIME=null" - для 1го кода
или оставить "timer array TIME" - для 2го кода
в обоих случаях дебаг строка выходит только в 1й тик таймера и потом перестаёт выводиться. что-то с алгоритмикой
второй код аналогично - только первая строка
попробую поискать где ошибка и как-то адаптировать чтобы заработало
вот
ты этой строкой выключаешь таймер после первого тика сразу внутри самого таймера

по поводу твоего второго варианта:
каждый 1 тик работает 12 раз (по количеству плееров)
т.е. если 1й игрок пишет -g то за 1 тик выдает 12 строк
видимо потому что в Start_init ты 12 раз запускаешь 12 таймеров т.е. 12 функций OnPeriodic за 1 тик
попробуй сам на карте
Загруженные файлы
1
29
1 год назад
1
из них у 1го игрока идёт общий подсчёт действий, у остальных без подсчёта
Держи. Каждому игроку по таймеру с подсчётом.
Хэштаблица хранит по хэндлу, так что можешь свою HandleHT переиспользовать.
//! zinc
library MyTimerLib {
    string msg = "-run";
    integer i, action[];
    timer ticker[];
    boolean running[];
    hashtable ht = InitHashtable();

    function onInit() {
        trigger t = CreateTrigger();

        for (0 <= i < bj_MAX_PLAYER_SLOTS) {
            if ( GetPlayerController(Player(i)) == MAP_CONTROL_USER && GetPlayerSlotState(Player(i)) == PLAYER_SLOT_STATE_PLAYING) {
                TriggerRegisterPlayerChatEvent(t, Player(i), msg, false);
                action[i] = - 1;
                running[i] = false;
                ticker[i] = CreateTimer();
                SaveInteger(ht, GetHandleId(ticker[i]), 0, i);
            }
        }

        TriggerAddAction(t, function() {
            i = GetPlayerId(GetTriggerPlayer());

            if (running[i]) {
                PauseTimer(ticker[i]);
                action[i] = - 1;
                running[i] = false;
                BJDebugMsg("Player: " + I2S(i) + ", stop");
                return;
            }
            running[i] = true;

            TimerStart(ticker[i], .3, true, function() {
                i = LoadInteger(ht, GetHandleId(GetExpiredTimer()), 0);

                action[i] += 1;

                BJDebugMsg("Player: " + I2S(i) + ", action: "  + I2S(action[i]));

                if (action[i] == 2) action[i] = - 1;
            });
        });

        t = null;
    }
}
//! endzinc
0
14
1 год назад
Отредактирован host_pi
0
Держи
работает
zinc to jass:
globals
string MyTimerLib___msg="-run"
integer MyTimerLib___i
integer array MyTimerLib___action
timer array MyTimerLib___ticker
boolean array MyTimerLib___running
hashtable MyTimerLib___ht=InitHashtable()
endglobals

function MyTimerLib___anon__1 takes nothing returns nothing
set MyTimerLib___i=LoadInteger(MyTimerLib___ht,GetHandleId(GetExpiredTimer()),0)
set MyTimerLib___action[MyTimerLib___i]=MyTimerLib___action[MyTimerLib___i]+1
call BJDebugMsg("Player: "+I2S(MyTimerLib___i)+", action: "+I2S(MyTimerLib___action[MyTimerLib___i]))
if(MyTimerLib___action[MyTimerLib___i]==2)then
set MyTimerLib___action[MyTimerLib___i]=-1
endif
endfunction

function MyTimerLib___anon__0 takes nothing returns nothing
set MyTimerLib___i=GetPlayerId(GetTriggerPlayer())
if(MyTimerLib___running[MyTimerLib___i])then
call PauseTimer(MyTimerLib___ticker[MyTimerLib___i])
set MyTimerLib___action[MyTimerLib___i]=-1
set MyTimerLib___running[MyTimerLib___i]=false
call BJDebugMsg("Player: "+I2S(MyTimerLib___i)+", stop")
return
endif
set MyTimerLib___running[MyTimerLib___i]=true
call TimerStart(MyTimerLib___ticker[MyTimerLib___i],.3,true,function MyTimerLib___anon__1)
endfunction

function MyTimerLib___onInit takes nothing returns nothing
local trigger t=CreateTrigger()
set MyTimerLib___i=0
loop
exitwhen(MyTimerLib___i>=bj_MAX_PLAYER_SLOTS)
if(GetPlayerController(Player(MyTimerLib___i))==MAP_CONTROL_USER and GetPlayerSlotState(Player(MyTimerLib___i))==PLAYER_SLOT_STATE_PLAYING)then
call TriggerRegisterPlayerChatEvent(t,Player(MyTimerLib___i),MyTimerLib___msg,false)
set MyTimerLib___action[MyTimerLib___i]=-1
set MyTimerLib___running[MyTimerLib___i]=false
set MyTimerLib___ticker[MyTimerLib___i]=CreateTimer()
call SaveInteger(MyTimerLib___ht,GetHandleId(MyTimerLib___ticker[MyTimerLib___i]),0,MyTimerLib___i)
endif
set MyTimerLib___i=MyTimerLib___i+1
endloop
call TriggerAddAction(t,function MyTimerLib___anon__0)
set t=null
endfunction

call ExecuteFunc("MyTimerLib___onInit")
т.е. на глобалках и таймерах подобный код не сделать с отдельным таймером для каждого плеера? (кроме как топорно отдельную функцию под отдельного плеера)
т.е. решить проблему передачи номера игрока внутрь таймера, что ты успешно проделал через HT
1
29
1 год назад
Отредактирован nazarpunk
1
т.е. на глобалках и таймерах подобный код не сделать с отдельным таймером для каждого плеера?
У меня код с отдельным таймером для каждого игрока какраз на глобалках. Можешь проверить через Multiwindow.
Вот здесь идёт получение номера игрока из ХТ. Игрока можно просто получить через Player(i).
Загруженные файлы
0
14
1 год назад
Отредактирован host_pi
0
Можешь проверить через Multiwindow.
проверил конечно
nazarpunk:
Вот здесь идёт получение номера игрока из ХТ.
имелись ввиду глобалки простые типа integer и string
в общем хештейбл я так понял это как словарь (еще и с древовидной child-parent структурой), из которого можно по нужной фразе вытянуть сохранённое значение
в данном случае тянется номер игрока по привязанному к нему id таймера. классное решение
1
29
1 год назад
1
имелись ввиду глобалки простые типа integer и string
Я только одну локалку использовал, всё остальное глобалки.
trigger t = CreateTrigger();
в общем хештейбл я так понял это как словарь
Это и есть хэш-таблица. Для простоты можешь относиться к ней как к к двумерному массиву с числовыми ключами.
ht[0][1] = somevalue;

данном случае тянется номер игрока по привязанному к нему id таймера. классное решение
Сохранение данных на хэндл это основа практически каждого MUI заклинания.
0
14
1 год назад
Отредактирован host_pi
0
накалякал вариант на тригере, таймерные тригеры у игроков также личные
по сути ничем не отличается по исполнению от таймера by nazarpunk
те же самые SaveInteger , LoadInteger
и ничего не оптимизировано, ничего не занулялось в конце функций
globals
integer PLAYERS=12
integer array GO
integer array N
trigger array tgo2
integer array tgo2_init
hashtable ht=InitHashtable()
endglobals

function GOO2_Actions takes nothing returns nothing
local integer i=LoadInteger(ht,GetHandleId(GetTriggeringTrigger()),0)
set N[i]=N[i]+1
if ModuloInteger(N[i],3)==1 then
call BJDebugMsg(I2S(N[i])+" Action 1: "+GetPlayerName(Player(i-1)))
elseif ModuloInteger(N[i],3)==2 then
call BJDebugMsg(I2S(N[i])+" Action 2: "+GetPlayerName(Player(i-1)))
elseif ModuloInteger(N[i],3)==0 then
call BJDebugMsg(I2S(N[i])+" Action 3: "+GetPlayerName(Player(i-1)))
//set N[i]=0
endif
endfunction

function GOO2 takes nothing returns nothing
local integer i=GetPlayerId(GetTriggerPlayer())+1
if tgo2_init[i]==0 then
set tgo2_init[i]=1
set tgo2[i]=CreateTrigger()
call SaveInteger(ht,GetHandleId(tgo2[i]),0,i)
call TriggerRegisterTimerEvent(tgo2[i], 1,true)
call TriggerAddAction(tgo2[i], function GOO2_Actions)
call DisableTrigger(tgo2[i])
endif
if GO[i]==0 then
set GO[i]=1
call EnableTrigger(tgo2[i])
else
set GO[i]=0
set N[i]=0
call DisableTrigger(tgo2[i])
call BJDebugMsg("STOP: "+GetPlayerName(Player(i-1)))
endif
endfunction

function Start takes nothing returns nothing
local string s=StringCase(GetEventPlayerChatString(),false)
elseif s=="-g2" then
call GOO2()
endif
endfunction

function Start_init takes nothing returns nothing
local trigger t=CreateTrigger()
local integer i=1
loop
exitwhen i>PLAYERS
call TriggerRegisterPlayerChatEvent(t,Player(i-1),"-",false)
set i=i+1
endloop
call TriggerAddAction(t,function Start)
endfunction

call Start_init()
1
13
1 год назад
Отредактирован Borodach
1
Я там описал смысл передачи, думал условия уже построиш для своей задачи.
Три варианта
Через цикл всем по таймеру
globals
    constant integer MAX_PLAYER = 12
    timer array TimerStartAction [MAX_PLAYER]
    integer array AnyAction[MAX_PLAYER]
endglobals

function StartAction takes nothing returns nothing
    local integer l = 0
    loop
        exitwhen l >= MAX_PLAYER
            if AnyAction[l] > 0 and AnyAction[l] < 4 then
                if AnyAction[l] == 1 then
                    call DisplayTimedTextToPlayer(Player(l),0,0,20,"Start any action 1. Start this action by player #"+I2S(l+1))
                elseif AnyAction[l] == 2 then
                    call DisplayTimedTextToPlayer(Player(l),0,0,20,"Start any action 2. Start this action by player #"+I2S(l+1))
                elseif AnyAction[l] == 3 then
                    call DisplayTimedTextToPlayer(Player(l),0,0,20,"Start any action 3. Start this action by player #"+I2S(l+1))
                endif
                set AnyAction[l] = AnyAction[l] + 1
            else
                set AnyAction[l] = 0
                call PauseTimer(TimerStartAction[l])
            endif
        set l = l + 1
    endloop
endfunction

function EnterChatMessage takes nothing returns nothing
    local integer pId = GetPlayerId(GetTriggerPlayer())
    call TimerStart(TimerStartAction[pId], 0.3, true, function StartAction)
    set AnyAction[pId] = 1
endfunction

//===========================================================================
function InitTrig_Loop takes nothing returns nothing
    local integer i = 0
    set gg_trg_Loop = CreateTrigger()
    
    loop
        exitwhen i >= MAX_PLAYER
        call TriggerRegisterPlayerChatEvent( gg_trg_Loop, Player(i), "go", true )
        set TimerStartAction[i] = CreateTimer()
        set i = i + 1
    endloop
    call TriggerAddAction(gg_trg_Loop, function EnterChatMessage )
endfunction
Через цикл один таймер
globals
    constant integer MAX_PLAYER1 = 12
    timer TimerStartAction1 = CreateTimer()
    real array PlayerTimeExpiered[MAX_PLAYER1]
endglobals

function StartAction1 takes nothing returns nothing
    local integer l = 0
    loop
        exitwhen l >= MAX_PLAYER1
            if PlayerTimeExpiered[l] >= 0 and PlayerTimeExpiered[l] < 4 then
                if PlayerTimeExpiered[l] == 1 then
                    call DisplayTimedTextToPlayer(Player(l),0,0,20,"Start any action 1. Start this action by player #"+I2S(l+1))
                elseif PlayerTimeExpiered[l] == 2 then
                    call DisplayTimedTextToPlayer(Player(l),0,0,20,"Start any action 2. Start this action by player #"+I2S(l+1))
                elseif PlayerTimeExpiered[l] == 3 then
                    call DisplayTimedTextToPlayer(Player(l),0,0,20,"Start any action 3. Start this action by player #"+I2S(l+1))
                endif
                set PlayerTimeExpiered[l] = PlayerTimeExpiered[l] + 1 //1 = one tick of timer = 0.3 sec
            endif
        set l = l + 1
    endloop
endfunction

function EnterChatMessage1 takes nothing returns nothing
    set PlayerTimeExpiered[GetPlayerId(GetTriggerPlayer())] = 0
endfunction

//===========================================================================
function InitTrig_StaticTimer takes nothing returns nothing
    local integer i = 0
    set gg_trg_StaticTimer = CreateTrigger()
    loop
        exitwhen i >= MAX_PLAYER1
        call TriggerRegisterPlayerChatEvent( gg_trg_StaticTimer, Player(i), "go", true )
        set PlayerTimeExpiered[i] = -1
        set i = i + 1
    endloop
    call TriggerAddAction(gg_trg_StaticTimer, function EnterChatMessage1 )
    
    call TimerStart( TimerStartAction1, 0.3, true, function StartAction1)
endfunction
Через хеш
globals
    constant integer MAX_PLAYER2 = 12
    timer array TimerStartAction2[MAX_PLAYER2]
    integer array ActionID[MAX_PLAYER2]
    hashtable htb = InitHashtable()
endglobals

function StartAction2 takes nothing returns nothing
    local integer l = 0
    local integer pId = LoadInteger(htb, GetHandleId(GetExpiredTimer()), StringHash("StartAction2"))

        if ActionID[pId] == 1 then
            call DisplayTimedTextToPlayer(Player(l),0,0,20,"Start any action 1. Start this action by player #"+I2S(l+1))
        elseif ActionID[pId] == 2 then
            call DisplayTimedTextToPlayer(Player(l),0,0,20,"Start any action 2. Start this action by player #"+I2S(l+1))
        elseif ActionID[pId] == 3 then
            call DisplayTimedTextToPlayer(Player(l),0,0,20,"Start any action 3. Start this action by player #"+I2S(l+1))
            call PauseTimer(GetExpiredTimer())
        endif
        set ActionID[pId] = ActionID[pId] + 1
        
endfunction

function EnterChatMessage2 takes nothing returns nothing
    local integer pId = GetPlayerId(GetTriggerPlayer())
    set ActionID[pId] = 1
    call SaveInteger(htb, GetHandleId(TimerStartAction2[pId]), StringHash("StartAction2"), pId)
    call TimerStart(TimerStartAction2[pId], 0.3, true, function StartAction2)
endfunction

//===========================================================================
function InitTrig_SaveHandle takes nothing returns nothing
    local integer i = 0
    set gg_trg_SaveHandle = CreateTrigger()
    loop
        exitwhen i >= MAX_PLAYER2
        call TriggerRegisterPlayerChatEvent( gg_trg_SaveHandle, Player(i), "go", true )
        set TimerStartAction2[i] = CreateTimer()
        set i = i + 1
    endloop
    call TriggerAddAction(gg_trg_SaveHandle, function EnterChatMessage2 )
endfunction
0
14
1 год назад
0
Три варианта


1й код - Через цикл всем по таймеру
кривокодие:
:3: syntax error
:3: Undefined type MAX_PLAYER
:4: syntax error
:4: Undefined type MAX_PLAYER
:37: Undeclared variable gg_trg_Loop
после починки кривокода видно, что каждый тикающий ускоряет тик всех остальных
это то, с чем я столкнулся в начале этого сообщения
для проверки этого феномена достаточно выставить таймер 5 секунд
и в 3 окнах одновременно отправить go
через 5 секунд у каждого будет по 3 тика, чего не может быть т.к. для трех тиков нужно 15 секунд


2й код - Через цикл один таймер
кривокодие:
:4: syntax error
:4: Undefined type MAX_PLAYER1
:32: Undeclared variable gg_trg_StaticTimer
после починки кривокода работает как и заявлено


3й код - Через хеш
кривокодие:
:3: syntax error
:3: Undefined type MAX_PLAYER2
:4: syntax error
:4: Undefined type MAX_PLAYER2
:34: Undeclared variable gg_trg_SaveHandle
+
надо заменить
I2S(l+1)
на
I2S(pId+1)
после починки кривокода работает как и заявлено
Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.