initial commit

This commit is contained in:
BotoX 2016-01-06 02:11:56 +01:00
commit 72f7665358
106 changed files with 17675 additions and 0 deletions

View 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);
}

View File

@ -0,0 +1 @@
SteamAPI.secret

View 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;
}

View 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

View File

@ -0,0 +1 @@
../../../includes/SteamWorks.inc

View 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;
}

View 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);
}

View 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;
}

View 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"
}
}
}
}

View 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;
}

View File

@ -0,0 +1 @@
../../../includes/dhooks.inc

View 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;
}

View 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;
}

View 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);
}
}

View File

@ -0,0 +1,28 @@
"Games"
{
"cstrike"
{
"Offsets"
{
"RadiusDamage"
{
"windows" "68"
"linux" "69"
"mac" "69"
}
}
}
"csgo"
{
"Offsets"
{
"RadiusDamage"
{
"windows" "68"
"linux" "69"
"mac" "69"
}
}
}
}

View 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;
}

View File

@ -0,0 +1 @@
../../../includes/dhooks.inc

View File

@ -0,0 +1,15 @@
"Games"
{
"cstrike"
{
"Offsets"
{
"OnDamagedByExplosion"
{
"windows" "335"
"linux" "336"
"mac" "336"
}
}
}
}

View 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;
}

View File

@ -0,0 +1 @@
../../../includes/dhooks.inc

View 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;
}

View 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"
}
}
}

View 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"
}
}
}

View 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"
}
}
}

View 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"
}
}
}

View 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"
}
}
}

View 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"
}
}
}

View 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"
}
}
}

View 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"
}
}
}

View 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"
}
}
}

View 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"
}
}
}

View 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;
}

View File

@ -0,0 +1 @@
../../../includes/outputinfo.inc

View 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;
}

View File

@ -0,0 +1 @@
../../../AdvancedTargeting/scripting/include/AdvancedTargeting.inc

View File

@ -0,0 +1 @@
../../../custom-chatcolors/scripting/include/ccc.inc

View File

@ -0,0 +1 @@
../../../voiceannounce_ex/scripting/include/voiceannounce_ex.inc

View File

@ -0,0 +1 @@
../../../includes/zombiereloaded.inc

208
Status/scripting/Status.sp Normal file
View 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;
}

View 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;
}

View File

@ -0,0 +1 @@
../../../includes/morecolors.inc

View 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;
}

View 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!");
}

File diff suppressed because it is too large Load Diff

View 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

View File

@ -0,0 +1 @@
../../../includes/morecolors.inc

View 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
View 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
View 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
View 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
View 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
View 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
View 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

View 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
View 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
View 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);

View 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);

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,9 @@
dod_anzio
dod_argentan
dod_avalanche
dod_colmar
dod_donner
dod_flash
dod_jagd
dod_kalt
dod_palermo

View File

@ -0,0 +1,7 @@
dm_lockdown
dm_overwatch
dm_runoff
dm_steamlab
dm_underpass
dm_resistance
dm_powerhouse

View 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

View File

@ -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"
}
}
}

View File

@ -0,0 +1 @@
../../../includes/colors.inc

View 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
};

View File

@ -0,0 +1 @@
../../../includes/nativevotes.inc

File diff suppressed because it is too large Load Diff

View 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;
}

View 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;
}

View 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"

View File

@ -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}\"."
}
}

View 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"

View File

@ -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}\"."
}
}

View 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"

View File

@ -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}'."
}
}

View File

@ -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}"
}
}

View File

@ -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!"
}
}

View File

@ -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."
}
}

View File

@ -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!"
}
}

View 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"

View File

@ -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"
}
}

View File

@ -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!"
}
}

View 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"

View File

@ -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}\"に変更しました。"
}
}

View File

@ -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}"
}
}

View 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"

View File

@ -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}\"."
}
}

View 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}"
}
}

View 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"

View File

@ -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}\"."
}
}

View 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"

View File

@ -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}\""
}
}

View File

@ -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!"
}
}

View File

@ -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}"
}
}

View File

@ -0,0 +1 @@
Missing "Cannot Start Vote" and "Tie Vote"

View File

@ -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" "...и не клацай кнопки,не подумав ;-)"
}
}

View 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"

View File

@ -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}\". "
}
}

View 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"

View File

@ -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