Timer для каждого клиента, или другой способ

Тема в разделе "Программирование / Скриптинг", создана пользователем Primo, 27 июл 2014.

  1. Primo

    Primo Где мои манеры

    Сообщения:
    1.190
    Симпатии:
    306
    Решил начать знакомство с таймерами, поэтому для начала решил сделать регенерацию hp игрокам.

    Имеется такой код:

    PHP:
    new Handle:Timer[MAXPLAYERS];
    public 
    VErtoe_Round_Start(Handle:event, const String:name[], bool:dontBroadcast
    {
        
    //new client = GetClientOfUserId(GetEventInt(event, "userid"));
        
    PrintToChatAll("Посетите нашу страницу \x01\x07vk.com/vertoe");
        
    PrintToChatAll("Вступайте в нашу группу Steam \x01\x07VErtoe Gaming");
        for(new 
    client=1client <= GetMaxClients(); client++)
        {
            if(
    Timer[client] == INVALID_HANDLE)
            {
                
    Timer[client] = CreateTimer(2.0PlayerHealclientTIMER_REPEAT);
            }
        }
    }
    public 
    VErtoe_Round_End(Handle:event, const String:name[], bool:dontBroadcast)
    {
        for(new 
    i=1<= GetMaxClients(); i++)
        {
            
    KillTimer(Timer[i]);
        }
    }

    public 
    Action:PlayerHeal(Handle:timerany:client)
    {
        if(
    IsClientInGame(client))
        {
            if(
    Player[Regen][client] >= 1)
            {
                if(
    GetClientHealth(client) <= 100)
                {
                    
    SetEntityHealth(clientGetClientHealth(client) + Player[Regen][client]);
                }
            }
            else
            {
                
    KillTimer(timer);
            }
        }
    }

     
    Проблема в том, что таймер работает только для одного игрока. Есть альтернативные варианты регенерации? Или что я сделал не так?
     
  2. AlmazON

    AlmazON деревянный © yand3xmail

    Сообщения:
    4.511
    Симпатии:
    1.963
    Это - бред. Повторяющийся таймер, по сути, так нельзя убить! Используй команду return Plugin_Stop;.
     
    Primo нравится это.
  3. Primo

    Primo Где мои манеры

    Сообщения:
    1.190
    Симпатии:
    306
    Продолжаем дискуссию. Одной проблемой насчёт остановки цикла меньше.
     
  4. AlmazON

    AlmazON деревянный © yand3xmail

    Сообщения:
    4.511
    Симпатии:
    1.963
    Primo, примерно так:
    PHP:
    public VErtoe_Round_End(Handle:event, const String:name[], bool:dontBroadcast

       
    Timer[client] = INVALID_HANDLE;


    public 
    Action:PlayerHeal(Handle:timerany:client

        if(
    Timer[client] != INVALID_HANDLE && IsClientInGame(client) && Player[Regen][client] >= && GetClientHealth(client) <= 100)
        {
            
    SetEntityHealth(clientGetClientHealth(client) + Player[Regen][client]);
            return 
    Plugin_Continue;
        }
        return 
    Plugin_Stop;
    Точно сказать не могу, ибо у тебя не весь код и о назначении, например, Player[Regen][client] лишь догадываюсь.
    После смерти игрока таймер тоже остановить, добавь проверку IsPlayerAlive(client).
    Можешь удалить, клиент в данном событии так не получить.
     
  5. Primo

    Primo Где мои манеры

    Сообщения:
    1.190
    Симпатии:
    306
    Я его закомментировал, и я знаю, что не получить в этом событии, я сохранял себе на всякий случай. Спасибо, протестирую, отпишусь)
     
  6. AlmazON

    AlmazON деревянный © yand3xmail

    Сообщения:
    4.511
    Симпатии:
    1.963
    Primo, цикл не забудь, а то я удалил вместе с "KillTimer". :-D
    Я бы на твоём месте поставил таймер на событие спавна игрока, а то на DM, например, будет сразу баг.
     
  7. R1KO

    R1KO Супер-модератор

    Сообщения:
    5.972
    Симпатии:
    2.978
    На днях тоже задался вопросом что оптимальнее:
    Односекундный таймер для каждого игрока или один односекундный таймер в котором будет цикл по всем игрокам?
     
  8. AlmazON

    AlmazON деревянный © yand3xmail

    Сообщения:
    4.511
    Симпатии:
    1.963
    Я бы сделал так, как раз хотел сейчас пример написать. В данном случае уж точно, ибо точность здесь не нужна (подумаешь, в первый раз даст хп не ровно через секунду, а полсекунды). Также это избавляет от ненужных событий. Зависит от применения.
     
  9. Primo

    Primo Где мои манеры

    Сообщения:
    1.190
    Симпатии:
    306
    И так, никаких изменений :D


    Добавлено через 1 минуту
    Оффтоп
     
    Последнее редактирование: 27 июл 2014
  10. R1KO

    R1KO Супер-модератор

    Сообщения:
    5.972
    Симпатии:
    2.978
    Да вот про оптимизацию регена думаю.

    Если из 20 игроков 2 випа это 2 таймера.
    Иначе 1 таймер но цикл по всем.

    Сложный выбор.
     
  11. AlmazON

    AlmazON деревянный © yand3xmail

    Сообщения:
    4.511
    Симпатии:
    1.963
    Как думаешь, что больше нагружает: тикающий повторяющийся таймер для каждого, который каждый раз выполняет действие, извлекая каждый раз клиента для каждого срабатывания или вместо извлечения клиента - цикл? Да, цикл куда больше нагружает, чем client из события. Но, и там, и там, его надо получать... Если бы нет, то пару таймеров было выгоднее. А так... Много ВИПов - хуже по таймеру, а цикл - та же нагрузка.

    Primo, зацени простоту с меньшей нагрузкой:
    PHP:
    public OnConfigsExecuted() CreateTimer(2.0Regen_TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE);

    public 
    Action:Regen(Handle:timer)
    {
        for (new 
    1<= MaxClientsi++)
        {
            if (
    IsClientInGame(i) && IsPlayerAlive(i) && GetClientHealth(i) < 100SetEntityHealth(iGetClientHealth(i) + 1);
        }
    }
    Где +1 - выводи в квар.
     
    Серый™ и Primo нравится это.
  12. Primo

    Primo Где мои манеры

    Сообщения:
    1.190
    Симпатии:
    306
    Ты лучший :secret:
     
  13. AlmazON

    AlmazON деревянный © yand3xmail

    Сообщения:
    4.511
    Симпатии:
    1.963
    Primo,
    Оффтоп
    это я тебе дал пример по аналогии твоего (лучший относительно твоего). А на самом деле, я бы так не сделал, а остановил таймер при отсутствии людей на сервере.
    Оффтоп
     
  14. AlmazON

    AlmazON деревянный © yand3xmail

    Сообщения:
    4.511
    Симпатии:
    1.963
    PHP:
    for (new 1<= GetClientCount(true); i++)
    {
    }
    и
    PHP:
    for (new 1<= GetClientCount(false); i++)
    {
    }
    ещё можно использовать, в зависимости от потребностей.
     
  15. R1KO

    R1KO Супер-модератор

    Сообщения:
    5.972
    Симпатии:
    2.978
    AlmazON, не проканает.
    Индекс игрока может быть больше чем игроков на сервере.
     
  16. AlmazON

    AlmazON деревянный © yand3xmail

    Сообщения:
    4.511
    Симпатии:
    1.963
    Индекс то да, но тупо разослать сообщение для одной команды, используя такой цикл - вполне. Также можно получить имя клиентов.
    Когда действия адресованы не чётко по индексу и потери не столь важны - запросто.
    Например:
    Голосование для одной команды и после каждого голоса нужно писать только им: "Непроголосовавших: X"
    PHP:
    for (new 1<= GetClientCount(true); i++)
    {
        if (
    IsClientInGame(i) && !IsFakeClient(i) && GetClientTeam(i) > 2)
        {
            
    PrintToChat(i"Непроголосовавших: %i."vote);
        }
    }
    Подумаешь, раз пусть даже не покажет кому-то - спам итак их достанет, а оптимизация налицо.
     
  17. R1KO

    R1KO Супер-модератор

    Сообщения:
    5.972
    Симпатии:
    2.978
    Это да, но спорю я тут потому что заинтересован в этом и в моем случае это критично.
     
  18. AlmazON

    AlmazON деревянный © yand3xmail

    Сообщения:
    4.511
    Симпатии:
    1.963
    Ясное дело. :) Это не универсальный цикл, а просто его "младший брат", скажем так.
    Оффтоп
    Я просто начинаю иногда применять его, вот и тебе посоветовал, где есть для него верное место.
     
  19. Root

    Root AWOL.

    Сообщения:
    77
    Симпатии:
    184
  20. AlmazON

    AlmazON деревянный © yand3xmail

    Сообщения:
    4.511
    Симпатии:
    1.963
    Root, не вижу там фактов... просто очередной код другого автора.
    UPD: Нубоватый код.
    PHP:
    if (IsClientInGame(i) && IsPlayerAlive(i))
            {
                
    // There are any bleeding players ?
                
    if (bool:BleedInfo[i][enabled] == true)
                {
    сделано раздельно, а ведь можно было вместе, причём, bool:BleedInfo[enabled] == true вообще первее, небось, ставить надо.
    PHP:
    switch (GetConVarBool(Bleed_Mode))
                    {
                        case 
    false:
                        {
    Тоже глупо, if и else будет быстрее.
     
    Последнее редактирование: 30 июл 2014