initial commit
This commit is contained in:
		
						commit
						72f7665358
					
				
							
								
								
									
										123
									
								
								AdminCheats/scripting/AdminCheats.sp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										123
									
								
								AdminCheats/scripting/AdminCheats.sp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,123 @@ | |||||||
|  | #pragma semicolon 1 | ||||||
|  | 
 | ||||||
|  | #include <sourcemod> | ||||||
|  | 
 | ||||||
|  | #pragma newdecls required | ||||||
|  | #define PLUGIN_VERSION "1.0" | ||||||
|  | public Plugin myinfo = | ||||||
|  | { | ||||||
|  | 	name 			= "AdminCheats", | ||||||
|  | 	author 			= "BotoX", | ||||||
|  | 	description 	= "Allows usage of (most) cheat commands for admins.", | ||||||
|  | 	version 		= PLUGIN_VERSION, | ||||||
|  | 	url 			= "" | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | ConVar g_CVar_sv_cheats; | ||||||
|  | 
 | ||||||
|  | public void OnPluginStart() | ||||||
|  | { | ||||||
|  | 	g_CVar_sv_cheats = FindConVar("sv_cheats"); | ||||||
|  | 	g_CVar_sv_cheats.Flags &= ~FCVAR_NOTIFY; | ||||||
|  | 	g_CVar_sv_cheats.Flags &= ~FCVAR_REPLICATED; | ||||||
|  | 	g_CVar_sv_cheats.AddChangeHook(OnConVarChanged); | ||||||
|  | 	g_CVar_sv_cheats.SetInt(1); | ||||||
|  | 
 | ||||||
|  | 	MakeCheatCommand("give"); | ||||||
|  | 
 | ||||||
|  | 	int NumHooks = 0; | ||||||
|  | 	char sConCommand[128]; | ||||||
|  | 	bool IsCommand; | ||||||
|  | 	int Flags; | ||||||
|  | 	Handle hSearch = FindFirstConCommand(sConCommand, sizeof(sConCommand), IsCommand, Flags); | ||||||
|  | 	do | ||||||
|  | 	{ | ||||||
|  | 		if(IsCommand && Flags & FCVAR_CHEAT) | ||||||
|  | 		{ | ||||||
|  | 			RegConsoleCmd(sConCommand, OnCheatCommand); | ||||||
|  | 			NumHooks++; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	while(FindNextConCommand(hSearch, sConCommand, sizeof(sConCommand), IsCommand, Flags)); | ||||||
|  | 
 | ||||||
|  | 	PrintToServer("Hooked %d cheat commands.", NumHooks); | ||||||
|  | 
 | ||||||
|  | 	UpdateClients(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public void OnPluginEnd() | ||||||
|  | { | ||||||
|  | 	g_CVar_sv_cheats.SetInt(0); | ||||||
|  | 	g_CVar_sv_cheats.Flags |= FCVAR_NOTIFY; | ||||||
|  | 	g_CVar_sv_cheats.Flags |= FCVAR_REPLICATED; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public void OnConVarChanged(ConVar convar, const char[] oldValue, const char[] newValue) | ||||||
|  | { | ||||||
|  | 	g_CVar_sv_cheats.SetInt(1); | ||||||
|  | 	CreateTimer(0.1, Timer_UpdateClients); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public Action Timer_UpdateClients(Handle timer, Handle hndl) | ||||||
|  | { | ||||||
|  | 	UpdateClients(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public void UpdateClients() | ||||||
|  | { | ||||||
|  | 	for(int i = 1; i <= MaxClients; i++) | ||||||
|  | 	{ | ||||||
|  | 		if(IsClientInGame(i) && !IsFakeClient(i) && IsClientAuthorized(i)) | ||||||
|  | 			OnClientPostAdminCheck(i); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public void OnClientPutInServer(int client) | ||||||
|  | { | ||||||
|  | 	SendConVarValue(client, g_CVar_sv_cheats, "0"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public void OnClientPostAdminCheck(int client) | ||||||
|  | { | ||||||
|  | 	if(IsFakeClient(client)) | ||||||
|  | 		return; | ||||||
|  | 
 | ||||||
|  | 	if(g_CVar_sv_cheats.BoolValue && GetAdminFlag(GetUserAdmin(client), Admin_Cheats)) | ||||||
|  | 		SendConVarValue(client, g_CVar_sv_cheats, "1"); | ||||||
|  | 	else | ||||||
|  | 		SendConVarValue(client, g_CVar_sv_cheats, "0"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public Action OnCheatCommand(int client, int args) | ||||||
|  | { | ||||||
|  | 	if(client == 0) | ||||||
|  | 		return Plugin_Continue; | ||||||
|  | 
 | ||||||
|  | 	if(IsClientAuthorized(client) && GetAdminFlag(GetUserAdmin(client), Admin_Cheats)) | ||||||
|  | 		return Plugin_Continue; | ||||||
|  | 
 | ||||||
|  | 	PrintToConsole(client, "denied :^)"); | ||||||
|  | 	return Plugin_Handled; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public Action OnPlayerRunCmd(int client, int &buttons, int &impulse, float vel[3], float angles[3], int &weapon, int &subtype, int &cmdnum, int &tickcount, int &seed, int mouse[2]) | ||||||
|  | { | ||||||
|  | 	if(!impulse) | ||||||
|  | 		return Plugin_Continue; | ||||||
|  | 
 | ||||||
|  | 	if(impulse == 100 || impulse == 201) | ||||||
|  | 		return Plugin_Continue; | ||||||
|  | 
 | ||||||
|  | 	if(IsClientAuthorized(client) && GetAdminFlag(GetUserAdmin(client), Admin_Cheats)) | ||||||
|  | 		return Plugin_Continue; | ||||||
|  | 
 | ||||||
|  | 	PrintToConsole(client, "denied :^)"); | ||||||
|  | 	return Plugin_Handled; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | stock void MakeCheatCommand(const char[] name) | ||||||
|  | { | ||||||
|  | 	int Flags = GetCommandFlags(name); | ||||||
|  | 	if(Flags != INVALID_FCVAR_FLAGS) | ||||||
|  | 		SetCommandFlags(name, FCVAR_CHEAT | Flags); | ||||||
|  | } | ||||||
							
								
								
									
										1
									
								
								AdvancedTargeting/scripting/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								AdvancedTargeting/scripting/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | |||||||
|  | SteamAPI.secret | ||||||
							
								
								
									
										451
									
								
								AdvancedTargeting/scripting/AdvancedTargeting.sp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										451
									
								
								AdvancedTargeting/scripting/AdvancedTargeting.sp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,451 @@ | |||||||
|  | #pragma semicolon 1 | ||||||
|  | #define PLUGIN_VERSION "1.0" | ||||||
|  | 
 | ||||||
|  | #pragma dynamic 128*1024 | ||||||
|  | 
 | ||||||
|  | #include <sourcemod> | ||||||
|  | #include <SteamWorks> | ||||||
|  | //#include <EasyJSON> | ||||||
|  | #include <AdvancedTargeting> | ||||||
|  | 
 | ||||||
|  | Handle g_FriendsArray[MAXPLAYERS + 1] = {INVALID_HANDLE, ...}; | ||||||
|  | bool g_bLateLoad = false; | ||||||
|  | 
 | ||||||
|  | //#define STEAM_API_KEY "secret" | ||||||
|  | #include "SteamAPI.secret" | ||||||
|  | 
 | ||||||
|  | public Plugin myinfo = | ||||||
|  | { | ||||||
|  | 	name = "Advanced Targeting", | ||||||
|  | 	author = "BotoX", | ||||||
|  | 	description = "Adds @admins and @friends targeting method", | ||||||
|  | 	version = PLUGIN_VERSION, | ||||||
|  | 	url = "" | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public OnPluginStart() | ||||||
|  | { | ||||||
|  | 	AddMultiTargetFilter("@admins", Filter_Admin, "Admins", false); | ||||||
|  | 	AddMultiTargetFilter("@!admins", Filter_NotAdmin, "Not Admins", false); | ||||||
|  | 	AddMultiTargetFilter("@friends", Filter_Friends, "Steam Friends", false); | ||||||
|  | 	AddMultiTargetFilter("@!friends", Filter_NotFriends, "Not Steam Friends", false); | ||||||
|  | 
 | ||||||
|  | 	RegConsoleCmd("sm_admins", Command_Admins, "Currently online admins."); | ||||||
|  | 	RegConsoleCmd("sm_friends", Command_Friends, "Currently online friends."); | ||||||
|  | 
 | ||||||
|  | 	if(g_bLateLoad) | ||||||
|  | 	{ | ||||||
|  | 		char sSteam32ID[32]; | ||||||
|  | 		for(new i = 1; i <= MaxClients; i++) | ||||||
|  | 		{ | ||||||
|  | 			if(IsClientInGame(i) && !IsFakeClient(i) && IsClientAuthorized(i) && | ||||||
|  | 				GetClientAuthId(i, AuthId_Steam2, sSteam32ID, sizeof(sSteam32ID))) | ||||||
|  | 			{ | ||||||
|  | 				OnClientAuthorized(i, sSteam32ID); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public OnPluginEnd() | ||||||
|  | { | ||||||
|  | 	RemoveMultiTargetFilter("@admins", Filter_Admin); | ||||||
|  | 	RemoveMultiTargetFilter("@!admins", Filter_NotAdmin); | ||||||
|  | 	RemoveMultiTargetFilter("@friends", Filter_Friends); | ||||||
|  | 	RemoveMultiTargetFilter("@!friends", Filter_NotFriends); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max) | ||||||
|  | { | ||||||
|  | 	CreateNative("IsClientFriend", Native_IsClientFriend); | ||||||
|  | 	CreateNative("ReadClientFriends", Native_ReadClientFriends); | ||||||
|  | 	RegPluginLibrary("AdvancedTargeting"); | ||||||
|  | 
 | ||||||
|  | 	g_bLateLoad = late; | ||||||
|  | 	return APLRes_Success; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public Action Command_Admins(int client, int args) | ||||||
|  | { | ||||||
|  | 	char aBuf[1024]; | ||||||
|  | 	char aBuf2[MAX_NAME_LENGTH]; | ||||||
|  | 	for(int i = 1; i <= MaxClients; i++) | ||||||
|  | 	{ | ||||||
|  | 		if(IsClientInGame(i) && !IsFakeClient(i) && GetAdminFlag(GetUserAdmin(i), Admin_Generic)) | ||||||
|  | 		{ | ||||||
|  | 			GetClientName(i, aBuf2, sizeof(aBuf2)); | ||||||
|  | 			StrCat(aBuf, sizeof(aBuf), aBuf2); | ||||||
|  | 			StrCat(aBuf, sizeof(aBuf), ", "); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if(strlen(aBuf)) | ||||||
|  | 	{ | ||||||
|  | 		aBuf[strlen(aBuf) - 2] = 0; | ||||||
|  | 		PrintToChat(client, "[SM] Admins currently online: %s", aBuf); | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 		PrintToChat(client, "[SM] Admins currently online: none"); | ||||||
|  | 
 | ||||||
|  | 	return Plugin_Handled; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public Action Command_Friends(int client, int args) | ||||||
|  | { | ||||||
|  | 	if(g_FriendsArray[client] == INVALID_HANDLE) | ||||||
|  | 	{ | ||||||
|  | 		PrintToChat(client, "[SM] Could not read your friendslist, your profile must be set to public!"); | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	char aBuf[1024]; | ||||||
|  | 	char aBuf2[MAX_NAME_LENGTH]; | ||||||
|  | 	for(int i = 1; i <= MaxClients; i++) | ||||||
|  | 	{ | ||||||
|  | 		if(IsClientInGame(i) && !IsFakeClient(i) && IsClientAuthorized(i)) | ||||||
|  | 		{ | ||||||
|  | 			int Steam3ID = GetSteamAccountID(i); | ||||||
|  | 
 | ||||||
|  | 			if(FindValueInArray(g_FriendsArray[client], Steam3ID) != -1) | ||||||
|  | 			{ | ||||||
|  | 				GetClientName(i, aBuf2, sizeof(aBuf2)); | ||||||
|  | 				StrCat(aBuf, sizeof(aBuf), aBuf2); | ||||||
|  | 				StrCat(aBuf, sizeof(aBuf), ", "); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if(strlen(aBuf)) | ||||||
|  | 	{ | ||||||
|  | 		aBuf[strlen(aBuf) - 2] = 0; | ||||||
|  | 		PrintToChat(client, "[SM] Friends currently online: %s", aBuf); | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 		PrintToChat(client, "[SM] Friends currently online: none"); | ||||||
|  | 
 | ||||||
|  | 	return Plugin_Handled; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public bool Filter_Admin(const char[] sPattern, Handle hClients, int client) | ||||||
|  | { | ||||||
|  | 	for(int i = 1; i <= MaxClients; i++) | ||||||
|  | 	{ | ||||||
|  | 		if(IsClientInGame(i) && !IsFakeClient(i) && GetAdminFlag(GetUserAdmin(i), Admin_Generic)) | ||||||
|  | 		{ | ||||||
|  | 			PushArrayCell(hClients, i); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public bool Filter_NotAdmin(const char[] sPattern, Handle hClients, int client) | ||||||
|  | { | ||||||
|  | 	for(int i = 1; i <= MaxClients; i++) | ||||||
|  | 	{ | ||||||
|  | 		if(IsClientInGame(i) && !IsFakeClient(i) && !GetAdminFlag(GetUserAdmin(i), Admin_Generic)) | ||||||
|  | 		{ | ||||||
|  | 			PushArrayCell(hClients, i); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public bool Filter_Friends(const char[] sPattern, Handle hClients, int client) | ||||||
|  | { | ||||||
|  | 	if(g_FriendsArray[client] == INVALID_HANDLE) | ||||||
|  | 	{ | ||||||
|  | 		PrintToChat(client, "[SM] Could not read your friendslist, your profile must be set to public!"); | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for(int i = 1; i <= MaxClients; i++) | ||||||
|  | 	{ | ||||||
|  | 		if(i != client && IsClientInGame(i) && !IsFakeClient(i) && IsClientAuthorized(i)) | ||||||
|  | 		{ | ||||||
|  | 			int Steam3ID = GetSteamAccountID(i); | ||||||
|  | 
 | ||||||
|  | 			if(FindValueInArray(g_FriendsArray[client], Steam3ID) != -1) | ||||||
|  | 				PushArrayCell(hClients, i); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public bool Filter_NotFriends(const char[] sPattern, Handle hClients, int client) | ||||||
|  | { | ||||||
|  | 	if(g_FriendsArray[client] == INVALID_HANDLE) | ||||||
|  | 	{ | ||||||
|  | 		PrintToChat(client, "[SM] Could not read your friendslist, your profile must be set to public!"); | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for(int i = 1; i <= MaxClients; i++) | ||||||
|  | 	{ | ||||||
|  | 		if(i != client && IsClientInGame(i) && !IsFakeClient(i) && IsClientAuthorized(i)) | ||||||
|  | 		{ | ||||||
|  | 			int Steam3ID = GetSteamAccountID(i); | ||||||
|  | 
 | ||||||
|  | 			if(FindValueInArray(g_FriendsArray[client], Steam3ID) == -1) | ||||||
|  | 				PushArrayCell(hClients, i); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public void OnClientAuthorized(int client, const char[] auth) | ||||||
|  | { | ||||||
|  | 	if(IsFakeClient(client)) | ||||||
|  | 		return; | ||||||
|  | 
 | ||||||
|  | 	char sSteam64ID[32]; | ||||||
|  | 	Steam32IDtoSteam64ID(auth, sSteam64ID, sizeof(sSteam64ID)); | ||||||
|  | 
 | ||||||
|  | 	static char sRequest[256]; | ||||||
|  | 	FormatEx(sRequest, sizeof(sRequest), "http://api.steampowered.com/ISteamUser/GetFriendList/v0001/?key=%s&steamid=%s&relationship=friend&format=vdf", STEAM_API_KEY, sSteam64ID); | ||||||
|  | 
 | ||||||
|  | 	Handle hRequest = SteamWorks_CreateHTTPRequest(k_EHTTPMethodGET, sRequest); | ||||||
|  | 	if (!hRequest || | ||||||
|  | 		!SteamWorks_SetHTTPRequestContextValue(hRequest, client) || | ||||||
|  | 		!SteamWorks_SetHTTPCallbacks(hRequest, OnTransferComplete) || | ||||||
|  | 		!SteamWorks_SendHTTPRequest(hRequest)) | ||||||
|  | 	{ | ||||||
|  | 		CloseHandle(hRequest); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public void OnClientDisconnect(int client) | ||||||
|  | { | ||||||
|  | 	if(g_FriendsArray[client] != INVALID_HANDLE) | ||||||
|  | 		CloseHandle(g_FriendsArray[client]); | ||||||
|  | 
 | ||||||
|  | 	g_FriendsArray[client] = INVALID_HANDLE; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public OnTransferComplete(Handle hRequest, bool bFailure, bool bRequestSuccessful, EHTTPStatusCode eStatusCode, int client) | ||||||
|  | { | ||||||
|  | 	if(bFailure || !bRequestSuccessful || eStatusCode != k_EHTTPStatusCode200OK) | ||||||
|  | 	{ | ||||||
|  | 		// Private profile or maybe steam down? | ||||||
|  | 		//LogError("SteamAPI HTTP Response failed: %d", eStatusCode); | ||||||
|  | 		CloseHandle(hRequest); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	int Length; | ||||||
|  | 	SteamWorks_GetHTTPResponseBodySize(hRequest, Length); | ||||||
|  | 
 | ||||||
|  | 	char[] sData = new char[Length]; | ||||||
|  | 	SteamWorks_GetHTTPResponseBodyData(hRequest, sData, Length); | ||||||
|  | 	//SteamWorks_GetHTTPResponseBodyCallback(hRequest, APIWebResponse, client); | ||||||
|  | 
 | ||||||
|  | 	CloseHandle(hRequest); | ||||||
|  | 
 | ||||||
|  | 	APIWebResponse(sData, client); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public APIWebResponse(const char[] sData, int client) | ||||||
|  | { | ||||||
|  | 	KeyValues Response = new KeyValues("SteamAPIResponse"); | ||||||
|  | 	if(!Response.ImportFromString(sData, "SteamAPIResponse")) | ||||||
|  | 	{ | ||||||
|  | 		LogError("ImportFromString(sData, \"SteamAPIResponse\") failed."); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if(!Response.JumpToKey("friends")) | ||||||
|  | 	{ | ||||||
|  | 		LogError("JumpToKey(\"friends\") failed."); | ||||||
|  | 		delete Response; | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// No friends? | ||||||
|  | 	if(!Response.GotoFirstSubKey()) | ||||||
|  | 	{ | ||||||
|  | 		//LogError("GotoFirstSubKey() failed."); | ||||||
|  | 		delete Response; | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	g_FriendsArray[client] = CreateArray(); | ||||||
|  | 
 | ||||||
|  | 	char sCommunityID[32]; | ||||||
|  | 	do | ||||||
|  | 	{ | ||||||
|  | 		Response.GetString("steamid", sCommunityID, sizeof(sCommunityID)); | ||||||
|  | 
 | ||||||
|  | 		PushArrayCell(g_FriendsArray[client], Steam64toSteam3(sCommunityID)); | ||||||
|  | 	} | ||||||
|  | 	while(Response.GotoNextKey()); | ||||||
|  | 
 | ||||||
|  | 	delete Response; | ||||||
|  | 
 | ||||||
|  | /* DEPRECATED JSON CODE | ||||||
|  | 	Handle hJSON = DecodeJSON(sData); | ||||||
|  | 	if(!hJSON) | ||||||
|  | 	{ | ||||||
|  | 		LogError("DecodeJSON failed."); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	Handle hFriendslist = INVALID_HANDLE; | ||||||
|  | 	if(!JSONGetObject(hJSON, "friendslist", hFriendslist)) | ||||||
|  | 	{ | ||||||
|  | 		LogError("JSONGetObject(hJSON, \"friendslist\", hFriendslist) failed."); | ||||||
|  | 		DestroyJSON(hJSON); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	Handle hFriends = INVALID_HANDLE; | ||||||
|  | 	if(!JSONGetArray(hFriendslist, "friends", hFriends)) | ||||||
|  | 	{ | ||||||
|  | 		LogError("JSONGetObject(hFriendslist, \"friends\", hFriends) failed."); | ||||||
|  | 		DestroyJSON(hJSON); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	int ArraySize = GetArraySize(hFriends); | ||||||
|  | 	PrintToServer("ArraySize: %d", ArraySize); | ||||||
|  | 
 | ||||||
|  | 	for(int i = 0; i < ArraySize; i++) | ||||||
|  | 	{ | ||||||
|  | 		Handle hEntry = INVALID_HANDLE; | ||||||
|  | 		JSONGetArrayObject(hFriends, i, hEntry); | ||||||
|  | 
 | ||||||
|  | 		static char sCommunityID[32]; | ||||||
|  | 		if(!JSONGetString(hEntry, "steamid", sCommunityID, sizeof(sCommunityID))) | ||||||
|  | 		{ | ||||||
|  | 			LogError("JSONGetString(hArray, \"steamid\", sCommunityID, %d) failed.", sizeof(sCommunityID)); | ||||||
|  | 			DestroyJSON(hJSON); | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		PushArrayCell(g_FriendsArray[client], Steam64toSteam3(sCommunityID)); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	DestroyJSON(hJSON); | ||||||
|  | */ | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | stock bool Steam32IDtoSteam64ID(const char[] sSteam32ID, char[] sSteam64ID, int Size) | ||||||
|  | { | ||||||
|  | 	if(strlen(sSteam32ID) < 11 || strncmp(sSteam32ID[0], "STEAM_0:", 8)) | ||||||
|  | 	{ | ||||||
|  | 		sSteam64ID[0] = 0; | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	int iUpper = 765611979; | ||||||
|  | 	int isSteam64ID = StringToInt(sSteam32ID[10]) * 2 + 60265728 + sSteam32ID[8] - 48; | ||||||
|  | 
 | ||||||
|  | 	int iDiv = isSteam64ID / 100000000; | ||||||
|  | 	int iIdx = 9 - (iDiv ? (iDiv / 10 + 1) : 0); | ||||||
|  | 	iUpper += iDiv; | ||||||
|  | 
 | ||||||
|  | 	IntToString(isSteam64ID, sSteam64ID[iIdx], Size - iIdx); | ||||||
|  | 	iIdx = sSteam64ID[9]; | ||||||
|  | 	IntToString(iUpper, sSteam64ID, Size); | ||||||
|  | 	sSteam64ID[9] = iIdx; | ||||||
|  | 
 | ||||||
|  | 	return true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | stock int Steam64toSteam3(const char[] sSteam64ID) | ||||||
|  | { | ||||||
|  | 	if(strlen(sSteam64ID) != 17) | ||||||
|  | 		return 0; | ||||||
|  | 
 | ||||||
|  | 	// convert SteamID64 to array of integers | ||||||
|  | 	int aSteam64ID[17]; | ||||||
|  | 	for(int i = 0; i < 17; i++) | ||||||
|  | 		aSteam64ID[i] = sSteam64ID[i] - 48; | ||||||
|  | 
 | ||||||
|  | 	// subtract individual SteamID64 identifier (0x0110000100000000) | ||||||
|  | 	int aSteam64IDIdent[] = {7, 6, 5, 6, 1, 1, 9, 7, 9, 6, 0, 2, 6, 5, 7, 2, 8}; | ||||||
|  | 	int Carry = 0; | ||||||
|  | 	for(int i = 16; i >= 0; i--) | ||||||
|  | 	{ | ||||||
|  | 		if(aSteam64ID[i] < aSteam64IDIdent[i] + Carry) | ||||||
|  | 		{ | ||||||
|  | 			aSteam64ID[i] = aSteam64ID[i] - aSteam64IDIdent[i] - Carry + 10; | ||||||
|  | 			Carry = 1; | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			aSteam64ID[i] = aSteam64ID[i] - aSteam64IDIdent[i] - Carry; | ||||||
|  | 			Carry = 0; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	char aBuf[17]; | ||||||
|  | 	int j = 0; | ||||||
|  | 	bool ZereosDone = false; | ||||||
|  | 	for(int i = 0; i < 17; i++) | ||||||
|  | 	{ | ||||||
|  | 		if(!ZereosDone && !aSteam64ID[i]) | ||||||
|  | 			continue; | ||||||
|  | 		ZereosDone = true; | ||||||
|  | 
 | ||||||
|  | 		aBuf[j++] = aSteam64ID[i] + 48; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return StringToInt(aBuf); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public int Native_IsClientFriend(Handle plugin, int numParams) | ||||||
|  | { | ||||||
|  | 	new client = GetNativeCell(1); | ||||||
|  | 	new friend = GetNativeCell(2); | ||||||
|  | 
 | ||||||
|  | 	if(client > MaxClients || client <= 0 || friend > MaxClients || friend <= 0) | ||||||
|  | 	{ | ||||||
|  | 		ThrowNativeError(SP_ERROR_NATIVE, "Client is not valid."); | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if(!IsClientInGame(client) || !IsClientInGame(friend)) | ||||||
|  | 	{ | ||||||
|  | 		ThrowNativeError(SP_ERROR_NATIVE, "Client is not in-game."); | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if(IsFakeClient(client) || IsFakeClient(friend)) | ||||||
|  | 	{ | ||||||
|  | 		ThrowNativeError(SP_ERROR_NATIVE, "Client is fake-client."); | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if(g_FriendsArray[client] == INVALID_HANDLE) | ||||||
|  | 		return -1; | ||||||
|  | 
 | ||||||
|  | 	if(IsClientAuthorized(friend)) | ||||||
|  | 	{ | ||||||
|  | 		int Steam3ID = GetSteamAccountID(friend); | ||||||
|  | 
 | ||||||
|  | 		if(FindValueInArray(g_FriendsArray[client], Steam3ID) != -1) | ||||||
|  | 			return 1; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public int Native_ReadClientFriends(Handle plugin, int numParams) | ||||||
|  | { | ||||||
|  | 	new client = GetNativeCell(1); | ||||||
|  | 
 | ||||||
|  | 	if(client > MaxClients || client <= 0) | ||||||
|  | 	{ | ||||||
|  | 		ThrowNativeError(SP_ERROR_NATIVE, "Client is not valid."); | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if(g_FriendsArray[client] != INVALID_HANDLE) | ||||||
|  | 		return 1; | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
							
								
								
									
										25
									
								
								AdvancedTargeting/scripting/include/AdvancedTargeting.inc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								AdvancedTargeting/scripting/include/AdvancedTargeting.inc
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,25 @@ | |||||||
|  | #if defined _AdvancedTargeting_Included
 | ||||||
|  | 	#endinput
 | ||||||
|  | #endif
 | ||||||
|  | #define _AdvancedTargeting_Included
 | ||||||
|  | 
 | ||||||
|  | native int IsClientFriend(int client, int friend); | ||||||
|  | native int ReadClientFriends(int client); | ||||||
|  | 
 | ||||||
|  | public SharedPlugin:__pl_AdvancedTargeting = | ||||||
|  | { | ||||||
|  | 	name = "AdvancedTargeting", | ||||||
|  | 	file = "AdvancedTargeting.smx", | ||||||
|  | #if defined REQUIRE_PLUGIN
 | ||||||
|  | 	required = 1, | ||||||
|  | #else
 | ||||||
|  | 	required = 0, | ||||||
|  | #endif
 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #if !defined REQUIRE_PLUGIN
 | ||||||
|  | public __pl_myfile_SetNTVOptional() | ||||||
|  | { | ||||||
|  | 	MarkNativeAsOptional("IsClientFriend"); | ||||||
|  | } | ||||||
|  | #endif
 | ||||||
							
								
								
									
										1
									
								
								AdvancedTargeting/scripting/include/SteamWorks.inc
									
									
									
									
									
										Symbolic link
									
								
							
							
						
						
									
										1
									
								
								AdvancedTargeting/scripting/include/SteamWorks.inc
									
									
									
									
									
										Symbolic link
									
								
							| @ -0,0 +1 @@ | |||||||
|  | ../../../includes/SteamWorks.inc | ||||||
							
								
								
									
										314
									
								
								AfkManager/scripting/AfkManager.sp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										314
									
								
								AfkManager/scripting/AfkManager.sp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,314 @@ | |||||||
|  | #pragma semicolon 1 | ||||||
|  | 
 | ||||||
|  | #include <sourcemod> | ||||||
|  | #include <sdktools> | ||||||
|  | #include <cstrike> | ||||||
|  | 
 | ||||||
|  | #define AFK_CHECK_INTERVAL 5.0 | ||||||
|  | 
 | ||||||
|  | bool g_Players_bEnabled[MAXPLAYERS + 1]; | ||||||
|  | bool g_Players_bFlagged[MAXPLAYERS + 1]; | ||||||
|  | int g_Players_iLastAction[MAXPLAYERS + 1]; | ||||||
|  | float g_Players_fEyePosition[MAXPLAYERS + 1][3]; | ||||||
|  | int g_Players_iButtons[MAXPLAYERS + 1]; | ||||||
|  | int g_Players_iSpecMode[MAXPLAYERS + 1]; | ||||||
|  | int g_Players_iSpecTarget[MAXPLAYERS + 1]; | ||||||
|  | 
 | ||||||
|  | float g_fKickTime; | ||||||
|  | float g_fMoveTime; | ||||||
|  | float g_fWarnTime; | ||||||
|  | int g_iKickMinPlayers; | ||||||
|  | int g_iMoveMinPlayers; | ||||||
|  | int g_iImmunity; | ||||||
|  | 
 | ||||||
|  | public Plugin myinfo = | ||||||
|  | { | ||||||
|  | 	name = "Good AFK Manager", | ||||||
|  | 	author = "BotoX", | ||||||
|  | 	description = "A good AFK manager?", | ||||||
|  | 	version = "1.0", | ||||||
|  | 	url = "" | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | public Cvar_KickTime(Handle:cvar, const String:oldvalue[], const String:newvalue[]) | ||||||
|  | { | ||||||
|  | 	g_fKickTime = GetConVarFloat(cvar); | ||||||
|  | } | ||||||
|  | public Cvar_MoveTime(Handle:cvar, const String:oldvalue[], const String:newvalue[]) | ||||||
|  | { | ||||||
|  | 	g_fMoveTime = GetConVarFloat(cvar); | ||||||
|  | } | ||||||
|  | public Cvar_WarnTime(Handle:cvar, const String:oldvalue[], const String:newvalue[]) | ||||||
|  | { | ||||||
|  | 	g_fWarnTime = GetConVarFloat(cvar); | ||||||
|  | } | ||||||
|  | public Cvar_KickMinPlayers(Handle:cvar, const String:oldvalue[], const String:newvalue[]) | ||||||
|  | { | ||||||
|  | 	g_iKickMinPlayers = GetConVarInt(cvar); | ||||||
|  | } | ||||||
|  | public Cvar_MoveMinPlayers(Handle:cvar, const String:oldvalue[], const String:newvalue[]) | ||||||
|  | { | ||||||
|  | 	g_iMoveMinPlayers = GetConVarInt(cvar); | ||||||
|  | } | ||||||
|  | public Cvar_Immunity(Handle:cvar, const String:oldvalue[], const String:newvalue[]) | ||||||
|  | { | ||||||
|  | 	g_iImmunity = GetConVarInt(cvar); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public OnPluginStart() | ||||||
|  | { | ||||||
|  | 	Handle cvar; | ||||||
|  | 	HookConVarChange((cvar = CreateConVar("sm_afk_move_min", "4", "Min players for AFK move")), Cvar_MoveMinPlayers); | ||||||
|  | 	g_iMoveMinPlayers = GetConVarInt(cvar); | ||||||
|  | 
 | ||||||
|  | 	HookConVarChange((cvar = CreateConVar("sm_afk_kick_min", "6", "Min players for AFK kick")), Cvar_KickMinPlayers); | ||||||
|  | 	g_iKickMinPlayers = GetConVarInt(cvar); | ||||||
|  | 
 | ||||||
|  | 	HookConVarChange((cvar = CreateConVar("sm_afk_move_time", "60.0", "Time in seconds for AFK Move. 0 = DISABLED")), Cvar_MoveTime); | ||||||
|  | 	g_fMoveTime = GetConVarFloat(cvar); | ||||||
|  | 
 | ||||||
|  | 	HookConVarChange((cvar = CreateConVar("sm_afk_kick_time", "120.0", "Time in seconds to AFK Kick. 0 = DISABLED")), Cvar_KickTime); | ||||||
|  | 	g_fKickTime = GetConVarFloat(cvar); | ||||||
|  | 
 | ||||||
|  | 	HookConVarChange((cvar = CreateConVar("sm_afk_warn_time", "30.0", "Time in seconds remaining before warning")), Cvar_WarnTime); | ||||||
|  | 	g_fWarnTime = GetConVarFloat(cvar); | ||||||
|  | 
 | ||||||
|  | 	HookConVarChange((cvar = CreateConVar("sm_afk_immunity", "1", "AFK admins immunity: 0 = DISABLED, 1 = COMPLETE, 2 = KICK, 3 = MOVE")), Cvar_Immunity); | ||||||
|  | 	g_iImmunity = GetConVarInt(cvar); | ||||||
|  | 
 | ||||||
|  | 	CloseHandle(cvar); | ||||||
|  | 
 | ||||||
|  | 	AddCommandListener(Command_Say, "say"); | ||||||
|  | 	AddCommandListener(Command_Say, "say_team"); | ||||||
|  | 	HookEvent("player_team", Event_PlayerTeamPost, EventHookMode_Post); | ||||||
|  | 
 | ||||||
|  | 	AutoExecConfig(true, "plugin.AfkManager"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public OnMapStart() | ||||||
|  | { | ||||||
|  | 	CreateTimer(AFK_CHECK_INTERVAL, Timer_CheckPlayer, _, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE); | ||||||
|  | 	for (int Index = 1; Index <= MaxClients; Index++) | ||||||
|  | 	{ | ||||||
|  | 		g_Players_bEnabled[Index] = false; | ||||||
|  | 		if (IsClientConnected(Index) && IsClientInGame(Index) && !IsFakeClient(Index)) | ||||||
|  | 			InitializePlayer(Index); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | CheckAdminImmunity(Index) | ||||||
|  | { | ||||||
|  | 	AdminId Id = GetUserAdmin(Index); | ||||||
|  | 	return GetAdminFlag(Id, Admin_Generic); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ResetPlayer(Index) | ||||||
|  | { | ||||||
|  | 	g_Players_bEnabled[Index] = false; | ||||||
|  | 	g_Players_bFlagged[Index] = false; | ||||||
|  | 	g_Players_iLastAction[Index] = 0; | ||||||
|  | 	g_Players_fEyePosition[Index] = Float:{0.0, 0.0, 0.0}; | ||||||
|  | 	g_Players_iButtons[Index] = 0; | ||||||
|  | 	g_Players_iSpecMode[Index] = 0; | ||||||
|  | 	g_Players_iSpecTarget[Index] = 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | InitializePlayer(Index) | ||||||
|  | { | ||||||
|  | 	if (!(g_iImmunity == 1 && CheckAdminImmunity(Index))) | ||||||
|  | 	{ | ||||||
|  | 		ResetPlayer(Index); | ||||||
|  | 		g_Players_iLastAction[Index] = GetTime(); | ||||||
|  | 		g_Players_bEnabled[Index] = true; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public OnClientPostAdminCheck(Index) | ||||||
|  | { | ||||||
|  | 	if (!IsFakeClient(Index)) | ||||||
|  | 		InitializePlayer(Index); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public OnClientDisconnect(Index) | ||||||
|  | { | ||||||
|  | 	ResetPlayer(Index); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public Action:Event_PlayerTeamPost(Handle:event, const String:name[], bool:dontBroadcast) | ||||||
|  | { | ||||||
|  | 	int Index = GetClientOfUserId(GetEventInt(event, "userid")); | ||||||
|  | 	if (Index > 0 && !IsFakeClient(Index)) | ||||||
|  | 	{ | ||||||
|  | 		if (!g_Players_bEnabled[Index]) | ||||||
|  | 			InitializePlayer(Index); | ||||||
|  | 		g_Players_iLastAction[Index] = GetTime(); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public Action:Command_Say(Index, const String:Command[], Args) | ||||||
|  | { | ||||||
|  | 	g_Players_iLastAction[Index] = GetTime(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public Action:OnPlayerRunCmd(Index, &iButtons, &iImpulse, Float:fVel[3], Float:fAngles[3], &iWeapon) | ||||||
|  | { | ||||||
|  | 	if (((g_Players_fEyePosition[Index][0] != fAngles[0]) || | ||||||
|  | 		(g_Players_fEyePosition[Index][1] != fAngles[1]) || | ||||||
|  | 		(g_Players_fEyePosition[Index][2] != fAngles[2])) | ||||||
|  | 		&& g_Players_iSpecMode[Index] != 4) // OBS_MODE_IN_EYE | ||||||
|  | 	{ | ||||||
|  | 		if(!((iButtons & IN_LEFT) || (iButtons & IN_RIGHT))) | ||||||
|  | 			g_Players_iLastAction[Index] = GetTime(); | ||||||
|  | 
 | ||||||
|  | 		g_Players_fEyePosition[Index] = fAngles; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if(g_Players_iButtons[Index] != iButtons) | ||||||
|  | 	{ | ||||||
|  | 		g_Players_iLastAction[Index] = GetTime(); | ||||||
|  | 		g_Players_iButtons[Index] = iButtons; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return Plugin_Continue; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public Action:Timer_CheckPlayer(Handle:Timer, any:Data) | ||||||
|  | { | ||||||
|  | 	int Index; | ||||||
|  | 	int Clients = 0; | ||||||
|  | 
 | ||||||
|  | 	for (Index = 1; Index <= MaxClients; Index++) | ||||||
|  | 	{ | ||||||
|  | 		if (IsClientInGame(Index) && !IsFakeClient(Index)) | ||||||
|  | 			Clients++; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	bool bMovePlayers = (Clients >= g_iMoveMinPlayers && g_fMoveTime > 0.0); | ||||||
|  | 	bool bKickPlayers = (Clients >= g_iKickMinPlayers && g_fKickTime > 0.0); | ||||||
|  | 
 | ||||||
|  | 	if (!bMovePlayers && !bKickPlayers) | ||||||
|  | 		return Plugin_Continue; | ||||||
|  | 
 | ||||||
|  | 	for (Index = 1; Index <= MaxClients; Index++) | ||||||
|  | 	{ | ||||||
|  | 		if (!g_Players_bEnabled[Index] || !IsClientInGame(Index)) // Is this player actually in the game? | ||||||
|  | 			continue; | ||||||
|  | 
 | ||||||
|  | 		int iTeamNum = GetClientTeam(Index); | ||||||
|  | 
 | ||||||
|  | 		if (IsClientObserver(Index)) | ||||||
|  | 		{ | ||||||
|  | 			if (iTeamNum > CS_TEAM_SPECTATOR && !IsPlayerAlive(Index)) | ||||||
|  | 				continue; | ||||||
|  | 
 | ||||||
|  | 			int iSpecMode = g_Players_iSpecMode[Index]; | ||||||
|  | 			int iSpecTarget = g_Players_iSpecTarget[Index]; | ||||||
|  | 
 | ||||||
|  | 			g_Players_iSpecMode[Index] = GetEntProp(Index, Prop_Send, "m_iObserverMode"); | ||||||
|  | 			g_Players_iSpecTarget[Index] = GetEntPropEnt(Index, Prop_Send, "m_hObserverTarget"); | ||||||
|  | 
 | ||||||
|  | 			if ((iSpecMode && g_Players_iSpecMode[Index] != iSpecMode) || (iSpecTarget && g_Players_iSpecTarget[Index] != iSpecTarget)) | ||||||
|  | 				g_Players_iLastAction[Index] = GetTime(); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		int IdleTime = GetTime() - g_Players_iLastAction[Index]; | ||||||
|  | 
 | ||||||
|  | 		if (g_Players_bFlagged[Index] && (g_fKickTime - IdleTime) > 0.0) | ||||||
|  | 		{ | ||||||
|  | 			PrintCenterText(Index, "Welcome back!"); | ||||||
|  | 			PrintToChat(Index, "\x04[AFK] \x01You have been un-flagged for being inactive."); | ||||||
|  | 			g_Players_bFlagged[Index] = false; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (bMovePlayers && iTeamNum > CS_TEAM_SPECTATOR && ( !g_iImmunity || g_iImmunity == 2 || !CheckAdminImmunity(Index))) | ||||||
|  | 		{ | ||||||
|  | 			float iTimeleft = g_fMoveTime - IdleTime; | ||||||
|  | 			if (iTimeleft > 0.0) | ||||||
|  | 			{ | ||||||
|  | 				if(iTimeleft <= g_fWarnTime) | ||||||
|  | 				{ | ||||||
|  | 					PrintCenterText(Index, "Warning: If you do not move in %d seconds, you will be moved to spectate.", RoundToFloor(iTimeleft)); | ||||||
|  | 					PrintToChat(Index, "\x04[AFK] \x01Warning: If you do not move in %d seconds, you will be moved to spectate.", RoundToFloor(iTimeleft)); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			else | ||||||
|  | 			{ | ||||||
|  | 				decl String:f_Name[MAX_NAME_LENGTH+4]; | ||||||
|  | 				Format(f_Name, sizeof(f_Name), "\x03%N\x01", Index); | ||||||
|  | 				PrintToChatAll("\x04[AFK] \x01%s was moved to spectate for being AFK too long.", f_Name); | ||||||
|  | 				ForcePlayerSuicide(Index); | ||||||
|  | 				ChangeClientTeam(Index, CS_TEAM_SPECTATOR); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		else if (g_fKickTime > 0.0 && (!g_iImmunity || g_iImmunity == 3 || !CheckAdminImmunity(Index))) | ||||||
|  | 		{ | ||||||
|  | 			float iTimeleft = g_fKickTime - IdleTime; | ||||||
|  | 			if (iTimeleft > 0.0) | ||||||
|  | 			{ | ||||||
|  | 				if (iTimeleft <= g_fWarnTime) | ||||||
|  | 				{ | ||||||
|  | 					PrintCenterText(Index, "Warning: If you do not move in %d seconds, you will be kick-flagged for being inactive.", RoundToFloor(iTimeleft)); | ||||||
|  | 					PrintToChat(Index, "\x04[AFK] \x01Warning: If you do not move in %d seconds, you will be kick-flagged for being inactive.", RoundToFloor(iTimeleft)); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			else | ||||||
|  | 			{ | ||||||
|  | 				if (!g_Players_bFlagged[Index]) | ||||||
|  | 				{ | ||||||
|  | 					PrintToChat(Index, "\x04[AFK] \x01You have been kick-flagged for being inactive."); | ||||||
|  | 					g_Players_bFlagged[Index] = true; | ||||||
|  | 				} | ||||||
|  | 				int FlaggedPlayers = 0; | ||||||
|  | 				int Position = 1; | ||||||
|  | 				for (int Index_ = 1; Index_ <= MaxClients; Index_++) | ||||||
|  | 				{ | ||||||
|  | 					if (!g_Players_bFlagged[Index_]) | ||||||
|  | 						continue; | ||||||
|  | 
 | ||||||
|  | 					FlaggedPlayers++; | ||||||
|  | 					int IdleTime_ = GetTime() - g_Players_iLastAction[Index_]; | ||||||
|  | 
 | ||||||
|  | 					if (IdleTime_ > IdleTime) | ||||||
|  | 						Position++; | ||||||
|  | 				} | ||||||
|  | 				PrintCenterText(Index, "You have been kick-flagged for being inactive. [%d/%d]", Position, FlaggedPlayers); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	while(bKickPlayers) | ||||||
|  | 	{ | ||||||
|  | 		int InactivePlayer = -1; | ||||||
|  | 		int InactivePlayerTime = 0; | ||||||
|  | 
 | ||||||
|  | 		for (Index = 1; Index <= MaxClients; Index++) | ||||||
|  | 		{ | ||||||
|  | 			if (!g_Players_bFlagged[Index]) | ||||||
|  | 				continue; | ||||||
|  | 
 | ||||||
|  | 			int IdleTime = GetTime() - g_Players_iLastAction[Index]; | ||||||
|  | 
 | ||||||
|  | 			if (IdleTime > InactivePlayerTime) | ||||||
|  | 			{ | ||||||
|  | 				InactivePlayer = Index; | ||||||
|  | 				InactivePlayerTime = IdleTime; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (InactivePlayer == -1) | ||||||
|  | 			break; | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			decl String:f_Name[MAX_NAME_LENGTH+4]; | ||||||
|  | 			Format(f_Name, sizeof(f_Name), "\x03%N\x01", InactivePlayer); | ||||||
|  | 			PrintToChatAll("\x04[AFK] %s was kicked for being AFK too long. (%d seconds)", f_Name, InactivePlayerTime); | ||||||
|  | 			KickClient(InactivePlayer, "[AFK] You were kicked for being AFK too long. (%d seconds)", InactivePlayerTime); | ||||||
|  | 			Clients--; | ||||||
|  | 			g_Players_bFlagged[InactivePlayer] = false; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		bKickPlayers = (Clients >= g_iKickMinPlayers && g_fKickTime > 0.0); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return Plugin_Continue; | ||||||
|  | } | ||||||
							
								
								
									
										31
									
								
								ConnectAnnounce/scripting/ConnectAnnounce.sp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								ConnectAnnounce/scripting/ConnectAnnounce.sp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,31 @@ | |||||||
|  | #pragma semicolon 1 | ||||||
|  | 
 | ||||||
|  | #include <sourcemod> | ||||||
|  | #include <geoip> | ||||||
|  | 
 | ||||||
|  | #pragma newdecls required | ||||||
|  | 
 | ||||||
|  | public Plugin myinfo = { | ||||||
|  | 	name = "Connect Announce", | ||||||
|  | 	author = "BotoX", | ||||||
|  | 	description = "Simple connect announcer", | ||||||
|  | 	version = "1.0", | ||||||
|  | 	url = "" | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public void OnClientPostAdminCheck(int client) | ||||||
|  | { | ||||||
|  | 	if(IsFakeClient(client)) | ||||||
|  | 		return; | ||||||
|  | 
 | ||||||
|  | 	static char sAuth[32]; | ||||||
|  | 	static char sIP[16]; | ||||||
|  | 	static char sCountry[32]; | ||||||
|  | 
 | ||||||
|  | 	GetClientAuthId(client, AuthId_Steam2, sAuth, sizeof(sAuth)); | ||||||
|  | 
 | ||||||
|  | 	if(GetClientIP(client, sIP, sizeof(sIP)) && GeoipCountry(sIP, sCountry, sizeof(sCountry))) | ||||||
|  | 		PrintToChatAll("\x04%L [\x03%s\x04] connected from %s", client, sAuth, sCountry); | ||||||
|  | 	else | ||||||
|  | 		PrintToChatAll("\x04%L [\x03%s\x04] connected", client, sAuth); | ||||||
|  | } | ||||||
							
								
								
									
										648
									
								
								ExtraCommands/scripting/ExtraCommands.sp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										648
									
								
								ExtraCommands/scripting/ExtraCommands.sp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,648 @@ | |||||||
|  | #pragma semicolon 1 | ||||||
|  | 
 | ||||||
|  | #include <sourcemod> | ||||||
|  | #include <sdktools> | ||||||
|  | #include <sdkhooks> | ||||||
|  | 
 | ||||||
|  | bool g_bInBuyZoneAll = false; | ||||||
|  | bool g_bInBuyZone[MAXPLAYERS + 1] = {false, ...}; | ||||||
|  | 
 | ||||||
|  | bool g_bInfAmmoHooked = false; | ||||||
|  | bool g_bInfAmmoAll = false; | ||||||
|  | bool g_bInfAmmo[MAXPLAYERS + 1] = {false, ...}; | ||||||
|  | 
 | ||||||
|  | ConVar g_CVar_sv_pausable; | ||||||
|  | bool g_bPaused; | ||||||
|  | 
 | ||||||
|  | public Plugin:myinfo = | ||||||
|  | { | ||||||
|  | 	name = "Advanced Commands", | ||||||
|  | 	author = "BotoX", | ||||||
|  | 	description = "Adds: hp, kevlar, weapon, strip, buyzone, iammo, speed", | ||||||
|  | 	version = "1.0", | ||||||
|  | 	url = "" | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | public OnPluginStart() | ||||||
|  | { | ||||||
|  | 	RegAdminCmd("sm_hp", Command_Health, ADMFLAG_GENERIC, "sm_hp <#userid|name> <value>"); | ||||||
|  | 	RegAdminCmd("sm_kevlar", Command_Kevlar, ADMFLAG_GENERIC, "sm_kevlar <#userid|name> <value>"); | ||||||
|  | 	RegAdminCmd("sm_weapon", Command_Weapon, ADMFLAG_GENERIC, "sm_weapon <#userid|name> <name> [clip] [ammo]"); | ||||||
|  | 	RegAdminCmd("sm_give", Command_Weapon, ADMFLAG_GENERIC, "sm_give <#userid|name> <name> [clip] [ammo]"); | ||||||
|  | 	RegAdminCmd("sm_strip", Command_Strip, ADMFLAG_GENERIC, "sm_strip <#userid|name>"); | ||||||
|  | 	RegAdminCmd("sm_buyzone", Command_BuyZone, ADMFLAG_CUSTOM3, "sm_buyzone <#userid|name> <0|1>"); | ||||||
|  | 	RegAdminCmd("sm_iammo", Command_InfAmmo, ADMFLAG_CUSTOM3, "sm_iammo <#userid|name> <0|1>"); | ||||||
|  | 	RegAdminCmd("sm_speed", Command_Speed, ADMFLAG_CUSTOM3, "sm_speed <#userid|name> <0|1>"); | ||||||
|  | 
 | ||||||
|  | 	HookEvent("bomb_planted", Event_BombPlanted, EventHookMode_Pre); | ||||||
|  | 	HookEvent("bomb_defused", Event_BombDefused, EventHookMode_Pre); | ||||||
|  | 
 | ||||||
|  | 	g_CVar_sv_pausable = FindConVar("sv_pausable"); | ||||||
|  | 	if(g_CVar_sv_pausable) | ||||||
|  | 		AddCommandListener(Listener_Pause, "pause"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public OnMapStart() | ||||||
|  | { | ||||||
|  | 	g_bInBuyZoneAll = false; | ||||||
|  | 	g_bInfAmmoAll = false; | ||||||
|  | 	if(g_bInfAmmoHooked) | ||||||
|  | 	{ | ||||||
|  | 		UnhookEvent("weapon_fire", Event_WeaponFire); | ||||||
|  | 		g_bInfAmmoHooked = false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* Handle late load */ | ||||||
|  | 	for(new i = 1; i <= MaxClients; i++) | ||||||
|  | 	{ | ||||||
|  | 		if(IsClientConnected(i) && IsClientInGame(i)) | ||||||
|  | 		{ | ||||||
|  | 			g_bInfAmmo[i] = false; | ||||||
|  | 			g_bInBuyZone[i] = false; | ||||||
|  | 			SDKHook(i, SDKHook_PreThink, OnPreThink); | ||||||
|  | 			SDKHook(i, SDKHook_PostThinkPost, OnPostThinkPost); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public Action Listener_Pause(int client, const char[] command, int argc) | ||||||
|  | { | ||||||
|  | 	if(!g_CVar_sv_pausable.BoolValue) | ||||||
|  | 	{ | ||||||
|  | 		ReplyToCommand(client, "sv_pausable is set to 0!"); | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 	} | ||||||
|  | 	if(client == 0) | ||||||
|  | 	{ | ||||||
|  | 		PrintToServer("[SM] Cannot use command from server console."); | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 	} | ||||||
|  | 	if(!IsClientAuthorized(client) || !GetAdminFlag(GetUserAdmin(client), Admin_Generic)) | ||||||
|  | 	{ | ||||||
|  | 		ReplyToCommand(client, "You do not have permission to pause the game."); | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	ShowActivity2(client, "[SM] ", "%s the game.", g_bPaused ? "Unpaused" : "Paused"); | ||||||
|  | 	LogAction(client, -1, "%s the game.", g_bPaused ? "Unpaused" : "Paused"); | ||||||
|  | 	g_bPaused = !g_bPaused; | ||||||
|  | 	return Plugin_Continue; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | public Action:Event_BombPlanted(Handle:event, const String:name[], bool:dontBroadcast) | ||||||
|  | { | ||||||
|  | 	for(new i = 1; i < MAXPLAYERS; i++) | ||||||
|  | 	{ | ||||||
|  | 		if(IsClientInGame(i)) | ||||||
|  | 			ClientCommand(i, "playgamesound \"radio/bombpl.wav\""); | ||||||
|  | 	} | ||||||
|  | 	return Plugin_Handled; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public Action:Event_BombDefused(Handle:event, const String:name[], bool:dontBroadcast) | ||||||
|  | { | ||||||
|  | 	for(new i = 1; i < MAXPLAYERS; i++) | ||||||
|  | 	{ | ||||||
|  | 		if(IsClientInGame(i)) | ||||||
|  | 			ClientCommand(i, "playgamesound \"radio/bombdef.wav\""); | ||||||
|  | 	} | ||||||
|  | 	return Plugin_Handled; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public OnClientPutInServer(client) | ||||||
|  | { | ||||||
|  | 	g_bInBuyZone[client] = false; | ||||||
|  | 	g_bInfAmmo[client] = false; | ||||||
|  | 	SDKHook(client, SDKHook_PreThink, OnPreThink); | ||||||
|  | 	SDKHook(client, SDKHook_PostThinkPost, OnPostThinkPost); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public OnPreThink(client) | ||||||
|  | { | ||||||
|  | 	if(IsClientInGame(client) && IsPlayerAlive(client)) | ||||||
|  | 	{ | ||||||
|  | 		SetEntProp(client, Prop_Send, "m_bInBombZone", 1); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public OnPostThinkPost(client) | ||||||
|  | { | ||||||
|  | 	if(IsClientInGame(client) && IsPlayerAlive(client)) | ||||||
|  | 	{ | ||||||
|  | 		if(g_bInBuyZoneAll || g_bInBuyZone[client]) | ||||||
|  | 			SetEntProp(client, Prop_Send, "m_bInBuyZone", 1); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public Event_WeaponFire(Handle:hEvent, String:name[], bool:dontBroadcast) | ||||||
|  | { | ||||||
|  | 	new client = GetClientOfUserId(GetEventInt(hEvent, "userid")); | ||||||
|  | 	if(!g_bInfAmmoAll && !g_bInfAmmo[client]) | ||||||
|  | 		return; | ||||||
|  | 
 | ||||||
|  | 	new weapon = GetEntPropEnt(client, Prop_Data, "m_hActiveWeapon", 0); | ||||||
|  | 	if(IsValidEntity(weapon)) | ||||||
|  | 	{ | ||||||
|  | 		if(weapon == GetPlayerWeaponSlot(client, 0) || weapon == GetPlayerWeaponSlot(client, 1)) | ||||||
|  | 		{ | ||||||
|  | 			if(GetEntProp(weapon, Prop_Send, "m_iState", 4, 0) == 2 && GetEntProp(weapon, Prop_Send, "m_iClip1", 4, 0)) | ||||||
|  | 			{ | ||||||
|  | 				new toAdd = 1; | ||||||
|  | 				new String:weaponClassname[128]; | ||||||
|  | 				GetEntityClassname(weapon, weaponClassname, 128); | ||||||
|  | 
 | ||||||
|  | 				if(StrEqual(weaponClassname, "weapon_glock", true) || StrEqual(weaponClassname, "weapon_famas", true)) | ||||||
|  | 				{ | ||||||
|  | 					if(GetEntProp(weapon, Prop_Data, "m_bBurstMode", 4, 0)) | ||||||
|  | 					{ | ||||||
|  | 						switch (GetEntProp(weapon, Prop_Send, "m_iClip1", 4, 0)) | ||||||
|  | 						{ | ||||||
|  | 							case 1: | ||||||
|  | 							{ | ||||||
|  | 								toAdd = 1; | ||||||
|  | 							} | ||||||
|  | 							case 2: | ||||||
|  | 							{ | ||||||
|  | 								toAdd = 2; | ||||||
|  | 							} | ||||||
|  | 							default: | ||||||
|  | 							{ | ||||||
|  | 								toAdd = 3; | ||||||
|  | 							} | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 				SetEntProp(weapon, Prop_Send, "m_iClip1", GetEntProp(weapon, Prop_Send, "m_iClip1", 4, 0) + toAdd, 4, 0); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public Action:Command_Health(client, args) | ||||||
|  | { | ||||||
|  | 	if(args < 2) | ||||||
|  | 	{ | ||||||
|  | 		ReplyToCommand(client, "[SM] Usage: sm_hp <#userid|name> <value>"); | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	decl String:arg[65]; | ||||||
|  | 	GetCmdArg(1, arg, sizeof(arg)); | ||||||
|  | 
 | ||||||
|  | 	new amount = 0; | ||||||
|  | 	decl String:arg2[20]; | ||||||
|  | 	GetCmdArg(2, arg2, sizeof(arg2)); | ||||||
|  | 	if(StringToIntEx(arg2, amount) == 0 || amount <= 0) | ||||||
|  | 	{ | ||||||
|  | 		ReplyToCommand(client, "[SM] Invalid Value"); | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	decl String:target_name[MAX_TARGET_LENGTH]; | ||||||
|  | 	decl target_list[MAXPLAYERS], target_count, bool:tn_is_ml; | ||||||
|  | 
 | ||||||
|  | 	if((target_count = ProcessTargetString( | ||||||
|  | 			arg, | ||||||
|  | 			client, | ||||||
|  | 			target_list, | ||||||
|  | 			MAXPLAYERS, | ||||||
|  | 			COMMAND_FILTER_ALIVE, | ||||||
|  | 			target_name, | ||||||
|  | 			sizeof(target_name), | ||||||
|  | 			tn_is_ml)) <= 0) | ||||||
|  | 	{ | ||||||
|  | 		ReplyToTargetError(client, target_count); | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for(new i = 0; i < target_count; i++) | ||||||
|  | 	{ | ||||||
|  | 		SetEntProp(target_list[i], Prop_Send, "m_iHealth", amount, 1); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	ShowActivity2(client, "[SM] ", "Set health to %d on target %s", amount, target_name); | ||||||
|  | 
 | ||||||
|  | 	return Plugin_Handled; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public Action:Command_Kevlar(client, args) | ||||||
|  | { | ||||||
|  | 	if(args < 2) | ||||||
|  | 	{ | ||||||
|  | 		ReplyToCommand(client, "[SM] Usage: sm_kevlar <#userid|name> <value>"); | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	decl String:arg[65]; | ||||||
|  | 	GetCmdArg(1, arg, sizeof(arg)); | ||||||
|  | 
 | ||||||
|  | 	new amount = 0; | ||||||
|  | 	decl String:arg2[20]; | ||||||
|  | 	GetCmdArg(2, arg2, sizeof(arg2)); | ||||||
|  | 	if(StringToIntEx(arg2, amount) == 0 || amount <= 0) | ||||||
|  | 	{ | ||||||
|  | 		ReplyToCommand(client, "[SM] Invalid Value"); | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	decl String:target_name[MAX_TARGET_LENGTH]; | ||||||
|  | 	decl target_list[MAXPLAYERS], target_count, bool:tn_is_ml; | ||||||
|  | 
 | ||||||
|  | 	if((target_count = ProcessTargetString( | ||||||
|  | 			arg, | ||||||
|  | 			client, | ||||||
|  | 			target_list, | ||||||
|  | 			MAXPLAYERS, | ||||||
|  | 			COMMAND_FILTER_ALIVE, | ||||||
|  | 			target_name, | ||||||
|  | 			sizeof(target_name), | ||||||
|  | 			tn_is_ml)) <= 0) | ||||||
|  | 	{ | ||||||
|  | 		ReplyToTargetError(client, target_count); | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for(new i = 0; i < target_count; i++) | ||||||
|  | 	{ | ||||||
|  | 		SetEntProp(target_list[i], Prop_Send, "m_ArmorValue", amount, 1); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	ShowActivity2(client, "[SM] ", "Set kevlar to %d on target %s", amount, target_name); | ||||||
|  | 	LogAction(client, -1, "Set kevlar to %d on target %s", amount, target_name); | ||||||
|  | 
 | ||||||
|  | 	return Plugin_Handled; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public Action:Command_Weapon(client, args) | ||||||
|  | { | ||||||
|  | 	if(args < 2) | ||||||
|  | 	{ | ||||||
|  | 		ReplyToCommand(client, "[SM] Usage: sm_weapon <#userid|name> <weapon> [clip] [ammo]"); | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	new ammo = 2500; | ||||||
|  | 	new clip = -1; | ||||||
|  | 
 | ||||||
|  | 	decl String:arg[65]; | ||||||
|  | 	GetCmdArg(1, arg, sizeof(arg)); | ||||||
|  | 
 | ||||||
|  | 	decl String:arg2[65]; | ||||||
|  | 	GetCmdArg(2, arg2, sizeof(arg2)); | ||||||
|  | 
 | ||||||
|  | 	decl String:weapon[65]; | ||||||
|  | 	if(strncmp(arg2, "weapon_", 7) != 0 && strncmp(arg2, "item_", 5) != 0 && !StrEqual(arg2, "nvg", false)) | ||||||
|  | 		Format(weapon, sizeof(weapon), "weapon_%s", arg2); | ||||||
|  | 	else | ||||||
|  | 		strcopy(weapon, sizeof(weapon), arg2); | ||||||
|  | 
 | ||||||
|  | 	if(StrContains(weapon, "grenade", false) != -1 || StrContains(weapon, "flashbang", false) != -1 || strncmp(arg2, "item_", 5) == 0) | ||||||
|  | 		ammo = -1; | ||||||
|  | 
 | ||||||
|  | 	new AdminId:id = GetUserAdmin(client); | ||||||
|  | 	new superadmin = GetAdminFlag(id, Admin_Custom3); | ||||||
|  | 
 | ||||||
|  | 	if(!superadmin) | ||||||
|  | 	{ | ||||||
|  | 		if(StrEqual(weapon, "weapon_c4", false) || StrEqual(weapon, "weapon_smokegrenade", false) || StrEqual(weapon, "item_defuser", false)) | ||||||
|  | 		{ | ||||||
|  | 			ReplyToCommand(client, "[SM] This weapon is restricted!"); | ||||||
|  | 			return Plugin_Handled; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if(args >= 3) | ||||||
|  | 	{ | ||||||
|  | 		decl String:arg3[20]; | ||||||
|  | 		GetCmdArg(3, arg3, sizeof(arg3)); | ||||||
|  | 		if(StringToIntEx(arg3, clip) == 0) | ||||||
|  | 		{ | ||||||
|  | 			ReplyToCommand(client, "[SM] Invalid Clip Value"); | ||||||
|  | 			return Plugin_Handled; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	if(args >= 4) | ||||||
|  | 	{ | ||||||
|  | 		decl String:arg4[20]; | ||||||
|  | 		GetCmdArg(4, arg4, sizeof(arg4)); | ||||||
|  | 		if(StringToIntEx(arg4, ammo) == 0) | ||||||
|  | 		{ | ||||||
|  | 			ReplyToCommand(client, "[SM] Invalid Ammo Value"); | ||||||
|  | 			return Plugin_Handled; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if(StrContains(weapon, "grenade", false) != -1 || StrContains(weapon, "flashbang", false) != -1) | ||||||
|  | 	{ | ||||||
|  | 		new tmp = ammo; | ||||||
|  | 		ammo = clip; | ||||||
|  | 		clip = tmp; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	decl String:target_name[MAX_TARGET_LENGTH]; | ||||||
|  | 	decl target_list[MAXPLAYERS], target_count, bool:tn_is_ml; | ||||||
|  | 
 | ||||||
|  | 	if((target_count = ProcessTargetString( | ||||||
|  | 			arg, | ||||||
|  | 			client, | ||||||
|  | 			target_list, | ||||||
|  | 			MAXPLAYERS, | ||||||
|  | 			COMMAND_FILTER_ALIVE, | ||||||
|  | 			target_name, | ||||||
|  | 			sizeof(target_name), | ||||||
|  | 			tn_is_ml)) <= 0) | ||||||
|  | 	{ | ||||||
|  | 		ReplyToTargetError(client, target_count); | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if(StrEqual(weapon, "nvg", false)) | ||||||
|  | 	{ | ||||||
|  | 		for(new i = 0; i < target_count; i++) | ||||||
|  | 			SetEntProp(target_list[i], Prop_Send, "m_bHasNightVision", 1, 1); | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 		for(new i = 0; i < target_count; i++) | ||||||
|  | 		{ | ||||||
|  | 			new ent = GivePlayerItem(target_list[i], weapon); | ||||||
|  | 
 | ||||||
|  | 			if(ent == -1) { | ||||||
|  | 				ReplyToCommand(client, "[SM] Invalid Weapon"); | ||||||
|  | 				return Plugin_Handled; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			if(clip != -1) | ||||||
|  | 				SetEntProp(ent, Prop_Send, "m_iClip1", clip); | ||||||
|  | 
 | ||||||
|  | 			if(ammo != -1) | ||||||
|  | 			{ | ||||||
|  | 				new PrimaryAmmoType = GetEntProp(ent, Prop_Data, "m_iPrimaryAmmoType"); | ||||||
|  | 				if(PrimaryAmmoType != -1) | ||||||
|  | 					SetEntProp(target_list[i], Prop_Send, "m_iAmmo", ammo, _, PrimaryAmmoType); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			if(strncmp(arg2, "item_", 5) != 0 && !StrEqual(weapon, "weapon_hegrenade", false)) | ||||||
|  | 				EquipPlayerWeapon(target_list[i], ent); | ||||||
|  | 
 | ||||||
|  | 			if(ammo != -1) | ||||||
|  | 			{ | ||||||
|  | 				new PrimaryAmmoType = GetEntProp(ent, Prop_Data, "m_iPrimaryAmmoType"); | ||||||
|  | 				if(PrimaryAmmoType != -1) | ||||||
|  | 					SetEntProp(target_list[i], Prop_Send, "m_iAmmo", ammo, _, PrimaryAmmoType); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	ShowActivity2(client, "[SM] ", "Gave %s to target %s", weapon, target_name); | ||||||
|  | 	LogAction(client, -1, "Gave %s to target %s", weapon, target_name); | ||||||
|  | 
 | ||||||
|  | 	return Plugin_Handled; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public Action:Command_Strip(client, args) | ||||||
|  | { | ||||||
|  | 	if(args < 1) | ||||||
|  | 	{ | ||||||
|  | 		ReplyToCommand(client, "[SM] Usage: sm_strip <#userid|name>"); | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	decl String:arg[65]; | ||||||
|  | 	GetCmdArg(1, arg, sizeof(arg)); | ||||||
|  | 
 | ||||||
|  | 	decl String:target_name[MAX_TARGET_LENGTH]; | ||||||
|  | 	decl target_list[MAXPLAYERS], target_count, bool:tn_is_ml; | ||||||
|  | 
 | ||||||
|  | 	if((target_count = ProcessTargetString( | ||||||
|  | 			arg, | ||||||
|  | 			client, | ||||||
|  | 			target_list, | ||||||
|  | 			MAXPLAYERS, | ||||||
|  | 			COMMAND_FILTER_ALIVE, | ||||||
|  | 			target_name, | ||||||
|  | 			sizeof(target_name), | ||||||
|  | 			tn_is_ml)) <= 0) | ||||||
|  | 	{ | ||||||
|  | 		ReplyToTargetError(client, target_count); | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for(new i = 0; i < target_count; i++) | ||||||
|  | 	{ | ||||||
|  | 		for(new j = 0; j < 5; j++) | ||||||
|  | 		{ | ||||||
|  | 			new w = -1; | ||||||
|  | 			while ((w = GetPlayerWeaponSlot(target_list[i], j)) != -1) | ||||||
|  | 			{ | ||||||
|  | 				if(IsValidEntity(w)) | ||||||
|  | 					RemovePlayerItem(target_list[i], w); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	ShowActivity2(client, "[SM] ", "Stripped all weapons on target %s", target_name); | ||||||
|  | 	LogAction(client, -1, "Stripped all weapons on target %s", target_name); | ||||||
|  | 
 | ||||||
|  | 	return Plugin_Handled; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public Action:Command_BuyZone(client, args) | ||||||
|  | { | ||||||
|  | 	if(args < 2) | ||||||
|  | 	{ | ||||||
|  | 		ReplyToCommand(client, "[SM] Usage: sm_buyzone <#userid|name> <0|1>"); | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	decl String:arg[65]; | ||||||
|  | 	GetCmdArg(1, arg, sizeof(arg)); | ||||||
|  | 
 | ||||||
|  | 	new value = -1; | ||||||
|  | 	decl String:arg2[20]; | ||||||
|  | 	GetCmdArg(2, arg2, sizeof(arg2)); | ||||||
|  | 	if(StringToIntEx(arg2, value) == 0) | ||||||
|  | 	{ | ||||||
|  | 		ReplyToCommand(client, "[SM] Invalid Value"); | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	decl String:target_name[MAX_TARGET_LENGTH]; | ||||||
|  | 
 | ||||||
|  | 	if(StrEqual(arg, "@all", false)) | ||||||
|  | 	{ | ||||||
|  | 		target_name = "all players"; | ||||||
|  | 		g_bInBuyZoneAll = value ? true : false; | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 		decl target_list[MAXPLAYERS], target_count, bool:tn_is_ml; | ||||||
|  | 
 | ||||||
|  | 		if((target_count = ProcessTargetString( | ||||||
|  | 				arg, | ||||||
|  | 				client, | ||||||
|  | 				target_list, | ||||||
|  | 				MAXPLAYERS, | ||||||
|  | 				COMMAND_FILTER_ALIVE, | ||||||
|  | 				target_name, | ||||||
|  | 				sizeof(target_name), | ||||||
|  | 				tn_is_ml)) <= 0) | ||||||
|  | 		{ | ||||||
|  | 			ReplyToTargetError(client, target_count); | ||||||
|  | 			return Plugin_Handled; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		for(new i = 0; i < target_count; i++) | ||||||
|  | 		{ | ||||||
|  | 			g_bInBuyZone[target_list[i]] = value ? true : false; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	ShowActivity2(client, "[SM] ", "%s permanent buyzone on target %s", (value ? "Enabled" : "Disabled"), target_name); | ||||||
|  | 	LogAction(client, -1, "%s permanent buyzone on target %s", (value ? "Enabled" : "Disabled"), target_name); | ||||||
|  | 
 | ||||||
|  | 	return Plugin_Handled; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public Action:Command_InfAmmo(client, args) | ||||||
|  | { | ||||||
|  | 	if(args < 2) | ||||||
|  | 	{ | ||||||
|  | 		ReplyToCommand(client, "[SM] Usage: sm_iammo <#userid|name> <0|1>"); | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	decl String:arg[65]; | ||||||
|  | 	GetCmdArg(1, arg, sizeof(arg)); | ||||||
|  | 
 | ||||||
|  | 	new value = -1; | ||||||
|  | 	decl String:arg2[20]; | ||||||
|  | 	GetCmdArg(2, arg2, sizeof(arg2)); | ||||||
|  | 	if(StringToIntEx(arg2, value) == 0) | ||||||
|  | 	{ | ||||||
|  | 		ReplyToCommand(client, "[SM] Invalid Value"); | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	decl String:target_name[MAX_TARGET_LENGTH]; | ||||||
|  | 
 | ||||||
|  | 	if(StrEqual(arg, "@all", false)) | ||||||
|  | 	{ | ||||||
|  | 		target_name = "all players"; | ||||||
|  | 		g_bInfAmmoAll = value ? true : false; | ||||||
|  | 
 | ||||||
|  | 		if(!g_bInfAmmoAll) | ||||||
|  | 		{ | ||||||
|  | 			for(new i = 0; i < MAXPLAYERS; i++) | ||||||
|  | 				g_bInfAmmo[i] = false; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 		decl target_list[MAXPLAYERS], target_count, bool:tn_is_ml; | ||||||
|  | 
 | ||||||
|  | 		if((target_count = ProcessTargetString( | ||||||
|  | 				arg, | ||||||
|  | 				client, | ||||||
|  | 				target_list, | ||||||
|  | 				MAXPLAYERS, | ||||||
|  | 				COMMAND_FILTER_ALIVE, | ||||||
|  | 				target_name, | ||||||
|  | 				sizeof(target_name), | ||||||
|  | 				tn_is_ml)) <= 0) | ||||||
|  | 		{ | ||||||
|  | 			ReplyToTargetError(client, target_count); | ||||||
|  | 			return Plugin_Handled; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		for(new i = 0; i < target_count; i++) | ||||||
|  | 		{ | ||||||
|  | 			g_bInfAmmo[target_list[i]] = value ? true : false; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	ShowActivity2(client, "[SM] ", "%s infinite ammo on target %s", (value ? "Enabled" : "Disabled"), target_name); | ||||||
|  | 	LogAction(client, -1, "%s infinite ammo on target %s", (value ? "Enabled" : "Disabled"), target_name); | ||||||
|  | 
 | ||||||
|  | 	if(g_bInfAmmoAll) | ||||||
|  | 	{ | ||||||
|  | 		if(!g_bInfAmmoHooked) | ||||||
|  | 		{ | ||||||
|  | 			HookEvent("weapon_fire", Event_WeaponFire); | ||||||
|  | 			g_bInfAmmoHooked = true; | ||||||
|  | 		} | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for(new i = 0; i < MAXPLAYERS; i++) | ||||||
|  | 	{ | ||||||
|  | 		if(g_bInfAmmo[i]) | ||||||
|  | 		{ | ||||||
|  | 			if(!g_bInfAmmoHooked) | ||||||
|  | 			{ | ||||||
|  | 				HookEvent("weapon_fire", Event_WeaponFire); | ||||||
|  | 				g_bInfAmmoHooked = true; | ||||||
|  | 			} | ||||||
|  | 			return Plugin_Handled; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if(g_bInfAmmoHooked) | ||||||
|  | 	{ | ||||||
|  | 		UnhookEvent("weapon_fire", Event_WeaponFire); | ||||||
|  | 		g_bInfAmmoHooked = false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return Plugin_Handled; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public Action:Command_Speed(client, args) | ||||||
|  | { | ||||||
|  | 	if(args < 2) | ||||||
|  | 	{ | ||||||
|  | 		ReplyToCommand(client, "[SM] Usage: sm_speed <#userid|name> <value>"); | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	decl String:arg[65]; | ||||||
|  | 	GetCmdArg(1, arg, sizeof(arg)); | ||||||
|  | 
 | ||||||
|  | 	new Float:speed = 0.0; | ||||||
|  | 	decl String:arg2[20]; | ||||||
|  | 	GetCmdArg(2, arg2, sizeof(arg2)); | ||||||
|  | 	if(StringToFloatEx(arg2, speed) == 0 || speed <= 0.0) | ||||||
|  | 	{ | ||||||
|  | 		ReplyToCommand(client, "[SM] Invalid Value"); | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	decl String:target_name[MAX_TARGET_LENGTH]; | ||||||
|  | 	decl target_list[MAXPLAYERS], target_count, bool:tn_is_ml; | ||||||
|  | 
 | ||||||
|  | 	if((target_count = ProcessTargetString( | ||||||
|  | 			arg, | ||||||
|  | 			client, | ||||||
|  | 			target_list, | ||||||
|  | 			MAXPLAYERS, | ||||||
|  | 			COMMAND_FILTER_ALIVE, | ||||||
|  | 			target_name, | ||||||
|  | 			sizeof(target_name), | ||||||
|  | 			tn_is_ml)) <= 0) | ||||||
|  | 	{ | ||||||
|  | 		ReplyToTargetError(client, target_count); | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for(new i = 0; i < target_count; i++) | ||||||
|  | 	{ | ||||||
|  | 		SetEntPropFloat(target_list[i], Prop_Data, "m_flLaggedMovementValue", speed); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	ShowActivity2(client, "[SM] ", "Set speed to %.2f on target %s", speed, target_name); | ||||||
|  | 	LogAction(client, -1, "Set speed to %.2f on target %s", speed, target_name); | ||||||
|  | 
 | ||||||
|  | 	return Plugin_Handled; | ||||||
|  | } | ||||||
							
								
								
									
										50
									
								
								FixGameUI/gamedata/FixGameUI.games.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								FixGameUI/gamedata/FixGameUI.games.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,50 @@ | |||||||
|  | "Games" | ||||||
|  | { | ||||||
|  | 	"#default" | ||||||
|  | 	{ | ||||||
|  | 		"#supported" | ||||||
|  | 		{ | ||||||
|  | 			"game"		"cstrike" | ||||||
|  | 			"game"		"tf" | ||||||
|  | 			"game"		"dod" | ||||||
|  | 			"game"		"hl2mp" | ||||||
|  | 			"engine"	"sdk2013" | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		"Offsets" | ||||||
|  | 		{ | ||||||
|  | 			"AcceptInput" | ||||||
|  | 			{ | ||||||
|  | 				"windows"	"36" | ||||||
|  | 				"linux"		"37" | ||||||
|  | 				"mac"		"37" | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"csgo" | ||||||
|  | 	{ | ||||||
|  | 		"Offsets" | ||||||
|  | 		{ | ||||||
|  | 			"AcceptInput" | ||||||
|  | 			{ | ||||||
|  | 				"windows"	"40" | ||||||
|  | 				"linux"		"41" | ||||||
|  | 				"mac"		"41" | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"left4dead2" | ||||||
|  | 	{ | ||||||
|  | 		"Offsets" | ||||||
|  | 		{ | ||||||
|  | 			"AcceptInput" | ||||||
|  | 			{ | ||||||
|  | 				"windows"	"43" | ||||||
|  | 				"linux"		"44" | ||||||
|  | 				"mac"		"44" | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										128
									
								
								FixGameUI/scripting/FixGameUI.sp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								FixGameUI/scripting/FixGameUI.sp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,128 @@ | |||||||
|  | #pragma semicolon 1 | ||||||
|  | 
 | ||||||
|  | #include <sourcemod> | ||||||
|  | #include <sdktools_entoutput> | ||||||
|  | #include <sdktools_entinput> | ||||||
|  | #include <sdktools_engine> | ||||||
|  | #include <sdkhooks> | ||||||
|  | #include <dhooks> | ||||||
|  | 
 | ||||||
|  | public Plugin:myinfo = | ||||||
|  | { | ||||||
|  | 	name = "FixGameUI", | ||||||
|  | 	author = "hlstriker + GoD-Tony", | ||||||
|  | 	description = "Fixes game_ui entity bug.", | ||||||
|  | 	version = "1.0", | ||||||
|  | 	url = "" | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | new g_iAttachedGameUI[MAXPLAYERS+1]; | ||||||
|  | new Handle:g_hAcceptInput = INVALID_HANDLE; | ||||||
|  | 
 | ||||||
|  | public OnPluginStart() | ||||||
|  | { | ||||||
|  | 	HookEvent("player_death", Event_PlayerDeath, EventHookMode_Post); | ||||||
|  | 
 | ||||||
|  | 	HookEntityOutput("game_ui", "PlayerOn", GameUI_PlayerOn); | ||||||
|  | 	HookEntityOutput("game_ui", "PlayerOff", GameUI_PlayerOff); | ||||||
|  | 
 | ||||||
|  | 	// Gamedata. | ||||||
|  | 	new Handle:hConfig = LoadGameConfigFile("FixGameUI.games"); | ||||||
|  | 	if (hConfig == INVALID_HANDLE) | ||||||
|  | 	{ | ||||||
|  | 		SetFailState("Could not find gamedata file: FixGameUI.games.txt"); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	new offset = GameConfGetOffset(hConfig, "AcceptInput"); | ||||||
|  | 	if (offset == -1) | ||||||
|  | 	{ | ||||||
|  | 		SetFailState("Failed to find AcceptInput offset"); | ||||||
|  | 	} | ||||||
|  | 	CloseHandle(hConfig); | ||||||
|  | 
 | ||||||
|  | 	// DHooks. | ||||||
|  | 	g_hAcceptInput = DHookCreate(offset, HookType_Entity, ReturnType_Bool, ThisPointer_CBaseEntity, Hook_AcceptInput); | ||||||
|  | 	DHookAddParam(g_hAcceptInput, HookParamType_CharPtr); | ||||||
|  | 	DHookAddParam(g_hAcceptInput, HookParamType_CBaseEntity); | ||||||
|  | 	DHookAddParam(g_hAcceptInput, HookParamType_CBaseEntity); | ||||||
|  | 	DHookAddParam(g_hAcceptInput, HookParamType_Object, 20); //varaint_t is a union of 12 (float[3]) plus two int type params 12 + 8 = 20 | ||||||
|  | 	DHookAddParam(g_hAcceptInput, HookParamType_Int); | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public Action:Event_PlayerDeath(Handle:hEvent, const String:szName[], bool:bDontBroadcast) | ||||||
|  | { | ||||||
|  | 	new iClient = GetClientOfUserId(GetEventInt(hEvent, "userid")); | ||||||
|  | 	RemoveFromGameUI(iClient); | ||||||
|  | 	SetClientViewEntity(iClient, iClient); | ||||||
|  | 
 | ||||||
|  | 	new iFlags = GetEntityFlags(iClient); | ||||||
|  | 	iFlags &= ~FL_ONTRAIN; | ||||||
|  | 	iFlags &= ~FL_FROZEN; | ||||||
|  | 	iFlags &= ~FL_ATCONTROLS; | ||||||
|  | 	SetEntityFlags(iClient, iFlags); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public OnClientDisconnect(iClient) | ||||||
|  | { | ||||||
|  | 	RemoveFromGameUI(iClient); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public GameUI_PlayerOn(const String:szOutput[], iCaller, iActivator, Float:fDelay) | ||||||
|  | { | ||||||
|  | 	if(!(1 <= iActivator <= MaxClients)) | ||||||
|  | 		return; | ||||||
|  | 
 | ||||||
|  | 	g_iAttachedGameUI[iActivator] = EntIndexToEntRef(iCaller); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public GameUI_PlayerOff(const String:szOutput[], iCaller, iActivator, Float:fDelay) | ||||||
|  | { | ||||||
|  | 	if(!(1 <= iActivator <= MaxClients)) | ||||||
|  | 		return; | ||||||
|  | 
 | ||||||
|  | 	g_iAttachedGameUI[iActivator] = 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | RemoveFromGameUI(iClient) | ||||||
|  | { | ||||||
|  | 	if(!g_iAttachedGameUI[iClient]) | ||||||
|  | 		return; | ||||||
|  | 
 | ||||||
|  | 	new iEnt = EntRefToEntIndex(g_iAttachedGameUI[iClient]); | ||||||
|  | 	if(iEnt == INVALID_ENT_REFERENCE) | ||||||
|  | 		return; | ||||||
|  | 
 | ||||||
|  | 	AcceptEntityInput(iEnt, "Deactivate", iClient, iEnt); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public OnEntityCreated(entity, const String:classname[]) | ||||||
|  | { | ||||||
|  | 	if (StrEqual(classname, "game_ui")) | ||||||
|  | 	{ | ||||||
|  | 		DHookEntity(g_hAcceptInput, false, entity); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public MRESReturn:Hook_AcceptInput(thisptr, Handle:hReturn, Handle:hParams) | ||||||
|  | { | ||||||
|  | 	new String:sCommand[128]; | ||||||
|  | 	DHookGetParamString(hParams, 1, sCommand, sizeof(sCommand)); | ||||||
|  | 
 | ||||||
|  | 	if (StrEqual(sCommand, "Deactivate")) | ||||||
|  | 	{ | ||||||
|  | 		new pPlayer = GetEntPropEnt(thisptr, Prop_Data, "m_player"); | ||||||
|  | 
 | ||||||
|  | 		if (pPlayer == -1) | ||||||
|  | 		{ | ||||||
|  | 			// Manually disable think. | ||||||
|  | 			SetEntProp(thisptr, Prop_Data, "m_nNextThinkTick", -1); | ||||||
|  | 
 | ||||||
|  | 			DHookSetReturn(hReturn, false); | ||||||
|  | 			return MRES_Supercede; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	DHookSetReturn(hReturn, true); | ||||||
|  | 	return MRES_Ignored; | ||||||
|  | } | ||||||
							
								
								
									
										1
									
								
								FixGameUI/scripting/includes/dhooks.inc
									
									
									
									
									
										Symbolic link
									
								
							
							
						
						
									
										1
									
								
								FixGameUI/scripting/includes/dhooks.inc
									
									
									
									
									
										Symbolic link
									
								
							| @ -0,0 +1 @@ | |||||||
|  | ../../../includes/dhooks.inc | ||||||
							
								
								
									
										44
									
								
								Flashlight/scripting/Flashlight.sp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								Flashlight/scripting/Flashlight.sp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,44 @@ | |||||||
|  | #pragma semicolon 1 | ||||||
|  | 
 | ||||||
|  | #include <sourcemod> | ||||||
|  | #include <sdktools> | ||||||
|  | 
 | ||||||
|  | #pragma newdecls required | ||||||
|  | #define PLUGIN_VERSION "1.0" | ||||||
|  | public Plugin myinfo = | ||||||
|  | { | ||||||
|  | 	name 			= "Flashlight", | ||||||
|  | 	author 			= "BotoX", | ||||||
|  | 	description 	= "Dead flashlight, block sound from other clients.", | ||||||
|  | 	version 		= PLUGIN_VERSION, | ||||||
|  | 	url 			= "" | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | public void OnPluginStart() | ||||||
|  | { | ||||||
|  | 	AddNormalSoundHook(OnSound); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public Action OnSound(int clients[64], int &numClients, char sample[PLATFORM_MAX_PATH], int &entity, int &channel, float &volume, int &level, int &pitch, int &flags) | ||||||
|  | { | ||||||
|  | 	if(entity >= 1 && entity <= MAXPLAYERS && StrEqual(sample, "items/flashlight1.wav", false)) | ||||||
|  | 	{ | ||||||
|  | 		numClients = 1; | ||||||
|  | 		clients[0] = entity; | ||||||
|  | 		return Plugin_Changed; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return Plugin_Continue; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public Action OnPlayerRunCmd(int client, int &buttons, int &impulse, float vel[3], float angles[3], int &weapon, int &subtype, int &cmdnum, int &tickcount, int &seed, int mouse[2]) | ||||||
|  | { | ||||||
|  | 	// Dead flashlight | ||||||
|  | 	if(impulse == 100 && !IsPlayerAlive(client)) | ||||||
|  | 	{ | ||||||
|  | 		SetEntProp(client, Prop_Send, "m_fEffects", GetEntProp(client, Prop_Send, "m_fEffects") ^ 4); | ||||||
|  | 		ClientCommand(client, "playgamesound \"items/flashlight1.wav\""); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return Plugin_Continue; | ||||||
|  | } | ||||||
							
								
								
									
										112
									
								
								ForceInputs/scripting/ForceInputs.sp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								ForceInputs/scripting/ForceInputs.sp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,112 @@ | |||||||
|  | //==================================================================================================== | ||||||
|  | // | ||||||
|  | // Name: ForceInput | ||||||
|  | // Author: zaCade | ||||||
|  | // Description: Allows admins to force inputs on entities. (ent_fire) | ||||||
|  | // | ||||||
|  | //==================================================================================================== | ||||||
|  | #include <sourcemod> | ||||||
|  | #include <sdktools> | ||||||
|  | 
 | ||||||
|  | //---------------------------------------------------------------------------------------------------- | ||||||
|  | // Purpose: | ||||||
|  | //---------------------------------------------------------------------------------------------------- | ||||||
|  | public Plugin:myinfo = | ||||||
|  | { | ||||||
|  | 	name 			= "ForceInput", | ||||||
|  | 	author 			= "zaCade", | ||||||
|  | 	description 	= "Allows admins to force inputs on entities. (ent_fire)", | ||||||
|  | 	version 		= "1.2", | ||||||
|  | 	url 			= "" | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | //---------------------------------------------------------------------------------------------------- | ||||||
|  | // Purpose: | ||||||
|  | //---------------------------------------------------------------------------------------------------- | ||||||
|  | public OnPluginStart() | ||||||
|  | { | ||||||
|  | 	RegAdminCmd("sm_forceinput", Command_ForceInput, ADMFLAG_ROOT); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | //---------------------------------------------------------------------------------------------------- | ||||||
|  | // Purpose: | ||||||
|  | //---------------------------------------------------------------------------------------------------- | ||||||
|  | public Action:Command_ForceInput(client, args) | ||||||
|  | { | ||||||
|  | 	if (GetCmdArgs() < 2) | ||||||
|  | 	{ | ||||||
|  | 		ReplyToCommand(client, "[SM] Usage: sm_forceinput <classname/targetname> <input> [parameter]"); | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	new String:sArguments[3][256]; | ||||||
|  | 	GetCmdArg(1, sArguments[0], sizeof(sArguments[])); | ||||||
|  | 	GetCmdArg(2, sArguments[1], sizeof(sArguments[])); | ||||||
|  | 	GetCmdArg(3, sArguments[2], sizeof(sArguments[])); | ||||||
|  | 
 | ||||||
|  | 	if (StrEqual(sArguments[0], "!self")) | ||||||
|  | 	{ | ||||||
|  | 		if (strlen(sArguments[2])) | ||||||
|  | 			SetVariantString(sArguments[2]); | ||||||
|  | 
 | ||||||
|  | 		AcceptEntityInput(client, sArguments[1], client, client); | ||||||
|  | 		ReplyToCommand(client, "[SM] Input succesfull."); | ||||||
|  | 	} | ||||||
|  | 	else if (StrEqual(sArguments[0], "!target")) | ||||||
|  | 	{ | ||||||
|  | 		new entity = INVALID_ENT_REFERENCE; | ||||||
|  | 
 | ||||||
|  | 		new Float:fPosition[3], Float:fAngles[3]; | ||||||
|  | 		GetClientEyePosition(client, fPosition); | ||||||
|  | 		GetClientEyeAngles(client, fAngles); | ||||||
|  | 
 | ||||||
|  | 		new Handle:hTrace = TR_TraceRayFilterEx(fPosition, fAngles, MASK_SOLID, RayType_Infinite, TraceRayFilter, client); | ||||||
|  | 
 | ||||||
|  | 		if (TR_DidHit(hTrace) && ((entity = TR_GetEntityIndex(hTrace)) >= 1)) | ||||||
|  | 		{ | ||||||
|  | 			if (IsValidEntity(entity) || IsValidEdict(entity)) | ||||||
|  | 			{ | ||||||
|  | 				if (strlen(sArguments[2])) | ||||||
|  | 					SetVariantString(sArguments[2]); | ||||||
|  | 
 | ||||||
|  | 				AcceptEntityInput(entity, sArguments[1], client, client); | ||||||
|  | 				ReplyToCommand(client, "[SM] Input succesfull."); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 		new entity = INVALID_ENT_REFERENCE; | ||||||
|  | 
 | ||||||
|  | 		while ((entity = FindEntityByClassname(entity, "*")) != INVALID_ENT_REFERENCE) | ||||||
|  | 		{ | ||||||
|  | 			if (IsValidEntity(entity) || IsValidEdict(entity)) | ||||||
|  | 			{ | ||||||
|  | 				new String:sClassname[64], String:sTargetname[64]; | ||||||
|  | 				GetEntPropString(entity, Prop_Data, "m_iClassname", sClassname, sizeof(sClassname)); | ||||||
|  | 				GetEntPropString(entity, Prop_Data, "m_iName", sTargetname, sizeof(sTargetname)); | ||||||
|  | 
 | ||||||
|  | 				if (StrEqual(sClassname, sArguments[0], false) || StrEqual(sTargetname, sArguments[0], false)) | ||||||
|  | 				{ | ||||||
|  | 					if (strlen(sArguments[2])) | ||||||
|  | 						SetVariantString(sArguments[2]); | ||||||
|  | 
 | ||||||
|  | 					AcceptEntityInput(entity, sArguments[1], client, client); | ||||||
|  | 					ReplyToCommand(client, "[SM] Input succesfull."); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return Plugin_Handled; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | //---------------------------------------------------------------------------------------------------- | ||||||
|  | // Purpose: | ||||||
|  | //---------------------------------------------------------------------------------------------------- | ||||||
|  | public bool:TraceRayFilter(entity, mask, any:client) | ||||||
|  | { | ||||||
|  | 	if (entity == client) | ||||||
|  | 		return false; | ||||||
|  | 
 | ||||||
|  | 	return true; | ||||||
|  | } | ||||||
							
								
								
									
										44
									
								
								KevlarEquip/scripting/KevlarEquip.sp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								KevlarEquip/scripting/KevlarEquip.sp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,44 @@ | |||||||
|  | #pragma semicolon 1 | ||||||
|  | 
 | ||||||
|  | #include <sourcemod> | ||||||
|  | #include <sdkhooks> | ||||||
|  | #include <zombiereloaded> | ||||||
|  | 
 | ||||||
|  | public Plugin:myinfo = | ||||||
|  | { | ||||||
|  | 	name 			= "KevlarEquip", | ||||||
|  | 	author 			= "BotoX", | ||||||
|  | 	description 	= "Equip players with kevlar when they spawn, unglitch kevlar and strip it when you get infected", | ||||||
|  | 	version 		= "2.0", | ||||||
|  | 	url 			= "" | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | public OnClientPutInServer(client) | ||||||
|  | { | ||||||
|  | 	SDKHook(client, SDKHook_SpawnPost, Hook_OnPlayerSpawn); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public Hook_OnPlayerSpawn(client) | ||||||
|  | { | ||||||
|  | 	if(IsPlayerAlive(client) && ZR_IsClientHuman(client)) | ||||||
|  | 	{ | ||||||
|  | 		SetEntProp(client, Prop_Send, "m_ArmorValue", 100, 1); | ||||||
|  | 		SetEntProp(client, Prop_Send, "m_bHasHelmet", 1); | ||||||
|  | 		// Reset last hitgroup to generic - fixes kevlar bug | ||||||
|  | 		// Example: You get hit in the head by a bullet as a zombie | ||||||
|  | 		// the round ends, you spawn as a human. | ||||||
|  | 		// You get damaged by a trigger, the game still thinks you | ||||||
|  | 		// are getting damaged in the head hitgroup, >mfw source engine. | ||||||
|  | 		// Thanks to leaked 2007 Source Engine Code. | ||||||
|  | 		SetEntData(client, 4444, 0, 4); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public ZR_OnClientInfected(client, attacker, bool:motherInfect, bool:respawnOverride, bool:respawn) | ||||||
|  | { | ||||||
|  | 	if(IsPlayerAlive(client)) | ||||||
|  | 	{ | ||||||
|  | 		SetEntProp(client, Prop_Send, "m_ArmorValue", 0, 1); | ||||||
|  | 		SetEntProp(client, Prop_Send, "m_bHasHelmet", 0); | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										28
									
								
								NapalmLagFix/gamedata/napalmlagfix.games.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								NapalmLagFix/gamedata/napalmlagfix.games.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,28 @@ | |||||||
|  | "Games" | ||||||
|  | { | ||||||
|  | 	"cstrike" | ||||||
|  | 	{ | ||||||
|  | 		"Offsets" | ||||||
|  | 		{ | ||||||
|  | 			"RadiusDamage" | ||||||
|  | 			{ | ||||||
|  | 				"windows"	"68" | ||||||
|  | 				"linux"		"69" | ||||||
|  | 				"mac"		"69" | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	"csgo" | ||||||
|  | 	{ | ||||||
|  | 		"Offsets" | ||||||
|  | 		{ | ||||||
|  | 			"RadiusDamage" | ||||||
|  | 			{ | ||||||
|  | 				"windows"	"68" | ||||||
|  | 				"linux"		"69" | ||||||
|  | 				"mac"		"69" | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										118
									
								
								NapalmLagFix/scripting/NapalmLagFix.sp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								NapalmLagFix/scripting/NapalmLagFix.sp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,118 @@ | |||||||
|  | #pragma semicolon 1 | ||||||
|  | 
 | ||||||
|  | #include <sourcemod> | ||||||
|  | #include <dhooks> | ||||||
|  | #undef REQUIRE_PLUGIN | ||||||
|  | #include <updater> | ||||||
|  | 
 | ||||||
|  | #define PLUGIN_NAME 	"Napalm Lag Fix" | ||||||
|  | #define PLUGIN_VERSION 	"1.0.3" | ||||||
|  | 
 | ||||||
|  | #define UPDATE_URL	"http://godtony.mooo.com/napalmlagfix/napalmlagfix.txt" | ||||||
|  | 
 | ||||||
|  | #define DMG_BURN	(1 << 3) | ||||||
|  | 
 | ||||||
|  | new Handle:g_hRadiusDamage = INVALID_HANDLE; | ||||||
|  | new bool:g_bCheckNullPtr = false; | ||||||
|  | 
 | ||||||
|  | public Plugin:myinfo = | ||||||
|  | { | ||||||
|  | 	name = PLUGIN_NAME, | ||||||
|  | 	author = "GoD-Tony + BotoX", | ||||||
|  | 	description = "Prevents lag when napalm is used on players", | ||||||
|  | 	version = PLUGIN_VERSION, | ||||||
|  | 	url = "https://forums.alliedmods.net/showthread.php?t=188093" // Demo: http://youtu.be/YdhAu5IEVVM | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | public APLRes:AskPluginLoad2(Handle:myself, bool:late, String:error[], err_max) | ||||||
|  | { | ||||||
|  | 	MarkNativeAsOptional("DHookIsNullParam"); | ||||||
|  | 
 | ||||||
|  | 	return APLRes_Success; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public OnPluginStart() | ||||||
|  | { | ||||||
|  | 	// Convars. | ||||||
|  | 	new Handle:hCvar = CreateConVar("sm_napalmlagfix_version", PLUGIN_VERSION, PLUGIN_NAME, FCVAR_PLUGIN|FCVAR_NOTIFY|FCVAR_DONTRECORD); | ||||||
|  | 	SetConVarString(hCvar, PLUGIN_VERSION); | ||||||
|  | 
 | ||||||
|  | 	// Gamedata. | ||||||
|  | 	new Handle:hConfig = LoadGameConfigFile("napalmlagfix.games"); | ||||||
|  | 
 | ||||||
|  | 	if (hConfig == INVALID_HANDLE) | ||||||
|  | 	{ | ||||||
|  | 		SetFailState("Could not find gamedata file: napalmlagfix.games.txt"); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	new offset = GameConfGetOffset(hConfig, "RadiusDamage"); | ||||||
|  | 
 | ||||||
|  | 	if (offset == -1) | ||||||
|  | 	{ | ||||||
|  | 		SetFailState("Failed to find RadiusDamage offset"); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	CloseHandle(hConfig); | ||||||
|  | 
 | ||||||
|  | 	// DHooks. | ||||||
|  | 	g_bCheckNullPtr = (GetFeatureStatus(FeatureType_Native, "DHookIsNullParam") == FeatureStatus_Available); | ||||||
|  | 
 | ||||||
|  | 	g_hRadiusDamage = DHookCreate(offset, HookType_GameRules, ReturnType_Void, ThisPointer_Ignore, Hook_RadiusDamage); | ||||||
|  | 	DHookAddParam(g_hRadiusDamage, HookParamType_ObjectPtr);	// 1 - CTakeDamageInfo &info | ||||||
|  | 	DHookAddParam(g_hRadiusDamage, HookParamType_VectorPtr);	// 2 - Vector &vecSrc | ||||||
|  | 	DHookAddParam(g_hRadiusDamage, HookParamType_Float);		// 3 - float flRadius | ||||||
|  | 	DHookAddParam(g_hRadiusDamage, HookParamType_Int);			// 4 - int iClassIgnore | ||||||
|  | 	DHookAddParam(g_hRadiusDamage, HookParamType_CBaseEntity);	// 5 - CBaseEntity *pEntityIgnore | ||||||
|  | 
 | ||||||
|  | 	// Updater. | ||||||
|  | 	if (LibraryExists("updater")) | ||||||
|  | 	{ | ||||||
|  | 		Updater_AddPlugin(UPDATE_URL); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public OnLibraryAdded(const String:name[]) | ||||||
|  | { | ||||||
|  | 	if (StrEqual(name, "updater")) | ||||||
|  | 	{ | ||||||
|  | 		Updater_AddPlugin(UPDATE_URL); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public Updater_OnPluginUpdated() | ||||||
|  | { | ||||||
|  | 	// There could be new gamedata in this update. | ||||||
|  | 	ReloadPlugin(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public OnMapStart() | ||||||
|  | { | ||||||
|  | 	DHookGamerules(g_hRadiusDamage, false); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public MRESReturn:Hook_RadiusDamage(Handle:hParams) | ||||||
|  | { | ||||||
|  | 	// As of DHooks 1.0.12 we must check for a null param. | ||||||
|  | 	if (g_bCheckNullPtr && DHookIsNullParam(hParams, 5)) | ||||||
|  | 		return MRES_Ignored; | ||||||
|  | 
 | ||||||
|  | 	new iDmgBits = DHookGetParamObjectPtrVar(hParams, 1, 60, ObjectValueType_Int); | ||||||
|  | 	new iEntIgnore = DHookGetParam(hParams, 5); | ||||||
|  | 
 | ||||||
|  | 	if(!(iDmgBits & DMG_BURN)) | ||||||
|  | 		return MRES_Ignored; | ||||||
|  | 
 | ||||||
|  | 	// Block napalm damage if it's coming from another client. | ||||||
|  | 	if (1 <= iEntIgnore <= MaxClients) | ||||||
|  | 		return MRES_Supercede; | ||||||
|  | 
 | ||||||
|  | 	// Block napalm that comes from grenades | ||||||
|  | 	new String:sEntClassName[64]; | ||||||
|  | 	if(GetEntityClassname(iEntIgnore, sEntClassName, sizeof(sEntClassName))) | ||||||
|  | 	{ | ||||||
|  | 		if(!strcmp(sEntClassName, "hegrenade_projectile")) | ||||||
|  | 			return MRES_Supercede; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return MRES_Ignored; | ||||||
|  | } | ||||||
							
								
								
									
										1
									
								
								NapalmLagFix/scripting/include/dhooks.inc
									
									
									
									
									
										Symbolic link
									
								
							
							
						
						
									
										1
									
								
								NapalmLagFix/scripting/include/dhooks.inc
									
									
									
									
									
										Symbolic link
									
								
							| @ -0,0 +1 @@ | |||||||
|  | ../../../includes/dhooks.inc | ||||||
							
								
								
									
										15
									
								
								NoGrenadeRinging/gamedata/NoGrenadeRinging.games.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								NoGrenadeRinging/gamedata/NoGrenadeRinging.games.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | |||||||
|  | "Games" | ||||||
|  | { | ||||||
|  | 	"cstrike" | ||||||
|  | 	{ | ||||||
|  | 		"Offsets" | ||||||
|  | 		{ | ||||||
|  | 			"OnDamagedByExplosion" | ||||||
|  | 			{ | ||||||
|  | 				"windows"	"335" | ||||||
|  | 				"linux"		"336" | ||||||
|  | 				"mac"		"336" | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										42
									
								
								NoGrenadeRinging/scripting/NoGrenadeRinging.sp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								NoGrenadeRinging/scripting/NoGrenadeRinging.sp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,42 @@ | |||||||
|  | #pragma semicolon 1 | ||||||
|  | #include <sourcemod> | ||||||
|  | #include <sdktools> | ||||||
|  | #include <dhooks> | ||||||
|  | 
 | ||||||
|  | //int CCSPlayer::OnDamagedByExplosion(CTakeDamageInfo const&) | ||||||
|  | Handle g_hDamagedByExplosion; | ||||||
|  | 
 | ||||||
|  | public Plugin myinfo = | ||||||
|  | { | ||||||
|  | 	name			= "NoGrenadeRinging", | ||||||
|  | 	author			= "BotoX", | ||||||
|  | 	description		= "Block the annoying ringing noise when a grenade explodes next to you", | ||||||
|  | 	version			= "1.0", | ||||||
|  | 	url				= "" | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | public void OnPluginStart() | ||||||
|  | { | ||||||
|  | 	Handle hTemp = LoadGameConfigFile("NoGrenadeRinging.games"); | ||||||
|  | 	if(hTemp == INVALID_HANDLE) | ||||||
|  | 		SetFailState("Why you no has gamedata?"); | ||||||
|  | 
 | ||||||
|  | 	int Offset = GameConfGetOffset(hTemp, "OnDamagedByExplosion"); | ||||||
|  | 	g_hDamagedByExplosion = DHookCreate(Offset, HookType_Entity, ReturnType_Int, ThisPointer_CBaseEntity, OnDamagedByExplosion); | ||||||
|  | 	DHookAddParam(g_hDamagedByExplosion, HookParamType_ObjectPtr); | ||||||
|  | 
 | ||||||
|  | 	CloseHandle(hTemp); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public void OnClientPutInServer(int client) | ||||||
|  | { | ||||||
|  | 	//Dont add removal callback for this one | ||||||
|  | 	DHookEntity(g_hDamagedByExplosion, false, client); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | //int CCSPlayer::OnDamagedByExplosion(CTakeDamageInfo const&) | ||||||
|  | public MRESReturn:OnDamagedByExplosion(int pThis, Handle hReturn, Handle hParams) | ||||||
|  | { | ||||||
|  | 	// Block call | ||||||
|  | 	return MRES_Supercede; | ||||||
|  | } | ||||||
							
								
								
									
										1
									
								
								NoGrenadeRinging/scripting/include/dhooks.inc
									
									
									
									
									
										Symbolic link
									
								
							
							
						
						
									
										1
									
								
								NoGrenadeRinging/scripting/include/dhooks.inc
									
									
									
									
									
										Symbolic link
									
								
							| @ -0,0 +1 @@ | |||||||
|  | ../../../includes/dhooks.inc | ||||||
							
								
								
									
										91
									
								
								NoShake/scripting/NoShake.sp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								NoShake/scripting/NoShake.sp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,91 @@ | |||||||
|  | #pragma semicolon 1 | ||||||
|  | 
 | ||||||
|  | #include <sourcemod> | ||||||
|  | #include <sdkhooks> | ||||||
|  | #include <clientprefs> | ||||||
|  | 
 | ||||||
|  | #pragma newdecls required | ||||||
|  | 
 | ||||||
|  | Handle g_hNoShakeCookie; | ||||||
|  | ConVar g_Cvar_NoShakeGlobal; | ||||||
|  | 
 | ||||||
|  | bool g_bNoShake[MAXPLAYERS] = {false, ...}; | ||||||
|  | bool g_bNoShakeGlobal = false; | ||||||
|  | 
 | ||||||
|  | public Plugin myinfo = | ||||||
|  | { | ||||||
|  | 	name 			= "NoShake", | ||||||
|  | 	author 			= "BotoX", | ||||||
|  | 	description 	= "Disable env_shake", | ||||||
|  | 	version 		= "1.0", | ||||||
|  | 	url 			= "" | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | public void OnPluginStart() | ||||||
|  | { | ||||||
|  | 	RegConsoleCmd("sm_shake", Command_Shake, "[NoShake] Disables or enables screen shakes."); | ||||||
|  | 	RegConsoleCmd("sm_noshake", Command_Shake, "[NoShake] Disables or enables screen shakes."); | ||||||
|  | 
 | ||||||
|  | 	g_hNoShakeCookie = RegClientCookie("noshake_cookie", "NoShake", CookieAccess_Protected); | ||||||
|  | 
 | ||||||
|  | 	g_Cvar_NoShakeGlobal = CreateConVar("sm_noshake_global", "0", "Disable screenshake globally.", 0, true, 0.0, true, 1.0); | ||||||
|  | 	g_bNoShakeGlobal = g_Cvar_NoShakeGlobal.BoolValue; | ||||||
|  | 	g_Cvar_NoShakeGlobal.AddChangeHook(OnConVarChanged); | ||||||
|  | 
 | ||||||
|  | 	HookUserMessage(GetUserMessageId("Shake"), MsgHook, true); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public void OnClientCookiesCached(int client) | ||||||
|  | { | ||||||
|  | 	static char sCookieValue[2]; | ||||||
|  | 	GetClientCookie(client, g_hNoShakeCookie, sCookieValue, sizeof(sCookieValue)); | ||||||
|  | 	g_bNoShake[client] = StringToInt(sCookieValue) != 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public void OnConVarChanged(ConVar convar, const char[] oldValue, const char[] newValue) | ||||||
|  | { | ||||||
|  | 	if(StringToInt(newValue) > StringToInt(oldValue)) | ||||||
|  | 		PrintToChatAll("\x03[NoShake]\x01 Enabled NoShake globally!"); | ||||||
|  | 	else if(StringToInt(newValue) < StringToInt(oldValue)) | ||||||
|  | 		PrintToChatAll("\x03[NoShake]\x01 Disabled NoShake globally!"); | ||||||
|  | 
 | ||||||
|  | 	g_bNoShakeGlobal = StringToInt(newValue) != 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public Action MsgHook(UserMsg msg_id, BfRead msg, const int[] players, int playersNum, bool reliable, bool init) | ||||||
|  | { | ||||||
|  | 	if(playersNum == 1 && (g_bNoShakeGlobal || g_bNoShake[players[0]])) | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 	else | ||||||
|  | 		return Plugin_Continue; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public Action Command_Shake(int client, int args) | ||||||
|  | { | ||||||
|  | 	if(g_bNoShakeGlobal) | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 
 | ||||||
|  | 	if(!AreClientCookiesCached(client)) | ||||||
|  | 	{ | ||||||
|  | 		ReplyToCommand(client, "\x03[NoShake]\x01 Please wait. Your settings are still loading."); | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if(g_bNoShake[client]) | ||||||
|  | 	{ | ||||||
|  | 		g_bNoShake[client] = false; | ||||||
|  | 		ReplyToCommand(client, "\x03[NoShake]\x01 has been disabled!"); | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 		g_bNoShake[client] = true; | ||||||
|  | 		ReplyToCommand(client, "\x03[NoShake]\x01 has been enabled!"); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	static char sCookieValue[2]; | ||||||
|  | 	IntToString(g_bNoShake[client], sCookieValue, sizeof(sCookieValue)); | ||||||
|  | 	SetClientCookie(client, g_hNoShakeCookie, sCookieValue); | ||||||
|  | 
 | ||||||
|  | 	return Plugin_Handled; | ||||||
|  | } | ||||||
|  | 
 | ||||||
							
								
								
									
										49
									
								
								SaveLevel/configs/savelevel/ze_FFVII_Mako_Reactor_v1_4_1.cfg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								SaveLevel/configs/savelevel/ze_FFVII_Mako_Reactor_v1_4_1.cfg
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,49 @@ | |||||||
|  | "levels" | ||||||
|  | { | ||||||
|  | 	"0" | ||||||
|  | 	{ | ||||||
|  | 		"name"					"Level 0" | ||||||
|  | 		"restore" | ||||||
|  | 		{ | ||||||
|  | 			"m_iName"			"" | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	"1" | ||||||
|  | 	{ | ||||||
|  | 		"name"					"Level 1" | ||||||
|  | 		"restore" | ||||||
|  | 		{ | ||||||
|  | 			"m_iName"			"" | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	"2" | ||||||
|  | 	{ | ||||||
|  | 		"name"					"Level 2" | ||||||
|  | 		"match" | ||||||
|  | 		{ | ||||||
|  | 			"props" | ||||||
|  | 			{ | ||||||
|  | 				"m_iName"		"a" | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		"restore" | ||||||
|  | 		{ | ||||||
|  | 			"m_iName"			"a" | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	"3" | ||||||
|  | 	{ | ||||||
|  | 		"name"					"Level 3" | ||||||
|  | 		"match" | ||||||
|  | 		{ | ||||||
|  | 			"props" | ||||||
|  | 			{ | ||||||
|  | 				"m_iName"		"b" | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		"restore" | ||||||
|  | 		{ | ||||||
|  | 			"m_iName"			"b" | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										49
									
								
								SaveLevel/configs/savelevel/ze_FFVII_Mako_Reactor_v3_1.cfg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								SaveLevel/configs/savelevel/ze_FFVII_Mako_Reactor_v3_1.cfg
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,49 @@ | |||||||
|  | "levels" | ||||||
|  | { | ||||||
|  | 	"0" | ||||||
|  | 	{ | ||||||
|  | 		"name"					"Level 0" | ||||||
|  | 		"restore" | ||||||
|  | 		{ | ||||||
|  | 			"m_iName"			"" | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	"1" | ||||||
|  | 	{ | ||||||
|  | 		"name"					"Level 1" | ||||||
|  | 		"restore" | ||||||
|  | 		{ | ||||||
|  | 			"m_iName"			"" | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	"2" | ||||||
|  | 	{ | ||||||
|  | 		"name"					"Level 2" | ||||||
|  | 		"match" | ||||||
|  | 		{ | ||||||
|  | 			"props" | ||||||
|  | 			{ | ||||||
|  | 				"m_iName"		"a" | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		"restore" | ||||||
|  | 		{ | ||||||
|  | 			"m_iName"			"a" | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	"3" | ||||||
|  | 	{ | ||||||
|  | 		"name"					"Level 3" | ||||||
|  | 		"match" | ||||||
|  | 		{ | ||||||
|  | 			"props" | ||||||
|  | 			{ | ||||||
|  | 				"m_iName"		"b" | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		"restore" | ||||||
|  | 		{ | ||||||
|  | 			"m_iName"			"b" | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										77
									
								
								SaveLevel/configs/savelevel/ze_FFVII_Mako_Reactor_v6.cfg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								SaveLevel/configs/savelevel/ze_FFVII_Mako_Reactor_v6.cfg
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,77 @@ | |||||||
|  | "levels" | ||||||
|  | { | ||||||
|  | 	"1" | ||||||
|  | 	{ | ||||||
|  | 		"name"					"Level 1" | ||||||
|  | 		"match" | ||||||
|  | 		{ | ||||||
|  | 			"outputs" | ||||||
|  | 			{ | ||||||
|  | 				"m_OnUser1"		"leveling_counter,Add,1" | ||||||
|  | 				"ExactMatches"	"1" | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		"restore" | ||||||
|  | 		{ | ||||||
|  | 			"AddOutput"			"OnUser1 leveling_counter,Add,1,0,-1" | ||||||
|  | 			"m_iFrags"			"100" | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	"2" | ||||||
|  | 	{ | ||||||
|  | 		"name"					"Level 2" | ||||||
|  | 		"match" | ||||||
|  | 		{ | ||||||
|  | 			"outputs" | ||||||
|  | 			{ | ||||||
|  | 				"m_OnUser1"		"leveling_counter,Add,1" | ||||||
|  | 				"ExactMatches"	"2" | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		"restore" | ||||||
|  | 		{ | ||||||
|  | 			"AddOutput"			"OnUser1 leveling_counter,Add,1,0,-1" | ||||||
|  | 			"AddOutput"			"OnUser1 leveling_counter,Add,1,0,-1" | ||||||
|  | 			"m_iFrags"			"200" | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	"3" | ||||||
|  | 	{ | ||||||
|  | 		"name"					"Level 3" | ||||||
|  | 		"match" | ||||||
|  | 		{ | ||||||
|  | 			"outputs" | ||||||
|  | 			{ | ||||||
|  | 				"m_OnUser1"		"leveling_counter,Add,1" | ||||||
|  | 				"ExactMatches"	"3" | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		"restore" | ||||||
|  | 		{ | ||||||
|  | 			"AddOutput"			"OnUser1 leveling_counter,Add,1,0,-1" | ||||||
|  | 			"AddOutput"			"OnUser1 leveling_counter,Add,1,0,-1" | ||||||
|  | 			"AddOutput"			"OnUser1 leveling_counter,Add,1,0,-1" | ||||||
|  | 			"m_iFrags"			"300" | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	"4" | ||||||
|  | 	{ | ||||||
|  | 		"name"					"Level 4" | ||||||
|  | 		"match" | ||||||
|  | 		{ | ||||||
|  | 			"outputs" | ||||||
|  | 			{ | ||||||
|  | 				"m_OnUser1"		"leveling_counter,Add,1" | ||||||
|  | 				"MinMatches"	"4" | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		"restore" | ||||||
|  | 		{ | ||||||
|  | 			"AddOutput"			"OnUser1 leveling_counter,Add,1,0,-1" | ||||||
|  | 			"AddOutput"			"OnUser1 leveling_counter,Add,1,0,-1" | ||||||
|  | 			"AddOutput"			"OnUser1 leveling_counter,Add,1,0,-1" | ||||||
|  | 			"AddOutput"			"OnUser1 leveling_counter,Add,1,0,-1" | ||||||
|  | 			"m_iFrags"			"400" | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										57
									
								
								SaveLevel/configs/savelevel/ze_FFXII_Feywood_b3_1.cfg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								SaveLevel/configs/savelevel/ze_FFXII_Feywood_b3_1.cfg
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,57 @@ | |||||||
|  | "levels" | ||||||
|  | { | ||||||
|  | 	"1" | ||||||
|  | 	{ | ||||||
|  | 		"name"					"Level 1" | ||||||
|  | 		"match" | ||||||
|  | 		{ | ||||||
|  | 			"outputs" | ||||||
|  | 			{ | ||||||
|  | 				"m_OnUser4"		"Map_Level_Check,Add,1" | ||||||
|  | 				"ExactMatches"	"1" | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		"restore" | ||||||
|  | 		{ | ||||||
|  | 			"AddOutput"			"OnUser4 Map_Level_Check,Add,1,0,-1" | ||||||
|  | 			"m_iFrags"			"100" | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	"2" | ||||||
|  | 	{ | ||||||
|  | 		"name"					"Level 2" | ||||||
|  | 		"match" | ||||||
|  | 		{ | ||||||
|  | 			"outputs" | ||||||
|  | 			{ | ||||||
|  | 				"m_OnUser4"		"Map_Level_Check,Add,1" | ||||||
|  | 				"ExactMatches"	"2" | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		"restore" | ||||||
|  | 		{ | ||||||
|  | 			"AddOutput"			"OnUser4 Map_Level_Check,Add,1,0,-1" | ||||||
|  | 			"AddOutput"			"OnUser4 Map_Level_Check,Add,1,0,-1" | ||||||
|  | 			"m_iFrags"			"200" | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	"3" | ||||||
|  | 	{ | ||||||
|  | 		"name"					"Level 3" | ||||||
|  | 		"match" | ||||||
|  | 		{ | ||||||
|  | 			"outputs" | ||||||
|  | 			{ | ||||||
|  | 				"m_OnUser4"		"Map_Level_Check,Add,1" | ||||||
|  | 				"MinMatches"	"3" | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		"restore" | ||||||
|  | 		{ | ||||||
|  | 			"AddOutput"			"OnUser4 Map_Level_Check,Add,1,0,-1" | ||||||
|  | 			"AddOutput"			"OnUser4 Map_Level_Check,Add,1,0,-1" | ||||||
|  | 			"AddOutput"			"OnUser4 Map_Level_Check,Add,1,0,-1" | ||||||
|  | 			"m_iFrags"			"300" | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										98
									
								
								SaveLevel/configs/savelevel/ze_FFXII_Paramina_Rift_v1_3.cfg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								SaveLevel/configs/savelevel/ze_FFXII_Paramina_Rift_v1_3.cfg
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,98 @@ | |||||||
|  | "levels" | ||||||
|  | { | ||||||
|  | 	"1" | ||||||
|  | 	{ | ||||||
|  | 		"name"					"Level 1" | ||||||
|  | 		"match" | ||||||
|  | 		{ | ||||||
|  | 			"outputs" | ||||||
|  | 			{ | ||||||
|  | 				"m_OnUser2"		"leveling_counter,add,1" | ||||||
|  | 				"ExactMatches"	"1" | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		"restore" | ||||||
|  | 		{ | ||||||
|  | 			"AddOutput"			"OnUser2 leveling_counter,add,1,0,-1" | ||||||
|  | 			"m_iFrags"			"100" | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	"2" | ||||||
|  | 	{ | ||||||
|  | 		"name"					"Level 2" | ||||||
|  | 		"match" | ||||||
|  | 		{ | ||||||
|  | 			"outputs" | ||||||
|  | 			{ | ||||||
|  | 				"m_OnUser2"		"leveling_counter,add,1" | ||||||
|  | 				"ExactMatches"	"2" | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		"restore" | ||||||
|  | 		{ | ||||||
|  | 			"AddOutput"			"OnUser2 leveling_counter,add,1,0,-1" | ||||||
|  | 			"AddOutput"			"OnUser2 leveling_counter,add,1,0,-1" | ||||||
|  | 			"m_iFrags"			"200" | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	"3" | ||||||
|  | 	{ | ||||||
|  | 		"name"					"Level 3" | ||||||
|  | 		"match" | ||||||
|  | 		{ | ||||||
|  | 			"outputs" | ||||||
|  | 			{ | ||||||
|  | 				"m_OnUser2"		"leveling_counter,add,1" | ||||||
|  | 				"ExactMatches"	"3" | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		"restore" | ||||||
|  | 		{ | ||||||
|  | 			"AddOutput"			"OnUser2 leveling_counter,add,1,0,-1" | ||||||
|  | 			"AddOutput"			"OnUser2 leveling_counter,add,1,0,-1" | ||||||
|  | 			"AddOutput"			"OnUser2 leveling_counter,add,1,0,-1" | ||||||
|  | 			"m_iFrags"			"300" | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	"4" | ||||||
|  | 	{ | ||||||
|  | 		"name"					"Level 4" | ||||||
|  | 		"match" | ||||||
|  | 		{ | ||||||
|  | 			"outputs" | ||||||
|  | 			{ | ||||||
|  | 				"m_OnUser2"		"leveling_counter,add,1" | ||||||
|  | 				"ExactMatches"	"4" | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		"restore" | ||||||
|  | 		{ | ||||||
|  | 			"AddOutput"			"OnUser2 leveling_counter,add,1,0,-1" | ||||||
|  | 			"AddOutput"			"OnUser2 leveling_counter,add,1,0,-1" | ||||||
|  | 			"AddOutput"			"OnUser2 leveling_counter,add,1,0,-1" | ||||||
|  | 			"AddOutput"			"OnUser2 leveling_counter,add,1,0,-1" | ||||||
|  | 			"m_iFrags"			"400" | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	"5" | ||||||
|  | 	{ | ||||||
|  | 		"name"					"Level 5" | ||||||
|  | 		"match" | ||||||
|  | 		{ | ||||||
|  | 			"outputs" | ||||||
|  | 			{ | ||||||
|  | 				"m_OnUser2"		"leveling_counter,add,1" | ||||||
|  | 				"MinMatches"	"5" | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		"restore" | ||||||
|  | 		{ | ||||||
|  | 			"AddOutput"			"OnUser2 leveling_counter,add,1,0,-1" | ||||||
|  | 			"AddOutput"			"OnUser2 leveling_counter,add,1,0,-1" | ||||||
|  | 			"AddOutput"			"OnUser2 leveling_counter,add,1,0,-1" | ||||||
|  | 			"AddOutput"			"OnUser2 leveling_counter,add,1,0,-1" | ||||||
|  | 			"AddOutput"			"OnUser2 leveling_counter,add,1,0,-1" | ||||||
|  | 			"m_iFrags"			"500" | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										76
									
								
								SaveLevel/configs/savelevel/ze_TESV_Skyrim_v3.cfg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								SaveLevel/configs/savelevel/ze_TESV_Skyrim_v3.cfg
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,76 @@ | |||||||
|  | "levels" | ||||||
|  | { | ||||||
|  | 	"0" | ||||||
|  | 	{ | ||||||
|  | 		"name"					"Level 0" | ||||||
|  | 		"restore" | ||||||
|  | 		{ | ||||||
|  | 			"m_iName"			"" | ||||||
|  | 			"m_iFrags"			"0" | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	"1" | ||||||
|  | 	{ | ||||||
|  | 		"name"					"Level 1" | ||||||
|  | 		"match" | ||||||
|  | 		{ | ||||||
|  | 			"props" | ||||||
|  | 			{ | ||||||
|  | 				"m_iName"		"1" | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		"restore" | ||||||
|  | 		{ | ||||||
|  | 			"m_iName"			"1" | ||||||
|  | 			"m_iFrags"			"100" | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	"2" | ||||||
|  | 	{ | ||||||
|  | 		"name"					"Level 2" | ||||||
|  | 		"match" | ||||||
|  | 		{ | ||||||
|  | 			"props" | ||||||
|  | 			{ | ||||||
|  | 				"m_iName"		"2" | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		"restore" | ||||||
|  | 		{ | ||||||
|  | 			"m_iName"			"2" | ||||||
|  | 			"m_iFrags"			"200" | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	"3" | ||||||
|  | 	{ | ||||||
|  | 		"name"					"Level 3" | ||||||
|  | 		"match" | ||||||
|  | 		{ | ||||||
|  | 			"props" | ||||||
|  | 			{ | ||||||
|  | 				"m_iName"		"3" | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		"restore" | ||||||
|  | 		{ | ||||||
|  | 			"m_iName"			"3" | ||||||
|  | 			"m_iFrags"			"300" | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	"4" | ||||||
|  | 	{ | ||||||
|  | 		"name"					"Level 4" | ||||||
|  | 		"match" | ||||||
|  | 		{ | ||||||
|  | 			"props" | ||||||
|  | 			{ | ||||||
|  | 				"m_iName"		"4" | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		"restore" | ||||||
|  | 		{ | ||||||
|  | 			"m_iName"			"4" | ||||||
|  | 			"m_iFrags"			"400" | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										77
									
								
								SaveLevel/configs/savelevel/ze_harry_potter_v1_3.cfg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								SaveLevel/configs/savelevel/ze_harry_potter_v1_3.cfg
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,77 @@ | |||||||
|  | "levels" | ||||||
|  | { | ||||||
|  | 	"1" | ||||||
|  | 	{ | ||||||
|  | 		"name"					"Level 1" | ||||||
|  | 		"match" | ||||||
|  | 		{ | ||||||
|  | 			"outputs" | ||||||
|  | 			{ | ||||||
|  | 				"m_OnUser3"		"map_wandlevels,Add,1" | ||||||
|  | 				"ExactMatches"	"1" | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		"restore" | ||||||
|  | 		{ | ||||||
|  | 			"AddOutput"			"OnUser3 map_wandlevels,Add,1,0,-1" | ||||||
|  | 			"m_iFrags"			"100" | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	"2" | ||||||
|  | 	{ | ||||||
|  | 		"name"					"Level 2" | ||||||
|  | 		"match" | ||||||
|  | 		{ | ||||||
|  | 			"outputs" | ||||||
|  | 			{ | ||||||
|  | 				"m_OnUser3"		"map_wandlevels,Add,1" | ||||||
|  | 				"ExactMatches"	"2" | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		"restore" | ||||||
|  | 		{ | ||||||
|  | 			"AddOutput"			"OnUser3 map_wandlevels,Add,1,0,-1" | ||||||
|  | 			"AddOutput"			"OnUser3 map_wandlevels,Add,1,0,-1" | ||||||
|  | 			"m_iFrags"			"200" | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	"3" | ||||||
|  | 	{ | ||||||
|  | 		"name"					"Level 3" | ||||||
|  | 		"match" | ||||||
|  | 		{ | ||||||
|  | 			"outputs" | ||||||
|  | 			{ | ||||||
|  | 				"m_OnUser3"		"map_wandlevels,Add,1" | ||||||
|  | 				"ExactMatches"	"3" | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		"restore" | ||||||
|  | 		{ | ||||||
|  | 			"AddOutput"			"OnUser3 map_wandlevels,Add,1,0,-1" | ||||||
|  | 			"AddOutput"			"OnUser3 map_wandlevels,Add,1,0,-1" | ||||||
|  | 			"AddOutput"			"OnUser3 map_wandlevels,Add,1,0,-1" | ||||||
|  | 			"m_iFrags"			"300" | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	"4" | ||||||
|  | 	{ | ||||||
|  | 		"name"					"Level 4" | ||||||
|  | 		"match" | ||||||
|  | 		{ | ||||||
|  | 			"outputs" | ||||||
|  | 			{ | ||||||
|  | 				"m_OnUser3"		"map_wandlevels,Add,1" | ||||||
|  | 				"MinMatches"	"4" | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		"restore" | ||||||
|  | 		{ | ||||||
|  | 			"AddOutput"			"OnUser3 map_wandlevels,Add,1,0,-1" | ||||||
|  | 			"AddOutput"			"OnUser3 map_wandlevels,Add,1,0,-1" | ||||||
|  | 			"AddOutput"			"OnUser3 map_wandlevels,Add,1,0,-1" | ||||||
|  | 			"AddOutput"			"OnUser3 map_wandlevels,Add,1,0,-1" | ||||||
|  | 			"m_iFrags"			"400" | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										92
									
								
								SaveLevel/configs/savelevel/ze_lotr_minas_tirith_v2_2fix.cfg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								SaveLevel/configs/savelevel/ze_lotr_minas_tirith_v2_2fix.cfg
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,92 @@ | |||||||
|  | "levels" | ||||||
|  | { | ||||||
|  | 	"0" | ||||||
|  | 	{ | ||||||
|  | 		"name"					"Level 0" | ||||||
|  | 		"restore" | ||||||
|  | 		{ | ||||||
|  | 			"m_iName"			"" | ||||||
|  | 			"m_iFrags"			"0" | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	"1" | ||||||
|  | 	{ | ||||||
|  | 		"name"					"Level 1" | ||||||
|  | 		"match" | ||||||
|  | 		{ | ||||||
|  | 			"props" | ||||||
|  | 			{ | ||||||
|  | 				"m_iName"		"1" | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		"restore" | ||||||
|  | 		{ | ||||||
|  | 			"m_iName"			"1" | ||||||
|  | 			"m_iFrags"			"100" | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	"2" | ||||||
|  | 	{ | ||||||
|  | 		"name"					"Level 2" | ||||||
|  | 		"match" | ||||||
|  | 		{ | ||||||
|  | 			"props" | ||||||
|  | 			{ | ||||||
|  | 				"m_iName"		"2" | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		"restore" | ||||||
|  | 		{ | ||||||
|  | 			"m_iName"			"2" | ||||||
|  | 			"m_iFrags"			"200" | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	"3" | ||||||
|  | 	{ | ||||||
|  | 		"name"					"Level 3" | ||||||
|  | 		"match" | ||||||
|  | 		{ | ||||||
|  | 			"props" | ||||||
|  | 			{ | ||||||
|  | 				"m_iName"		"3" | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		"restore" | ||||||
|  | 		{ | ||||||
|  | 			"m_iName"			"3" | ||||||
|  | 			"m_iFrags"			"300" | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	"4" | ||||||
|  | 	{ | ||||||
|  | 		"name"					"Level 4" | ||||||
|  | 		"match" | ||||||
|  | 		{ | ||||||
|  | 			"props" | ||||||
|  | 			{ | ||||||
|  | 				"m_iName"		"4" | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		"restore" | ||||||
|  | 		{ | ||||||
|  | 			"m_iName"			"4" | ||||||
|  | 			"m_iFrags"			"400" | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	"5" | ||||||
|  | 	{ | ||||||
|  | 		"name"					"Level 5" | ||||||
|  | 		"match" | ||||||
|  | 		{ | ||||||
|  | 			"props" | ||||||
|  | 			{ | ||||||
|  | 				"m_iName"		"5" | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		"restore" | ||||||
|  | 		{ | ||||||
|  | 			"m_iName"			"5" | ||||||
|  | 			"m_iFrags"			"500" | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										92
									
								
								SaveLevel/configs/savelevel/ze_lotr_minas_tirith_v3_5.cfg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								SaveLevel/configs/savelevel/ze_lotr_minas_tirith_v3_5.cfg
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,92 @@ | |||||||
|  | "levels" | ||||||
|  | { | ||||||
|  | 	"0" | ||||||
|  | 	{ | ||||||
|  | 		"name"					"Level 0" | ||||||
|  | 		"restore" | ||||||
|  | 		{ | ||||||
|  | 			"m_iName"			"" | ||||||
|  | 			"m_iFrags"			"0" | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	"1" | ||||||
|  | 	{ | ||||||
|  | 		"name"					"Level 1" | ||||||
|  | 		"match" | ||||||
|  | 		{ | ||||||
|  | 			"props" | ||||||
|  | 			{ | ||||||
|  | 				"m_iName"		"1" | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		"restore" | ||||||
|  | 		{ | ||||||
|  | 			"m_iName"			"1" | ||||||
|  | 			"m_iFrags"			"100" | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	"2" | ||||||
|  | 	{ | ||||||
|  | 		"name"					"Level 2" | ||||||
|  | 		"match" | ||||||
|  | 		{ | ||||||
|  | 			"props" | ||||||
|  | 			{ | ||||||
|  | 				"m_iName"		"2" | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		"restore" | ||||||
|  | 		{ | ||||||
|  | 			"m_iName"			"2" | ||||||
|  | 			"m_iFrags"			"200" | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	"3" | ||||||
|  | 	{ | ||||||
|  | 		"name"					"Level 3" | ||||||
|  | 		"match" | ||||||
|  | 		{ | ||||||
|  | 			"props" | ||||||
|  | 			{ | ||||||
|  | 				"m_iName"		"3" | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		"restore" | ||||||
|  | 		{ | ||||||
|  | 			"m_iName"			"3" | ||||||
|  | 			"m_iFrags"			"300" | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	"4" | ||||||
|  | 	{ | ||||||
|  | 		"name"					"Level 4" | ||||||
|  | 		"match" | ||||||
|  | 		{ | ||||||
|  | 			"props" | ||||||
|  | 			{ | ||||||
|  | 				"m_iName"		"4" | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		"restore" | ||||||
|  | 		{ | ||||||
|  | 			"m_iName"			"4" | ||||||
|  | 			"m_iFrags"			"400" | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	"5" | ||||||
|  | 	{ | ||||||
|  | 		"name"					"Level 5" | ||||||
|  | 		"match" | ||||||
|  | 		{ | ||||||
|  | 			"props" | ||||||
|  | 			{ | ||||||
|  | 				"m_iName"		"5" | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		"restore" | ||||||
|  | 		{ | ||||||
|  | 			"m_iName"			"5" | ||||||
|  | 			"m_iFrags"			"500" | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										76
									
								
								SaveLevel/configs/savelevel/ze_tesv_skyrim_v4fix.cfg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								SaveLevel/configs/savelevel/ze_tesv_skyrim_v4fix.cfg
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,76 @@ | |||||||
|  | "levels" | ||||||
|  | { | ||||||
|  | 	"0" | ||||||
|  | 	{ | ||||||
|  | 		"name"					"Level 0" | ||||||
|  | 		"restore" | ||||||
|  | 		{ | ||||||
|  | 			"m_iName"			"" | ||||||
|  | 			"m_iFrags"			"0" | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	"1" | ||||||
|  | 	{ | ||||||
|  | 		"name"					"Level 1" | ||||||
|  | 		"match" | ||||||
|  | 		{ | ||||||
|  | 			"props" | ||||||
|  | 			{ | ||||||
|  | 				"m_iName"		"1" | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		"restore" | ||||||
|  | 		{ | ||||||
|  | 			"m_iName"			"1" | ||||||
|  | 			"m_iFrags"			"100" | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	"2" | ||||||
|  | 	{ | ||||||
|  | 		"name"					"Level 2" | ||||||
|  | 		"match" | ||||||
|  | 		{ | ||||||
|  | 			"props" | ||||||
|  | 			{ | ||||||
|  | 				"m_iName"		"2" | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		"restore" | ||||||
|  | 		{ | ||||||
|  | 			"m_iName"			"2" | ||||||
|  | 			"m_iFrags"			"200" | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	"3" | ||||||
|  | 	{ | ||||||
|  | 		"name"					"Level 3" | ||||||
|  | 		"match" | ||||||
|  | 		{ | ||||||
|  | 			"props" | ||||||
|  | 			{ | ||||||
|  | 				"m_iName"		"3" | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		"restore" | ||||||
|  | 		{ | ||||||
|  | 			"m_iName"			"3" | ||||||
|  | 			"m_iFrags"			"300" | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	"4" | ||||||
|  | 	{ | ||||||
|  | 		"name"					"Level 4" | ||||||
|  | 		"match" | ||||||
|  | 		{ | ||||||
|  | 			"props" | ||||||
|  | 			{ | ||||||
|  | 				"m_iName"		"4" | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		"restore" | ||||||
|  | 		{ | ||||||
|  | 			"m_iName"			"4" | ||||||
|  | 			"m_iFrags"			"400" | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										299
									
								
								SaveLevel/scripting/SaveLevel.sp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										299
									
								
								SaveLevel/scripting/SaveLevel.sp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,299 @@ | |||||||
|  | #pragma semicolon 1 | ||||||
|  | 
 | ||||||
|  | #include <sourcemod> | ||||||
|  | #include <sdktools> | ||||||
|  | #include <outputinfo> | ||||||
|  | 
 | ||||||
|  | #pragma newdecls required | ||||||
|  | 
 | ||||||
|  | StringMap g_PlayerLevels; | ||||||
|  | KeyValues g_Config; | ||||||
|  | KeyValues g_PropAltNames; | ||||||
|  | 
 | ||||||
|  | #define PLUGIN_VERSION "1.0" | ||||||
|  | public Plugin myinfo = | ||||||
|  | { | ||||||
|  | 	name 			= "SaveLevel", | ||||||
|  | 	author 			= "BotoX", | ||||||
|  | 	description 	= "Saves players level on maps when they disconnect and restore them on connect.", | ||||||
|  | 	version 		= PLUGIN_VERSION, | ||||||
|  | 	url 			= "" | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | public void OnPluginStart() | ||||||
|  | { | ||||||
|  | 	g_PropAltNames = new KeyValues("PropAltNames"); | ||||||
|  | 	g_PropAltNames.SetString("m_iName", "targetname"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public void OnPluginEnd() | ||||||
|  | { | ||||||
|  | 	if(g_Config) | ||||||
|  | 		delete g_Config; | ||||||
|  | 	if(g_PlayerLevels) | ||||||
|  | 		delete g_PlayerLevels; | ||||||
|  | 	delete g_PropAltNames; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public void OnMapStart() | ||||||
|  | { | ||||||
|  | 	if(g_Config) | ||||||
|  | 		delete g_Config; | ||||||
|  | 	if(g_PlayerLevels) | ||||||
|  | 		delete g_PlayerLevels; | ||||||
|  | 
 | ||||||
|  | 	char sMapName[PLATFORM_MAX_PATH]; | ||||||
|  | 	GetCurrentMap(sMapName, sizeof(sMapName)); | ||||||
|  | 
 | ||||||
|  | 	char sConfigFile[PLATFORM_MAX_PATH]; | ||||||
|  | 	BuildPath(Path_SM, sConfigFile, sizeof(sConfigFile), "configs/savelevel/%s.cfg", sMapName); | ||||||
|  | 	if(!FileExists(sConfigFile)) | ||||||
|  | 	{ | ||||||
|  | 		LogMessage("Could not find mapconfig: \"%s\"", sConfigFile); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 	LogMessage("Found mapconfig: \"%s\"", sConfigFile); | ||||||
|  | 
 | ||||||
|  | 	g_Config = new KeyValues("levels"); | ||||||
|  | 	if(!g_Config.ImportFromFile(sConfigFile)) | ||||||
|  | 	{ | ||||||
|  | 		delete g_Config; | ||||||
|  | 		LogMessage("ImportFromFile() failed!"); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 	g_Config.Rewind(); | ||||||
|  | 
 | ||||||
|  | 	if(!g_Config.GotoFirstSubKey()) | ||||||
|  | 	{ | ||||||
|  | 		delete g_Config; | ||||||
|  | 		LogMessage("GotoFirstSubKey() failed!"); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	g_PlayerLevels = new StringMap(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public void OnClientPostAdminCheck(int client) | ||||||
|  | { | ||||||
|  | 	if(!g_PlayerLevels) | ||||||
|  | 		return; | ||||||
|  | 
 | ||||||
|  | 	char sSteamID[32]; | ||||||
|  | 	GetClientAuthId(client, AuthId_Steam3, sSteamID, sizeof(sSteamID)); | ||||||
|  | 
 | ||||||
|  | 	static char sTargets[128]; | ||||||
|  | 	if(g_PlayerLevels.GetString(sSteamID, sTargets, sizeof(sTargets))) | ||||||
|  | 	{ | ||||||
|  | 		g_PlayerLevels.Remove(sSteamID); | ||||||
|  | 		char sNames[128]; | ||||||
|  | 		static char asTargets[4][32]; | ||||||
|  | 		int Split = ExplodeString(sTargets, ";", asTargets, sizeof(asTargets), sizeof(asTargets[])); | ||||||
|  | 
 | ||||||
|  | 		g_Config.Rewind(); | ||||||
|  | 		for(int i = 0; i < Split; i++) | ||||||
|  | 		{ | ||||||
|  | 			if(!g_Config.JumpToKey(asTargets[i])) | ||||||
|  | 				continue; | ||||||
|  | 
 | ||||||
|  | 			static char sKey[32]; | ||||||
|  | 			static char sValue[1024]; | ||||||
|  | 			if(g_Config.JumpToKey("restore")) | ||||||
|  | 			{ | ||||||
|  | 				if(g_Config.GotoFirstSubKey(false)) | ||||||
|  | 				{ | ||||||
|  | 					do | ||||||
|  | 					{ | ||||||
|  | 						g_Config.GetSectionName(sKey, sizeof(sKey)); | ||||||
|  | 						g_Config.GetString(NULL_STRING, sValue, sizeof(sValue)); | ||||||
|  | 						if(StrEqual(sKey, "AddOutput", false)) | ||||||
|  | 						{ | ||||||
|  | 							SetVariantString(sValue); | ||||||
|  | 							AcceptEntityInput(client, sKey, client, client); | ||||||
|  | 						} | ||||||
|  | 						else | ||||||
|  | 						{ | ||||||
|  | 							PropFieldType Type; | ||||||
|  | 							int NumBits; | ||||||
|  | 							int Offset = FindDataMapInfo(client, sKey, Type, NumBits); | ||||||
|  | 							if(Offset != -1) | ||||||
|  | 							{ | ||||||
|  | 								if(Type == PropField_Integer) | ||||||
|  | 								{ | ||||||
|  | 									int Value = StringToInt(sValue); | ||||||
|  | 									SetEntData(client, Offset, Value, NumBits / 8, false); | ||||||
|  | 								} | ||||||
|  | 								else if(Type == PropField_Float) | ||||||
|  | 								{ | ||||||
|  | 									float Value = StringToFloat(sValue); | ||||||
|  | 									SetEntDataFloat(client, Offset, Value, false); | ||||||
|  | 								} | ||||||
|  | 								else if(Type == PropField_String) | ||||||
|  | 								{ | ||||||
|  | 									SetEntDataString(client, Offset, sValue, strlen(sValue) + 1, false); | ||||||
|  | 								} | ||||||
|  | 								else if(Type == PropField_String_T) | ||||||
|  | 								{ | ||||||
|  | 									static char sAltKey[32]; | ||||||
|  | 									g_PropAltNames.GetString(sKey, sAltKey, sizeof(sAltKey), NULL_STRING); | ||||||
|  | 									if(sAltKey[0]) | ||||||
|  | 										DispatchKeyValue(client, sAltKey, sValue); | ||||||
|  | 								} | ||||||
|  | 							} | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
|  | 					while(g_Config.GotoNextKey(false)); | ||||||
|  | 
 | ||||||
|  | 					g_Config.GoBack(); | ||||||
|  | 					g_Config.GoBack(); | ||||||
|  | 					g_Config.GetString("name", sValue, sizeof(sValue)); | ||||||
|  | 					g_Config.GoBack(); | ||||||
|  | 					StrCat(sNames, sizeof(sNames), sValue); | ||||||
|  | 					StrCat(sNames, sizeof(sNames), ", "); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		int NamesLen = strlen(sNames); | ||||||
|  | 		if(NamesLen) | ||||||
|  | 		{ | ||||||
|  | 			sNames[NamesLen - 2] = 0; // Cut off ', ' | ||||||
|  | 			PrintToChatAll("\x03[SaveLevel]\x01 %N has been restored to: \x04%s", client, sNames); | ||||||
|  | 		} | ||||||
|  | 		g_Config.Rewind(); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public void OnClientDisconnect(int client) | ||||||
|  | { | ||||||
|  | 	if(!g_Config || !g_PlayerLevels) | ||||||
|  | 		return; | ||||||
|  | 
 | ||||||
|  | 	g_Config.Rewind(); | ||||||
|  | 	g_Config.GotoFirstSubKey(); | ||||||
|  | 
 | ||||||
|  | 	char sTargets[128]; | ||||||
|  | 	static char sTarget[32]; | ||||||
|  | 	static char sKey[32]; | ||||||
|  | 	static char sValue[1024]; | ||||||
|  | 	static char sOutput[1024]; | ||||||
|  | 	bool Found = false; | ||||||
|  | 	do | ||||||
|  | 	{ | ||||||
|  | 		g_Config.GetSectionName(sTarget, sizeof(sTarget)); | ||||||
|  | 		if(!g_Config.JumpToKey("match")) | ||||||
|  | 			continue; | ||||||
|  | 
 | ||||||
|  | 		int Matches = 0; | ||||||
|  | 		int ExactMatches = g_Config.GetNum("ExactMatches", -1); | ||||||
|  | 		int MinMatches = g_Config.GetNum("MinMatches", -1); | ||||||
|  | 		int MaxMatches = g_Config.GetNum("MaxMatches", -1); | ||||||
|  | 
 | ||||||
|  | 		if(!g_Config.GotoFirstSubKey(false)) | ||||||
|  | 			continue; | ||||||
|  | 
 | ||||||
|  | 		do | ||||||
|  | 		{ | ||||||
|  | 			static char sSection[32]; | ||||||
|  | 			g_Config.GetSectionName(sSection, sizeof(sSection)); | ||||||
|  | 
 | ||||||
|  | 			if(StrEqual(sSection, "outputs")) | ||||||
|  | 			{ | ||||||
|  | 				int _Matches = 0; | ||||||
|  | 				int _ExactMatches = g_Config.GetNum("ExactMatches", -1); | ||||||
|  | 				int _MinMatches = g_Config.GetNum("MinMatches", -1); | ||||||
|  | 				int _MaxMatches = g_Config.GetNum("MaxMatches", -1); | ||||||
|  | 
 | ||||||
|  | 				if(g_Config.GotoFirstSubKey(false)) | ||||||
|  | 				{ | ||||||
|  | 					do | ||||||
|  | 					{ | ||||||
|  | 						g_Config.GetSectionName(sKey, sizeof(sKey)); | ||||||
|  | 						g_Config.GetString(NULL_STRING, sValue, sizeof(sValue)); | ||||||
|  | 
 | ||||||
|  | 						int Count = GetOutputCount(client, sKey); | ||||||
|  | 						for(int i = 0; i < Count; i++) | ||||||
|  | 						{ | ||||||
|  | 							int Len = GetOutputTarget(client, sKey, i, sOutput); | ||||||
|  | 							sOutput[Len] = ','; Len++; | ||||||
|  | 							Len += GetOutputTargetInput(client, sKey, i, sOutput[Len]); | ||||||
|  | 							sOutput[Len] = ','; Len++; | ||||||
|  | 							Len += GetOutputParameter(client, sKey, i, sOutput[Len]); | ||||||
|  | 
 | ||||||
|  | 							if(StrEqual(sValue, sOutput)) | ||||||
|  | 								_Matches++; | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
|  | 					while(g_Config.GotoNextKey(false)); | ||||||
|  | 
 | ||||||
|  | 					g_Config.GoBack(); | ||||||
|  | 				} | ||||||
|  | 				g_Config.GoBack(); | ||||||
|  | 
 | ||||||
|  | 				Matches += CalcMatches(_Matches, _ExactMatches, _MinMatches, _MaxMatches); | ||||||
|  | 			} | ||||||
|  | 			else if(StrEqual(sSection, "props")) | ||||||
|  | 			{ | ||||||
|  | 				int _Matches = 0; | ||||||
|  | 				int _ExactMatches = g_Config.GetNum("ExactMatches", -1); | ||||||
|  | 				int _MinMatches = g_Config.GetNum("MinMatches", -1); | ||||||
|  | 				int _MaxMatches = g_Config.GetNum("MaxMatches", -1); | ||||||
|  | 
 | ||||||
|  | 				if(g_Config.GotoFirstSubKey(false)) | ||||||
|  | 				{ | ||||||
|  | 					do | ||||||
|  | 					{ | ||||||
|  | 						g_Config.GetSectionName(sKey, sizeof(sKey)); | ||||||
|  | 						g_Config.GetString(NULL_STRING, sValue, sizeof(sValue)); | ||||||
|  | 
 | ||||||
|  | 						GetEntPropString(client, Prop_Data, sKey, sOutput, sizeof(sOutput)); | ||||||
|  | 
 | ||||||
|  | 						if(StrEqual(sValue, sOutput)) | ||||||
|  | 							_Matches++; | ||||||
|  | 					} | ||||||
|  | 					while(g_Config.GotoNextKey(false)); | ||||||
|  | 
 | ||||||
|  | 					g_Config.GoBack(); | ||||||
|  | 				} | ||||||
|  | 				g_Config.GoBack(); | ||||||
|  | 
 | ||||||
|  | 				Matches += CalcMatches(_Matches, _ExactMatches, _MinMatches, _MaxMatches); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		while(g_Config.GotoNextKey(false)); | ||||||
|  | 
 | ||||||
|  | 		g_Config.GoBack(); | ||||||
|  | 
 | ||||||
|  | 		if(CalcMatches(Matches, ExactMatches, MinMatches, MaxMatches)) | ||||||
|  | 		{ | ||||||
|  | 			if(Found) | ||||||
|  | 				StrCat(sTargets, sizeof(sTargets), ";"); | ||||||
|  | 
 | ||||||
|  | 			Found = true; | ||||||
|  | 			StrCat(sTargets, sizeof(sTargets), sTarget); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	while(g_Config.GotoNextKey()); | ||||||
|  | 
 | ||||||
|  | 	g_Config.Rewind(); | ||||||
|  | 	if(!Found) | ||||||
|  | 		return; | ||||||
|  | 
 | ||||||
|  | 	char sSteamID[32]; | ||||||
|  | 	GetClientAuthId(client, AuthId_Steam3, sSteamID, sizeof(sSteamID)); | ||||||
|  | 	g_PlayerLevels.SetString(sSteamID, sTargets, true); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | stock int CalcMatches(int Matches, int ExactMatches, int MinMatches, int MaxMatches) | ||||||
|  | { | ||||||
|  | 	int Value = 0; | ||||||
|  | 	if((ExactMatches == -1 && MinMatches == -1 && MaxMatches == -1 && Matches) || | ||||||
|  | 		Matches == ExactMatches || | ||||||
|  | 		(MinMatches != -1 && MaxMatches == -1 && Matches >= MinMatches) || | ||||||
|  | 		(MaxMatches != -1 && MinMatches == -1 && Matches <= MaxMatches) || | ||||||
|  | 		(MinMatches != -1 && MaxMatches != -1 && Matches >= MinMatches && Matches <= MaxMatches)) | ||||||
|  | 	{ | ||||||
|  | 		Value++; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return Value; | ||||||
|  | } | ||||||
							
								
								
									
										1
									
								
								SaveLevel/scripting/include/outputinfo.inc
									
									
									
									
									
										Symbolic link
									
								
							
							
						
						
									
										1
									
								
								SaveLevel/scripting/include/outputinfo.inc
									
									
									
									
									
										Symbolic link
									
								
							| @ -0,0 +1 @@ | |||||||
|  | ../../../includes/outputinfo.inc | ||||||
							
								
								
									
										908
									
								
								SelfMute/scripting/SelfMute.sp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										908
									
								
								SelfMute/scripting/SelfMute.sp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,908 @@ | |||||||
|  | #pragma semicolon 1 | ||||||
|  | 
 | ||||||
|  | #include <sourcemod> | ||||||
|  | #include <sdktools> | ||||||
|  | #include <adminmenu> | ||||||
|  | #include <cstrike> | ||||||
|  | 
 | ||||||
|  | #undef REQUIRE_PLUGIN | ||||||
|  | #include <ccc> | ||||||
|  | #include <zombiereloaded> | ||||||
|  | #include <voiceannounce_ex> | ||||||
|  | #include <AdvancedTargeting> | ||||||
|  | #define REQUIRE_PLUGIN | ||||||
|  | 
 | ||||||
|  | #pragma newdecls required | ||||||
|  | 
 | ||||||
|  | bool g_Plugin_ccc = false; | ||||||
|  | bool g_Plugin_zombiereloaded = false; | ||||||
|  | bool g_Plugin_voiceannounce_ex = false; | ||||||
|  | bool g_Plugin_AdvancedTargeting = false; | ||||||
|  | 
 | ||||||
|  | #define PLUGIN_VERSION "2.0" | ||||||
|  | 
 | ||||||
|  | public Plugin myinfo = | ||||||
|  | { | ||||||
|  | 	name 			= "SelfMute", | ||||||
|  | 	author 			= "BotoX", | ||||||
|  | 	description 	= "Ignore other players in text and voicechat.", | ||||||
|  | 	version 		= PLUGIN_VERSION, | ||||||
|  | 	url 			= "" | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | enum | ||||||
|  | { | ||||||
|  | 	MUTE_NONE = 0, | ||||||
|  | 	MUTE_SPEC = 1, | ||||||
|  | 	MUTE_CT = 2, | ||||||
|  | 	MUTE_T = 4, | ||||||
|  | 	MUTE_DEAD = 8, | ||||||
|  | 	MUTE_ALIVE = 16, | ||||||
|  | 	MUTE_NOTFRIENDS = 32, | ||||||
|  | 	MUTE_ALL = 64, | ||||||
|  | 	MUTE_LAST = 64 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | bool g_Ignored[(MAXPLAYERS + 1) * (MAXPLAYERS + 1)]; | ||||||
|  | int g_SpecialMutes[MAXPLAYERS + 1]; | ||||||
|  | 
 | ||||||
|  | char g_PlayerNames[MAXPLAYERS+1][MAX_NAME_LENGTH]; | ||||||
|  | 
 | ||||||
|  | public void OnPluginStart() | ||||||
|  | { | ||||||
|  | 	CreateConVar("sm_selfmute_version", PLUGIN_VERSION, "Version of Self-Mute", FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY); | ||||||
|  | 
 | ||||||
|  | 	RegConsoleCmd("sm_sm", Command_SelfMute, "Mute player by typing !sm [playername]"); | ||||||
|  | 	RegConsoleCmd("sm_su", Command_SelfUnMute, "Unmute player by typing !su [playername]"); | ||||||
|  | 	RegConsoleCmd("sm_cm", Command_CheckMutes, "Check who you have self-muted"); | ||||||
|  | 
 | ||||||
|  | 	HookEvent("round_start", Event_Round); | ||||||
|  | 	HookEvent("round_end", Event_Round); | ||||||
|  | 	HookEvent("player_team", Event_TeamChange); | ||||||
|  | 
 | ||||||
|  | 	UserMsg RadioText = GetUserMessageId("RadioText"); | ||||||
|  | 	if(RadioText == INVALID_MESSAGE_ID) | ||||||
|  | 		SetFailState("This game doesn't support RadioText user messages."); | ||||||
|  | 
 | ||||||
|  | 	HookUserMessage(RadioText, Hook_UserMessageRadioText, true); | ||||||
|  | 
 | ||||||
|  | 	UserMsg SendAudio = GetUserMessageId("SendAudio"); | ||||||
|  | 	if(SendAudio == INVALID_MESSAGE_ID) | ||||||
|  | 		SetFailState("This game doesn't support SendAudio user messages."); | ||||||
|  | 
 | ||||||
|  | 	HookUserMessage(SendAudio, Hook_UserMessageSendAudio, true); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public void OnAllPluginsLoaded() | ||||||
|  | { | ||||||
|  | 	g_Plugin_ccc = LibraryExists("ccc"); | ||||||
|  | 	g_Plugin_zombiereloaded = true;//LibraryExists("zombiereloaded"); | ||||||
|  | 	g_Plugin_voiceannounce_ex = LibraryExists("voiceannounce_ex"); | ||||||
|  | 	g_Plugin_AdvancedTargeting = LibraryExists("AdvancedTargeting"); | ||||||
|  | 	PrintToServer("CCC: %s\nZombieReloaded: %s\nVoiceAnnounce: %s\nAdvancedTargeting: %s", | ||||||
|  | 		(g_Plugin_ccc ? "loaded" : "not loaded"), | ||||||
|  | 		(g_Plugin_zombiereloaded ? "loaded" : "not loaded"), | ||||||
|  | 		(g_Plugin_voiceannounce_ex ? "loaded" : "not loaded"), | ||||||
|  | 		(g_Plugin_AdvancedTargeting ? "loaded" : "not loaded")); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public void OnClientPutInServer(int client) | ||||||
|  | { | ||||||
|  | 	g_SpecialMutes[client] = MUTE_NONE; | ||||||
|  | 	for(int i = 1; i <= MaxClients; i++) | ||||||
|  | 		SetIgnored(client, i, false); | ||||||
|  | 
 | ||||||
|  | 	UpdateSpecialMutesOtherClients(client); | ||||||
|  | 	UpdateIgnored(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public void OnClientPostAdminCheck(int client) | ||||||
|  | { | ||||||
|  | 	UpdateSpecialMutesOtherClients(client); | ||||||
|  | 	UpdateSpecialMutesThisClient(client); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public void OnClientDisconnect(int client) | ||||||
|  | { | ||||||
|  | 	g_SpecialMutes[client] = MUTE_NONE; | ||||||
|  | 	for(int i = 1; i <= MaxClients; i++) | ||||||
|  | 	{ | ||||||
|  | 		SetIgnored(client, i, false); | ||||||
|  | 
 | ||||||
|  | 		if(IsClientInGame(i) && !IsFakeClient(i) && i != client) | ||||||
|  | 			SetListenOverride(i, client, Listen_Yes); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	UpdateIgnored(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public void Event_Round(Handle event, const char[] name, bool dontBroadcast) | ||||||
|  | { | ||||||
|  | 	for(int i = 1; i <= MaxClients; i++) | ||||||
|  | 	{ | ||||||
|  | 		if(IsClientInGame(i) && !IsFakeClient(i)) | ||||||
|  | 			UpdateSpecialMutesThisClient(i); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public void Event_TeamChange(Handle event, const char[] name, bool dontBroadcast) | ||||||
|  | { | ||||||
|  | 	int client = GetClientOfUserId(GetEventInt(event, "userid")); | ||||||
|  | 
 | ||||||
|  | 	UpdateSpecialMutesOtherClients(client); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public int ZR_OnClientInfected(int client, int attacker, bool motherInfect, bool respawnOverride, bool respawn) | ||||||
|  | { | ||||||
|  | 	UpdateSpecialMutesOtherClients(client); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public int ZR_OnClientHumanPost(int client, bool respawn, bool protect) | ||||||
|  | { | ||||||
|  | 	UpdateSpecialMutesOtherClients(client); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* | ||||||
|  |  * Mutes this client on other players | ||||||
|  | */ | ||||||
|  | void UpdateSpecialMutesOtherClients(int client) | ||||||
|  | { | ||||||
|  | 	bool Alive = IsPlayerAlive(client); | ||||||
|  | 	int Team = GetClientTeam(client); | ||||||
|  | 
 | ||||||
|  | 	for(int i = 1; i <= MaxClients; i++) | ||||||
|  | 	{ | ||||||
|  | 		if(i == client || !IsClientInGame(i) || IsFakeClient(i)) | ||||||
|  | 			continue; | ||||||
|  | 
 | ||||||
|  | 		int Flags = MUTE_NONE; | ||||||
|  | 
 | ||||||
|  | 		if(g_SpecialMutes[i] & MUTE_SPEC && Team == CS_TEAM_SPECTATOR) | ||||||
|  | 			Flags |= MUTE_SPEC; | ||||||
|  | 
 | ||||||
|  | 		else if(g_SpecialMutes[i] & MUTE_CT && Alive && | ||||||
|  | 			((g_Plugin_zombiereloaded && ZR_IsClientHuman(client)) || (!g_Plugin_zombiereloaded && Team == CS_TEAM_CT))) | ||||||
|  | 			Flags |= MUTE_CT; | ||||||
|  | 
 | ||||||
|  | 		else if(g_SpecialMutes[i] & MUTE_T && Alive && | ||||||
|  | 			((g_Plugin_zombiereloaded && ZR_IsClientZombie(client)) || (!g_Plugin_zombiereloaded && Team == CS_TEAM_T))) | ||||||
|  | 			Flags |= MUTE_T; | ||||||
|  | 
 | ||||||
|  | 		else if(g_SpecialMutes[i] & MUTE_DEAD && !Alive) | ||||||
|  | 			Flags |= MUTE_DEAD; | ||||||
|  | 
 | ||||||
|  | 		else if(g_SpecialMutes[i] & MUTE_ALIVE && Alive) | ||||||
|  | 			Flags |= MUTE_ALIVE; | ||||||
|  | 
 | ||||||
|  | 		else if(g_SpecialMutes[i] & MUTE_NOTFRIENDS && | ||||||
|  | 			g_Plugin_AdvancedTargeting && IsClientFriend(i, client) == 0) | ||||||
|  | 			Flags |= MUTE_NOTFRIENDS; | ||||||
|  | 
 | ||||||
|  | 		else if(g_SpecialMutes[i] & MUTE_ALL) | ||||||
|  | 			Flags |= MUTE_ALL; | ||||||
|  | 
 | ||||||
|  | 		if(Flags) | ||||||
|  | 			SetListenOverride(i, client, Listen_No); | ||||||
|  | 		else if(!GetIgnored(i, client)) | ||||||
|  | 			SetListenOverride(i, client, Listen_Yes); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* | ||||||
|  |  * Mutes other players on this client | ||||||
|  | */ | ||||||
|  | void UpdateSpecialMutesThisClient(int client) | ||||||
|  | { | ||||||
|  | 	for(int i = 1; i <= MaxClients; i++) | ||||||
|  | 	{ | ||||||
|  | 		if(i == client || !IsClientInGame(i) || IsFakeClient(i)) | ||||||
|  | 			continue; | ||||||
|  | 
 | ||||||
|  | 		bool Alive = IsPlayerAlive(i); | ||||||
|  | 		int Team = GetClientTeam(i); | ||||||
|  | 
 | ||||||
|  | 		int Flags = MUTE_NONE; | ||||||
|  | 
 | ||||||
|  | 		if(g_SpecialMutes[client] & MUTE_SPEC && Team == CS_TEAM_SPECTATOR) | ||||||
|  | 			Flags |= MUTE_SPEC; | ||||||
|  | 
 | ||||||
|  | 		else if(g_SpecialMutes[client] & MUTE_CT && Alive && | ||||||
|  | 			((g_Plugin_zombiereloaded && ZR_IsClientHuman(i) || (!g_Plugin_zombiereloaded) && Team == CS_TEAM_CT))) | ||||||
|  | 			Flags |= MUTE_CT; | ||||||
|  | 
 | ||||||
|  | 		else if(g_SpecialMutes[client] & MUTE_T && Alive && | ||||||
|  | 			((g_Plugin_zombiereloaded && ZR_IsClientZombie(i) || (!g_Plugin_zombiereloaded) && Team == CS_TEAM_T))) | ||||||
|  | 			Flags |= MUTE_T; | ||||||
|  | 
 | ||||||
|  | 		else if(g_SpecialMutes[client] & MUTE_DEAD && !Alive) | ||||||
|  | 			Flags |= MUTE_DEAD; | ||||||
|  | 
 | ||||||
|  | 		else if(g_SpecialMutes[client] & MUTE_ALIVE && Alive) | ||||||
|  | 			Flags |= MUTE_ALIVE; | ||||||
|  | 
 | ||||||
|  | 		else if(g_SpecialMutes[client] & MUTE_NOTFRIENDS && | ||||||
|  | 			g_Plugin_AdvancedTargeting && IsClientFriend(client, i) == 0) | ||||||
|  | 			Flags |= MUTE_NOTFRIENDS; | ||||||
|  | 
 | ||||||
|  | 		else if(g_SpecialMutes[client] & MUTE_ALL) | ||||||
|  | 			Flags |= MUTE_ALL; | ||||||
|  | 
 | ||||||
|  | 		if(Flags) | ||||||
|  | 			SetListenOverride(client, i, Listen_No); | ||||||
|  | 		else if(!GetIgnored(client, i)) | ||||||
|  | 			SetListenOverride(client, i, Listen_Yes); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int GetSpecialMutesFlags(char[] Argument) | ||||||
|  | { | ||||||
|  | 	int SpecialMute = MUTE_NONE; | ||||||
|  | 	if(StrEqual(Argument, "@spec", false) || StrEqual(Argument, "@!ct", false) || StrEqual(Argument, "@!t", false)) | ||||||
|  | 		SpecialMute |= MUTE_SPEC; | ||||||
|  | 	if(StrEqual(Argument, "@ct", false) || StrEqual(Argument, "@!t", false) || StrEqual(Argument, "@!spec", false)) | ||||||
|  | 		SpecialMute |= MUTE_CT; | ||||||
|  | 	if(StrEqual(Argument, "@t", false) || StrEqual(Argument, "@!ct", false) || StrEqual(Argument, "@!spec", false)) | ||||||
|  | 		SpecialMute |= MUTE_T; | ||||||
|  | 	if(StrEqual(Argument, "@dead", false) || StrEqual(Argument, "@!alive", false)) | ||||||
|  | 		SpecialMute |= MUTE_DEAD; | ||||||
|  | 	if(StrEqual(Argument, "@alive", false) || StrEqual(Argument, "@!dead", false)) | ||||||
|  | 		SpecialMute |= MUTE_ALIVE; | ||||||
|  | 	if(g_Plugin_AdvancedTargeting && StrEqual(Argument, "@!friends", false)) | ||||||
|  | 		SpecialMute |= MUTE_NOTFRIENDS; | ||||||
|  | 	if(StrEqual(Argument, "@all", false)) | ||||||
|  | 		SpecialMute |= MUTE_ALL; | ||||||
|  | 
 | ||||||
|  | 	return SpecialMute; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void FormatSpecialMutes(int SpecialMute, char[] aBuf, int BufLen) | ||||||
|  | { | ||||||
|  | 	if(!SpecialMute) | ||||||
|  | 	{ | ||||||
|  | 		StrCat(aBuf, BufLen, "none"); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	bool Status = false; | ||||||
|  | 	int MuteCount = RoundFloat(Logarithm(float(MUTE_LAST), 2.0)); | ||||||
|  | 	for(int i = 0; i <= MuteCount; i++) | ||||||
|  | 	{ | ||||||
|  | 		switch(SpecialMute & RoundFloat(Pow(2.0, float(i)))) | ||||||
|  | 		{ | ||||||
|  | 			case MUTE_SPEC: | ||||||
|  | 			{ | ||||||
|  | 				StrCat(aBuf, BufLen, "Spectators, "); | ||||||
|  | 				Status = true; | ||||||
|  | 			} | ||||||
|  | 			case MUTE_CT: | ||||||
|  | 			{ | ||||||
|  | 				StrCat(aBuf, BufLen, "CTs, "); | ||||||
|  | 				Status = true; | ||||||
|  | 			} | ||||||
|  | 			case MUTE_T: | ||||||
|  | 			{ | ||||||
|  | 				StrCat(aBuf, BufLen, "Ts, "); | ||||||
|  | 				Status = true; | ||||||
|  | 			} | ||||||
|  | 			case MUTE_DEAD: | ||||||
|  | 			{ | ||||||
|  | 				StrCat(aBuf, BufLen, "Dead players, "); | ||||||
|  | 				Status = true; | ||||||
|  | 			} | ||||||
|  | 			case MUTE_ALIVE: | ||||||
|  | 			{ | ||||||
|  | 				StrCat(aBuf, BufLen, "Alive players, "); | ||||||
|  | 				Status = true; | ||||||
|  | 			} | ||||||
|  | 			case MUTE_NOTFRIENDS: | ||||||
|  | 			{ | ||||||
|  | 				StrCat(aBuf, BufLen, "Not Steam friends, "); | ||||||
|  | 				Status = true; | ||||||
|  | 			} | ||||||
|  | 			case MUTE_ALL: | ||||||
|  | 			{ | ||||||
|  | 				StrCat(aBuf, BufLen, "Everyone, "); | ||||||
|  | 				Status = true; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Cut off last ', ' | ||||||
|  | 	if(Status) | ||||||
|  | 		aBuf[strlen(aBuf) - 2] = 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool MuteSpecial(int client, char[] Argument) | ||||||
|  | { | ||||||
|  | 	bool RetValue = false; | ||||||
|  | 	int SpecialMute = GetSpecialMutesFlags(Argument); | ||||||
|  | 
 | ||||||
|  | 	if(SpecialMute & MUTE_NOTFRIENDS && g_Plugin_AdvancedTargeting && ReadClientFriends(client) != 1) | ||||||
|  | 	{ | ||||||
|  | 		PrintToChat(client, "\x04[Self-Mute]\x01 Could not read your friendslist, your profile must be set to public!"); | ||||||
|  | 		SpecialMute &= ~MUTE_NOTFRIENDS; | ||||||
|  | 		RetValue = true; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if(SpecialMute) | ||||||
|  | 	{ | ||||||
|  | 		if(SpecialMute & MUTE_ALL || g_SpecialMutes[client] & MUTE_ALL) | ||||||
|  | 		{ | ||||||
|  | 			g_SpecialMutes[client] = MUTE_ALL; | ||||||
|  | 			SpecialMute = MUTE_ALL; | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 			g_SpecialMutes[client] |= SpecialMute; | ||||||
|  | 
 | ||||||
|  | 		UpdateSpecialMutesThisClient(client); | ||||||
|  | 
 | ||||||
|  | 		char aBuf[128]; | ||||||
|  | 		FormatSpecialMutes(SpecialMute, aBuf, sizeof(aBuf)); | ||||||
|  | 
 | ||||||
|  | 		PrintToChat(client, "\x04[Self-Mute]\x01 You have self-muted group:\x04 %s", aBuf); | ||||||
|  | 		RetValue = true; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return RetValue; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool UnMuteSpecial(int client, char[] Argument) | ||||||
|  | { | ||||||
|  | 	int SpecialMute = GetSpecialMutesFlags(Argument); | ||||||
|  | 
 | ||||||
|  | 	if(SpecialMute) | ||||||
|  | 	{ | ||||||
|  | 		if(SpecialMute & MUTE_ALL) | ||||||
|  | 		{ | ||||||
|  | 			if(g_SpecialMutes[client]) | ||||||
|  | 			{ | ||||||
|  | 				SpecialMute = g_SpecialMutes[client]; | ||||||
|  | 				g_SpecialMutes[client] = MUTE_NONE; | ||||||
|  | 			} | ||||||
|  | 			else | ||||||
|  | 			{ | ||||||
|  | 				for(int i = 1; i <= MaxClients; i++) | ||||||
|  | 				{ | ||||||
|  | 					if(IsClientInGame(i) && !IsFakeClient(i)) | ||||||
|  | 						UnIgnore(client, i); | ||||||
|  | 
 | ||||||
|  | 					PrintToChat(client, "\x04[Self-Mute]\x01 You have self-unmuted:\x04 all players"); | ||||||
|  | 					return true; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 			g_SpecialMutes[client] &= ~SpecialMute; | ||||||
|  | 
 | ||||||
|  | 		UpdateSpecialMutesThisClient(client); | ||||||
|  | 
 | ||||||
|  | 		char aBuf[256]; | ||||||
|  | 		FormatSpecialMutes(SpecialMute, aBuf, sizeof(aBuf)); | ||||||
|  | 
 | ||||||
|  | 		PrintToChat(client, "\x04[Self-Mute]\x01 You have self-unmuted group:\x04 %s", aBuf); | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return false; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Ignore(int client, int target) | ||||||
|  | { | ||||||
|  | 	SetIgnored(client, target, true); | ||||||
|  | 	SetListenOverride(client, target, Listen_No); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void UnIgnore(int client, int target) | ||||||
|  | { | ||||||
|  | 	SetIgnored(client, target, false); | ||||||
|  | 	SetListenOverride(client, target, Listen_Yes); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* | ||||||
|  |  * CHAT COMMANDS | ||||||
|  | */ | ||||||
|  | public Action Command_SelfMute(int client, int args) | ||||||
|  | { | ||||||
|  | 	if(client == 0) | ||||||
|  | 	{ | ||||||
|  | 		PrintToServer("[SM] Cannot use command from server console."); | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if(args < 1) | ||||||
|  | 	{ | ||||||
|  | 		DisplayMuteMenu(client); | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	char Argument[65]; | ||||||
|  | 	GetCmdArgString(Argument, sizeof(Argument)); | ||||||
|  | 
 | ||||||
|  | 	char Filtered[65]; | ||||||
|  | 	strcopy(Filtered, sizeof(Filtered), Argument); | ||||||
|  | 	StripQuotes(Filtered); | ||||||
|  | 	TrimString(Filtered); | ||||||
|  | 
 | ||||||
|  | 	if(StrEqual(Filtered, "@me", false)) | ||||||
|  | 	{ | ||||||
|  | 		PrintToChat(client, "\x04[Self-Mute]\x01 You can't mute yourself, don't be silly."); | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if(MuteSpecial(client, Filtered)) | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 
 | ||||||
|  | 	char sTargetName[MAX_TARGET_LENGTH]; | ||||||
|  | 	int aTargetList[MAXPLAYERS]; | ||||||
|  | 	int TargetCount; | ||||||
|  | 	bool TnIsMl; | ||||||
|  | 
 | ||||||
|  | 	if((TargetCount = ProcessTargetString( | ||||||
|  | 			Argument, | ||||||
|  | 			client, | ||||||
|  | 			aTargetList, | ||||||
|  | 			MAXPLAYERS, | ||||||
|  | 			COMMAND_FILTER_CONNECTED|COMMAND_FILTER_NO_IMMUNITY, | ||||||
|  | 			sTargetName, | ||||||
|  | 			sizeof(sTargetName), | ||||||
|  | 			TnIsMl)) <= 0) | ||||||
|  | 	{ | ||||||
|  | 		ReplyToTargetError(client, TargetCount); | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for(int i = 0; i < TargetCount; i++) | ||||||
|  | 	{ | ||||||
|  | 		if(aTargetList[i] != client) | ||||||
|  | 			Ignore(client, aTargetList[i]); | ||||||
|  | 	} | ||||||
|  | 	UpdateIgnored(); | ||||||
|  | 
 | ||||||
|  | 	PrintToChat(client, "\x04[Self-Mute]\x01 You have self-muted:\x04 %s", sTargetName); | ||||||
|  | 
 | ||||||
|  | 	return Plugin_Handled; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public Action Command_SelfUnMute(int client, int args) | ||||||
|  | { | ||||||
|  | 	if(client == 0) | ||||||
|  | 	{ | ||||||
|  | 		PrintToServer("[SM] Cannot use command from server console."); | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if(args < 1) | ||||||
|  | 	{ | ||||||
|  | 		DisplayUnMuteMenu(client); | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	char Argument[65]; | ||||||
|  | 	GetCmdArgString(Argument, sizeof(Argument)); | ||||||
|  | 
 | ||||||
|  | 	char Filtered[65]; | ||||||
|  | 	strcopy(Filtered, sizeof(Filtered), Argument); | ||||||
|  | 	StripQuotes(Filtered); | ||||||
|  | 	TrimString(Filtered); | ||||||
|  | 
 | ||||||
|  | 	if(StrEqual(Filtered, "@me", false)) | ||||||
|  | 	{ | ||||||
|  | 		PrintToChat(client, "\x04[Self-Mute]\x01 Unmuting won't work either."); | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if(UnMuteSpecial(client, Filtered)) | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 
 | ||||||
|  | 	char sTargetName[MAX_TARGET_LENGTH]; | ||||||
|  | 	int aTargetList[MAXPLAYERS]; | ||||||
|  | 	int TargetCount; | ||||||
|  | 	bool TnIsMl; | ||||||
|  | 
 | ||||||
|  | 	if((TargetCount = ProcessTargetString( | ||||||
|  | 			Argument, | ||||||
|  | 			client, | ||||||
|  | 			aTargetList, | ||||||
|  | 			MAXPLAYERS, | ||||||
|  | 			COMMAND_FILTER_CONNECTED|COMMAND_FILTER_NO_IMMUNITY, | ||||||
|  | 			sTargetName, | ||||||
|  | 			sizeof(sTargetName), | ||||||
|  | 			TnIsMl)) <= 0) | ||||||
|  | 	{ | ||||||
|  | 		ReplyToTargetError(client, TargetCount); | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for(int i = 0; i < TargetCount; i++) | ||||||
|  | 	{ | ||||||
|  | 		if(aTargetList[i] != client) | ||||||
|  | 			UnIgnore(client, aTargetList[i]); | ||||||
|  | 	} | ||||||
|  | 	UpdateIgnored(); | ||||||
|  | 
 | ||||||
|  | 	PrintToChat(client, "\x04[Self-Mute]\x01 You have self-unmuted:\x04 %s", sTargetName); | ||||||
|  | 
 | ||||||
|  | 	return Plugin_Handled; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public Action Command_CheckMutes(int client, int args) | ||||||
|  | { | ||||||
|  | 	if(client == 0) | ||||||
|  | 	{ | ||||||
|  | 		PrintToServer("[SM] Cannot use command from server console."); | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	char aBuf[1024]; | ||||||
|  | 	char aBuf2[MAX_NAME_LENGTH]; | ||||||
|  | 	for(int i = 1; i <= MaxClients; i++) | ||||||
|  | 	{ | ||||||
|  | 		if(GetIgnored(client, i)) | ||||||
|  | 		{ | ||||||
|  | 			GetClientName(i, aBuf2, sizeof(aBuf2)); | ||||||
|  | 			StrCat(aBuf, sizeof(aBuf), aBuf2); | ||||||
|  | 			StrCat(aBuf, sizeof(aBuf), ", "); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Cut off last ', ' | ||||||
|  | 	if(strlen(aBuf)) | ||||||
|  | 	{ | ||||||
|  | 		aBuf[strlen(aBuf) - 2] = 0; | ||||||
|  | 		PrintToChat(client, "\x04[Self-Mute]\x01 You have self-muted:\x04 %s", aBuf); | ||||||
|  | 	} | ||||||
|  | 	else if(!g_SpecialMutes[client]) | ||||||
|  | 		PrintToChat(client, "\x04[Self-Mute]\x01 You have not self-muted anyone!\x04", aBuf); | ||||||
|  | 
 | ||||||
|  | 	if(g_SpecialMutes[client]) | ||||||
|  | 	{ | ||||||
|  | 		aBuf[0] = 0; | ||||||
|  | 		FormatSpecialMutes(g_SpecialMutes[client], aBuf, sizeof(aBuf)); | ||||||
|  | 		PrintToChat(client, "\x04[Self-Mute]\x01 You have self-muted group:\x04 %s", aBuf); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return Plugin_Handled; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* | ||||||
|  |  * MENU | ||||||
|  | */ | ||||||
|  | void DisplayMuteMenu(int client) | ||||||
|  | { | ||||||
|  | 	Menu menu = new Menu(MenuHandler_MuteMenu, MenuAction_Select|MenuAction_Cancel|MenuAction_End|MenuAction_DrawItem|MenuAction_DisplayItem); | ||||||
|  | 	menu.ExitButton = true; | ||||||
|  | 
 | ||||||
|  | 	int[] aClients = new int[MaxClients + 1]; | ||||||
|  | 
 | ||||||
|  | 	if(g_Plugin_voiceannounce_ex) | ||||||
|  | 	{ | ||||||
|  | 		// Count talking players and insert id's into aClients array | ||||||
|  | 		int CurrentlyTalking = 0; | ||||||
|  | 		for(int i = 1; i <= MaxClients; i++) | ||||||
|  | 		{ | ||||||
|  | 			if(i != client && IsClientInGame(i) && !IsFakeClient(i) && IsClientSpeaking(i)) | ||||||
|  | 				aClients[CurrentlyTalking++] = i; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if(CurrentlyTalking > 0) | ||||||
|  | 		{ | ||||||
|  | 			// insert player names into g_PlayerNames array | ||||||
|  | 			for(int i = 0; i < CurrentlyTalking; i++) | ||||||
|  | 				GetClientName(aClients[i], g_PlayerNames[aClients[i]], sizeof(g_PlayerNames[])); | ||||||
|  | 
 | ||||||
|  | 			// sort aClients array by player name | ||||||
|  | 			SortCustom1D(aClients, CurrentlyTalking, SortByPlayerName); | ||||||
|  | 
 | ||||||
|  | 			// insert players sorted | ||||||
|  | 			char aBuf[11]; | ||||||
|  | 			for(int i = 0; i < CurrentlyTalking; i++) | ||||||
|  | 			{ | ||||||
|  | 				IntToString(GetClientUserId(aClients[i]), aBuf, sizeof(aBuf)); | ||||||
|  | 				menu.AddItem(aBuf, g_PlayerNames[aClients[i]]); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			// insert spacers | ||||||
|  | 			int Entries = 7 - CurrentlyTalking % 7; | ||||||
|  | 			while(Entries--) | ||||||
|  | 				menu.AddItem("", "", ITEMDRAW_RAWLINE); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	menu.AddItem("@all", "Everyone"); | ||||||
|  | 	menu.AddItem("@spec", "Spectators"); | ||||||
|  | 	menu.AddItem("@ct", "Counter-Terrorists"); | ||||||
|  | 	menu.AddItem("@t", "Terrorists"); | ||||||
|  | 	menu.AddItem("@dead", "Dead players"); | ||||||
|  | 	menu.AddItem("@alive", "Alive players"); | ||||||
|  | 	if(g_Plugin_AdvancedTargeting) | ||||||
|  | 		menu.AddItem("@!friends", "Not Steam friend"); | ||||||
|  | 	else | ||||||
|  | 		menu.AddItem("", "", ITEMDRAW_RAWLINE); | ||||||
|  | 
 | ||||||
|  | 	// Count valid players and insert id's into aClients array | ||||||
|  | 	int Players = 0; | ||||||
|  | 	for(int i = 1; i <= MaxClients; i++) | ||||||
|  | 	{ | ||||||
|  | 		if(i != client && IsClientInGame(i) && !IsFakeClient(i)) | ||||||
|  | 			aClients[Players++] = i; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// insert player names into g_PlayerNames array | ||||||
|  | 	for(int i = 0; i < Players; i++) | ||||||
|  | 		GetClientName(aClients[i], g_PlayerNames[aClients[i]], sizeof(g_PlayerNames[])); | ||||||
|  | 
 | ||||||
|  | 	// sort aClients array by player name | ||||||
|  | 	SortCustom1D(aClients, Players, SortByPlayerName); | ||||||
|  | 
 | ||||||
|  | 	// insert players sorted | ||||||
|  | 	char aBuf[12]; | ||||||
|  | 	for(int i = 0; i < Players; i++) | ||||||
|  | 	{ | ||||||
|  | 		IntToString(GetClientUserId(aClients[i]), aBuf, sizeof(aBuf)); | ||||||
|  | 		menu.AddItem(aBuf, g_PlayerNames[aClients[i]]); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	menu.Display(client, MENU_TIME_FOREVER); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public int MenuHandler_MuteMenu(Menu menu, MenuAction action, int param1, int param2) | ||||||
|  | { | ||||||
|  | 	switch(action) | ||||||
|  | 	{ | ||||||
|  | 		case MenuAction_End: | ||||||
|  | 		{ | ||||||
|  | 			if(param1 != MenuEnd_Selected) | ||||||
|  | 				CloseHandle(menu); | ||||||
|  | 		} | ||||||
|  | 		case MenuAction_Select: | ||||||
|  | 		{ | ||||||
|  | 			int Style; | ||||||
|  | 			char aItem[32]; | ||||||
|  | 			char aDisp[MAX_NAME_LENGTH + 4]; | ||||||
|  | 			menu.GetItem(param2, aItem, sizeof(aItem), Style, aDisp, sizeof(aDisp)); | ||||||
|  | 
 | ||||||
|  | 			if(Style != ITEMDRAW_DEFAULT || !aItem[0]) | ||||||
|  | 			{ | ||||||
|  | 				PrintToChat(param1, "Internal error: aItem[0] -> %d | Style -> %d", aItem[0], Style); | ||||||
|  | 				return 0; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			if(aItem[0] == '@') | ||||||
|  | 			{ | ||||||
|  | 				int Flag = GetSpecialMutesFlags(aItem); | ||||||
|  | 				if(Flag && g_SpecialMutes[param1] & Flag) | ||||||
|  | 					UnMuteSpecial(param1, aItem); | ||||||
|  | 				else | ||||||
|  | 					MuteSpecial(param1, aItem); | ||||||
|  | 
 | ||||||
|  | 				menu.DisplayAt(param1, GetMenuSelectionPosition(), MENU_TIME_FOREVER); | ||||||
|  | 				return 0; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			int UserId = StringToInt(aItem); | ||||||
|  | 			int client = GetClientOfUserId(UserId); | ||||||
|  | 			if(!client) | ||||||
|  | 			{ | ||||||
|  | 				PrintToChat(param1, "\x04[Self-Mute]\x01 Player no longer available."); | ||||||
|  | 				menu.DisplayAt(param1, GetMenuSelectionPosition(), MENU_TIME_FOREVER); | ||||||
|  | 				return 0; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			if(GetIgnored(param1, client)) | ||||||
|  | 			{ | ||||||
|  | 				UnIgnore(param1, client); | ||||||
|  | 				PrintToChat(param1, "\x04[Self-Mute]\x01 You have self-unmuted:\x04 %N", client); | ||||||
|  | 			} | ||||||
|  | 			else | ||||||
|  | 			{ | ||||||
|  | 				Ignore(param1, client); | ||||||
|  | 				PrintToChat(param1, "\x04[Self-Mute]\x01 You have self-muted:\x04 %N", client); | ||||||
|  | 			} | ||||||
|  | 			menu.DisplayAt(param1, GetMenuSelectionPosition(), MENU_TIME_FOREVER); | ||||||
|  | 			return 0; | ||||||
|  | 		} | ||||||
|  | 		case MenuAction_DrawItem: | ||||||
|  | 		{ | ||||||
|  | 			int Style; | ||||||
|  | 			char aItem[32]; | ||||||
|  | 			menu.GetItem(param2, aItem, sizeof(aItem), Style); | ||||||
|  | 
 | ||||||
|  | 			if(!aItem[0]) | ||||||
|  | 				return ITEMDRAW_DISABLED; | ||||||
|  | 
 | ||||||
|  | 			if(aItem[0] == '@') | ||||||
|  | 			{ | ||||||
|  | 				int Flag = GetSpecialMutesFlags(aItem); | ||||||
|  | 				if(Flag & MUTE_ALL) | ||||||
|  | 					return Style; | ||||||
|  | 				else if(g_SpecialMutes[param1] & MUTE_ALL) | ||||||
|  | 					return ITEMDRAW_DISABLED; | ||||||
|  | 
 | ||||||
|  | 				return Style; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			int UserId = StringToInt(aItem); | ||||||
|  | 			int client = GetClientOfUserId(UserId); | ||||||
|  | 			if(!client) // Player disconnected | ||||||
|  | 				return ITEMDRAW_DISABLED; | ||||||
|  | 
 | ||||||
|  | 			return Style; | ||||||
|  | 		} | ||||||
|  | 		case MenuAction_DisplayItem: | ||||||
|  | 		{ | ||||||
|  | 			int Style; | ||||||
|  | 			char aItem[32]; | ||||||
|  | 			char aDisp[MAX_NAME_LENGTH + 4]; | ||||||
|  | 			menu.GetItem(param2, aItem, sizeof(aItem), Style, aDisp, sizeof(aDisp)); | ||||||
|  | 
 | ||||||
|  | 			// Start of current page | ||||||
|  | 			if((param2 + 1) % 7 == 1) | ||||||
|  | 			{ | ||||||
|  | 				if(aItem[0] == '@') | ||||||
|  | 					menu.SetTitle("[Self-Mute] Groups"); | ||||||
|  | 				else if(param2 == 0) | ||||||
|  | 					menu.SetTitle("[Self-Mute] Talking players"); | ||||||
|  | 				else | ||||||
|  | 					menu.SetTitle("[Self-Mute] All players"); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			if(!aItem[0]) | ||||||
|  | 				return 0; | ||||||
|  | 
 | ||||||
|  | 			if(aItem[0] == '@') | ||||||
|  | 			{ | ||||||
|  | 				int Flag = GetSpecialMutesFlags(aItem); | ||||||
|  | 				if(Flag && g_SpecialMutes[param1] & Flag) | ||||||
|  | 				{ | ||||||
|  | 					char aBuf[32] = "[M] "; | ||||||
|  | 					FormatSpecialMutes(Flag, aBuf, sizeof(aBuf)); | ||||||
|  | 					if(!StrEqual(aDisp, aBuf)) | ||||||
|  | 						return RedrawMenuItem(aBuf); | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				return 0; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			int UserId = StringToInt(aItem); | ||||||
|  | 			int client = GetClientOfUserId(UserId); | ||||||
|  | 			if(!client) // Player disconnected | ||||||
|  | 			{ | ||||||
|  | 				char aBuf[MAX_NAME_LENGTH + 4] = "[D] "; | ||||||
|  | 				StrCat(aBuf, sizeof(aBuf), aDisp); | ||||||
|  | 				if(!StrEqual(aDisp, aBuf)) | ||||||
|  | 					return RedrawMenuItem(aBuf); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			if(GetIgnored(param1, client)) | ||||||
|  | 			{ | ||||||
|  | 				char aBuf[MAX_NAME_LENGTH + 4] = "[M] "; | ||||||
|  | 				GetClientName(client, g_PlayerNames[client], sizeof(g_PlayerNames[])); | ||||||
|  | 				StrCat(aBuf, sizeof(aBuf), g_PlayerNames[client]); | ||||||
|  | 				if(!StrEqual(aDisp, aBuf)) | ||||||
|  | 					return RedrawMenuItem(aBuf); | ||||||
|  | 			} | ||||||
|  | 			else | ||||||
|  | 			{ | ||||||
|  | 				GetClientName(client, g_PlayerNames[client], sizeof(g_PlayerNames[])); | ||||||
|  | 				if(!StrEqual(aDisp, g_PlayerNames[client])) | ||||||
|  | 					return RedrawMenuItem(g_PlayerNames[client]); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			return 0; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void DisplayUnMuteMenu(int client) | ||||||
|  | { | ||||||
|  | 	// TODO: Implement me | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* | ||||||
|  |  * HOOKS | ||||||
|  | */ | ||||||
|  | int g_MsgDest; | ||||||
|  | int g_MsgClient; | ||||||
|  | char g_MsgName[256]; | ||||||
|  | char g_MsgParam1[256]; | ||||||
|  | char g_MsgParam2[256]; | ||||||
|  | char g_MsgParam3[256]; | ||||||
|  | char g_MsgParam4[256]; | ||||||
|  | int g_MsgPlayersNum; | ||||||
|  | int g_MsgPlayers[MAXPLAYERS + 1]; | ||||||
|  | 
 | ||||||
|  | int g_TimerDerp = 0; | ||||||
|  | 
 | ||||||
|  | public Action Hook_UserMessageRadioText(UserMsg msg_id, Handle bf, const int[] players, int playersNum, bool reliable, bool init) | ||||||
|  | { | ||||||
|  | 	g_MsgDest = BfReadByte(bf); | ||||||
|  | 	g_MsgClient = BfReadByte(bf); | ||||||
|  | 	BfReadString(bf, g_MsgName, sizeof(g_MsgName), false); | ||||||
|  | 	BfReadString(bf, g_MsgParam1, sizeof(g_MsgParam1), false); | ||||||
|  | 	BfReadString(bf, g_MsgParam2, sizeof(g_MsgParam2), false); | ||||||
|  | 	BfReadString(bf, g_MsgParam3, sizeof(g_MsgParam3), false); | ||||||
|  | 	BfReadString(bf, g_MsgParam4, sizeof(g_MsgParam4), false); | ||||||
|  | 
 | ||||||
|  | 	g_MsgPlayersNum = playersNum; | ||||||
|  | 	for(int i = 0; i < playersNum; i++) | ||||||
|  | 		g_MsgPlayers[i] = players[i]; | ||||||
|  | 
 | ||||||
|  | 	if(!g_TimerDerp) | ||||||
|  | 		CreateTimer(0.1, Timer_PlayerRadio); | ||||||
|  | 
 | ||||||
|  | 	g_TimerDerp++; | ||||||
|  | 	if(g_TimerDerp > 1) | ||||||
|  | 		PrintToServer("DEBUG: Timer_PlayerRadio derped! (%d)", g_TimerDerp); | ||||||
|  | 
 | ||||||
|  | 	return Plugin_Handled; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | char g_MsgRadioSound[256]; | ||||||
|  | 
 | ||||||
|  | public Action Hook_UserMessageSendAudio(UserMsg msg_id, Handle bf, const int[] players, int playersNum, bool reliable, bool init) | ||||||
|  | { | ||||||
|  | 	BfReadString(bf, g_MsgRadioSound, sizeof(g_MsgRadioSound), false); | ||||||
|  | 
 | ||||||
|  | 	return Plugin_Handled; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public Action Timer_PlayerRadio(Handle timer) | ||||||
|  | { | ||||||
|  | 	g_TimerDerp = 0; | ||||||
|  | 	if(g_MsgClient == -1) | ||||||
|  | 		return Plugin_Continue; | ||||||
|  | 
 | ||||||
|  | 	int[] players = new int[g_MsgPlayersNum + 1]; | ||||||
|  | 	int playersNum = 0; | ||||||
|  | 
 | ||||||
|  | 	for(int i = 0; i < g_MsgPlayersNum; i++) | ||||||
|  | 	{ | ||||||
|  | 		int client = g_MsgPlayers[i]; | ||||||
|  | 		if(IsClientInGame(client) && !GetIgnored(client, g_MsgClient)) | ||||||
|  | 			players[playersNum++] = client; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	Handle RadioText = StartMessage("RadioText", players, playersNum, USERMSG_RELIABLE | USERMSG_BLOCKHOOKS); | ||||||
|  | 	BfWriteByte(RadioText, g_MsgDest); | ||||||
|  | 	BfWriteByte(RadioText, g_MsgClient); | ||||||
|  | 	BfWriteString(RadioText, g_MsgName); | ||||||
|  | 	BfWriteString(RadioText, g_MsgParam1); | ||||||
|  | 	BfWriteString(RadioText, g_MsgParam2); | ||||||
|  | 	BfWriteString(RadioText, g_MsgParam3); | ||||||
|  | 	BfWriteString(RadioText, g_MsgParam4); | ||||||
|  | 	EndMessage(); | ||||||
|  | 
 | ||||||
|  | 	Handle SendAudio = StartMessage("SendAudio", players, playersNum, USERMSG_RELIABLE | USERMSG_BLOCKHOOKS); | ||||||
|  | 	BfWriteString(SendAudio, g_MsgRadioSound); | ||||||
|  | 	EndMessage(); | ||||||
|  | 
 | ||||||
|  | 	g_MsgClient = -1; | ||||||
|  | 
 | ||||||
|  | 	return Plugin_Continue; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* | ||||||
|  |  * HELPERS | ||||||
|  | */ | ||||||
|  | void UpdateIgnored() | ||||||
|  | { | ||||||
|  | 	if(g_Plugin_ccc) | ||||||
|  | 		CCC_UpdateIgnoredArray(g_Ignored); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public int SortByPlayerName(int elem1, int elem2, const int[] array, Handle hndl) | ||||||
|  | { | ||||||
|  | 	return strcmp(g_PlayerNames[elem1], g_PlayerNames[elem2], false); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool GetIgnored(int client, int target) | ||||||
|  | { | ||||||
|  | 	return g_Ignored[(client * (MAXPLAYERS + 1) + target)]; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void SetIgnored(int client, int target, bool ignored) | ||||||
|  | { | ||||||
|  | 	g_Ignored[(client * (MAXPLAYERS + 1) + target)] = ignored; | ||||||
|  | } | ||||||
							
								
								
									
										1
									
								
								SelfMute/scripting/include/AdvancedTargeting.inc
									
									
									
									
									
										Symbolic link
									
								
							
							
						
						
									
										1
									
								
								SelfMute/scripting/include/AdvancedTargeting.inc
									
									
									
									
									
										Symbolic link
									
								
							| @ -0,0 +1 @@ | |||||||
|  | ../../../AdvancedTargeting/scripting/include/AdvancedTargeting.inc | ||||||
							
								
								
									
										1
									
								
								SelfMute/scripting/include/ccc.inc
									
									
									
									
									
										Symbolic link
									
								
							
							
						
						
									
										1
									
								
								SelfMute/scripting/include/ccc.inc
									
									
									
									
									
										Symbolic link
									
								
							| @ -0,0 +1 @@ | |||||||
|  | ../../../custom-chatcolors/scripting/include/ccc.inc | ||||||
							
								
								
									
										1
									
								
								SelfMute/scripting/include/voiceannounce_ex.inc
									
									
									
									
									
										Symbolic link
									
								
							
							
						
						
									
										1
									
								
								SelfMute/scripting/include/voiceannounce_ex.inc
									
									
									
									
									
										Symbolic link
									
								
							| @ -0,0 +1 @@ | |||||||
|  | ../../../voiceannounce_ex/scripting/include/voiceannounce_ex.inc | ||||||
							
								
								
									
										1
									
								
								SelfMute/scripting/include/zombiereloaded.inc
									
									
									
									
									
										Symbolic link
									
								
							
							
						
						
									
										1
									
								
								SelfMute/scripting/include/zombiereloaded.inc
									
									
									
									
									
										Symbolic link
									
								
							| @ -0,0 +1 @@ | |||||||
|  | ../../../includes/zombiereloaded.inc | ||||||
							
								
								
									
										208
									
								
								Status/scripting/Status.sp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										208
									
								
								Status/scripting/Status.sp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,208 @@ | |||||||
|  | #pragma semicolon 1 | ||||||
|  | //==================================================================================================== | ||||||
|  | // | ||||||
|  | // Name: Status Fixer. | ||||||
|  | // Author: zaCade + BotoX | ||||||
|  | // Description: Fixes the 'status' command. | ||||||
|  | // | ||||||
|  | //==================================================================================================== | ||||||
|  | #include <sourcemod> | ||||||
|  | #include <sdktools> | ||||||
|  | 
 | ||||||
|  | #pragma newdecls required | ||||||
|  | 
 | ||||||
|  | ConVar g_Cvar_HostIP; | ||||||
|  | ConVar g_Cvar_HostPort; | ||||||
|  | ConVar g_Cvar_HostName; | ||||||
|  | ConVar g_Cvar_HostTags; | ||||||
|  | 
 | ||||||
|  | Handle g_hPlayerList[MAXPLAYERS + 1] = {INVALID_HANDLE, ...}; | ||||||
|  | bool g_bDataAvailable = false; | ||||||
|  | 
 | ||||||
|  | //---------------------------------------------------------------------------------------------------- | ||||||
|  | // Purpose: | ||||||
|  | //---------------------------------------------------------------------------------------------------- | ||||||
|  | public Plugin myinfo = | ||||||
|  | { | ||||||
|  | 	name         = "Status Fixer", | ||||||
|  | 	author       = "zaCade + BotoX", | ||||||
|  | 	description  = "Fixes the 'status' command", | ||||||
|  | 	version      = "1.1", | ||||||
|  | 	url          = "" | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | //---------------------------------------------------------------------------------------------------- | ||||||
|  | // Purpose: | ||||||
|  | //---------------------------------------------------------------------------------------------------- | ||||||
|  | public void OnPluginStart() | ||||||
|  | { | ||||||
|  | 	g_Cvar_HostIP   = FindConVar("hostip"); | ||||||
|  | 	g_Cvar_HostPort = FindConVar("hostport"); | ||||||
|  | 	g_Cvar_HostName = FindConVar("hostname"); | ||||||
|  | 	g_Cvar_HostTags = FindConVar("sv_tags"); | ||||||
|  | 
 | ||||||
|  | 	AddCommandListener(Command_Status, "status"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | //---------------------------------------------------------------------------------------------------- | ||||||
|  | // Purpose: | ||||||
|  | //---------------------------------------------------------------------------------------------------- | ||||||
|  | public Action Command_Status(int client, const char[] command, int args) | ||||||
|  | { | ||||||
|  | 	if(client) | ||||||
|  | 	{ | ||||||
|  | 		if(g_hPlayerList[client] != INVALID_HANDLE) | ||||||
|  | 			return Plugin_Handled; | ||||||
|  | 
 | ||||||
|  | 		static char sServerName[128]; | ||||||
|  | 		static char sServerTags[128]; | ||||||
|  | 		static char sServerAdress[128]; | ||||||
|  | 
 | ||||||
|  | 		int iServerIP   = g_Cvar_HostIP.IntValue; | ||||||
|  | 		int iServerPort = g_Cvar_HostPort.IntValue; | ||||||
|  | 
 | ||||||
|  | 		g_Cvar_HostName.GetString(sServerName, sizeof(sServerName)); | ||||||
|  | 		g_Cvar_HostTags.GetString(sServerTags, sizeof(sServerTags)); | ||||||
|  | 
 | ||||||
|  | 		Format(sServerAdress, sizeof(sServerAdress), "%d.%d.%d.%d:%d", iServerIP >>> 24 & 255, iServerIP >>> 16 & 255, iServerIP >>> 8 & 255, iServerIP & 255, iServerPort); | ||||||
|  | 
 | ||||||
|  | 		static char sMapName[128]; | ||||||
|  | 		GetCurrentMap(sMapName, sizeof(sMapName)); | ||||||
|  | 
 | ||||||
|  | 		float fPosition[3]; | ||||||
|  | 		GetClientAbsOrigin(client, fPosition); | ||||||
|  | 
 | ||||||
|  | 		int iRealClients; | ||||||
|  | 		int iFakeClients; | ||||||
|  | 		int iTotalClients; | ||||||
|  | 
 | ||||||
|  | 		for(int player = 1; player <= MaxClients; player++) | ||||||
|  | 		{ | ||||||
|  | 			if(IsClientConnected(player)) | ||||||
|  | 			{ | ||||||
|  | 				iTotalClients++; | ||||||
|  | 
 | ||||||
|  | 				if(IsFakeClient(player)) | ||||||
|  | 					iFakeClients++; | ||||||
|  | 				else | ||||||
|  | 					iRealClients++; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		static char sSendBuffer[1000]; | ||||||
|  | 		int iBufLength = 0; | ||||||
|  | 		Format(sSendBuffer, sizeof(sSendBuffer), "hostname: %s\n", sServerName); | ||||||
|  | 		Format(sSendBuffer, sizeof(sSendBuffer), "%stickrate: %d\n", sSendBuffer, RoundToZero(1.0 / GetTickInterval())); | ||||||
|  | 		Format(sSendBuffer, sizeof(sSendBuffer), "%sudp/ip  : %s\n", sSendBuffer, sServerAdress); | ||||||
|  | 		Format(sSendBuffer, sizeof(sSendBuffer), "%smap     : %s at: %.0f x, %.0f y, %.0f z\n", sSendBuffer, sMapName, fPosition[0], fPosition[1], fPosition[2]); | ||||||
|  | 		Format(sSendBuffer, sizeof(sSendBuffer), "%stags    : %s\n", sSendBuffer, sServerTags); | ||||||
|  | 		Format(sSendBuffer, sizeof(sSendBuffer), "%s%edicts : %d/%d/%d (used/max/free)\n", sSendBuffer, GetEntityCount(), GetMaxEntities(), GetMaxEntities() - GetEntityCount()); | ||||||
|  | 		Format(sSendBuffer, sizeof(sSendBuffer), "%splayers : %d humans | %d bots (%d/%d)\n", sSendBuffer, iRealClients, iFakeClients, iTotalClients, MaxClients); | ||||||
|  | 		Format(sSendBuffer, sizeof(sSendBuffer), "%s# %8s %40s %24s %12s %4s %4s %s", sSendBuffer, "userid", "name", "uniqueid", "connected", "ping", "loss", "state"); | ||||||
|  | 
 | ||||||
|  | 		g_hPlayerList[client] = CreateArray(ByteCountToCells(1000)); | ||||||
|  | 
 | ||||||
|  | 		PushArrayString(g_hPlayerList[client], sSendBuffer); | ||||||
|  | 		g_bDataAvailable = true; | ||||||
|  | 		sSendBuffer[0] = 0; | ||||||
|  | 
 | ||||||
|  | 		for(int player = 1; player <= MaxClients; player++) | ||||||
|  | 		{ | ||||||
|  | 			if(IsClientConnected(player)) | ||||||
|  | 			{ | ||||||
|  | 				static char sPlayerID[8]; | ||||||
|  | 				static char sPlayerName[40]; | ||||||
|  | 				char sPlayerAuth[24]; | ||||||
|  | 				char sPlayerTime[12]; | ||||||
|  | 				char sPlayerPing[4]; | ||||||
|  | 				char sPlayerLoss[4]; | ||||||
|  | 				static char sPlayerState[16]; | ||||||
|  | 
 | ||||||
|  | 				Format(sPlayerID, sizeof(sPlayerID), "%d", GetClientUserId(player)); | ||||||
|  | 				Format(sPlayerName, sizeof(sPlayerName), "\"%N\"", player); | ||||||
|  | 
 | ||||||
|  | 				if(!GetClientAuthId(player, AuthId_Steam2, sPlayerAuth, sizeof(sPlayerAuth))) | ||||||
|  | 					Format(sPlayerAuth, sizeof(sPlayerAuth), "STEAM_ID_PENDING"); | ||||||
|  | 
 | ||||||
|  | 				if(!IsFakeClient(player)) | ||||||
|  | 				{ | ||||||
|  | 					int iHours   = RoundToFloor((GetClientTime(player) / 3600)); | ||||||
|  | 					int iMinutes = RoundToFloor((GetClientTime(player) - (iHours * 3600)) / 60); | ||||||
|  | 					int iSeconds = RoundToFloor((GetClientTime(player) - (iHours * 3600)) - (iMinutes * 60)); | ||||||
|  | 
 | ||||||
|  | 					if (iHours) | ||||||
|  | 						Format(sPlayerTime, sizeof(sPlayerTime), "%d:%02d:%02d", iHours, iMinutes, iSeconds); | ||||||
|  | 					else | ||||||
|  | 						Format(sPlayerTime, sizeof(sPlayerTime), "%d:%02d", iMinutes, iSeconds); | ||||||
|  | 
 | ||||||
|  | 					Format(sPlayerPing, sizeof(sPlayerPing), "%d", RoundFloat(GetClientLatency(player, NetFlow_Outgoing) * 800)); | ||||||
|  | 					Format(sPlayerLoss, sizeof(sPlayerLoss), "%d", RoundFloat(GetClientAvgLoss(player, NetFlow_Outgoing) * 100)); | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				if(IsClientInGame(player)) | ||||||
|  | 					Format(sPlayerState, sizeof(sPlayerState), "active"); | ||||||
|  | 				else | ||||||
|  | 					Format(sPlayerState, sizeof(sPlayerState), "spawning"); | ||||||
|  | 
 | ||||||
|  | 				static char sFormatted[128]; | ||||||
|  | 				Format(sFormatted, sizeof(sFormatted), "# %8s %40s %24s %12s %4s %4s %s\n", sPlayerID, sPlayerName, sPlayerAuth, sPlayerTime, sPlayerPing, sPlayerLoss, sPlayerState); | ||||||
|  | 
 | ||||||
|  | 				int iFormattedLength = strlen(sFormatted); | ||||||
|  | 				if(iBufLength + iFormattedLength >= 1000) | ||||||
|  | 				{ | ||||||
|  | 					sSendBuffer[iBufLength - 1] = 0; | ||||||
|  | 					PushArrayString(g_hPlayerList[client], sSendBuffer); | ||||||
|  | 					sSendBuffer[0] = 0; | ||||||
|  | 					iBufLength = 0; | ||||||
|  | 				} | ||||||
|  | 				else | ||||||
|  | 				{ | ||||||
|  | 					StrCat(sSendBuffer, sizeof(sSendBuffer), sFormatted); | ||||||
|  | 					iBufLength += iFormattedLength; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if(iBufLength) | ||||||
|  | 		{ | ||||||
|  | 			sSendBuffer[iBufLength - 1] = 0; | ||||||
|  | 			PushArrayString(g_hPlayerList[client], sSendBuffer); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 	} | ||||||
|  | 	return Plugin_Continue; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | //---------------------------------------------------------------------------------------------------- | ||||||
|  | // Purpose: | ||||||
|  | //---------------------------------------------------------------------------------------------------- | ||||||
|  | public void OnGameFrame() | ||||||
|  | { | ||||||
|  | 	if(!g_bDataAvailable) | ||||||
|  | 		return; | ||||||
|  | 
 | ||||||
|  | 	bool bGotData = false; | ||||||
|  | 	for(int client = 0; client < MAXPLAYERS + 1; client++) | ||||||
|  | 	{ | ||||||
|  | 		if(g_hPlayerList[client] == INVALID_HANDLE) | ||||||
|  | 			continue; | ||||||
|  | 
 | ||||||
|  | 		if(!IsClientInGame(client) || !GetArraySize(g_hPlayerList[client])) | ||||||
|  | 		{ | ||||||
|  | 			CloseHandle(g_hPlayerList[client]); | ||||||
|  | 			g_hPlayerList[client] = INVALID_HANDLE; | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		static char sBuffer[1000]; | ||||||
|  | 		GetArrayString(g_hPlayerList[client], 0, sBuffer, sizeof(sBuffer)); | ||||||
|  | 		RemoveFromArray(g_hPlayerList[client], 0); | ||||||
|  | 
 | ||||||
|  | 		PrintToConsole(client, sBuffer); | ||||||
|  | 		bGotData = true; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if(!bGotData) | ||||||
|  | 		g_bDataAvailable = false; | ||||||
|  | } | ||||||
							
								
								
									
										333
									
								
								StopSound/scripting/StopSound.sp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										333
									
								
								StopSound/scripting/StopSound.sp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,333 @@ | |||||||
|  | #pragma semicolon 1 | ||||||
|  | 
 | ||||||
|  | #include <sourcemod> | ||||||
|  | #include <sdktools> | ||||||
|  | #include <morecolors> | ||||||
|  | 
 | ||||||
|  | #define PLUGIN_NAME 	"Toggle Weapon Sounds" | ||||||
|  | #define PLUGIN_VERSION 	"1.2.0" | ||||||
|  | 
 | ||||||
|  | #define UPDATE_URL	"http://godtony.mooo.com/stopsound/stopsound.txt" | ||||||
|  | 
 | ||||||
|  | new bool:g_bStopSound[MAXPLAYERS+1], bool:g_bHooked; | ||||||
|  | static String:g_sKVPATH[PLATFORM_MAX_PATH]; | ||||||
|  | new Handle:g_hWepSounds; | ||||||
|  | 
 | ||||||
|  | public Plugin:myinfo = | ||||||
|  | { | ||||||
|  | 	name = PLUGIN_NAME, | ||||||
|  | 	author = "GoD-Tony, edit by id/Obus", | ||||||
|  | 	description = "Allows clients to stop hearing weapon sounds", | ||||||
|  | 	version = PLUGIN_VERSION, | ||||||
|  | 	url = "http://www.sourcemod.net/" | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | public OnPluginStart() | ||||||
|  | { | ||||||
|  | 	// Detect game and hook appropriate tempent. | ||||||
|  | 	decl String:sGame[32]; | ||||||
|  | 	GetGameFolderName(sGame, sizeof(sGame)); | ||||||
|  | 
 | ||||||
|  | 	if (StrEqual(sGame, "cstrike")) | ||||||
|  | 	{ | ||||||
|  | 		AddTempEntHook("Shotgun Shot", CSS_Hook_ShotgunShot); | ||||||
|  | 	} | ||||||
|  | 	else if (StrEqual(sGame, "dod")) | ||||||
|  | 	{ | ||||||
|  | 		AddTempEntHook("FireBullets", DODS_Hook_FireBullets); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// TF2/HL2:DM and misc weapon sounds will be caught here. | ||||||
|  | 	AddNormalSoundHook(Hook_NormalSound); | ||||||
|  | 
 | ||||||
|  | 	CreateConVar("sm_stopsound_version", PLUGIN_VERSION, "Toggle Weapon Sounds", FCVAR_NOTIFY|FCVAR_DONTRECORD|FCVAR_REPLICATED); | ||||||
|  | 	RegConsoleCmd("sm_stopsound", Command_StopSound, "Toggle hearing weapon sounds"); | ||||||
|  | 
 | ||||||
|  | 	if (g_hWepSounds != INVALID_HANDLE) | ||||||
|  | 	{ | ||||||
|  | 		CloseHandle(g_hWepSounds); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	g_hWepSounds = CreateKeyValues("WeaponSounds"); | ||||||
|  | 	BuildPath(Path_SM, g_sKVPATH, sizeof(g_sKVPATH), "data/playerprefs.WepSounds.txt"); | ||||||
|  | 
 | ||||||
|  | 	FileToKeyValues(g_hWepSounds, g_sKVPATH); | ||||||
|  | 
 | ||||||
|  | 	// Updater. | ||||||
|  | 	//if (LibraryExists("updater")) | ||||||
|  | 	//{ | ||||||
|  | 	//	Updater_AddPlugin(UPDATE_URL); | ||||||
|  | 	//} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /*public OnLibraryAdded(const String:name[]) | ||||||
|  | { | ||||||
|  | 	if (StrEqual(name, "updater")) | ||||||
|  | 	{ | ||||||
|  | 		Updater_AddPlugin(UPDATE_URL); | ||||||
|  | 	} | ||||||
|  | }*/ | ||||||
|  | 
 | ||||||
|  | public Action:Command_StopSound(client, args) | ||||||
|  | { | ||||||
|  | 	if (client == 0) | ||||||
|  | 	{ | ||||||
|  | 		PrintToServer("[SM] Cannot use command from server console."); | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (args > 0) | ||||||
|  | 	{ | ||||||
|  | 		decl String:Arguments[32]; | ||||||
|  | 		GetCmdArg(1, Arguments, sizeof(Arguments)); | ||||||
|  | 
 | ||||||
|  | 		if (StrEqual(Arguments, "save")) | ||||||
|  | 		{ | ||||||
|  | 			KvRewind(g_hWepSounds); | ||||||
|  | 
 | ||||||
|  | 			decl String:SID[32]; | ||||||
|  | 			GetClientAuthId(client, AuthId_Steam2, SID, sizeof(SID)); | ||||||
|  | 
 | ||||||
|  | 			if (KvJumpToKey(g_hWepSounds, SID, true)) | ||||||
|  | 			{ | ||||||
|  | 				new disabled; | ||||||
|  | 				disabled = KvGetNum(g_hWepSounds, "disabled", 0); | ||||||
|  | 
 | ||||||
|  | 				if (!disabled) | ||||||
|  | 				{ | ||||||
|  | 					//CPrintToChat(client, "[StopSound] Saved entry for STEAMID({green}%s{default}) {green}successfully{default}.", SID); | ||||||
|  | 					KvSetNum(g_hWepSounds, "disabled", 1); | ||||||
|  | 					KvRewind(g_hWepSounds); | ||||||
|  | 					KeyValuesToFile(g_hWepSounds, g_sKVPATH); | ||||||
|  | 
 | ||||||
|  | 					g_bStopSound[client] = true; | ||||||
|  | 					CReplyToCommand(client, "{green}[StopSound]{default} Weapon sounds {red}disabled{default} - {green}entry saved{default}."); | ||||||
|  | 					CheckHooks(); | ||||||
|  | 
 | ||||||
|  | 					return Plugin_Handled; | ||||||
|  | 				} | ||||||
|  | 				else | ||||||
|  | 				{ | ||||||
|  | 					//CPrintToChat(client, "[StopSound] Entry for STEAMID({green}%s{default}) {green}successfully deleted{default}.", SID); | ||||||
|  | 					KvDeleteThis(g_hWepSounds); | ||||||
|  | 					KvRewind(g_hWepSounds); | ||||||
|  | 					KeyValuesToFile(g_hWepSounds, g_sKVPATH); | ||||||
|  | 
 | ||||||
|  | 					g_bStopSound[client] = false; | ||||||
|  | 					CReplyToCommand(client, "{green}[StopSound]{default} Weapon sounds {green}enabled{default} - {red}entry deleted{default}."); | ||||||
|  | 					CheckHooks(); | ||||||
|  | 
 | ||||||
|  | 					return Plugin_Handled; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			KvRewind(g_hWepSounds); | ||||||
|  | 		} | ||||||
|  | 		else if (StrEqual(Arguments, "delete")) | ||||||
|  | 		{ | ||||||
|  | 			KvRewind(g_hWepSounds); | ||||||
|  | 
 | ||||||
|  | 			decl String:SID[32]; | ||||||
|  | 			GetClientAuthId(client, AuthId_Steam2, SID, sizeof(SID)); | ||||||
|  | 
 | ||||||
|  | 			if (KvJumpToKey(g_hWepSounds, SID, false)) | ||||||
|  | 			{ | ||||||
|  | 				g_bStopSound[client] = false; | ||||||
|  | 				CReplyToCommand(client, "{green}[StopSound]{default} Weapon sounds {green}enabled{default} - {red}entry deleted{default}."); | ||||||
|  | 				CheckHooks(); | ||||||
|  | 
 | ||||||
|  | 				KvDeleteThis(g_hWepSounds); | ||||||
|  | 				KvRewind(g_hWepSounds); | ||||||
|  | 				KeyValuesToFile(g_hWepSounds, g_sKVPATH); | ||||||
|  | 
 | ||||||
|  | 				return Plugin_Handled; | ||||||
|  | 			} | ||||||
|  | 			else | ||||||
|  | 			{ | ||||||
|  | 				CPrintToChat(client, "{green}[StopSound]{default} Entry {red}not found{default}."); | ||||||
|  | 				return Plugin_Handled; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			PrintToChat(client, "[SM] Usage sm_stopsound <save|delete>"); | ||||||
|  | 			return Plugin_Handled; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	g_bStopSound[client] = !g_bStopSound[client]; | ||||||
|  | 	CReplyToCommand(client, "{green}[StopSound]{default} Weapon sounds %s.", g_bStopSound[client] ? "{red}disabled{default}" : "{green}enabled{default}"); | ||||||
|  | 	CheckHooks(); | ||||||
|  | 
 | ||||||
|  | 	return Plugin_Handled; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public OnClientPutInServer(client) | ||||||
|  | { | ||||||
|  | 	KvRewind(g_hWepSounds); | ||||||
|  | 
 | ||||||
|  | 	decl String:SID[32]; | ||||||
|  | 	GetClientAuthId(client, AuthId_Steam2, SID, sizeof(SID)); | ||||||
|  | 
 | ||||||
|  | 	if (KvJumpToKey(g_hWepSounds, SID, false)) | ||||||
|  | 	{ | ||||||
|  | 		new disabled; | ||||||
|  | 		disabled = KvGetNum(g_hWepSounds, "disabled", 0); | ||||||
|  | 
 | ||||||
|  | 		if (disabled) | ||||||
|  | 		{ | ||||||
|  | 			g_bStopSound[client] = true; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	CheckHooks(); | ||||||
|  | 	KvRewind(g_hWepSounds); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public OnClientDisconnect_Post(client) | ||||||
|  | { | ||||||
|  | 	g_bStopSound[client] = false; | ||||||
|  | 	CheckHooks(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | CheckHooks() | ||||||
|  | { | ||||||
|  | 	new bool:bShouldHook = false; | ||||||
|  | 
 | ||||||
|  | 	for (new i = 1; i <= MaxClients; i++) | ||||||
|  | 	{ | ||||||
|  | 		if (g_bStopSound[i]) | ||||||
|  | 		{ | ||||||
|  | 			bShouldHook = true; | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Fake (un)hook because toggling actual hooks will cause server instability. | ||||||
|  | 	g_bHooked = bShouldHook; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public Action:Hook_NormalSound(clients[64], &numClients, String:sample[PLATFORM_MAX_PATH], &entity, &channel, &Float:volume, &level, &pitch, &flags) | ||||||
|  | { | ||||||
|  | 	// Ignore non-weapon sounds. | ||||||
|  | 	if (!g_bHooked || !(strncmp(sample, "weapons", 7) == 0 || strncmp(sample[1], "weapons", 7) == 0)) | ||||||
|  | 	{ | ||||||
|  | 		return Plugin_Continue; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	decl i, j; | ||||||
|  | 
 | ||||||
|  | 	for (i = 0; i < numClients; i++) | ||||||
|  | 	{ | ||||||
|  | 		if (g_bStopSound[clients[i]]) | ||||||
|  | 		{ | ||||||
|  | 			// Remove the client from the array. | ||||||
|  | 			for (j = i; j < numClients - 1; j++) | ||||||
|  | 			{ | ||||||
|  | 				clients[j] = clients[j + 1]; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			numClients--; | ||||||
|  | 			i--; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return (numClients > 0) ? Plugin_Changed : Plugin_Stop; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public Action:CSS_Hook_ShotgunShot(const String:te_name[], const Players[], numClients, Float:delay) | ||||||
|  | { | ||||||
|  | 	if (!g_bHooked) | ||||||
|  | 	{ | ||||||
|  | 		return Plugin_Continue; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Check which clients need to be excluded. | ||||||
|  | 	decl newClients[MaxClients], client, i; | ||||||
|  | 	new newTotal = 0; | ||||||
|  | 
 | ||||||
|  | 	for (i = 0; i < numClients; i++) | ||||||
|  | 	{ | ||||||
|  | 		client = Players[i]; | ||||||
|  | 
 | ||||||
|  | 		if (!g_bStopSound[client]) | ||||||
|  | 		{ | ||||||
|  | 			newClients[newTotal++] = client; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// No clients were excluded. | ||||||
|  | 	if (newTotal == numClients) | ||||||
|  | 	{ | ||||||
|  | 		return Plugin_Continue; | ||||||
|  | 	} | ||||||
|  | 	else if (newTotal == 0) // All clients were excluded and there is no need to broadcast. | ||||||
|  | 	{ | ||||||
|  | 		return Plugin_Stop; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Re-broadcast to clients that still need it. | ||||||
|  | 	decl Float:vTemp[3]; | ||||||
|  | 	TE_Start("Shotgun Shot"); | ||||||
|  | 	TE_ReadVector("m_vecOrigin", vTemp); | ||||||
|  | 	TE_WriteVector("m_vecOrigin", vTemp); | ||||||
|  | 	TE_WriteFloat("m_vecAngles[0]", TE_ReadFloat("m_vecAngles[0]")); | ||||||
|  | 	TE_WriteFloat("m_vecAngles[1]", TE_ReadFloat("m_vecAngles[1]")); | ||||||
|  | 	TE_WriteNum("m_iWeaponID", TE_ReadNum("m_iWeaponID")); | ||||||
|  | 	TE_WriteNum("m_iMode", TE_ReadNum("m_iMode")); | ||||||
|  | 	TE_WriteNum("m_iSeed", TE_ReadNum("m_iSeed")); | ||||||
|  | 	TE_WriteNum("m_iPlayer", TE_ReadNum("m_iPlayer")); | ||||||
|  | 	TE_WriteFloat("m_fInaccuracy", TE_ReadFloat("m_fInaccuracy")); | ||||||
|  | 	TE_WriteFloat("m_fSpread", TE_ReadFloat("m_fSpread")); | ||||||
|  | 	TE_Send(newClients, newTotal, delay); | ||||||
|  | 
 | ||||||
|  | 	return Plugin_Stop; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public Action:DODS_Hook_FireBullets(const String:te_name[], const Players[], numClients, Float:delay) | ||||||
|  | { | ||||||
|  | 	if (!g_bHooked) | ||||||
|  | 	{ | ||||||
|  | 		return Plugin_Continue; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Check which clients need to be excluded. | ||||||
|  | 	decl newClients[MaxClients], client, i; | ||||||
|  | 	new newTotal = 0; | ||||||
|  | 
 | ||||||
|  | 	for (i = 0; i < numClients; i++) | ||||||
|  | 	{ | ||||||
|  | 		client = Players[i]; | ||||||
|  | 
 | ||||||
|  | 		if (!g_bStopSound[client]) | ||||||
|  | 		{ | ||||||
|  | 			newClients[newTotal++] = client; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// No clients were excluded. | ||||||
|  | 	if (newTotal == numClients) | ||||||
|  | 	{ | ||||||
|  | 		return Plugin_Continue; | ||||||
|  | 	} | ||||||
|  | 	else if (newTotal == 0)// All clients were excluded and there is no need to broadcast. | ||||||
|  | 	{ | ||||||
|  | 		return Plugin_Stop; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Re-broadcast to clients that still need it. | ||||||
|  | 	decl Float:vTemp[3]; | ||||||
|  | 	TE_Start("FireBullets"); | ||||||
|  | 	TE_ReadVector("m_vecOrigin", vTemp); | ||||||
|  | 	TE_WriteVector("m_vecOrigin", vTemp); | ||||||
|  | 	TE_WriteFloat("m_vecAngles[0]", TE_ReadFloat("m_vecAngles[0]")); | ||||||
|  | 	TE_WriteFloat("m_vecAngles[1]", TE_ReadFloat("m_vecAngles[1]")); | ||||||
|  | 	TE_WriteNum("m_iWeaponID", TE_ReadNum("m_iWeaponID")); | ||||||
|  | 	TE_WriteNum("m_iMode", TE_ReadNum("m_iMode")); | ||||||
|  | 	TE_WriteNum("m_iSeed", TE_ReadNum("m_iSeed")); | ||||||
|  | 	TE_WriteNum("m_iPlayer", TE_ReadNum("m_iPlayer")); | ||||||
|  | 	TE_WriteFloat("m_flSpread", TE_ReadFloat("m_flSpread")); | ||||||
|  | 	TE_Send(newClients, newTotal, delay); | ||||||
|  | 
 | ||||||
|  | 	return Plugin_Stop; | ||||||
|  | } | ||||||
							
								
								
									
										1
									
								
								StopSound/scripting/include/morecolors.inc
									
									
									
									
									
										Symbolic link
									
								
							
							
						
						
									
										1
									
								
								StopSound/scripting/include/morecolors.inc
									
									
									
									
									
										Symbolic link
									
								
							| @ -0,0 +1 @@ | |||||||
|  | ../../../includes/morecolors.inc | ||||||
							
								
								
									
										21
									
								
								SvGravityFix/scripting/SvGravityFix.sp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								SvGravityFix/scripting/SvGravityFix.sp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,21 @@ | |||||||
|  | #pragma semicolon 1 | ||||||
|  | 
 | ||||||
|  | #include <sourcemod> | ||||||
|  | #include <sdktools> | ||||||
|  | 
 | ||||||
|  | #pragma newdecls required | ||||||
|  | 
 | ||||||
|  | public Plugin myinfo = | ||||||
|  | { | ||||||
|  | 	name = "sv_gravity fix", | ||||||
|  | 	author = "BotoX", | ||||||
|  | 	description = "Resets sv_gravity at game_end", | ||||||
|  | 	version = "1.0", | ||||||
|  | 	url = "" | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | public void OnMapEnd() | ||||||
|  | { | ||||||
|  | 	ConVar SvGravity = FindConVar("sv_gravity"); | ||||||
|  | 	SvGravity.IntValue = 800; | ||||||
|  | } | ||||||
							
								
								
									
										274
									
								
								WeaponCleaner/scripting/WeaponCleaner.sp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										274
									
								
								WeaponCleaner/scripting/WeaponCleaner.sp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,274 @@ | |||||||
|  | #pragma semicolon 1 | ||||||
|  | 
 | ||||||
|  | #include <sourcemod> | ||||||
|  | #include <sdkhooks> | ||||||
|  | #include <sdktools> | ||||||
|  | 
 | ||||||
|  | #define TIMER_INTERVAL 1.0 | ||||||
|  | Handle g_hTimer = INVALID_HANDLE; | ||||||
|  | 
 | ||||||
|  | ConVar g_CVar_MaxWeapons; | ||||||
|  | ConVar g_CVar_WeaponLifetime; | ||||||
|  | 
 | ||||||
|  | new g_RealRoundStartedTime; | ||||||
|  | new g_MaxWeapons; | ||||||
|  | new g_MaxWeaponLifetime; | ||||||
|  | 
 | ||||||
|  | #define MAX_WEAPONS MAXPLAYERS | ||||||
|  | new G_WeaponArray[MAX_WEAPONS][2]; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | public Plugin myinfo = | ||||||
|  | { | ||||||
|  | 	name 			= "WeaponCleaner", | ||||||
|  | 	author 			= "BotoX", | ||||||
|  | 	description 	= "Clean unneeded weapons", | ||||||
|  | 	version 		= "2.0", | ||||||
|  | 	url 			= "" | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | public void OnPluginStart() | ||||||
|  | { | ||||||
|  | 	RegAdminCmd("sm_sweep", Command_CleanupWeapons, ADMFLAG_GENERIC, "Cleans up all the weapons on the map unless they have a HammerID attached to them."); | ||||||
|  | 
 | ||||||
|  | 	g_CVar_MaxWeapons = CreateConVar("sm_weaponcleaner_max", "5", "The maximum amount of weapons allowed in the game.", 0, true, 0.0, true, MAX_WEAPONS - 1.0); | ||||||
|  | 	g_MaxWeapons = g_CVar_MaxWeapons.IntValue; | ||||||
|  | 	g_CVar_MaxWeapons.AddChangeHook(OnConVarChanged); | ||||||
|  | 
 | ||||||
|  | 	g_CVar_WeaponLifetime = CreateConVar("sm_weaponcleaner_lifetime", "15", "The maximum amount of time in seconds a weapon is allowed in the game.", 0, true, 0.0); | ||||||
|  | 	g_MaxWeaponLifetime = g_CVar_WeaponLifetime.IntValue; | ||||||
|  | 	g_CVar_WeaponLifetime.AddChangeHook(OnConVarChanged); | ||||||
|  | 
 | ||||||
|  | 	HookEvent("round_start", Event_RoundStart); | ||||||
|  | 
 | ||||||
|  | 	AutoExecConfig(true, "plugin.WeaponCleaner"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public void OnConVarChanged(ConVar convar, const char[] oldValue, const char[] newValue) | ||||||
|  | { | ||||||
|  | 	if(convar == g_CVar_MaxWeapons) | ||||||
|  | 	{ | ||||||
|  | 		if(StringToInt(newValue) < StringToInt(oldValue)) | ||||||
|  | 		{ | ||||||
|  | 			// Need to shrink list and kill items | ||||||
|  | 			new d = StringToInt(oldValue) - StringToInt(newValue); | ||||||
|  | 
 | ||||||
|  | 			// Kill items that don't have space anymore | ||||||
|  | 			for(new i = 0; d && i < g_MaxWeapons; i++) | ||||||
|  | 			{ | ||||||
|  | 				if(!G_WeaponArray[i][0]) | ||||||
|  | 					continue; | ||||||
|  | 
 | ||||||
|  | 				// Kill it | ||||||
|  | 				AcceptEntityInput(G_WeaponArray[0][0], "Kill"); | ||||||
|  | 				// This implicitly calls OnEntityDestroyed() which calls RemoveWeapon() | ||||||
|  | 
 | ||||||
|  | 				// Move index backwards (since the list was modified by removing it) | ||||||
|  | 				i--; | ||||||
|  | 				d--; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		g_MaxWeapons = StringToInt(newValue); | ||||||
|  | 	} | ||||||
|  | 	else if(convar == g_CVar_WeaponLifetime) | ||||||
|  | 	{ | ||||||
|  | 		g_MaxWeaponLifetime = StringToInt(newValue); | ||||||
|  | 		CheckWeapons(); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public void OnMapStart() | ||||||
|  | { | ||||||
|  | 	if(g_hTimer != INVALID_HANDLE && CloseHandle(g_hTimer)) | ||||||
|  | 		g_hTimer = INVALID_HANDLE; | ||||||
|  | 
 | ||||||
|  | 	g_hTimer = CreateTimer(TIMER_INTERVAL, Timer_CleanupWeapons, INVALID_HANDLE, TIMER_REPEAT); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public void OnMapEnd() | ||||||
|  | { | ||||||
|  | 	if(g_hTimer != INVALID_HANDLE && CloseHandle(g_hTimer)) | ||||||
|  | 		g_hTimer = INVALID_HANDLE; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public void OnClientPutInServer(int client) | ||||||
|  | { | ||||||
|  | 	SDKHook(client, SDKHook_WeaponDropPost, OnWeaponDrop); | ||||||
|  | 	SDKHook(client, SDKHook_WeaponEquipPost, OnWeaponEquip); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public void OnClientDisconnect(int client) | ||||||
|  | { | ||||||
|  | 	SDKUnhook(client, SDKHook_WeaponDropPost, OnWeaponDrop); | ||||||
|  | 	SDKUnhook(client, SDKHook_WeaponEquipPost, OnWeaponEquip); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public void OnEntityCreated(int entity, const char[] classname) | ||||||
|  | { | ||||||
|  | 	if(IsValidEntity(entity) && strncmp(classname, "weapon_", 7) == 0) | ||||||
|  | 	{ | ||||||
|  | 		SDKHook(entity, SDKHook_Spawn, OnWeaponSpawned); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public void OnEntityDestroyed(int entity) | ||||||
|  | { | ||||||
|  | 	RemoveWeapon(entity); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public void OnWeaponSpawned(int entity) | ||||||
|  | { | ||||||
|  | 	new HammerID = GetEntProp(entity, Prop_Data, "m_iHammerID"); | ||||||
|  | 	// Should not be cleaned since it's a map spawned weapon | ||||||
|  | 	if(HammerID) | ||||||
|  | 		return; | ||||||
|  | 
 | ||||||
|  | 	// Weapon doesn't belong to any player | ||||||
|  | 	if(GetEntPropEnt(entity, Prop_Data, "m_hOwnerEntity") == -1) | ||||||
|  | 		InsertWeapon(entity); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public Action OnWeaponEquip(int client, int entity) | ||||||
|  | { | ||||||
|  | 	if(!IsValidEntity(entity)) | ||||||
|  | 		return; | ||||||
|  | 
 | ||||||
|  | 	new HammerID = GetEntProp(entity, Prop_Data, "m_iHammerID"); | ||||||
|  | 	// Should not be cleaned since it's a map spawned weapon | ||||||
|  | 	if(HammerID) | ||||||
|  | 		return; | ||||||
|  | 
 | ||||||
|  | 	// Weapon should not be cleaned anymore | ||||||
|  | 	RemoveWeapon(entity); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public Action OnWeaponDrop(int client, int entity) | ||||||
|  | { | ||||||
|  | 	if(!IsValidEntity(entity)) | ||||||
|  | 		return; | ||||||
|  | 
 | ||||||
|  | 	new HammerID = GetEntProp(entity, Prop_Data, "m_iHammerID"); | ||||||
|  | 	// Should not be cleaned since it's a map spawned weapon | ||||||
|  | 	if(HammerID) | ||||||
|  | 		return; | ||||||
|  | 
 | ||||||
|  | 	// Kill all dropped weapons during mp_freezetime | ||||||
|  | 	if(GetTime() < g_RealRoundStartedTime) | ||||||
|  | 	{ | ||||||
|  | 		// Kill it | ||||||
|  | 		AcceptEntityInput(entity, "Kill"); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Weapon should be cleaned again | ||||||
|  | 	InsertWeapon(entity); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool InsertWeapon(int entity) | ||||||
|  | { | ||||||
|  | 	// Try to find a free slot | ||||||
|  | 	for(new i = 0; i < g_MaxWeapons; i++) | ||||||
|  | 	{ | ||||||
|  | 		if(G_WeaponArray[i][0]) | ||||||
|  | 			continue; | ||||||
|  | 
 | ||||||
|  | 		// Found a free slot, add it here | ||||||
|  | 		G_WeaponArray[i][0] = entity; | ||||||
|  | 		G_WeaponArray[i][1] = GetTime(); | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// No free slot found | ||||||
|  | 	// Kill the first (oldest) item in the list | ||||||
|  | 	AcceptEntityInput(G_WeaponArray[0][0], "Kill"); | ||||||
|  | 	// This implicitly calls OnEntityDestroyed() which calls RemoveWeapon() | ||||||
|  | 
 | ||||||
|  | 	// Add new weapon to the end of the list | ||||||
|  | 	G_WeaponArray[g_MaxWeapons - 1][0] = entity; | ||||||
|  | 	G_WeaponArray[g_MaxWeapons - 1][1] = GetTime(); | ||||||
|  | 	return true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool RemoveWeapon(int entity) | ||||||
|  | { | ||||||
|  | 	// Find the Weapon | ||||||
|  | 	for(new i = 0; i < g_MaxWeapons; i++) | ||||||
|  | 	{ | ||||||
|  | 		if(G_WeaponArray[i][0] == entity) | ||||||
|  | 		{ | ||||||
|  | 			G_WeaponArray[i][0] = 0; G_WeaponArray[i][1] = 0; | ||||||
|  | 
 | ||||||
|  | 			// Move list items in front of this index back by one | ||||||
|  | 			for(new j = i + 1; j < g_MaxWeapons; j++) | ||||||
|  | 			{ | ||||||
|  | 				G_WeaponArray[j - 1][0] = G_WeaponArray[j][0]; | ||||||
|  | 				G_WeaponArray[j - 1][1] = G_WeaponArray[j][1]; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			// Reset last list item | ||||||
|  | 			G_WeaponArray[g_MaxWeapons - 1][0] = 0; | ||||||
|  | 			G_WeaponArray[g_MaxWeapons - 1][1] = 0; | ||||||
|  | 
 | ||||||
|  | 			return true; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return false; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool CheckWeapons() | ||||||
|  | { | ||||||
|  | 	for(new i = 0; i < g_MaxWeapons; i++) | ||||||
|  | 	{ | ||||||
|  | 		if(!G_WeaponArray[i][0]) | ||||||
|  | 			continue; | ||||||
|  | 
 | ||||||
|  | 		if(GetTime() - G_WeaponArray[i][1] >= g_MaxWeaponLifetime) | ||||||
|  | 		{ | ||||||
|  | 			// Kill it | ||||||
|  | 			AcceptEntityInput(G_WeaponArray[i][0], "Kill"); | ||||||
|  | 			// This implicitly calls OnEntityDestroyed() which calls RemoveWeapon() | ||||||
|  | 
 | ||||||
|  | 			// Move index backwards (since the list was modified by removing it) | ||||||
|  | 			i--; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void CleanupWeapons() | ||||||
|  | { | ||||||
|  | 	for(new i = 0; i < g_MaxWeapons; i++) | ||||||
|  | 	{ | ||||||
|  | 		if(!G_WeaponArray[i][0]) | ||||||
|  | 			continue; | ||||||
|  | 
 | ||||||
|  | 		// Kill it | ||||||
|  | 		AcceptEntityInput(G_WeaponArray[i][0], "Kill"); | ||||||
|  | 		// This implicitly calls OnEntityDestroyed() which calls RemoveWeapon() | ||||||
|  | 
 | ||||||
|  | 		// Move index backwards (since the list was modified by removing it) | ||||||
|  | 		i--; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public Action Event_RoundStart(Handle:event, const char[] name, bool:dontBroadcast) | ||||||
|  | { | ||||||
|  | 	for(new i = 0; i < MAX_WEAPONS; i++) | ||||||
|  | 	{ | ||||||
|  | 		G_WeaponArray[i][0] = 0; G_WeaponArray[i][1] = 0; | ||||||
|  | 	} | ||||||
|  | 	g_RealRoundStartedTime = GetTime() + GetConVarInt(FindConVar("mp_freezetime")); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public Action Timer_CleanupWeapons(Handle:timer) | ||||||
|  | { | ||||||
|  | 	CheckWeapons(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public Action Command_CleanupWeapons(client, args) | ||||||
|  | { | ||||||
|  | 	CleanupWeapons(); | ||||||
|  | 
 | ||||||
|  | 	LogAction(client, -1, "%L performed a weapons cleanup", client); | ||||||
|  | 	PrintToChat(client, "[SM] Weapons cleaned successfully!"); | ||||||
|  | } | ||||||
							
								
								
									
										3307
									
								
								custom-chatcolors/scripting/custom-chatcolors.sp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3307
									
								
								custom-chatcolors/scripting/custom-chatcolors.sp
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										190
									
								
								custom-chatcolors/scripting/include/ccc.inc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										190
									
								
								custom-chatcolors/scripting/include/ccc.inc
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,190 @@ | |||||||
|  | /** | ||||||
|  |  * This is the include file for Custom Chat Colors | ||||||
|  |  * https://forums.alliedmods.net/showthread.php?t=186695 | ||||||
|  |  * To check that Custom Chat Colors is installed and running, verify that the "ccc" library exists | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #if defined _ccc_included
 | ||||||
|  |   #endinput
 | ||||||
|  | #endif
 | ||||||
|  | #define _ccc_included
 | ||||||
|  | 
 | ||||||
|  | enum CCC_ColorType { | ||||||
|  | 	CCC_TagColor, | ||||||
|  | 	CCC_NameColor, | ||||||
|  | 	CCC_ChatColor | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #define COLOR_NULL		-1
 | ||||||
|  | #define COLOR_NONE		-2
 | ||||||
|  | #define COLOR_CGREEN	-3 //0x40FF40
 | ||||||
|  | #define COLOR_OLIVE		-4 //0x99FF99
 | ||||||
|  | #define COLOR_TEAM		-5
 | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Gets a client's color as a hexadecimal integer. | ||||||
|  |  *  | ||||||
|  |  * @param client		Client index | ||||||
|  |  * @param type			Color type to retreive | ||||||
|  |  * @param alpha			Pass a boolean variable by reference here and it will be true if the color has alpha specified or false if it doesn't (or is a stock color) | ||||||
|  |  * @return				Color as a hexadecimal integer (use %X in formatting to get a hexadecimal string) | ||||||
|  |  *  | ||||||
|  |  * On error/errors:		Invalid client index or client is not in game | ||||||
|  |  */ | ||||||
|  | native CCC_GetColor(client, CCC_ColorType:type, &bool:alpha = false); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Sets a client's color as a hexadecimal integer. | ||||||
|  |  *  | ||||||
|  |  * @param client		Client index | ||||||
|  |  * @param type			Color type to set | ||||||
|  |  * @param color			Integer representation of the color (use StringToInt(input, 16) to convert a hexadecimal string) or one of the color defines | ||||||
|  |  * @param alpha			Are you specifying a color with alpha? | ||||||
|  |  * @return				True if the color is updated successfully, false otherwise | ||||||
|  |  *  | ||||||
|  |  * On error/errors:		Invalid client index or client is not in game | ||||||
|  |  */ | ||||||
|  | native bool:CCC_SetColor(client, CCC_ColorType:type, color, bool:alpha); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Gets a client's tag | ||||||
|  |  *  | ||||||
|  |  * @param client		Client index | ||||||
|  |  * @param buffer		Buffer to store the tag in | ||||||
|  |  * @param maxlen		Maximum buffer length | ||||||
|  |  * @noreturn | ||||||
|  |  *  | ||||||
|  |  * On error/errors:		Invalid client index or client is not in game | ||||||
|  |  */ | ||||||
|  | native CCC_GetTag(client, String:buffer[], maxlen); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Sets a client's tag | ||||||
|  |  *  | ||||||
|  |  * @param client		Client index | ||||||
|  |  * @param tag			String containing the new tag | ||||||
|  |  * @noreturn | ||||||
|  |  *  | ||||||
|  |  * On error/errors:		Invalid client index or client is not in game | ||||||
|  |  */ | ||||||
|  | native CCC_SetTag(client, const String:tag[]); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Resets a client's color to the value in the config file. | ||||||
|  |  *  | ||||||
|  |  * @param client		Client index | ||||||
|  |  * @param type			Color type to restore | ||||||
|  |  * @noreturn | ||||||
|  |  *  | ||||||
|  |  * On error/errors:		Invalid client index or client is not in game | ||||||
|  |  */ | ||||||
|  | native CCC_ResetColor(client, CCC_ColorType:type); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Resets a client's tag to the value in the config file. | ||||||
|  |  *  | ||||||
|  |  * @param client		Client index | ||||||
|  |  * @noreturn | ||||||
|  |  *  | ||||||
|  |  * On error/errors:		Invalid client index or client is not in game | ||||||
|  |  */ | ||||||
|  | native CCC_ResetTag(client); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Called when a cilent's name is about to be colored | ||||||
|  |  * DO NOT START A NEW USERMESSAGE (i.e. PrintToChat, PrintToChatAll) WITHIN THIS FORWARD | ||||||
|  |  *  | ||||||
|  |  * @param client		Client index | ||||||
|  |  * @return				Plugin_Handled to prevent coloring, Plugin_Continue to allow coloring | ||||||
|  |  */ | ||||||
|  | #pragma deprecated Use CCC_OnColor instead
 | ||||||
|  | forward Action:CCC_OnNameColor(client); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Called when a client's chat is about to be colored | ||||||
|  |  * DO NOT START A NEW USERMESSAGE (i.e. PrintToChat, PrintToChatAll) WITHIN THIS FORWARD | ||||||
|  |  *  | ||||||
|  |  * @param client		Client index | ||||||
|  |  * @return				Plugin_Handled to prevent coloring, Plugin_Continue to allow coloring | ||||||
|  |  */ | ||||||
|  | #pragma deprecated Use CCC_OnColor instead
 | ||||||
|  | forward Action:CCC_OnChatColor(client); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Called when a client's name is about to be tagged | ||||||
|  |  * DO NOT START A NEW USERMESSAGE (i.e. PrintToChat, PrintToChatAll) WITHIN THIS FORWARD | ||||||
|  |  *  | ||||||
|  |  * @param client		Client index | ||||||
|  |  * @return				Plugin_Handled to prevent tagging, Plugin_Continue to allow tagging | ||||||
|  |  */ | ||||||
|  | #pragma deprecated Use CCC_OnColor instead
 | ||||||
|  | forward Action:CCC_OnTagApplied(client); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Called when a client's name is about to be tagged | ||||||
|  |  * DO NOT START A NEW USERMESSAGE (i.e. PrintToChat, PrintToChatAll) WITHIN THIS FORWARD | ||||||
|  |  *  | ||||||
|  |  * @param client		Client index | ||||||
|  |  * @param message		Chat message that will be printed | ||||||
|  |  * @param type			What type of color will be applied. If this is CCC_TagColor, it controls whether the tag will be applied at all, not whether the tag will be colored. | ||||||
|  |  * @return				Plugin_Handled to prevent coloring, Plugin_Continue to allow coloring | ||||||
|  |  */ | ||||||
|  | forward Action:CCC_OnColor(client, const String:message[], CCC_ColorType:type); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Called when a message has been fully colored and will be sent, unless further plugins modify it through Simple Chat Processor | ||||||
|  |  *  | ||||||
|  |  * @param author		Author client index | ||||||
|  |  * @param message		Message | ||||||
|  |  * @param maxlen		Maximum length of message buffer | ||||||
|  |  * @noreturn | ||||||
|  |  */ | ||||||
|  | forward CCC_OnChatMessage(author, String:message[], maxlen); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Called when a client's colors and tag are about to be loaded from the config file | ||||||
|  |  * At this point, the client has NO COLORS | ||||||
|  |  *  | ||||||
|  |  * @param client		Client index | ||||||
|  |  * @return				Plugin_Handled or Plugin_Stop to prevent loading, Plugin_Continue or Plugin_Changed to allow | ||||||
|  |  */ | ||||||
|  | forward Action:CCC_OnUserConfigPreLoaded(client); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Called when a client's colors and tag have been loaded from the config file | ||||||
|  |  *  | ||||||
|  |  * @param client		Client index | ||||||
|  |  * @noreturn | ||||||
|  |  */ | ||||||
|  | forward CCC_OnUserConfigLoaded(client); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Called when the configuration file is reloaded with the sm_reloadccc command | ||||||
|  |  *  | ||||||
|  |  * @noreturn | ||||||
|  |  */ | ||||||
|  | forward CCC_OnConfigReloaded(); | ||||||
|  | 
 | ||||||
|  | native void CCC_UpdateIgnoredArray(bool IgnoredArray[(MAXPLAYERS + 1) * (MAXPLAYERS + 1)]); | ||||||
|  | 
 | ||||||
|  | public SharedPlugin:__pl_ccc = { | ||||||
|  | 	name = "ccc", | ||||||
|  | 	file = "custom-chatcolors.smx", | ||||||
|  | #if defined REQUIRE_PLUGIN
 | ||||||
|  | 	required = 1 | ||||||
|  | #else
 | ||||||
|  | 	required = 0 | ||||||
|  | #endif
 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #if !defined REQUIRE_PLUGIN
 | ||||||
|  | public __pl_ccc_SetNTVOptional() { | ||||||
|  | 	MarkNativeAsOptional("CCC_GetColor"); | ||||||
|  | 	MarkNativeAsOptional("CCC_SetColor"); | ||||||
|  | 	MarkNativeAsOptional("CCC_GetTag"); | ||||||
|  | 	MarkNativeAsOptional("CCC_ResetTag"); | ||||||
|  | 	MarkNativeAsOptional("CCC_ResetColor"); | ||||||
|  | 	MarkNativeAsOptional("CCC_ResetTag"); | ||||||
|  | 	MarkNativeAsOptional("CCC_UpdateIgnoredArray"); | ||||||
|  | } | ||||||
|  | #endif
 | ||||||
							
								
								
									
										1
									
								
								custom-chatcolors/scripting/include/morecolors.inc
									
									
									
									
									
										Symbolic link
									
								
							
							
						
						
									
										1
									
								
								custom-chatcolors/scripting/include/morecolors.inc
									
									
									
									
									
										Symbolic link
									
								
							| @ -0,0 +1 @@ | |||||||
|  | ../../../includes/morecolors.inc | ||||||
							
								
								
									
										53
									
								
								custom-chatcolors/translations/allchat.phrases.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								custom-chatcolors/translations/allchat.phrases.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,53 @@ | |||||||
|  | "Phrases" | ||||||
|  | { | ||||||
|  | 	"Cstrike_Chat_CT_Loc" | ||||||
|  | 	{ | ||||||
|  | 		"#format"	"{1:s},{2:s}" | ||||||
|  | 		"en"			"(Counter-Terrorist) {1} :  {2}" | ||||||
|  | 	} | ||||||
|  | 	"Cstrike_Chat_CT" | ||||||
|  | 	{ | ||||||
|  | 		"#format"	"{1:s},{2:s}" | ||||||
|  | 		"en"			"(Counter-Terrorist) {1} :  {2}" | ||||||
|  | 	} | ||||||
|  | 	"Cstrike_Chat_T_Loc" | ||||||
|  | 	{ | ||||||
|  | 		"#format"	"{1:s},{2:s}" | ||||||
|  | 		"en"			"(Terrorist) {1} :  {2}" | ||||||
|  | 	} | ||||||
|  | 	"Cstrike_Chat_T" | ||||||
|  | 	{ | ||||||
|  | 		"#format"	"{1:s},{2:s}" | ||||||
|  | 		"en"			"(Terrorist) {1} :  {2}" | ||||||
|  | 	} | ||||||
|  | 	"Cstrike_Chat_CT_Dead" | ||||||
|  | 	{ | ||||||
|  | 		"#format"	"{1:s},{2:s}" | ||||||
|  | 		"en"			"*DEAD*(Counter-Terrorist) {1} :  {2}" | ||||||
|  | 	} | ||||||
|  | 	"Cstrike_Chat_T_Dead" | ||||||
|  | 	{ | ||||||
|  | 		"#format"	"{1:s},{2:s}" | ||||||
|  | 		"en"			"*DEAD*(Terrorist) {1} :  {2}" | ||||||
|  | 	} | ||||||
|  | 	"Cstrike_Chat_Spec" | ||||||
|  | 	{ | ||||||
|  | 		"#format"	"{1:s},{2:s}" | ||||||
|  | 		"en"			"(Spectator) {1} :  {2}" | ||||||
|  | 	} | ||||||
|  | 	"Cstrike_Chat_All" | ||||||
|  | 	{ | ||||||
|  | 		"#format"	"{1:s},{2:s}" | ||||||
|  | 		"en"			"{1} :  {2}" | ||||||
|  | 	} | ||||||
|  | 	"Cstrike_Chat_AllDead" | ||||||
|  | 	{ | ||||||
|  | 		"#format"	"{1:s},{2:s}" | ||||||
|  | 		"en"			"*DEAD* {1} :  {2}" | ||||||
|  | 	} | ||||||
|  | 	"Cstrike_Chat_AllSpec" | ||||||
|  | 	{ | ||||||
|  | 		"#format"	"{1:s},{2:s}" | ||||||
|  | 		"en"			"*SPEC* {1} :  {2}" | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										324
									
								
								includes/SteamWorks.inc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										324
									
								
								includes/SteamWorks.inc
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,324 @@ | |||||||
|  | #if defined _SteamWorks_Included
 | ||||||
|  |  #endinput
 | ||||||
|  | #endif
 | ||||||
|  | #define _SteamWorks_Included
 | ||||||
|  | 
 | ||||||
|  | /* results from UserHasLicenseForApp */ | ||||||
|  | enum EUserHasLicenseForAppResult | ||||||
|  | { | ||||||
|  | 	k_EUserHasLicenseResultHasLicense = 0,					// User has a license for specified app
 | ||||||
|  | 	k_EUserHasLicenseResultDoesNotHaveLicense = 1,			// User does not have a license for the specified app
 | ||||||
|  | 	k_EUserHasLicenseResultNoAuth = 2,						// User has not been authenticated
 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /* General result codes */ | ||||||
|  | enum EResult | ||||||
|  | { | ||||||
|  | 	k_EResultOK	= 1,							// success
 | ||||||
|  | 	k_EResultFail = 2,							// generic failure 
 | ||||||
|  | 	k_EResultNoConnection = 3,					// no/failed network connection
 | ||||||
|  | //	k_EResultNoConnectionRetry = 4,				// OBSOLETE - removed
 | ||||||
|  | 	k_EResultInvalidPassword = 5,				// password/ticket is invalid
 | ||||||
|  | 	k_EResultLoggedInElsewhere = 6,				// same user logged in elsewhere
 | ||||||
|  | 	k_EResultInvalidProtocolVer = 7,			// protocol version is incorrect
 | ||||||
|  | 	k_EResultInvalidParam = 8,					// a parameter is incorrect
 | ||||||
|  | 	k_EResultFileNotFound = 9,					// file was not found
 | ||||||
|  | 	k_EResultBusy = 10,							// called method busy - action not taken
 | ||||||
|  | 	k_EResultInvalidState = 11,					// called object was in an invalid state
 | ||||||
|  | 	k_EResultInvalidName = 12,					// name is invalid
 | ||||||
|  | 	k_EResultInvalidEmail = 13,					// email is invalid
 | ||||||
|  | 	k_EResultDuplicateName = 14,				// name is not unique
 | ||||||
|  | 	k_EResultAccessDenied = 15,					// access is denied
 | ||||||
|  | 	k_EResultTimeout = 16,						// operation timed out
 | ||||||
|  | 	k_EResultBanned = 17,						// VAC2 banned
 | ||||||
|  | 	k_EResultAccountNotFound = 18,				// account not found
 | ||||||
|  | 	k_EResultInvalidSteamID = 19,				// steamID is invalid
 | ||||||
|  | 	k_EResultServiceUnavailable = 20,			// The requested service is currently unavailable
 | ||||||
|  | 	k_EResultNotLoggedOn = 21,					// The user is not logged on
 | ||||||
|  | 	k_EResultPending = 22,						// Request is pending (may be in process, or waiting on third party)
 | ||||||
|  | 	k_EResultEncryptionFailure = 23,			// Encryption or Decryption failed
 | ||||||
|  | 	k_EResultInsufficientPrivilege = 24,		// Insufficient privilege
 | ||||||
|  | 	k_EResultLimitExceeded = 25,				// Too much of a good thing
 | ||||||
|  | 	k_EResultRevoked = 26,						// Access has been revoked (used for revoked guest passes)
 | ||||||
|  | 	k_EResultExpired = 27,						// License/Guest pass the user is trying to access is expired
 | ||||||
|  | 	k_EResultAlreadyRedeemed = 28,				// Guest pass has already been redeemed by account, cannot be acked again
 | ||||||
|  | 	k_EResultDuplicateRequest = 29,				// The request is a duplicate and the action has already occurred in the past, ignored this time
 | ||||||
|  | 	k_EResultAlreadyOwned = 30,					// All the games in this guest pass redemption request are already owned by the user
 | ||||||
|  | 	k_EResultIPNotFound = 31,					// IP address not found
 | ||||||
|  | 	k_EResultPersistFailed = 32,				// failed to write change to the data store
 | ||||||
|  | 	k_EResultLockingFailed = 33,				// failed to acquire access lock for this operation
 | ||||||
|  | 	k_EResultLogonSessionReplaced = 34, | ||||||
|  | 	k_EResultConnectFailed = 35, | ||||||
|  | 	k_EResultHandshakeFailed = 36, | ||||||
|  | 	k_EResultIOFailure = 37, | ||||||
|  | 	k_EResultRemoteDisconnect = 38, | ||||||
|  | 	k_EResultShoppingCartNotFound = 39,			// failed to find the shopping cart requested
 | ||||||
|  | 	k_EResultBlocked = 40,						// a user didn't allow it
 | ||||||
|  | 	k_EResultIgnored = 41,						// target is ignoring sender
 | ||||||
|  | 	k_EResultNoMatch = 42,						// nothing matching the request found
 | ||||||
|  | 	k_EResultAccountDisabled = 43, | ||||||
|  | 	k_EResultServiceReadOnly = 44,				// this service is not accepting content changes right now
 | ||||||
|  | 	k_EResultAccountNotFeatured = 45,			// account doesn't have value, so this feature isn't available
 | ||||||
|  | 	k_EResultAdministratorOK = 46,				// allowed to take this action, but only because requester is admin
 | ||||||
|  | 	k_EResultContentVersion = 47,				// A Version mismatch in content transmitted within the Steam protocol.
 | ||||||
|  | 	k_EResultTryAnotherCM = 48,					// The current CM can't service the user making a request, user should try another.
 | ||||||
|  | 	k_EResultPasswordRequiredToKickSession = 49,// You are already logged in elsewhere, this cached credential login has failed.
 | ||||||
|  | 	k_EResultAlreadyLoggedInElsewhere = 50,		// You are already logged in elsewhere, you must wait
 | ||||||
|  | 	k_EResultSuspended = 51,					// Long running operation (content download) suspended/paused
 | ||||||
|  | 	k_EResultCancelled = 52,					// Operation canceled (typically by user: content download)
 | ||||||
|  | 	k_EResultDataCorruption = 53,				// Operation canceled because data is ill formed or unrecoverable
 | ||||||
|  | 	k_EResultDiskFull = 54,						// Operation canceled - not enough disk space.
 | ||||||
|  | 	k_EResultRemoteCallFailed = 55,				// an remote call or IPC call failed
 | ||||||
|  | 	k_EResultPasswordUnset = 56,				// Password could not be verified as it's unset server side
 | ||||||
|  | 	k_EResultExternalAccountUnlinked = 57,		// External account (PSN, Facebook...) is not linked to a Steam account
 | ||||||
|  | 	k_EResultPSNTicketInvalid = 58,				// PSN ticket was invalid
 | ||||||
|  | 	k_EResultExternalAccountAlreadyLinked = 59,	// External account (PSN, Facebook...) is already linked to some other account, must explicitly request to replace/delete the link first
 | ||||||
|  | 	k_EResultRemoteFileConflict = 60,			// The sync cannot resume due to a conflict between the local and remote files
 | ||||||
|  | 	k_EResultIllegalPassword = 61,				// The requested new password is not legal
 | ||||||
|  | 	k_EResultSameAsPreviousValue = 62,			// new value is the same as the old one ( secret question and answer )
 | ||||||
|  | 	k_EResultAccountLogonDenied = 63,			// account login denied due to 2nd factor authentication failure
 | ||||||
|  | 	k_EResultCannotUseOldPassword = 64,			// The requested new password is not legal
 | ||||||
|  | 	k_EResultInvalidLoginAuthCode = 65,			// account login denied due to auth code invalid
 | ||||||
|  | 	k_EResultAccountLogonDeniedNoMail = 66,		// account login denied due to 2nd factor auth failure - and no mail has been sent
 | ||||||
|  | 	k_EResultHardwareNotCapableOfIPT = 67,		// 
 | ||||||
|  | 	k_EResultIPTInitError = 68,					// 
 | ||||||
|  | 	k_EResultParentalControlRestricted = 69,	// operation failed due to parental control restrictions for current user
 | ||||||
|  | 	k_EResultFacebookQueryError = 70,			// Facebook query returned an error
 | ||||||
|  | 	k_EResultExpiredLoginAuthCode = 71,			// account login denied due to auth code expired
 | ||||||
|  | 	k_EResultIPLoginRestrictionFailed = 72, | ||||||
|  | 	k_EResultAccountLockedDown = 73, | ||||||
|  | 	k_EResultAccountLogonDeniedVerifiedEmailRequired = 74, | ||||||
|  | 	k_EResultNoMatchingURL = 75, | ||||||
|  | 	k_EResultBadResponse = 76,					// parse failure, missing field, etc.
 | ||||||
|  | 	k_EResultRequirePasswordReEntry = 77,		// The user cannot complete the action until they re-enter their password
 | ||||||
|  | 	k_EResultValueOutOfRange = 78				// the value entered is outside the acceptable range
 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /* This enum is used in client API methods, do not re-number existing values. */ | ||||||
|  | enum EHTTPMethod | ||||||
|  | { | ||||||
|  | 	k_EHTTPMethodInvalid = 0, | ||||||
|  | 	k_EHTTPMethodGET, | ||||||
|  | 	k_EHTTPMethodHEAD, | ||||||
|  | 	k_EHTTPMethodPOST, | ||||||
|  | 	k_EHTTPMethodPUT, | ||||||
|  | 	k_EHTTPMethodDELETE, | ||||||
|  | 	k_EHTTPMethodOPTIONS, | ||||||
|  | 
 | ||||||
|  | 	// The remaining HTTP methods are not yet supported, per rfc2616 section 5.1.1 only GET and HEAD are required for 
 | ||||||
|  | 	// a compliant general purpose server.  We'll likely add more as we find uses for them.
 | ||||||
|  | 
 | ||||||
|  | 	// k_EHTTPMethodTRACE,
 | ||||||
|  | 	// k_EHTTPMethodCONNECT
 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* HTTP Status codes that the server can send in response to a request, see rfc2616 section 10.3 for descriptions | ||||||
|  |  of each of these. */ | ||||||
|  | enum EHTTPStatusCode | ||||||
|  | { | ||||||
|  | 	// Invalid status code (this isn't defined in HTTP, used to indicate unset in our code)
 | ||||||
|  | 	k_EHTTPStatusCodeInvalid =					0, | ||||||
|  | 
 | ||||||
|  | 	// Informational codes
 | ||||||
|  | 	k_EHTTPStatusCode100Continue =				100, | ||||||
|  | 	k_EHTTPStatusCode101SwitchingProtocols =	101, | ||||||
|  | 
 | ||||||
|  | 	// Success codes
 | ||||||
|  | 	k_EHTTPStatusCode200OK =					200, | ||||||
|  | 	k_EHTTPStatusCode201Created =				201, | ||||||
|  | 	k_EHTTPStatusCode202Accepted =				202, | ||||||
|  | 	k_EHTTPStatusCode203NonAuthoritative =		203, | ||||||
|  | 	k_EHTTPStatusCode204NoContent =				204, | ||||||
|  | 	k_EHTTPStatusCode205ResetContent =			205, | ||||||
|  | 	k_EHTTPStatusCode206PartialContent =		206, | ||||||
|  | 
 | ||||||
|  | 	// Redirection codes
 | ||||||
|  | 	k_EHTTPStatusCode300MultipleChoices =		300, | ||||||
|  | 	k_EHTTPStatusCode301MovedPermanently =		301, | ||||||
|  | 	k_EHTTPStatusCode302Found =					302, | ||||||
|  | 	k_EHTTPStatusCode303SeeOther =				303, | ||||||
|  | 	k_EHTTPStatusCode304NotModified =			304, | ||||||
|  | 	k_EHTTPStatusCode305UseProxy =				305, | ||||||
|  | 	//k_EHTTPStatusCode306Unused =				306, (used in old HTTP spec, now unused in 1.1)
 | ||||||
|  | 	k_EHTTPStatusCode307TemporaryRedirect =		307, | ||||||
|  | 
 | ||||||
|  | 	// Error codes
 | ||||||
|  | 	k_EHTTPStatusCode400BadRequest =			400, | ||||||
|  | 	k_EHTTPStatusCode401Unauthorized =			401, // You probably want 403 or something else. 401 implies you're sending a WWW-Authenticate header and the client can sent an Authorization header in response.
 | ||||||
|  | 	k_EHTTPStatusCode402PaymentRequired =		402, // This is reserved for future HTTP specs, not really supported by clients
 | ||||||
|  | 	k_EHTTPStatusCode403Forbidden =				403, | ||||||
|  | 	k_EHTTPStatusCode404NotFound =				404, | ||||||
|  | 	k_EHTTPStatusCode405MethodNotAllowed =		405, | ||||||
|  | 	k_EHTTPStatusCode406NotAcceptable =			406, | ||||||
|  | 	k_EHTTPStatusCode407ProxyAuthRequired =		407, | ||||||
|  | 	k_EHTTPStatusCode408RequestTimeout =		408, | ||||||
|  | 	k_EHTTPStatusCode409Conflict =				409, | ||||||
|  | 	k_EHTTPStatusCode410Gone =					410, | ||||||
|  | 	k_EHTTPStatusCode411LengthRequired =		411, | ||||||
|  | 	k_EHTTPStatusCode412PreconditionFailed =	412, | ||||||
|  | 	k_EHTTPStatusCode413RequestEntityTooLarge =	413, | ||||||
|  | 	k_EHTTPStatusCode414RequestURITooLong =		414, | ||||||
|  | 	k_EHTTPStatusCode415UnsupportedMediaType =	415, | ||||||
|  | 	k_EHTTPStatusCode416RequestedRangeNotSatisfiable = 416, | ||||||
|  | 	k_EHTTPStatusCode417ExpectationFailed =		417, | ||||||
|  | 	k_EHTTPStatusCode4xxUnknown = 				418, // 418 is reserved, so we'll use it to mean unknown
 | ||||||
|  | 	k_EHTTPStatusCode429TooManyRequests	=		429, | ||||||
|  | 
 | ||||||
|  | 	// Server error codes
 | ||||||
|  | 	k_EHTTPStatusCode500InternalServerError =	500, | ||||||
|  | 	k_EHTTPStatusCode501NotImplemented =		501, | ||||||
|  | 	k_EHTTPStatusCode502BadGateway =			502, | ||||||
|  | 	k_EHTTPStatusCode503ServiceUnavailable =	503, | ||||||
|  | 	k_EHTTPStatusCode504GatewayTimeout =		504, | ||||||
|  | 	k_EHTTPStatusCode505HTTPVersionNotSupported = 505, | ||||||
|  | 	k_EHTTPStatusCode5xxUnknown =				599, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | native bool:SteamWorks_IsVACEnabled(); | ||||||
|  | native bool:SteamWorks_GetPublicIP(ipaddr[4]); | ||||||
|  | native SteamWorks_GetPublicIPCell(); | ||||||
|  | native bool:SteamWorks_IsLoaded(); | ||||||
|  | native bool:SteamWorks_SetGameDescription(String:sDesc[]); | ||||||
|  | native bool:SteamWorks_IsConnected(); | ||||||
|  | native bool:SteamWorks_SetRule(const String:sKey[], const String:sValue[]); | ||||||
|  | native bool:SteamWorks_ClearRules(); | ||||||
|  | native bool:SteamWorks_ForceHeartbeat(); | ||||||
|  | native bool:SteamWorks_GetUserGroupStatus(client, groupid); | ||||||
|  | native bool:SteamWorks_GetUserGroupStatusAuthID(authid, groupid); | ||||||
|  | 
 | ||||||
|  | native EUserHasLicenseForAppResult:SteamWorks_HasLicenseForApp(client, app); | ||||||
|  | native SteamWorks_GetClientSteamID(client, String:sSteamID[], length); | ||||||
|  | 
 | ||||||
|  | native bool:SteamWorks_RequestStatsAuthID(authid, appid); | ||||||
|  | native bool:SteamWorks_RequestStats(client, appid); | ||||||
|  | native bool:SteamWorks_GetStatCell(client, const String:sKey[], &value); | ||||||
|  | native bool:SteamWorks_GetStatAuthIDCell(authid, const String:sKey[], &value); | ||||||
|  | native bool:SteamWorks_GetStatFloat(client, const String:sKey[], &Float:value); | ||||||
|  | native bool:SteamWorks_GetStatAuthIDFloat(authid, const String:sKey[], &Float:value); | ||||||
|  | 
 | ||||||
|  | native Handle:SteamWorks_CreateHTTPRequest(EHTTPMethod:method, const String:sURL[]); | ||||||
|  | native bool:SteamWorks_SetHTTPRequestContextValue(Handle:hHandle, any:data1, any:data2=0); | ||||||
|  | native bool:SteamWorks_SetHTTPRequestNetworkActivityTimeout(Handle:hHandle, timeout); | ||||||
|  | native bool:SteamWorks_SetHTTPRequestHeaderValue(Handle:hHandle, const String:sName[], const String:sValue[]); | ||||||
|  | native bool:SteamWorks_SetHTTPRequestGetOrPostParameter(Handle:hHandle, const String:sName[], const String:sValue[]); | ||||||
|  | 
 | ||||||
|  | funcenum SteamWorksHTTPRequestCompleted | ||||||
|  | { | ||||||
|  | 	public(Handle:hRequest, bool:bFailure, bool:bRequestSuccessful, EHTTPStatusCode:eStatusCode), | ||||||
|  | 	public(Handle:hRequest, bool:bFailure, bool:bRequestSuccessful, EHTTPStatusCode:eStatusCode, any:data1), | ||||||
|  | 	public(Handle:hRequest, bool:bFailure, bool:bRequestSuccessful, EHTTPStatusCode:eStatusCode, any:data1, any:data2) | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | funcenum SteamWorksHTTPHeadersReceived | ||||||
|  | { | ||||||
|  | 	public(Handle:hRequest, bool:bFailure), | ||||||
|  | 	public(Handle:hRequest, bool:bFailure, any:data1), | ||||||
|  | 	public(Handle:hRequest, bool:bFailure, any:data1, any:data2) | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | funcenum SteamWorksHTTPDataReceived | ||||||
|  | { | ||||||
|  | 	public(Handle:hRequest, bool:bFailure, offset, bytesreceived), | ||||||
|  | 	public(Handle:hRequest, bool:bFailure, offset, bytesreceived, any:data1), | ||||||
|  | 	public(Handle:hRequest, bool:bFailure, offset, bytesreceived, any:data1, any:data2) | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | native bool:SteamWorks_SetHTTPCallbacks(Handle:hHandle, SteamWorksHTTPRequestCompleted:fCompleted = INVALID_FUNCTION, SteamWorksHTTPHeadersReceived:fHeaders = INVALID_FUNCTION, SteamWorksHTTPDataReceived:fData = INVALID_FUNCTION, Handle:hCalling = INVALID_HANDLE); | ||||||
|  | native bool:SteamWorks_SendHTTPRequest(Handle:hRequest); | ||||||
|  | native bool:SteamWorks_SendHTTPRequestAndStreamResponse(Handle:hRequest); | ||||||
|  | native bool:SteamWorks_DeferHTTPRequest(Handle:hRequest); | ||||||
|  | native bool:SteamWorks_PrioritizeHTTPRequest(Handle:hRequest); | ||||||
|  | native bool:SteamWorks_GetHTTPResponseHeaderSize(Handle:hRequest, const String:sHeader[], &size); | ||||||
|  | native bool:SteamWorks_GetHTTPResponseHeaderValue(Handle:hRequest, const String:sHeader[], String:sValue[], size); | ||||||
|  | native bool:SteamWorks_GetHTTPResponseBodySize(Handle:hRequest, &size); | ||||||
|  | native bool:SteamWorks_GetHTTPResponseBodyData(Handle:hRequest, String:sBody[], length); | ||||||
|  | native bool:SteamWorks_GetHTTPStreamingResponseBodyData(Handle:hRequest, cOffset, String:sBody[], length); | ||||||
|  | native bool:SteamWorks_GetHTTPDownloadProgressPct(Handle:hRequest, &Float:percent); | ||||||
|  | native bool:SteamWorks_SetHTTPRequestRawPostBody(Handle:hRequest, const String:sContentType[], const String:sBody[], bodylen); | ||||||
|  | 
 | ||||||
|  | funcenum SteamWorksHTTPBodyCallback | ||||||
|  | { | ||||||
|  | 	public(const String:sData[]), | ||||||
|  | 	public(const String:sData[], any:value), | ||||||
|  | 	public(const data[], any:value, datalen) | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | native bool:SteamWorks_GetHTTPResponseBodyCallback(Handle:hRequest, SteamWorksHTTPBodyCallback:fCallback, any:data = 0, Handle:hPlugin = INVALID_HANDLE); | ||||||
|  | native bool:SteamWorks_WriteHTTPResponseBodyToFile(Handle:hRequest, const String:sFileName[]); | ||||||
|  | 
 | ||||||
|  | forward SW_OnValidateClient(ownerauthid, authid); | ||||||
|  | forward SteamWorks_OnValidateClient(ownerauthid, authid); | ||||||
|  | forward SteamWorks_SteamServersConnected(); | ||||||
|  | forward SteamWorks_SteamServersConnectFailure(EResult:result); | ||||||
|  | forward SteamWorks_SteamServersDisconnected(EResult:result); | ||||||
|  | 
 | ||||||
|  | forward Action:SteamWorks_RestartRequested(); | ||||||
|  | forward SteamWorks_TokenRequested(String:sToken[], maxlen); | ||||||
|  | 
 | ||||||
|  | forward SteamWorks_OnClientGroupStatus(authid, groupid, bool:isMember, bool:isOfficer); | ||||||
|  | 
 | ||||||
|  | public Extension:__ext_SteamWorks =  | ||||||
|  | { | ||||||
|  | 	name = "SteamWorks", | ||||||
|  | 	file = "SteamWorks.ext", | ||||||
|  | #if defined AUTOLOAD_EXTENSIONS
 | ||||||
|  | 	autoload = 1, | ||||||
|  | #else
 | ||||||
|  | 	autoload = 0, | ||||||
|  | #endif
 | ||||||
|  | #if defined REQUIRE_EXTENSIONS
 | ||||||
|  | 	required = 1, | ||||||
|  | #else
 | ||||||
|  | 	required = 0, | ||||||
|  | #endif
 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #if !defined REQUIRE_EXTENSIONS
 | ||||||
|  | public __ext_SteamWorks_SetNTVOptional() | ||||||
|  | { | ||||||
|  | 	MarkNativeAsOptional("SteamWorks_IsVACEnabled"); | ||||||
|  | 	MarkNativeAsOptional("SteamWorks_GetPublicIP"); | ||||||
|  | 	MarkNativeAsOptional("SteamWorks_GetPublicIPCell"); | ||||||
|  | 	MarkNativeAsOptional("SteamWorks_IsLoaded"); | ||||||
|  | 	MarkNativeAsOptional("SteamWorks_SetGameDescription"); | ||||||
|  | 	MarkNativeAsOptional("SteamWorks_IsConnected"); | ||||||
|  | 	MarkNativeAsOptional("SteamWorks_SetRule"); | ||||||
|  | 	MarkNativeAsOptional("SteamWorks_ClearRules"); | ||||||
|  | 	MarkNativeAsOptional("SteamWorks_ForceHeartbeat"); | ||||||
|  | 	MarkNativeAsOptional("SteamWorks_GetUserGroupStatus"); | ||||||
|  | 	MarkNativeAsOptional("SteamWorks_GetUserGroupStatusAuthID"); | ||||||
|  | 
 | ||||||
|  | 	MarkNativeAsOptional("SteamWorks_HasLicenseForApp"); | ||||||
|  | 	MarkNativeAsOptional("SteamWorks_GetClientSteamID"); | ||||||
|  | 
 | ||||||
|  | 	MarkNativeAsOptional("SteamWorks_RequestStatsAuthID"); | ||||||
|  | 	MarkNativeAsOptional("SteamWorks_RequestStats"); | ||||||
|  | 	MarkNativeAsOptional("SteamWorks_GetStatCell"); | ||||||
|  | 	MarkNativeAsOptional("SteamWorks_GetStatAuthIDCell"); | ||||||
|  | 	MarkNativeAsOptional("SteamWorks_GetStatFloat"); | ||||||
|  | 	MarkNativeAsOptional("SteamWorks_GetStatAuthIDFloat"); | ||||||
|  | 
 | ||||||
|  | 	MarkNativeAsOptional("SteamWorks_CreateHTTPRequest"); | ||||||
|  | 	MarkNativeAsOptional("SteamWorks_SetHTTPRequestContextValue"); | ||||||
|  | 	MarkNativeAsOptional("SteamWorks_SetHTTPRequestNetworkActivityTimeout"); | ||||||
|  | 	MarkNativeAsOptional("SteamWorks_SetHTTPRequestHeaderValue"); | ||||||
|  | 	MarkNativeAsOptional("SteamWorks_SetHTTPRequestGetOrPostParameter"); | ||||||
|  | 
 | ||||||
|  | 	MarkNativeAsOptional("SteamWorks_SetHTTPCallbacks"); | ||||||
|  | 	MarkNativeAsOptional("SteamWorks_SendHTTPRequest"); | ||||||
|  | 	MarkNativeAsOptional("SteamWorks_SendHTTPRequestAndStreamResponse"); | ||||||
|  | 	MarkNativeAsOptional("SteamWorks_DeferHTTPRequest"); | ||||||
|  | 	MarkNativeAsOptional("SteamWorks_PrioritizeHTTPRequest"); | ||||||
|  | 	MarkNativeAsOptional("SteamWorks_GetHTTPResponseHeaderSize"); | ||||||
|  | 	MarkNativeAsOptional("SteamWorks_GetHTTPResponseHeaderValue"); | ||||||
|  | 	MarkNativeAsOptional("SteamWorks_GetHTTPResponseBodySize"); | ||||||
|  | 	MarkNativeAsOptional("SteamWorks_GetHTTPResponseBodyData"); | ||||||
|  | 	MarkNativeAsOptional("SteamWorks_GetHTTPStreamingResponseBodyData"); | ||||||
|  | 	MarkNativeAsOptional("SteamWorks_GetHTTPDownloadProgressPct"); | ||||||
|  | 	MarkNativeAsOptional("SteamWorks_SetHTTPRequestRawPostBody"); | ||||||
|  | 
 | ||||||
|  | 	MarkNativeAsOptional("SteamWorks_GetHTTPResponseBodyCallback"); | ||||||
|  | 	MarkNativeAsOptional("SteamWorks_WriteHTTPResponseBodyToFile"); | ||||||
|  | } | ||||||
|  | #endif
 | ||||||
							
								
								
									
										539
									
								
								includes/colors.inc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										539
									
								
								includes/colors.inc
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,539 @@ | |||||||
|  | /************************************************************************** | ||||||
|  |  *                                                                        * | ||||||
|  |  *                       Colored Chat Functions                           * | ||||||
|  |  *                   Author: exvel, Editor: Popoklopsi, Powerlord, Bara   * | ||||||
|  |  *                           Version: 1.1.3	                              * | ||||||
|  |  *                                                                        * | ||||||
|  |  **************************************************************************/ | ||||||
|  |   | ||||||
|  | 
 | ||||||
|  | #if defined _colors_included
 | ||||||
|  |  #endinput
 | ||||||
|  | #endif
 | ||||||
|  | #define _colors_included
 | ||||||
|  |   | ||||||
|  | #define MAX_MESSAGE_LENGTH 250
 | ||||||
|  | #define MAX_COLORS 12
 | ||||||
|  | 
 | ||||||
|  | #define SERVER_INDEX 0
 | ||||||
|  | #define NO_INDEX -1
 | ||||||
|  | #define NO_PLAYER -2
 | ||||||
|  | 
 | ||||||
|  | enum Colors | ||||||
|  | { | ||||||
|  |  	Color_Default = 0, | ||||||
|  | 	Color_Darkred, | ||||||
|  | 	Color_Green, | ||||||
|  | 	Color_Lightgreen, | ||||||
|  | 	Color_Red, | ||||||
|  | 	Color_Blue, | ||||||
|  | 	Color_Olive, | ||||||
|  | 	Color_Lime, | ||||||
|  | 	Color_Lightred, | ||||||
|  | 	Color_Purple, | ||||||
|  | 	Color_Grey, | ||||||
|  | 	Color_Orange | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Colors' properties */ | ||||||
|  | new String:CTag[][] = {"{default}", "{darkred}", "{green}", "{lightgreen}", "{red}", "{blue}", "{olive}", "{lime}", "{lightred}", "{purple}", "{grey}", "{orange}"}; | ||||||
|  | new String:CTagCode[][] = {"\x01", "\x02", "\x04", "\x03", "\x03", "\x03", "\x05", "\x06", "\x07", "\x03", "\x08", "\x09"}; | ||||||
|  | new bool:CTagReqSayText2[] = {false, false, false, true, true, true, false, false, false, false, false, false}; | ||||||
|  | new bool:CEventIsHooked = false; | ||||||
|  | new bool:CSkipList[MAXPLAYERS+1] = {false,...}; | ||||||
|  | 
 | ||||||
|  | /* Game default profile */ | ||||||
|  | new bool:CProfile_Colors[] = {true, false, true, false, false, false, false, false, false, false, false, false}; | ||||||
|  | new CProfile_TeamIndex[] = {NO_INDEX, NO_INDEX, NO_INDEX, NO_INDEX, NO_INDEX, NO_INDEX, NO_INDEX, NO_INDEX, NO_INDEX, NO_INDEX}; | ||||||
|  | new bool:CProfile_SayText2 = false; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Prints a message to a specific client in the chat area. | ||||||
|  |  * Supports color tags. | ||||||
|  |  * | ||||||
|  |  * @param client	  Client index. | ||||||
|  |  * @param szMessage   Message (formatting rules). | ||||||
|  |  * @return			  No return | ||||||
|  |  *  | ||||||
|  |  * On error/Errors:   If the client is not connected an error will be thrown. | ||||||
|  |  */ | ||||||
|  | stock CPrintToChat(client, const String:szMessage[], any:...) | ||||||
|  | { | ||||||
|  | 	if (client <= 0 || client > MaxClients) | ||||||
|  | 		ThrowError("Invalid client index %d", client); | ||||||
|  | 	 | ||||||
|  | 	if (!IsClientInGame(client)) | ||||||
|  | 		ThrowError("Client %d is not in game", client); | ||||||
|  | 	 | ||||||
|  | 	decl String:szBuffer[MAX_MESSAGE_LENGTH]; | ||||||
|  | 	decl String:szCMessage[MAX_MESSAGE_LENGTH]; | ||||||
|  | 
 | ||||||
|  | 	SetGlobalTransTarget(client); | ||||||
|  | 	 | ||||||
|  | 	Format(szBuffer, sizeof(szBuffer), "\x01%s", szMessage); | ||||||
|  | 	VFormat(szCMessage, sizeof(szCMessage), szBuffer, 3); | ||||||
|  | 	 | ||||||
|  | 	new index = CFormat(szCMessage, sizeof(szCMessage)); | ||||||
|  | 	 | ||||||
|  | 	if (index == NO_INDEX) | ||||||
|  | 		PrintToChat(client, "%s", szCMessage); | ||||||
|  | 	else | ||||||
|  | 		CSayText2(client, index, szCMessage); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | stock CReplyToCommand(client, const String:szMessage[], any:...) | ||||||
|  | { | ||||||
|  | 	 | ||||||
|  | 	decl String:szCMessage[MAX_MESSAGE_LENGTH]; | ||||||
|  | 	VFormat(szCMessage, sizeof(szCMessage), szMessage, 3); | ||||||
|  | 	 | ||||||
|  | 	if (client == 0) | ||||||
|  | 	{ | ||||||
|  | 		CRemoveTags(szCMessage, sizeof(szCMessage)); | ||||||
|  | 		PrintToServer("%s", szCMessage); | ||||||
|  | 	} | ||||||
|  | 	else if (GetCmdReplySource() == SM_REPLY_TO_CONSOLE) | ||||||
|  | 	{ | ||||||
|  | 		CRemoveTags(szCMessage, sizeof(szCMessage)); | ||||||
|  | 		PrintToConsole(client, "%s", szCMessage); | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 		CPrintToChat(client, "%s", szCMessage); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Prints a message to all clients in the chat area. | ||||||
|  |  * Supports color tags. | ||||||
|  |  * | ||||||
|  |  * @param client	  Client index. | ||||||
|  |  * @param szMessage   Message (formatting rules) | ||||||
|  |  * @return			  No return | ||||||
|  |  */ | ||||||
|  | stock CPrintToChatAll(const String:szMessage[], any:...) | ||||||
|  | { | ||||||
|  | 	decl String:szBuffer[MAX_MESSAGE_LENGTH]; | ||||||
|  | 	 | ||||||
|  | 	for (new i = 1; i <= MaxClients; i++) | ||||||
|  | 	{ | ||||||
|  | 		if (IsClientInGame(i) && !IsFakeClient(i) && !CSkipList[i]) | ||||||
|  | 		{ | ||||||
|  | 			SetGlobalTransTarget(i); | ||||||
|  | 			VFormat(szBuffer, sizeof(szBuffer), szMessage, 2); | ||||||
|  | 			 | ||||||
|  | 			CPrintToChat(i, "%s", szBuffer); | ||||||
|  | 		} | ||||||
|  | 		 | ||||||
|  | 		CSkipList[i] = false; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Prints a message to a specific client in the chat area. | ||||||
|  |  * Supports color tags and teamcolor tag. | ||||||
|  |  * | ||||||
|  |  * @param client	  Client index. | ||||||
|  |  * @param author	  Author index whose color will be used for teamcolor tag. | ||||||
|  |  * @param szMessage   Message (formatting rules). | ||||||
|  |  * @return			  No return | ||||||
|  |  *  | ||||||
|  |  * On error/Errors:   If the client or author are not connected an error will be thrown. | ||||||
|  |  */ | ||||||
|  | stock CPrintToChatEx(client, author, const String:szMessage[], any:...) | ||||||
|  | { | ||||||
|  | 	if (client <= 0 || client > MaxClients) | ||||||
|  | 		ThrowError("Invalid client index %d", client); | ||||||
|  | 	 | ||||||
|  | 	if (!IsClientInGame(client)) | ||||||
|  | 		ThrowError("Client %d is not in game", client); | ||||||
|  | 	 | ||||||
|  | 	if (author < 0 || author > MaxClients) | ||||||
|  | 		ThrowError("Invalid client index %d", author); | ||||||
|  | 	 | ||||||
|  | 	decl String:szBuffer[MAX_MESSAGE_LENGTH]; | ||||||
|  | 	decl String:szCMessage[MAX_MESSAGE_LENGTH]; | ||||||
|  | 
 | ||||||
|  | 	SetGlobalTransTarget(client); | ||||||
|  | 	 | ||||||
|  | 	Format(szBuffer, sizeof(szBuffer), "\x01%s", szMessage); | ||||||
|  | 	VFormat(szCMessage, sizeof(szCMessage), szBuffer, 4); | ||||||
|  | 	 | ||||||
|  | 	new index = CFormat(szCMessage, sizeof(szCMessage), author); | ||||||
|  | 	 | ||||||
|  | 	if (index == NO_INDEX) | ||||||
|  | 		PrintToChat(client, "%s", szCMessage); | ||||||
|  | 	else | ||||||
|  | 		CSayText2(client, author, szCMessage); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Prints a message to all clients in the chat area. | ||||||
|  |  * Supports color tags and teamcolor tag. | ||||||
|  |  * | ||||||
|  |  * @param author	  Author index whos color will be used for teamcolor tag. | ||||||
|  |  * @param szMessage   Message (formatting rules). | ||||||
|  |  * @return			  No return | ||||||
|  |  *  | ||||||
|  |  * On error/Errors:   If the author is not connected an error will be thrown. | ||||||
|  |  */ | ||||||
|  | stock CPrintToChatAllEx(author, const String:szMessage[], any:...) | ||||||
|  | { | ||||||
|  | 	if (author < 0 || author > MaxClients) | ||||||
|  | 		ThrowError("Invalid client index %d", author); | ||||||
|  | 	 | ||||||
|  | 	if (!IsClientInGame(author)) | ||||||
|  | 		ThrowError("Client %d is not in game", author); | ||||||
|  | 	 | ||||||
|  | 	decl String:szBuffer[MAX_MESSAGE_LENGTH]; | ||||||
|  | 	 | ||||||
|  | 	for (new i = 1; i <= MaxClients; i++) | ||||||
|  | 	{ | ||||||
|  | 		if (IsClientInGame(i) && !IsFakeClient(i) && !CSkipList[i]) | ||||||
|  | 		{ | ||||||
|  | 			SetGlobalTransTarget(i); | ||||||
|  | 			VFormat(szBuffer, sizeof(szBuffer), szMessage, 3); | ||||||
|  | 			 | ||||||
|  | 			CPrintToChatEx(i, author, "%s", szBuffer); | ||||||
|  | 		} | ||||||
|  | 		 | ||||||
|  | 		CSkipList[i] = false; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Removes color tags from the string. | ||||||
|  |  * | ||||||
|  |  * @param szMessage   String. | ||||||
|  |  * @return			  No return | ||||||
|  |  */ | ||||||
|  | stock CRemoveTags(String:szMessage[], maxlength) | ||||||
|  | { | ||||||
|  | 	for (new i = 0; i < MAX_COLORS; i++) | ||||||
|  | 		ReplaceString(szMessage, maxlength, CTag[i], "", false); | ||||||
|  | 	 | ||||||
|  | 	ReplaceString(szMessage, maxlength, "{teamcolor}", "", false); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Checks whether a color is allowed or not | ||||||
|  |  * | ||||||
|  |  * @param tag   		Color Tag. | ||||||
|  |  * @return			 	True when color is supported, otherwise false | ||||||
|  |  */ | ||||||
|  | stock CColorAllowed(Colors:color) | ||||||
|  | { | ||||||
|  | 	if (!CEventIsHooked) | ||||||
|  | 	{ | ||||||
|  | 		CSetupProfile(); | ||||||
|  | 		 | ||||||
|  | 		CEventIsHooked = true; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	return CProfile_Colors[color]; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Replace the color with another color | ||||||
|  |  * Handle with care! | ||||||
|  |  * | ||||||
|  |  * @param color   			color to replace. | ||||||
|  |  * @param newColor   		color to replace with. | ||||||
|  |  * @noreturn | ||||||
|  |  */ | ||||||
|  | stock CReplaceColor(Colors:color, Colors:newColor) | ||||||
|  | { | ||||||
|  | 	if (!CEventIsHooked) | ||||||
|  | 	{ | ||||||
|  | 		CSetupProfile(); | ||||||
|  | 		 | ||||||
|  | 		CEventIsHooked = true; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	CProfile_Colors[color] = CProfile_Colors[newColor]; | ||||||
|  | 	CProfile_TeamIndex[color] = CProfile_TeamIndex[newColor]; | ||||||
|  | 	 | ||||||
|  | 	CTagReqSayText2[color] = CTagReqSayText2[newColor]; | ||||||
|  | 	Format(CTagCode[color], sizeof(CTagCode[]), CTagCode[newColor]) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * This function should only be used right in front of | ||||||
|  |  * CPrintToChatAll or CPrintToChatAllEx and it tells | ||||||
|  |  * to those funcions to skip specified client when printing | ||||||
|  |  * message to all clients. After message is printed client will | ||||||
|  |  * no more be skipped. | ||||||
|  |  *  | ||||||
|  |  * @param client   Client index | ||||||
|  |  * @return		   No return | ||||||
|  |  */ | ||||||
|  | stock CSkipNextClient(client) | ||||||
|  | { | ||||||
|  | 	if (client <= 0 || client > MaxClients) | ||||||
|  | 		ThrowError("Invalid client index %d", client); | ||||||
|  | 	 | ||||||
|  | 	CSkipList[client] = true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Replaces color tags in a string with color codes | ||||||
|  |  * | ||||||
|  |  * @param szMessage   String. | ||||||
|  |  * @param maxlength   Maximum length of the string buffer. | ||||||
|  |  * @return			  Client index that can be used for SayText2 author index | ||||||
|  |  *  | ||||||
|  |  * On error/Errors:   If there is more then one team color is used an error will be thrown. | ||||||
|  |  */ | ||||||
|  | stock CFormat(String:szMessage[], maxlength, author=NO_INDEX) | ||||||
|  | { | ||||||
|  | 	decl String:szGameName[30]; | ||||||
|  | 	 | ||||||
|  | 	GetGameFolderName(szGameName, sizeof(szGameName)); | ||||||
|  | 	 | ||||||
|  | 	/* Hook event for auto profile setup on map start */ | ||||||
|  | 	if (!CEventIsHooked) | ||||||
|  | 	{ | ||||||
|  | 		CSetupProfile(); | ||||||
|  | 		HookEvent("server_spawn", CEvent_MapStart, EventHookMode_PostNoCopy); | ||||||
|  | 		 | ||||||
|  | 		CEventIsHooked = true; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	new iRandomPlayer = NO_INDEX; | ||||||
|  | 	 | ||||||
|  | 	// On CS:GO set invisible precolor
 | ||||||
|  | 	if (StrEqual(szGameName, "csgo", false))  | ||||||
|  | 		Format(szMessage, maxlength, " \x01\x0B\x01%s", szMessage); | ||||||
|  | 	 | ||||||
|  | 	/* If author was specified replace {teamcolor} tag */ | ||||||
|  | 	if (author != NO_INDEX) | ||||||
|  | 	{ | ||||||
|  | 		if (CProfile_SayText2) | ||||||
|  | 		{ | ||||||
|  | 			ReplaceString(szMessage, maxlength, "{teamcolor}", "\x03", false); | ||||||
|  | 			 | ||||||
|  | 			iRandomPlayer = author; | ||||||
|  | 		} | ||||||
|  | 		/* If saytext2 is not supported by game replace {teamcolor} with green tag  */ | ||||||
|  | 		else | ||||||
|  | 			ReplaceString(szMessage, maxlength, "{teamcolor}", CTagCode[Color_Green], false); | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 		ReplaceString(szMessage, maxlength, "{teamcolor}", "", false); | ||||||
|  | 	 | ||||||
|  | 	/* For other color tags we need a loop */ | ||||||
|  | 	for (new i = 0; i < MAX_COLORS; i++) | ||||||
|  | 	{ | ||||||
|  | 		/* If tag not found - skip */ | ||||||
|  | 		if (StrContains(szMessage, CTag[i], false) == -1) | ||||||
|  | 			continue; | ||||||
|  | 			 | ||||||
|  | 		/* If tag is not supported by game replace it with green tag */ | ||||||
|  | 		else if (!CProfile_Colors[i]) | ||||||
|  | 			ReplaceString(szMessage, maxlength, CTag[i], CTagCode[Color_Green], false); | ||||||
|  | 		 | ||||||
|  | 		/* If tag doesn't need saytext2 simply replace */ | ||||||
|  | 		else if (!CTagReqSayText2[i]) | ||||||
|  | 			ReplaceString(szMessage, maxlength, CTag[i], CTagCode[i], false); | ||||||
|  | 
 | ||||||
|  | 		/* Tag needs saytext2 */ | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			/* If saytext2 is not supported by game replace tag with green tag */ | ||||||
|  | 			if (!CProfile_SayText2) | ||||||
|  | 				ReplaceString(szMessage, maxlength, CTag[i], CTagCode[Color_Green], false); | ||||||
|  | 				 | ||||||
|  | 			/* Game supports saytext2 */ | ||||||
|  | 			else  | ||||||
|  | 			{ | ||||||
|  | 				/* If random player for tag wasn't specified replace tag and find player */ | ||||||
|  | 				if (iRandomPlayer == NO_INDEX) | ||||||
|  | 				{ | ||||||
|  | 					/* Searching for valid client for tag */ | ||||||
|  | 					iRandomPlayer = CFindRandomPlayerByTeam(CProfile_TeamIndex[i]); | ||||||
|  | 					 | ||||||
|  | 					/* If player not found replace tag with green color tag */ | ||||||
|  | 					if (iRandomPlayer == NO_PLAYER) | ||||||
|  | 						ReplaceString(szMessage, maxlength, CTag[i], CTagCode[Color_Green], false); | ||||||
|  | 
 | ||||||
|  | 					/* If player was found simply replace */ | ||||||
|  | 					else | ||||||
|  | 						ReplaceString(szMessage, maxlength, CTag[i], CTagCode[i], false); | ||||||
|  | 					 | ||||||
|  | 				} | ||||||
|  | 				/* If found another team color tag throw error */ | ||||||
|  | 				else | ||||||
|  | 				{ | ||||||
|  | 					//ReplaceString(szMessage, maxlength, CTag[i], "");
 | ||||||
|  | 					ThrowError("Using two team colors in one message is not allowed"); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			 | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	return iRandomPlayer; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Founds a random player with specified team | ||||||
|  |  * | ||||||
|  |  * @param color_team  Client team. | ||||||
|  |  * @return			  Client index or NO_PLAYER if no player found | ||||||
|  |  */ | ||||||
|  | stock CFindRandomPlayerByTeam(color_team) | ||||||
|  | { | ||||||
|  | 	if (color_team == SERVER_INDEX) | ||||||
|  | 		return 0; | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 		for (new i = 1; i <= MaxClients; i++) | ||||||
|  | 		{ | ||||||
|  | 			if (IsClientInGame(i) && GetClientTeam(i) == color_team) | ||||||
|  | 				return i; | ||||||
|  | 		}	 | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return NO_PLAYER; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Sends a SayText2 usermessage to a client | ||||||
|  |  * | ||||||
|  |  * @param szMessage   Client index | ||||||
|  |  * @param maxlength   Author index | ||||||
|  |  * @param szMessage   Message | ||||||
|  |  * @return			  No return. | ||||||
|  |  */ | ||||||
|  | stock CSayText2(client, author, const String:szMessage[]) | ||||||
|  | { | ||||||
|  | 	new Handle:hBuffer = StartMessageOne("SayText2", client, USERMSG_RELIABLE|USERMSG_BLOCKHOOKS); | ||||||
|  | 	 | ||||||
|  | 	if(GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available && GetUserMessageType() == UM_Protobuf)  | ||||||
|  | 	{ | ||||||
|  | 		PbSetInt(hBuffer, "ent_idx", author); | ||||||
|  | 		PbSetBool(hBuffer, "chat", true); | ||||||
|  | 		PbSetString(hBuffer, "msg_name", szMessage); | ||||||
|  | 		PbAddString(hBuffer, "params", ""); | ||||||
|  | 		PbAddString(hBuffer, "params", ""); | ||||||
|  | 		PbAddString(hBuffer, "params", ""); | ||||||
|  | 		PbAddString(hBuffer, "params", ""); | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 		BfWriteByte(hBuffer, author); | ||||||
|  | 		BfWriteByte(hBuffer, true); | ||||||
|  | 		BfWriteString(hBuffer, szMessage); | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	EndMessage(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Creates game color profile  | ||||||
|  |  * This function must be edited if you want to add more games support | ||||||
|  |  * | ||||||
|  |  * @return			  No return. | ||||||
|  |  */ | ||||||
|  | stock CSetupProfile() | ||||||
|  | { | ||||||
|  | 	decl String:szGameName[30]; | ||||||
|  | 	GetGameFolderName(szGameName, sizeof(szGameName)); | ||||||
|  | 	 | ||||||
|  | 	if (StrEqual(szGameName, "cstrike", false)) | ||||||
|  | 	{ | ||||||
|  | 		CProfile_Colors[Color_Lightgreen] = true; | ||||||
|  | 		CProfile_Colors[Color_Red] = true; | ||||||
|  | 		CProfile_Colors[Color_Blue] = true; | ||||||
|  | 		CProfile_Colors[Color_Olive] = true; | ||||||
|  | 		CProfile_TeamIndex[Color_Lightgreen] = SERVER_INDEX; | ||||||
|  | 		CProfile_TeamIndex[Color_Red] = 2; | ||||||
|  | 		CProfile_TeamIndex[Color_Blue] = 3; | ||||||
|  | 		CProfile_SayText2 = true; | ||||||
|  | 	} | ||||||
|  | 	else if (StrEqual(szGameName, "csgo", false)) | ||||||
|  | 	{ | ||||||
|  | 		CProfile_Colors[Color_Red] = true; | ||||||
|  | 		CProfile_Colors[Color_Blue] = true; | ||||||
|  | 		CProfile_Colors[Color_Olive] = true; | ||||||
|  | 		CProfile_Colors[Color_Darkred] = true; | ||||||
|  | 		CProfile_Colors[Color_Lime] = true; | ||||||
|  | 		CProfile_Colors[Color_Lightred] = true; | ||||||
|  | 		CProfile_Colors[Color_Purple] = true; | ||||||
|  | 		CProfile_Colors[Color_Grey] = true; | ||||||
|  | 		CProfile_Colors[Color_Orange] = true; | ||||||
|  | 		CProfile_TeamIndex[Color_Red] = 2; | ||||||
|  | 		CProfile_TeamIndex[Color_Blue] = 3; | ||||||
|  | 		CProfile_SayText2 = true; | ||||||
|  | 	} | ||||||
|  | 	else if (StrEqual(szGameName, "tf", false)) | ||||||
|  | 	{ | ||||||
|  | 		CProfile_Colors[Color_Lightgreen] = true; | ||||||
|  | 		CProfile_Colors[Color_Red] = true; | ||||||
|  | 		CProfile_Colors[Color_Blue] = true; | ||||||
|  | 		CProfile_Colors[Color_Olive] = true; | ||||||
|  | 		CProfile_TeamIndex[Color_Lightgreen] = SERVER_INDEX; | ||||||
|  | 		CProfile_TeamIndex[Color_Red] = 2; | ||||||
|  | 		CProfile_TeamIndex[Color_Blue] = 3; | ||||||
|  | 		CProfile_SayText2 = true; | ||||||
|  | 	} | ||||||
|  | 	else if (StrEqual(szGameName, "left4dead", false) || StrEqual(szGameName, "left4dead2", false)) | ||||||
|  | 	{ | ||||||
|  | 		CProfile_Colors[Color_Lightgreen] = true; | ||||||
|  | 		CProfile_Colors[Color_Red] = true; | ||||||
|  | 		CProfile_Colors[Color_Blue] = true; | ||||||
|  | 		CProfile_Colors[Color_Olive] = true;		 | ||||||
|  | 		CProfile_TeamIndex[Color_Lightgreen] = SERVER_INDEX; | ||||||
|  | 		CProfile_TeamIndex[Color_Red] = 3; | ||||||
|  | 		CProfile_TeamIndex[Color_Blue] = 2; | ||||||
|  | 		CProfile_SayText2 = true; | ||||||
|  | 	} | ||||||
|  | 	else if (StrEqual(szGameName, "hl2mp", false)) | ||||||
|  | 	{ | ||||||
|  | 		/* hl2mp profile is based on mp_teamplay convar */ | ||||||
|  | 		if (GetConVarBool(FindConVar("mp_teamplay"))) | ||||||
|  | 		{ | ||||||
|  | 			CProfile_Colors[Color_Red] = true; | ||||||
|  | 			CProfile_Colors[Color_Blue] = true; | ||||||
|  | 			CProfile_Colors[Color_Olive] = true; | ||||||
|  | 			CProfile_TeamIndex[Color_Red] = 3; | ||||||
|  | 			CProfile_TeamIndex[Color_Blue] = 2; | ||||||
|  | 			CProfile_SayText2 = true; | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			CProfile_SayText2 = false; | ||||||
|  | 			CProfile_Colors[Color_Olive] = true; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	else if (StrEqual(szGameName, "dod", false)) | ||||||
|  | 	{ | ||||||
|  | 		CProfile_Colors[Color_Olive] = true; | ||||||
|  | 		CProfile_SayText2 = false; | ||||||
|  | 	} | ||||||
|  | 	/* Profile for other games */ | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 		if (GetUserMessageId("SayText2") == INVALID_MESSAGE_ID) | ||||||
|  | 		{ | ||||||
|  | 			CProfile_SayText2 = false; | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			CProfile_Colors[Color_Red] = true; | ||||||
|  | 			CProfile_Colors[Color_Blue] = true; | ||||||
|  | 			CProfile_TeamIndex[Color_Red] = 2; | ||||||
|  | 			CProfile_TeamIndex[Color_Blue] = 3; | ||||||
|  | 			CProfile_SayText2 = true; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public Action:CEvent_MapStart(Handle:event, const String:name[], bool:dontBroadcast) | ||||||
|  | { | ||||||
|  | 	CSetupProfile(); | ||||||
|  | 	 | ||||||
|  | 	for (new i = 1; i <= MaxClients; i++) | ||||||
|  | 		CSkipList[i] = false; | ||||||
|  | } | ||||||
							
								
								
									
										482
									
								
								includes/dhooks.inc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										482
									
								
								includes/dhooks.inc
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,482 @@ | |||||||
|  | #if defined _dhooks_included
 | ||||||
|  | #endinput
 | ||||||
|  | #endif
 | ||||||
|  | #define _dhooks_included
 | ||||||
|  | 
 | ||||||
|  | enum ObjectValueType | ||||||
|  | { | ||||||
|  | 	ObjectValueType_Int = 0, | ||||||
|  | 	ObjectValueType_Bool, | ||||||
|  | 	ObjectValueType_Ehandle, | ||||||
|  | 	ObjectValueType_Float, | ||||||
|  | 	ObjectValueType_CBaseEntityPtr, | ||||||
|  | 	ObjectValueType_IntPtr, | ||||||
|  | 	ObjectValueType_BoolPtr, | ||||||
|  | 	ObjectValueType_EhandlePtr, | ||||||
|  | 	ObjectValueType_FloatPtr, | ||||||
|  | 	ObjectValueType_Vector, | ||||||
|  | 	ObjectValueType_VectorPtr, | ||||||
|  | 	ObjectValueType_CharPtr, | ||||||
|  | 	ObjectValueType_String | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | enum ListenType | ||||||
|  | { | ||||||
|  | 	ListenType_Created, | ||||||
|  | 	ListenType_Deleted | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | enum ReturnType | ||||||
|  | { | ||||||
|  | 	ReturnType_Unknown, | ||||||
|  | 	ReturnType_Void, | ||||||
|  | 	ReturnType_Int, | ||||||
|  | 	ReturnType_Bool, | ||||||
|  | 	ReturnType_Float, | ||||||
|  | 	ReturnType_String, //Note this is a string_t
 | ||||||
|  | 	ReturnType_StringPtr, //Note this is a string_t *
 | ||||||
|  | 	ReturnType_CharPtr, | ||||||
|  | 	ReturnType_Vector, | ||||||
|  | 	ReturnType_VectorPtr, | ||||||
|  | 	ReturnType_CBaseEntity, | ||||||
|  | 	ReturnType_Edict | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | enum HookParamType | ||||||
|  | { | ||||||
|  | 	HookParamType_Unknown, | ||||||
|  | 	HookParamType_Int, | ||||||
|  | 	HookParamType_Bool, | ||||||
|  | 	HookParamType_Float, | ||||||
|  | 	HookParamType_String, //Note this is a string_t
 | ||||||
|  | 	HookParamType_StringPtr, //Note this is a string_t *
 | ||||||
|  | 	HookParamType_CharPtr, | ||||||
|  | 	HookParamType_VectorPtr, | ||||||
|  | 	HookParamType_CBaseEntity, | ||||||
|  | 	HookParamType_ObjectPtr, | ||||||
|  | 	HookParamType_Edict, | ||||||
|  | 	HookParamType_Object | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | enum ThisPointerType | ||||||
|  | { | ||||||
|  | 	ThisPointer_Ignore, | ||||||
|  | 	ThisPointer_CBaseEntity, | ||||||
|  | 	ThisPointer_Address | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | enum HookType | ||||||
|  | { | ||||||
|  | 	HookType_Entity, | ||||||
|  | 	HookType_GameRules, | ||||||
|  | 	HookType_Raw | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | enum MRESReturn | ||||||
|  | { | ||||||
|  | 	MRES_ChangedHandled = -2,	// Use changed values and return MRES_Handled
 | ||||||
|  | 	MRES_ChangedOverride,		// Use changed values and return MRES_Override
 | ||||||
|  | 	MRES_Ignored,				// plugin didn't take any action
 | ||||||
|  | 	MRES_Handled,				// plugin did something, but real function should still be called
 | ||||||
|  | 	MRES_Override,				// call real function, but use my return value
 | ||||||
|  | 	MRES_Supercede				// skip real function; use my return value
 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | enum DHookPassFlag | ||||||
|  | { | ||||||
|  | 	DHookPass_ByVal = (1<<0), | ||||||
|  | 	DHookPass_ByRef = (1<<1) | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | typeset ListenCB | ||||||
|  | { | ||||||
|  | 	//Deleted
 | ||||||
|  | 	function void (int entity); | ||||||
|  | 	 | ||||||
|  | 	//Created
 | ||||||
|  | 	function void (int entity, const char[] classname); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | typeset DHookRemovalCB | ||||||
|  | { | ||||||
|  | 	function void (int hookid); | ||||||
|  | }; | ||||||
|  | typeset DHookCallback | ||||||
|  | { | ||||||
|  | 	//Function Example: void Ham::Test() with this pointer ignore
 | ||||||
|  | 	function MRESReturn (); | ||||||
|  | 	 | ||||||
|  | 	//Function Example: void Ham::Test() with this pointer passed
 | ||||||
|  | 	function MRESReturn (int pThis); | ||||||
|  | 	 | ||||||
|  | 	//Function Example: void Ham::Test(int cake) with this pointer ignore
 | ||||||
|  | 	function MRESReturn (Handle hParams); | ||||||
|  | 	 | ||||||
|  | 	//Function Example: void Ham::Test(int cake) with this pointer passed
 | ||||||
|  | 	function MRESReturn (int pThis, Handle hParams); | ||||||
|  | 	 | ||||||
|  | 	//Function Example: int Ham::Test() with this pointer ignore
 | ||||||
|  | 	function MRESReturn (Handle hReturn); | ||||||
|  | 	 | ||||||
|  | 	//Function Example: int Ham::Test() with this pointer passed
 | ||||||
|  | 	function MRESReturn (int pThis, Handle hReturn); | ||||||
|  | 	 | ||||||
|  | 	//Function Example: int Ham::Test(int cake) with this pointer ignore
 | ||||||
|  | 	function MRESReturn (Handle hReturn, Handle hParams); | ||||||
|  | 	 | ||||||
|  | 	//Function Example: int Ham::Test(int cake) with this pointer passed
 | ||||||
|  | 	function MRESReturn (int pThis, Handle hReturn, Handle hParams); | ||||||
|  | 	 | ||||||
|  | 	//Address NOW
 | ||||||
|  | 	 | ||||||
|  | 	//Function Example: void Ham::Test() with this pointer passed
 | ||||||
|  | 	function MRESReturn (Address pThis); | ||||||
|  | 	 | ||||||
|  | 	//Function Example: void Ham::Test(int cake) with this pointer passed
 | ||||||
|  | 	function MRESReturn (Address pThis, Handle hParams); | ||||||
|  | 	 | ||||||
|  | 	//Function Example: int Ham::Test() with this pointer passed
 | ||||||
|  | 	function MRESReturn (Address pThis, Handle hReturn); | ||||||
|  | 	 | ||||||
|  | 	//Function Example: int Ham::Test(int cake) with this pointer passed
 | ||||||
|  | 	function MRESReturn (Address pThis, Handle hReturn, Handle hParams); | ||||||
|  | 	 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /* Adds an entity listener hook | ||||||
|  |  * | ||||||
|  |  * @param type			Type of listener to add | ||||||
|  |  * @param callback		Callback to use | ||||||
|  |  * | ||||||
|  |  * @noreturn | ||||||
|  | */ | ||||||
|  | native void DHookAddEntityListener(ListenType type, ListenCB callback); | ||||||
|  | 
 | ||||||
|  | /* Removes an entity listener hook | ||||||
|  |  * | ||||||
|  |  * @param type			Type of listener to remove | ||||||
|  |  * @param callback		Callback this listener was using | ||||||
|  |  * | ||||||
|  |  * @return True if one was removed false otherwise. | ||||||
|  | */ | ||||||
|  | native bool DHookRemoveEntityListener(ListenType type, ListenCB callback); | ||||||
|  | 
 | ||||||
|  | /* Creates a hook | ||||||
|  |  * | ||||||
|  |  * @param offset		vtable offset for function to hook | ||||||
|  |  * @param hooktype		Type of hook | ||||||
|  |  * @param returntype	Type type of return | ||||||
|  |  * @param thistype		Type of this pointer or ignore (ignore can be used if not needed) | ||||||
|  |  * @param callback		Callback function
 | ||||||
|  |  *  | ||||||
|  |  * @return Returns setup handle for the hook or INVALID_HANDLE. | ||||||
|  | */ | ||||||
|  | native Handle DHookCreate(int offset, HookType hooktype, ReturnType returntype, ThisPointerType thistype, DHookCallback callback); | ||||||
|  | 
 | ||||||
|  | /* Adds param to a hook setup | ||||||
|  |  * | ||||||
|  |  * @param setup			Setup handle to add the param to. | ||||||
|  |  * @param type			Param type | ||||||
|  |  * @param size			Used for Objects (not Object ptr) to define the size of the object. | ||||||
|  |  * @param flag			Used to change the pass type. | ||||||
|  |  *  | ||||||
|  |  * @error	Invalid setup handle or too many params added (request upping the max in thread) | ||||||
|  |  * @noreturn | ||||||
|  | */ | ||||||
|  | native void DHookAddParam(Handle setup, HookParamType type, int size=-1, DHookPassFlag flag=DHookPass_ByVal); | ||||||
|  | //native DHookAddParam(Handle:setup, HookParamType:type);
 | ||||||
|  | 
 | ||||||
|  | /* Hook entity | ||||||
|  |  *  | ||||||
|  |  * @param setup			Setup handle to use to add the hook. | ||||||
|  |  * @param post			True to make the hook a post hook. (If you need to change the retunr value or need the return value use a post hook! If you need to change params and return use a pre and post hook!) | ||||||
|  |  * @param entity		Entity index to hook on. | ||||||
|  |  * @param removalcb		Callback for when the hook is removed (Entity hooks are auto-removed on entity destroyed and will call this callback) | ||||||
|  |  *  | ||||||
|  |  * @error Invalid setup handle, invalid entity or invalid hook type. | ||||||
|  |  * @return -1 on fail a hookid on success | ||||||
|  | */ | ||||||
|  | native int DHookEntity(Handle setup, bool post, int entity, DHookRemovalCB removalcb=INVALID_FUNCTION); | ||||||
|  | 
 | ||||||
|  | /* Hook gamerules | ||||||
|  |  *  | ||||||
|  |  * @param setup			Setup handle to use to add the hook. | ||||||
|  |  * @param post			True to make the hook a post hook. (If you need to change the retunr value or need the return value use a post hook! If you need to change params and return use a pre and post hook!) | ||||||
|  |  * @param removalcb		Callback for when the hook is removed (Game rules hooks are auto-removed on map end and will call this callback) | ||||||
|  |  *  | ||||||
|  |  * @error Invalid setup handle, failing to get gamerules pointer or invalid hook type. | ||||||
|  |  * @return -1 on fail a hookid on success | ||||||
|  | */ | ||||||
|  | native int DHookGamerules(Handle setup, bool post, DHookRemovalCB removalcb=INVALID_FUNCTION); | ||||||
|  | 
 | ||||||
|  | /* Hook a raw pointer | ||||||
|  |  *  | ||||||
|  |  * @param setup			Setup handle to use to add the hook. | ||||||
|  |  * @param post			True to make the hook a post hook. (If you need to change the retunr value or need the return value use a post hook! If you need to change params and return use a pre and post hook!) | ||||||
|  |  * @param addr			This pointer address. | ||||||
|  |  * @param removalcb		Callback for when the hook is removed (Entity hooks are auto-removed on entity destroyed and will call this callback) | ||||||
|  |  *  | ||||||
|  |  * @error Invalid setup handle, invalid address or invalid hook type. | ||||||
|  |  * @return -1 on fail a hookid on success | ||||||
|  | */ | ||||||
|  | native int DHookRaw(Handle setup, bool post, Address addr, DHookRemovalCB removalcb=INVALID_FUNCTION); | ||||||
|  | 
 | ||||||
|  | /* Remove hook by hook id | ||||||
|  |  *  | ||||||
|  |  * @param hookid		Hook id to remove | ||||||
|  |  *  | ||||||
|  |  * @return true on success false otherwise | ||||||
|  |  * @note This will not fire the removal callback! | ||||||
|  | */ | ||||||
|  | native bool DHookRemoveHookID(int hookid); | ||||||
|  | 
 | ||||||
|  | /* Get param value (Only use for: int, entity, bool or float param types) | ||||||
|  |  *  | ||||||
|  |  * @param hParams		Handle to params structure | ||||||
|  |  * @param num			Param number to get. (Example if the function has 2 params and you need the value of the first param num would be 1. 0 Will return the number of params stored) | ||||||
|  |  *  | ||||||
|  |  * @error Invalid handle. Invalid param number. Invalid param type. | ||||||
|  |  * @return value if num greater than 0. If 0 returns paramcount. | ||||||
|  | */ | ||||||
|  | native any DHookGetParam(Handle hParams, int num); | ||||||
|  | 
 | ||||||
|  | /* Get vector param value | ||||||
|  |  *  | ||||||
|  |  * @param hParams		Handle to params structure | ||||||
|  |  * @param num			Param number to get. (Example if the function has 2 params and you need the value of the first param num would be 1.) | ||||||
|  |  * @param vec			Vector buffer to store result. | ||||||
|  |  *  | ||||||
|  |  * @error Invalid handle. Invalid param number. Invalid param type. | ||||||
|  |  * @noreturn | ||||||
|  | */ | ||||||
|  | native void DHookGetParamVector(Handle hParams, int num, float vec[3]); | ||||||
|  | 
 | ||||||
|  | /* Get string param value | ||||||
|  |  *  | ||||||
|  |  * @param hParams		Handle to params structure | ||||||
|  |  * @param num			Param number to get. (Example if the function has 2 params and you need the value of the first param num would be 1.) | ||||||
|  |  * @param buffer		String buffer to store result | ||||||
|  |  * @param size			Buffer size | ||||||
|  |  *  | ||||||
|  |  * @error Invalid handle. Invalid param number. Invalid param type. | ||||||
|  |  * @noreturn | ||||||
|  | */ | ||||||
|  | native void DHookGetParamString(Handle hParams, int num, char[] buffer, int size); | ||||||
|  | 
 | ||||||
|  | /* Set param value (Only use for: int, entity, bool or float param types) | ||||||
|  |  *  | ||||||
|  |  * @param hParams		Handle to params structure | ||||||
|  |  * @params num			Param number to set (Example if the function has 2 params and you need to set the value of the first param num would be 1.) | ||||||
|  |  * @param value			Value to set it as (only pass int, bool, float or entity index) | ||||||
|  |  *  | ||||||
|  |  * @error Invalid handle. Invalid param number. Invalid param type. | ||||||
|  |  * @noreturn | ||||||
|  | */ | ||||||
|  | native void DHookSetParam(Handle hParams, int num, any value); | ||||||
|  | 
 | ||||||
|  | /* Set vector param value | ||||||
|  |  *  | ||||||
|  |  * @param hParams		Handle to params structure | ||||||
|  |  * @params num			Param number to set (Example if the function has 2 params and you need to set the value of the first param num would be 1.) | ||||||
|  |  * @param vec			Value to set vector as. | ||||||
|  |  *  | ||||||
|  |  * @error Invalid handle. Invalid param number. Invalid param type. | ||||||
|  |  * @noreturn | ||||||
|  | */ | ||||||
|  | native void DHookSetParamVector(Handle hParams, int num, float vec[3]); | ||||||
|  | 
 | ||||||
|  | /* Set string param value | ||||||
|  |  *  | ||||||
|  |  * @param hParams		Handle to params structure | ||||||
|  |  * @params num			Param number to set (Example if the function has 2 params and you need to set the value of the first param num would be 1.) | ||||||
|  |  * @param value			Value to set string as. | ||||||
|  |  *  | ||||||
|  |  * @error Invalid handle. Invalid param number. Invalid param type. | ||||||
|  |  * @noreturn | ||||||
|  | */ | ||||||
|  | native void DHookSetParamString(Handle hParams, int num, char[] value); | ||||||
|  | 
 | ||||||
|  | /* Get return value (Only use for: int, entity, bool or float return types) | ||||||
|  |  *  | ||||||
|  |  * @param hReturn		Handle to return structure | ||||||
|  |  *  | ||||||
|  |  * @error Invalid Handle, invalid type. | ||||||
|  |  * @return Returns default value if prehook returns actual value if post hook. | ||||||
|  | */ | ||||||
|  | native any DHookGetReturn(Handle hReturn); | ||||||
|  | 
 | ||||||
|  | /* Get return vector value | ||||||
|  |  *  | ||||||
|  |  * @param hReturn		Handle to return structure | ||||||
|  |  * @param vec			Vector buffer to store result in. (In pre hooks will be default value (0.0,0.0,0.0)) | ||||||
|  |  *  | ||||||
|  |  * @error Invalid Handle, invalid type. | ||||||
|  |  * @noreturn | ||||||
|  | */ | ||||||
|  | native void DHookGetReturnVector(Handle hReturn, float vec[3]); | ||||||
|  | 
 | ||||||
|  | /* Get return string value | ||||||
|  |  *  | ||||||
|  |  * @param hReturn		Handle to return structure | ||||||
|  |  * @param buffer		String buffer to store result in. (In pre hooks will be default value "") | ||||||
|  |  * @param size			String buffer size | ||||||
|  |  *  | ||||||
|  |  * @error Invalid Handle, invalid type. | ||||||
|  |  * @noreturn | ||||||
|  | */ | ||||||
|  | native void DHookGetReturnString(Handle hReturn, char[] buffer, int size); | ||||||
|  | 
 | ||||||
|  | /* Set return value (Only use for: int, entity, bool or float return types) | ||||||
|  |  *  | ||||||
|  |  * @param hReturn		Handle to return structure | ||||||
|  |  * @param value			Value to set return as | ||||||
|  |  *  | ||||||
|  |  * @error Invalid Handle, invalid type. | ||||||
|  |  * @noreturn | ||||||
|  | */ | ||||||
|  | native void DHookSetReturn(Handle hReturn, any value); | ||||||
|  | 
 | ||||||
|  | /* Set return vector value | ||||||
|  |  *  | ||||||
|  |  * @param hReturn		Handle to return structure | ||||||
|  |  * @param vec			Value to set return vector as | ||||||
|  |  *  | ||||||
|  |  * @error Invalid Handle, invalid type. | ||||||
|  |  * @noreturn | ||||||
|  | */ | ||||||
|  | native void DHookSetReturnVector(Handle hReturn, float vec[3]); | ||||||
|  | 
 | ||||||
|  | /* Set return string value | ||||||
|  |  *  | ||||||
|  |  * @param hReturn		Handle to return structure | ||||||
|  |  * @param value			Value to set return string as | ||||||
|  |  *  | ||||||
|  |  * @error Invalid Handle, invalid type. | ||||||
|  |  * @noreturn | ||||||
|  | */ | ||||||
|  | native void DHookSetReturnString(Handle hReturn, char[] value); | ||||||
|  | 
 | ||||||
|  | //WE SHOULD WRAP THESE AROUND STOCKS FOR NON PTR AS WE SUPPORT BOTH WITH THESE NATIVE'S
 | ||||||
|  | 
 | ||||||
|  | /* Gets an objects variable value | ||||||
|  |  * | ||||||
|  |  * @param hParams		Handle to params structure | ||||||
|  |  * @param num			Param number to get. | ||||||
|  |  * @param offset		Offset within the object to the var to get. | ||||||
|  |  * @param type			Type of var it is | ||||||
|  |  * | ||||||
|  |  * @error Invalid handle. Invalid param number. Invalid param type. Invalid Object type. | ||||||
|  |  * @return Value of the objects var. If EHANDLE type or entity returns entity index. | ||||||
|  | */ | ||||||
|  | native any DHookGetParamObjectPtrVar(Handle hParams, int num, int offset, ObjectValueType type); | ||||||
|  | 
 | ||||||
|  | /* Sets an objects variable value | ||||||
|  |  * | ||||||
|  |  * @param hParams		Handle to params structure | ||||||
|  |  * @param num			Param number to set. | ||||||
|  |  * @param offset		Offset within the object to the var to set. | ||||||
|  |  * @param type			Type of var it is | ||||||
|  |  * @param value			The value to set the var to. | ||||||
|  |  * | ||||||
|  |  * @error Invalid handle. Invalid param number. Invalid param type. Invalid Object type. | ||||||
|  |  * @noreturn | ||||||
|  | */ | ||||||
|  | native void DHookSetParamObjectPtrVar(Handle hParams, int num, int offset, ObjectValueType type, any value); | ||||||
|  | 
 | ||||||
|  | /* Gets an objects vector variable value | ||||||
|  |  * | ||||||
|  |  * @param hParams		Handle to params structure | ||||||
|  |  * @param num			Param number to get. | ||||||
|  |  * @param offset		Offset within the object to the var to get. | ||||||
|  |  * @param type			Type of var it is | ||||||
|  |  * @param buffer		Buffer to store the result vector | ||||||
|  |  * | ||||||
|  |  * @error Invalid handle. Invalid param number. Invalid param type. Invalid Object type. | ||||||
|  |  * @noreturn | ||||||
|  | */ | ||||||
|  | native void DHookGetParamObjectPtrVarVector(Handle hParams, int num, int offset, ObjectValueType type, float buffer[3]); | ||||||
|  | 
 | ||||||
|  | /* Sets an objects vector variable value | ||||||
|  |  * | ||||||
|  |  * @param hParams		Handle to params structure | ||||||
|  |  * @param num			Param number to set. | ||||||
|  |  * @param offset		Offset within the object to the var to set. | ||||||
|  |  * @param type			Type of var it is | ||||||
|  |  * @param value			The value to set the vector var to. | ||||||
|  |  * | ||||||
|  |  * @error Invalid handle. Invalid param number. Invalid param type. Invalid Object type. | ||||||
|  |  * @noreturn | ||||||
|  | */ | ||||||
|  | native void DHookSetParamObjectPtrVarVector(Handle hParams, int num, int offset, ObjectValueType type, float value[3]); | ||||||
|  | 
 | ||||||
|  | /* Gets an objects string variable value | ||||||
|  |  * | ||||||
|  |  * @param hParams		Handle to params structure | ||||||
|  |  * @param num			Param number to get. | ||||||
|  |  * @param offset		Offset within the object to the var to get. | ||||||
|  |  * @param type			Type of var it is | ||||||
|  |  * @param buffer		Buffer to store the result vector | ||||||
|  |  * @param size			Size of the buffer | ||||||
|  |  * | ||||||
|  |  * @error Invalid handle. Invalid param number. Invalid param type. Invalid Object type. | ||||||
|  |  * @noreturn | ||||||
|  | */ | ||||||
|  | native void DHookGetParamObjectPtrString(Handle hParams, int num, int offset, ObjectValueType type, char[] buffer, int size); | ||||||
|  | 
 | ||||||
|  | /* Checks if a pointer param is null | ||||||
|  |  * | ||||||
|  |  * @param hParams		Handle to params structure | ||||||
|  |  * @param num			Param number to check. | ||||||
|  |  * | ||||||
|  |  * @error Non pointer param | ||||||
|  |  * @return True if null false otherwise. | ||||||
|  | */ | ||||||
|  | native bool DHookIsNullParam(Handle hParams, int num); | ||||||
|  | 
 | ||||||
|  | public Extension __ext_dhooks = | ||||||
|  | { | ||||||
|  | 	name = "dhooks", | ||||||
|  | 	file = "dhooks.ext", | ||||||
|  | #if defined AUTOLOAD_EXTENSIONS
 | ||||||
|  | 	autoload = 1, | ||||||
|  | #else
 | ||||||
|  | 	autoload = 0, | ||||||
|  | #endif
 | ||||||
|  | #if defined REQUIRE_EXTENSIONS
 | ||||||
|  | 	required = 1, | ||||||
|  | #else
 | ||||||
|  | 	required = 0, | ||||||
|  | #endif
 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #if !defined REQUIRE_EXTENSIONS
 | ||||||
|  | public __ext_dhooks_SetNTVOptional() | ||||||
|  | { | ||||||
|  | 	MarkNativeAsOptional("DHookAddEntityListener"); | ||||||
|  | 	MarkNativeAsOptional("DHookRemoveEntityListener"); | ||||||
|  | 	MarkNativeAsOptional("DHookCreate"); | ||||||
|  | 	MarkNativeAsOptional("DHookAddParam"); | ||||||
|  | 	MarkNativeAsOptional("DHookEntity"); | ||||||
|  | 	MarkNativeAsOptional("DHookGamerules"); | ||||||
|  | 	MarkNativeAsOptional("DHookRaw"); | ||||||
|  | 	MarkNativeAsOptional("DHookRemoveHookID"); | ||||||
|  | 	MarkNativeAsOptional("DHookGetParam"); | ||||||
|  | 	MarkNativeAsOptional("DHookGetParamVector"); | ||||||
|  | 	MarkNativeAsOptional("DHookGetParamString"); | ||||||
|  | 	MarkNativeAsOptional("DHookSetParam"); | ||||||
|  | 	MarkNativeAsOptional("DHookSetParamVector"); | ||||||
|  | 	MarkNativeAsOptional("DHookSetParamString"); | ||||||
|  | 	MarkNativeAsOptional("DHookGetReturn"); | ||||||
|  | 	MarkNativeAsOptional("DHookGetReturnVector"); | ||||||
|  | 	MarkNativeAsOptional("DHookGetReturnString"); | ||||||
|  | 	MarkNativeAsOptional("DHookSetReturn"); | ||||||
|  | 	MarkNativeAsOptional("DHookSetReturnVector"); | ||||||
|  | 	MarkNativeAsOptional("DHookSetReturnString"); | ||||||
|  | 	MarkNativeAsOptional("DHookGetParamObjectPtrVar"); | ||||||
|  | 	MarkNativeAsOptional("DHookSetParamObjectPtrVar"); | ||||||
|  | 	MarkNativeAsOptional("DHookGetParamObjectPtrVarVector"); | ||||||
|  | 	MarkNativeAsOptional("DHookSetParamObjectPtrVarVector"); | ||||||
|  | 	MarkNativeAsOptional("DHookIsNullParam"); | ||||||
|  | 	MarkNativeAsOptional("DHookGetParamObjectPtrString"); | ||||||
|  | } | ||||||
|  | #endif
 | ||||||
							
								
								
									
										674
									
								
								includes/morecolors.inc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										674
									
								
								includes/morecolors.inc
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,674 @@ | |||||||
|  | // MOAR COLORS
 | ||||||
|  | // By Dr. McKay
 | ||||||
|  | // Inspired by: https://forums.alliedmods.net/showthread.php?t=96831
 | ||||||
|  | 
 | ||||||
|  | #if defined _colors_included
 | ||||||
|  |  #endinput
 | ||||||
|  | #endif
 | ||||||
|  | #define _colors_included
 | ||||||
|  | 
 | ||||||
|  | #include <regex>
 | ||||||
|  | 
 | ||||||
|  | #define MORE_COLORS_VERSION		"1.9.1"
 | ||||||
|  | #define MAX_MESSAGE_LENGTH		256
 | ||||||
|  | #define MAX_BUFFER_LENGTH		(MAX_MESSAGE_LENGTH * 4)
 | ||||||
|  | 
 | ||||||
|  | #define COLOR_RED				0xFF4040
 | ||||||
|  | #define COLOR_BLUE				0x99CCFF
 | ||||||
|  | #define COLOR_GRAY				0xCCCCCC
 | ||||||
|  | #define COLOR_GREEN				0x3EFF3E
 | ||||||
|  | 
 | ||||||
|  | #define GAME_DODS				0
 | ||||||
|  | 
 | ||||||
|  | new bool:CSkipList[MAXPLAYERS + 1]; | ||||||
|  | new Handle:CTrie; | ||||||
|  | new CTeamColors[][] = {{0xCCCCCC, 0x4D7942, 0xFF4040}}; // Multi-dimensional array for games that don't support SayText2. First index is the game index (as defined by the GAME_ defines), second index is team. 0 = spectator, 1 = team1, 2 = team2
 | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Prints a message to a specific client in the chat area. | ||||||
|  |  * Supports color tags. | ||||||
|  |  *  | ||||||
|  |  * @param client		Client index. | ||||||
|  |  * @param message		Message (formatting rules). | ||||||
|  |  * @noreturn | ||||||
|  |  *  | ||||||
|  |  * On error/Errors:		If the client is not connected an error will be thrown. | ||||||
|  |  */ | ||||||
|  | stock CPrintToChat(client, const String:message[], any:...) { | ||||||
|  | 	CCheckTrie(); | ||||||
|  | 	if(client <= 0 || client > MaxClients) { | ||||||
|  | 		ThrowError("Invalid client index %i", client); | ||||||
|  | 	} | ||||||
|  | 	if(!IsClientInGame(client)) { | ||||||
|  | 		ThrowError("Client %i is not in game", client); | ||||||
|  | 	} | ||||||
|  | 	decl String:buffer[MAX_BUFFER_LENGTH], String:buffer2[MAX_BUFFER_LENGTH]; | ||||||
|  | 	SetGlobalTransTarget(client); | ||||||
|  | 	Format(buffer, sizeof(buffer), "\x01%s", message); | ||||||
|  | 	VFormat(buffer2, sizeof(buffer2), buffer, 3); | ||||||
|  | 	CReplaceColorCodes(buffer2); | ||||||
|  | 	CSendMessage(client, buffer2); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Prints a message to all clients in the chat area. | ||||||
|  |  * Supports color tags. | ||||||
|  |  *  | ||||||
|  |  * @param client		Client index. | ||||||
|  |  * @param message		Message (formatting rules). | ||||||
|  |  * @noreturn | ||||||
|  |  */ | ||||||
|  | stock CPrintToChatAll(const String:message[], any:...) { | ||||||
|  | 	CCheckTrie(); | ||||||
|  | 	decl String:buffer[MAX_BUFFER_LENGTH], String:buffer2[MAX_BUFFER_LENGTH]; | ||||||
|  | 	for(new i = 1; i <= MaxClients; i++) { | ||||||
|  | 		if(!IsClientInGame(i) || CSkipList[i]) { | ||||||
|  | 			CSkipList[i] = false; | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 		SetGlobalTransTarget(i); | ||||||
|  | 		Format(buffer, sizeof(buffer), "\x01%s", message); | ||||||
|  | 		VFormat(buffer2, sizeof(buffer2), buffer, 2); | ||||||
|  | 		CReplaceColorCodes(buffer2); | ||||||
|  | 		CSendMessage(i, buffer2); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Prints a message to a specific client in the chat area. | ||||||
|  |  * Supports color tags and teamcolor tag. | ||||||
|  |  *  | ||||||
|  |  * @param client		Client index. | ||||||
|  |  * @param author		Author index whose color will be used for teamcolor tag. | ||||||
|  |  * @param message		Message (formatting rules). | ||||||
|  |  * @noreturn | ||||||
|  |  *  | ||||||
|  |  * On error/Errors:		If the client or author are not connected an error will be thrown | ||||||
|  |  */ | ||||||
|  | stock CPrintToChatEx(client, author, const String:message[], any:...) { | ||||||
|  | 	CCheckTrie(); | ||||||
|  | 	if(client <= 0 || client > MaxClients) { | ||||||
|  | 		ThrowError("Invalid client index %i", client); | ||||||
|  | 	} | ||||||
|  | 	if(!IsClientInGame(client)) { | ||||||
|  | 		ThrowError("Client %i is not in game", client); | ||||||
|  | 	} | ||||||
|  | 	if(author <= 0 || author > MaxClients) { | ||||||
|  | 		ThrowError("Invalid client index %i", author); | ||||||
|  | 	} | ||||||
|  | 	if(!IsClientInGame(author)) { | ||||||
|  | 		ThrowError("Client %i is not in game", author); | ||||||
|  | 	} | ||||||
|  | 	decl String:buffer[MAX_BUFFER_LENGTH], String:buffer2[MAX_BUFFER_LENGTH]; | ||||||
|  | 	SetGlobalTransTarget(client); | ||||||
|  | 	Format(buffer, sizeof(buffer), "\x01%s", message); | ||||||
|  | 	VFormat(buffer2, sizeof(buffer2), buffer, 4); | ||||||
|  | 	CReplaceColorCodes(buffer2, author); | ||||||
|  | 	CSendMessage(client, buffer2, author); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Prints a message to all clients in the chat area. | ||||||
|  |  * Supports color tags and teamcolor tag. | ||||||
|  |  * | ||||||
|  |  * @param author	  Author index whose color will be used for teamcolor tag. | ||||||
|  |  * @param message   Message (formatting rules). | ||||||
|  |  * @noreturn | ||||||
|  |  *  | ||||||
|  |  * On error/Errors:   If the author is not connected an error will be thrown. | ||||||
|  |  */ | ||||||
|  | stock CPrintToChatAllEx(author, const String:message[], any:...) { | ||||||
|  | 	CCheckTrie(); | ||||||
|  | 	if(author <= 0 || author > MaxClients) { | ||||||
|  | 		ThrowError("Invalid client index %i", author); | ||||||
|  | 	} | ||||||
|  | 	if(!IsClientInGame(author)) { | ||||||
|  | 		ThrowError("Client %i is not in game", author); | ||||||
|  | 	} | ||||||
|  | 	decl String:buffer[MAX_BUFFER_LENGTH], String:buffer2[MAX_BUFFER_LENGTH]; | ||||||
|  | 	for(new i = 1; i <= MaxClients; i++) { | ||||||
|  | 		if(!IsClientInGame(i) || CSkipList[i]) { | ||||||
|  | 			CSkipList[i] = false; | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 		SetGlobalTransTarget(i); | ||||||
|  | 		Format(buffer, sizeof(buffer), "\x01%s", message); | ||||||
|  | 		VFormat(buffer2, sizeof(buffer2), buffer, 3); | ||||||
|  | 		CReplaceColorCodes(buffer2, author); | ||||||
|  | 		CSendMessage(i, buffer2, author); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Sends a SayText2 usermessage | ||||||
|  |  *  | ||||||
|  |  * @param client	Client to send usermessage to | ||||||
|  |  * @param message	Message to send | ||||||
|  |  * @noreturn | ||||||
|  |  */ | ||||||
|  | stock CSendMessage(client, const String:message[], author=0) { | ||||||
|  | 	if(author == 0) { | ||||||
|  | 		author = client; | ||||||
|  | 	} | ||||||
|  | 	decl String:buffer[MAX_MESSAGE_LENGTH], String:game[16]; | ||||||
|  | 	GetGameFolderName(game, sizeof(game)); | ||||||
|  | 	strcopy(buffer, sizeof(buffer), message); | ||||||
|  | 	new UserMsg:index = GetUserMessageId("SayText2"); | ||||||
|  | 	if(index == INVALID_MESSAGE_ID) { | ||||||
|  | 		if(StrEqual(game, "dod")) { | ||||||
|  | 			new team = GetClientTeam(author); | ||||||
|  | 			if(team == 0) { | ||||||
|  | 				ReplaceString(buffer, sizeof(buffer), "\x03", "\x04", false); // Unassigned gets green
 | ||||||
|  | 			} else { | ||||||
|  | 				decl String:temp[16]; | ||||||
|  | 				Format(temp, sizeof(temp), "\x07%06X", CTeamColors[GAME_DODS][team - 1]); | ||||||
|  | 				ReplaceString(buffer, sizeof(buffer), "\x03", temp, false); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		PrintToChat(client, "%s", buffer); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 	new Handle:buf = StartMessageOne("SayText2", client, USERMSG_RELIABLE|USERMSG_BLOCKHOOKS); | ||||||
|  | 	if(GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available && GetUserMessageType() == UM_Protobuf) { | ||||||
|  | 		PbSetInt(buf, "ent_idx", author); | ||||||
|  | 		PbSetBool(buf, "chat", true); | ||||||
|  | 		PbSetString(buf, "msg_name", buffer); | ||||||
|  | 		PbAddString(buf, "params", ""); | ||||||
|  | 		PbAddString(buf, "params", ""); | ||||||
|  | 		PbAddString(buf, "params", ""); | ||||||
|  | 		PbAddString(buf, "params", ""); | ||||||
|  | 	} else { | ||||||
|  | 		BfWriteByte(buf, author); // Message author
 | ||||||
|  | 		BfWriteByte(buf, true); // Chat message
 | ||||||
|  | 		BfWriteString(buf, buffer); // Message text
 | ||||||
|  | 	} | ||||||
|  | 	EndMessage(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * This function should only be used right in front of | ||||||
|  |  * CPrintToChatAll or CPrintToChatAllEx. It causes those functions | ||||||
|  |  * to skip the specified client when printing the message. | ||||||
|  |  * After printing the message, the client will no longer be skipped. | ||||||
|  |  *  | ||||||
|  |  * @param client   Client index | ||||||
|  |  * @noreturn | ||||||
|  |  */ | ||||||
|  | stock CSkipNextClient(client) { | ||||||
|  | 	if(client <= 0 || client > MaxClients) { | ||||||
|  | 		ThrowError("Invalid client index %i", client); | ||||||
|  | 	} | ||||||
|  | 	CSkipList[client] = true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Checks if the colors trie is initialized and initializes it if it's not (used internally) | ||||||
|  |  *  | ||||||
|  |  * @return			No return | ||||||
|  |  */ | ||||||
|  | stock CCheckTrie() { | ||||||
|  | 	if(CTrie == INVALID_HANDLE) { | ||||||
|  | 		CTrie = InitColorTrie(); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Replaces color tags in a string with color codes (used internally by CPrintToChat, CPrintToChatAll, CPrintToChatEx, and CPrintToChatAllEx | ||||||
|  |  * | ||||||
|  |  * @param buffer		String. | ||||||
|  |  * @param author		Optional client index to use for {teamcolor} tags, or 0 for none | ||||||
|  |  * @param removeTags	Optional boolean value to determine whether we're replacing tags with colors, or just removing tags, used by CRemoveTags | ||||||
|  |  * @param maxlen		Optional value for max buffer length, used by CRemoveTags | ||||||
|  |  * @noreturn | ||||||
|  |  *  | ||||||
|  |  * On error/Errors:		If the client index passed for author is invalid or not in game. | ||||||
|  |  */ | ||||||
|  | stock CReplaceColorCodes(String:buffer[], author=0, bool:removeTags=false, maxlen=MAX_BUFFER_LENGTH) { | ||||||
|  | 	CCheckTrie(); | ||||||
|  | 	if(!removeTags) { | ||||||
|  | 		ReplaceString(buffer, maxlen, "{default}", "\x01", false); | ||||||
|  | 	} else { | ||||||
|  | 		ReplaceString(buffer, maxlen, "{default}", "", false); | ||||||
|  | 		ReplaceString(buffer, maxlen, "{teamcolor}", "", false); | ||||||
|  | 	} | ||||||
|  | 	if(author != 0 && !removeTags) { | ||||||
|  | 		if(author < 0 || author > MaxClients) { | ||||||
|  | 			ThrowError("Invalid client index %i", author); | ||||||
|  | 		} | ||||||
|  | 		if(!IsClientInGame(author)) { | ||||||
|  | 			ThrowError("Client %i is not in game", author); | ||||||
|  | 		} | ||||||
|  | 		ReplaceString(buffer, maxlen, "{teamcolor}", "\x03", false); | ||||||
|  | 	} | ||||||
|  | 	new cursor = 0; | ||||||
|  | 	new value; | ||||||
|  | 	decl String:tag[32], String:buff[32], String:output[maxlen]; | ||||||
|  | 	strcopy(output, maxlen, buffer); | ||||||
|  | 	// Since the string's size is going to be changing, output will hold the replaced string and we'll search buffer
 | ||||||
|  | 	 | ||||||
|  | 	new Handle:regex = CompileRegex("{[a-zA-Z0-9]+}"); | ||||||
|  | 	for(new i = 0; i < 1000; i++) { // The RegEx extension is quite flaky, so we have to loop here :/. This loop is supposed to be infinite and broken by return, but conditions have been added to be safe.
 | ||||||
|  | 		if(MatchRegex(regex, buffer[cursor]) < 1) { | ||||||
|  | 			CloseHandle(regex); | ||||||
|  | 			strcopy(buffer, maxlen, output); | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  | 		GetRegexSubString(regex, 0, tag, sizeof(tag)); | ||||||
|  | 		CStrToLower(tag); | ||||||
|  | 		cursor = StrContains(buffer[cursor], tag, false) + cursor + 1; | ||||||
|  | 		strcopy(buff, sizeof(buff), tag); | ||||||
|  | 		ReplaceString(buff, sizeof(buff), "{", ""); | ||||||
|  | 		ReplaceString(buff, sizeof(buff), "}", ""); | ||||||
|  | 		 | ||||||
|  | 		if(!GetTrieValue(CTrie, buff, value)) { | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 		 | ||||||
|  | 		if(removeTags) { | ||||||
|  | 			ReplaceString(output, maxlen, tag, "", false); | ||||||
|  | 		} else { | ||||||
|  | 			Format(buff, sizeof(buff), "\x07%06X", value); | ||||||
|  | 			ReplaceString(output, maxlen, tag, buff, false); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	LogError("[MORE COLORS] Infinite loop broken."); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Gets a part of a string | ||||||
|  |  *  | ||||||
|  |  * @param input			String to get the part from | ||||||
|  |  * @param output		Buffer to write to | ||||||
|  |  * @param maxlen		Max length of output buffer | ||||||
|  |  * @param start			Position to start at | ||||||
|  |  * @param numChars		Number of characters to return, or 0 for the end of the string | ||||||
|  |  * @noreturn | ||||||
|  |  */ | ||||||
|  | stock CSubString(const String:input[], String:output[], maxlen, start, numChars=0) { | ||||||
|  | 	new i = 0; | ||||||
|  | 	for(;;) { | ||||||
|  | 		if(i == maxlen - 1 || i >= numChars || input[start + i] == '\0') { | ||||||
|  | 			output[i] = '\0'; | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  | 		output[i] = input[start + i]; | ||||||
|  | 		i++; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Converts a string to lowercase | ||||||
|  |  *  | ||||||
|  |  * @param buffer		String to convert | ||||||
|  |  * @noreturn | ||||||
|  |  */ | ||||||
|  | stock CStrToLower(String:buffer[]) { | ||||||
|  | 	new len = strlen(buffer); | ||||||
|  | 	for(new i = 0; i < len; i++) { | ||||||
|  | 		buffer[i] = CharToLower(buffer[i]); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Adds a color to the colors trie | ||||||
|  |  * | ||||||
|  |  * @param name			Color name, without braces | ||||||
|  |  * @param color			Hexadecimal representation of the color (0xRRGGBB) | ||||||
|  |  * @return				True if color was added successfully, false if a color already exists with that name | ||||||
|  |  */ | ||||||
|  | stock bool:CAddColor(const String:name[], color) { | ||||||
|  | 	CCheckTrie(); | ||||||
|  | 	new value; | ||||||
|  | 	if(GetTrieValue(CTrie, name, value)) { | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 	decl String:newName[64]; | ||||||
|  | 	strcopy(newName, sizeof(newName), name); | ||||||
|  | 	CStrToLower(newName); | ||||||
|  | 	SetTrieValue(CTrie, newName, color); | ||||||
|  | 	return true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Removes color tags from a message | ||||||
|  |  *  | ||||||
|  |  * @param message		Message to remove tags from | ||||||
|  |  * @param maxlen		Maximum buffer length | ||||||
|  |  * @noreturn | ||||||
|  |  */ | ||||||
|  | stock CRemoveTags(String:message[], maxlen) { | ||||||
|  | 	CReplaceColorCodes(message, 0, true, maxlen); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Replies to a command with colors | ||||||
|  |  *  | ||||||
|  |  * @param client		Client to reply to | ||||||
|  |  * @param message		Message (formatting rules) | ||||||
|  |  * @noreturn | ||||||
|  |  */ | ||||||
|  | stock CReplyToCommand(client, const String:message[], any:...) { | ||||||
|  | 	decl String:buffer[MAX_BUFFER_LENGTH]; | ||||||
|  | 	SetGlobalTransTarget(client); | ||||||
|  | 	VFormat(buffer, sizeof(buffer), message, 3); | ||||||
|  | 	if(GetCmdReplySource() == SM_REPLY_TO_CONSOLE) { | ||||||
|  | 		CRemoveTags(buffer, sizeof(buffer)); | ||||||
|  | 		PrintToConsole(client, "%s", buffer); | ||||||
|  | 	} else { | ||||||
|  | 		CPrintToChat(client, "%s", buffer); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Replies to a command with colors | ||||||
|  |  *  | ||||||
|  |  * @param client		Client to reply to | ||||||
|  |  * @param author		Client to use for {teamcolor} | ||||||
|  |  * @param message		Message (formatting rules) | ||||||
|  |  * @noreturn | ||||||
|  |  */ | ||||||
|  | stock CReplyToCommandEx(client, author, const String:message[], any:...) { | ||||||
|  | 	decl String:buffer[MAX_BUFFER_LENGTH]; | ||||||
|  | 	SetGlobalTransTarget(client); | ||||||
|  | 	VFormat(buffer, sizeof(buffer), message, 4); | ||||||
|  | 	if(GetCmdReplySource() == SM_REPLY_TO_CONSOLE) { | ||||||
|  | 		CRemoveTags(buffer, sizeof(buffer)); | ||||||
|  | 		PrintToConsole(client, "%s", buffer); | ||||||
|  | 	} else { | ||||||
|  | 		CPrintToChatEx(client, author, "%s", buffer); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Shows admin activity with colors | ||||||
|  |  *  | ||||||
|  |  * @param client		Client performing an action | ||||||
|  |  * @param message		Message (formatting rules) | ||||||
|  |  * @noreturn | ||||||
|  |  */ | ||||||
|  | stock CShowActivity(client, const String:message[], any:...) { | ||||||
|  | 	CCheckTrie(); | ||||||
|  | 	if(client < 0 || client > MaxClients) { | ||||||
|  | 		ThrowError("Invalid client index %d", client); | ||||||
|  | 	} | ||||||
|  | 	if(client != 0 && !IsClientInGame(client)) { | ||||||
|  | 		ThrowError("Client %d is not in game", client); | ||||||
|  | 	} | ||||||
|  | 	decl String:buffer[MAX_BUFFER_LENGTH], String:buffer2[MAX_BUFFER_LENGTH]; | ||||||
|  | 	Format(buffer, sizeof(buffer), "\x01%s", message); | ||||||
|  | 	VFormat(buffer2, sizeof(buffer2), buffer, 3); | ||||||
|  | 	CReplaceColorCodes(buffer2); | ||||||
|  | 	ShowActivity(client, "%s", buffer2); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Shows admin activity with colors | ||||||
|  |  *  | ||||||
|  |  * @param client		Client performing an action | ||||||
|  |  * @param tag			Tag to prepend to the message (color tags supported) | ||||||
|  |  * @param message		Message (formatting rules) | ||||||
|  |  * @noreturn | ||||||
|  |  */ | ||||||
|  | stock CShowActivityEx(client, const String:tag[], const String:message[], any:...) { | ||||||
|  | 	CCheckTrie(); | ||||||
|  | 	if(client < 0 || client > MaxClients) { | ||||||
|  | 		ThrowError("Invalid client index %d", client); | ||||||
|  | 	} | ||||||
|  | 	if(client != 0 && !IsClientInGame(client)) { | ||||||
|  | 		ThrowError("Client %d is not in game", client); | ||||||
|  | 	} | ||||||
|  | 	decl String:buffer[MAX_BUFFER_LENGTH], String:buffer2[MAX_BUFFER_LENGTH]; | ||||||
|  | 	Format(buffer, sizeof(buffer), "\x01%s", message); | ||||||
|  | 	VFormat(buffer2, sizeof(buffer2), buffer, 4); | ||||||
|  | 	CReplaceColorCodes(buffer2); | ||||||
|  | 	strcopy(buffer, sizeof(buffer), tag); | ||||||
|  | 	CReplaceColorCodes(buffer); | ||||||
|  | 	ShowActivityEx(client, tag, "%s", buffer2); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Shows admin activity with colors | ||||||
|  |  *  | ||||||
|  |  * @param client		Client performing an action | ||||||
|  |  * @param tag			Tag to prepend to the message (color tags supported) | ||||||
|  |  * @param message		Message (formatting rules) | ||||||
|  |  * @noreturn | ||||||
|  |  */ | ||||||
|  | stock CShowActivity2(client, const String:tag[], const String:message[], any:...) { | ||||||
|  | 	CCheckTrie(); | ||||||
|  | 	if(client < 0 || client > MaxClients) { | ||||||
|  | 		ThrowError("Invalid client index %d", client); | ||||||
|  | 	} | ||||||
|  | 	if(client != 0 && !IsClientInGame(client)) { | ||||||
|  | 		ThrowError("Client %d is not in game", client); | ||||||
|  | 	} | ||||||
|  | 	decl String:buffer[MAX_BUFFER_LENGTH], String:buffer2[MAX_BUFFER_LENGTH]; | ||||||
|  | 	Format(buffer, sizeof(buffer), "\x01%s", message); | ||||||
|  | 	VFormat(buffer2, sizeof(buffer2), buffer, 4); | ||||||
|  | 	CReplaceColorCodes(buffer2); | ||||||
|  | 	strcopy(buffer, sizeof(buffer), tag); | ||||||
|  | 	CReplaceColorCodes(buffer); | ||||||
|  | 	ShowActivity2(client, buffer, "%s", buffer2); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Determines whether a color name exists | ||||||
|  |  *  | ||||||
|  |  * @param color			The color name to check | ||||||
|  |  * @return				True if the color exists, false otherwise | ||||||
|  |  */ | ||||||
|  | stock bool:CColorExists(const String:color[]) { | ||||||
|  | 	CCheckTrie(); | ||||||
|  | 	new temp; | ||||||
|  | 	return GetTrieValue(CTrie, color, temp); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Returns the hexadecimal representation of a client's team color (will NOT initialize the trie) | ||||||
|  |  * | ||||||
|  |  * @param client		Client to get the team color for | ||||||
|  |  * @return				Client's team color in hexadecimal, or green if unknown | ||||||
|  |  * On error/Errors:		If the client index passed is invalid or not in game. | ||||||
|  |  */ | ||||||
|  | stock CGetTeamColor(client) { | ||||||
|  | 	if(client <= 0 || client > MaxClients) { | ||||||
|  | 		ThrowError("Invalid client index %i", client); | ||||||
|  | 	} | ||||||
|  | 	if(!IsClientInGame(client)) { | ||||||
|  | 		ThrowError("Client %i is not in game", client); | ||||||
|  | 	} | ||||||
|  | 	new value; | ||||||
|  | 	switch(GetClientTeam(client)) { | ||||||
|  | 		case 1: { | ||||||
|  | 			value = COLOR_GRAY; | ||||||
|  | 		} | ||||||
|  | 		case 2: { | ||||||
|  | 			value = COLOR_RED; | ||||||
|  | 		} | ||||||
|  | 		case 3: { | ||||||
|  | 			value = COLOR_BLUE; | ||||||
|  | 		} | ||||||
|  | 		default: { | ||||||
|  | 			value = COLOR_GREEN; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return value; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | stock Handle:InitColorTrie() { | ||||||
|  | 	new Handle:hTrie = CreateTrie(); | ||||||
|  | 	SetTrieValue(hTrie, "aliceblue", 0xF0F8FF); | ||||||
|  | 	SetTrieValue(hTrie, "allies", 0x4D7942); // same as Allies team in DoD:S
 | ||||||
|  | 	SetTrieValue(hTrie, "ancient", 0xEB4B4B); // same as Ancient item rarity in Dota 2
 | ||||||
|  | 	SetTrieValue(hTrie, "antiquewhite", 0xFAEBD7); | ||||||
|  | 	SetTrieValue(hTrie, "aqua", 0x00FFFF); | ||||||
|  | 	SetTrieValue(hTrie, "aquamarine", 0x7FFFD4); | ||||||
|  | 	SetTrieValue(hTrie, "arcana", 0xADE55C); // same as Arcana item rarity in Dota 2
 | ||||||
|  | 	SetTrieValue(hTrie, "axis", 0xFF4040); // same as Axis team in DoD:S
 | ||||||
|  | 	SetTrieValue(hTrie, "azure", 0x007FFF); | ||||||
|  | 	SetTrieValue(hTrie, "beige", 0xF5F5DC); | ||||||
|  | 	SetTrieValue(hTrie, "bisque", 0xFFE4C4); | ||||||
|  | 	SetTrieValue(hTrie, "black", 0x000000); | ||||||
|  | 	SetTrieValue(hTrie, "blanchedalmond", 0xFFEBCD); | ||||||
|  | 	SetTrieValue(hTrie, "blue", 0x99CCFF); // same as BLU/Counter-Terrorist team color
 | ||||||
|  | 	SetTrieValue(hTrie, "blueviolet", 0x8A2BE2); | ||||||
|  | 	SetTrieValue(hTrie, "brown", 0xA52A2A); | ||||||
|  | 	SetTrieValue(hTrie, "burlywood", 0xDEB887); | ||||||
|  | 	SetTrieValue(hTrie, "cadetblue", 0x5F9EA0); | ||||||
|  | 	SetTrieValue(hTrie, "chartreuse", 0x7FFF00); | ||||||
|  | 	SetTrieValue(hTrie, "chocolate", 0xD2691E); | ||||||
|  | 	SetTrieValue(hTrie, "collectors", 0xAA0000); // same as Collector's item quality in TF2
 | ||||||
|  | 	SetTrieValue(hTrie, "common", 0xB0C3D9); // same as Common item rarity in Dota 2
 | ||||||
|  | 	SetTrieValue(hTrie, "community", 0x70B04A); // same as Community item quality in TF2
 | ||||||
|  | 	SetTrieValue(hTrie, "coral", 0xFF7F50); | ||||||
|  | 	SetTrieValue(hTrie, "cornflowerblue", 0x6495ED); | ||||||
|  | 	SetTrieValue(hTrie, "cornsilk", 0xFFF8DC); | ||||||
|  | 	SetTrieValue(hTrie, "corrupted", 0xA32C2E); // same as Corrupted item quality in Dota 2
 | ||||||
|  | 	SetTrieValue(hTrie, "crimson", 0xDC143C); | ||||||
|  | 	SetTrieValue(hTrie, "cyan", 0x00FFFF); | ||||||
|  | 	SetTrieValue(hTrie, "darkblue", 0x00008B); | ||||||
|  | 	SetTrieValue(hTrie, "darkcyan", 0x008B8B); | ||||||
|  | 	SetTrieValue(hTrie, "darkgoldenrod", 0xB8860B); | ||||||
|  | 	SetTrieValue(hTrie, "darkgray", 0xA9A9A9); | ||||||
|  | 	SetTrieValue(hTrie, "darkgrey", 0xA9A9A9); | ||||||
|  | 	SetTrieValue(hTrie, "darkgreen", 0x006400); | ||||||
|  | 	SetTrieValue(hTrie, "darkkhaki", 0xBDB76B); | ||||||
|  | 	SetTrieValue(hTrie, "darkmagenta", 0x8B008B); | ||||||
|  | 	SetTrieValue(hTrie, "darkolivegreen", 0x556B2F); | ||||||
|  | 	SetTrieValue(hTrie, "darkorange", 0xFF8C00); | ||||||
|  | 	SetTrieValue(hTrie, "darkorchid", 0x9932CC); | ||||||
|  | 	SetTrieValue(hTrie, "darkred", 0x8B0000); | ||||||
|  | 	SetTrieValue(hTrie, "darksalmon", 0xE9967A); | ||||||
|  | 	SetTrieValue(hTrie, "darkseagreen", 0x8FBC8F); | ||||||
|  | 	SetTrieValue(hTrie, "darkslateblue", 0x483D8B); | ||||||
|  | 	SetTrieValue(hTrie, "darkslategray", 0x2F4F4F); | ||||||
|  | 	SetTrieValue(hTrie, "darkslategrey", 0x2F4F4F); | ||||||
|  | 	SetTrieValue(hTrie, "darkturquoise", 0x00CED1); | ||||||
|  | 	SetTrieValue(hTrie, "darkviolet", 0x9400D3); | ||||||
|  | 	SetTrieValue(hTrie, "deeppink", 0xFF1493); | ||||||
|  | 	SetTrieValue(hTrie, "deepskyblue", 0x00BFFF); | ||||||
|  | 	SetTrieValue(hTrie, "dimgray", 0x696969); | ||||||
|  | 	SetTrieValue(hTrie, "dimgrey", 0x696969); | ||||||
|  | 	SetTrieValue(hTrie, "dodgerblue", 0x1E90FF); | ||||||
|  | 	SetTrieValue(hTrie, "exalted", 0xCCCCCD); // same as Exalted item quality in Dota 2
 | ||||||
|  | 	SetTrieValue(hTrie, "firebrick", 0xB22222); | ||||||
|  | 	SetTrieValue(hTrie, "floralwhite", 0xFFFAF0); | ||||||
|  | 	SetTrieValue(hTrie, "forestgreen", 0x228B22); | ||||||
|  | 	SetTrieValue(hTrie, "frozen", 0x4983B3); // same as Frozen item quality in Dota 2
 | ||||||
|  | 	SetTrieValue(hTrie, "fuchsia", 0xFF00FF); | ||||||
|  | 	SetTrieValue(hTrie, "fullblue", 0x0000FF); | ||||||
|  | 	SetTrieValue(hTrie, "fullred", 0xFF0000); | ||||||
|  | 	SetTrieValue(hTrie, "gainsboro", 0xDCDCDC); | ||||||
|  | 	SetTrieValue(hTrie, "genuine", 0x4D7455); // same as Genuine item quality in TF2
 | ||||||
|  | 	SetTrieValue(hTrie, "ghostwhite", 0xF8F8FF); | ||||||
|  | 	SetTrieValue(hTrie, "gold", 0xFFD700); | ||||||
|  | 	SetTrieValue(hTrie, "goldenrod", 0xDAA520); | ||||||
|  | 	SetTrieValue(hTrie, "gray", 0xCCCCCC); // same as spectator team color
 | ||||||
|  | 	SetTrieValue(hTrie, "grey", 0xCCCCCC); | ||||||
|  | 	SetTrieValue(hTrie, "green", 0x3EFF3E); | ||||||
|  | 	SetTrieValue(hTrie, "greenyellow", 0xADFF2F); | ||||||
|  | 	SetTrieValue(hTrie, "haunted", 0x38F3AB); // same as Haunted item quality in TF2
 | ||||||
|  | 	SetTrieValue(hTrie, "honeydew", 0xF0FFF0); | ||||||
|  | 	SetTrieValue(hTrie, "hotpink", 0xFF69B4); | ||||||
|  | 	SetTrieValue(hTrie, "immortal", 0xE4AE33); // same as Immortal item rarity in Dota 2
 | ||||||
|  | 	SetTrieValue(hTrie, "indianred", 0xCD5C5C); | ||||||
|  | 	SetTrieValue(hTrie, "indigo", 0x4B0082); | ||||||
|  | 	SetTrieValue(hTrie, "ivory", 0xFFFFF0); | ||||||
|  | 	SetTrieValue(hTrie, "khaki", 0xF0E68C); | ||||||
|  | 	SetTrieValue(hTrie, "lavender", 0xE6E6FA); | ||||||
|  | 	SetTrieValue(hTrie, "lavenderblush", 0xFFF0F5); | ||||||
|  | 	SetTrieValue(hTrie, "lawngreen", 0x7CFC00); | ||||||
|  | 	SetTrieValue(hTrie, "legendary", 0xD32CE6); // same as Legendary item rarity in Dota 2
 | ||||||
|  | 	SetTrieValue(hTrie, "lemonchiffon", 0xFFFACD); | ||||||
|  | 	SetTrieValue(hTrie, "lightblue", 0xADD8E6); | ||||||
|  | 	SetTrieValue(hTrie, "lightcoral", 0xF08080); | ||||||
|  | 	SetTrieValue(hTrie, "lightcyan", 0xE0FFFF); | ||||||
|  | 	SetTrieValue(hTrie, "lightgoldenrodyellow", 0xFAFAD2); | ||||||
|  | 	SetTrieValue(hTrie, "lightgray", 0xD3D3D3); | ||||||
|  | 	SetTrieValue(hTrie, "lightgrey", 0xD3D3D3); | ||||||
|  | 	SetTrieValue(hTrie, "lightgreen", 0x99FF99); | ||||||
|  | 	SetTrieValue(hTrie, "lightpink", 0xFFB6C1); | ||||||
|  | 	SetTrieValue(hTrie, "lightsalmon", 0xFFA07A); | ||||||
|  | 	SetTrieValue(hTrie, "lightseagreen", 0x20B2AA); | ||||||
|  | 	SetTrieValue(hTrie, "lightskyblue", 0x87CEFA); | ||||||
|  | 	SetTrieValue(hTrie, "lightslategray", 0x778899); | ||||||
|  | 	SetTrieValue(hTrie, "lightslategrey", 0x778899); | ||||||
|  | 	SetTrieValue(hTrie, "lightsteelblue", 0xB0C4DE); | ||||||
|  | 	SetTrieValue(hTrie, "lightyellow", 0xFFFFE0); | ||||||
|  | 	SetTrieValue(hTrie, "lime", 0x00FF00); | ||||||
|  | 	SetTrieValue(hTrie, "limegreen", 0x32CD32); | ||||||
|  | 	SetTrieValue(hTrie, "linen", 0xFAF0E6); | ||||||
|  | 	SetTrieValue(hTrie, "magenta", 0xFF00FF); | ||||||
|  | 	SetTrieValue(hTrie, "maroon", 0x800000); | ||||||
|  | 	SetTrieValue(hTrie, "mediumaquamarine", 0x66CDAA); | ||||||
|  | 	SetTrieValue(hTrie, "mediumblue", 0x0000CD); | ||||||
|  | 	SetTrieValue(hTrie, "mediumorchid", 0xBA55D3); | ||||||
|  | 	SetTrieValue(hTrie, "mediumpurple", 0x9370D8); | ||||||
|  | 	SetTrieValue(hTrie, "mediumseagreen", 0x3CB371); | ||||||
|  | 	SetTrieValue(hTrie, "mediumslateblue", 0x7B68EE); | ||||||
|  | 	SetTrieValue(hTrie, "mediumspringgreen", 0x00FA9A); | ||||||
|  | 	SetTrieValue(hTrie, "mediumturquoise", 0x48D1CC); | ||||||
|  | 	SetTrieValue(hTrie, "mediumvioletred", 0xC71585); | ||||||
|  | 	SetTrieValue(hTrie, "midnightblue", 0x191970); | ||||||
|  | 	SetTrieValue(hTrie, "mintcream", 0xF5FFFA); | ||||||
|  | 	SetTrieValue(hTrie, "mistyrose", 0xFFE4E1); | ||||||
|  | 	SetTrieValue(hTrie, "moccasin", 0xFFE4B5); | ||||||
|  | 	SetTrieValue(hTrie, "mythical", 0x8847FF); // same as Mythical item rarity in Dota 2
 | ||||||
|  | 	SetTrieValue(hTrie, "navajowhite", 0xFFDEAD); | ||||||
|  | 	SetTrieValue(hTrie, "navy", 0x000080); | ||||||
|  | 	SetTrieValue(hTrie, "normal", 0xB2B2B2); // same as Normal item quality in TF2
 | ||||||
|  | 	SetTrieValue(hTrie, "oldlace", 0xFDF5E6); | ||||||
|  | 	SetTrieValue(hTrie, "olive", 0x9EC34F); | ||||||
|  | 	SetTrieValue(hTrie, "olivedrab", 0x6B8E23); | ||||||
|  | 	SetTrieValue(hTrie, "orange", 0xFFA500); | ||||||
|  | 	SetTrieValue(hTrie, "orangered", 0xFF4500); | ||||||
|  | 	SetTrieValue(hTrie, "orchid", 0xDA70D6); | ||||||
|  | 	SetTrieValue(hTrie, "palegoldenrod", 0xEEE8AA); | ||||||
|  | 	SetTrieValue(hTrie, "palegreen", 0x98FB98); | ||||||
|  | 	SetTrieValue(hTrie, "paleturquoise", 0xAFEEEE); | ||||||
|  | 	SetTrieValue(hTrie, "palevioletred", 0xD87093); | ||||||
|  | 	SetTrieValue(hTrie, "papayawhip", 0xFFEFD5); | ||||||
|  | 	SetTrieValue(hTrie, "peachpuff", 0xFFDAB9); | ||||||
|  | 	SetTrieValue(hTrie, "peru", 0xCD853F); | ||||||
|  | 	SetTrieValue(hTrie, "pink", 0xFFC0CB); | ||||||
|  | 	SetTrieValue(hTrie, "plum", 0xDDA0DD); | ||||||
|  | 	SetTrieValue(hTrie, "powderblue", 0xB0E0E6); | ||||||
|  | 	SetTrieValue(hTrie, "purple", 0x800080); | ||||||
|  | 	SetTrieValue(hTrie, "rare", 0x4B69FF); // same as Rare item rarity in Dota 2
 | ||||||
|  | 	SetTrieValue(hTrie, "red", 0xFF4040); // same as RED/Terrorist team color
 | ||||||
|  | 	SetTrieValue(hTrie, "rosybrown", 0xBC8F8F); | ||||||
|  | 	SetTrieValue(hTrie, "royalblue", 0x4169E1); | ||||||
|  | 	SetTrieValue(hTrie, "saddlebrown", 0x8B4513); | ||||||
|  | 	SetTrieValue(hTrie, "salmon", 0xFA8072); | ||||||
|  | 	SetTrieValue(hTrie, "sandybrown", 0xF4A460); | ||||||
|  | 	SetTrieValue(hTrie, "seagreen", 0x2E8B57); | ||||||
|  | 	SetTrieValue(hTrie, "seashell", 0xFFF5EE); | ||||||
|  | 	SetTrieValue(hTrie, "selfmade", 0x70B04A); // same as Self-Made item quality in TF2
 | ||||||
|  | 	SetTrieValue(hTrie, "sienna", 0xA0522D); | ||||||
|  | 	SetTrieValue(hTrie, "silver", 0xC0C0C0); | ||||||
|  | 	SetTrieValue(hTrie, "skyblue", 0x87CEEB); | ||||||
|  | 	SetTrieValue(hTrie, "slateblue", 0x6A5ACD); | ||||||
|  | 	SetTrieValue(hTrie, "slategray", 0x708090); | ||||||
|  | 	SetTrieValue(hTrie, "slategrey", 0x708090); | ||||||
|  | 	SetTrieValue(hTrie, "snow", 0xFFFAFA); | ||||||
|  | 	SetTrieValue(hTrie, "springgreen", 0x00FF7F); | ||||||
|  | 	SetTrieValue(hTrie, "steelblue", 0x4682B4); | ||||||
|  | 	SetTrieValue(hTrie, "strange", 0xCF6A32); // same as Strange item quality in TF2
 | ||||||
|  | 	SetTrieValue(hTrie, "tan", 0xD2B48C); | ||||||
|  | 	SetTrieValue(hTrie, "teal", 0x008080); | ||||||
|  | 	SetTrieValue(hTrie, "thistle", 0xD8BFD8); | ||||||
|  | 	SetTrieValue(hTrie, "tomato", 0xFF6347); | ||||||
|  | 	SetTrieValue(hTrie, "turquoise", 0x40E0D0); | ||||||
|  | 	SetTrieValue(hTrie, "uncommon", 0xB0C3D9); // same as Uncommon item rarity in Dota 2
 | ||||||
|  | 	SetTrieValue(hTrie, "unique", 0xFFD700); // same as Unique item quality in TF2
 | ||||||
|  | 	SetTrieValue(hTrie, "unusual", 0x8650AC); // same as Unusual item quality in TF2
 | ||||||
|  | 	SetTrieValue(hTrie, "valve", 0xA50F79); // same as Valve item quality in TF2
 | ||||||
|  | 	SetTrieValue(hTrie, "vintage", 0x476291); // same as Vintage item quality in TF2
 | ||||||
|  | 	SetTrieValue(hTrie, "violet", 0xEE82EE); | ||||||
|  | 	SetTrieValue(hTrie, "wheat", 0xF5DEB3); | ||||||
|  | 	SetTrieValue(hTrie, "white", 0xFFFFFF); | ||||||
|  | 	SetTrieValue(hTrie, "whitesmoke", 0xF5F5F5); | ||||||
|  | 	SetTrieValue(hTrie, "yellow", 0xFFFF00); | ||||||
|  | 	SetTrieValue(hTrie, "yellowgreen", 0x9ACD32); | ||||||
|  | 	return hTrie; | ||||||
|  | } | ||||||
							
								
								
									
										915
									
								
								includes/nativevotes.inc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										915
									
								
								includes/nativevotes.inc
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,915 @@ | |||||||
|  | /** | ||||||
|  |  * vim: set ts=4 : | ||||||
|  |  * ============================================================================= | ||||||
|  |  * NativeVotes | ||||||
|  |  * Copyright (C) 2011-2013 Ross Bemrose (Powerlord).  All rights reserved. | ||||||
|  |  * ============================================================================= | ||||||
|  |  * | ||||||
|  |  * This program is free software; you can redistribute it and/or modify it under | ||||||
|  |  * the terms of the GNU General Public License, version 3.0, as published by the | ||||||
|  |  * Free Software Foundation. | ||||||
|  |  *  | ||||||
|  |  * This program is distributed in the hope that it will be useful, but WITHOUT | ||||||
|  |  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||||||
|  |  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more | ||||||
|  |  * details. | ||||||
|  |  * | ||||||
|  |  * You should have received a copy of the GNU General Public License along with | ||||||
|  |  * this program.  If not, see <http://www.gnu.org/licenses/>. | ||||||
|  |  * | ||||||
|  |  * As a special exception, AlliedModders LLC gives you permission to link the | ||||||
|  |  * code of this program (as well as its derivative works) to "Half-Life 2," the | ||||||
|  |  * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software | ||||||
|  |  * by the Valve Corporation.  You must obey the GNU General Public License in | ||||||
|  |  * all respects for all other code used.  Additionally, AlliedModders LLC grants | ||||||
|  |  * this exception to all derivative works.  AlliedModders LLC defines further | ||||||
|  |  * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), | ||||||
|  |  * or <http://www.sourcemod.net/license.php>. | ||||||
|  |  * | ||||||
|  |  * Version: $Id$ | ||||||
|  |  */ | ||||||
|  |   | ||||||
|  | #include <menus>
 | ||||||
|  | #include <sourcemod>
 | ||||||
|  | 
 | ||||||
|  | // NativeVotes 0.8 series
 | ||||||
|  | 
 | ||||||
|  | #if defined _nativevotes_included
 | ||||||
|  |  #endinput
 | ||||||
|  | #endif
 | ||||||
|  | #define _nativevotes_included
 | ||||||
|  | 
 | ||||||
|  | #define CLIENT_DISCONNECTED			-1
 | ||||||
|  | 
 | ||||||
|  | #define NATIVEVOTES_EXTEND 			"Extend current Map" /** Defined in TF2, but doesn't appear to be localized */
 | ||||||
|  | 
 | ||||||
|  | #define NATIVEVOTES_ALL_TEAMS		-1 // Defined by TF2, may be the same in L4D/L4D2
 | ||||||
|  | #define NATIVEVOTES_TF2_ALL_TEAMS	0 // Defined by TF2, may be the same in L4D/L4D2
 | ||||||
|  | #define NATIVEVOTES_TEAM_UNASSIGNED 0 // For completeness, do not otherwise use
 | ||||||
|  | #define NATIVEVOTES_TEAM_SPECTATOR	1 // Spectators
 | ||||||
|  | #define NATIVEVOTES_TEAM_1			2 // RED/Survivors/Terrorists
 | ||||||
|  | #define NATIVEVOTES_TEAM_2			3 // BLU/Infected/Counter-Terrorists
 | ||||||
|  | 
 | ||||||
|  | #define NATIVEVOTES_SERVER_INDEX 	99 // Defined by TF2, may be the same in L4D/L4D2
 | ||||||
|  | 
 | ||||||
|  | // These may seem backwards, but this is the order that the votes appear in the vote screen
 | ||||||
|  | #define NATIVEVOTES_VOTE_INVALID	-1		/**< Vote was invalid, currently only valid internally */
 | ||||||
|  | #define NATIVEVOTES_VOTE_YES		0		/**< Vote was yes */
 | ||||||
|  | #define NATIVEVOTES_VOTE_NO			1		/**< Vote was no */
 | ||||||
|  | 
 | ||||||
|  | /* | ||||||
|  | The following MenuActions are supported.  Arguments are also listed, as they differ slightly from the default | ||||||
|  | MenuAction_Start		A menu has been started (nothing passed). Only exists for compat reasons. | ||||||
|  | MenuAction_Display		A menu is about to be displayed (param1=client). If you choose to change the vote text, | ||||||
|  |  						To change the text, use RedrawVoteTitle() | ||||||
|  | 						If you do so, return 1 or _:Plugin_Changed  Otherwise, return _:Plugin_Continue or 0. | ||||||
|  | MenuAction_Select		An item was selected (param1=client, param2=item). For subplugin support. | ||||||
|  | MenuAction_End			A vote has fully ended and the vote object is ready to be cleaned up | ||||||
|  | 						param1 is MenuEnd reason, either MenuEnd_VotingCancelled or MenuEnd_VotingDone | ||||||
|  | MenuAction_VoteEnd		A vote sequence has succeeded (param1=chosen item)  | ||||||
|  | 						This is not called if NativeVotes_SetResultCallback has been used on the vote. | ||||||
|  | 						You should call NativeVotes_DisplayPass or NativeVotes_DisplayPassEx after this | ||||||
|  | MenuAction_VoteStart	A vote sequence has started (nothing passed).  Use this instead of MenuAction_Start | ||||||
|  | MenuAction_VoteCancel	A vote sequence has been cancelled (param1=reason) | ||||||
|  | MenuAction_DisplayItem	Item text is being drawn to the display (param1=client, param2=item) | ||||||
|  | 						To change the text, use RedrawVoteItem(). | ||||||
|  | 						If you do so, return 1 or _:Plugin_Changed.  Otherwise, return _:Plugin_Continue or 0. | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | #define NATIVEVOTES_ACTIONS_DEFAULT		MenuAction_VoteStart|MenuAction_VoteCancel|MenuAction_VoteEnd|MenuAction_End
 | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Vote types. These are mapped to translation strings and pass strings by VoteStart and VotePass handlers | ||||||
|  |  */ | ||||||
|  | enum NativeVotesType | ||||||
|  | { | ||||||
|  | 	NativeVotesType_None = 0,		/** Special placeholder for callvote with no arguments for NativeVotes_OnCallVote */ | ||||||
|  | 	NativeVotesType_Custom_YesNo,	/**< Yes/No, details are vote text. */ | ||||||
|  | 	NativeVotesType_Custom_Mult,	/**< TF2/CS:GO: Multiple-choice, details are vote text. */ | ||||||
|  | 	NativeVotesType_ChgCampaign,	/**< L4D/L4D2: Yes/No, details are campaign name */ | ||||||
|  | 	NativeVotesType_ChgDifficulty,	/**< L4D/L4D2: Yes/No, details are difficulty number in L4D/L4D2 */ | ||||||
|  | 	NativeVotesType_ReturnToLobby,	/**< L4D/L4D2: Yes/No, details are ignored */ | ||||||
|  | 	NativeVotesType_AlltalkOn,		/**< L4D2: Yes/No, details are ignored (handled internally by extension) */ | ||||||
|  | 	NativeVotesType_AlltalkOff,		/**< L4D2: Yes/No, details are ignored (handled internally by extension) */ | ||||||
|  | 	NativeVotesType_Restart,		/**< Yes/No, details are ignored */ | ||||||
|  | 	NativeVotesType_Kick,			/**< Yes/No, target is player userid, details are auto-set by target */ | ||||||
|  | 	NativeVotesType_KickIdle,		/**< TF2/CS:GO: Yes/No, target is player userid, details are auto-set by target */ | ||||||
|  | 	NativeVotesType_KickScamming,	/**< TF2/CS:GO: Yes/No, target is player userid, details are auto-set by target */ | ||||||
|  | 	NativeVotesType_KickCheating,	/**< TF2/CS:GO: Yes/No, target is player userid, details are auto-set by target */ | ||||||
|  | 	NativeVotesType_ChgLevel,		/**< Yes/No, details are level number in L4D/L4D2 or map name in TF2 */ | ||||||
|  | 	NativeVotesType_NextLevel,		/**< TF2/CS:GO: Yes/No, details are map name */ | ||||||
|  | 	NativeVotesType_NextLevelMult,	/**< TF2/CS:GO: Multiple-choice, details are ignored */ | ||||||
|  | 	NativeVotesType_ScrambleNow,	/**< TF2/CS:GO: Yes/No, details are ignored */ | ||||||
|  | 	NativeVotesType_ScrambleEnd,	/**< TF2: Yes/No, details are ignored */ | ||||||
|  | 	NativeVotesType_ChgMission,		/**< TF2: Yes/No, details are popfile */ | ||||||
|  | 	NativeVotesType_SwapTeams,		/**< CS:GO: Yes/No, details are ignored */ | ||||||
|  | 	NativeVotesType_Surrender,		/**< CS:GO: Yes/No, details are ignored */ | ||||||
|  | 	NativeVotesType_Rematch,		/**< CS:GO: Yes/No, details are ignored */ | ||||||
|  | 	NativeVotesType_Continue,		/**< CS:GO: Yes/No, details are ignored */ | ||||||
|  | 	NativeVotesType_StartRound,		/**< TF2: Yes/No, details are ignored */ | ||||||
|  | 	NativeVotesType_Eternaween,		/**< TF2: Yes/No, details are ignored */ | ||||||
|  | 	NativeVotesType_AutoBalanceOn,	/**< TF2: Yes/No, details are ignored */ | ||||||
|  | 	NativeVotesType_AutoBalanceOff,	/**< TF2: Yes/No, details are ignored */ | ||||||
|  | 	NativeVotesType_ClassLimitsOn,	/**< TF2: Yes/No, details are ignored */ | ||||||
|  | 	NativeVotesType_ClassLimitsOff,	/**< TF2: Yes/No, details are ignored */ | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | enum NativeVotesPassType | ||||||
|  | { | ||||||
|  | 	NativeVotesPass_None = 0,			/**< Special placeholder for error value */ | ||||||
|  | 	NativeVotesPass_Custom,				/**< Details are custom pass message */ | ||||||
|  | 	NativeVotesPass_ChgCampaign,		/**< L4D/L4D2: Details are campaign name */ | ||||||
|  | 	NativeVotesPass_ChgDifficulty,		/**< L4D/L4D2/TF2: Details are difficulty number in L4D/L4D2 and mission name in TF2 */ | ||||||
|  | 	NativeVotesPass_ReturnToLobby,      /**< L4D/L4D2: Details are ignored */ | ||||||
|  | 	NativeVotesPass_AlltalkOn,			/**< L4D2: Details are ignored */ | ||||||
|  | 	NativeVotesPass_AlltalkOff,			/**< L4D2: Details are ignored */ | ||||||
|  | 	NativeVotesPass_Restart,			/**< Details are ignored */ | ||||||
|  | 	NativeVotesPass_Kick,				/**< Details are player name */ | ||||||
|  | 	NativeVotesPass_ChgLevel,			/**< Details are level number in L4D/L4D2 or map name in TF2/CS:GO */ | ||||||
|  | 	NativeVotesPass_NextLevel,			/**< TF2/CS:GO: Details are map name */ | ||||||
|  | 	NativeVotesPass_Extend,				/**< TF2/CS:GO: Details are ignored */ | ||||||
|  | 	NativeVotesPass_Scramble,			/**< TF2/CS:GO: Details are ignored */ | ||||||
|  | 	NativeVotesPass_ChgMission,			/**< TF2: Details are popfile */ | ||||||
|  | 	NativeVotesPass_SwapTeams,			/**< CS:GO: Details are ignored */ | ||||||
|  | 	NativeVotesPass_Surrender,			/**< CS:GO: Details are ignored */ | ||||||
|  | 	NativeVotesPass_Rematch,			/**< CS:GO: Details are ignored */ | ||||||
|  | 	NativeVotesPass_Continue,			/**< CS:GO: Details are ignored */ | ||||||
|  | 	NativeVotesPass_StartRound,			/**< TF2: Details are ignored */ | ||||||
|  | 	NativeVotesPass_Eternaween,			/**< TF2: Details are ignored */ | ||||||
|  | 	NativeVotesPass_AutoBalanceOn,		/**< TF2: Yes/No, details are ignored */ | ||||||
|  | 	NativeVotesPass_AutoBalanceOff,		/**< TF2: Yes/No, details are ignored */ | ||||||
|  | 	NativeVotesPass_ClassLimitsOn,		/**< TF2: Yes/No, details are ignored */ | ||||||
|  | 	NativeVotesPass_ClassLimitsOff,		/**< TF2: Yes/No, details are ignored */ | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Reasons a vote was canceled.  Not used for L4D/L4D2, as they don't care | ||||||
|  |  */ | ||||||
|  | enum NativeVotesFailType | ||||||
|  | { | ||||||
|  | 	NativeVotesFail_Generic = 0,		/**< Vote was generically cancelled. */ | ||||||
|  | 	NativeVotesFail_Loses = 3,			/**< No votes outnumbered Yes votes */ | ||||||
|  | 	NativeVotesFail_NotEnoughVotes = 4,	/**< Vote did not receive enough votes. */ | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Reasons a callvote command failed. | ||||||
|  |  * This is provided as a convenience to plugin authors as it's not strictly part of the vote system | ||||||
|  |  */ | ||||||
|  | enum NativeVotesCallFailType | ||||||
|  | { | ||||||
|  | 	NativeVotesCallFail_Generic = 0,			/**< Generic fail. */ | ||||||
|  | 	NativeVotesCallFail_Loading = 1,			/**< L4D/L4D2: Players are still loading. */ | ||||||
|  | 	NativeVotesCallFail_Recent = 2,				/**< TF2/CS:GO: You can't call another vote yet: Argument is seconds until you can call another vote. */ | ||||||
|  | 	NativeVotesCallFail_Disabled = 5,			/**< TF2/CS:GO: Server has disabled that issue. */ | ||||||
|  | 	NativeVotesCallFail_MapNotFound = 6,		/**< TF2/CS:GO: Server does not have that map. */ | ||||||
|  | 	NativeVotesCallFail_SpecifyMap = 7,			/**< TF2/CS:GO: You must specify a map. */ | ||||||
|  | 	NativeVotesCallFail_Failed = 8,				/**< TF2/CS:GO: This vote failed recently. */ | ||||||
|  | 	NativeVotesCallFail_WrongTeam = 9,			/**< TF2/CS:GO: Team can't call this vote. */ | ||||||
|  | 	NativeVotesCallFail_Waiting = 10,			/**< TF2/CS:GO: Vote can't be called during Waiting For Players. */ | ||||||
|  | 	NativeVotesCallFail_PlayerNotFound = 11,	/**< TF2/CS:GO: Player to kick can't be found. Buggy in TF2. */ | ||||||
|  | 	NativeVotesCallFail_Unknown = 11, | ||||||
|  | 	NativeVotesCallFail_CantKickAdmin = 12,		/**< TF2/CS:GO: Can't kick server admin. */ | ||||||
|  | 	NativeVotesCallFail_ScramblePending = 13,	/**< TF2/CS:GO: Team Scramble is pending.. */ | ||||||
|  | 	NativeVotesCallFail_Spectators = 14,		/**< TF2/CS:GO: Spectators aren't allowed to call votes. */ | ||||||
|  | 	NativeVotesCallFail_LevelSet = 15,			/**< TF2/CS:GO: Next level already set. */ | ||||||
|  | 	NativeVotesCallFail_MapNotValid = 16,		/**< ???: Map is invalid. */ | ||||||
|  | 	NativeVotesCallFail_KickTime = 17,			/**< ???: Cannot kick for time. */ | ||||||
|  | 	NativeVotesCallFail_KickDuringRound = 18,	/**< ???: Cannot kick during a round. */ | ||||||
|  | 	NativeVotesCallFail_AlreadyActive = 19		/**< TF2: Cannot call vote because modification (Eternaween) is already active (may not work) */ | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /* | ||||||
|  |  * Is a specific vote type supported by this game? | ||||||
|  |  *  | ||||||
|  |  * @param voteType			Vote type | ||||||
|  |  */ | ||||||
|  | native bool:NativeVotes_IsVoteTypeSupported(NativeVotesType:voteType); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Creates a new, empty vote. | ||||||
|  |  *  | ||||||
|  |  * @param handler			Function which will receive vote actions. | ||||||
|  |  * @param voteType			Vote type, cannot be changed after set | ||||||
|  |  * @param actions			Optionally set which actions to receive.  Start,  | ||||||
|  |  *							Cancel, and End will always be received regardless | ||||||
|  |  *							of whether they are set or not.  They are also | ||||||
|  |  *							the only default actions. | ||||||
|  |  * @return					A new vote Handle on INVALID_HANDLE if a vote type is unsupported by this game. | ||||||
|  |  */ | ||||||
|  | native Handle:NativeVotes_Create(MenuHandler:handler, NativeVotesType:voteType, | ||||||
|  | 							MenuAction:actions=NATIVEVOTES_ACTIONS_DEFAULT); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Frees all handles related to a vote. | ||||||
|  |  *  | ||||||
|  |  * THIS MUST BE CALLED TO AVOID HANDLE LEAKS | ||||||
|  |  *  | ||||||
|  |  * @param vote				Vote handle | ||||||
|  |  * @noreturn | ||||||
|  |  */ | ||||||
|  | native Handle:NativeVotes_Close(Handle:vote); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Appends a new item to the end of a vote.  Only valid for Multiple Choice votes | ||||||
|  |  * | ||||||
|  |  * @param vote				NativeVotes Handle. | ||||||
|  |  * @param info				Item information string. | ||||||
|  |  * @return					True on success, false on failure. | ||||||
|  |  * @error					Invalid Handle, item limit reached, or if the vote is not multiple choice. | ||||||
|  |  */ | ||||||
|  | native bool:NativeVotes_AddItem(Handle:vote, const String:info[], const String:display[]); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Inserts an item into the menu before a certain position; the new item will | ||||||
|  |  * be at the given position and all next items pushed forward. | ||||||
|  |  * | ||||||
|  |  * @param vote				Vote Handle. | ||||||
|  |  * @param position			Position, starting from 0. | ||||||
|  |  * @param info				Item information string. | ||||||
|  |  * @return					True on success, false on failure. | ||||||
|  |  * @error					Invalid Handle or vote position, or if the vote is not multiple choice. | ||||||
|  |  */ | ||||||
|  | native bool:NativeVotes_InsertItem(Handle:vote, position, const String:info[], const String:display[]); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Removes an item from the menu. | ||||||
|  |  * | ||||||
|  |  * @param vote				Vote Handle. | ||||||
|  |  * @param position			Position, starting from 0. | ||||||
|  |  * @return					True on success, false on failure. | ||||||
|  |  * @error					Invalid Handle or vote position,  or if the vote is not multiple choice. | ||||||
|  |  */ | ||||||
|  | native bool:NativeVotes_RemoveItem(Handle:vote, position); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Removes all items from a vote. | ||||||
|  |  * | ||||||
|  |  * @param vote				Vote Handle. | ||||||
|  |  * @noreturn | ||||||
|  |  * @error					Invalid Handle or vote position, or if the vote is not multiple choice. | ||||||
|  |  */ | ||||||
|  | native NativeVotes_RemoveAllItems(Handle:vote); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Retrieves information about a vote item. | ||||||
|  |  * | ||||||
|  |  * @param vote				Vote Handle. | ||||||
|  |  * @param position			Position, starting from 0. | ||||||
|  |  * @param infoBuf			Info buffer. | ||||||
|  |  * @param infoBufLen		Maximum length of the info buffer. | ||||||
|  |  * @return					True on success, false if position is invalid. | ||||||
|  |  * @error					Invalid Handlem | ||||||
|  |  */ | ||||||
|  | native bool:NativeVotes_GetItem(Handle:vote,  | ||||||
|  | 						position,  | ||||||
|  | 						String:infoBuf[],  | ||||||
|  | 						infoBufLen, | ||||||
|  | 						String:dispBuf[]="", | ||||||
|  | 						dispBufLen=0); | ||||||
|  | 						 | ||||||
|  | /** | ||||||
|  |  * Returns the number of items in a vote. | ||||||
|  |  * | ||||||
|  |  * @param vote				Vote Handle. | ||||||
|  |  * @return					Number of items in the vote. | ||||||
|  |  * @error					Invalid Handle. | ||||||
|  |  */ | ||||||
|  | native NativeVotes_GetItemCount(Handle:vote); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Sets the vote's details for votes that support details | ||||||
|  |  * If this is a custom vote, use NativeVotes_SetTitle to set the vote's title. | ||||||
|  |  * | ||||||
|  |  * @param vote				Vote Handle. | ||||||
|  |  * @param argument			Details string. See vote types for what details stands for. | ||||||
|  |  * @noreturn | ||||||
|  |  * @error					Invalid Handle. | ||||||
|  |  */ | ||||||
|  | native NativeVotes_SetDetails(Handle:vote, const String:argument[]); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Returns the text of a vote's details if set. | ||||||
|  |  * | ||||||
|  |  * @param vote				Vote Handle. | ||||||
|  |  * @param buffer			Buffer to store details. | ||||||
|  |  * @param maxlength			Maximum length of the buffer. | ||||||
|  |  * @noreturn | ||||||
|  |  * @error					Invalid Handle. | ||||||
|  |  */ | ||||||
|  | native NativeVotes_GetDetails(Handle:vote, String:buffer[], maxlength); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Sets a custom vote's title | ||||||
|  |  * | ||||||
|  |  * @param vote				Vote Handle. | ||||||
|  |  * @param title			 	Vote title string. | ||||||
|  |  * @noreturn | ||||||
|  |  * @error					Invalid Handle. | ||||||
|  |  */ | ||||||
|  | native NativeVotes_SetTitle(Handle:vote, const String:argument[]); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Return the vote's Title. | ||||||
|  |  * If not set, returns Details instead. | ||||||
|  |  *     This behavior is for compatibility with NativeVotes 0.8.0 and below. | ||||||
|  |  * | ||||||
|  |  * @param vote				Vote Handle. | ||||||
|  |  * @param buffer			Buffer to store title. | ||||||
|  |  * @param maxlength			Maximum length of the buffer. | ||||||
|  |  * @noreturn | ||||||
|  |  * @error					Invalid Handle. | ||||||
|  |  */ | ||||||
|  | native NativeVotes_GetTitle(Handle:vote, String:buffer[], maxlength); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Sets the target userid for vote | ||||||
|  |  * This should be used instead of SetArgument for votes that target players | ||||||
|  |  *  | ||||||
|  |  * Also sets target SteamID | ||||||
|  |  *  | ||||||
|  |  * @param vote				Vote Handle. | ||||||
|  |  * @param userid			Client index of target player | ||||||
|  |  * @param setDetails		If true, also sets vote details to client's name | ||||||
|  |  * @noreturn | ||||||
|  |  * @error					Invalid Handle. | ||||||
|  |  */ | ||||||
|  | native NativeVotes_SetTarget(Handle:vote, client, bool:setDetails=true); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Returns the userid of a vote's target | ||||||
|  |  * | ||||||
|  |  * @param vote				Vote Handle. | ||||||
|  |  * @return					Client index of target player or 0 for no target or target disconnected since vote started | ||||||
|  |  * @error					Invalid Handle. | ||||||
|  |  */ | ||||||
|  | native NativeVotes_GetTarget(Handle:vote); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Get the Steam ID of a vote's target | ||||||
|  |  * Useful if the target has disconnect from the server during a vote. | ||||||
|  |  * This was added in specifically for Kick/Ban votes | ||||||
|  |  * | ||||||
|  |  * @param vote				Vote Handle. | ||||||
|  |  * @param buffer			Buffer to store steamId.  Should be 19 characters or more.. | ||||||
|  |  * @param maxlength			Maximum length of the buffer. | ||||||
|  |  * @noreturn | ||||||
|  |  * @error					Invalid Handle. | ||||||
|  |  */ | ||||||
|  | native NativeVotes_GetTargetSteam(Handle:vote, String:buffer[], maxlength); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Returns whether a vote is in progress. | ||||||
|  |  * | ||||||
|  |  * @return					True if a NativeVotes vote is in progress, false otherwise. | ||||||
|  |  */ | ||||||
|  | native bool:NativeVotes_IsVoteInProgress(); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Returns a style's maximum items | ||||||
|  |  *  | ||||||
|  |  * @return Maximum items | ||||||
|  |  */ | ||||||
|  | native NativeVotes_GetMaxItems(); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Sets a vote's option flags. | ||||||
|  |  * | ||||||
|  |  * If a certain bit is not supported, it will be stripped before being set. | ||||||
|  |  *  | ||||||
|  |  * NOTE: This is currently unused, but reserved for future use. | ||||||
|  |  * | ||||||
|  |  * @param menu				Builtin Vote Handle. | ||||||
|  |  * @param flags				A new bitstring of VOTEFLAG bits. | ||||||
|  |  * @noreturn | ||||||
|  |  * @error					Invalid Handle. | ||||||
|  |  */ | ||||||
|  | native NativeVotes_SetOptionFlags(Handle:vote, flags); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Retrieves a menu's option flags. | ||||||
|  |  * | ||||||
|  |  * NOTE: This is currently unused, but reserved for future use. | ||||||
|  |  * | ||||||
|  |  * @param vote				Builtin Vote Handle. | ||||||
|  |  * @return					A bitstring of VOTEFLAG bits. | ||||||
|  |  * @error					Invalid Handle. | ||||||
|  |  */ | ||||||
|  | native NativeVotes_GetOptionFlags(Handle:vote); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Cancels the vote in progress. | ||||||
|  |  * | ||||||
|  |  * @noreturn | ||||||
|  |  * @error					If no vote is in progress. | ||||||
|  |  */ | ||||||
|  | native NativeVotes_Cancel(); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Callback for when a vote has ended and results are available. | ||||||
|  |  *  | ||||||
|  |  * Due to SourceMod Forward limitations in plugins, multi-dimension arrays can't be passed | ||||||
|  |  * to forwards.  This means we have to split the client_info and item_info arrays into | ||||||
|  |  * their components. | ||||||
|  |  *  | ||||||
|  |  * @param vote				The vote being voted on. | ||||||
|  |  * @param num_votes			Number of votes tallied in total. | ||||||
|  |  * @param num_clients		Number of clients who could vote. | ||||||
|  |  * @param client_indexes	Array of client indexes. Parallel with client_votes. | ||||||
|  |  * @param client_votes		Array of client votes. Parallel with client_indexes. | ||||||
|  |  * @param num_items			Number of unique items that were selected. | ||||||
|  |  * @param item_indexes		Array of vote item indexes. Parallel with item_votes.. | ||||||
|  |  * @param item_votes		Array of vote vote counts. Parallel with item_indexes. | ||||||
|  |  * @noreturn | ||||||
|  |  */ | ||||||
|  | functag public NativeVotes_VoteHandler(Handle:vote, | ||||||
|  | 							num_votes,  | ||||||
|  | 							num_clients, | ||||||
|  | 							const client_indexes[], | ||||||
|  | 							const client_votes[], | ||||||
|  | 							num_items, | ||||||
|  | 							const item_indexes[], | ||||||
|  | 							const item_votes[]); | ||||||
|  | /** | ||||||
|  |  * Function to convert client/vote arrays into their two-dimensional versions, | ||||||
|  |  * which can then be passed to a standard vote handler. | ||||||
|  |  *  | ||||||
|  |  * client_info and item_info are the resulting arrays. | ||||||
|  |  *  | ||||||
|  |  * Note: When declaring client_info and item_info, you'll probably want to declare them like this: | ||||||
|  |  * new client_info[num_clients][2]; | ||||||
|  |  * new item_info[num_items][2]; | ||||||
|  |  *  | ||||||
|  |  * @param num_clients		Number of clients who could vote. | ||||||
|  |  * @param client_indexes	Array of client indexes. Parallel with client_votes. | ||||||
|  |  * @param client_votes		Array of client votes. Parallel with client_indexes. | ||||||
|  |  * @param num_items			Number of unique items that were selected. | ||||||
|  |  * @param item_indexes		Array of vote item indexes. Parallel with item_votes.. | ||||||
|  |  * @param item_votes		Array of vote vote counts. Parallel with item_indexes. | ||||||
|  |  * @param client_info		Array of clients.  Use VOTEINFO_CLIENT_ defines. | ||||||
|  |  * @param item_info			Array of items, sorted by count.  Use VOTEINFO_ITEM | ||||||
|  |  *							defines. | ||||||
|  |  * @noreturn | ||||||
|  |  */ | ||||||
|  | stock NativeVotes_FixResults(num_clients, | ||||||
|  | 							const client_indexes[], | ||||||
|  | 							const client_votes[], | ||||||
|  | 							num_items, | ||||||
|  | 							const item_indexes[], | ||||||
|  | 							const item_votes[], | ||||||
|  | 							client_info[][2],  | ||||||
|  | 							item_info[][2]) | ||||||
|  | { | ||||||
|  | 	for (new i = 0; i < num_clients; ++i) | ||||||
|  | 	{ | ||||||
|  | 		client_info[i][VOTEINFO_CLIENT_INDEX] = client_indexes[i]; | ||||||
|  | 		client_info[i][VOTEINFO_CLIENT_ITEM] = client_votes[i]; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	for (new i = 0; i < num_items; ++i) | ||||||
|  | 	{ | ||||||
|  | 		item_info[i][VOTEINFO_ITEM_INDEX] = item_indexes[i]; | ||||||
|  | 		item_info[i][VOTEINFO_ITEM_VOTES] = item_votes[i]; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Sets an advanced vote handling callback.  If this callback is set, | ||||||
|  |  * MenuAction_VoteEnd will not be called. | ||||||
|  |  * | ||||||
|  |  * @param vote				NativeVotes Handle. | ||||||
|  |  * @param callback			Callback function. | ||||||
|  |  * @noreturn | ||||||
|  |  * @error					Invalid Handle or callback. | ||||||
|  |  */ | ||||||
|  | native NativeVotes_SetResultCallback(Handle:vote, NativeVotes_VoteHandler:callback); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Returns the number of seconds you should "wait" before displaying | ||||||
|  |  * a public vote.  This number is the time remaining until | ||||||
|  |  * (last_vote + sm_vote_delay). | ||||||
|  |  * | ||||||
|  |  * @return					Number of seconds to wait, or 0 for none. | ||||||
|  |  */ | ||||||
|  | native NativeVotes_CheckVoteDelay(); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Returns whether a client is in the pool of clients allowed  | ||||||
|  |  * to participate in the current vote.  This is determined by  | ||||||
|  |  * the client list passed to NativeVotes_Display(). | ||||||
|  |  * | ||||||
|  |  * @param client			Client index. | ||||||
|  |  * @return					True if client is allowed to vote, false otherwise. | ||||||
|  |  * @error					If no vote is in progress or client index is invalid. | ||||||
|  |  */ | ||||||
|  | native bool:NativeVotes_IsClientInVotePool(client); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Redraws the current vote to a client in the voting pool. | ||||||
|  |  * | ||||||
|  |  * @param client			Client index. | ||||||
|  |  * @param revotes			True to allow revotes, false otherwise. | ||||||
|  |  * @return					True on success, false if the client is in the vote pool  | ||||||
|  |  *							but cannot vote again. | ||||||
|  |  * @error					No vote in progress, client is not in the voting pool,  | ||||||
|  |  *							or client index is invalid. | ||||||
|  |  */ | ||||||
|  | native bool:NativeVotes_RedrawClientVote(client, bool:revotes=true); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Retrieve the vote type | ||||||
|  |  *  | ||||||
|  |  * @param vote				NativeVotes Handle. | ||||||
|  |  * @return					The built in vote type | ||||||
|  |  * @error					Invalid Handle | ||||||
|  |  */ | ||||||
|  | native NativeVotesType:NativeVotes_GetType(Handle:vote); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Set the team this vote is for, or NATIVEVOTES_ALL_TEAMS for all teams. | ||||||
|  |  *  | ||||||
|  |  * Defaults to NATIVEVOTES_ALL_TEAMS if not explicitly set. | ||||||
|  |  *  | ||||||
|  |  * @param vote				NativeVotes Handle. | ||||||
|  |  * @param team				Team number this vote is for | ||||||
|  |  * @noreturn | ||||||
|  |  * @error					Invalid Handle | ||||||
|  |  */ | ||||||
|  | native NativeVotes_SetTeam(Handle:vote, team); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Retrieve the team this vote is for | ||||||
|  |  *  | ||||||
|  |  * @param vote				NativeVotes Handle. | ||||||
|  |  * @return					Team index or NATIVEVOTES_ALL_TEAMS for all teams. | ||||||
|  |  * @error					Invalid Handle | ||||||
|  |  */ | ||||||
|  | native NativeVotes_GetTeam(Handle:vote); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Set the client index of the player who initiated the vote. | ||||||
|  |  * Use NATIVEVOTES_SERVER_INDEX if initiated by the server itself. | ||||||
|  |  *  | ||||||
|  |  * Defaults to NATIVEVOTES_SERVER_INDEX if not explicitly set. | ||||||
|  |  *  | ||||||
|  |  * @param vote				NativeVotes Handle. | ||||||
|  |  * @param client			Client who initiated the vote or NATIVEVOTES_SERVER_INDEX | ||||||
|  |  * @noreturn | ||||||
|  |  * @error					Invalid Handle | ||||||
|  |  */ | ||||||
|  | native NativeVotes_SetInitiator(Handle:vote, client); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Retrieve the client index of the player who initiated the vote or NATIVEVOTES_SERVER_INDEX if  | ||||||
|  |  * initiated by the server itself. | ||||||
|  |  *  | ||||||
|  |  * @param					Vote handle | ||||||
|  |  * @return					Client index or NATIVEVOTES_SERVER_INDEX | ||||||
|  |  * @error					Invalid Handle | ||||||
|  |  */ | ||||||
|  | native NativeVotes_GetInitiator(Handle:vote); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Broadcasts a vote to a list of clients.  The most selected item will be  | ||||||
|  |  * returned through MenuAction_VoteEnd.  On a tie, a random item will be returned  | ||||||
|  |  * from a list of the tied items. | ||||||
|  |  * | ||||||
|  |  * Note that MenuAction_VoteStart, MenuAction_VoteCancel, MenuAction_VoteEnd, and MenuAction_End are all | ||||||
|  |  * default callbacks and do not need to be enabled. | ||||||
|  |  * | ||||||
|  |  * @param vote				Vote Handle. | ||||||
|  |  * @param clients			Array of clients to broadcast to. | ||||||
|  |  * @param numClients		Number of clients in the array. | ||||||
|  |  * @param time				Maximum time to leave menu on the screen. | ||||||
|  |  * @return					True on success, false if a vote is already in progress. | ||||||
|  |  * @error					Invalid Handle, or a vote is already in progress. | ||||||
|  |  */ | ||||||
|  | native bool:NativeVotes_Display(Handle:vote, clients[], numClients, time); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Sends a vote menu to all clients.  See NativeVotes_Display() for more information. | ||||||
|  |  * | ||||||
|  |  * @param vote				Vote Handle. | ||||||
|  |  * @param time				Maximum time to leave menu on the screen. | ||||||
|  |  * @return					True on success, false if this menu already has a vote session | ||||||
|  |  *							in progress. | ||||||
|  |  * @error					Invalid Handle, or a vote is already in progress. | ||||||
|  |  */ | ||||||
|  | stock bool:NativeVotes_DisplayToAll(Handle:vote, time) | ||||||
|  | { | ||||||
|  | 	new total = 0; | ||||||
|  | 	decl players[MaxClients]; | ||||||
|  | 	 | ||||||
|  | 	for (new i=1; i<=MaxClients; i++) | ||||||
|  | 	{ | ||||||
|  | 		if (!IsClientInGame(i) || IsFakeClient(i)) | ||||||
|  | 		{ | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 		players[total++] = i; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	return NativeVotes_Display(vote, players, total, time); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Sends a vote menu to a single team.  See NativeVotes_Display() for more information. | ||||||
|  |  * | ||||||
|  |  * @param vote				Vote Handle. | ||||||
|  |  * @param team				Team to send vote to. 1 = spectators, 2 = RED/Survivors/Terrorists, 3 = BLU/Infected/Counter-Terrorists | ||||||
|  |  * @param time				Maximum time to leave menu on the screen. | ||||||
|  |  * @return					True on success, false if this menu already has a vote session | ||||||
|  |  *							in progress. | ||||||
|  |  * @error					Invalid Handle, or a vote is already in progress. | ||||||
|  |  */ | ||||||
|  | stock bool:NativeVotes_DisplayToTeam(Handle:vote, team, time) | ||||||
|  | { | ||||||
|  | 	NativeVotes_SetTeam(vote, team); | ||||||
|  | 
 | ||||||
|  | 	new total; | ||||||
|  | 	decl players[MaxClients]; | ||||||
|  | 	 | ||||||
|  | 	for (new i=1; i<=MaxClients; i++) | ||||||
|  | 	{ | ||||||
|  | 		if (!IsClientInGame(i) || IsFakeClient(i) || (GetClientTeam(i) != team)) | ||||||
|  | 		{ | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 		players[total++] = i; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	return NativeVotes_Display(vote, players, total, time); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Sends a vote menu to all clients who are not spectators or waiting to choose a team.  See NativeVotes_Display() for more information. | ||||||
|  |  * | ||||||
|  |  * @param vote				Vote Handle. | ||||||
|  |  * @param time				Maximum time to leave menu on the screen. | ||||||
|  |  * @return					True on success, false if this menu already has a vote session | ||||||
|  |  *							in progress. | ||||||
|  |  * @error					Invalid Handle, or a vote is already in progress. | ||||||
|  |  */ | ||||||
|  | stock bool:NativeVotes_DisplayToAllNonSpectators(Handle:vote, time) | ||||||
|  | { | ||||||
|  | 	new total; | ||||||
|  | 	decl players[MaxClients]; | ||||||
|  | 	 | ||||||
|  | 	for (new i=1; i<=MaxClients; i++) | ||||||
|  | 	{ | ||||||
|  | 		if (!IsClientInGame(i) || IsFakeClient(i) || (GetClientTeam(i) < 2)) | ||||||
|  | 		{ | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 		players[total++] = i; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	return NativeVotes_Display(vote, players, total, time); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Display vote passed screen | ||||||
|  |  * | ||||||
|  |  * You MUST call one of the NativeVotesDisplayPass* or NativeVotes_DisplayFail functions | ||||||
|  |  * to hide the vote screen for users who didn't vote, and to clear out their selection | ||||||
|  |  * for the next vote. | ||||||
|  |  *  | ||||||
|  |  * @param vote				Vote handle | ||||||
|  |  * @param details			Normally the item that won the vote or format string. Also used for custom vote winners | ||||||
|  |  * @param ...				Variable number of format parameters. | ||||||
|  |  * @noreturn | ||||||
|  |  */ | ||||||
|  | native NativeVotes_DisplayPass(Handle:vote, const String:details[]=""); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Display vote passed screen with custom text to a single user | ||||||
|  |  * | ||||||
|  |  * You MUST call one of the NativeVotesDisplayPass* or NativeVotes_DisplayFail functions | ||||||
|  |  * to hide the vote screen for users who didn't vote, and to clear out their selection | ||||||
|  |  * for the next vote. | ||||||
|  |  *  | ||||||
|  |  * @param vote				Vote handle | ||||||
|  |  * @param client			client to display to | ||||||
|  |  * @param format			A format string. | ||||||
|  |  * @param any				Variable number of format parameters | ||||||
|  |  * @noreturn | ||||||
|  |  */ | ||||||
|  | native NativeVotes_DisplayPassCustomToOne(Handle:vote, client, const String:format[], any:...); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Display vote passed screen with custom text | ||||||
|  |  * | ||||||
|  |  * You MUST call one of the NativeVotesDisplayPass* or NativeVotes_DisplayFail functions | ||||||
|  |  * to hide the vote screen for users who didn't vote, and to clear out their selection | ||||||
|  |  * for the next vote. | ||||||
|  |  *  | ||||||
|  |  * @param vote				Vote handle | ||||||
|  |  * @param format			A format string. | ||||||
|  |  * @param any				Variable number of format parameters | ||||||
|  |  * @noreturn | ||||||
|  |  */ | ||||||
|  | stock NativeVotes_DisplayPassCustom(Handle:vote, const String:format[], any:...) | ||||||
|  | { | ||||||
|  | 	decl String:buffer[192]; | ||||||
|  | 	 | ||||||
|  | 	for (new i = 1; i <= MaxClients; ++i) | ||||||
|  | 	{ | ||||||
|  | 		if (IsClientInGame(i)) | ||||||
|  | 		{ | ||||||
|  | 			SetGlobalTransTarget(i); | ||||||
|  | 			VFormat(buffer, sizeof(buffer), format, 3); | ||||||
|  | 			NativeVotes_DisplayPassCustomToOne(vote, i, "%s", buffer); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Display vote passed screen with a custom type. | ||||||
|  |  * | ||||||
|  |  * A sample usage of this would be if Extend won an RTV vote: NativeVotes_DisplayPassEx(vote, NativeVotesPass_Extend, map); | ||||||
|  |  * | ||||||
|  |  * You MUST call one of NativeVotes_DisplayPass, NativeVotes_DisplayPassEx, | ||||||
|  |  * or NativeVotes_DisplayFail to hide the vote screen for users who didn't vote | ||||||
|  |  * and to clear out their selection for the next vote. | ||||||
|  |  *  | ||||||
|  |  * #param vote				Vote handle
 | ||||||
|  |  * @param passType			The pass screen to display | ||||||
|  |  * @param details			Normally the item that won the vote. Also used for custom vote winners | ||||||
|  |  * @noreturn | ||||||
|  |  */ | ||||||
|  | native NativeVotes_DisplayPassEx(Handle:vote, NativeVotesPassType:passType, const String:details[]=""); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Display failure screen. | ||||||
|  |  * | ||||||
|  |  * You MUST call one of NativeVotes_DisplayPass, NativeVotes_DisplayPassEx, | ||||||
|  |  * or NativeVotes_DisplayFail to hide the vote screen for users who didn't vote, | ||||||
|  |  * and to clear out their selection for the next vote. | ||||||
|  |  *  | ||||||
|  |  * @param reason			Vote failure reason from NativeVotesFailType enum | ||||||
|  |  * @noreturn | ||||||
|  |  */ | ||||||
|  | native NativeVotes_DisplayFail(Handle:vote, NativeVotesFailType:reason=NativeVotesFail_Generic); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Quick stock to determine whether voting is allowed.  This doesn't let you  | ||||||
|  |  * fine-tune a reason for not voting, so it's not recommended for lazily  | ||||||
|  |  * telling clients that voting isn't allowed. | ||||||
|  |  *  | ||||||
|  |  * @return				True if voting is allowed, false if voting is in progress | ||||||
|  |  *						or the cooldown is active. | ||||||
|  |  */ | ||||||
|  | stock bool:NativeVotes_IsNewVoteAllowed() | ||||||
|  | { | ||||||
|  | 	if (NativeVotes_IsVoteInProgress() || NativeVotes_CheckVoteDelay() != 0) | ||||||
|  | 	{ | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	return true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Used when callvote is called with no arguments. | ||||||
|  |  *  | ||||||
|  |  * This is used to configure the VoteSetup usermessage on TF2 and CS:GO | ||||||
|  |  *  | ||||||
|  |  * @param client		Client, in case the votes are restricted by client | ||||||
|  |  * @param voteTypes		Populate this array with the vote types this server supports | ||||||
|  |  * 						Custom and multiple choice votes are not supported from | ||||||
|  |  * 						the GUI and are thus ignored. | ||||||
|  |  * @return				Plugin_Continue to allow the server itself (or another plugin) to process the callvote | ||||||
|  |  * 						Plugin_Changed if you're changing the voteTypes, | ||||||
|  |  * 						Plugin_Handled to return a blank VoteSetup usermessage | ||||||
|  |  * 						Plugin_Stop to prevent VoteSetup usermessage (not recommended) | ||||||
|  |  */ | ||||||
|  | //functag public Action:NativeVotes_CallVoteSetupHandler(client, NativeVotesType:voteTypes[]);
 | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Forward for "callvote" handling | ||||||
|  |  *  | ||||||
|  |  * You should respond to this by starting a vote or by calling NativeVotes_DisplayCallVoteFail | ||||||
|  |  *  | ||||||
|  |  * @param client		Client | ||||||
|  |  * @param voteType		Type of vote being called.  This will NEVER be a multiple-choice or custom vote. | ||||||
|  |  * @param voteArgument	Vote argument or blank if the vote type has no argument. | ||||||
|  |  * @param target		target userid for kick votes or 0 for all other votes | ||||||
|  |  * @return				Plugin_Continue to allow the server itself (or another plugin) to process the callvote | ||||||
|  |  * 						Plugin_Handled if you processed this vote type | ||||||
|  |  * 						Plugin_Stop to block the vote type (not recommended) | ||||||
|  |  */ | ||||||
|  | //functag public Action:NativeVotes_CallVoteHandler(client, NativeVotesType:voteType, const String:voteArgument[], target);
 | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Register a plugin as a vote manager. | ||||||
|  |  * This is used to abstract away the details of the callvote command. | ||||||
|  |  *  | ||||||
|  |  * @param callHandler	Handler for callvote commands. | ||||||
|  |  * @param setupHandler	Handler to override the which vote types your server supports.  Only useful on TF2 and CS:GO. | ||||||
|  |  * @noreturn | ||||||
|  |  */ | ||||||
|  | //native NativeVotes_RegisterVoteManager(NativeVotes_CallVoteHandler:callHandler, NativeVotes_CallVoteSetupHandler:setupHandler=INVALID_FUNCTION);
 | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  *  Send a call vote fail screen to a user | ||||||
|  |  * Used to respond to a callvote with invalid arguments or for other reasons | ||||||
|  |  * (such as trying to target an admin for a kick/ban vote) | ||||||
|  |  *  | ||||||
|  |  * @param client		The client to display the fail screen to | ||||||
|  |  * @param reason		A vote call fail reason | ||||||
|  |  * @param time			For NativeVotesCallFail_Recent, the number of seconds until the vote | ||||||
|  |  * 						can be called again | ||||||
|  |  */ | ||||||
|  | native NativeVotes_DisplayCallVoteFail(client, NativeVotesCallFailType:reason, time); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Redraws the vote title from inside a MenuAction_Display callback | ||||||
|  |  * Not supported on L4D | ||||||
|  |  *  | ||||||
|  |  * @param text			Vote title to draw | ||||||
|  |  * @error 				If called from outside MenuAction_Display | ||||||
|  |  * @return				Plugin_Changed if the change is allowed, Plugin_Continue if it isn't. | ||||||
|  |  */ | ||||||
|  | native Action:NativeVotes_RedrawVoteTitle(const String:text[]); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Redraws the vote text from inside a MenuAction_DisplayItem callback. | ||||||
|  |  * Only supported on multiple-choice votes | ||||||
|  |  *  | ||||||
|  |  * @param text			Vote text to draw. | ||||||
|  |  * @error 				If called from outside MenuAction_DisplayItem | ||||||
|  |  * @return				Plugin_Changed if the change is allowed, Plugin_Continue if it isn't. | ||||||
|  |  */ | ||||||
|  | native Action:NativeVotes_RedrawVoteItem(const String:text[]); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Retrieves voting information from MenuAction_VoteEnd. | ||||||
|  |  * | ||||||
|  |  * @param param2		Second parameter of MenuAction_VoteEnd. | ||||||
|  |  * @param winningVotes	Number of votes received by the winning option. | ||||||
|  |  * @param totalVotes	Number of total votes received. | ||||||
|  |  * @noreturn | ||||||
|  |  */ | ||||||
|  | stock NativeVotes_GetInfo(param2, &winningVotes, &totalVotes) | ||||||
|  | { | ||||||
|  | 	winningVotes = param2 & 0xFFFF; | ||||||
|  | 	totalVotes = param2 >> 16; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Do not edit below this line! | ||||||
|  |  */ | ||||||
|  | public SharedPlugin:__pl_nativevotes =  | ||||||
|  | { | ||||||
|  | 	name = "nativevotes", | ||||||
|  | 	file = "nativevotes.smx", | ||||||
|  | #if defined REQUIRE_PLUGINS
 | ||||||
|  | 	required = 1, | ||||||
|  | #else
 | ||||||
|  | 	required = 0, | ||||||
|  | #endif
 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | public __pl_nativevotes_SetNTVOptional() | ||||||
|  | { | ||||||
|  | 	MarkNativeAsOptional("NativeVotes_IsVoteTypeSupported"); | ||||||
|  | 	MarkNativeAsOptional("NativeVotes_Create"); | ||||||
|  | 	MarkNativeAsOptional("NativeVotes_Close"); | ||||||
|  | 	MarkNativeAsOptional("NativeVotes_AddItem"); | ||||||
|  | 	MarkNativeAsOptional("NativeVotes_InsertItem"); | ||||||
|  | 	MarkNativeAsOptional("NativeVotes_RemoveItem"); | ||||||
|  | 	MarkNativeAsOptional("NativeVotes_RemoveAllItems"); | ||||||
|  | 	MarkNativeAsOptional("NativeVotes_GetItem"); | ||||||
|  | 	MarkNativeAsOptional("NativeVotes_GetItemCount"); | ||||||
|  | 	MarkNativeAsOptional("NativeVotes_SetDetails"); | ||||||
|  | 	MarkNativeAsOptional("NativeVotes_GetDetails"); | ||||||
|  | 	MarkNativeAsOptional("NativeVotes_SetTitle"); | ||||||
|  | 	MarkNativeAsOptional("NativeVotes_GetTitle"); | ||||||
|  | 	MarkNativeAsOptional("NativeVotes_SetTarget"); | ||||||
|  | 	MarkNativeAsOptional("NativeVotes_GetTarget"); | ||||||
|  | 	MarkNativeAsOptional("NativeVotes_GetTargetSteam"); | ||||||
|  | 	MarkNativeAsOptional("NativeVotes_IsVoteInProgress"); | ||||||
|  | 	MarkNativeAsOptional("NativeVotes_GetMaxItems"); | ||||||
|  | 	MarkNativeAsOptional("NativeVotes_SetOptionFlags"); | ||||||
|  | 	MarkNativeAsOptional("NativeVotes_GetOptionFlags"); | ||||||
|  | 	MarkNativeAsOptional("NativeVotes_Cancel"); | ||||||
|  | 	MarkNativeAsOptional("NativeVotes_SetResultCallback"); | ||||||
|  | 	MarkNativeAsOptional("NativeVotes_CheckVoteDelay"); | ||||||
|  | 	MarkNativeAsOptional("NativeVotes_IsClientInVotePool"); | ||||||
|  | 	MarkNativeAsOptional("NativeVotes_RedrawClientVote"); | ||||||
|  | 	MarkNativeAsOptional("NativeVotes_RedrawClientVote"); | ||||||
|  | 	MarkNativeAsOptional("NativeVotes_GetType"); | ||||||
|  | 	MarkNativeAsOptional("NativeVotes_SetTeam"); | ||||||
|  | 	MarkNativeAsOptional("NativeVotes_GetTeam"); | ||||||
|  | 	MarkNativeAsOptional("NativeVotes_SetInitiator"); | ||||||
|  | 	MarkNativeAsOptional("NativeVotes_GetInitiator"); | ||||||
|  | 	MarkNativeAsOptional("NativeVotes_Display"); | ||||||
|  | 	MarkNativeAsOptional("NativeVotes_DisplayPass"); | ||||||
|  | 	MarkNativeAsOptional("NativeVotes_DisplayPassCustomToOne"); | ||||||
|  | 	MarkNativeAsOptional("NativeVotes_DisplayPassEx"); | ||||||
|  | 	MarkNativeAsOptional("NativeVotes_DisplayFail"); | ||||||
|  | 	MarkNativeAsOptional("NativeVotes_RegisterVoteManager"); | ||||||
|  | 	MarkNativeAsOptional("NativeVotes_DisplayCallVoteFail"); | ||||||
|  | 	MarkNativeAsOptional("NativeVotes_RedrawVoteTitle"); | ||||||
|  | 	MarkNativeAsOptional("NativeVotes_RedrawVoteItem"); | ||||||
|  | } | ||||||
							
								
								
									
										40
									
								
								includes/outputinfo.inc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								includes/outputinfo.inc
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,40 @@ | |||||||
|  | #if defined _OutputInfo_Included
 | ||||||
|  |  #endinput
 | ||||||
|  | #endif
 | ||||||
|  | #define _OutputInfo_Included
 | ||||||
|  | 
 | ||||||
|  | native GetOutputCount(int Entity, const char[] sOutput); | ||||||
|  | native GetOutputTarget(int Entity, const char[] sOutput, int Index, char[] sTarget); | ||||||
|  | native GetOutputTargetInput(int Entity, const char[] sOutput, int Index, char[] sTargetInput); | ||||||
|  | native GetOutputParameter(int Entity, const char[] sOutput, int Index, char[] sParameter); | ||||||
|  | native Float:GetOutputDelay(int Entity, const char[] sOutput, int Index); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Do not edit below this line! | ||||||
|  |  */ | ||||||
|  | public Extension __ext_outputinfo = | ||||||
|  | { | ||||||
|  | 	name = "OutputInfo", | ||||||
|  | 	file = "outputinfo.ext", | ||||||
|  | #if defined AUTOLOAD_EXTENSIONS
 | ||||||
|  | 	autoload = 1, | ||||||
|  | #else
 | ||||||
|  | 	autoload = 0, | ||||||
|  | #endif
 | ||||||
|  | #if defined REQUIRE_EXTENSIONS
 | ||||||
|  | 	required = 1, | ||||||
|  | #else
 | ||||||
|  | 	required = 0, | ||||||
|  | #endif
 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #if !defined REQUIRE_EXTENSIONS
 | ||||||
|  | public __ext_outputinfo_SetNTVOptional() | ||||||
|  | { | ||||||
|  | 	MarkNativeAsOptional("GetOutputCount"); | ||||||
|  | 	MarkNativeAsOptional("GetOutputTarget"); | ||||||
|  | 	MarkNativeAsOptional("GetOutputTargetInput"); | ||||||
|  | 	MarkNativeAsOptional("GetOutputParameter"); | ||||||
|  | 	MarkNativeAsOptional("GetOutputDelay"); | ||||||
|  | } | ||||||
|  | #endif
 | ||||||
							
								
								
									
										36
									
								
								includes/zombiereloaded.inc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								includes/zombiereloaded.inc
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,36 @@ | |||||||
|  | /* | ||||||
|  |  * ============================================================================ | ||||||
|  |  * | ||||||
|  |  *  Zombie:Reloaded | ||||||
|  |  * | ||||||
|  |  *  File:          zombiereloaded.inc | ||||||
|  |  *  Type:          Include | ||||||
|  |  *  Description:   Main API include file. | ||||||
|  |  *  Notes:         Include this file to include the whole ZR API.  | ||||||
|  |  * | ||||||
|  |  *  Copyright (C) 2009-2013  Greyscale, Richard Helgeby | ||||||
|  |  * | ||||||
|  |  *  This program is free software: you can redistribute it and/or modify | ||||||
|  |  *  it under the terms of the GNU General Public License as published by | ||||||
|  |  *  the Free Software Foundation, either version 3 of the License, or | ||||||
|  |  *  (at your option) any later version. | ||||||
|  |  * | ||||||
|  |  *  This program is distributed in the hope that it will be useful, | ||||||
|  |  *  but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |  *  GNU General Public License for more details. | ||||||
|  |  * | ||||||
|  |  *  You should have received a copy of the GNU General Public License | ||||||
|  |  *  along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||||
|  |  * | ||||||
|  |  * ============================================================================ | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #if defined _zr_included
 | ||||||
|  |  #endinput
 | ||||||
|  | #endif
 | ||||||
|  | #define _zr_included
 | ||||||
|  | 
 | ||||||
|  | #include <zr/infect.zr>
 | ||||||
|  | #include <zr/respawn.zr>
 | ||||||
|  | #include <zr/class.zr>
 | ||||||
							
								
								
									
										127
									
								
								includes/zr/class.zr.inc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										127
									
								
								includes/zr/class.zr.inc
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,127 @@ | |||||||
|  | /* | ||||||
|  |  * ============================================================================ | ||||||
|  |  * | ||||||
|  |  *  Zombie:Reloaded | ||||||
|  |  * | ||||||
|  |  *  File:          class.zr.inc | ||||||
|  |  *  Type:          Include | ||||||
|  |  *  Description:   Player class API. | ||||||
|  |  * | ||||||
|  |  *  Copyright (C) 2009-2013  Greyscale, Richard Helgeby | ||||||
|  |  * | ||||||
|  |  *  This program is free software: you can redistribute it and/or modify | ||||||
|  |  *  it under the terms of the GNU General Public License as published by | ||||||
|  |  *  the Free Software Foundation, either version 3 of the License, or | ||||||
|  |  *  (at your option) any later version. | ||||||
|  |  * | ||||||
|  |  *  This program is distributed in the hope that it will be useful, | ||||||
|  |  *  but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |  *  GNU General Public License for more details. | ||||||
|  |  * | ||||||
|  |  *  You should have received a copy of the GNU General Public License | ||||||
|  |  *  along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||||
|  |  * | ||||||
|  |  * ============================================================================ | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * @section Internal class cache types. Specifies which class data to access. | ||||||
|  |  */ | ||||||
|  | #define ZR_CLASS_CACHE_ORIGINAL 0   /** Original class data loaded from file. */
 | ||||||
|  | #define ZR_CLASS_CACHE_MODIFIED 1   /** Default cache. Class data modified by eventual multipliers, map configs, commands, etc. */
 | ||||||
|  | #define ZR_CLASS_CACHE_PLAYER   2   /** Current player class attributes. The class index parameter is used as client index when reading from this cache. */
 | ||||||
|  | /** | ||||||
|  |  * @endsection | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Results when selecting a class for a player. | ||||||
|  |  */ | ||||||
|  | enum ClassSelectResult | ||||||
|  | { | ||||||
|  |     ClassSelected_NoChange,     /** No class change was necessary (class already selected). */ | ||||||
|  |     ClassSelected_Instant,      /** Class was instantly changed. */ | ||||||
|  |     ClassSelected_NextSpawn     /** Class will be used next spawn. */ | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Returns whether a class index is valid or not. | ||||||
|  |  * | ||||||
|  |  * @param classIndex    Class index to validate. | ||||||
|  |  * | ||||||
|  |  * @return              True if valid, false otherwise. | ||||||
|  |  */ | ||||||
|  | native bool:ZR_IsValidClassIndex(classIndex); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Gets the currently active class index that the player is using. | ||||||
|  |  * | ||||||
|  |  * @param client    The client index. | ||||||
|  |  * | ||||||
|  |  * @return          The active class index. | ||||||
|  |  */ | ||||||
|  | native bool:ZR_GetActiveClass(client); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Gets the current human class index that the player is using. | ||||||
|  |  * | ||||||
|  |  * @param client    The client index. | ||||||
|  |  * | ||||||
|  |  * @return          The human class index. | ||||||
|  |  */ | ||||||
|  | native bool:ZR_GetHumanClass(client); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Gets the current zombie class index that the player is using. | ||||||
|  |  * | ||||||
|  |  * @param client    The client index. | ||||||
|  |  * | ||||||
|  |  * @return          The zombie class index. | ||||||
|  |  */ | ||||||
|  | native bool:ZR_GetZombieClass(client); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Selects a class for a player. | ||||||
|  |  * | ||||||
|  |  * Human class attribute may be instantly applied if player is alive, human and | ||||||
|  |  * instant class change is enabled. Otherwise only the selected index will be | ||||||
|  |  * updated for next spawn. | ||||||
|  |  * | ||||||
|  |  * Class selection will be saved in client cookies if enabled. | ||||||
|  |  * | ||||||
|  |  * @param client            Client index. | ||||||
|  |  * @param classIndex        Class index. | ||||||
|  |  * @param applyIfPossible   Optional. Apply class attributes if conditions allow | ||||||
|  |  *                          it. Default is true. | ||||||
|  |  * @param saveIfEnabled     Optional. Save class selection in client cookies if | ||||||
|  |  *                          enabled. Default is true. | ||||||
|  |  * | ||||||
|  |  * @return                  Class selection result. See enum ClassSelectResult. | ||||||
|  |  */ | ||||||
|  | native ClassSelectResult:ZR_SelectClientClass(client, classIndex, bool:applyIfPossible = true, bool:saveIfEnabled = true); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Gets the class index of the class with the specified name. | ||||||
|  |  * | ||||||
|  |  * Note: This search is linear and probably won't perform well in large loops. | ||||||
|  |  * | ||||||
|  |  * @param className     Class name to search for. | ||||||
|  |  * @param cacheType     Optional. Specifies which class cache to read from, | ||||||
|  |  *                      except player cache. | ||||||
|  |  * | ||||||
|  |  * @return              Class index, or -1 if none found. | ||||||
|  |  */ | ||||||
|  | native ZR_GetClassByName(const String:className[], cacheType = ZR_CLASS_CACHE_MODIFIED); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Gets the class name displayed in the class menu. | ||||||
|  |  * | ||||||
|  |  * @param index         Index of the class in a class cache or a client index, | ||||||
|  |  *                      depending on the cache type specified. | ||||||
|  |  * @param buffer        The destination string buffer. | ||||||
|  |  * @param maxlen        The length of the destination string buffer. | ||||||
|  |  * @param cacheType     Optional. Specifies which class cache to read from. | ||||||
|  |  * @return              Number of cells written. -1 on error. | ||||||
|  |  */ | ||||||
|  | native ZR_GetClassDisplayName(index, String:buffer[], maxlen, cacheType = ZR_CLASS_CACHE_MODIFIED); | ||||||
							
								
								
									
										123
									
								
								includes/zr/infect.zr.inc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										123
									
								
								includes/zr/infect.zr.inc
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,123 @@ | |||||||
|  | /* | ||||||
|  |  * ============================================================================ | ||||||
|  |  * | ||||||
|  |  *  Zombie:Reloaded | ||||||
|  |  * | ||||||
|  |  *  File:          infect.zr.inc | ||||||
|  |  *  Type:          Include | ||||||
|  |  *  Description:   Infect-related natives/forwards. | ||||||
|  |  * | ||||||
|  |  *  Copyright (C) 2009-2013  Greyscale, Richard Helgeby | ||||||
|  |  * | ||||||
|  |  *  This program is free software: you can redistribute it and/or modify | ||||||
|  |  *  it under the terms of the GNU General Public License as published by | ||||||
|  |  *  the Free Software Foundation, either version 3 of the License, or | ||||||
|  |  *  (at your option) any later version. | ||||||
|  |  * | ||||||
|  |  *  This program is distributed in the hope that it will be useful, | ||||||
|  |  *  but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |  *  GNU General Public License for more details. | ||||||
|  |  * | ||||||
|  |  *  You should have received a copy of the GNU General Public License | ||||||
|  |  *  along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||||
|  |  * | ||||||
|  |  * ============================================================================ | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Returns true if the player is a zombie, false if not. | ||||||
|  |  * | ||||||
|  |  * @param client            The client index. | ||||||
|  |  *   | ||||||
|  |  * @return			        True if zombie, false if not. | ||||||
|  |  * @error                   Invalid client index, not connected or not alive. | ||||||
|  |  */ | ||||||
|  | native bool:ZR_IsClientZombie(client); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Returns true if the player is a human, false if not. | ||||||
|  |  * | ||||||
|  |  * @param client            The client index. | ||||||
|  |  *   | ||||||
|  |  * @return			        True if human, false if not. | ||||||
|  |  * @error                   Invalid client index, not connected or not alive. | ||||||
|  |  */ | ||||||
|  | native bool:ZR_IsClientHuman(client); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Infects a player. | ||||||
|  |  * | ||||||
|  |  * Note: If the player already is a zombie, the player will be re-infected. | ||||||
|  |  * | ||||||
|  |  * @param client            The client to infect. | ||||||
|  |  * @param attacker          (Optional) The attacker who did the infect. | ||||||
|  |  * @param motherInfect      (Optional) Infect as a mother zombie. | ||||||
|  |  * @param respawnOverride   (Optional) Set to true to override respawn cvar. | ||||||
|  |  * @param respawn           (Optional) Value to override with. | ||||||
|  |  * | ||||||
|  |  * @error                   Invalid client index, not connected or not alive. | ||||||
|  |  */ | ||||||
|  | native ZR_InfectClient(client, attacker = -1, bool:motherInfect = false, bool:respawnOverride = false, bool:respawn = false); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Turns a zombie back into a human. | ||||||
|  |  * | ||||||
|  |  * Note: If the player already is a human, this code will still run as the | ||||||
|  |  *       player was a zombie. | ||||||
|  |  * | ||||||
|  |  * @param client            The client to make human. | ||||||
|  |  * @param respawn           Teleport client back to spawn. | ||||||
|  |  * @param protect           Start spawn protection on client. | ||||||
|  |  * | ||||||
|  |  * @error                   Invalid client index, not connected or not alive. | ||||||
|  |  */ | ||||||
|  | native ZR_HumanClient(client, bool:respawn = false, bool:protect = false); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Called when a player is about to become a zombie. | ||||||
|  |  * Here you can modify any variable or block the infection entirely. | ||||||
|  |  *  | ||||||
|  |  * @param client            The client index. | ||||||
|  |  * @param attacker          The the infecter. (-1 if there is no infecter) | ||||||
|  |  * @param motherInfect      If the client is becoming a mother zombie. | ||||||
|  |  * @param respawnOverride   True if the respawn cvar is being overridden. | ||||||
|  |  * @param respawn           The value that respawn is being overridden with. | ||||||
|  |  *  | ||||||
|  |  * @return                  Plugin_Handled to block infection. Anything else | ||||||
|  |  *                          (like Plugin_Continue) to allow infection. | ||||||
|  |  */ | ||||||
|  | forward Action:ZR_OnClientInfect(&client, &attacker, &bool:motherInfect, &bool:respawnOverride, &bool:respawn); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Called after a player has become a zombie. | ||||||
|  |  *  | ||||||
|  |  * @param client            The client that was infected. | ||||||
|  |  * @param attacker          The the infecter. (-1 if there is no infecter) | ||||||
|  |  * @param motherInfect      If the client is a mother zombie. | ||||||
|  |  * @param respawnOverride   True if the respawn cvar was overridden. | ||||||
|  |  * @param respawn           The value that respawn was overridden with. | ||||||
|  |  */ | ||||||
|  | forward ZR_OnClientInfected(client, attacker, bool:motherInfect, bool:respawnOverride, bool:respawn); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Called when a player is about to become a human. (Through an admin command). | ||||||
|  |  * Here you can modify any variable or block the action entirely. | ||||||
|  |  *  | ||||||
|  |  * @param client            The client index. | ||||||
|  |  * @param respawn           True if the client was respawned, false if not. | ||||||
|  |  * @param protect           True if the client spawn protected, false if not. | ||||||
|  |  *  | ||||||
|  |  * @return                  Plugin_Handled to block infection. Anything else | ||||||
|  |  *                          (like Plugin_Continue) to allow acion. | ||||||
|  |  */ | ||||||
|  | forward Action:ZR_OnClientHuman(&client, &bool:respawn, &bool:protect); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Called after a player has become a human. (Through an admin command.) | ||||||
|  |  *  | ||||||
|  |  * @param client            The client index. | ||||||
|  |  * @param respawn           Whether the client was respawned. | ||||||
|  |  * @param protect           Whether the client has spawn protection. | ||||||
|  |  */ | ||||||
|  | forward ZR_OnClientHumanPost(client, bool:respawn, bool:protect); | ||||||
							
								
								
									
										95
									
								
								includes/zr/respawn.zr.inc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								includes/zr/respawn.zr.inc
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,95 @@ | |||||||
|  | /* | ||||||
|  |  * ============================================================================ | ||||||
|  |  * | ||||||
|  |  *  Zombie:Reloaded | ||||||
|  |  * | ||||||
|  |  *  File:          respawn.zr.inc | ||||||
|  |  *  Type:          Include | ||||||
|  |  *  Description:   Infect-related natives/forwards. | ||||||
|  |  * | ||||||
|  |  *  Copyright (C) 2009-2013  Greyscale, Richard Helgeby | ||||||
|  |  * | ||||||
|  |  *  This program is free software: you can redistribute it and/or modify | ||||||
|  |  *  it under the terms of the GNU General Public License as published by | ||||||
|  |  *  the Free Software Foundation, either version 3 of the License, or | ||||||
|  |  *  (at your option) any later version. | ||||||
|  |  * | ||||||
|  |  *  This program is distributed in the hope that it will be useful, | ||||||
|  |  *  but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |  *  GNU General Public License for more details. | ||||||
|  |  * | ||||||
|  |  *  You should have received a copy of the GNU General Public License | ||||||
|  |  *  along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||||
|  |  * | ||||||
|  |  * ============================================================================ | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Conditions for respawning players. | ||||||
|  |  */ | ||||||
|  | enum ZR_RespawnCondition | ||||||
|  | { | ||||||
|  |     ZR_Repsawn_Default = -1,    /** Let ZR decide according to its settings. */ | ||||||
|  |     ZR_Respawn_Human = 0,       /** Respawn as a human. */ | ||||||
|  |     ZR_Respawn_Zombie,          /** Respawn as a zombie. */ | ||||||
|  |     ZR_Respawn_ZombieIfSuicide  /** Respawn as a zombie if killed by world damage. */ | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Spawns a player into the round. | ||||||
|  |  *  | ||||||
|  |  * @param client            The client index. | ||||||
|  |  * @param condition         Optional. Set respawn condition, defaults to current | ||||||
|  |  *                          ZR settings. See ZR_RespawnCondition for details. | ||||||
|  |  * @error                   Invalid client index, not connected or already alive. | ||||||
|  |  */ | ||||||
|  | native ZR_RespawnClient(client, ZR_RespawnCondition:condition = ZR_Repsawn_Default); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Called right before ZR is about to respawn a player. | ||||||
|  |  * Here you can modify any variable or stop the action entirely. | ||||||
|  |  *  | ||||||
|  |  * @param client            The client index. | ||||||
|  |  * @param condition         Respawn condition. See ZR_RespawnCondition for | ||||||
|  |  *                          details. | ||||||
|  |  * | ||||||
|  |  * @return      Plugin_Handled to block respawn. | ||||||
|  |  */ | ||||||
|  | forward Action:ZR_OnClientRespawn(&client, &ZR_RespawnCondition:condition); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Called after ZR respawned a player. | ||||||
|  |  *  | ||||||
|  |  * @param client            The client index. | ||||||
|  |  * @param condition         Current condition of the respawned player. See | ||||||
|  |  *                          ZR_RespawnCondition for details. | ||||||
|  |  */ | ||||||
|  | forward ZR_OnClientRespawned(client, ZR_RespawnCondition:condition); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Set if a player died by a suicide or world damage. | ||||||
|  |   | ||||||
|  |  * Note: This will change the respawn condition. | ||||||
|  |  * Note: This value is reset to default by ZR when a zombie player dies. | ||||||
|  |  *  | ||||||
|  |  * @param client    The client index. | ||||||
|  |  * @param suicide   True to say the player suicided, false if killed by another | ||||||
|  |  *                  player. | ||||||
|  |  * | ||||||
|  |  * @error           Invalid client index or not connected. | ||||||
|  |  */ | ||||||
|  | native ZR_SetKilledByWorld(client, bool:suicide); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Get whether the player died by a suicide or world damage. | ||||||
|  |  * | ||||||
|  |  * Note: This value is only valid after death event, and before respawn. | ||||||
|  |  *  | ||||||
|  |  * @param client    The client index. | ||||||
|  |  *  | ||||||
|  |  * @return          True if the player died by suicide, false if killed by | ||||||
|  |  *                  another player. | ||||||
|  |  * @error           Invalid client index or not connected. | ||||||
|  |  */ | ||||||
|  | native bool:ZR_GetKilledByWorld(client); | ||||||
| @ -0,0 +1,21 @@ | |||||||
|  | ar_baggage | ||||||
|  | ar_monastery | ||||||
|  | ar_shoots | ||||||
|  | cs_assault | ||||||
|  | cs_italy | ||||||
|  | cs_militia | ||||||
|  | cs_office | ||||||
|  | de_aztec | ||||||
|  | de_bank | ||||||
|  | de_dust | ||||||
|  | de_dust2 | ||||||
|  | de_inferno | ||||||
|  | de_lake | ||||||
|  | de_mirage | ||||||
|  | de_nuke | ||||||
|  | de_safehouse | ||||||
|  | de_shorttrain | ||||||
|  | de_stmarc | ||||||
|  | de_sugarcane | ||||||
|  | de_train | ||||||
|  | de_vertigo | ||||||
| @ -0,0 +1,28 @@ | |||||||
|  | as_oilrig | ||||||
|  | cs_747 | ||||||
|  | cs_assault | ||||||
|  | cs_backalley | ||||||
|  | cs_compound | ||||||
|  | cs_estate | ||||||
|  | cs_havana | ||||||
|  | cs_italy | ||||||
|  | cs_militia | ||||||
|  | cs_office | ||||||
|  | cs_siege | ||||||
|  | de_airstrip | ||||||
|  | de_aztec | ||||||
|  | de_cbble | ||||||
|  | de_chateau | ||||||
|  | de_dust2 | ||||||
|  | de_dust | ||||||
|  | de_inferno | ||||||
|  | de_nuke | ||||||
|  | de_piranesi | ||||||
|  | de_port | ||||||
|  | de_prodigy | ||||||
|  | de_storm | ||||||
|  | de_survivor | ||||||
|  | de_tides | ||||||
|  | de_torn | ||||||
|  | de_train | ||||||
|  | de_vertigo | ||||||
| @ -0,0 +1,9 @@ | |||||||
|  | dod_anzio | ||||||
|  | dod_argentan | ||||||
|  | dod_avalanche | ||||||
|  | dod_colmar | ||||||
|  | dod_donner | ||||||
|  | dod_flash | ||||||
|  | dod_jagd | ||||||
|  | dod_kalt | ||||||
|  | dod_palermo | ||||||
| @ -0,0 +1,7 @@ | |||||||
|  | dm_lockdown | ||||||
|  | dm_overwatch | ||||||
|  | dm_runoff | ||||||
|  | dm_steamlab | ||||||
|  | dm_underpass | ||||||
|  | dm_resistance | ||||||
|  | dm_powerhouse | ||||||
							
								
								
									
										65
									
								
								mapchooser_extended/configs/mapchooser_extended/maps/tf.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								mapchooser_extended/configs/mapchooser_extended/maps/tf.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,65 @@ | |||||||
|  | tc_hydro | ||||||
|  | cp_well | ||||||
|  | cp_granary | ||||||
|  | cp_dustbowl | ||||||
|  | cp_gravelpit | ||||||
|  | ctf_2fort | ||||||
|  | ctf_well | ||||||
|  | cp_badlands | ||||||
|  | pl_goldrush | ||||||
|  | cp_fastlane | ||||||
|  | ctf_turbine | ||||||
|  | pl_badwater | ||||||
|  | cp_steel | ||||||
|  | arena_badlands | ||||||
|  | arena_granary | ||||||
|  | arena_lumberyard | ||||||
|  | arena_ravine | ||||||
|  | arena_well | ||||||
|  | cp_egypt_final | ||||||
|  | cp_junction_final | ||||||
|  | arena_watchtower | ||||||
|  | plr_pipeline | ||||||
|  | arena_sawmill | ||||||
|  | arena_nucleus | ||||||
|  | pl_hoodoo_final | ||||||
|  | koth_sawmill | ||||||
|  | koth_nucleus | ||||||
|  | koth_viaduct | ||||||
|  | ctf_sawmill | ||||||
|  | arena_offblast_final | ||||||
|  | cp_yukon_final | ||||||
|  | koth_harvest_final | ||||||
|  | koth_harvest_event | ||||||
|  | ctf_doublecross | ||||||
|  | cp_gorge | ||||||
|  | cp_freight_final1 | ||||||
|  | pl_upward | ||||||
|  | plr_hightower | ||||||
|  | pl_thundermountain | ||||||
|  | cp_coldfront | ||||||
|  | cp_mountainlab | ||||||
|  | cp_manor_event | ||||||
|  | cp_degrootkeep | ||||||
|  | cp_5gorge | ||||||
|  | pl_frontier_final | ||||||
|  | plr_nightfall_final | ||||||
|  | koth_lakeside_final | ||||||
|  | koth_badlands | ||||||
|  | pl_barnblitz | ||||||
|  | cp_gullywash_final1 | ||||||
|  | koth_viaduct_event | ||||||
|  | cp_foundry | ||||||
|  | sd_doomsday | ||||||
|  | koth_king | ||||||
|  | mvm_mannworks | ||||||
|  | mvm_coaltown | ||||||
|  | mvm_decoy | ||||||
|  | koth_lakeside_event | ||||||
|  | mvm_bigrock | ||||||
|  | cp_process_final | ||||||
|  | cp_standin_final | ||||||
|  | plr_hightower_event | ||||||
|  | cp_snakewater_final1 | ||||||
|  | mvm_mannhattan | ||||||
|  | mvm_rottenburg | ||||||
| @ -0,0 +1,77 @@ | |||||||
|  | "MapchooserSoundsList" | ||||||
|  | { | ||||||
|  | 	"tf" | ||||||
|  | 	{ | ||||||
|  | 		"counter" | ||||||
|  | 		{ | ||||||
|  | 			"1" | ||||||
|  | 			{ | ||||||
|  | 				"sound"		"sourcemod/mapchooser/tf2/announcer_begins_1sec.mp3" | ||||||
|  | 				"builtin" 	"vo/announcer_begins_1sec.wav" | ||||||
|  | 				"event"		"Announcer.RoundBegins1Seconds" | ||||||
|  | 			} | ||||||
|  | 			"2" | ||||||
|  | 			{ | ||||||
|  | 				"sound"		"sourcemod/mapchooser/tf2/announcer_begins_2sec.mp3" | ||||||
|  | 				"builtin"	"vo/announcer_begins_2sec.wav" | ||||||
|  | 				"event"		"Announcer.RoundBegins2Seconds" | ||||||
|  | 			} | ||||||
|  | 			"3" | ||||||
|  | 			{ | ||||||
|  | 				"sound"		"sourcemod/mapchooser/tf2/announcer_begins_3sec.mp3" | ||||||
|  | 				"builtin"	"vo/announcer_begins_3sec.wav" | ||||||
|  | 				"event"		"Announcer.RoundBegins3Seconds" | ||||||
|  | 			} | ||||||
|  | 			"4" | ||||||
|  | 			{ | ||||||
|  | 				"sound"		"sourcemod/mapchooser/tf2/announcer_begins_4sec.mp3" | ||||||
|  | 				"builtin"	"vo/announcer_begins_4sec.wav" | ||||||
|  | 				"event"		"Announcer.RoundBegins4Seconds" | ||||||
|  | 			} | ||||||
|  | 			"5" | ||||||
|  | 			{ | ||||||
|  | 				"sound"		"sourcemod/mapchooser/tf2/announcer_begins_5sec.mp3" | ||||||
|  | 				"builtin"	"vo/announcer_begins_5sec.wav" | ||||||
|  | 				"event"		"Announcer.RoundBegins5Seconds" | ||||||
|  | 			}	 | ||||||
|  | 			"10" | ||||||
|  | 			{ | ||||||
|  | 				"sound"		"sourcemod/mapchooser/tf2/announcer_dec_missionbegins10s01.mp3" | ||||||
|  | 				"builtin"	"vo/announcer_dec_missionbegins10s01.wav" | ||||||
|  | 			}	 | ||||||
|  | 			"30" | ||||||
|  | 			{ | ||||||
|  | 				"sound"		"sourcemod/mapchooser/tf2/announcer_dec_missionbegins30s01.mp3" | ||||||
|  | 				"builtin"	"vo/announcer_dec_missionbegins30s01.wav" | ||||||
|  | 			} | ||||||
|  | 			"60" | ||||||
|  | 			{ | ||||||
|  | 				"sound"		"sourcemod/mapchooser/tf2/announcer_dec_missionbegins60s06.mp3" | ||||||
|  | 				"builtin"	"vo/announcer_dec_missionbegins60s06.wav" | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		"vote start" | ||||||
|  | 		{ | ||||||
|  | 			"sound"		"sourcemod/mapchooser/tf2/vote_started.mp3" | ||||||
|  | 			"event"		"Vote.Created" | ||||||
|  | 			"builtin"	"ui/vote_started.wav" | ||||||
|  | 		} | ||||||
|  | 		"vote end" | ||||||
|  | 		{ | ||||||
|  | 			"sound"		"sourcemod/mapchooser/tf2/vote_success.mp3" | ||||||
|  | 			"event"		"Vote.Passed" | ||||||
|  | 			"builtin"	"ui/vote_success.wav" | ||||||
|  | 		} | ||||||
|  | 		"vote warning" | ||||||
|  | 		{ | ||||||
|  | 			"sound"		"sourcemod/mapchooser/tf2/announcer_dec_missionbegins60s03.mp3" | ||||||
|  | 			"builtin"	"vo/announcer_dec_missionbegins60s03.wav" | ||||||
|  | 		} | ||||||
|  | 		"runoff warning" | ||||||
|  | 		{ | ||||||
|  | 			"sound"		"sourcemod/mapchooser/tf2/vote_failure.mp3" | ||||||
|  | 			"event"		"Vote.Failed" | ||||||
|  | 			"builtin"	"ui/vote_failure.wav" | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										1
									
								
								mapchooser_extended/scripting/include/colors.inc
									
									
									
									
									
										Symbolic link
									
								
							
							
						
						
									
										1
									
								
								mapchooser_extended/scripting/include/colors.inc
									
									
									
									
									
										Symbolic link
									
								
							| @ -0,0 +1 @@ | |||||||
|  | ../../../includes/colors.inc | ||||||
							
								
								
									
										108
									
								
								mapchooser_extended/scripting/include/mapchooser_extended.inc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								mapchooser_extended/scripting/include/mapchooser_extended.inc
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,108 @@ | |||||||
|  | /** | ||||||
|  |  * vim: set ts=4 : | ||||||
|  |  * ============================================================================= | ||||||
|  |  * MapChooser Extended | ||||||
|  |  * Creates a map vote at appropriate times, setting sm_nextmap to the winning | ||||||
|  |  * vote | ||||||
|  |  * | ||||||
|  |  * MapChooser Extended (C)2011-2013 Powerlord (Ross Bemrose) | ||||||
|  |  * SourceMod (C)2004-2007 AlliedModders LLC.  All rights reserved. | ||||||
|  |  * ============================================================================= | ||||||
|  |  * | ||||||
|  |  * This program is free software; you can redistribute it and/or modify it under | ||||||
|  |  * the terms of the GNU General Public License, version 3.0, as published by the | ||||||
|  |  * Free Software Foundation. | ||||||
|  |  *  | ||||||
|  |  * This program is distributed in the hope that it will be useful, but WITHOUT | ||||||
|  |  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||||||
|  |  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more | ||||||
|  |  * details. | ||||||
|  |  * | ||||||
|  |  * You should have received a copy of the GNU General Public License along with | ||||||
|  |  * this program.  If not, see <http://www.gnu.org/licenses/>. | ||||||
|  |  * | ||||||
|  |  * As a special exception, AlliedModders LLC gives you permission to link the | ||||||
|  |  * code of this program (as well as its derivative works) to "Half-Life 2," the | ||||||
|  |  * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software | ||||||
|  |  * by the Valve Corporation.  You must obey the GNU General Public License in | ||||||
|  |  * all respects for all other code used.  Additionally, AlliedModders LLC grants | ||||||
|  |  * this exception to all derivative works.  AlliedModders LLC defines further | ||||||
|  |  * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), | ||||||
|  |  * or <http://www.sourcemod.net/license.php>. | ||||||
|  |  * | ||||||
|  |  * Version: $Id$ | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #if defined _mapchooser_extended_included_
 | ||||||
|  |   #endinput
 | ||||||
|  | #endif
 | ||||||
|  | #define _mapchooser_extended_included_
 | ||||||
|  | #include <mapchooser>
 | ||||||
|  | 
 | ||||||
|  | // MCE 1.9 series
 | ||||||
|  | 
 | ||||||
|  | enum CanNominateResult | ||||||
|  | { | ||||||
|  | 	CanNominate_No_VoteFull,		/** No, nominations list is full */ | ||||||
|  | 	CanNominate_No_VoteInProgress,	/** No, map vote is in progress */ | ||||||
|  | 	CanNominate_No_VoteComplete,	/** No, map vote is completed */ | ||||||
|  | 	CanNominate_Yes,				/** Yes, you can nominate */ | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Called whenever warning timer starts | ||||||
|  |  *  | ||||||
|  |  */ | ||||||
|  | forward OnMapVoteWarningStart(); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Called whenever runoff warning timer starts | ||||||
|  |  */ | ||||||
|  | forward OnMapVoteRunnoffWarningStart(); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Called whenever the timer ticks | ||||||
|  |  */ | ||||||
|  | forward OnMapVoteWarningTick(time); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Called whenever vote starts | ||||||
|  |  *  | ||||||
|  |  * @deprecated Will be removed in MapChooser 1.8.  Use OnMapVoteStarted instead. | ||||||
|  |  */ | ||||||
|  | forward OnMapVoteStart(); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Called whenever vote ends | ||||||
|  |  */ | ||||||
|  | forward OnMapVoteEnd(const String:map[]); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Is a map on the current game's official list? | ||||||
|  |  * This should be treated as informative only. | ||||||
|  |  *  | ||||||
|  |  * @param map 	Name of map to check | ||||||
|  |  * @return 		true if it's on the list of official maps for this game | ||||||
|  |  */ | ||||||
|  | native bool:IsMapOfficial(const String:map[]); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Is nominate allowed? | ||||||
|  |  *  | ||||||
|  |  * @return		A CanNominateResult corresponding to whether a vote is allowed or not | ||||||
|  |  */ | ||||||
|  | native CanNominateResult:CanNominate(); | ||||||
|  | 
 | ||||||
|  | native bool:ExcludeMap(const String:map[]); | ||||||
|  | 
 | ||||||
|  | public SharedPlugin:__pl_mapchooser_extended =  | ||||||
|  | { | ||||||
|  | 	name = "mapchooser", | ||||||
|  | 	file = "mapchooser_extended.smx", | ||||||
|  | #if defined REQUIRE_PLUGIN
 | ||||||
|  | 	required = 1, | ||||||
|  | #else
 | ||||||
|  | 	required = 0, | ||||||
|  | #endif
 | ||||||
|  | }; | ||||||
							
								
								
									
										1
									
								
								mapchooser_extended/scripting/include/nativevotes.inc
									
									
									
									
									
										Symbolic link
									
								
							
							
						
						
									
										1
									
								
								mapchooser_extended/scripting/include/nativevotes.inc
									
									
									
									
									
										Symbolic link
									
								
							| @ -0,0 +1 @@ | |||||||
|  | ../../../includes/nativevotes.inc | ||||||
							
								
								
									
										2343
									
								
								mapchooser_extended/scripting/mapchooser_extended.sp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2343
									
								
								mapchooser_extended/scripting/mapchooser_extended.sp
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										703
									
								
								mapchooser_extended/scripting/nominations_extended.sp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										703
									
								
								mapchooser_extended/scripting/nominations_extended.sp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,703 @@ | |||||||
|  | /** | ||||||
|  |  * vim: set ts=4 : | ||||||
|  |  * ============================================================================= | ||||||
|  |  * Nominations Extended | ||||||
|  |  * Allows players to nominate maps for Mapchooser | ||||||
|  |  * | ||||||
|  |  * Nominations Extended (C)2012-2013 Powerlord (Ross Bemrose) | ||||||
|  |  * SourceMod (C)2004-2007 AlliedModders LLC.  All rights reserved. | ||||||
|  |  * ============================================================================= | ||||||
|  |  * | ||||||
|  |  * This program is free software; you can redistribute it and/or modify it under | ||||||
|  |  * the terms of the GNU General Public License, version 3.0, as published by the | ||||||
|  |  * Free Software Foundation. | ||||||
|  |  * | ||||||
|  |  * This program is distributed in the hope that it will be useful, but WITHOUT | ||||||
|  |  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||||||
|  |  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more | ||||||
|  |  * details. | ||||||
|  |  * | ||||||
|  |  * You should have received a copy of the GNU General Public License along with | ||||||
|  |  * this program.  If not, see <http://www.gnu.org/licenses/>. | ||||||
|  |  * | ||||||
|  |  * As a special exception, AlliedModders LLC gives you permission to link the | ||||||
|  |  * code of this program (as well as its derivative works) to "Half-Life 2," the | ||||||
|  |  * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software | ||||||
|  |  * by the Valve Corporation.  You must obey the GNU General Public License in | ||||||
|  |  * all respects for all other code used.  Additionally, AlliedModders LLC grants | ||||||
|  |  * this exception to all derivative works.  AlliedModders LLC defines further | ||||||
|  |  * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), | ||||||
|  |  * or <http://www.sourcemod.net/license.php>. | ||||||
|  |  * | ||||||
|  |  * Version: $Id$ | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include <sourcemod> | ||||||
|  | #include <mapchooser> | ||||||
|  | #include "include/mapchooser_extended" | ||||||
|  | #include <colors> | ||||||
|  | #pragma semicolon 1 | ||||||
|  | 
 | ||||||
|  | #define MCE_VERSION "1.10.0" | ||||||
|  | 
 | ||||||
|  | public Plugin:myinfo = | ||||||
|  | { | ||||||
|  | 	name = "Map Nominations Extended", | ||||||
|  | 	author = "Powerlord and AlliedModders LLC", | ||||||
|  | 	description = "Provides Map Nominations", | ||||||
|  | 	version = MCE_VERSION, | ||||||
|  | 	url = "https://forums.alliedmods.net/showthread.php?t=156974" | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | new Handle:g_Cvar_ExcludeOld = INVALID_HANDLE; | ||||||
|  | new Handle:g_Cvar_ExcludeCurrent = INVALID_HANDLE; | ||||||
|  | 
 | ||||||
|  | new Handle:g_MapList = INVALID_HANDLE; | ||||||
|  | new Handle:g_AdminMapList = INVALID_HANDLE; | ||||||
|  | new Handle:g_MapMenu = INVALID_HANDLE; | ||||||
|  | new Handle:g_AdminMapMenu = INVALID_HANDLE; | ||||||
|  | new g_mapFileSerial = -1; | ||||||
|  | new g_AdminMapFileSerial = -1; | ||||||
|  | 
 | ||||||
|  | #define MAPSTATUS_ENABLED (1<<0) | ||||||
|  | #define MAPSTATUS_DISABLED (1<<1) | ||||||
|  | #define MAPSTATUS_EXCLUDE_CURRENT (1<<2) | ||||||
|  | #define MAPSTATUS_EXCLUDE_PREVIOUS (1<<3) | ||||||
|  | #define MAPSTATUS_EXCLUDE_NOMINATED (1<<4) | ||||||
|  | 
 | ||||||
|  | new Handle:g_mapTrie; | ||||||
|  | 
 | ||||||
|  | // Nominations Extended Convars | ||||||
|  | new Handle:g_Cvar_MarkCustomMaps = INVALID_HANDLE; | ||||||
|  | 
 | ||||||
|  | new Handle:g_Cvar_NominateDelay = INVALID_HANDLE; | ||||||
|  | new Handle:g_Cvar_InitialDelay = INVALID_HANDLE; | ||||||
|  | new g_Player_NominationDelay[MAXPLAYERS+1]; | ||||||
|  | new g_NominationDelay; | ||||||
|  | 
 | ||||||
|  | public OnPluginStart() | ||||||
|  | { | ||||||
|  | 	LoadTranslations("common.phrases"); | ||||||
|  | 	LoadTranslations("nominations.phrases"); | ||||||
|  | 	LoadTranslations("basetriggers.phrases"); // for Next Map phrase | ||||||
|  | 	LoadTranslations("mapchooser_extended.phrases"); | ||||||
|  | 
 | ||||||
|  | 	new arraySize = ByteCountToCells(PLATFORM_MAX_PATH); | ||||||
|  | 	g_MapList = CreateArray(arraySize); | ||||||
|  | 	g_AdminMapList = CreateArray(arraySize); | ||||||
|  | 
 | ||||||
|  | 	g_Cvar_ExcludeOld = CreateConVar("sm_nominate_excludeold", "1", "Specifies if the current map should be excluded from the Nominations list", 0, true, 0.00, true, 1.0); | ||||||
|  | 	g_Cvar_ExcludeCurrent = CreateConVar("sm_nominate_excludecurrent", "1", "Specifies if the MapChooser excluded maps should also be excluded from Nominations", 0, true, 0.00, true, 1.0); | ||||||
|  | 	g_Cvar_InitialDelay = CreateConVar("sm_nominate_initialdelay", "60.0", "Time in seconds before first Nomination can be made", 0, true, 0.00); | ||||||
|  | 	g_Cvar_NominateDelay = CreateConVar("sm_nominate_delay", "3.0", "Delay between nominations", 0, true, 0.00, true, 60.00); | ||||||
|  | 
 | ||||||
|  | 	RegConsoleCmd("say", Command_Say); | ||||||
|  | 	RegConsoleCmd("say_team", Command_Say); | ||||||
|  | 
 | ||||||
|  | 	RegConsoleCmd("sm_nominate", Command_Nominate); | ||||||
|  | 	RegConsoleCmd("sm_nomlist", Command_NominateList); | ||||||
|  | 
 | ||||||
|  | 	RegAdminCmd("sm_nominate_addmap", Command_Addmap, ADMFLAG_CHANGEMAP, "sm_nominate_addmap <mapname> - Forces a map to be on the next mapvote."); | ||||||
|  | 
 | ||||||
|  | 	// BotoX | ||||||
|  | 	RegAdminCmd("sm_nominate_exclude", Command_AddExclude, ADMFLAG_CHANGEMAP, "sm_nominate_exclude <mapname> - Forces a map to be inserted into the recently played maps. Effectively blocking the map from being nominated."); | ||||||
|  | 
 | ||||||
|  | 	// Nominations Extended cvars | ||||||
|  | 	CreateConVar("ne_version", MCE_VERSION, "Nominations Extended Version", FCVAR_SPONLY|FCVAR_NOTIFY|FCVAR_DONTRECORD); | ||||||
|  | 
 | ||||||
|  | 	g_mapTrie = CreateTrie(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public OnAllPluginsLoaded() | ||||||
|  | { | ||||||
|  | 	// This is an MCE cvar... this plugin requires MCE to be loaded.  Granted, this plugin SHOULD have an MCE dependency. | ||||||
|  | 	g_Cvar_MarkCustomMaps = FindConVar("mce_markcustommaps"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public OnConfigsExecuted() | ||||||
|  | { | ||||||
|  | 	if (ReadMapList(g_MapList, | ||||||
|  | 					g_mapFileSerial, | ||||||
|  | 					"nominations", | ||||||
|  | 					MAPLIST_FLAG_CLEARARRAY|MAPLIST_FLAG_MAPSFOLDER) | ||||||
|  | 		== INVALID_HANDLE) | ||||||
|  | 	{ | ||||||
|  | 		if (g_mapFileSerial == -1) | ||||||
|  | 		{ | ||||||
|  | 			SetFailState("Unable to create a valid map list."); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	if (ReadMapList(g_AdminMapList, | ||||||
|  | 					g_AdminMapFileSerial, | ||||||
|  | 					"sm_nominate_addmap menu", | ||||||
|  | 					MAPLIST_FLAG_CLEARARRAY|MAPLIST_FLAG_NO_DEFAULT|MAPLIST_FLAG_MAPSFOLDER) | ||||||
|  | 		== INVALID_HANDLE) | ||||||
|  | 	{ | ||||||
|  | 		if (g_AdminMapFileSerial == -1) | ||||||
|  | 		{ | ||||||
|  | 			SetFailState("Unable to create a valid admin map list."); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 		for (new i = 0; i < GetArraySize(g_MapList); i++) | ||||||
|  | 		{ | ||||||
|  | 			decl String:map[PLATFORM_MAX_PATH]; | ||||||
|  | 			GetArrayString(g_MapList, i, map, sizeof(map)); | ||||||
|  | 
 | ||||||
|  | 			new Index = FindStringInArray(g_AdminMapList, map); | ||||||
|  | 			if (Index != -1) | ||||||
|  | 				RemoveFromArray(g_AdminMapList, Index); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	g_NominationDelay = GetTime() + GetConVarInt(g_Cvar_InitialDelay); | ||||||
|  | 
 | ||||||
|  | 	BuildMapMenu(); | ||||||
|  | 	BuildAdminMapMenu(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public OnNominationRemoved(const String:map[], owner) | ||||||
|  | { | ||||||
|  | 	new status; | ||||||
|  | 
 | ||||||
|  | 	/* Is the map in our list? */ | ||||||
|  | 	if (!GetTrieValue(g_mapTrie, map, status)) | ||||||
|  | 	{ | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* Was the map disabled due to being nominated */ | ||||||
|  | 	if ((status & MAPSTATUS_EXCLUDE_NOMINATED) != MAPSTATUS_EXCLUDE_NOMINATED) | ||||||
|  | 	{ | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	SetTrieValue(g_mapTrie, map, MAPSTATUS_ENABLED); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public Action:Command_Addmap(client, args) | ||||||
|  | { | ||||||
|  | 	if (args == 0) | ||||||
|  | 	{ | ||||||
|  | 		AttemptAdminNominate(client); | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (args != 1) | ||||||
|  | 	{ | ||||||
|  | 		CReplyToCommand(client, "[NE] Usage: sm_nominate_addmap <mapname>"); | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	decl String:mapname[PLATFORM_MAX_PATH]; | ||||||
|  | 	GetCmdArg(1, mapname, sizeof(mapname)); | ||||||
|  | 
 | ||||||
|  | 	// new status; | ||||||
|  | 	if (/*!GetTrieValue(g_mapTrie, mapname, status)*/!IsMapValid(mapname)) | ||||||
|  | 	{ | ||||||
|  | 		CReplyToCommand(client, "%t", "Map was not found", mapname); | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	new NominateResult:result = NominateMap(mapname, true, 0); | ||||||
|  | 
 | ||||||
|  | 	if (result > Nominate_Replaced) | ||||||
|  | 	{ | ||||||
|  | 		/* We assume already in vote is the casue because the maplist does a Map Validity check and we forced, so it can't be full */ | ||||||
|  | 		CReplyToCommand(client, "%t", "Map Already In Vote", mapname); | ||||||
|  | 
 | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	SetTrieValue(g_mapTrie, mapname, MAPSTATUS_DISABLED|MAPSTATUS_EXCLUDE_NOMINATED); | ||||||
|  | 
 | ||||||
|  | 	CReplyToCommand(client, "%t", "Map Inserted", mapname); | ||||||
|  | 	LogAction(client, -1, "\"%L\" inserted map \"%s\".", client, mapname); | ||||||
|  | 
 | ||||||
|  | 	PrintToChatAll("[NE] %N has inserted %s into nominations", client, mapname); | ||||||
|  | 
 | ||||||
|  | 	return Plugin_Handled; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public Action:Command_AddExclude(client, args) | ||||||
|  | { | ||||||
|  | 	if (args < 1) | ||||||
|  | 	{ | ||||||
|  | 		CReplyToCommand(client, "[NE] Usage: sm_nominate_exclude <mapname>"); | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	decl String:mapname[PLATFORM_MAX_PATH]; | ||||||
|  | 	GetCmdArg(1, mapname, sizeof(mapname)); | ||||||
|  | 
 | ||||||
|  | 	new status; | ||||||
|  | 	if(!GetTrieValue(g_mapTrie, mapname, status)) | ||||||
|  | 	{ | ||||||
|  | 		ReplyToCommand(client, "[NE] %t", "Map was not found", mapname); | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	ShowActivity(client, "Excluded map \"%s\" from nomination", mapname); | ||||||
|  | 	LogAction(client, -1, "\"%L\" excluded map \"%s\" from nomination", client, mapname); | ||||||
|  | 
 | ||||||
|  | 	SetTrieValue(g_mapTrie, mapname, MAPSTATUS_DISABLED|MAPSTATUS_EXCLUDE_PREVIOUS); | ||||||
|  | 
 | ||||||
|  | 	// native call to mapchooser_extended | ||||||
|  | 	ExcludeMap(mapname); | ||||||
|  | 
 | ||||||
|  | 	return Plugin_Handled; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public Action:Command_Say(client, args) | ||||||
|  | { | ||||||
|  | 	if (!client) | ||||||
|  | 	{ | ||||||
|  | 		return Plugin_Continue; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	decl String:text[192]; | ||||||
|  | 	if (!GetCmdArgString(text, sizeof(text))) | ||||||
|  | 	{ | ||||||
|  | 		return Plugin_Continue; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	new startidx = 0; | ||||||
|  | 	if(text[strlen(text)-1] == '"') | ||||||
|  | 	{ | ||||||
|  | 		text[strlen(text)-1] = '\0'; | ||||||
|  | 		startidx = 1; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	new ReplySource:old = SetCmdReplySource(SM_REPLY_TO_CHAT); | ||||||
|  | 
 | ||||||
|  | 	if (strcmp(text[startidx], "nominate", false) == 0) | ||||||
|  | 	{ | ||||||
|  | 		if (IsNominateAllowed(client)) | ||||||
|  | 		{ | ||||||
|  | 			if (g_NominationDelay > GetTime()) | ||||||
|  | 				ReplyToCommand(client, "[NE] Nominations will be unlocked in %d seconds", g_NominationDelay - GetTime()); | ||||||
|  | 			else | ||||||
|  | 				AttemptNominate(client); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	SetCmdReplySource(old); | ||||||
|  | 
 | ||||||
|  | 	return Plugin_Continue; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public Action:Command_Nominate(client, args) | ||||||
|  | { | ||||||
|  | 	if (!client || !IsNominateAllowed(client)) | ||||||
|  | 	{ | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (g_NominationDelay > GetTime()) | ||||||
|  | 	{ | ||||||
|  | 		ReplyToCommand(client, "[NE] Nominations will be unlocked in %d seconds", g_NominationDelay - GetTime()); | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (args == 0) | ||||||
|  | 	{ | ||||||
|  | 		AttemptNominate(client); | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (g_Player_NominationDelay[client] > GetTime()) | ||||||
|  | 	{ | ||||||
|  | 		ReplyToCommand(client, "[NE] Please wait %d seconds before you can nominate again", g_Player_NominationDelay[client] - GetTime()); | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	decl String:mapname[PLATFORM_MAX_PATH]; | ||||||
|  | 	GetCmdArg(1, mapname, sizeof(mapname)); | ||||||
|  | 
 | ||||||
|  | 	new status; | ||||||
|  | 	if (!GetTrieValue(g_mapTrie, mapname, status)) | ||||||
|  | 	{ | ||||||
|  | 		CReplyToCommand(client, "%t", "Map was not found", mapname); | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if ((status & MAPSTATUS_DISABLED) == MAPSTATUS_DISABLED) | ||||||
|  | 	{ | ||||||
|  | 		if ((status & MAPSTATUS_EXCLUDE_CURRENT) == MAPSTATUS_EXCLUDE_CURRENT) | ||||||
|  | 		{ | ||||||
|  | 			CReplyToCommand(client, "[NE] %t", "Can't Nominate Current Map"); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if ((status & MAPSTATUS_EXCLUDE_PREVIOUS) == MAPSTATUS_EXCLUDE_PREVIOUS) | ||||||
|  | 		{ | ||||||
|  | 			CReplyToCommand(client, "[NE] %t", "Map in Exclude List"); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if ((status & MAPSTATUS_EXCLUDE_NOMINATED) == MAPSTATUS_EXCLUDE_NOMINATED) | ||||||
|  | 		{ | ||||||
|  | 			CReplyToCommand(client, "[NE] %t", "Map Already Nominated"); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	new NominateResult:result = NominateMap(mapname, false, client); | ||||||
|  | 
 | ||||||
|  | 	if (result > Nominate_Replaced) | ||||||
|  | 	{ | ||||||
|  | 		if (result == Nominate_AlreadyInVote) | ||||||
|  | 		{ | ||||||
|  | 			CReplyToCommand(client, "[NE] %t", "Map Already In Vote", mapname); | ||||||
|  | 		} | ||||||
|  | 		else if (result == Nominate_VoteFull) | ||||||
|  | 		{ | ||||||
|  | 			CReplyToCommand(client, "[ME] %t", "Max Nominations"); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* Map was nominated! - Disable the menu item and update the trie */ | ||||||
|  | 
 | ||||||
|  | 	SetTrieValue(g_mapTrie, mapname, MAPSTATUS_DISABLED|MAPSTATUS_EXCLUDE_NOMINATED); | ||||||
|  | 
 | ||||||
|  | 	decl String:name[MAX_NAME_LENGTH]; | ||||||
|  | 	GetClientName(client, name, sizeof(name)); | ||||||
|  | 
 | ||||||
|  | 	if(result == Nominate_Added) | ||||||
|  | 		PrintToChatAll("[NE] %t", "Map Nominated", name, mapname); | ||||||
|  | 	else if(result == Nominate_Replaced) | ||||||
|  | 		PrintToChatAll("[NE] %t", "Map Nomination Changed", name, mapname); | ||||||
|  | 
 | ||||||
|  | 	LogMessage("%s nominated %s", name, mapname); | ||||||
|  | 
 | ||||||
|  | 	g_Player_NominationDelay[client] = GetTime() + GetConVarInt(g_Cvar_NominateDelay); | ||||||
|  | 
 | ||||||
|  | 	return Plugin_Continue; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public Action:Command_NominateList(client, args) | ||||||
|  | { | ||||||
|  | 	new arraySize = ByteCountToCells(PLATFORM_MAX_PATH); | ||||||
|  | 	new Handle:MapList = CreateArray(arraySize); | ||||||
|  | 	GetNominatedMapList(MapList); | ||||||
|  | 	if (!GetArraySize(MapList)) | ||||||
|  | 	{ | ||||||
|  | 		CReplyToCommand(client, "[NE] No maps have been nominated."); | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	new Handle:NominateListMenu = CreateMenu(Handler_NominateListMenu, MENU_ACTIONS_DEFAULT|MenuAction_DisplayItem); | ||||||
|  | 
 | ||||||
|  | 	decl String:map[PLATFORM_MAX_PATH]; | ||||||
|  | 	for (new i = 0; i < GetArraySize(MapList); i++) | ||||||
|  | 	{ | ||||||
|  | 		GetArrayString(MapList, i, map, sizeof(map)); | ||||||
|  | 		AddMenuItem(NominateListMenu, map, map); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	SetMenuTitle(NominateListMenu, "Nominated Maps", client); | ||||||
|  | 	DisplayMenu(NominateListMenu, client, MENU_TIME_FOREVER); | ||||||
|  | 
 | ||||||
|  | 	return Plugin_Handled; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public Handler_NominateListMenu(Handle:menu, MenuAction:action, param1, param2) | ||||||
|  | { | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | AttemptNominate(client) | ||||||
|  | { | ||||||
|  | 	SetMenuTitle(g_MapMenu, "%T", "Nominate Title", client); | ||||||
|  | 	DisplayMenu(g_MapMenu, client, MENU_TIME_FOREVER); | ||||||
|  | 
 | ||||||
|  | 	return; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | AttemptAdminNominate(client) | ||||||
|  | { | ||||||
|  | 	SetMenuTitle(g_AdminMapMenu, "%T", "Nominate Title", client); | ||||||
|  | 	DisplayMenu(g_AdminMapMenu, client, MENU_TIME_FOREVER); | ||||||
|  | 
 | ||||||
|  | 	return; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BuildMapMenu() | ||||||
|  | { | ||||||
|  | 	if (g_MapMenu != INVALID_HANDLE) | ||||||
|  | 	{ | ||||||
|  | 		CloseHandle(g_MapMenu); | ||||||
|  | 		g_MapMenu = INVALID_HANDLE; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	ClearTrie(g_mapTrie); | ||||||
|  | 
 | ||||||
|  | 	g_MapMenu = CreateMenu(Handler_MapSelectMenu, MENU_ACTIONS_DEFAULT|MenuAction_DrawItem|MenuAction_DisplayItem); | ||||||
|  | 
 | ||||||
|  | 	decl String:map[PLATFORM_MAX_PATH]; | ||||||
|  | 
 | ||||||
|  | 	new Handle:excludeMaps = INVALID_HANDLE; | ||||||
|  | 	decl String:currentMap[32]; | ||||||
|  | 
 | ||||||
|  | 	if (GetConVarBool(g_Cvar_ExcludeOld)) | ||||||
|  | 	{ | ||||||
|  | 		excludeMaps = CreateArray(ByteCountToCells(PLATFORM_MAX_PATH)); | ||||||
|  | 		GetExcludeMapList(excludeMaps); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (GetConVarBool(g_Cvar_ExcludeCurrent)) | ||||||
|  | 	{ | ||||||
|  | 		GetCurrentMap(currentMap, sizeof(currentMap)); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	for (new i = 0; i < GetArraySize(g_MapList); i++) | ||||||
|  | 	{ | ||||||
|  | 		new status = MAPSTATUS_ENABLED; | ||||||
|  | 
 | ||||||
|  | 		GetArrayString(g_MapList, i, map, sizeof(map)); | ||||||
|  | 
 | ||||||
|  | 		if (GetConVarBool(g_Cvar_ExcludeCurrent)) | ||||||
|  | 		{ | ||||||
|  | 			if (StrEqual(map, currentMap)) | ||||||
|  | 			{ | ||||||
|  | 				status = MAPSTATUS_DISABLED|MAPSTATUS_EXCLUDE_CURRENT; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		/* Dont bother with this check if the current map check passed */ | ||||||
|  | 		if (GetConVarBool(g_Cvar_ExcludeOld) && status == MAPSTATUS_ENABLED) | ||||||
|  | 		{ | ||||||
|  | 			if (FindStringInArray(excludeMaps, map) != -1) | ||||||
|  | 			{ | ||||||
|  | 				status = MAPSTATUS_DISABLED|MAPSTATUS_EXCLUDE_PREVIOUS; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		AddMenuItem(g_MapMenu, map, map); | ||||||
|  | 		SetTrieValue(g_mapTrie, map, status); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	SetMenuExitButton(g_MapMenu, true); | ||||||
|  | 
 | ||||||
|  | 	if (excludeMaps != INVALID_HANDLE) | ||||||
|  | 	{ | ||||||
|  | 		CloseHandle(excludeMaps); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BuildAdminMapMenu() | ||||||
|  | { | ||||||
|  | 	if (g_AdminMapMenu != INVALID_HANDLE) | ||||||
|  | 	{ | ||||||
|  | 		CloseHandle(g_AdminMapMenu); | ||||||
|  | 		g_AdminMapMenu = INVALID_HANDLE; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	g_AdminMapMenu = CreateMenu(Handler_AdminMapSelectMenu, MENU_ACTIONS_DEFAULT|MenuAction_DrawItem|MenuAction_DisplayItem); | ||||||
|  | 
 | ||||||
|  | 	decl String:map[PLATFORM_MAX_PATH]; | ||||||
|  | 
 | ||||||
|  | 	for (new i = 0; i < GetArraySize(g_AdminMapList); i++) | ||||||
|  | 	{ | ||||||
|  | 		GetArrayString(g_AdminMapList, i, map, sizeof(map)); | ||||||
|  | 
 | ||||||
|  | 		AddMenuItem(g_AdminMapMenu, map, map); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	SetMenuExitButton(g_AdminMapMenu, true); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public Handler_MapSelectMenu(Handle:menu, MenuAction:action, param1, param2) | ||||||
|  | { | ||||||
|  | 	switch (action) | ||||||
|  | 	{ | ||||||
|  | 		case MenuAction_Select: | ||||||
|  | 		{ | ||||||
|  | 			decl String:map[PLATFORM_MAX_PATH], String:name[MAX_NAME_LENGTH]; | ||||||
|  | 			GetMenuItem(menu, param2, map, sizeof(map)); | ||||||
|  | 
 | ||||||
|  | 			GetClientName(param1, name, MAX_NAME_LENGTH); | ||||||
|  | 
 | ||||||
|  | 			new NominateResult:result = NominateMap(map, false, param1); | ||||||
|  | 
 | ||||||
|  | 			/* Don't need to check for InvalidMap because the menu did that already */ | ||||||
|  | 			if (result == Nominate_AlreadyInVote) | ||||||
|  | 			{ | ||||||
|  | 				PrintToChat(param1, "[NE] %t", "Map Already Nominated"); | ||||||
|  | 				return 0; | ||||||
|  | 			} | ||||||
|  | 			else if (result == Nominate_VoteFull) | ||||||
|  | 			{ | ||||||
|  | 				PrintToChat(param1, "[NE] %t", "Max Nominations"); | ||||||
|  | 				return 0; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			SetTrieValue(g_mapTrie, map, MAPSTATUS_DISABLED|MAPSTATUS_EXCLUDE_NOMINATED); | ||||||
|  | 
 | ||||||
|  | 			if(result == Nominate_Added) | ||||||
|  | 				PrintToChatAll("[NE] %t", "Map Nominated", name, map); | ||||||
|  | 			else if(result == Nominate_Replaced) | ||||||
|  | 				PrintToChatAll("[NE] %t", "Map Nomination Changed", name, map); | ||||||
|  | 
 | ||||||
|  | 			LogMessage("%s nominated %s", name, map); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		case MenuAction_DrawItem: | ||||||
|  | 		{ | ||||||
|  | 			decl String:map[PLATFORM_MAX_PATH]; | ||||||
|  | 			GetMenuItem(menu, param2, map, sizeof(map)); | ||||||
|  | 
 | ||||||
|  | 			new status; | ||||||
|  | 
 | ||||||
|  | 			if (!GetTrieValue(g_mapTrie, map, status)) | ||||||
|  | 			{ | ||||||
|  | 				LogError("Menu selection of item not in trie. Major logic problem somewhere."); | ||||||
|  | 				return ITEMDRAW_DEFAULT; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			if ((status & MAPSTATUS_DISABLED) == MAPSTATUS_DISABLED) | ||||||
|  | 			{ | ||||||
|  | 				return ITEMDRAW_DISABLED; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			return ITEMDRAW_DEFAULT; | ||||||
|  | 
 | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		case MenuAction_DisplayItem: | ||||||
|  | 		{ | ||||||
|  | 			decl String:map[PLATFORM_MAX_PATH]; | ||||||
|  | 			GetMenuItem(menu, param2, map, sizeof(map)); | ||||||
|  | 
 | ||||||
|  | 			new mark = GetConVarInt(g_Cvar_MarkCustomMaps); | ||||||
|  | 			new bool:official; | ||||||
|  | 
 | ||||||
|  | 			new status; | ||||||
|  | 
 | ||||||
|  | 			if (!GetTrieValue(g_mapTrie, map, status)) | ||||||
|  | 			{ | ||||||
|  | 				LogError("Menu selection of item not in trie. Major logic problem somewhere."); | ||||||
|  | 				return 0; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			decl String:buffer[100]; | ||||||
|  | 			decl String:display[150]; | ||||||
|  | 
 | ||||||
|  | 			if (mark) | ||||||
|  | 			{ | ||||||
|  | 				official = IsMapOfficial(map); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			if (mark && !official) | ||||||
|  | 			{ | ||||||
|  | 				switch (mark) | ||||||
|  | 				{ | ||||||
|  | 					case 1: | ||||||
|  | 					{ | ||||||
|  | 						Format(buffer, sizeof(buffer), "%T", "Custom Marked", param1, map); | ||||||
|  | 					} | ||||||
|  | 
 | ||||||
|  | 					case 2: | ||||||
|  | 					{ | ||||||
|  | 						Format(buffer, sizeof(buffer), "%T", "Custom", param1, map); | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			else | ||||||
|  | 			{ | ||||||
|  | 				strcopy(buffer, sizeof(buffer), map); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			if ((status & MAPSTATUS_DISABLED) == MAPSTATUS_DISABLED) | ||||||
|  | 			{ | ||||||
|  | 				if ((status & MAPSTATUS_EXCLUDE_CURRENT) == MAPSTATUS_EXCLUDE_CURRENT) | ||||||
|  | 				{ | ||||||
|  | 					Format(display, sizeof(display), "%s (%T)", buffer, "Current Map", param1); | ||||||
|  | 					return RedrawMenuItem(display); | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				if ((status & MAPSTATUS_EXCLUDE_PREVIOUS) == MAPSTATUS_EXCLUDE_PREVIOUS) | ||||||
|  | 				{ | ||||||
|  | 					Format(display, sizeof(display), "%s (%T)", buffer, "Recently Played", param1); | ||||||
|  | 					return RedrawMenuItem(display); | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				if ((status & MAPSTATUS_EXCLUDE_NOMINATED) == MAPSTATUS_EXCLUDE_NOMINATED) | ||||||
|  | 				{ | ||||||
|  | 					Format(display, sizeof(display), "%s (%T)", buffer, "Nominated", param1); | ||||||
|  | 					return RedrawMenuItem(display); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			if (mark && !official) | ||||||
|  | 				return RedrawMenuItem(buffer); | ||||||
|  | 
 | ||||||
|  | 			return 0; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | stock bool:IsNominateAllowed(client) | ||||||
|  | { | ||||||
|  | 	new CanNominateResult:result = CanNominate(); | ||||||
|  | 
 | ||||||
|  | 	switch(result) | ||||||
|  | 	{ | ||||||
|  | 		case CanNominate_No_VoteInProgress: | ||||||
|  | 		{ | ||||||
|  | 			CReplyToCommand(client, "[ME] %t", "Nextmap Voting Started"); | ||||||
|  | 			return false; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		case CanNominate_No_VoteComplete: | ||||||
|  | 		{ | ||||||
|  | 			new String:map[PLATFORM_MAX_PATH]; | ||||||
|  | 			GetNextMap(map, sizeof(map)); | ||||||
|  | 			CReplyToCommand(client, "[NE] %t", "Next Map", map); | ||||||
|  | 			return false; | ||||||
|  | 		} | ||||||
|  | /* | ||||||
|  | 		case CanNominate_No_VoteFull: | ||||||
|  | 		{ | ||||||
|  | 			CReplyToCommand(client, "[ME] %t", "Max Nominations"); | ||||||
|  | 			return false; | ||||||
|  | 		} | ||||||
|  | */ | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public Handler_AdminMapSelectMenu(Handle:menu, MenuAction:action, param1, param2) | ||||||
|  | { | ||||||
|  | 	switch (action) | ||||||
|  | 	{ | ||||||
|  | 		case MenuAction_Select: | ||||||
|  | 		{ | ||||||
|  | 			decl String:map[PLATFORM_MAX_PATH], String:name[MAX_NAME_LENGTH]; | ||||||
|  | 			GetMenuItem(menu, param2, map, sizeof(map)); | ||||||
|  | 
 | ||||||
|  | 			new NominateResult:result = NominateMap(map, false, 0); | ||||||
|  | 
 | ||||||
|  | 			if (result == Nominate_AlreadyInVote) | ||||||
|  | 			{ | ||||||
|  | 				PrintToChat(param1, "[NE] %t", "Map Already In Vote", map); | ||||||
|  | 				return 0; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			SetTrieValue(g_mapTrie, map, MAPSTATUS_DISABLED|MAPSTATUS_EXCLUDE_NOMINATED); | ||||||
|  | 
 | ||||||
|  | 			PrintToChat(param1, "[NE] %t", "Map Inserted", map); | ||||||
|  | 			LogAction(param1, -1, "\"%L\" inserted map \"%s\".", param1, map); | ||||||
|  | 
 | ||||||
|  | 			PrintToChatAll("[NE] %N has inserted %s into nominations", name, map); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
							
								
								
									
										378
									
								
								mapchooser_extended/scripting/rockthevote_extended.sp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										378
									
								
								mapchooser_extended/scripting/rockthevote_extended.sp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,378 @@ | |||||||
|  | /** | ||||||
|  |  * vim: set ts=4 : | ||||||
|  |  * ============================================================================= | ||||||
|  |  * Rock The Vote Extended | ||||||
|  |  * Creates a map vote when the required number of players have requested one. | ||||||
|  |  * | ||||||
|  |  * Rock The Vote Extended (C)2012-2013 Powerlord (Ross Bemrose) | ||||||
|  |  * SourceMod (C)2004-2007 AlliedModders LLC.  All rights reserved. | ||||||
|  |  * ============================================================================= | ||||||
|  |  * | ||||||
|  |  * This program is free software; you can redistribute it and/or modify it under | ||||||
|  |  * the terms of the GNU General Public License, version 3.0, as published by the | ||||||
|  |  * Free Software Foundation. | ||||||
|  |  * | ||||||
|  |  * This program is distributed in the hope that it will be useful, but WITHOUT | ||||||
|  |  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||||||
|  |  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more | ||||||
|  |  * details. | ||||||
|  |  * | ||||||
|  |  * You should have received a copy of the GNU General Public License along with | ||||||
|  |  * this program.  If not, see <http://www.gnu.org/licenses/>. | ||||||
|  |  * | ||||||
|  |  * As a special exception, AlliedModders LLC gives you permission to link the | ||||||
|  |  * code of this program (as well as its derivative works) to "Half-Life 2," the | ||||||
|  |  * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software | ||||||
|  |  * by the Valve Corporation.  You must obey the GNU General Public License in | ||||||
|  |  * all respects for all other code used.  Additionally, AlliedModders LLC grants | ||||||
|  |  * this exception to all derivative works.  AlliedModders LLC defines further | ||||||
|  |  * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), | ||||||
|  |  * or <http://www.sourcemod.net/license.php>. | ||||||
|  |  * | ||||||
|  |  * Version: $Id$ | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include <sourcemod> | ||||||
|  | #include <sdktools> | ||||||
|  | #include <sdkhooks> | ||||||
|  | #include <mapchooser> | ||||||
|  | #include "include/mapchooser_extended" | ||||||
|  | #include <nextmap> | ||||||
|  | #include <colors> | ||||||
|  | 
 | ||||||
|  | #pragma semicolon 1 | ||||||
|  | 
 | ||||||
|  | #define MCE_VERSION "1.10.0" | ||||||
|  | 
 | ||||||
|  | public Plugin:myinfo = | ||||||
|  | { | ||||||
|  | 	name = "Rock The Vote Extended", | ||||||
|  | 	author = "Powerlord and AlliedModders LLC", | ||||||
|  | 	description = "Provides RTV Map Voting", | ||||||
|  | 	version = MCE_VERSION, | ||||||
|  | 	url = "https://forums.alliedmods.net/showthread.php?t=156974" | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | new Handle:g_Cvar_Needed = INVALID_HANDLE; | ||||||
|  | new Handle:g_Cvar_MinPlayers = INVALID_HANDLE; | ||||||
|  | new Handle:g_Cvar_InitialDelay = INVALID_HANDLE; | ||||||
|  | new Handle:g_Cvar_Interval = INVALID_HANDLE; | ||||||
|  | new Handle:g_Cvar_ChangeTime = INVALID_HANDLE; | ||||||
|  | new Handle:g_Cvar_RTVPostVoteAction = INVALID_HANDLE; | ||||||
|  | 
 | ||||||
|  | new bool:g_CanRTV = false;		// True if RTV loaded maps and is active. | ||||||
|  | new bool:g_RTVAllowed = false;	// True if RTV is available to players. Used to delay rtv votes. | ||||||
|  | new g_Voters = 0;				// Total voters connected. Doesn't include fake clients. | ||||||
|  | new g_Votes = 0;				// Total number of "say rtv" votes | ||||||
|  | new g_VotesNeeded = 0;			// Necessary votes before map vote begins. (voters * percent_needed) | ||||||
|  | new bool:g_Voted[MAXPLAYERS+1] = {false, ...}; | ||||||
|  | 
 | ||||||
|  | new bool:g_InChange = false; | ||||||
|  | 
 | ||||||
|  | public OnPluginStart() | ||||||
|  | { | ||||||
|  | 	LoadTranslations("common.phrases"); | ||||||
|  | 	LoadTranslations("rockthevote.phrases"); | ||||||
|  | 	LoadTranslations("basevotes.phrases"); | ||||||
|  | 
 | ||||||
|  | 	g_Cvar_Needed = CreateConVar("sm_rtv_needed", "0.60", "Percentage of players needed to rockthevote (Def 60%)", 0, true, 0.05, true, 1.0); | ||||||
|  | 	g_Cvar_MinPlayers = CreateConVar("sm_rtv_minplayers", "0", "Number of players required before RTV will be enabled.", 0, true, 0.0, true, float(MAXPLAYERS)); | ||||||
|  | 	g_Cvar_InitialDelay = CreateConVar("sm_rtv_initialdelay", "30.0", "Time (in seconds) before first RTV can be held", 0, true, 0.00); | ||||||
|  | 	g_Cvar_Interval = CreateConVar("sm_rtv_interval", "240.0", "Time (in seconds) after a failed RTV before another can be held", 0, true, 0.00); | ||||||
|  | 	g_Cvar_ChangeTime = CreateConVar("sm_rtv_changetime", "0", "When to change the map after a succesful RTV: 0 - Instant, 1 - RoundEnd, 2 - MapEnd", _, true, 0.0, true, 2.0); | ||||||
|  | 	g_Cvar_RTVPostVoteAction = CreateConVar("sm_rtv_postvoteaction", "0", "What to do with RTV's after a mapvote has completed. 0 - Allow, success = instant change, 1 - Deny", _, true, 0.0, true, 1.0); | ||||||
|  | 
 | ||||||
|  | 	HookEvent("player_team", OnPlayerChangedTeam); | ||||||
|  | 
 | ||||||
|  | 	RegConsoleCmd("say", Command_Say); | ||||||
|  | 	RegConsoleCmd("say_team", Command_Say); | ||||||
|  | 
 | ||||||
|  | 	RegConsoleCmd("sm_rtv", Command_RTV); | ||||||
|  | 
 | ||||||
|  | 	RegAdminCmd("sm_forcertv", Command_ForceRTV, ADMFLAG_CHANGEMAP, "Force an RTV vote"); | ||||||
|  | 	RegAdminCmd("mce_forcertv", Command_ForceRTV, ADMFLAG_CHANGEMAP, "Force an RTV vote"); | ||||||
|  | 
 | ||||||
|  | 	// Rock The Vote Extended cvars | ||||||
|  | 	CreateConVar("rtve_version", MCE_VERSION, "Rock The Vote Extended Version", FCVAR_SPONLY|FCVAR_NOTIFY|FCVAR_DONTRECORD); | ||||||
|  | 
 | ||||||
|  | 	AutoExecConfig(true, "rtv"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public OnMapStart() | ||||||
|  | { | ||||||
|  | 	g_Voters = 0; | ||||||
|  | 	g_Votes = 0; | ||||||
|  | 	g_VotesNeeded = 0; | ||||||
|  | 	g_InChange = false; | ||||||
|  | 
 | ||||||
|  | 	/* Handle late load */ | ||||||
|  | 	for (new i=1; i<=MaxClients; i++) | ||||||
|  | 	{ | ||||||
|  | 		if (IsClientConnected(i)) | ||||||
|  | 		{ | ||||||
|  | 			OnClientConnected(i); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public OnMapEnd() | ||||||
|  | { | ||||||
|  | 	g_CanRTV = false; | ||||||
|  | 	g_RTVAllowed = false; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public OnConfigsExecuted() | ||||||
|  | { | ||||||
|  | 	g_CanRTV = true; | ||||||
|  | 	g_RTVAllowed = false; | ||||||
|  | 	CreateTimer(GetConVarFloat(g_Cvar_InitialDelay), Timer_DelayRTV, _, TIMER_FLAG_NO_MAPCHANGE); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public OnClientConnected(client) | ||||||
|  | { | ||||||
|  | 	if(IsFakeClient(client)) | ||||||
|  | 		return; | ||||||
|  | 
 | ||||||
|  | 	g_Voted[client] = false; | ||||||
|  | 
 | ||||||
|  | 	g_Voters = GetTeamClientCount(2) + GetTeamClientCount(3); | ||||||
|  | 	g_VotesNeeded = RoundToFloor(float(g_Voters) * GetConVarFloat(g_Cvar_Needed)); | ||||||
|  | 
 | ||||||
|  | 	return; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public OnClientDisconnect(client) | ||||||
|  | { | ||||||
|  | 	if(IsFakeClient(client)) | ||||||
|  | 		return; | ||||||
|  | 
 | ||||||
|  | 	if(g_Voted[client]) | ||||||
|  | 	{ | ||||||
|  | 		g_Votes--; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	g_Voters = GetTeamClientCount(2) + GetTeamClientCount(3); | ||||||
|  | 
 | ||||||
|  | 	g_VotesNeeded = RoundToFloor(float(g_Voters) * GetConVarFloat(g_Cvar_Needed)); | ||||||
|  | 
 | ||||||
|  | 	if (!g_CanRTV) | ||||||
|  | 	{ | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (g_Votes && | ||||||
|  | 		g_Voters && | ||||||
|  | 		g_Votes >= g_VotesNeeded && | ||||||
|  | 		g_RTVAllowed ) | ||||||
|  | 	{ | ||||||
|  | 		if (GetConVarInt(g_Cvar_RTVPostVoteAction) == 1 && HasEndOfMapVoteFinished()) | ||||||
|  | 		{ | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		StartRTV(); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public OnPlayerChangedTeam(Handle:event, const String:name[], bool:dontBroadcast) | ||||||
|  | { | ||||||
|  | 	new Client = GetClientOfUserId(GetEventInt(event, "userid")); | ||||||
|  | 
 | ||||||
|  | 	if(IsFakeClient(Client)) | ||||||
|  | 		return; | ||||||
|  | 
 | ||||||
|  | 	if(Client == 0) | ||||||
|  | 	{ | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (IsClientInGame(Client) && IsClientConnected(Client)) | ||||||
|  | 	{ | ||||||
|  | 		if (GetClientTeam(Client) == 1) | ||||||
|  | 		{ | ||||||
|  | 			g_Voters = GetTeamClientCount(2) + GetTeamClientCount(3); | ||||||
|  | 			g_VotesNeeded = RoundToFloor(float(g_Voters) * GetConVarFloat(g_Cvar_Needed)); | ||||||
|  | 
 | ||||||
|  | 			if (g_Votes && | ||||||
|  | 				g_Voters && | ||||||
|  | 				g_Votes >= g_VotesNeeded && | ||||||
|  | 				g_RTVAllowed ) | ||||||
|  | 			{ | ||||||
|  | 				if (GetConVarInt(g_Cvar_RTVPostVoteAction) == 1 && HasEndOfMapVoteFinished()) | ||||||
|  | 				{ | ||||||
|  | 					return; | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				StartRTV(); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public Action:Command_RTV(client, args) | ||||||
|  | { | ||||||
|  | 	if (!g_CanRTV || !client) | ||||||
|  | 	{ | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	AttemptRTV(client); | ||||||
|  | 
 | ||||||
|  | 	return Plugin_Handled; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public Action:Command_Say(client, args) | ||||||
|  | { | ||||||
|  | 	if (!g_CanRTV || !client) | ||||||
|  | 	{ | ||||||
|  | 		return Plugin_Continue; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	decl String:text[192]; | ||||||
|  | 	if (!GetCmdArgString(text, sizeof(text))) | ||||||
|  | 	{ | ||||||
|  | 		return Plugin_Continue; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	new startidx = 0; | ||||||
|  | 	if(text[strlen(text)-1] == '"') | ||||||
|  | 	{ | ||||||
|  | 		text[strlen(text)-1] = '\0'; | ||||||
|  | 		startidx = 1; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	new ReplySource:old = SetCmdReplySource(SM_REPLY_TO_CHAT); | ||||||
|  | 
 | ||||||
|  | 	if (strcmp(text[startidx], "rtv", false) == 0 || strcmp(text[startidx], "rockthevote", false) == 0) | ||||||
|  | 	{ | ||||||
|  | 		AttemptRTV(client); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	SetCmdReplySource(old); | ||||||
|  | 
 | ||||||
|  | 	return Plugin_Continue; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | AttemptRTV(client) | ||||||
|  | { | ||||||
|  | 	if (!g_RTVAllowed  || (GetConVarInt(g_Cvar_RTVPostVoteAction) == 1 && HasEndOfMapVoteFinished())) | ||||||
|  | 	{ | ||||||
|  | 		CReplyToCommand(client, "[SM] %t", "RTV Not Allowed"); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (!CanMapChooserStartVote()) | ||||||
|  | 	{ | ||||||
|  | 		CReplyToCommand(client, "[SM] %t", "RTV Started"); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (GetClientCount(true) < GetConVarInt(g_Cvar_MinPlayers)) | ||||||
|  | 	{ | ||||||
|  | 		CReplyToCommand(client, "[SM] %t", "Minimal Players Not Met"); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (g_Voted[client]) | ||||||
|  | 	{ | ||||||
|  | 		CReplyToCommand(client, "[SM] %t", "Already Voted", g_Votes, g_VotesNeeded); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	new String:name[MAX_NAME_LENGTH]; | ||||||
|  | 	GetClientName(client, name, sizeof(name)); | ||||||
|  | 
 | ||||||
|  | 	g_Votes++; | ||||||
|  | 	g_Voted[client] = true; | ||||||
|  | 
 | ||||||
|  | 	CPrintToChatAll("[SM] %t", "RTV Requested", name, g_Votes, g_VotesNeeded); | ||||||
|  | 
 | ||||||
|  | 	if (g_Votes >= g_VotesNeeded) | ||||||
|  | 	{ | ||||||
|  | 		StartRTV(); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public Action:Timer_DelayRTV(Handle:timer) | ||||||
|  | { | ||||||
|  | 	g_RTVAllowed = true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | StartRTV() | ||||||
|  | { | ||||||
|  | 	if (g_InChange) | ||||||
|  | 	{ | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (EndOfMapVoteEnabled() && HasEndOfMapVoteFinished()) | ||||||
|  | 	{ | ||||||
|  | 		/* Change right now then */ | ||||||
|  | 		new String:map[PLATFORM_MAX_PATH]; | ||||||
|  | 		if (GetNextMap(map, sizeof(map))) | ||||||
|  | 		{ | ||||||
|  | 			CPrintToChatAll("[SM] %t", "Changing Maps", map); | ||||||
|  | 			CreateTimer(5.0, Timer_ChangeMap, _, TIMER_FLAG_NO_MAPCHANGE); | ||||||
|  | 			g_InChange = true; | ||||||
|  | 
 | ||||||
|  | 			ResetRTV(); | ||||||
|  | 
 | ||||||
|  | 			g_RTVAllowed = false; | ||||||
|  | 		} | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (CanMapChooserStartVote()) | ||||||
|  | 	{ | ||||||
|  | 		new MapChange:when = MapChange:GetConVarInt(g_Cvar_ChangeTime); | ||||||
|  | 		InitiateMapChooserVote(when); | ||||||
|  | 
 | ||||||
|  | 		ResetRTV(); | ||||||
|  | 
 | ||||||
|  | 		g_RTVAllowed = false; | ||||||
|  | 		CreateTimer(GetConVarFloat(g_Cvar_Interval), Timer_DelayRTV, _, TIMER_FLAG_NO_MAPCHANGE); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ResetRTV() | ||||||
|  | { | ||||||
|  | 	g_Votes = 0; | ||||||
|  | 
 | ||||||
|  | 	for (new i=1; i<=MAXPLAYERS; i++) | ||||||
|  | 	{ | ||||||
|  | 		g_Voted[i] = false; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public Action:Timer_ChangeMap(Handle:hTimer) | ||||||
|  | { | ||||||
|  | 	g_InChange = false; | ||||||
|  | 
 | ||||||
|  | 	LogMessage("RTV changing map manually"); | ||||||
|  | 
 | ||||||
|  | 	new String:map[PLATFORM_MAX_PATH]; | ||||||
|  | 	if (GetNextMap(map, sizeof(map))) | ||||||
|  | 	{ | ||||||
|  | 		ForceChangeLevel(map, "RTV after mapvote"); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return Plugin_Stop; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Rock The Vote Extended functions | ||||||
|  | 
 | ||||||
|  | public Action:Command_ForceRTV(client, args) | ||||||
|  | { | ||||||
|  | 	if (!g_CanRTV || !client) | ||||||
|  | 	{ | ||||||
|  | 		return Plugin_Handled; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	ShowActivity2(client, "[RTVE] ", "%t", "Initiated Vote Map"); | ||||||
|  | 
 | ||||||
|  | 	StartRTV(); | ||||||
|  | 
 | ||||||
|  | 	return Plugin_Handled; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
							
								
								
									
										2
									
								
								mapchooser_extended/translations/chi/incomplete.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								mapchooser_extended/translations/chi/incomplete.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,2 @@ | |||||||
|  | Missing "Runoff Vote Nextmap", "Number Of Votes", "Custom", "Revote Is Needed", "Revote Warning", "Vote Warning", | ||||||
|  | "Line One", "Line Two", "Cannot Start Vote", and "Tie Vote" | ||||||
| @ -0,0 +1,43 @@ | |||||||
|  | "Phrases" | ||||||
|  | { | ||||||
|  | 	"Vote Nextmap" | ||||||
|  | 	{ | ||||||
|  | 		"chi"		"下一幅地图投票了!" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Nextmap Voting Started" | ||||||
|  | 	{ | ||||||
|  | 		"chi"		"下一幅地图投选已开始." | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Nextmap Voting Finished" | ||||||
|  | 	{ | ||||||
|  | 		"chi"		" 地图投票已结束. 下一幅地图将为 {1}. ( 得票{2}%% , {3}票)" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Current Map Extended" | ||||||
|  | 	{ | ||||||
|  | 		"chi"		"当前地图已被延长." | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Extend Map" | ||||||
|  | 	{ | ||||||
|  | 		"chi"		"延长当前地图" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Dont Change" | ||||||
|  | 	{ | ||||||
|  | 		"chi"		"请勿更换" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Current Map Stays" | ||||||
|  | 	{ | ||||||
|  | 		"chi"		"当前地图已被延长! 投票显示! (得票 {1}%% 共 {2} 票)" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Changed Next Map" | ||||||
|  | 	{ | ||||||
|  | 		"chi"		"更换下一幅地图为 \"{1}\"." | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | } | ||||||
							
								
								
									
										2
									
								
								mapchooser_extended/translations/cze/incomplete.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								mapchooser_extended/translations/cze/incomplete.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,2 @@ | |||||||
|  | Missing "Runoff Vote Nextmap", "Number Of Votes", "Custom", "Revote Is Needed", "Revote Warning", "Vote Warning", | ||||||
|  | "Line One", "Line Two", "Cannot Start Vote", and "Tie Vote" | ||||||
| @ -0,0 +1,43 @@ | |||||||
|  | "Phrases" | ||||||
|  | { | ||||||
|  | 	"Vote Nextmap" | ||||||
|  | 	{ | ||||||
|  | 		"cze"		"Hlasujte o příští mapě!" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Nextmap Voting Started" | ||||||
|  | 	{ | ||||||
|  | 		"cze"		"Hlasování o příští mapě začalo." | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Nextmap Voting Finished" | ||||||
|  | 	{ | ||||||
|  | 		"cze"		"Hlasování o mapě skončilo. Příští mapou bude {1}. (Obdržela {2}%% z {3} hlasů)" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Current Map Extended" | ||||||
|  | 	{ | ||||||
|  | 		"cze"		"Současná mapa byla prodloužena. (Obdržela {1}%% z {2} hlasů)" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Extend Map" | ||||||
|  | 	{ | ||||||
|  | 		"cze"		"Prodloužit současnou mapu" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Dont Change" | ||||||
|  | 	{ | ||||||
|  | 		"cze"		"Neměnit" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Current Map Stays" | ||||||
|  | 	{ | ||||||
|  | 		"cze"		"Současná mapa pokračuje! Hlasování rozhodlo! (Obdržela {1}%% z {2} hlasů)" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Changed Next Map" | ||||||
|  | 	{ | ||||||
|  | 		"cze"		"Změnil příští mapu na \"{1}\"." | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | } | ||||||
							
								
								
									
										2
									
								
								mapchooser_extended/translations/da/incomplete.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								mapchooser_extended/translations/da/incomplete.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,2 @@ | |||||||
|  | Missing "Runoff Vote Nextmap", "Number Of Votes", "Custom", "Revote Is Needed", "Revote Warning", "Vote Warning", | ||||||
|  | "Line One", "Line Two", "Cannot Start Vote", and "Tie Vote" | ||||||
| @ -0,0 +1,43 @@ | |||||||
|  | "Phrases" | ||||||
|  | { | ||||||
|  | 	"Vote Nextmap" | ||||||
|  | 	{ | ||||||
|  | 		"da"		"Stem om næste bane!" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Nextmap Voting Started" | ||||||
|  | 	{ | ||||||
|  | 		"da"		"Afstemning for næste bane er begyndt." | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Nextmap Voting Finished" | ||||||
|  | 	{ | ||||||
|  | 		"da"		"Bane afstemning er fuldført. Den næste bane vil være {1}. (Modtog {2}%% af {3} stemmer) " | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Current Map Extended" | ||||||
|  | 	{ | ||||||
|  | 		"da"		"Den nuværende bane er blevet forlænget. (Modtog {1}%% af {2} stemmer)  " | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Extend Map" | ||||||
|  | 	{ | ||||||
|  | 		"da"		"Forlæng bane" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Dont Change" | ||||||
|  | 	{ | ||||||
|  | 		"da"		"Skift ikke!" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Current Map Stays" | ||||||
|  | 	{ | ||||||
|  | 		"da"		"Den aktuelle bane fortsætter! Afstemningen har talt! (Modtog {1}%% af {2} stemmer)" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Changed Next Map" | ||||||
|  | 	{ | ||||||
|  | 		"da"		"Skiftede næste bane til \"{1}'." | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,98 @@ | |||||||
|  | "Phrases" | ||||||
|  | { | ||||||
|  | 	"Vote Nextmap" | ||||||
|  | 	{ | ||||||
|  | 		"de"		"Stimme für die nächste Karte!" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Nextmap Voting Started" | ||||||
|  | 	{ | ||||||
|  | 		"de"		"Abstimmung für die nächste Karte wurde gestartet." | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Nextmap Voting Finished" | ||||||
|  | 	{ | ||||||
|  | 		"de"		"Karten-Abstimmung wurde abgeschlossen. Nächste Karte wird {1} sein. ({2}%% von {3} Stimmen erhalten) " | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Current Map Extended" | ||||||
|  | 	{ | ||||||
|  | 		"de"		"Die aktuelle Karte wurde verlängert. ({1}%% von {2} Stimmen erhalten) " | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Extend Map" | ||||||
|  | 	{ | ||||||
|  | 		"de"		"Verlängere aktuelle Karte" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Dont Change" | ||||||
|  | 	{ | ||||||
|  | 		"de"		"Nicht wechseln" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Current Map Stays" | ||||||
|  | 	{ | ||||||
|  | 		"de"		"Aktuelle Karte geht weiter! Die Abstimmung hat entschieden! ({1}%% von {2} Stimmen erhalten) " | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Changed Next Map" | ||||||
|  | 	{ | ||||||
|  | 		"de"		"Nächste Karte wurde  auf \"{1}\" geändert. " | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Runoff Vote Nextmap" | ||||||
|  | 	{ | ||||||
|  | 		"de"		"Stichwahl für die nächste Karte!" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Number Of Votes" | ||||||
|  | 	{ | ||||||
|  | 		"de"		"Anzahl der Stimmen" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Custom" | ||||||
|  | 	{ | ||||||
|  | 		"de"		"{1} (nicht vorhanden)" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Revote Is Needed" | ||||||
|  | 	{ | ||||||
|  | 		"de"		"Keine Karte hat mehr als {1}%% der Stimmen.\nEine neue Abstimmung ist erforderlich!" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Revote Warning" | ||||||
|  | 	{ | ||||||
|  | 		"de"		"Stichwahl startet in: {1} Sekunden" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Vote Warning" | ||||||
|  | 	{ | ||||||
|  | 		"de"		"Achtung! Die Abstimmung für die nächste Karte startet in: {1} Sekunden" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Line One" | ||||||
|  | 	{ | ||||||
|  | 		"de"		"Überlegen Sie, welche Karte Sie spielen möchten ..." | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Line Two" | ||||||
|  | 	{ | ||||||
|  | 		"de"		"... und nicht unüberlegt wählen!" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Cannot Start Vote" | ||||||
|  | 	{ | ||||||
|  | 		"de"		"Abstimmung ist bereits im Gange. Versuch Sie es erneut in {1} Sekunden" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Tie Vote" | ||||||
|  | 	{ | ||||||
|  | 		"de"		"Die Top-{1} Karten haben gleich viele Stimmen!.\nEine neue Abstimmung ist erforderlich!" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Custom Marked" | ||||||
|  | 	{ | ||||||
|  | 		"de"		"*{1}" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,92 @@ | |||||||
|  | "Phrases" | ||||||
|  | { | ||||||
|  | 	"Vote Nextmap" | ||||||
|  | 	{ | ||||||
|  | 		"es"			"Vota para el siguiente mapa!" | ||||||
|  | 	}	 | ||||||
|  | 
 | ||||||
|  | 	"Nextmap Voting Started" | ||||||
|  | 	{ | ||||||
|  | 		"es"			"La votacion para el siguiente mapa ha comenzado." | ||||||
|  | 	}	 | ||||||
|  | 
 | ||||||
|  | 	"Nextmap Voting Finished" | ||||||
|  | 	{ | ||||||
|  | 		"es"			"Votacion de Mapa finalizado. El siguiente mapa sera {1}. (Recibidos {2}%% de {3} votos)" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Current Map Extended" | ||||||
|  | 	{ | ||||||
|  | 		"es"			"El mapa actual ha sido extendido. (Recibidos {1}%% de {2} votos)" | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	"Extend Map" | ||||||
|  | 	{ | ||||||
|  | 		"es"			"Extender mapa actual" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Dont Change" | ||||||
|  | 	{ | ||||||
|  | 		"es"			"No cambiar" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Current Map Stays" | ||||||
|  | 	{ | ||||||
|  | 		"es"			"El mapa actual continua! La votacion ha hablado! (Recibidos {1}%% de {2} votos)" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Changed Next Map" | ||||||
|  | 	{ | ||||||
|  | 		"es"		"El siguiente mapa ha cambiado a \"{1}\"."	 | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Runoff Vote Nextmap" | ||||||
|  | 	{ | ||||||
|  | 		"es"		"Hacer votacion para el siguiente mapa!" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Number Of Votes" | ||||||
|  | 	{ | ||||||
|  | 		"es"		"Numero de Votaciones" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Custom" | ||||||
|  | 	{ | ||||||
|  | 		"es"		"{1} (Custom)" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Revote Is Needed" | ||||||
|  | 	{ | ||||||
|  | 		"es"		"No hay ningun mapa que haya recibido el {1}%% de votaciones.\nEntonces, que mapa ganara? Es necesario otra votacion!" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Revote Warning" | ||||||
|  | 	{ | ||||||
|  | 		"es"		"La votacion empezara en: {1}s" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Vote Warning" | ||||||
|  | 	{ | ||||||
|  | 		"es"		"Atencion! La votacion para el siguiente mapa se iniciara en: {1}s" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Line One" | ||||||
|  | 	{ | ||||||
|  | 		"es"		"Considera que mapa quieres jugar..." | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Line Two" | ||||||
|  | 	{ | ||||||
|  | 		"es"		"...y no pulse los botones sin pensar ;-)" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Cannot Start Vote" | ||||||
|  | 	{ | ||||||
|  | 		"es"		"Votacion ya iniciada.  Intentando de nuevo en {1}s." | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Tie Vote" | ||||||
|  | 	{ | ||||||
|  | 		"es"		"El top {1} de mapas tienen el mismo numero de votaciones.\nSe necesita una nueva votacion!" | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @ -0,0 +1,87 @@ | |||||||
|  | "Phrases" | ||||||
|  | { | ||||||
|  | 	"Vote Nextmap" | ||||||
|  | 	{ | ||||||
|  | 		"fr"            "Voter pour la prochaine map!" | ||||||
|  | 	}	 | ||||||
|  | 
 | ||||||
|  | 	"Nextmap Voting Started" | ||||||
|  | 	{ | ||||||
|  | 		"fr"            "Voter pour la prochaine map est lancer." | ||||||
|  | 	}	 | ||||||
|  | 
 | ||||||
|  | 	"Nextmap Voting Finished" | ||||||
|  | 	{ | ||||||
|  | 		"fr"            "Le VoteMap est terminer. La prochaine map sera {1}. (Reçu {2}%% sur {3} votes)" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Current Map Extended" | ||||||
|  | 	{ | ||||||
|  | 		"fr"            "La map actuelle a été prolonger. (Reçu {1}%% sur {2} votes)" | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	"Extend Map" | ||||||
|  | 	{ | ||||||
|  | 		"fr"            "Prolonger la map" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Dont Change" | ||||||
|  | 	{ | ||||||
|  | 		"fr"            "Ne pas changer" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Current Map Stays" | ||||||
|  | 	{ | ||||||
|  | 		"fr"			"La map continue! Le vote a tranché! (Reçu {1}%% sur {2} votes)" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Changed Next Map" | ||||||
|  | 	{ | ||||||
|  | 		"fr"        "La map suivante sera \"{1}\"." | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Runoff Vote Nextmap" | ||||||
|  | 	{ | ||||||
|  | 		"fr"        "Votez a nouveau pour la prochaine Map!" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Number Of Votes" | ||||||
|  | 	{ | ||||||
|  | 		"fr"		"Nombres de votes" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Custom" | ||||||
|  | 	{ | ||||||
|  | 		"fr"        "{1} (Custom)" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Revote Is Needed" | ||||||
|  | 	{ | ||||||
|  | 		"fr"		"Aucune map n'a reçu plus de {1}%% du vote.\nAlors, quels maps va gagner? Un nouveau vote va être lancé!" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Revote Warning" | ||||||
|  | 	{ | ||||||
|  | 		"fr"		"Un nouveau vote commence dans: {1}s" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Vote Warning" | ||||||
|  | 	{ | ||||||
|  | 		"fr"        "Attention! Le vote pour la prochaine map commence dans: {1}s" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Line One" | ||||||
|  | 	{ | ||||||
|  | 		"fr"		"Voter pour la map que vous voulez jouer..." | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Line Two" | ||||||
|  | 	{ | ||||||
|  | 		"fr"		"...et ne pas cliquez sur une touche comme un con ;-)" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Cannot Start Vote" | ||||||
|  | 	{ | ||||||
|  | 		"fr"        "Vote déjà en cours.  Reassayer dans {1}s." | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @ -0,0 +1,92 @@ | |||||||
|  | "Phrases" | ||||||
|  | { | ||||||
|  | 	"Vote Nextmap" | ||||||
|  | 	{ | ||||||
|  | 		"fr"            "Votez pour la prochaine map!" | ||||||
|  | 	}	 | ||||||
|  | 
 | ||||||
|  | 	"Nextmap Voting Started" | ||||||
|  | 	{ | ||||||
|  | 		"fr"            "Le vote pour la prochaine map est lancé." | ||||||
|  | 	}	 | ||||||
|  | 
 | ||||||
|  | 	"Nextmap Voting Finished" | ||||||
|  | 	{ | ||||||
|  | 		"fr"            "Le VoteMap est terminé. La prochaine map sera {1}. (Reçu {2}%% sur {3} votes)" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Current Map Extended" | ||||||
|  | 	{ | ||||||
|  | 		"fr"            "La map actuelle a été prolongée. (Reçu {1}%% sur {2} votes)" | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	"Extend Map" | ||||||
|  | 	{ | ||||||
|  | 		"fr"            "Prolonger la map" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Dont Change" | ||||||
|  | 	{ | ||||||
|  | 		"fr"            "Ne pas changer" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Current Map Stays" | ||||||
|  | 	{ | ||||||
|  | 		"fr"			"La map continue! Le vote a tranché! (Reçu {1}%% sur {2} votes)" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Changed Next Map" | ||||||
|  | 	{ | ||||||
|  | 		"fr"        "La map suivante sera \"{1}\"." | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Runoff Vote Nextmap" | ||||||
|  | 	{ | ||||||
|  | 		"fr"        "Votez à nouveau pour la prochaine Map!" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Number Of Votes" | ||||||
|  | 	{ | ||||||
|  | 		"fr"		"Nombres de votes" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Custom" | ||||||
|  | 	{ | ||||||
|  | 		"fr"        "{1} (Custom)" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Revote Is Needed" | ||||||
|  | 	{ | ||||||
|  | 		"fr"		"Aucune map n'a reçu plus de {1}%% du vote.\nAlors, quelle map va gagner? Un nouveau vote va être lancé!" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Revote Warning" | ||||||
|  | 	{ | ||||||
|  | 		"fr"		"Un nouveau vote commence dans: {1}s" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Vote Warning" | ||||||
|  | 	{ | ||||||
|  | 		"fr"        "Attention! Le vote pour la prochaine map commence dans: {1}s" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Line One" | ||||||
|  | 	{ | ||||||
|  | 		"fr"		"Votez pour la map que vous voulez jouer..." | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Line Two" | ||||||
|  | 	{ | ||||||
|  | 		"fr"		"...et n'appuyez pas sur une touche comme un con ;-)" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Cannot Start Vote" | ||||||
|  | 	{ | ||||||
|  | 		"fr"        "Vote déjà en cours.  Reassayez dans {1}s." | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	"Tie Vote" | ||||||
|  | 	{ | ||||||
|  | 		"fr"		"{1} maps ont eu un même nombre de voix.\nUn nouveau vote est nécessaire!" | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										2
									
								
								mapchooser_extended/translations/hu/incomplete.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								mapchooser_extended/translations/hu/incomplete.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,2 @@ | |||||||
|  | Missing "Runoff Vote Nextmap", "Number Of Votes", "Custom", "Revote Is Needed", "Revote Warning", "Vote Warning", | ||||||
|  | "Line One", "Line Two", "Cannot Start Vote", and "Tie Vote" | ||||||
| @ -0,0 +1,43 @@ | |||||||
|  | "Phrases" | ||||||
|  | { | ||||||
|  | 	"Vote Nextmap" | ||||||
|  | 	{ | ||||||
|  | 		"hu"		"Mi legyen a következő pálya?" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Nextmap Voting Started" | ||||||
|  | 	{ | ||||||
|  | 		"hu"		"Palyavalaszto szavazas elindult!" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Nextmap Voting Finished" | ||||||
|  | 	{ | ||||||
|  | 		"hu"		"A szavazás lezárult. A következő pálya a {1} lesz" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Current Map Extended" | ||||||
|  | 	{ | ||||||
|  | 		"hu"		"Az aktualis palya meghosszabitva." | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Extend Map" | ||||||
|  | 	{ | ||||||
|  | 		"hu"		"Palya meghosszabitasa" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Dont Change" | ||||||
|  | 	{ | ||||||
|  | 		"hu"		"Ne valtsunk!" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Current Map Stays" | ||||||
|  | 	{ | ||||||
|  | 		"hu"		"Jelenlegi palya folytatodik." | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Changed Next Map" | ||||||
|  | 	{ | ||||||
|  | 		"hu"		"\"{1}\" lesz a kovetkezo palya" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,92 @@ | |||||||
|  | "Phrases" | ||||||
|  | { | ||||||
|  | 	"Vote Nextmap" | ||||||
|  | 	{ | ||||||
|  | 		"it"            "Vota per la prossima mappa!" | ||||||
|  | 	}	 | ||||||
|  | 
 | ||||||
|  | 	"Nextmap Voting Started" | ||||||
|  | 	{ | ||||||
|  | 		"it"            "Le votazione per scegliere la prossima mappa sono iniziate." | ||||||
|  | 	}	 | ||||||
|  | 
 | ||||||
|  | 	"Nextmap Voting Finished" | ||||||
|  | 	{ | ||||||
|  | 		"it"            "Le votazioni sono terminate. La prossima mappa sarà {1}. (Con {2}%% su {3} votes)" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Current Map Extended" | ||||||
|  | 	{ | ||||||
|  | 		"it"            "La mappa attuale è stata estesa. (Con {1}%% su {2} votes)" | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	"Extend Map" | ||||||
|  | 	{ | ||||||
|  | 		"it"            "Estendi la mappa corrente" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Dont Change" | ||||||
|  | 	{ | ||||||
|  | 		"it"            "Non cambiare" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Current Map Stays" | ||||||
|  | 	{ | ||||||
|  | 		"it"			"La mappa continua! Il voto ha parlato! (Con {1}%% su {2} votes)" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Changed Next Map" | ||||||
|  | 	{ | ||||||
|  | 		"it"        "La mappa successiva sarà \"{1}\"." | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Runoff Vote Nextmap" | ||||||
|  | 	{ | ||||||
|  | 		"it"        "Vota nuovamente per scegliere la prossima mappa!" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Number Of Votes" | ||||||
|  | 	{ | ||||||
|  | 		"it"		"Numero di voti" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Custom" | ||||||
|  | 	{ | ||||||
|  | 		"it"        "{1} (Custom)" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Revote Is Needed" | ||||||
|  | 	{ | ||||||
|  | 		"it"		"Nessuna mappa ha ricevuto più del {1}%% di voti.\nAllora, quale mappa vincerà? Si inizia un' altra votazione!" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Revote Warning" | ||||||
|  | 	{ | ||||||
|  | 		"it"		"Una nuova votazione inizierà tra: {1}s" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Vote Warning" | ||||||
|  | 	{ | ||||||
|  | 		"it"        "Attenzione! Le votazione per la prossima mappa cominceranno tra: {1}s" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Line One" | ||||||
|  | 	{ | ||||||
|  | 		"it"		"Vota la mappa chevorresti giocare..." | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Line Two" | ||||||
|  | 	{ | ||||||
|  | 		"it"		"...e non cliccare i tasti sconsideratamente :D" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Cannot Start Vote" | ||||||
|  | 	{ | ||||||
|  | 		"it"        "Il voto è in corso.  Riprova tra {1}s." | ||||||
|  | 	} | ||||||
|  |          | ||||||
|  |         "Tie Vote" | ||||||
|  | 	{ | ||||||
|  |                 "it"            "Le mappe hanno raggiunto il pareggio dei voti.\nBisogna nuovamente votare!" | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										2
									
								
								mapchooser_extended/translations/jp/incomplete.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								mapchooser_extended/translations/jp/incomplete.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,2 @@ | |||||||
|  | Missing "Runoff Vote Nextmap", "Number Of Votes", "Custom", "Revote Is Needed", "Revote Warning", "Vote Warning", | ||||||
|  | "Line One", "Line Two", "Cannot Start Vote", and "Tie Vote" | ||||||
| @ -0,0 +1,43 @@ | |||||||
|  | "Phrases" | ||||||
|  | { | ||||||
|  | 	"Vote Nextmap" | ||||||
|  | 	{ | ||||||
|  | 		"jp"		"次のマップを投票してください!" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Nextmap Voting Started" | ||||||
|  | 	{ | ||||||
|  | 		"jp"		"次のマップ投票をスタートしました。" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Nextmap Voting Finished" | ||||||
|  | 	{ | ||||||
|  | 		"jp"		"マップ投票が完了しました。次はマップは{1}です。({3}中{2}%%)" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Current Map Extended" | ||||||
|  | 	{ | ||||||
|  | 		"jp"		"現在のマップを延長します。({3}中{2}%%)" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Extend Map" | ||||||
|  | 	{ | ||||||
|  | 		"jp"		"現在のマップを延長" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Dont Change" | ||||||
|  | 	{ | ||||||
|  | 		"jp"		"変更しない" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Current Map Stays" | ||||||
|  | 	{ | ||||||
|  | 		"jp"		"現在のマップを延長します。({3}中{2}%%)" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Changed Next Map" | ||||||
|  | 	{ | ||||||
|  | 		"jp"		"次のマップを\"{1}\"に変更しました。" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,98 @@ | |||||||
|  | "Phrases" | ||||||
|  | { | ||||||
|  | 	"Vote Nextmap" | ||||||
|  | 	{ | ||||||
|  | 		"ko"			"다음 맵을 결정하기 위한 투표!" | ||||||
|  | 	}	 | ||||||
|  | 
 | ||||||
|  | 	"Nextmap Voting Started" | ||||||
|  | 	{ | ||||||
|  | 		"ko"			"다음 맵을 결정하기 위한 투표가 시작되었습니다." | ||||||
|  | 	}	 | ||||||
|  | 
 | ||||||
|  | 	"Nextmap Voting Finished" | ||||||
|  | 	{ | ||||||
|  | 		"ko"			"맵 투표가 끝났습니다. 다음 맵은 {1} 이 될 것입니다. (전체 인원 {2}명 중 {1}%%의 표를 받았습니다.)" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Current Map Extended" | ||||||
|  | 	{ | ||||||
|  | 		"ko"			"현재 맵을 더하기로 결정했습니다. (전체 인원 {2}명 중 {1}%%의 표를 받았습니다.)" | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	"Extend Map" | ||||||
|  | 	{ | ||||||
|  | 		"ko"			"지금 맵을 더 하자" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Dont Change" | ||||||
|  | 	{ | ||||||
|  | 		"ko"			"바꾸지 말자" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Current Map Stays" | ||||||
|  | 	{ | ||||||
|  | 		"ko"			"현재 맵을 계속 합니다!(전체 인원 {2} 명의 {1}%% 의 표를 받았습니다)" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Changed Next Map" | ||||||
|  | 	{ | ||||||
|  | 		"ko"		"다음 맵을 \"{1}\" 로 바꾸었습니다."	 | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Runoff Vote Nextmap" | ||||||
|  | 	{ | ||||||
|  | 		"ko"		"다음 맵을 결정하기 위한 재투표!" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Number Of Votes" | ||||||
|  | 	{ | ||||||
|  | 		"ko"		"투표수" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Custom" | ||||||
|  | 	{ | ||||||
|  | 		"ko"		"{1} (커스텀 맵)" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Revote Is Needed" | ||||||
|  | 	{ | ||||||
|  | 		"ko"		"{1}%% 이상 투표를 받은 맵이 없습니다.\n다음 맵을 결정하기 위해 재투표를 합니다!" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Revote Warning" | ||||||
|  | 	{ | ||||||
|  | 		"ko"		"재투표까지: {1}초" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Vote Warning" | ||||||
|  | 	{ | ||||||
|  | 		"ko"		"알립니다! 다음 맵을 결정하는 투표까지: {1}초" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Line One" | ||||||
|  | 	{ | ||||||
|  | 		"ko"		"원하는 맵을 선택하세요..." | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Line Two" | ||||||
|  | 	{ | ||||||
|  | 		"ko"		"...그리고 아무거나 막 찍지 말고요 -_-" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Cannot Start Vote" | ||||||
|  | 	{ | ||||||
|  | 		"ko"		"투표가 진행 중에 있습니다. {1}초 후 다시 시도합니다." | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Tie Vote" | ||||||
|  | 	{ | ||||||
|  | 		"ko"		"{1}개 맵이 같은 투표수를 얻었습니다.\n재투표를 합니다!" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Custom Marked" | ||||||
|  | 	{ | ||||||
|  | 		"ko"		"*{1}" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | } | ||||||
							
								
								
									
										2
									
								
								mapchooser_extended/translations/lv/incomplete.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								mapchooser_extended/translations/lv/incomplete.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,2 @@ | |||||||
|  | Missing "Runoff Vote Nextmap", "Number Of Votes", "Custom", "Revote Is Needed", "Revote Warning", "Vote Warning", | ||||||
|  | "Line One", "Line Two", "Cannot Start Vote", and "Tie Vote" | ||||||
| @ -0,0 +1,43 @@ | |||||||
|  | "Phrases" | ||||||
|  | { | ||||||
|  | 	"Vote Nextmap" | ||||||
|  | 	{ | ||||||
|  | 		"lv"		"Balso par nākamo karti!" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Nextmap Voting Started" | ||||||
|  | 	{ | ||||||
|  | 		"lv"		"Balsošana par nākamo karti ir sākusies." | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Nextmap Voting Finished" | ||||||
|  | 	{ | ||||||
|  | 		"lv"		"Balsošana par karti ir beigusies. Nākamā karte būs {1}. (Saņēma {2}%% no {3} balsīm)  " | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Current Map Extended" | ||||||
|  | 	{ | ||||||
|  | 		"lv"		"Patreizējās kartes laiks ir pagarināts. (Saņēma {1}%% no {2} balsīm)  " | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Extend Map" | ||||||
|  | 	{ | ||||||
|  | 		"lv"		"Pagarināt laiku patreizējā kartē" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Dont Change" | ||||||
|  | 	{ | ||||||
|  | 		"lv"		"Nemainīt" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Current Map Stays" | ||||||
|  | 	{ | ||||||
|  | 		"lv"		"Patreizējā karte turpinās! Aptauja ir beigusies! (Saņēma {1}%% no {2} balsīm)" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Changed Next Map" | ||||||
|  | 	{ | ||||||
|  | 		"lv"		"Nomainīja nākamo karti uz \"{1}\"." | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | } | ||||||
							
								
								
									
										109
									
								
								mapchooser_extended/translations/mapchooser_extended.phrases.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								mapchooser_extended/translations/mapchooser_extended.phrases.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,109 @@ | |||||||
|  | "Phrases" | ||||||
|  | { | ||||||
|  | 	"Vote Nextmap" | ||||||
|  | 	{ | ||||||
|  | 		"en"			"Vote for the next map!" | ||||||
|  | 	}	 | ||||||
|  | 
 | ||||||
|  | 	"Nextmap Voting Started" | ||||||
|  | 	{ | ||||||
|  | 		"en"			"Voting for next map has started." | ||||||
|  | 	}	 | ||||||
|  | 
 | ||||||
|  | 	"Nextmap Voting Finished" | ||||||
|  | 	{ | ||||||
|  | 		"#format"			"{1:s},{2:i},{3:i}" | ||||||
|  | 		"en"			"Map voting has finished. The next map will be {1}. (Received {2}%% of {3} votes)" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Current Map Extended" | ||||||
|  | 	{ | ||||||
|  | 		"#format"			"{1:i},{2:i}" | ||||||
|  | 		"en"			"The current map has been extended. (Received {1}%% of {2} votes)" | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	"Extend Map" | ||||||
|  | 	{ | ||||||
|  | 		"en"			"Extend Current Map" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Dont Change" | ||||||
|  | 	{ | ||||||
|  | 		"en"			"Don't Change" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Current Map Stays" | ||||||
|  | 	{ | ||||||
|  | 		"#format"			"{1:i},{2:i}" | ||||||
|  | 		"en"			"Current map continues! The Vote has spoken! (Received {1}%% of {2} votes)" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Changed Next Map" | ||||||
|  | 	{ | ||||||
|  | 		"#format"		"{1:s}" | ||||||
|  | 		"en"		"Changed nextmap to \"{1}\"."	 | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Runoff Vote Nextmap" | ||||||
|  | 	{ | ||||||
|  | 		"en"		"Runoff Vote for the next map!" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Number Of Votes" | ||||||
|  | 	{ | ||||||
|  | 		"en"		"Number of votes" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Custom" | ||||||
|  | 	{ | ||||||
|  | 		"#format"	"{1:s}" | ||||||
|  | 		"en"		"{1} (Custom)" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Revote Is Needed" | ||||||
|  | 	{ | ||||||
|  | 		"#format"	"{1:i}" | ||||||
|  | 		"en"		"No map has received more than {1}%% of the vote.\nSo, which map will win? A revote is needed!" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Revote Warning" | ||||||
|  | 	{ | ||||||
|  | 		"#format"	"{1:i}" | ||||||
|  | 		"en"		"Runoff vote will start in: {1}s" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Vote Warning" | ||||||
|  | 	{ | ||||||
|  | 		"#format"	"{1:i}" | ||||||
|  | 		"en"		"Warning! Voting for the next map will begin in: {1}s" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Line One" | ||||||
|  | 	{ | ||||||
|  | 		"en"		"Consider which map you want to play..." | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Line Two" | ||||||
|  | 	{ | ||||||
|  | 		"en"		"...and don't hit buttons thoughtlessly ;-)" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Cannot Start Vote" | ||||||
|  | 	{ | ||||||
|  | 		"#format"	"{1:i}" | ||||||
|  | 		"en"		"Vote already in progress.  Retrying in {1}s." | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Tie Vote" | ||||||
|  | 	{ | ||||||
|  | 		"#format"	"{1:i}" | ||||||
|  | 		"en"		"The top {1} maps had the same number of votes.\nA revote is needed!" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Custom Marked" | ||||||
|  | 	{ | ||||||
|  | 		"#format"	"{1:s}" | ||||||
|  | 		"en"		"*{1}" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | } | ||||||
							
								
								
									
										2
									
								
								mapchooser_extended/translations/nl/incomplete.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								mapchooser_extended/translations/nl/incomplete.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,2 @@ | |||||||
|  | Missing "Runoff Vote Nextmap", "Number Of Votes", "Custom", "Revote Is Needed", "Revote Warning", "Vote Warning", | ||||||
|  | "Line One", "Line Two", "Cannot Start Vote", and "Tie Vote" | ||||||
| @ -0,0 +1,43 @@ | |||||||
|  | "Phrases" | ||||||
|  | { | ||||||
|  | 	"Vote Nextmap" | ||||||
|  | 	{ | ||||||
|  | 		"nl"		"Stem voor de volgende map!" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Nextmap Voting Started" | ||||||
|  | 	{ | ||||||
|  | 		"nl"		"Stemmen voor de volgende map is gestart." | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Nextmap Voting Finished" | ||||||
|  | 	{ | ||||||
|  | 		"nl"		"Map stemmen gestopt. De volgende map wordt {1}." | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Current Map Extended" | ||||||
|  | 	{ | ||||||
|  | 		"nl"		"De huidige map is verlengd." | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Extend Map" | ||||||
|  | 	{ | ||||||
|  | 		"nl"		"Verleng huidige map" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Dont Change" | ||||||
|  | 	{ | ||||||
|  | 		"nl"		"Niet veranderen" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Current Map Stays" | ||||||
|  | 	{ | ||||||
|  | 		"nl"		"Huidige map gaat verder! De Stem heeft gesproken! (Ontvangen {1}%% van de {2} stemmen)" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Changed Next Map" | ||||||
|  | 	{ | ||||||
|  | 		"nl"		"Volgende map verandert naar \"{1}\"." | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | } | ||||||
							
								
								
									
										2
									
								
								mapchooser_extended/translations/no/incomplete.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								mapchooser_extended/translations/no/incomplete.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,2 @@ | |||||||
|  | Missing "Runoff Vote Nextmap", "Number Of Votes", "Custom", "Revote Is Needed", "Revote Warning", "Vote Warning", | ||||||
|  | "Line One", "Line Two", "Cannot Start Vote", and "Tie Vote" | ||||||
| @ -0,0 +1,43 @@ | |||||||
|  | "Phrases" | ||||||
|  | { | ||||||
|  | 	"Vote Nextmap" | ||||||
|  | 	{ | ||||||
|  | 		"no"		"Stem for det neste kartet!" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Nextmap Voting Started" | ||||||
|  | 	{ | ||||||
|  | 		"no"		"Avstemning for det neste kartet har startet." | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Nextmap Voting Finished" | ||||||
|  | 	{ | ||||||
|  | 		"no"		"Kart-avstemningen er avsluttet. Det neste kartet vil være {1}. (Mottok {2}%% av {3} stemmer)." | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Current Map Extended" | ||||||
|  | 	{ | ||||||
|  | 		"no"		"Gjeldende kart videreføres! (Mottok {1}%% av {2} stemmer)." | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Extend Map" | ||||||
|  | 	{ | ||||||
|  | 		"no"		"Forleng gjeldende kart." | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Dont Change" | ||||||
|  | 	{ | ||||||
|  | 		"no"		"Ikke bytt!" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Current Map Stays" | ||||||
|  | 	{ | ||||||
|  | 		"no"		"Gjeldende kart videreføres! Avstemningen har talt! (Mottok {1}%% av {2} stemmer)." | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Changed Next Map" | ||||||
|  | 	{ | ||||||
|  | 		"no"		"Byttet neste kart til \"{1}\"" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,92 @@ | |||||||
|  | "Phrases" | ||||||
|  | { | ||||||
|  | 	"Vote Nextmap" | ||||||
|  | 	{ | ||||||
|  | 		"pl"		"Głosuj na następną mapę!" | ||||||
|  | 	}	 | ||||||
|  | 
 | ||||||
|  | 	"Nextmap Voting Started" | ||||||
|  | 	{ | ||||||
|  | 		"pl"		"Rozpoczęto głosowanie na następną mapę." | ||||||
|  | 	}	 | ||||||
|  | 
 | ||||||
|  | 	"Nextmap Voting Finished" | ||||||
|  | 	{ | ||||||
|  | 		"pl"		"Głosowanie na mapę zostało zakończone. Następną mapą będzie {1}. (Otrzymała {2} procent z {3} głosów) " | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Current Map Extended" | ||||||
|  | 	{ | ||||||
|  | 		"pl"		"Aktualna mapa została przedłużona. (Otrzymała {1} procent z {2} głosów)" | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	"Extend Map" | ||||||
|  | 	{ | ||||||
|  | 		"pl"		"Przedłuż bieżącą mapę" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Dont Change" | ||||||
|  | 	{ | ||||||
|  | 		"pl"		"Nie Zmieniaj" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Current Map Stays" | ||||||
|  | 	{ | ||||||
|  | 		"pl"		"Aktualna mapa będzie kontynuowana! (Otrzymano {1} procent z {2} głosów)" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Changed Next Map" | ||||||
|  | 	{ | ||||||
|  | 		"pl"		"Zmieniono następną mapę na: \"{1}\"."	 | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Runoff Vote Nextmap" | ||||||
|  | 	{ | ||||||
|  | 		"pl"		"Wybierz ponownie!" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Number Of Votes" | ||||||
|  | 	{ | ||||||
|  | 		"pl"		"Otrzymane głosy" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Custom" | ||||||
|  | 	{ | ||||||
|  | 		"pl"		"{1} (Niestandardowa)" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Revote Is Needed" | ||||||
|  | 	{ | ||||||
|  | 		"pl"		"Żadna mapa nie otrzymała przynajmniej {1}%% głosów.\nWięc która mapa jest zwycięzcą? Trzeba zagłosować ponownie!" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Revote Warning" | ||||||
|  | 	{ | ||||||
|  | 		"pl"		"Ponowne głosowanie rozpocznie się za: {1}s\nTym razem się już zdecydujcie ;-)" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Vote Warning" | ||||||
|  | 	{ | ||||||
|  | 		"pl"		"UWAGA!!! Głosowanie na następną mapę rozpocznie się za: {1}s" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Line One" | ||||||
|  | 	{ | ||||||
|  | 		"pl"		"Zastanów się na której mapie chcesz grać..." | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Line Two" | ||||||
|  | 	{ | ||||||
|  | 		"pl"		"...wpisując !revote możesz zmienić swój głos." | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Cannot Start Vote" | ||||||
|  | 	{ | ||||||
|  | 		"pl"		"Głosowanie w toku. Ponawiam za {1}s." | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Tie Vote" | ||||||
|  | 	{ | ||||||
|  | 		"pl"		"{1} najlepsze mapy otrzymały tę samą ilość głosów.\nPotrzeba ponownego głosowania!" | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @ -0,0 +1,98 @@ | |||||||
|  | "Phrases" | ||||||
|  | { | ||||||
|  | 	"Vote Nextmap" | ||||||
|  | 	{ | ||||||
|  | 		"pt"			"Vote para o próximo mapa!" | ||||||
|  | 	}	 | ||||||
|  | 
 | ||||||
|  | 	"Nextmap Voting Started" | ||||||
|  | 	{ | ||||||
|  | 		"pt"			"Votação para o próximo mapa começou." | ||||||
|  | 	}	 | ||||||
|  | 
 | ||||||
|  | 	"Nextmap Voting Finished" | ||||||
|  | 	{ | ||||||
|  | 		"pt"			"A votação para o próximo mapa terminou. O próximo mapa será {1}. (Recebidos {2}%% de {3} votos)" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Current Map Extended" | ||||||
|  | 	{ | ||||||
|  | 		"pt"			"A mapa atual foi estendido. (Recebidos {1}%% de {2} votos)" | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	"Extend Map" | ||||||
|  | 	{ | ||||||
|  | 		"pt"			"Estender tempo do mapa atual" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Dont Change" | ||||||
|  | 	{ | ||||||
|  | 		"pt"			"Não Mudar" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Current Map Stays" | ||||||
|  | 	{ | ||||||
|  | 		"pt"			"O mapa atual continua! O Voto foi dado! (Recebidos {1}%% de {2} votos)" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Changed Next Map" | ||||||
|  | 	{ | ||||||
|  | 		"pt"		"Mudado o próximo mapa para \"{1}\"."	 | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Runoff Vote Nextmap" | ||||||
|  | 	{ | ||||||
|  | 		"pt"		"Segundo turno de votos para o próximo mapa!" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Number Of Votes" | ||||||
|  | 	{ | ||||||
|  | 		"pt"		"Número de votos" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Custom" | ||||||
|  | 	{ | ||||||
|  | 		"pt"		"{1} (Custom)" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Revote Is Needed" | ||||||
|  | 	{ | ||||||
|  | 		"pt"		"Nenhum mapa recebeu mais que {1}%% de votos.\nEntão, qual mapa ganhará? Precisa de uma nova votação!" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Revote Warning" | ||||||
|  | 	{ | ||||||
|  | 		"pt"		"Segundo turno começa em: {1}s" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Vote Warning" | ||||||
|  | 	{ | ||||||
|  | 		"pt"		"Atenção! Votação para o próximo mapa começará em: {1}s" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Line One" | ||||||
|  | 	{ | ||||||
|  | 		"pt"		"Considere que mapa você quer jogar..." | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Line Two" | ||||||
|  | 	{ | ||||||
|  | 		"pt"		"...e não aperte os botões sem pensar ;-)" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Cannot Start Vote" | ||||||
|  | 	{ | ||||||
|  | 		"pt"		"Votação em progresso.  Tentando novamente em {1}s." | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Tie Vote" | ||||||
|  | 	{ | ||||||
|  | 		"pt"		"Os {1} mapas tiveram o mesmo número de votos.\nUma nova votação é necessária!" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Custom Marked" | ||||||
|  | 	{ | ||||||
|  | 		"pt"		"*{1}" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | } | ||||||
							
								
								
									
										1
									
								
								mapchooser_extended/translations/ru/incomplete.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								mapchooser_extended/translations/ru/incomplete.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | |||||||
|  | Missing "Cannot Start Vote" and "Tie Vote" | ||||||
| @ -0,0 +1,83 @@ | |||||||
|  | "Phrases" | ||||||
|  | { | ||||||
|  | 	"Vote Nextmap" | ||||||
|  | 	{ | ||||||
|  | 		"ru"		"Голосование за следующую карту." | ||||||
|  | 	}	 | ||||||
|  | 
 | ||||||
|  | 	"Runoff Vote Nextmap" | ||||||
|  | 	{ | ||||||
|  | 		"ru"		"Повторное голосование за карту." | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Nextmap Voting Started" | ||||||
|  | 	{ | ||||||
|  | 		"ru"		"Голосование за следующую карту запущено." | ||||||
|  | 	}	 | ||||||
|  | 
 | ||||||
|  | 	"Nextmap Voting Finished" | ||||||
|  | 	{ | ||||||
|  | 		"ru"		"Голосование за карту завершено. Следующей картой будет: {1}. (Получено {2}%% из {3} голосов(а))" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Current Map Extended" | ||||||
|  | 	{ | ||||||
|  | 		"ru"		"Текущая карта была продлена. (Получено {1}%% из {2} голосов(а))" | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	"Extend Map" | ||||||
|  | 	{ | ||||||
|  | 		"ru"		"Продлить текущую карту." | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Dont Change" | ||||||
|  | 	{ | ||||||
|  | 		"ru"		"Не менять карту." | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Current Map Stays" | ||||||
|  | 	{ | ||||||
|  | 		"ru"		"Текущая карта не сменится! (Получено {1}%% из {2} голосов(а))" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Changed Next Map" | ||||||
|  | 	{ | ||||||
|  | 		"ru"		"Следующая карта изменена на \"{1}\"."	 | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Number Of Votes" | ||||||
|  | 	{ | ||||||
|  | 		"ru"		"Количество голосов" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Custom" | ||||||
|  | 	{ | ||||||
|  | 		"ru"		"{1} (Случайная)" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Revote Is Needed" | ||||||
|  | 	{ | ||||||
|  | 		"ru"		"Ни одна карта не получила более, чем {1}%% голосов(а).\nИтак, какая карта будет следующей? Приготовьтесь к повторному голосованию!" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Revote Warning" | ||||||
|  | 	{ | ||||||
|  | 		"ru"		"Повторное голосование начнётся через: {1}s" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Vote Warning" | ||||||
|  | 	{ | ||||||
|  | 		"ru"		"Внимание! Голосование за следующую карту начнётся через: {1}s" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Line One" | ||||||
|  | 	{ | ||||||
|  | 		"ru"		"Выбери, какая карта будет следующей..." | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Line Two" | ||||||
|  | 	{ | ||||||
|  | 		"ru"		"...и не клацай кнопки,не подумав ;-)" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | } | ||||||
							
								
								
									
										2
									
								
								mapchooser_extended/translations/sv/incomplete.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								mapchooser_extended/translations/sv/incomplete.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,2 @@ | |||||||
|  | Missing "Runoff Vote Nextmap", "Number Of Votes", "Custom", "Revote Is Needed", "Revote Warning", "Vote Warning", | ||||||
|  | "Line One", "Line Two", "Cannot Start Vote", and "Tie Vote" | ||||||
| @ -0,0 +1,43 @@ | |||||||
|  | "Phrases" | ||||||
|  | { | ||||||
|  | 	"Vote Nextmap" | ||||||
|  | 	{ | ||||||
|  | 		"sv"		"Rösta för nästa bana!" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Nextmap Voting Started" | ||||||
|  | 	{ | ||||||
|  | 		"sv"		"Röstning om nästa bana har börjat." | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Nextmap Voting Finished" | ||||||
|  | 	{ | ||||||
|  | 		"sv"		"Röstningen om banan har avslutats. Nästa bana kommer att bli {1}. (Fick {2}%% av {3} röster)  " | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Current Map Extended" | ||||||
|  | 	{ | ||||||
|  | 		"sv"		"Den nuvarande banan har förlängts. (Fick {1}%% av {2} röster)  " | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Extend Map" | ||||||
|  | 	{ | ||||||
|  | 		"sv"		"Förläng nuvarande bana" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Dont Change" | ||||||
|  | 	{ | ||||||
|  | 		"sv"		"Byt inte" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Current Map Stays" | ||||||
|  | 	{ | ||||||
|  | 		"sv"		"Nuvarande banan fortsätter! Röstningen har talat! (Fick {1}%% av {2} röster)  " | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Changed Next Map" | ||||||
|  | 	{ | ||||||
|  | 		"sv"		"Bytta nästa bana till \"{1}\".  " | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | } | ||||||
							
								
								
									
										2
									
								
								mapchooser_extended/translations/tr/incomplete.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								mapchooser_extended/translations/tr/incomplete.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,2 @@ | |||||||
|  | Missing "Runoff Vote Nextmap", "Number Of Votes", "Custom", "Revote Is Needed", "Revote Warning", "Vote Warning", | ||||||
|  | "Line One", "Line Two", "Cannot Start Vote", and "Tie Vote" | ||||||
| @ -0,0 +1,43 @@ | |||||||
|  | "Phrases" | ||||||
|  | { | ||||||
|  | 	"Vote Nextmap" | ||||||
|  | 	{ | ||||||
|  | 		"tr"		"Sonraki harita için oy ver!" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Nextmap Voting Started" | ||||||
|  | 	{ | ||||||
|  | 		"tr"		"Sonraki harita için oylama başladı." | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Nextmap Voting Finished" | ||||||
|  | 	{ | ||||||
|  | 		"tr"		"Harita oylaması sona erdi. Sıradaki harita {1} olacak. ({3} oyun %%{2}'i alındı) " | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Current Map Extended" | ||||||
|  | 	{ | ||||||
|  | 		"tr"		"Geçerli harita uzatıldı. ({2} oyun %%{1}'i alındı) " | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Extend Map" | ||||||
|  | 	{ | ||||||
|  | 		"tr"		"Geçerli Haritayı Uzat" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Dont Change" | ||||||
|  | 	{ | ||||||
|  | 		"tr"		"Değiştirme" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Current Map Stays" | ||||||
|  | 	{ | ||||||
|  | 		"tr"		"Geçerli harita devam ediyor! Oylama konuştu! ({2} oyun %%{1}'i alındı)  " | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	"Changed Next Map" | ||||||
|  | 	{ | ||||||
|  | 		"tr"		"Sıradaki harita \"{1}\" olarak değiştirildi." | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | } | ||||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
		Reference in New Issue
	
	Block a user