Помогите с оптимизацией

(admiral)

Участник
Сообщения
69
Реакции
8
Есть массив, где для каждого игрока есть булево значение.Нужно создавать повторяющийся таймер с интервалом в 0.1 секунды, вызывающий временные энтити на месте игроков со значением true. Какой способ лучше?
1)
C-подобный:
new Handle:NemesisAura;
new bool:g_IsNemesis[MAXPLAYERS + 1];
public ZR_OnClientInfected(client, attacker, bool:motherInfect, bool:respawnOverride, bool:respawn)
{
	if (!g_IsNemesis[client])
		return;
	if (NemesisAura == INVALID_HANDLE)
		NemesisAura = CreateTimer(0.1, TimerAura, _, TIMER_REPEAT | TIMER_FLAG_NO_MAPCHANGE);
}
public Action:TimerAura(Handle:timer)
{
	for (new client = 1; client < MaxClients; client++)
	{
		if (g_IsNemesis[client] && IsPlayerAlive(client))
		{
			static Float:origin[3];
			GetEntPropVector(client, Prop_Data, "m_vecOrigin", origin);
			TE_Start("Dynamic Light");
			TE_WriteVector("m_vecOrigin", origin);
			TE_WriteNum("r", цвет);
			TE_WriteNum("g", цвет);
			TE_WriteNum("b", цвет);
			TE_WriteNum("exponent", 50);
			TE_WriteFloat("m_fRadius", 50.0);
			TE_WriteFloat("m_fTime", 2.0);
			TE_WriteFloat("m_fDecay", 0.0);
			TE_SendToAll();
		}
	}
}
public OnClientDisconnect(client) // такая же проверка при спауне игрока и при превращении его в человека
{
	if (g_IsNemesis[client])
	{
		g_IsNemesis[client] = false;
		if (NemesisAura != INVALID_HANDLE)
		{
			for (new i = 1; i < MaxClients; i++)
			{
				new x;
				if (g_IsNemesis[i])
					x++;
				if (!x)
				{
					KillTimer(NemesisAura);
					NemesisAura = INVALID_HANDLE;
				}
			}
		}
	}
}
2)
C-подобный:
new Handle:NemesisAura[MAXPLAYERS + 1];
new bool:g_IsNemesis[MAXPLAYERS + 1];
public ZR_OnClientInfected(client, attacker, bool:motherInfect, bool:respawnOverride, bool:respawn)
{
	if (!g_IsNemesis[client])
		return;
	if (NemesisAura[client] == INVALID_HANDLE)
		NemesisAura[client] = CreateTimer(0.1, TimerAura, client, TIMER_REPEAT | TIMER_FLAG_NO_MAPCHANGE);
}
public Action:TimerAura(Handle:timer, any:data)
{
	static Float:origin[3];
	GetEntPropVector(data, Prop_Data, "m_vecOrigin", origin);
	TE_Start("Dynamic Light");
	TE_WriteVector("m_vecOrigin", origin);
	TE_WriteNum("r", цвет);
	TE_WriteNum("g", цвет);
	TE_WriteNum("b", цвет);
	TE_WriteNum("exponent", 50);
	TE_WriteFloat("m_fRadius", 50.0);
	TE_WriteFloat("m_fTime", 2.0);
	TE_WriteFloat("m_fDecay", 0.0);
	TE_SendToAll();
}
public OnClientDisconnect(client) // такая же проверка при спауне игрока и при превращении его в человека, при убийстве таймер игрока удаляется
{
	if (g_IsNemesis[client])
	{
		g_IsNemesis[client] = false;
		if (NemesisAura[client] != INVALID_HANDLE)
		{
			KillTimer(NemesisAura[client]);
			NemesisAura[client] = INVALID_HANDLE;
		}
	}
}
3)У меня еще была идея создать динамический массив, и при инфецировании игрока, если g_IsNemesis[client] = true, заносить его индекс в этот массив, а при таймере (он был бы один) получать клиентов из массива и создавать на их месте временные энтити. А при убийстве или спауне, если g_IsNemesis[client] = true, находить индекс игрока в массиве с помощью FindValueInArray и удалять его, и проверять, если размер массива равен 0, то удалить таймер.
Если вы знаете способ лучше, то, пожалуйста, опишите его.
 

Reiko1231

AlexTheRegent
Сообщения
508
Реакции
1,336
В первом способе недочет в цикле фор:
C-подобный:
for (new client = 1; client <= MaxClients; client++)
Пропущено или равно, иначе для последнего клиента данный цикл не будет выполняться.

По поводу задания - есть вариант с прикреплением свечения к игроку, там не нужны будут никакие таймеры, и не будет бликов\мерцаний. Вот пример с аптечкой - создается аптечка, потом к ней прикрепляется свечение, которое везде следует за ней:
C-подобный:
	new iEntity = CreateEntityByName("prop_physics_override");
	DispatchKeyValue(iEntity, "model", "models/items/healthkit.mdl");
	DispatchKeyValueVector(iEntity, "origin", fOrigin);
	DispatchKeyValue(iEntity, "solid", "6");
	DispatchSpawn(iEntity);
		
	new iEnt = CreateEntityByName("light_dynamic");  
	DispatchKeyValue(iEnt, "_light", "255 0 0");  
	DispatchKeyValue(iEnt, "brightness", "10");  
	DispatchKeyValueFloat(iEnt, "spotlight_radius", 360.0);  
	DispatchKeyValueFloat(iEnt, "distance", 50.0);  
	DispatchKeyValue(iEnt, "style", "0");
	DispatchSpawn(iEnt);
	TeleportEntity(iEnt, fOrigin, NULL_VECTOR, NULL_VECTOR);
		
	new String:szTarget[32];
	Format(szTarget, sizeof(szTarget), "lighthealthkit_%d", iEntity);
	DispatchKeyValue(iEntity, "targetname", szTarget);
	SetVariantString(szTarget);
	AcceptEntityInput(iEnt, "SetParent");
	AcceptEntityInput(iEnt, "TurnOn");
 
Сверху Снизу