Ошибка работы плагина (CS:GO)

Z3R0M1ND

Участник
Сообщения
24
Реакции
1
Пытаюсь написать свой простенький плагин по защите игроков которые находятся АФК.

Столкнулся с проблемой удаления таймеров:
PHP:
L 11/25/2014 - 12:12:33: [SM]   [0]  Line 369, CSGO SERVER\scripting\AFKP.sp::Event_RoundEnd()
L 11/25/2014 - 12:12:40: [SM] Native "KillTimer" reported: Invalid timer handle 3da030e (error 1)
L 11/25/2014 - 12:12:40: [SM] Displaying call stack trace for plugin "AFKP.smx":
L 11/25/2014 - 12:12:40: [SM]   [0]  Line 339, CSGO SERVER\scripting\AFKP.sp::Event_RoundStart()

Сам исходник:
PHP:
#include <sourcemod>
#include <sdktools>
#include <sdkhooks>
#include <smlib>
#include <cstrike>
#include <csgo_colors>
#include <loghelper>

#pragma semicolon 1

#define PLUGIN_VERSION "1.1.0.0"
#define IsPlayer(%1) ( 1 <= %1 <= MaxPlayers )

enum FX
{
	FxNone = 0,
	FxPulseFast,
	FxPulseSlowWide,
	FxPulseFastWide,
	FxFadeSlow,
	FxFadeFast,
	FxSolidSlow,
	FxSolidFast,
	FxStrobeSlow,
	FxStrobeFast,
	FxStrobeFaster,
	FxFlickerSlow,
	FxFlickerFast,
	FxNoDissipation,
	FxDistort,               // Distort/scale/translate flicker
	FxHologram,              // kRenderFxDistort + distance fade
	FxExplode,               // Scale up really big!
	FxGlowShell,             // Glowing Shell
	FxClampMinScale,         // Keep this sprite from getting very small (SPRITES only!)
	FxEnvRain,               // for environmental rendermode, make rain
	FxEnvSnow,               //  "        "            "    , make snow
	FxSpotlight,     
	FxRagdoll,
	FxPulseFastWider,
};

enum Render
{
	Normal = 0, 		// src
	TransColor, 		// c*a+dest*(1-a)
	TransTexture,		// src*a+dest*(1-a)
	Glow,				// src*a+dest -- No Z buffer checks -- Fixed size in screen space
	TransAlpha,			// src*srca+dest*(1-srca)
	TransAdd,			// src*a+dest
	Environmental,		// not drawn, used for environmental effects
	TransAddFrameBlend,	// use a fractional frame value to blend between animation frames
	TransAlphaAdd,		// src + dest*(1-a)
	WorldGlow,			// Same as kRenderGlow but not fixed size in screen space
	None,				// Don't render.
};

new FX:g_Effect = FX:FxGlowShell;
new Render:g_Render = Render:Glow;

public Plugin:myinfo =
{
        name = "AFK Protect",
        author = "Z3R0M1ND",
        description = "AFK Protection",
        version = PLUGIN_VERSION,
        url = "http://www.csgoboost.ru/"
};

new Handle:g_hPlayerTimer[MAXPLAYERS + 1];
new Handle:g_hLoopTimer = INVALID_HANDLE;

new Float:g_PlayerAngles[MAXPLAYERS + 1][3];
new Float:g_PlayerPositions[MAXPLAYERS + 1][3];

new bool:g_AFKModElabled = true;
new bool:isPlayersAFK[MAXPLAYERS + 1];

new g_PlayerAFKTries[MAXPLAYERS + 1];

public OnPluginStart()
{
	CreateConVar("afk_protect_version", PLUGIN_VERSION, "AFK Protect Version", FCVAR_PLUGIN|FCVAR_NOTIFY|FCVAR_REPLICATED);
	
	// Hook Events
	HookEvent("player_spawn", Event_PlayerSpawn, EventHookMode_Pre);
	HookEvent("player_death", Event_PlayerDeath);
	
	HookEvent("round_start", Event_RoundStart);
	HookEvent("round_end", Event_RoundEnd);
}

public OnMapStart()
{
	
}

f_PlayerCheck_T(client)
{
	if (g_AFKModElabled && IsValidPlayer(client))
	{
		g_PlayerAFKTries[client] = 0;
		
		if (g_hPlayerTimer[client] != INVALID_HANDLE)
		{
			KillTimer(g_hPlayerTimer[client]);
			g_hPlayerTimer[client] = INVALID_HANDLE;
			g_hPlayerTimer[client] = CreateTimer(1.0, g_AfkTimer_CallBack, client, TIMER_REPEAT | TIMER_FLAG_NO_MAPCHANGE);
		}
	}
}

f_PlayersLoop_T()
{
	if (g_AFKModElabled)
	{
		if (g_hLoopTimer != INVALID_HANDLE)
		{
			KillTimer(g_hLoopTimer);
			g_hLoopTimer = INVALID_HANDLE;
		}
		
		g_hLoopTimer = CreateTimer(10.0, g_AfkLoopTimer_CallBack, _, TIMER_REPEAT | TIMER_FLAG_NO_MAPCHANGE);
	}
}

public Action:g_AfkTimer_CallBack(Handle:timer, any:client)
{
	if (g_AFKModElabled)
	{
		new MAX_AFK_TRIES = 8;
		
		if (IsPlayerAway(client))
		{
			if (g_PlayerAFKTries[client] >= MAX_AFK_TRIES)
			{
				CGOPrintHintText(client, "ВЫ ПЕРЕШЛИ В РЕЖИМ {{#359FD0==AFK}}.\n{{#299A0B==ЗАЩИТА АКТИВНА}}");
				
				isPlayersAFK[client] = true;
				set_rendering(client, g_Effect, g_Render);
			}
			else g_PlayerAFKTries[client]++;
		}
		else
		{
			if (isPlayersAFK[client])
				CGOPrintHintText(client, "ВЫ ВЫШЛИ ИЗ РЕЖИМА {{#359FD0==AFK}}.\n{{#CC0000==ЗАЩИТА ОТКЛЮЧЕНА}}");
			
			isPlayersAFK[client] = false;
			g_PlayerAFKTries[client] = 0;
			set_rendering(client);
		}
	}
	else
	{
		if (g_hPlayerTimer[client] != INVALID_HANDLE)
		{
			KillTimer(g_hPlayerTimer[client]);
			g_hPlayerTimer[client] = INVALID_HANDLE;
		}
		
		return Plugin_Stop;
	}
	
	return Plugin_Continue;
}

public Action:g_AfkLoopTimer_CallBack(Handle:timer)
{
	if (g_AFKModElabled)
		CGOPrintToChatAll("[ {LIME}AFK PROTECT {DEFAULT}] {GREEN}Включен");
	else
		CGOPrintToChatAll("[ {LIME}AFK PROTECT {DEFAULT}] {RED}Выключен");

	new TeamCT = 0,
		TeamCTAlive = 0,
		TeamCTAFK = 0;
		
	new TeamTR = 0,
		TeamTRAlive = 0,
		TeamTRAFK = 0;
	
	LOOP_CLIENTS(client, CLIENTFILTER_INGAME) {
	
		new team_id = GetClientTeam(client);
		if (team_id == 2)
		{
			TeamCT++;
			if (IsPlayerAlive(client)) TeamCTAlive++;
			if (isPlayersAFK[client]) TeamCTAFK++;
		}
		else if (team_id == 3)
		{
			TeamTR++;
			if (IsPlayerAlive(client)) TeamTRAlive++;
			if (isPlayersAFK[client]) TeamTRAFK++;
		}
	}
	
	if (g_AFKModElabled && TeamCTAlive == TeamCTAFK)
	{
		g_AFKModElabled = false;
		LOOP_CLIENTS(client, CLIENTFILTER_INGAME) {
			if (IsPlayerAlive(client) && GetClientTeam(client) == 2 && isPlayersAFK[client])
			{
				CGOPrintHintText(client, "РЕЖИМ {{#359FD0==AFK}} ВЫКЛЮЧЕН!\n{{#CC0000==ЗАЩИТА ОТКЛЮЧЕНА}}");
				isPlayersAFK[client] = false;
				
				set_rendering(client);
			}
		}
	}
	else if (g_AFKModElabled && TeamTRAlive == TeamTRAFK)
	{
		g_AFKModElabled = false;
		LOOP_CLIENTS(client, CLIENTFILTER_INGAME) {
			if (IsPlayerAlive(client) && GetClientTeam(client) == 3 && isPlayersAFK[client])
			{
				CGOPrintHintText(client, "РЕЖИМ {{#359FD0==AFK}} ВЫКЛЮЧЕН!\n{{#CC0000==ЗАЩИТА ОТКЛЮЧЕНА}}");
				isPlayersAFK[client] = false;
				
				set_rendering(client);
			}
		}
	}
	
	if (g_AFKModElabled)
	{
		LOOP_CLIENTS(client, CLIENTFILTER_INGAME) {
			if (g_hPlayerTimer[client] == INVALID_HANDLE) f_PlayerCheck_T(client);
		}
	}
	else
	{
		if (g_hLoopTimer == INVALID_HANDLE)
		{
			KillTimer(g_hLoopTimer);
			g_hLoopTimer = INVALID_HANDLE;
		}
		
		return Plugin_Stop;
	}
	
	return Plugin_Continue;
}

public IsPlayerAway(client)
{
	decl Float:angles[3];
	decl Float:positions[3];
	
	if (IsValidPlayer(client) && IsPlayerAlive(client))
	{
		GetClientAbsOrigin(client, positions);
		GetClientEyeAngles(client, angles);
		
		if (angles[0] == g_PlayerAngles[client][0] && angles[1] == g_PlayerAngles[client][1] && angles[2] == g_PlayerAngles[client][2])
		{
			if (positions[0] == g_PlayerPositions[client][0] && positions[1] == g_PlayerPositions[client][1] && positions[2] == g_PlayerPositions[client][2])
			{
				return true;
			}else g_PlayerPositions[client] = positions;
		}
		else g_PlayerAngles[client] = angles;
	}
	
	return false;
}

public OnClientPutInServer(client)
{
	isPlayersAFK[client] = false;
	g_PlayerAFKTries[client] = 0;
	
	SDKHook(client, SDKHook_OnTakeDamage, Hook_OnTakeDamage);
	
	if (g_hPlayerTimer[client] != INVALID_HANDLE)
	{
		KillTimer(g_hPlayerTimer[client]);
		g_hPlayerTimer[client] = INVALID_HANDLE;
	}
}

public OnClientDisconnect(client)
{
	isPlayersAFK[client] = false;
	g_PlayerAFKTries[client] = 0;
	
	if (g_hPlayerTimer[client] != INVALID_HANDLE)
	{
		KillTimer(g_hPlayerTimer[client]);
		g_hPlayerTimer[client] = INVALID_HANDLE;
	}
}

public Event_PlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast)
{
	new client = GetClientOfUserId(GetEventInt(event, "userid"));
	g_AFKModElabled = true;

	isPlayersAFK[client] = false;
	g_PlayerAFKTries[client] = 0;
	
	if (g_hPlayerTimer[client] == INVALID_HANDLE) f_PlayerCheck_T(client);
	else
	{
		KillTimer(g_hPlayerTimer[client]);
		g_hPlayerTimer[client] = INVALID_HANDLE;
		f_PlayerCheck_T(client);
	}
}

public Event_PlayerDeath(Handle:event, const String:name[], bool:dontBroadcast)
{
	new client = GetClientOfUserId(GetEventInt(event, "userid"));
	
	isPlayersAFK[client] = false;
	g_PlayerAFKTries[client] = 0;
	
	if (g_hPlayerTimer[client] != INVALID_HANDLE)
	{
		KillTimer(g_hPlayerTimer[client]);
		g_hPlayerTimer[client] = INVALID_HANDLE;
	}
}

public Event_RoundStart(Handle:event, const String:name[], bool:dontBroadcast)
{
	g_AFKModElabled = true;
	
	LOOP_CLIENTS(client, CLIENTFILTER_INGAME)
	{
		isPlayersAFK[client] = false;
		g_PlayerAFKTries[client] = 0;
	}
	
	if (g_hLoopTimer == INVALID_HANDLE) f_PlayersLoop_T();
	else
	{
		KillTimer(g_hLoopTimer);
		g_hLoopTimer = INVALID_HANDLE;
		
		f_PlayersLoop_T();
	}
}

public Event_RoundEnd(Handle:event, const String:name[], bool:dontBroadcast)
{
	g_AFKModElabled = false;

	LOOP_CLIENTS(client, CLIENTFILTER_INGAME)
	{
		if (IsPlayerAlive(client))
		{
			set_rendering(client);
			
			isPlayersAFK[client] = false;
			g_PlayerAFKTries[client] = 0;
		}
		
		if (g_hPlayerTimer[client] != INVALID_HANDLE)
		{
			KillTimer(g_hPlayerTimer[client]);
			g_hPlayerTimer[client] = INVALID_HANDLE;
		}
	}
	
	if (g_hLoopTimer != INVALID_HANDLE)
	{
		KillTimer(g_hLoopTimer);
		g_hLoopTimer = INVALID_HANDLE;
	}
}

public Action:Hook_OnTakeDamage(victim, &attacker, &inflictor, &Float:damage, &damagetype, &weapon, Float:damageForce[3], Float:damagePosition[3], damagecustom)
{
	if (g_AFKModElabled && attacker != 0)
	{
		if (isPlayersAFK[victim] && IsValidPlayer(victim) || isPlayersAFK[attacker] && IsValidPlayer(attacker))
		{
			damage = 0.0;
			return Plugin_Changed;
		}
	}
	
	return Plugin_Continue;
}

stock set_rendering(index, FX:fx=FxNone, Render:render=Normal)
{
	SetEntProp(index, Prop_Send, "m_nRenderFX", _:fx, 1);
	SetEntProp(index, Prop_Send, "m_nRenderMode", _:render, 1);
}
 

AlmazON

Не путать с самим yand3xmail
Сообщения
5,099
Реакции
2,755
проблемой удаления таймеров
Глупо управлять функциями с повторяющимся таймером через Handle и, тем более, удалять такой таймер через KillTimer. Для получения управляющих переменных используй bool или, при необходимости (удобности) - int. Остановка повторяющегося таймера осуществляется только через return Plugin_Stop;.
KillTimer, в данном случае, будет просто работать, как CloseHandle.
Сделаешь так - и проблем с Handle не будет вовсе (включая утечки памяти).
 
Сверху Снизу