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

Primo

типа серьёзный тип
Сообщения
1,532
Реакции
759
Решил начать знакомство с таймерами, поэтому для начала решил сделать регенерацию 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=1; client <= GetMaxClients(); client++)
	{
		if(Timer[client] == INVALID_HANDLE)
		{
			Timer[client] = CreateTimer(2.0, PlayerHeal, client, TIMER_REPEAT);
		}
	}
}
public VErtoe_Round_End(Handle:event, const String:name[], bool:dontBroadcast)
{
	for(new i=1; i <= GetMaxClients(); i++)
	{
		KillTimer(Timer[i]);
	}
}

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

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

Primo

типа серьёзный тип
Сообщения
1,532
Реакции
759
Продолжаем дискуссию. Одной проблемой насчёт остановки цикла меньше.
 

AlmazON

Не путать с самим yand3xmail
Сообщения
5,099
Реакции
2,755
Primo, примерно так:
PHP:
public VErtoe_Round_End(Handle:event, const String:name[], bool:dontBroadcast) 
{ 
   Timer[client] = INVALID_HANDLE;
} 

public Action:PlayerHeal(Handle:timer, any:client) 
{ 
    if(Timer[client] != INVALID_HANDLE && IsClientInGame(client) && Player[Regen][client] >= 1 && GetClientHealth(client) <= 100)
	{
		SetEntityHealth(client, GetClientHealth(client) + Player[Regen][client]);
		return Plugin_Continue;
    }
	return Plugin_Stop;
}
Точно сказать не могу, ибо у тебя не весь код и о назначении, например, Player[Regen][client] лишь догадываюсь.
После смерти игрока таймер тоже остановить, добавь проверку IsPlayerAlive(client).
//new client = GetClientOfUserId(GetEventInt(event, "userid"));
Можешь удалить, клиент в данном событии так не получить.
 

Primo

типа серьёзный тип
Сообщения
1,532
Реакции
759
Primo, примерно так:
PHP:
public VErtoe_Round_End(Handle:event, const String:name[], bool:dontBroadcast) 
{ 
   Timer[client] = INVALID_HANDLE;
} 

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

Можешь удалить, клиент в данном событии так не получить.

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

AlmazON

Не путать с самим yand3xmail
Сообщения
5,099
Реакции
2,755
Primo, цикл не забудь, а то я удалил вместе с "KillTimer". :-D
Я бы на твоём месте поставил таймер на событие спавна игрока, а то на DM, например, будет сразу баг.
 

R1KO

fuck society
Сообщения
9,457
Реакции
7,786
  • Команда форума
  • #7
На днях тоже задался вопросом что оптимальнее:
Односекундный таймер для каждого игрока или один односекундный таймер в котором будет цикл по всем игрокам?
 

AlmazON

Не путать с самим yand3xmail
Сообщения
5,099
Реакции
2,755
один односекундный таймер в котором будет цикл по всем игрокам
Я бы сделал так, как раз хотел сейчас пример написать. В данном случае уж точно, ибо точность здесь не нужна (подумаешь, в первый раз даст хп не ровно через секунду, а полсекунды). Также это избавляет от ненужных событий. Зависит от применения.
 

Primo

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

И так, никаких изменений :D


Добавлено через 1 минуту
Я бы сделал так, как раз хотел сейчас пример написать. В данном случае уж точно, ибо точность здесь не нужна (подумаешь, в первый раз даст хп не ровно через секунду, а полсекунды). Также это избавляет от ненужных событий. Зависит от применения.

Оффтоп
 
Последнее редактирование:

R1KO

fuck society
Сообщения
9,457
Реакции
7,786
  • Команда форума
  • #10
Я бы сделал так, как раз хотел сейчас пример написать. В данном случае уж точно, ибо точность здесь не нужна (подумаешь, в первый раз даст хп не ровно через секунду, а полсекунды). Также это избавляет от ненужных событий. Зависит от применения.

Да вот про оптимизацию регена думаю.

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

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

AlmazON

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

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

public Action:Regen(Handle:timer)
{
	for (new i = 1; i <= MaxClients; i++)
	{
		if (IsClientInGame(i) && IsPlayerAlive(i) && GetClientHealth(i) < 100) SetEntityHealth(i, GetClientHealth(i) + 1);
	}
}
Где +1 - выводи в квар.
 

Primo

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

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

public Action:Regen(Handle:timer)
{
	for (new i = 1; i <= MaxClients; i++)
	{
		if (IsClientInGame(i) && IsPlayerAlive(i) && GetClientHealth(i) < 100) SetEntityHealth(i, GetClientHealth(i) + 1);
	}
}
Где +1 - выводи в квар.

Ты лучший :secret:
 

AlmazON

Не путать с самим yand3xmail
Сообщения
5,099
Реакции
2,755
Primo,
Оффтоп
это я тебе дал пример по аналогии твоего (лучший относительно твоего). А на самом деле, я бы так не сделал, а остановил таймер при отсутствии людей на сервере.
Оффтоп
 

AlmazON

Не путать с самим yand3xmail
Сообщения
5,099
Реакции
2,755
PHP:
for (new i = 1; i <= GetClientCount(true); i++)
{
}
и
PHP:
for (new i = 1; i <= GetClientCount(false); i++)
{
}
ещё можно использовать, в зависимости от потребностей.
 

R1KO

fuck society
Сообщения
9,457
Реакции
7,786
  • Команда форума
  • #15
AlmazON, не проканает.
Индекс игрока может быть больше чем игроков на сервере.
 

AlmazON

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

AlmazON

Не путать с самим yand3xmail
Сообщения
5,099
Реакции
2,755
спорю я тут потому что заинтересован в этом и в моем случае это критично
Ясное дело. :) Это не универсальный цикл, а просто его "младший брат", скажем так.
Оффтоп
Я просто начинаю иногда применять его, вот и тебе посоветовал, где есть для него верное место.
 

AlmazON

Не путать с самим yand3xmail
Сообщения
5,099
Реакции
2,755
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 будет быстрее.
 
Последнее редактирование:
Сверху Снизу