Ошибка: Invalid timer handle 68870091 (error 3)

m-v-

Участник
Сообщения
7
Реакции
0
Плагин делался для Dev Zones от Franc1sco.

Суть плагина: При заходе в зону - стартует таймер для команды. Каждую секунду команде выдаётся ХП. (Даже если один игрок из команды в зоне, то выдаётся всем.). Так вот проблема в том, что если два игрока из разных команд находятся в зоне и один игрок из команды выходит - один таймер останавливается. А второй таймер для другой команды не останавливается, когда игрок выходит из зоны.

Кто-бы мог помочь решить проблему с ошибкой KillTimer - Буду очень благодарен.

L 06/24/2020 - 14:31:23: [SM] Exception reported: Invalid timer handle 68870091 (error 3)
L 06/24/2020 - 14:31:23: [SM] Blaming: test.smx
L 06/24/2020 - 14:31:23: [SM] Call stack trace:
L 06/24/2020 - 14:31:23: [SM] [0] KillTimer
L 06/24/2020 - 14:31:23: [SM] [1] Line 81, D:\Plugins\compiler1.10\test.sp::Zone_OnClientLeave
L 06/24/2020 - 14:31:23: [SM] [3] Call_Finish
L 06/24/2020 - 14:31:23: [SM] [4] Line 264, E:\Github\DevZones\DevZones (CORE PLUGIN)\scripting\devzones.sp::EntOut_OnEndTouch

C-подобный:
public Zone_OnClientEntry(client, const char[] zone)
{
    decl String:playerName[64];
    GetClientName(client, playerName, sizeof(playerName));
    char classname[64];
    if(client < 1 || client > MaxClients || !IsClientInGame(client)) 
    {
        GetEdictClassname(client, classname, 64);
    }
    for(int i = 1; i <= MaxClients; i++)
    {
        if(IsClientInGame(i) && GetClientTeam(i) == GetClientTeam(client) && i != client)
        {
            if(Zone_IsClientInZone(i, "test", false))
                {
                    LogError("Nothing");
                }
else
{
                Timer_Join = CreateTimer(1.0, Timer_StartPoint, GetClientUserId(client), TIMER_REPEAT);
                }
}
}

}

public Zone_OnClientLeave(client, const char[] zone)
{
    decl String:playerName[64];
    GetClientName(client, playerName, sizeof(playerName));
    char classname[64];
    if(client < 1 || client > MaxClients || !IsClientInGame(client)) 
    {
        GetEdictClassname(client, classname, 64);
    }
    numPrinted = 0;
    for(int i = 1; i <= MaxClients; i++)
    {
        if(IsClientInGame(i) && GetClientTeam(i) == GetClientTeam(client) && i != client)
        {
            if(Zone_IsClientInZone(i, "test", false))
                {
                LogError("Nothing");
                }
else
{
                KillTimer(Timer_Join);
                }
}
}
}
 
Решение
GetClientName(client, playerName, sizeof(playerName));
Нафига получать то, что потом никак и нигде не используется?
GetEdictClassname(client, classname, 64);
та же фигня, что и выше
Какой смысл получать GetClientTeam(client) в цикле, если это лучше получить ещё перед ним, т.к. за этот тик игрок команду не сменит.
если два игрока из разных команд находятся в зоне и один игрок из команды выходит - один таймер останавливается. А второй таймер для другой команды не останавливается, когда игрок выходит из зоны.
Что-то не наблюдаю в коде 2-го таймера
В общем можно сделать так (если тебе необходим по 1 таймеру на команду):
C-подобный:
Handle Timer_Join[2];

public Zone_OnClientEntry(client, const...

Kruzya

Участник
Сообщения
12,970
Реакции
10,914
  • Команда форума
  • #2
После строки
C-подобный:
KillTimer(Timer_Join);
Дописать
C-подобный:
Timer_Join = null;

Но вообще код крайне странный. Всего одна переменная на несколько таймеров. Будет хрень полная.
 

m-v-

Участник
Сообщения
7
Реакции
0
После строки
C-подобный:
KillTimer(Timer_Join);
Дописать
C-подобный:
Timer_Join = null;

Но вообще код крайне странный. Всего одна переменная на несколько таймеров. Будет хрень полная.
Спасибо.
Был бы очень благодарен если мой код преоброзится благодаря тебе 😉
 

tonline_kms65_1

Участник
Сообщения
565
Реакции
225
@m-v-,
Даже не знаю как и с чего начать.
Скажу проще - полный бред. Бредище!
Я сейчас на работе, как буду дома, обязательно напишу свои мысли по этому поводу.
Если бы сказал так - пацаны, я где-то оттопырил код, а он падла не работает, объясните как он работает, тебя бы поняли. А так, как минимум, как твой таймер вообще остановится?

Сейчас пришел домой, сижу, смотрю. Как мартышка и очки, не пойму а как он вообще работает, этот код?
Например:
- для какой цели получать имя класса игрока? (немного сократил) Но да это ладно, сделаем вид что не заметили.
C-подобный:
if(client < 1 || client > MaxClients || !IsClientInGame(client)) GetEdictClassname(client, classname, 64);
- как у тебя отключится таймер(к примеру) при смене карты? Он ведь повторяющийся
C-подобный:
Timer_Join = CreateTimer(1.0, Timer_StartPoint, GetClientUserId(client), TIMER_REPEAT);
- как уже было сказано, к чему привязан таймер? К какой команде?
C-подобный:
[B]Timer_Join[/B] = CreateTimer(1.0, Timer_StartPoint, GetClientUserId(client), TIMER_REPEAT);
Один зашел-вышел, а таймер не остановился(по какой то причине), снова зашел-вышел - опять таймер (с таким же именем!) запустился, и так до бесконечности. Как ты кучу таймеров(с одинаковыми именами) собираешься убить одной командой kill? Очень интересно. Можно долго писать еще.
-
C-подобный:
GetClientUserId(client)
вообще не понятно.
почему не перегнать еще в шапке ф-ции клиента из ID что бы не было ошибок и пользоваться уже преобразованным значением?
C-подобный:
GetClientOfUserId(GetClientUserId(client));


Почему нельзя все это сделать в одном, постоянно работающем таймере, с заданным радиусом действия (либо, на крайняка, халвовским триггером).
Честно, не укладывается в голове. Я поэтому и не выдержал - написал.
 
Последнее редактирование:

Kruzya

Участник
Сообщения
12,970
Реакции
10,914
  • Команда форума
  • #5
Чтобы преобразить этот код, нужен полный исходник. Этой выдержки для приведения его в порядок - недостаточно.
 
  • Мне нравится
Реакции: m-v-

tonline_kms65_1

Участник
Сообщения
565
Реакции
225
Был бы очень благодарен если мой код преоброзится благодаря тебе
Не преобразится, точно. Не надейся. Это просто вопрос времени когда опять лаганет.
Интересно, конечно, было бы посмотреть исходный код, чей он там, кто так намутил.

оригинал если я правильно понял. Вкратце глянул - как я и говорил, один таймер, халвовские триггеры и т.д. Всё в норме.
Здесь же мы видим очевидную переделку, и к сожалению кривую.
 
Последнее редактирование:
  • Мне нравится
Реакции: m-v-

Grey83

не пишу плагины с весны 2022
Сообщения
8,521
Реакции
4,982
GetClientName(client, playerName, sizeof(playerName));
Нафига получать то, что потом никак и нигде не используется?
GetEdictClassname(client, classname, 64);
та же фигня, что и выше
Какой смысл получать GetClientTeam(client) в цикле, если это лучше получить ещё перед ним, т.к. за этот тик игрок команду не сменит.
если два игрока из разных команд находятся в зоне и один игрок из команды выходит - один таймер останавливается. А второй таймер для другой команды не останавливается, когда игрок выходит из зоны.
Что-то не наблюдаю в коде 2-го таймера
В общем можно сделать так (если тебе необходим по 1 таймеру на команду):
C-подобный:
Handle Timer_Join[2];

public Zone_OnClientEntry(client, const char[] zone)
{
    for(int i = 1, t = GetClientTeam(client), id = t == 2 ? 0 : 1; i <= MaxClients; i++)
        if(i != client && IsClientInGame(i) && GetClientTeam(i) == t)
        {
            if(Zone_IsClientInZone(i, "test", false))
                LogError("Nothing");
            else if(!Timer_Join[id])
            {
                Timer_Join[id] = CreateTimer(1.0, Timer_StartPoint, GetClientUserId(client), TIMER_REPEAT);
                break;
            }
        }
}

public Zone_OnClientLeave(client, const char[] zone)
{
    numPrinted = 0; // а это нафига?
    for(int i = 1, t = GetClientTeam(client), id = t == 2 ? 0 : 1; i <= MaxClients; i++)
        if(i != client && IsClientInGame(i) && GetClientTeam(i) == t)
        {
            if(Zone_IsClientInZone(i, "test", false))
                LogError("Nothing");
            else if(Timer_Join[id])
            {
                delete Timer_Join[id];
                break;
            }
        }
}
 
Решение
Сверху Снизу