commit 527e7ec05e907255f3dfe177ca034bbc19d2239b
Author: xen <24222257+xen-000@users.noreply.github.com>
Date: Wed Mar 25 20:04:16 2020 +0200
Init
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..043bc3b
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+/include
+/spcomp
+/spcomp.exe
diff --git a/AdvancedTargeting/scripting/AdvancedTargeting.sp b/AdvancedTargeting/scripting/AdvancedTargeting.sp
new file mode 100644
index 0000000..dd2b59d
--- /dev/null
+++ b/AdvancedTargeting/scripting/AdvancedTargeting.sp
@@ -0,0 +1,610 @@
+#pragma semicolon 1
+
+#pragma dynamic 128*1024
+
+#include
+#include
+#include
+#include
+#include
+
+#undef REQUIRE_PLUGIN
+#include
+#include
+#define REQUIRE_PLUGIN
+
+#undef REQUIRE_EXTENSIONS
+#tryinclude
+#define REQUIRE_EXTENSIONS
+
+#pragma newdecls required
+
+Handle g_FriendsArray[MAXPLAYERS + 1] = {INVALID_HANDLE, ...};
+
+bool g_Plugin_voiceannounce_ex = false;
+bool g_Extension_Voice = false;
+bool g_bLateLoad = false;
+
+#include //#define STEAM_API_KEY here
+
+public Plugin myinfo =
+{
+ name = "Advanced Targeting",
+ author = "BotoX + Obus",
+ description = "Adds extra targeting methods",
+ version = "1.3",
+ url = "https://github.com/CSSZombieEscape/sm-plugins/tree/master/AdvancedTargeting/"
+}
+
+public void 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);
+ AddMultiTargetFilter("@random", Filter_Random, "a Random Player", false);
+ AddMultiTargetFilter("@randomct", Filter_RandomCT, "a Random CT", false);
+ AddMultiTargetFilter("@randomt", Filter_RandomT, "a Random T", false);
+ AddMultiTargetFilter("@alivect", Filter_AliveCT, "Alive Humans", false);
+ AddMultiTargetFilter("@alivet", Filter_AliveT, "Alive Zombies", false);
+ AddMultiTargetFilter("@talking", Filter_Talking, "Talking", false);
+ AddMultiTargetFilter("@!talking", Filter_NotTalking, "Not Talking", false);
+ AddMultiTargetFilter("@speaking", Filter_Talking, "Talking", false);
+ AddMultiTargetFilter("@!speaking", Filter_NotTalking, "Not Talking", false);
+
+ RegConsoleCmd("sm_admins", Command_Admins, "Currently online admins.");
+ RegConsoleCmd("sm_friends", Command_Friends, "Currently online friends.");
+
+ if(g_bLateLoad)
+ {
+ char sSteam32ID[32];
+ for(int i = 1; i <= MaxClients; i++)
+ {
+ if(IsClientInGame(i) && !IsFakeClient(i) && IsClientAuthorized(i) &&
+ GetClientAuthId(i, AuthId_Steam2, sSteam32ID, sizeof(sSteam32ID)))
+ {
+ OnClientAuthorized(i, sSteam32ID);
+ }
+ }
+ }
+}
+
+public void OnPluginEnd()
+{
+ RemoveMultiTargetFilter("@admins", Filter_Admin);
+ RemoveMultiTargetFilter("@!admins", Filter_NotAdmin);
+ RemoveMultiTargetFilter("@friends", Filter_Friends);
+ RemoveMultiTargetFilter("@!friends", Filter_NotFriends);
+ RemoveMultiTargetFilter("@random", Filter_Random);
+ RemoveMultiTargetFilter("@randomct", Filter_RandomCT);
+ RemoveMultiTargetFilter("@randomt", Filter_RandomT);
+ RemoveMultiTargetFilter("@alivect", Filter_AliveCT);
+ RemoveMultiTargetFilter("@alivet", Filter_AliveT);
+ RemoveMultiTargetFilter("@talking", Filter_Talking);
+ RemoveMultiTargetFilter("@!talking", Filter_NotTalking);
+ RemoveMultiTargetFilter("@speaking", Filter_Talking);
+ RemoveMultiTargetFilter("@!speaking", Filter_NotTalking);
+}
+
+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 void OnAllPluginsLoaded()
+{
+ g_Plugin_voiceannounce_ex = LibraryExists("voiceannounce_ex");
+ g_Extension_Voice = LibraryExists("Voice");
+
+ LogMessage("AdvancedTargeting capabilities:\nVoiceAnnounce: %s\nVoice: %s",
+ (g_Plugin_voiceannounce_ex ? "loaded" : "not loaded"),
+ (g_Extension_Voice ? "loaded" : "not loaded"));
+}
+
+public void OnLibraryAdded(const char[] name)
+{
+ if(StrEqual(name, "voiceannounce_ex"))
+ g_Plugin_voiceannounce_ex = true;
+ else if(StrEqual(name, "Voice"))
+ g_Extension_Voice = true;
+}
+
+public void OnLibraryRemoved(const char[] name)
+{
+ if(StrEqual(name, "voiceannounce_ex"))
+ g_Plugin_voiceannounce_ex = false;
+ else if(StrEqual(name, "Voice"))
+ g_Extension_Voice = false;
+}
+
+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;
+ ReplyToCommand(client, "[SM] Admins currently online: %s", aBuf);
+ }
+ else
+ ReplyToCommand(client, "[SM] Admins currently online: none");
+
+ return Plugin_Handled;
+}
+
+public Action Command_Friends(int client, int args)
+{
+ if(!client)
+ return Plugin_Handled;
+
+ 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_AliveCT(const char[] sPattern, Handle hClients, int client)
+{
+ for(int i = 1; i <= MaxClients; i++)
+ {
+ if(IsClientInGame(i) && !IsFakeClient(i) && GetClientTeam(i) == CS_TEAM_CT && IsPlayerAlive(i))
+ {
+ PushArrayCell(hClients, i);
+ }
+ }
+
+ return true;
+}
+
+public bool Filter_AliveT(const char[] sPattern, Handle hClients, int client)
+{
+ for(int i = 1; i <= MaxClients; i++)
+ {
+ if(IsClientInGame(i) && !IsFakeClient(i) && GetClientTeam(i) == CS_TEAM_T && IsPlayerAlive(i))
+ {
+ PushArrayCell(hClients, i);
+ }
+ }
+
+ return true;
+}
+
+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 bool Filter_Random(const char[] sPattern, Handle hClients, int client)
+{
+ int iRand = GetRandomInt(1, MaxClients);
+
+ if(IsClientInGame(iRand) && IsPlayerAlive(iRand))
+ PushArrayCell(hClients, iRand);
+ else
+ Filter_Random(sPattern, hClients, client);
+
+ return true;
+}
+
+public bool Filter_RandomCT(const char[] sPattern, Handle hClients, int client)
+{
+ int iCTCount = GetTeamClientCount(CS_TEAM_CT);
+
+ if(!iCTCount)
+ return false;
+
+ int[] iCTs = new int[iCTCount];
+
+ int iCurIndex;
+
+ for(int i = 1; i <= MaxClients; i++)
+ {
+ if(!IsClientInGame(i) || GetClientTeam(i) != CS_TEAM_CT)
+ continue;
+
+ if(!IsPlayerAlive(i))
+ {
+ iCTCount--;
+ continue;
+ }
+
+ iCTs[iCurIndex] = i;
+ iCurIndex++;
+ }
+
+ PushArrayCell(hClients, iCTs[GetRandomInt(0, iCTCount-1)]);
+
+ return true;
+}
+
+public bool Filter_RandomT(const char[] sPattern, Handle hClients, int client)
+{
+ int iTCount = GetTeamClientCount(CS_TEAM_T);
+
+ if(!iTCount)
+ return false;
+
+ int[] iTs = new int[iTCount];
+
+ int iCurIndex;
+
+ for(int i = 1; i <= MaxClients; i++)
+ {
+ if(!IsClientInGame(i) || GetClientTeam(i) != CS_TEAM_T)
+ continue;
+
+ if(!IsPlayerAlive(i))
+ {
+ iTCount--;
+ continue;
+ }
+
+ iTs[iCurIndex] = i;
+ iCurIndex++;
+ }
+
+ PushArrayCell(hClients, iTs[GetRandomInt(0, iTCount-1)]);
+
+ return true;
+}
+
+stock bool _IsClientSpeaking(int client)
+{
+ #if defined _voiceannounceex_included_
+ if(g_Plugin_voiceannounce_ex)
+ return IsClientSpeaking(client);
+ #endif
+
+ #if defined _voice_included
+ if(g_Extension_Voice)
+ return IsClientTalking(client);
+ #endif
+
+ return false;
+}
+
+public bool Filter_Talking(const char[] sPattern, Handle hClients, int client)
+{
+ for(int i = 1; i <= MaxClients; i++)
+ {
+ if(IsClientInGame(i) && !IsFakeClient(i) && _IsClientSpeaking(i))
+ {
+ PushArrayCell(hClients, i);
+ }
+ }
+
+ return true;
+}
+
+public bool Filter_NotTalking(const char[] sPattern, Handle hClients, int client)
+{
+ for(int i = 1; i <= MaxClients; i++)
+ {
+ if(IsClientInGame(i) && !IsFakeClient(i) && !_IsClientSpeaking(i))
+ {
+ 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 int 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 void APIWebResponse(const char[] sData, int client)
+{
+ KeyValues Response = new KeyValues("SteamAPIResponse");
+ if(!Response.ImportFromString(sData, "SteamAPIResponse"))
+ {
+ LogError("ImportFromString(sData, \"SteamAPIResponse\") failed.");
+ delete Response;
+ return;
+ }
+
+ if(!Response.JumpToKey("friends"))
+ {
+ LogError("JumpToKey(\"friends\") failed.");
+ delete Response;
+ return;
+ }
+
+ // No friends?
+ if(!Response.GotoFirstSubKey())
+ {
+ //LogError("GotoFirstSubKey() failed.");
+ delete Response;
+ return;
+ }
+
+ if(g_FriendsArray[client] != INVALID_HANDLE)
+ CloseHandle(g_FriendsArray[client]);
+
+ 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;
+}
+
+
+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)
+{
+ int client = GetNativeCell(1);
+ int 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)
+{
+ int 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;
+}
diff --git a/AdvancedTargeting/scripting/include/AdvancedTargeting.inc b/AdvancedTargeting/scripting/include/AdvancedTargeting.inc
new file mode 100644
index 0000000..8ffd3ad
--- /dev/null
+++ b/AdvancedTargeting/scripting/include/AdvancedTargeting.inc
@@ -0,0 +1,26 @@
+#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_AdvancedTargeting_SetNTVOptional()
+{
+ MarkNativeAsOptional("IsClientFriend");
+ MarkNativeAsOptional("ReadClientFriends");
+}
+#endif
diff --git a/AntiBhopCheat/scripting/AntiBhopCheat.sp b/AntiBhopCheat/scripting/AntiBhopCheat.sp
new file mode 100644
index 0000000..4b2f3d6
--- /dev/null
+++ b/AntiBhopCheat/scripting/AntiBhopCheat.sp
@@ -0,0 +1,652 @@
+#include
+#include
+#include
+#include
+
+#include
+#include "CJump.inc"
+#include "CStreak.inc"
+#include "CPlayer.inc"
+
+#define MAX_STREAKS 5
+#define VALID_MIN_JUMPS 3
+#define VALID_MAX_TICKS 5
+#define VALID_MIN_VELOCITY 250
+
+int g_aButtons[MAXPLAYERS + 1];
+bool g_bOnGround[MAXPLAYERS + 1];
+bool g_bHoldingJump[MAXPLAYERS + 1];
+bool g_bInJump[MAXPLAYERS + 1];
+
+CPlayer g_aPlayers[MAXPLAYERS + 1];
+
+// Api
+Handle g_hOnClientDetected;
+
+public Plugin myinfo =
+{
+ name = "AntiBhopCheat",
+ author = "BotoX",
+ description = "Detect all kinds of bhop cheats",
+ version = "0.0",
+ url = ""
+};
+
+
+public void OnPluginStart()
+{
+ LoadTranslations("common.phrases");
+
+ RegAdminCmd("sm_stats", Command_Stats, ADMFLAG_GENERIC, "sm_stats <#userid|name>");
+ RegAdminCmd("sm_streak", Command_Streak, ADMFLAG_GENERIC, "sm_streak <#userid|name> [streak]");
+
+ /* Handle late load */
+ for(int client = 1; client <= MaxClients; client++)
+ {
+ if(IsClientConnected(client))
+ {
+ if(IsClientConnected(client))
+ OnClientConnected(client);
+ }
+ }
+
+ // Api
+ g_hOnClientDetected = CreateGlobalForward("AntiBhopCheat_OnClientDetected", ET_Ignore, Param_Cell, Param_String, Param_String);
+}
+
+public void OnClientConnected(int client)
+{
+ if(g_aPlayers[client])
+ {
+ g_aPlayers[client].Dispose();
+ g_aPlayers[client] = null;
+ }
+
+ g_aPlayers[client] = new CPlayer(client);
+}
+
+public void OnClientDisconnect(int client)
+{
+ if(g_aPlayers[client])
+ {
+ g_aPlayers[client].Dispose();
+ g_aPlayers[client] = null;
+ }
+
+ g_bOnGround[client] = false;
+ g_bHoldingJump[client] = false;
+ g_bInJump[client] = false;
+}
+
+public Action OnPlayerRunCmd(int client, int &buttons)
+{
+ g_aButtons[client] = buttons;
+ return Plugin_Continue;
+}
+
+public void OnPlayerRunCmdPost(int client, int buttons, int impulse, const float vel[3], const float angles[3], int weapon, int subtype, int cmdnum, int tickcount, int seed, const int mouse[2])
+{
+ if(!IsPlayerAlive(client))
+ return;
+
+ CPlayer Player = g_aPlayers[client];
+
+ MoveType ClientMoveType = GetEntityMoveType(client);
+ bool bInWater = GetEntProp(client, Prop_Send, "m_nWaterLevel") >= 2;
+
+ bool bPrevOnGround = g_bOnGround[client];
+ bool bOnGround = !bInWater && GetEntityFlags(client) & FL_ONGROUND;
+
+ bool bPrevHoldingJump = g_bHoldingJump[client];
+ bool bHoldingJump = view_as(g_aButtons[client] & IN_JUMP);
+
+ bool bInJump = g_bInJump[client];
+
+ float fVecVelocity[3];
+ GetEntPropVector(client, Prop_Data, "m_vecAbsVelocity", fVecVelocity);
+ fVecVelocity[2] = 0.0;
+ float fVelocity = GetVectorLength(fVecVelocity);
+
+ if(bInJump && (bInWater || ClientMoveType == MOVETYPE_LADDER || ClientMoveType == MOVETYPE_NOCLIP))
+ bOnGround = true;
+
+ if(bOnGround)
+ {
+ if(!bPrevOnGround)
+ {
+ g_bOnGround[client] = true;
+ g_bInJump[client] = false;
+ if(bInJump)
+ OnTouchGround(Player, tickcount, fVelocity);
+ }
+ }
+ else
+ {
+ if(bPrevOnGround)
+ g_bOnGround[client] = false;
+ }
+
+ if(bHoldingJump)
+ {
+ if(!bPrevHoldingJump && !bOnGround && (bPrevOnGround || bInJump))
+ {
+ g_bHoldingJump[client] = true;
+ g_bInJump[client] = true;
+ OnPressJump(Player, tickcount, fVelocity, bPrevOnGround);
+ }
+ }
+ else
+ {
+ if(bPrevHoldingJump)
+ {
+ g_bHoldingJump[client] = false;
+ OnReleaseJump(Player, tickcount, fVelocity);
+ }
+ }
+}
+
+// TODO: Release after touch ground
+
+void OnTouchGround(CPlayer Player, int iTick, float fVelocity)
+{
+ //PrintToServer("%d - OnTouchGround", iTick);
+
+ CStreak CurStreak = Player.hStreak;
+ ArrayList hJumps = CurStreak.hJumps;
+ CJump hJump = hJumps.Get(hJumps.Length - 1);
+
+ hJump.iEndTick = iTick;
+ hJump.fEndVel = fVelocity;
+
+ int iLength = hJumps.Length;
+ if(iLength == VALID_MIN_JUMPS)
+ {
+ CurStreak.bValid = true;
+
+ // Current streak is valid, push onto hStreaks ArrayList
+ ArrayList hStreaks = Player.hStreaks;
+ if(hStreaks.Length == MAX_STREAKS)
+ {
+ // Keep the last 10 streaks
+ CStreak hStreak = hStreaks.Get(0);
+ hStreak.Dispose();
+ hStreaks.Erase(0);
+ }
+ hStreaks.Push(CurStreak);
+
+ for(int i = 0; i < iLength - 1; i++)
+ {
+ CJump hJump_ = hJumps.Get(i);
+ DoStats(Player, CurStreak, hJump_);
+ }
+ }
+ else if(iLength > VALID_MIN_JUMPS)
+ {
+ CJump hJump_ = hJumps.Get(hJumps.Length - 2);
+ DoStats(Player, CurStreak, hJump_);
+ }
+}
+
+void OnPressJump(CPlayer Player, int iTick, float fVelocity, bool bLeaveGround)
+{
+ //PrintToServer("%d - OnPressJump %d", iTick, bLeaveGround);
+
+ CStreak CurStreak = Player.hStreak;
+ ArrayList hJumps = CurStreak.hJumps;
+ CJump hJump;
+
+ if(bLeaveGround)
+ {
+ int iPrevJump = -1;
+ // Check if we should start a new streak
+ if(hJumps.Length)
+ {
+ // Last jump was more than VALID_MAX_TICKS ticks ago or not valid and fVelocity < VALID_MIN_VELOCITY
+ hJump = hJumps.Get(hJumps.Length - 1);
+ if(hJump.iEndTick < iTick - VALID_MAX_TICKS || fVelocity < VALID_MIN_VELOCITY)
+ {
+ if(CurStreak.bValid)
+ {
+ CurStreak.iEndTick = hJump.iEndTick;
+
+ DoStats(Player, CurStreak, hJump);
+ CheckStats(Player, CurStreak);
+ }
+ else
+ CurStreak.Dispose();
+
+ CurStreak = new CStreak();
+ Player.hStreak = CurStreak;
+ hJumps = CurStreak.hJumps;
+ }
+ else
+ {
+ iPrevJump = iTick - hJump.iEndTick;
+ hJump.iNextJump = iPrevJump;
+ }
+ }
+
+ hJump = new CJump();
+ hJump.iStartTick = iTick;
+ hJump.fStartVel = fVelocity;
+ if(iPrevJump != -1)
+ hJump.iPrevJump = iPrevJump;
+ hJumps.Push(hJump);
+ }
+ else
+ hJump = hJumps.Get(hJumps.Length - 1);
+
+ ArrayList hPresses = hJump.hPresses;
+ hPresses.Push(iTick);
+}
+
+void OnReleaseJump(CPlayer Player, int iTick, float fVelocity)
+{
+ //PrintToServer("%d - OnReleaseJump", iTick);
+
+ CStreak CurStreak = Player.hStreak;
+ ArrayList hJumps = CurStreak.hJumps;
+ CJump hJump = hJumps.Get(hJumps.Length - 1);
+ ArrayList hPresses = hJump.hPresses;
+
+ hPresses.Set(hPresses.Length - 1, iTick, 1);
+}
+
+void DoStats(CPlayer Player, CStreak CurStreak, CJump hJump)
+{
+ int aJumps[3] = {0, 0, 0};
+ int iPresses = 0;
+ int iTicks = 0;
+ int iLastJunk = 0;
+
+ CurStreak.iJumps++;
+ Player.iJumps++;
+
+ ArrayList hPresses = hJump.hPresses;
+ int iStartTick = hJump.iStartTick;
+ int iEndTick = hJump.iEndTick;
+ int iPrevJump = hJump.iPrevJump;
+ int iNextJump = hJump.iNextJump;
+
+ if(iPrevJump > 0)
+ {
+ int iPerf = iPrevJump - 1;
+ if(iPerf > 2)
+ iPerf = 2;
+
+ aJumps[iPerf]++;
+ }
+
+ iPresses = hPresses.Length;
+ iTicks = iEndTick - iStartTick;
+ iLastJunk = iEndTick - hPresses.Get(iPresses - 1, 1);
+
+ float PressesPerTick = (iPresses * 4.0) / float(iTicks);
+ if(PressesPerTick >= 0.85)
+ {
+ CurStreak.iHyperJumps++;
+ Player.iHyperJumps++;
+ }
+
+ if(iNextJump != -1 && iNextJump <= 1 && (iLastJunk > 5 || iPresses <= 2) && hJump.fEndVel >= 285.0)
+ {
+ CurStreak.iHackJumps++;
+ Player.iHackJumps++;
+ }
+
+ int aGlobalJumps[3];
+ Player.GetJumps(aGlobalJumps);
+ aGlobalJumps[0] += aJumps[0];
+ aGlobalJumps[1] += aJumps[1];
+ aGlobalJumps[2] += aJumps[2];
+ Player.SetJumps(aGlobalJumps);
+
+ int aStreakJumps[3];
+ CurStreak.GetJumps(aStreakJumps);
+ aStreakJumps[0] += aJumps[0];
+ aStreakJumps[1] += aJumps[1];
+ aStreakJumps[2] += aJumps[2];
+ CurStreak.SetJumps(aStreakJumps);
+}
+
+void CheckStats(CPlayer Player, CStreak Streak)
+{
+ int client = Player.iClient;
+ int iStreakJumps = Streak.iJumps;
+ if(iStreakJumps >= 6)
+ {
+ float HackRatio = Streak.iHackJumps / float(iStreakJumps);
+ if(HackRatio >= 0.80)
+ {
+ Player.iHackFlagged += 1;
+ char sBuffer[32];
+ Format(sBuffer, sizeof(sBuffer), "bhop hack streak %d\n", Player.iHackFlagged);
+ NotifyAdmins(client, sBuffer);
+ }
+
+ float HyperRatio = Streak.iHyperJumps / float(iStreakJumps);
+ if(HyperRatio >= 0.80)
+ {
+ Player.iHyperFlagged += 1;
+ CPrintToChat(client, "{green}[SM]{default} Turn off your bhop macro/script or hyperscroll!");
+ CPrintToChat(client, "{green}[SM]{default} Your bhop is {red}turned off{default} until you bhop legit again.");
+ LimitBhop(client, true);
+ }
+ else if(IsBhopLimited(client))
+ {
+ LimitBhop(client, false);
+ CPrintToChat(client, "{green}[SM]{default} Your bhop is {green}turned on{default} again.");
+ }
+ }
+
+ int iGlobalJumps = Player.iJumps;
+ if(iGlobalJumps >= 35)
+ {
+ float HackRatio = Player.iHackJumps / float(iGlobalJumps);
+ if(HackRatio >= 0.60 && !Player.bHackGlobal)
+ {
+ Player.bHackGlobal = true;
+ NotifyAdmins(client, "bhop hack global");
+ }
+
+ float HyperRatio = Player.iHyperJumps / float(iGlobalJumps);
+ if(HyperRatio >= 0.50)
+ {
+ if(!Player.bHyperGlobal)
+ {
+ Player.bHyperGlobal = true;
+ CPrintToChat(client, "{green}[SM]{default} Turn off your bhop macro/script or hyperscroll!");
+ CPrintToChat(client, "{green}[SM]{default} Your bhop is {red}turned off{default} until you bhop legit again.");
+ LimitBhop(client, true);
+ }
+ }
+ else if(Player.bHyperGlobal && IsBhopLimited(client))
+ {
+ LimitBhop(client, false);
+ CPrintToChat(client, "{green}[SM]{default} Your bhop is {green}turned on{default} again.");
+ }
+ }
+}
+
+NotifyAdmins(int client, const char[] sReason)
+{
+ for(int i = 1; i <= MaxClients; i++)
+ {
+ if(IsClientInGame(i) && !IsFakeClient(i) && CheckCommandAccess(i, "sm_stats", ADMFLAG_GENERIC))
+ {
+ CPrintToChat(i, "{green}[SM]{default} %L has been detected for {red}%s{default}, please check your console!", client, sReason);
+ FormatStats(i, client);
+ PrintToConsole(client, "%s", "\n");
+ FormatStreak(i, client, 0);
+ }
+ }
+
+ char sBuffer[2000];
+ int len = FormatStats(-1, client, sBuffer, sizeof(sBuffer));
+ sBuffer[len++] = '\n';
+ len += FormatStreak(-1, client, 0, sBuffer[len], sizeof(sBuffer) - len);
+
+ Forward_OnDetected(client, sReason, sBuffer);
+}
+
+public Action Command_Stats(int client, int argc)
+{
+ if(argc < 1 || argc > 2)
+ {
+ ReplyToCommand(client, "[SM] Usage: sm_stats <#userid|name>");
+ return Plugin_Handled;
+ }
+
+ char sArg[65];
+ char sTargetName[MAX_TARGET_LENGTH];
+ int iTargets[MAXPLAYERS];
+ int iTargetCount;
+ bool bIsML;
+
+ GetCmdArg(1, sArg, sizeof(sArg));
+
+ if((iTargetCount = ProcessTargetString(sArg, client, iTargets, MAXPLAYERS, COMMAND_FILTER_NO_MULTI | COMMAND_FILTER_NO_IMMUNITY, sTargetName, sizeof(sTargetName), bIsML)) <= 0)
+ {
+ ReplyToTargetError(client, iTargetCount);
+ return Plugin_Handled;
+ }
+
+ for(int i = 0; i < iTargetCount; i++)
+ {
+ FormatStats(client, iTargets[i]);
+ PrintToConsole(client, "%s", "\n");
+
+ for(int j = 0; j < 3; j++)
+ {
+ FormatStreak(client, iTargets[i], j);
+ PrintToConsole(client, "%s", "\n");
+ }
+ }
+
+ return Plugin_Handled;
+}
+
+public Action Command_Streak(int client, int argc)
+{
+ if(argc < 1 || argc > 2)
+ {
+ ReplyToCommand(client, "[SM] Usage: sm_streak <#userid|name> [streak]");
+ return Plugin_Handled;
+ }
+
+ char sArg[65];
+ char sArg2[8];
+ char sTargetName[MAX_TARGET_LENGTH];
+ int iTargets[MAXPLAYERS];
+ int iTargetCount;
+ bool bIsML;
+ int iStreak = -1;
+
+ GetCmdArg(1, sArg, sizeof(sArg));
+
+ if(argc == 2)
+ {
+ GetCmdArg(2, sArg2, sizeof(sArg2));
+ iStreak = StringToInt(sArg2);
+ }
+
+ if((iTargetCount = ProcessTargetString(sArg, client, iTargets, MAXPLAYERS, COMMAND_FILTER_NO_MULTI | COMMAND_FILTER_NO_IMMUNITY, sTargetName, sizeof(sTargetName), bIsML)) <= 0)
+ {
+ ReplyToTargetError(client, iTargetCount);
+ return Plugin_Handled;
+ }
+
+ for(int i = 0; i < iTargetCount; i++)
+ {
+ FormatStreak(client, iTargets[i], iStreak);
+ }
+
+ return Plugin_Handled;
+}
+
+int FormatStats(int client, int iTarget, char[] sBuf=0, int len=0)
+{
+ int iBuf = ConsoleFormat(client, sBuf, len, "[SM] Bunnyhop stats for %L\n", iTarget);
+
+ CPlayer Player = g_aPlayers[iTarget];
+
+ int iGlobalJumps = Player.iJumps;
+ float HyperRatio = Player.iHyperJumps / float(iGlobalJumps);
+ float HackRatio = Player.iHackJumps / float(iGlobalJumps);
+
+ iBuf += ConsoleFormat(client, sBuf[iBuf], len-iBuf, "Global jumps: %d | Hyper?: %.1f%% | Hack?: %.1f%%\n",
+ iGlobalJumps, HyperRatio * 100.0, HackRatio * 100.0);
+
+ iBuf += ConsoleFormat(client, sBuf[iBuf], len-iBuf, "bHackGlobal: %d | bHyperGlobal: %d | iHackFlagged: %d | iHyperFlagged: %d\n",
+ Player.bHackGlobal, Player.bHyperGlobal, Player.iHackFlagged, Player.iHyperFlagged);
+
+ int aGlobalJumps[3];
+ Player.GetJumps(aGlobalJumps);
+
+ iBuf += ConsoleFormat(client, sBuf[iBuf], len-iBuf, "Global jumps perf group (1 2 +): %1.f%% %1.f%% %1.f%%\n",
+ (aGlobalJumps[0] / float(iGlobalJumps)) * 100.0,
+ (aGlobalJumps[1] / float(iGlobalJumps)) * 100.0,
+ (aGlobalJumps[2] / float(iGlobalJumps)) * 100.0);
+
+ return iBuf;
+}
+
+int FormatStreak(int client, int iTarget, int iStreak, char[] sBuf=0, int len=0)
+{
+ int iBuf = ConsoleFormat(client, sBuf, len, "[SM] Bunnyhop streak %d for %L\n", iStreak, iTarget);
+
+ CPlayer Player = g_aPlayers[iTarget];
+ ArrayList hStreaks = Player.hStreaks;
+ CStreak hStreak = Player.hStreak;
+ int iStreaks = hStreaks.Length;
+
+ // Try showing latest valid streak
+ if(iStreak <= 0 && !hStreak.bValid)
+ {
+ if(iStreaks)
+ hStreak = hStreaks.Get(iStreaks - 1);
+ }
+ else if(iStreak > 0)
+ {
+ if(iStreak > MAX_STREAKS)
+ {
+ iBuf += ConsoleFormat(client, sBuf[iBuf], len-iBuf, "[SM] Streak is out of bounds (max. %d)!\n", MAX_STREAKS);
+ return iBuf;
+ }
+
+ int iIndex = iStreaks - iStreak;
+ if(iIndex < 0)
+ {
+ iBuf += ConsoleFormat(client, sBuf[iBuf], len-iBuf, "[SM] Only %d streaks are available for this player right now!\n", iStreaks);
+ return iBuf;
+ }
+
+ hStreak = hStreaks.Get(iIndex);
+ }
+
+ int iStreakJumps = hStreak.iJumps;
+ float HyperRatio = hStreak.iHyperJumps / float(iStreakJumps);
+ float HackRatio = hStreak.iHackJumps / float(iStreakJumps);
+
+ iBuf += ConsoleFormat(client, sBuf[iBuf], len-iBuf, "Streak jumps: %d | Hyper?: %.1f%% | Hack?: %.1f%%\n",
+ iStreakJumps, HyperRatio * 100.0, HackRatio * 100.0);
+
+ int aStreakJumps[3];
+ hStreak.GetJumps(aStreakJumps);
+
+ iBuf += ConsoleFormat(client, sBuf[iBuf], len-iBuf, "Streak jumps perf group (1 2 +): %1.f%% %1.f%% %1.f%%\n",
+ (aStreakJumps[0] / float(iStreakJumps)) * 100.0,
+ (aStreakJumps[1] / float(iStreakJumps)) * 100.0,
+ (aStreakJumps[2] / float(iStreakJumps)) * 100.0);
+
+ iBuf += ConsoleFormat(client, sBuf[iBuf], len-iBuf, "#%2s %7s %5s %8s %4s %6s %s\n",
+ "id", " outvel", " gain", " avgdist", " num", " avg+-", "pattern");
+
+ ArrayList hJumps = hStreak.hJumps;
+ float fPrevVel = 0.0;
+ int iPrevEndTick = -1;
+
+ for(int i = 0; i < hJumps.Length; i++)
+ {
+ CJump hJump = hJumps.Get(i);
+ ArrayList hPresses = hJump.hPresses;
+
+ float fInVel = hJump.fStartVel;
+ float fOutVel = hJump.fEndVel;
+ int iEndTick = hJump.iEndTick;
+
+ static char sPattern[512];
+ int iPatternLen = 0;
+ int iPrevTick = -1;
+ int iTicks;
+
+ if(iPrevEndTick != -1)
+ {
+ iTicks = hJump.iStartTick - iPrevEndTick;
+ for(int k = 0; k < iTicks && k < 16; k++)
+ sPattern[iPatternLen++] = '|';
+ }
+
+ float fAvgDist = 0.0;
+ float fAvgDownUp = 0.0;
+
+ int iPresses = hPresses.Length;
+ for(int j = 0; j < iPresses; j++)
+ {
+ int aJunkJump[2];
+ hPresses.GetArray(j, aJunkJump);
+
+ if(iPrevTick != -1)
+ {
+ iTicks = aJunkJump[0] - iPrevTick;
+ for(int k = 0; k < iTicks && k < 16; k++)
+ sPattern[iPatternLen++] = '.';
+
+ fAvgDist += iTicks;
+ }
+
+ sPattern[iPatternLen++] = '^';
+
+ iTicks = aJunkJump[1] - aJunkJump[0];
+ for(int k = 0; k < iTicks && k < 16; k++)
+ sPattern[iPatternLen++] = ',';
+
+ fAvgDownUp += iTicks;
+
+ sPattern[iPatternLen++] = 'v';
+
+ iPrevTick = aJunkJump[1];
+ }
+
+ fAvgDist /= iPresses;
+ fAvgDownUp /= iPresses;
+
+ iTicks = iEndTick - iPrevTick;
+ for(int k = 0; k < iTicks && k < 16; k++)
+ sPattern[iPatternLen++] = '.';
+
+ sPattern[iPatternLen++] = '|';
+ sPattern[iPatternLen++] = '\0';
+
+ if(fPrevVel == 0.0)
+ fPrevVel = fInVel;
+
+ iBuf += ConsoleFormat(client, sBuf[iBuf], len-iBuf, "#%2d %7.1f %4d%% %8.2f %4d %6.2f %s\n",
+ i,
+ fOutVel,
+ fPrevVel == 0.0 ? 100 : RoundFloat((fOutVel / fPrevVel) * 100.0 - 100.0),
+ fAvgDist,
+ iPresses,
+ fAvgDownUp,
+ sPattern);
+
+ iPrevEndTick = iEndTick;
+ fPrevVel = fOutVel;
+ }
+
+ return iBuf;
+}
+
+bool Forward_OnDetected(int client, const char[] reason, const char[] stats)
+{
+ Call_StartForward(g_hOnClientDetected);
+ Call_PushCell(client);
+ Call_PushString(reason);
+ Call_PushString(stats);
+ Call_Finish();
+}
+
+stock int ConsoleFormat(int client, char[] buffer, int maxlength, const char[] format, any ...)
+{
+ if(client >= 1 && client <= MAXPLAYERS)
+ {
+ char sBuf[1024];
+ sBuf[VFormat(sBuf, sizeof(sBuf), format, 5) - 1] = 0;
+ PrintToConsole(client, "%s", sBuf);
+ }
+
+ if(maxlength > 0)
+ return VFormat(buffer, maxlength, format, 5);
+
+ return 0;
+}
diff --git a/AntiBhopCheat/scripting/CJump.inc b/AntiBhopCheat/scripting/CJump.inc
new file mode 100644
index 0000000..6bcc240
--- /dev/null
+++ b/AntiBhopCheat/scripting/CJump.inc
@@ -0,0 +1,118 @@
+#if defined _class_cjump_
+ #endinput
+#endif
+#define _class_cjump_
+
+methodmap CJump < Basic
+{
+ public CJump()
+ {
+ Basic myclass = new Basic();
+
+ myclass.SetInt("iStartTick", -1);
+ myclass.SetInt("iEndTick", -1);
+ myclass.SetFloat("fStartVel", 0.0);
+ myclass.SetFloat("fEndVel", 0.0);
+
+ myclass.SetInt("iPrevJump", -1);
+ myclass.SetInt("iNextJump", -1);
+
+ myclass.SetHandle("hPresses", new ArrayList(2));
+
+ return view_as(myclass);
+ }
+
+ property int iStartTick
+ {
+ public get()
+ {
+ return this.GetInt("iStartTick");
+ }
+ public set(int value)
+ {
+ this.SetInt("iStartTick", value);
+ }
+ }
+
+ property int iEndTick
+ {
+ public get()
+ {
+ return this.GetInt("iEndTick");
+ }
+ public set(int value)
+ {
+ this.SetInt("iEndTick", value);
+ }
+ }
+
+ property float fStartVel
+ {
+ public get()
+ {
+ return this.GetFloat("fStartVel");
+ }
+ public set(float value)
+ {
+ this.SetFloat("fStartVel", value);
+ }
+ }
+
+ property float fEndVel
+ {
+ public get()
+ {
+ return this.GetFloat("fEndVel");
+ }
+ public set(float value)
+ {
+ this.SetFloat("fEndVel", value);
+ }
+ }
+
+ property int iPrevJump
+ {
+ public get()
+ {
+ return this.GetInt("iPrevJump");
+ }
+ public set(int value)
+ {
+ this.SetInt("iPrevJump", value);
+ }
+ }
+
+ property int iNextJump
+ {
+ public get()
+ {
+ return this.GetInt("iNextJump");
+ }
+ public set(int value)
+ {
+ this.SetInt("iNextJump", value);
+ }
+ }
+
+ property ArrayList hPresses
+ {
+ public get()
+ {
+ return view_as(this.GetHandle("hPresses"));
+ }
+ public set(ArrayList value)
+ {
+ this.SetHandle("hPresses", value);
+ }
+ }
+
+ public void Dispose(bool disposemembers=true)
+ {
+ if(disposemembers)
+ {
+ delete this.hPresses;
+ }
+
+ delete this;
+ }
+}
diff --git a/AntiBhopCheat/scripting/CPlayer.inc b/AntiBhopCheat/scripting/CPlayer.inc
new file mode 100644
index 0000000..58a35ee
--- /dev/null
+++ b/AntiBhopCheat/scripting/CPlayer.inc
@@ -0,0 +1,193 @@
+#if defined _class_cplayer_
+ #endinput
+#endif
+#define _class_cplayer_
+
+methodmap CPlayer < Basic
+{
+ public CPlayer(int client)
+ {
+ Basic myclass = new Basic();
+
+ myclass.SetInt("iClient", client);
+ myclass.SetBool("bHackGlobal", false);
+ myclass.SetBool("bHyperGlobal", false);
+ myclass.SetInt("iHackFlagged", 0);
+ myclass.SetInt("iHyperFlagged", 0);
+
+ myclass.SetInt("iJumps", 0);
+ myclass.SetInt("iHyperJumps", 0);
+ myclass.SetInt("iHackJumps", 0);
+ myclass.SetArray("aJumps", {0, 0, 0}, 3);
+
+ myclass.SetInt("iLastStreakTick", -1);
+ myclass.SetHandle("hStreak", new CStreak());
+ myclass.SetHandle("hStreaks", new ArrayList(1));
+
+ return view_as(myclass);
+ }
+
+ property int iClient
+ {
+ public get()
+ {
+ return this.GetInt("iClient");
+ }
+ public set(int value)
+ {
+ this.SetInt("iClient", value);
+ }
+ }
+
+ property bool bHackGlobal
+ {
+ public get()
+ {
+ return this.GetBool("bHackGlobal");
+ }
+ public set(bool value)
+ {
+ this.SetBool("bHackGlobal", value);
+ }
+ }
+
+ property bool bHyperGlobal
+ {
+ public get()
+ {
+ return this.GetBool("bHyperGlobal");
+ }
+ public set(bool value)
+ {
+ this.SetBool("bHyperGlobal", value);
+ }
+ }
+
+ property int iHackFlagged
+ {
+ public get()
+ {
+ return this.GetInt("iHackFlagged");
+ }
+ public set(int value)
+ {
+ this.SetInt("iHackFlagged", value);
+ }
+ }
+
+ property int iHyperFlagged
+ {
+ public get()
+ {
+ return this.GetInt("iHyperFlagged");
+ }
+ public set(int value)
+ {
+ this.SetInt("iHyperFlagged", value);
+ }
+ }
+
+ property int iJumps
+ {
+ public get()
+ {
+ return this.GetInt("iJumps");
+ }
+ public set(int value)
+ {
+ this.SetInt("iJumps", value);
+ }
+ }
+
+ property int iHyperJumps
+ {
+ public get()
+ {
+ return this.GetInt("iHyperJumps");
+ }
+ public set(int value)
+ {
+ this.SetInt("iHyperJumps", value);
+ }
+ }
+
+ property int iHackJumps
+ {
+ public get()
+ {
+ return this.GetInt("iHackJumps");
+ }
+ public set(int value)
+ {
+ this.SetInt("iHackJumps", value);
+ }
+ }
+
+ property int iLastStreakTick
+ {
+ public get()
+ {
+ return this.GetInt("iLastStreakTick");
+ }
+ public set(int value)
+ {
+ this.SetInt("iLastStreakTick", value);
+ }
+ }
+
+ public void GetJumps(int value[3])
+ {
+ this.GetArray("aJumps", value, sizeof(value));
+ }
+
+ public void SetJumps(const int value[3])
+ {
+ this.SetArray("aJumps", value, sizeof(value));
+ }
+
+ property CStreak hStreak
+ {
+ public get()
+ {
+ return view_as(this.GetHandle("hStreak"));
+ }
+ public set(CStreak value)
+ {
+ this.SetHandle("hStreak", value);
+ }
+ }
+
+ property ArrayList hStreaks
+ {
+ public get()
+ {
+ return view_as(this.GetHandle("hStreaks"));
+ }
+ public set(ArrayList value)
+ {
+ this.SetHandle("hStreaks", value);
+ }
+ }
+
+ public void Dispose(bool disposemembers=true)
+ {
+ if(disposemembers)
+ {
+ ArrayList hStreaks = this.hStreaks;
+
+ CStreak hStreak;
+ for(int i = 0; i < hStreaks.Length; i++)
+ {
+ hStreak = view_as(hStreaks.Get(i));
+ hStreak.Dispose();
+ }
+
+ delete hStreaks;
+
+ if(this.hStreak != hStreak)
+ this.hStreak.Dispose();
+ }
+
+ delete this;
+ }
+}
diff --git a/AntiBhopCheat/scripting/CStreak.inc b/AntiBhopCheat/scripting/CStreak.inc
new file mode 100644
index 0000000..f4b4d28
--- /dev/null
+++ b/AntiBhopCheat/scripting/CStreak.inc
@@ -0,0 +1,163 @@
+#if defined _class_cstreak_
+ #endinput
+#endif
+#define _class_cstreak_
+
+methodmap CStreak < Basic
+{
+ public CStreak()
+ {
+ Basic myclass = new Basic();
+
+ myclass.SetBool("bValid", false);
+ myclass.SetInt("iStartTick", -1);
+ myclass.SetInt("iEndTick", -1);
+ myclass.SetFloat("fStartVel", 0.0);
+ myclass.SetFloat("fEndVel", 0.0);
+
+ myclass.SetInt("iJumps", 0);
+ myclass.SetInt("iHyperJumps", 0);
+ myclass.SetInt("iHackJumps", 0);
+ myclass.SetArray("aJumps", {0, 0, 0}, 3);
+
+ myclass.SetHandle("hJumps", new ArrayList(1));
+
+ return view_as(myclass);
+ }
+
+ property bool bValid
+ {
+ public get()
+ {
+ return this.GetBool("bValid");
+ }
+ public set(bool value)
+ {
+ this.SetBool("bValid", value);
+ }
+ }
+
+ property int iStartTick
+ {
+ public get()
+ {
+ return this.GetInt("iStartTick");
+ }
+ public set(int value)
+ {
+ this.SetInt("iStartTick", value);
+ }
+ }
+
+ property int iEndTick
+ {
+ public get()
+ {
+ return this.GetInt("iEndTick");
+ }
+ public set(int value)
+ {
+ this.SetInt("iEndTick", value);
+ }
+ }
+
+ property float fStartVel
+ {
+ public get()
+ {
+ return this.GetFloat("fStartVel");
+ }
+ public set(float value)
+ {
+ this.SetFloat("fStartVel", value);
+ }
+ }
+
+ property float fEndVel
+ {
+ public get()
+ {
+ return this.GetFloat("fEndVel");
+ }
+ public set(float value)
+ {
+ this.SetFloat("fEndVel", value);
+ }
+ }
+
+ property int iJumps
+ {
+ public get()
+ {
+ return this.GetInt("iJumps");
+ }
+ public set(int value)
+ {
+ this.SetInt("iJumps", value);
+ }
+ }
+
+ property int iHyperJumps
+ {
+ public get()
+ {
+ return this.GetInt("iHyperJumps");
+ }
+ public set(int value)
+ {
+ this.SetInt("iHyperJumps", value);
+ }
+ }
+
+ property int iHackJumps
+ {
+ public get()
+ {
+ return this.GetInt("iHackJumps");
+ }
+ public set(int value)
+ {
+ this.SetInt("iHackJumps", value);
+ }
+ }
+
+ public void GetJumps(int value[3])
+ {
+ this.GetArray("aJumps", value, sizeof(value));
+ }
+
+ public void SetJumps(const int value[3])
+ {
+ this.SetArray("aJumps", value, sizeof(value));
+ }
+
+ property ArrayList hJumps
+ {
+ public get()
+ {
+ return view_as(this.GetHandle("hJumps"));
+ }
+ public set(ArrayList value)
+ {
+ this.SetHandle("hJumps", value);
+ }
+ }
+
+ public void Dispose(bool disposemembers=true)
+ {
+ if(disposemembers)
+ {
+ ArrayList hJumps = this.hJumps;
+
+ for(int i = 0; i < hJumps.Length; i++)
+ {
+ CJump hJump = view_as(hJumps.Get(i));
+ hJump.Dispose();
+ }
+
+ delete hJumps;
+ }
+
+ delete this;
+ }
+}
diff --git a/AntiBhopCheat/scripting/include/AntiBhopCheat.inc b/AntiBhopCheat/scripting/include/AntiBhopCheat.inc
new file mode 100644
index 0000000..0b968fb
--- /dev/null
+++ b/AntiBhopCheat/scripting/include/AntiBhopCheat.inc
@@ -0,0 +1,6 @@
+#if defined _AntiBhopCheat_Included
+ #endinput
+#endif
+#define _AntiBhopCheat_Included
+
+forward void AntiBhopCheat_OnClientDetected(int client, char[] sReason, char[] sStats);
\ No newline at end of file
diff --git a/BSPConvarAllower/content/bspconvar_whitelist_permanent.txt b/BSPConvarAllower/content/bspconvar_whitelist_permanent.txt
new file mode 100644
index 0000000..9cd9071
--- /dev/null
+++ b/BSPConvarAllower/content/bspconvar_whitelist_permanent.txt
@@ -0,0 +1,25 @@
+"convars"
+{
+ say 1
+ exec 1
+ sm_cvar 1
+ sm_say 1
+
+ zr_infect_mzombie_ratio 1
+ zr_infect_mzombie_respawn 1
+ zr_infect_spawntime_max 1
+ zr_infect_spawntime_min 1
+ zr_roundend_overlay 1
+ zr_roundend_overlays_zombie 1
+ zr_roundend_overlays_human 1
+ zr_ambientsounds_volume 1
+ zr_respawn 1
+ zr_respawn_delay 1
+ zr_respawn_team_zombie 1
+ zr_respawn_team_zombie_world 1
+ zr_class_modify 1
+ zr_roundend_overlays_zombie 1
+ zr_roundend_overlays_human 1
+
+ sm_gravity 1
+}
diff --git a/BSPConvarAllower/scripting/BspConvarAllower.sp b/BSPConvarAllower/scripting/BspConvarAllower.sp
new file mode 100644
index 0000000..4c468d9
--- /dev/null
+++ b/BSPConvarAllower/scripting/BspConvarAllower.sp
@@ -0,0 +1,104 @@
+#pragma semicolon 1
+#pragma newdecls required
+
+#include
+#include
+#include
+
+KeyValues kv;
+KeyValues config;
+Handle hAcceptInput;
+
+public Plugin myinfo = {
+ name = "BSP ConVar Allower",
+ author = "SHUFEN from POSSESSION.tokyo, fix by xen",
+ description = "Allows server commands to maps",
+ version = "0.2",
+ url = "https://possession.tokyo"
+};
+
+public void OnPluginStart() {
+ if (!CheckTxtFile_bspconvar_whitelist()) return;
+
+ if (hAcceptInput == null) {
+ char tmpOffset[148];
+
+ switch(GetEngineVersion()) {
+ case Engine_CSGO:
+ tmpOffset = "sdktools.games\\engine.csgo";
+ default:
+ SetFailState("This plugin is only for CS:GO");
+ }
+
+ Handle temp = LoadGameConfigFile(tmpOffset);
+
+ if (temp == null)
+ SetFailState("Why you no has gamedata?");
+
+ int offset = GameConfGetOffset(temp, "AcceptInput");
+ hAcceptInput = DHookCreate(offset, HookType_Entity, ReturnType_Bool, ThisPointer_CBaseEntity, AcceptInput);
+ DHookAddParam(hAcceptInput, HookParamType_CharPtr);
+ DHookAddParam(hAcceptInput, HookParamType_CBaseEntity);
+ DHookAddParam(hAcceptInput, HookParamType_CBaseEntity);
+ DHookAddParam(hAcceptInput, HookParamType_Object, 20, DHookPass_ByVal|DHookPass_ODTOR|DHookPass_OCTOR|DHookPass_OASSIGNOP);
+ DHookAddParam(hAcceptInput, HookParamType_Int);
+
+ delete temp;
+ }
+}
+
+public void OnPluginEnd() {
+ if (kv != INVALID_HANDLE)
+ delete kv;
+ if (config != INVALID_HANDLE)
+ delete config;
+}
+
+bool CheckTxtFile_bspconvar_whitelist() {
+ if (kv != INVALID_HANDLE)
+ delete kv;
+ kv = new KeyValues("convars");
+ if (!kv.ImportFromFile("bspconvar_whitelist.txt")) {
+ SetFailState("Couldn't get KeyValues from bspconvar_whitelist.txt");
+ return false;
+ }
+ if (config != INVALID_HANDLE)
+ delete config;
+ config = new KeyValues("convars");
+ if (!config.ImportFromFile("bspconvar_whitelist_permanent.txt")) {
+ SetFailState("Couldn't get KeyValues from bspconvar_whitelist_permanent.txt");
+ return false;
+ }
+ return true;
+}
+
+public void OnEntityCreated(int entity, const char[] classname) {
+ if (StrEqual(classname, "point_servercommand", false))
+ DHookEntity(hAcceptInput, false, entity);
+}
+
+public MRESReturn AcceptInput(int entity, Handle hReturn, Handle hParams) {
+ if (!IsValidEntity(entity))
+ return MRES_Ignored;
+
+ char eCommand[128], eParam[256], eServerCommand[64];
+
+ DHookGetParamString(hParams, 1, eCommand, 128);
+
+ if (StrEqual(eCommand, "Command", false)) {
+ int type = DHookGetParamObjectPtrVar(hParams, 4, 16, ObjectValueType_Int);
+ if (type == 2) {
+ DHookGetParamObjectPtrString(hParams, 4, 0, ObjectValueType_String, eParam, 256);
+
+ SplitString(eParam, " ", eServerCommand, 64);
+ if (kv.JumpToKey(eServerCommand, false) || config.JumpToKey(eServerCommand, false)) {
+ PrintToServer("[BSPConvarAllower] Allowing \"%s\"", eParam);
+ ServerCommand(eParam);
+ }
+ kv.Rewind();
+ config.Rewind();
+ }
+ }
+
+ return MRES_Ignored;
+}
diff --git a/BossHP/configs/MapBossHP/Template.txt b/BossHP/configs/MapBossHP/Template.txt
new file mode 100644
index 0000000..2e3f28c
--- /dev/null
+++ b/BossHP/configs/MapBossHP/Template.txt
@@ -0,0 +1,87 @@
+"math_counter"
+{
+ "config"
+ {
+ "ForceEnable" "" //强制显示实体血量(bhud) 1=开启(默认) 0=关闭
+ "RoundEndShowTopDamage" "" //回合结束显示输出排行 1=开启(默认) 0=关闭
+ "ShowTopDamageDuringBOSS" "" //打BOSS期间显示输出排行 1=开启 0=关闭(默认)
+ "BossBeatenShowTopDamage" ""
+ "CrosshairChannel" "" //击中BOSS准星通道 范围1-6 默认=5
+ "BossRewardMoney" "" //击中BOSS奖励金钱 默认=10
+ "BossHpKeepTime" "" //BOSS HP数值维持显示时间 (数值无变动超过该秒数将不再显示) 默认=10
+ "BossDieKeepTime" "" //BOSS阵亡后HP数值维持显示时间 默认=1 该秒数必须低于上面的秒数
+ "DisplayWhenHPAdded" ""
+ "MaxLegalBreakableHP" ""
+ "MaxLegalMathCounterHP" ""
+ }
+ "config"
+ {
+ "ForceEnable" ""
+ "RoundEndShowTopDamage" ""
+ "ShowTopDamageDuringBOSS" ""
+ "BossBeatenShowTopDamage" ""
+ "CrosshairChannel" ""
+ "BossRewardMoney" ""
+ "BossHpKeepTime" ""
+ "BossDieKeepTime" ""
+ "DisplayWhenHPAdded" ""
+ "MaxLegalBreakableHP" ""
+ "MaxLegalMathCounterHP" ""
+ }
+
+
+ "0" //math_counter
+ {
+ "HP_counter" "" //实体名
+ "HPbar_counter" "" //实体名
+ "HPinit_counter" "" //实体名
+ "CustomText" "" //Boss名
+ }
+ "0"
+ {
+ "HP_counter" ""
+ "HPbar_counter" ""
+ "HPinit_counter" ""
+ "CustomText" ""
+ }
+
+
+ "0" //FFXIV V2_8 V4_10
+ {
+ "HP_Group"
+ {
+ "0" ""
+ "1" ""
+ "2" ""
+ "3" ""
+ "4" ""
+ }
+ "CustomText" ""
+ }
+ "0"
+ {
+ "HP_Group"
+ {
+ "0" ""
+ "1" ""
+ "2" ""
+ "3" ""
+ "4" ""
+ }
+ "CustomText" ""
+ }
+
+
+ "1" //func_breakable or func_physbox
+ {
+ "Type" "breakable"
+ "BreakableName" "" //实体名
+ "CustomText" "" //BOSS名
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" ""
+ "CustomText" ""
+ }
+}
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_666_crazy_escape_v1_1.txt b/BossHP/configs/MapBossHP/ze_666_crazy_escape_v1_1.txt
new file mode 100644
index 0000000..4cc7bc6
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_666_crazy_escape_v1_1.txt
@@ -0,0 +1,21 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "nrk1_boss_laser_counter"
+ "HP_Mode" "1"
+ "HPbar_counter" "nrk1_boss_hp_iterations"
+ "HPinit_counter" "nrk1_boss_hp_backup"
+ "CustomText" ""
+ "HPbar_mode" "1"
+ }
+ "1"
+ {
+ "HP_counter" "nrk1_counter"
+ "HP_Mode" "1"
+ "HPbar_counter" "nrk1_hp_iterations"
+ "HPinit_counter" "nrk1_hp_backup"
+ "CustomText" ""
+ "HPbar_mode" "1"
+ }
+}
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_8bit_csgo2.txt b/BossHP/configs/MapBossHP/ze_8bit_csgo2.txt
new file mode 100644
index 0000000..864454f
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_8bit_csgo2.txt
@@ -0,0 +1,52 @@
+"math_counter"
+{
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "Boss_box_1"
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "Boss_box_2"
+ }
+
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "Boss_box_3"
+ }
+
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "Boss_box_4"
+ }
+
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "Boss_box_5"
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "Boss6_1"
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "Ponch_Box_1"
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "Govno_Box"
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "Pidaras_Boss6"
+ }
+
+}
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_A_E_S_T_H_E_T_I_C_v1_1.txt b/BossHP/configs/MapBossHP/ze_A_E_S_T_H_E_T_I_C_v1_1.txt
new file mode 100644
index 0000000..18a4516
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_A_E_S_T_H_E_T_I_C_v1_1.txt
@@ -0,0 +1,15 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "Boss_Mini_HP1"
+ }
+ "1"
+ {
+ "HP_counter" "Boss_Mini_HP2"
+ }
+ "2"
+ {
+ "HP_counter" "EyesHP"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_Bathroom_v2_5.txt b/BossHP/configs/MapBossHP/ze_Bathroom_v2_5.txt
new file mode 100644
index 0000000..c0e531d
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_Bathroom_v2_5.txt
@@ -0,0 +1,23 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "krokodyl_counter"
+ "HPbar_counter" "krokodyl_hp_iterations"
+ "HPinit_counter" "krokodyl_hp_backup"
+ "HPbar_min" ""
+ "HPbar_max" "5"
+ "HPbar_default" "5"
+ "HPbar_mode" "1"
+ }
+ "1"
+ {
+ "HP_counter" "kostka_hp"
+ "HPbar_counter" "kostka_hp_iterations"
+ "HPinit_counter" "kostka_hp_backup"
+ "HPbar_min" ""
+ "HPbar_max" "8"
+ "HPbar_default" "8"
+ "HPbar_mode" "1"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_FFXIV_Wanderers_Palace_v6.txt b/BossHP/configs/MapBossHP/ze_FFXIV_Wanderers_Palace_v6.txt
new file mode 100644
index 0000000..e4c3701
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_FFXIV_Wanderers_Palace_v6.txt
@@ -0,0 +1,29 @@
+"math_counter"
+{
+ "config"
+ {
+ "ForceEnable" "0"
+ "BossRewardMoney" "1"
+ }
+ "0"
+ {
+ "HP_counter" "Boss_HP_Counter"
+ }
+ "1"
+ {
+ "HP_counter" "Ultima_Weapon_HP_Counter"
+ "CustomText" "Ultima Weapon"
+ }
+ "2"
+ {
+ "Type" "breakable"
+ "BreakableName" "Aqua_Breakable"
+ "CustomText" "Ice Wall"
+ }
+ "3"
+ {
+ "Type" "breakable"
+ "BreakableName" "Final_Kain_Highwind_Hitbox"
+ "CustomText" "Final Kain Highwind"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_FFXIV_Wanderers_Palace_v6_beta.txt b/BossHP/configs/MapBossHP/ze_FFXIV_Wanderers_Palace_v6_beta.txt
new file mode 100644
index 0000000..248ffd1
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_FFXIV_Wanderers_Palace_v6_beta.txt
@@ -0,0 +1,33 @@
+"math_counter"
+{
+ "config"
+ {
+ "ForceEnable" "0"
+ "BossRewardMoney" "1"
+ }
+ "0"
+ {
+ "HP_counter" "Boss_HP_Counter"
+ }
+ "1"
+ {
+ "HP_counter" "Ultima_Weapon_HP_Counter"
+ "HP_Mode" "1"
+ "HPbar_counter" "Ultima_Weapon_HP_Phase_Counter"
+ "HPinit_counter" "Ultima_Weapon_HP_Initial"
+ "CustomText" "Ultima Weapon"
+ "HPbar_mode" "2"
+ }
+ "2"
+ {
+ "Type" "breakable"
+ "BreakableName" "Aqua_Breakable"
+ "CustomText" "Ice Wall"
+ }
+ "3"
+ {
+ "Type" "breakable"
+ "BreakableName" "Final_Kain_Highwind_Hitbox"
+ "CustomText" "Final Kain Highwind"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_Naruto_p.txt b/BossHP/configs/MapBossHP/ze_Naruto_p.txt
new file mode 100644
index 0000000..f0757e9
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_Naruto_p.txt
@@ -0,0 +1,8 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "health_boss"
+ "CustomText" "Sasuke"
+ }
+}
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_PKMN_Adventure_v7_6.txt b/BossHP/configs/MapBossHP/ze_PKMN_Adventure_v7_6.txt
new file mode 100644
index 0000000..0333cfa
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_PKMN_Adventure_v7_6.txt
@@ -0,0 +1,88 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "crobatcyrushp"
+ "CustomText" "Crobat"
+ }
+ "1"
+ {
+ "HP_counter" "crobatfinal2_health"
+ "CustomText" "Crobat"
+ }
+ "2"
+ {
+ "HP_counter" "finalkirlia_hp"
+ "CustomText" "Kirlia"
+ }
+ "3"
+ {
+ "HP_counter" "giratinahp"
+ "CustomText" "Giratina"
+ }
+ "4"
+ {
+ "HP_counter" "groudonhp"
+ "CustomText" "Groudon"
+ }
+ "5"
+ {
+ "HP_counter" "honchkrowhp"
+ "CustomText" "Honchkrow"
+ }
+ "6"
+ {
+ "HP_counter" "puruglyhealth"
+ "CustomText" "Purugly"
+ }
+ "7"
+ {
+ "HP_counter" "regicehealth"
+ "CustomText" "Regice"
+ }
+ "8"
+ {
+ "HP_counter" "skuntankhealth"
+ "CustomText" "Skuntank"
+ }
+ "9"
+ {
+ "HP_counter" "weavilefinalhp"
+ "CustomText" "Weavile"
+ }
+ "10"
+ {
+ "HP_counter" "weavilehp"
+ "CustomText" "Weavile"
+ }
+ "10"
+ {
+ "HP_counter" "PrimalGroudonHP"
+ "CustomText" "Primal Groudon"
+ }
+ "11"
+ {
+ "HP_counter" "ArceusHP_1"
+ "CustomText" "Arceus(1/4)"
+ }
+ "11"
+ {
+ "HP_counter" "ArceusHP_2"
+ "CustomText" "Arceus(2/4)"
+ }
+ "11"
+ {
+ "HP_counter" "ArceusHP_3"
+ "CustomText" "Arceus(3/4)"
+ }
+ "11"
+ {
+ "HP_counter" "ArceusHP_4"
+ "CustomText" "Arceus(4/4)"
+ }
+ "10"
+ {
+ "HP_counter" "Arceus_Judgement_HP"
+ "CustomText" "Judgement"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_PKMN_Adventure_v8_2.txt b/BossHP/configs/MapBossHP/ze_PKMN_Adventure_v8_2.txt
new file mode 100644
index 0000000..0333cfa
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_PKMN_Adventure_v8_2.txt
@@ -0,0 +1,88 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "crobatcyrushp"
+ "CustomText" "Crobat"
+ }
+ "1"
+ {
+ "HP_counter" "crobatfinal2_health"
+ "CustomText" "Crobat"
+ }
+ "2"
+ {
+ "HP_counter" "finalkirlia_hp"
+ "CustomText" "Kirlia"
+ }
+ "3"
+ {
+ "HP_counter" "giratinahp"
+ "CustomText" "Giratina"
+ }
+ "4"
+ {
+ "HP_counter" "groudonhp"
+ "CustomText" "Groudon"
+ }
+ "5"
+ {
+ "HP_counter" "honchkrowhp"
+ "CustomText" "Honchkrow"
+ }
+ "6"
+ {
+ "HP_counter" "puruglyhealth"
+ "CustomText" "Purugly"
+ }
+ "7"
+ {
+ "HP_counter" "regicehealth"
+ "CustomText" "Regice"
+ }
+ "8"
+ {
+ "HP_counter" "skuntankhealth"
+ "CustomText" "Skuntank"
+ }
+ "9"
+ {
+ "HP_counter" "weavilefinalhp"
+ "CustomText" "Weavile"
+ }
+ "10"
+ {
+ "HP_counter" "weavilehp"
+ "CustomText" "Weavile"
+ }
+ "10"
+ {
+ "HP_counter" "PrimalGroudonHP"
+ "CustomText" "Primal Groudon"
+ }
+ "11"
+ {
+ "HP_counter" "ArceusHP_1"
+ "CustomText" "Arceus(1/4)"
+ }
+ "11"
+ {
+ "HP_counter" "ArceusHP_2"
+ "CustomText" "Arceus(2/4)"
+ }
+ "11"
+ {
+ "HP_counter" "ArceusHP_3"
+ "CustomText" "Arceus(3/4)"
+ }
+ "11"
+ {
+ "HP_counter" "ArceusHP_4"
+ "CustomText" "Arceus(4/4)"
+ }
+ "10"
+ {
+ "HP_counter" "Arceus_Judgement_HP"
+ "CustomText" "Judgement"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_PKMN_Adventure_v9c.txt b/BossHP/configs/MapBossHP/ze_PKMN_Adventure_v9c.txt
new file mode 100644
index 0000000..0333cfa
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_PKMN_Adventure_v9c.txt
@@ -0,0 +1,88 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "crobatcyrushp"
+ "CustomText" "Crobat"
+ }
+ "1"
+ {
+ "HP_counter" "crobatfinal2_health"
+ "CustomText" "Crobat"
+ }
+ "2"
+ {
+ "HP_counter" "finalkirlia_hp"
+ "CustomText" "Kirlia"
+ }
+ "3"
+ {
+ "HP_counter" "giratinahp"
+ "CustomText" "Giratina"
+ }
+ "4"
+ {
+ "HP_counter" "groudonhp"
+ "CustomText" "Groudon"
+ }
+ "5"
+ {
+ "HP_counter" "honchkrowhp"
+ "CustomText" "Honchkrow"
+ }
+ "6"
+ {
+ "HP_counter" "puruglyhealth"
+ "CustomText" "Purugly"
+ }
+ "7"
+ {
+ "HP_counter" "regicehealth"
+ "CustomText" "Regice"
+ }
+ "8"
+ {
+ "HP_counter" "skuntankhealth"
+ "CustomText" "Skuntank"
+ }
+ "9"
+ {
+ "HP_counter" "weavilefinalhp"
+ "CustomText" "Weavile"
+ }
+ "10"
+ {
+ "HP_counter" "weavilehp"
+ "CustomText" "Weavile"
+ }
+ "10"
+ {
+ "HP_counter" "PrimalGroudonHP"
+ "CustomText" "Primal Groudon"
+ }
+ "11"
+ {
+ "HP_counter" "ArceusHP_1"
+ "CustomText" "Arceus(1/4)"
+ }
+ "11"
+ {
+ "HP_counter" "ArceusHP_2"
+ "CustomText" "Arceus(2/4)"
+ }
+ "11"
+ {
+ "HP_counter" "ArceusHP_3"
+ "CustomText" "Arceus(3/4)"
+ }
+ "11"
+ {
+ "HP_counter" "ArceusHP_4"
+ "CustomText" "Arceus(4/4)"
+ }
+ "10"
+ {
+ "HP_counter" "Arceus_Judgement_HP"
+ "CustomText" "Judgement"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_S_A_M_a29.txt b/BossHP/configs/MapBossHP/ze_S_A_M_a29.txt
new file mode 100644
index 0000000..f68bd12
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_S_A_M_a29.txt
@@ -0,0 +1,92 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "lvl4_boss_hp"
+ "HPbar_counter" "lvl4_boss_hpbar_counter"
+ "HPinit_counter" "lvl4_boss_hp_init"
+ "CustomText" "Barlog"
+ "HPbar_min" ""
+ "HPbar_max" "9"
+ "HPbar_default" "1"
+ "HPbar_mode" "2"
+ }
+ "1"
+ {
+ "HP_counter" "lvl2_boss_dark_hp"
+ "CustomText" "Dark"
+ }
+ "2"
+ {
+ "HP_counter" "lvl2_boss_fire_hp"
+ "CustomText" "Fire"
+ }
+ "3"
+ {
+ "HP_counter" "lvl2_boss_hp"
+ }
+ "4"
+ {
+ "HP_counter" "lvl2_boss_ice_hp"
+ "CustomText" "Ice"
+ }
+ "5"
+ {
+ "HP_counter" "lvl2_boss_light_hp"
+ "CustomText" "Light"
+ }
+ "6"
+ {
+ "HP_counter" "lvl3_boss_hp"
+ "HPbar_counter" "lvl3_boss_hpbar_counter"
+ "HPinit_counter" "lvl3_boss_hp_init"
+ "CustomText" "Dragon"
+ "HPbar_min" ""
+ "HPbar_max" "9"
+ "HPbar_default" "1"
+ "HPbar_mode" "2"
+ }
+ "7"
+ {
+ "HP_counter" "lvl4_boss2_hp"
+ "CustomText" "Barlog"
+ }
+ "8"
+ {
+ "HP_counter" "Troll_health"
+ "HPbar_counter" "Troll_hpbar_counter"
+ "HPinit_counter" "Troll_hp_init"
+ "CustomText" "Troll"
+ "HPbar_min" ""
+ "HPbar_max" "9"
+ "HPbar_default" "1"
+ "HPbar_mode" "2"
+ }
+ "9"
+ {
+ "HP_counter" "lvl5_boss_hp_1"
+ "HPbar_counter" "lvl5_boss_hpbar_counter_1"
+ "HPinit_counter" "lvl5_boss_hp_init_1"
+ "CustomText" "Sword Castle"
+ "HPbar_min" ""
+ "HPbar_max" "9"
+ "HPbar_default" "1"
+ "HPbar_mode" "2"
+ }
+ "10"
+ {
+ "HP_counter" "lvl5_finalboss_hp"
+ }
+ "11"
+ {
+ "HP_counter" "lvl5_laserboss_hp"
+ }
+ "12"
+ {
+ "HP_counter" "darklaser_hp_1"
+ }
+ "13"
+ {
+ "HP_counter" "darklaser_hp_2"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_S_A_M_a32.txt b/BossHP/configs/MapBossHP/ze_S_A_M_a32.txt
new file mode 100644
index 0000000..87cdf09
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_S_A_M_a32.txt
@@ -0,0 +1,65 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "lvl4_boss_hp"
+ "HPbar_counter" "lvl4_boss_hpbar_counter"
+ "HPinit_counter" "lvl4_boss_hp_init"
+ "CustomText" "Barlog"
+ "HPbar_min" ""
+ "HPbar_max" "9"
+ "HPbar_default" "1"
+ "HPbar_mode" "2"
+ }
+ "1"
+ {
+ "HP_counter" "lvl2_boss_dark_hp"
+ "CustomText" "Dark"
+ }
+ "2"
+ {
+ "HP_counter" "lvl2_boss_fire_hp"
+ "CustomText" "Fire"
+ }
+ "3"
+ {
+ "HP_counter" "lvl2_boss_hp"
+ }
+ "4"
+ {
+ "HP_counter" "lvl2_boss_ice_hp"
+ "CustomText" "Ice"
+ }
+ "5"
+ {
+ "HP_counter" "lvl2_boss_light_hp"
+ "CustomText" "Light"
+ }
+ "6"
+ {
+ "HP_counter" "lvl3_boss_hp"
+ "HPbar_counter" "lvl3_boss_hpbar_counter"
+ "HPinit_counter" "lvl3_boss_hp_init"
+ "CustomText" "Dragon"
+ "HPbar_min" ""
+ "HPbar_max" "9"
+ "HPbar_default" "1"
+ "HPbar_mode" "2"
+ }
+ "7"
+ {
+ "HP_counter" "lvl4_boss2_hp"
+ "CustomText" "Barlog"
+ }
+ "8"
+ {
+ "HP_counter" "Troll_health"
+ "HPbar_counter" "Troll_hpbar_counter"
+ "HPinit_counter" "Troll_hp_init"
+ "CustomText" "Troll"
+ "HPbar_min" ""
+ "HPbar_max" "9"
+ "HPbar_default" "1"
+ "HPbar_mode" "2"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_S_A_M_a33.txt b/BossHP/configs/MapBossHP/ze_S_A_M_a33.txt
new file mode 100644
index 0000000..f68bd12
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_S_A_M_a33.txt
@@ -0,0 +1,92 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "lvl4_boss_hp"
+ "HPbar_counter" "lvl4_boss_hpbar_counter"
+ "HPinit_counter" "lvl4_boss_hp_init"
+ "CustomText" "Barlog"
+ "HPbar_min" ""
+ "HPbar_max" "9"
+ "HPbar_default" "1"
+ "HPbar_mode" "2"
+ }
+ "1"
+ {
+ "HP_counter" "lvl2_boss_dark_hp"
+ "CustomText" "Dark"
+ }
+ "2"
+ {
+ "HP_counter" "lvl2_boss_fire_hp"
+ "CustomText" "Fire"
+ }
+ "3"
+ {
+ "HP_counter" "lvl2_boss_hp"
+ }
+ "4"
+ {
+ "HP_counter" "lvl2_boss_ice_hp"
+ "CustomText" "Ice"
+ }
+ "5"
+ {
+ "HP_counter" "lvl2_boss_light_hp"
+ "CustomText" "Light"
+ }
+ "6"
+ {
+ "HP_counter" "lvl3_boss_hp"
+ "HPbar_counter" "lvl3_boss_hpbar_counter"
+ "HPinit_counter" "lvl3_boss_hp_init"
+ "CustomText" "Dragon"
+ "HPbar_min" ""
+ "HPbar_max" "9"
+ "HPbar_default" "1"
+ "HPbar_mode" "2"
+ }
+ "7"
+ {
+ "HP_counter" "lvl4_boss2_hp"
+ "CustomText" "Barlog"
+ }
+ "8"
+ {
+ "HP_counter" "Troll_health"
+ "HPbar_counter" "Troll_hpbar_counter"
+ "HPinit_counter" "Troll_hp_init"
+ "CustomText" "Troll"
+ "HPbar_min" ""
+ "HPbar_max" "9"
+ "HPbar_default" "1"
+ "HPbar_mode" "2"
+ }
+ "9"
+ {
+ "HP_counter" "lvl5_boss_hp_1"
+ "HPbar_counter" "lvl5_boss_hpbar_counter_1"
+ "HPinit_counter" "lvl5_boss_hp_init_1"
+ "CustomText" "Sword Castle"
+ "HPbar_min" ""
+ "HPbar_max" "9"
+ "HPbar_default" "1"
+ "HPbar_mode" "2"
+ }
+ "10"
+ {
+ "HP_counter" "lvl5_finalboss_hp"
+ }
+ "11"
+ {
+ "HP_counter" "lvl5_laserboss_hp"
+ }
+ "12"
+ {
+ "HP_counter" "darklaser_hp_1"
+ }
+ "13"
+ {
+ "HP_counter" "darklaser_hp_2"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_S_A_M_a39.txt b/BossHP/configs/MapBossHP/ze_S_A_M_a39.txt
new file mode 100644
index 0000000..f68bd12
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_S_A_M_a39.txt
@@ -0,0 +1,92 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "lvl4_boss_hp"
+ "HPbar_counter" "lvl4_boss_hpbar_counter"
+ "HPinit_counter" "lvl4_boss_hp_init"
+ "CustomText" "Barlog"
+ "HPbar_min" ""
+ "HPbar_max" "9"
+ "HPbar_default" "1"
+ "HPbar_mode" "2"
+ }
+ "1"
+ {
+ "HP_counter" "lvl2_boss_dark_hp"
+ "CustomText" "Dark"
+ }
+ "2"
+ {
+ "HP_counter" "lvl2_boss_fire_hp"
+ "CustomText" "Fire"
+ }
+ "3"
+ {
+ "HP_counter" "lvl2_boss_hp"
+ }
+ "4"
+ {
+ "HP_counter" "lvl2_boss_ice_hp"
+ "CustomText" "Ice"
+ }
+ "5"
+ {
+ "HP_counter" "lvl2_boss_light_hp"
+ "CustomText" "Light"
+ }
+ "6"
+ {
+ "HP_counter" "lvl3_boss_hp"
+ "HPbar_counter" "lvl3_boss_hpbar_counter"
+ "HPinit_counter" "lvl3_boss_hp_init"
+ "CustomText" "Dragon"
+ "HPbar_min" ""
+ "HPbar_max" "9"
+ "HPbar_default" "1"
+ "HPbar_mode" "2"
+ }
+ "7"
+ {
+ "HP_counter" "lvl4_boss2_hp"
+ "CustomText" "Barlog"
+ }
+ "8"
+ {
+ "HP_counter" "Troll_health"
+ "HPbar_counter" "Troll_hpbar_counter"
+ "HPinit_counter" "Troll_hp_init"
+ "CustomText" "Troll"
+ "HPbar_min" ""
+ "HPbar_max" "9"
+ "HPbar_default" "1"
+ "HPbar_mode" "2"
+ }
+ "9"
+ {
+ "HP_counter" "lvl5_boss_hp_1"
+ "HPbar_counter" "lvl5_boss_hpbar_counter_1"
+ "HPinit_counter" "lvl5_boss_hp_init_1"
+ "CustomText" "Sword Castle"
+ "HPbar_min" ""
+ "HPbar_max" "9"
+ "HPbar_default" "1"
+ "HPbar_mode" "2"
+ }
+ "10"
+ {
+ "HP_counter" "lvl5_finalboss_hp"
+ }
+ "11"
+ {
+ "HP_counter" "lvl5_laserboss_hp"
+ }
+ "12"
+ {
+ "HP_counter" "darklaser_hp_1"
+ }
+ "13"
+ {
+ "HP_counter" "darklaser_hp_2"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_S_A_M_v1.txt b/BossHP/configs/MapBossHP/ze_S_A_M_v1.txt
new file mode 100644
index 0000000..f68bd12
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_S_A_M_v1.txt
@@ -0,0 +1,92 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "lvl4_boss_hp"
+ "HPbar_counter" "lvl4_boss_hpbar_counter"
+ "HPinit_counter" "lvl4_boss_hp_init"
+ "CustomText" "Barlog"
+ "HPbar_min" ""
+ "HPbar_max" "9"
+ "HPbar_default" "1"
+ "HPbar_mode" "2"
+ }
+ "1"
+ {
+ "HP_counter" "lvl2_boss_dark_hp"
+ "CustomText" "Dark"
+ }
+ "2"
+ {
+ "HP_counter" "lvl2_boss_fire_hp"
+ "CustomText" "Fire"
+ }
+ "3"
+ {
+ "HP_counter" "lvl2_boss_hp"
+ }
+ "4"
+ {
+ "HP_counter" "lvl2_boss_ice_hp"
+ "CustomText" "Ice"
+ }
+ "5"
+ {
+ "HP_counter" "lvl2_boss_light_hp"
+ "CustomText" "Light"
+ }
+ "6"
+ {
+ "HP_counter" "lvl3_boss_hp"
+ "HPbar_counter" "lvl3_boss_hpbar_counter"
+ "HPinit_counter" "lvl3_boss_hp_init"
+ "CustomText" "Dragon"
+ "HPbar_min" ""
+ "HPbar_max" "9"
+ "HPbar_default" "1"
+ "HPbar_mode" "2"
+ }
+ "7"
+ {
+ "HP_counter" "lvl4_boss2_hp"
+ "CustomText" "Barlog"
+ }
+ "8"
+ {
+ "HP_counter" "Troll_health"
+ "HPbar_counter" "Troll_hpbar_counter"
+ "HPinit_counter" "Troll_hp_init"
+ "CustomText" "Troll"
+ "HPbar_min" ""
+ "HPbar_max" "9"
+ "HPbar_default" "1"
+ "HPbar_mode" "2"
+ }
+ "9"
+ {
+ "HP_counter" "lvl5_boss_hp_1"
+ "HPbar_counter" "lvl5_boss_hpbar_counter_1"
+ "HPinit_counter" "lvl5_boss_hp_init_1"
+ "CustomText" "Sword Castle"
+ "HPbar_min" ""
+ "HPbar_max" "9"
+ "HPbar_default" "1"
+ "HPbar_mode" "2"
+ }
+ "10"
+ {
+ "HP_counter" "lvl5_finalboss_hp"
+ }
+ "11"
+ {
+ "HP_counter" "lvl5_laserboss_hp"
+ }
+ "12"
+ {
+ "HP_counter" "darklaser_hp_1"
+ }
+ "13"
+ {
+ "HP_counter" "darklaser_hp_2"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_S_A_M_v1_4.txt b/BossHP/configs/MapBossHP/ze_S_A_M_v1_4.txt
new file mode 100644
index 0000000..f68bd12
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_S_A_M_v1_4.txt
@@ -0,0 +1,92 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "lvl4_boss_hp"
+ "HPbar_counter" "lvl4_boss_hpbar_counter"
+ "HPinit_counter" "lvl4_boss_hp_init"
+ "CustomText" "Barlog"
+ "HPbar_min" ""
+ "HPbar_max" "9"
+ "HPbar_default" "1"
+ "HPbar_mode" "2"
+ }
+ "1"
+ {
+ "HP_counter" "lvl2_boss_dark_hp"
+ "CustomText" "Dark"
+ }
+ "2"
+ {
+ "HP_counter" "lvl2_boss_fire_hp"
+ "CustomText" "Fire"
+ }
+ "3"
+ {
+ "HP_counter" "lvl2_boss_hp"
+ }
+ "4"
+ {
+ "HP_counter" "lvl2_boss_ice_hp"
+ "CustomText" "Ice"
+ }
+ "5"
+ {
+ "HP_counter" "lvl2_boss_light_hp"
+ "CustomText" "Light"
+ }
+ "6"
+ {
+ "HP_counter" "lvl3_boss_hp"
+ "HPbar_counter" "lvl3_boss_hpbar_counter"
+ "HPinit_counter" "lvl3_boss_hp_init"
+ "CustomText" "Dragon"
+ "HPbar_min" ""
+ "HPbar_max" "9"
+ "HPbar_default" "1"
+ "HPbar_mode" "2"
+ }
+ "7"
+ {
+ "HP_counter" "lvl4_boss2_hp"
+ "CustomText" "Barlog"
+ }
+ "8"
+ {
+ "HP_counter" "Troll_health"
+ "HPbar_counter" "Troll_hpbar_counter"
+ "HPinit_counter" "Troll_hp_init"
+ "CustomText" "Troll"
+ "HPbar_min" ""
+ "HPbar_max" "9"
+ "HPbar_default" "1"
+ "HPbar_mode" "2"
+ }
+ "9"
+ {
+ "HP_counter" "lvl5_boss_hp_1"
+ "HPbar_counter" "lvl5_boss_hpbar_counter_1"
+ "HPinit_counter" "lvl5_boss_hp_init_1"
+ "CustomText" "Sword Castle"
+ "HPbar_min" ""
+ "HPbar_max" "9"
+ "HPbar_default" "1"
+ "HPbar_mode" "2"
+ }
+ "10"
+ {
+ "HP_counter" "lvl5_finalboss_hp"
+ }
+ "11"
+ {
+ "HP_counter" "lvl5_laserboss_hp"
+ }
+ "12"
+ {
+ "HP_counter" "darklaser_hp_1"
+ }
+ "13"
+ {
+ "HP_counter" "darklaser_hp_2"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_ShroomForest3_p.txt b/BossHP/configs/MapBossHP/ze_ShroomForest3_p.txt
new file mode 100644
index 0000000..62ab514
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_ShroomForest3_p.txt
@@ -0,0 +1,106 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "Boss_Health"
+ "HPbar_counter" "Boss_HealthCount"
+ "HPinit_counter" "Boss_HealthInit"
+ "HPbar_min" ""
+ "HPbar_max" "5"
+ "HPbar_default" ""
+ "HPbar_mode" "2"
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "Hitler_Boss_Tank1_Break"
+ "CustomText" "Tank1"
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "Hitler_Boss_Tank2_Break"
+ "CustomText" "Tank2"
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "House_ClockBattery_Break1"
+ "CustomText" "Clock"
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "House_ClockBattery_Break2"
+ "CustomText" "Battery"
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "Spider_Break1"
+ "CustomText" "Spider1"
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "Spider_Break2"
+ "CustomText" "Spider2"
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "Spider_Break3"
+ "CustomText" "Spider3"
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "Spider_Break4"
+ "CustomText" "Spider4"
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "Spider_Break5"
+ "CustomText" "Spider5"
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "Spider_Break6"
+ "CustomText" "Spider6"
+ }
+ "1"
+ {
+ "HP_counter" "Skeleton_Boss_Health1"
+ "HPbar_counter" "Skeleton_Boss_HealthCount1"
+ "HPinit_counter" "Skeleton_Boss_HealthInit1"
+ "CustomText" "Skeleton 1"
+ "HPbar_min" ""
+ "HPbar_max" "5"
+ "HPbar_default" ""
+ "HPbar_mode" "2"
+ }
+ "2"
+ {
+ "HP_counter" "Skeleton_Boss_Health2"
+ "HPbar_counter" "Skeleton_Boss_HealthCount2"
+ "HPinit_counter" "Skeleton_Boss_HealthInit2"
+ "CustomText" "Skeleton 2"
+ "HPbar_min" ""
+ "HPbar_max" "5"
+ "HPbar_default" ""
+ "HPbar_mode" "2"
+ }
+ "3"
+ {
+ "HP_counter" "Skeleton_Boss_Health3"
+ "HPbar_counter" "Skeleton_Boss_HealthCount3"
+ "HPinit_counter" "Skeleton_Boss_HealthInit3"
+ "CustomText" "Skeleton 3"
+ "HPbar_min" ""
+ "HPbar_max" "5"
+ "HPbar_default" ""
+ "HPbar_mode" "2"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_Sit_Caelum_Paradisus_b7.txt b/BossHP/configs/MapBossHP/ze_Sit_Caelum_Paradisus_b7.txt
new file mode 100644
index 0000000..e69de29
diff --git a/BossHP/configs/MapBossHP/ze_UT2004_Convoy_p2.txt b/BossHP/configs/MapBossHP/ze_UT2004_Convoy_p2.txt
new file mode 100644
index 0000000..8bde1e7
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_UT2004_Convoy_p2.txt
@@ -0,0 +1,7 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "boss_counter2"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_alien_shooter_v7_ps4.txt b/BossHP/configs/MapBossHP/ze_alien_shooter_v7_ps4.txt
new file mode 100644
index 0000000..7784595
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_alien_shooter_v7_ps4.txt
@@ -0,0 +1,18 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "counter1"
+ "HP_Mode" "1"
+ "HPbar_counter" "counter3"
+ "HPbar_mode" "1"
+ "CustomText" "Alien"
+ }
+ "1"
+ {
+ "HP_counter" "roshi_counter"
+ "HP_Mode" "1"
+ "HPbar_mode" "1"
+ "CustomText" "Roshi"
+ }
+}
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_ancient_wrath_r4.txt b/BossHP/configs/MapBossHP/ze_ancient_wrath_r4.txt
new file mode 100644
index 0000000..ca34aeb
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_ancient_wrath_r4.txt
@@ -0,0 +1,29 @@
+"math_counter"
+{
+ "config"
+ {
+ "BossDieKeepTime" "5"
+ }
+ "0"
+ {
+ "HP_counter" "boss_3_knockback_1_counter"
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "boss_3_energy_1"
+ "CustomText" "Energy Tube(Left)"
+ }
+ "2"
+ {
+ "Type" "breakable"
+ "BreakableName" "boss_3_energy_2"
+ "CustomText" "Energy Tube(Right)"
+ }
+ "3"
+ {
+ "Type" "breakable"
+ "BreakableName" "boss_3_container"
+ "CustomText" "Core"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_ancient_wrath_v1_2.txt b/BossHP/configs/MapBossHP/ze_ancient_wrath_v1_2.txt
new file mode 100644
index 0000000..4e7d6d3
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_ancient_wrath_v1_2.txt
@@ -0,0 +1,23 @@
+"math_counter"
+{
+ "config"
+ {
+ "BossDieKeepTime" "5"
+ }
+ "0"
+ {
+ "HP_counter" "boss_3_knockback_1_counter"
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "boss_3_energy_1"
+ "CustomText" "Energy1"
+ }
+ "2"
+ {
+ "Type" "breakable"
+ "BreakableName" "boss_3_energy_2"
+ "CustomText" "Energy2"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_biohazard3_nemesis_b5_2.txt b/BossHP/configs/MapBossHP/ze_biohazard3_nemesis_b5_2.txt
new file mode 100644
index 0000000..9606a04
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_biohazard3_nemesis_b5_2.txt
@@ -0,0 +1,8 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "Special_Health"
+ "HP_Mode" "1"
+ }
+}
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_bioshock_v6_2_csgo4.txt b/BossHP/configs/MapBossHP/ze_bioshock_v6_2_csgo4.txt
new file mode 100644
index 0000000..a20ef52
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_bioshock_v6_2_csgo4.txt
@@ -0,0 +1,43 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "bouncer_Health_BarHP"
+ "HPbar_counter" "bouncer_Health_HP"
+ "HPbar_min" ""
+ "HPbar_max" "5"
+ "HPbar_default" ""
+ "HPbar_mode" "2"
+ }
+ "1"
+ {
+ "HP_counter" "cohen_Health_BarHP"
+ "HPbar_counter" "cohen_Health_HP"
+ "HPbar_min" ""
+ "HPbar_max" "5"
+ "HPbar_default" ""
+ "HPbar_mode" "2"
+ }
+ "2"
+ {
+ "HP_counter" "fontaine_Health_BarHP"
+ "HPbar_counter" "fontaine_Health_HP"
+ "HPbar_min" ""
+ "HPbar_max" "6"
+ "HPbar_default" ""
+ "HPbar_mode" "2"
+ }
+ "3"
+ {
+ "HP_counter" "songbird_finale_health"
+ }
+ "4"
+ {
+ "HP_counter" "songbird_Health_BarHP"
+ "HPbar_counter" "songbird_Health_HP"
+ "HPbar_min" ""
+ "HPbar_max" "5"
+ "HPbar_default" ""
+ "HPbar_mode" "2"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_bioshock_v6_2_csgo6.txt b/BossHP/configs/MapBossHP/ze_bioshock_v6_2_csgo6.txt
new file mode 100644
index 0000000..a20ef52
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_bioshock_v6_2_csgo6.txt
@@ -0,0 +1,43 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "bouncer_Health_BarHP"
+ "HPbar_counter" "bouncer_Health_HP"
+ "HPbar_min" ""
+ "HPbar_max" "5"
+ "HPbar_default" ""
+ "HPbar_mode" "2"
+ }
+ "1"
+ {
+ "HP_counter" "cohen_Health_BarHP"
+ "HPbar_counter" "cohen_Health_HP"
+ "HPbar_min" ""
+ "HPbar_max" "5"
+ "HPbar_default" ""
+ "HPbar_mode" "2"
+ }
+ "2"
+ {
+ "HP_counter" "fontaine_Health_BarHP"
+ "HPbar_counter" "fontaine_Health_HP"
+ "HPbar_min" ""
+ "HPbar_max" "6"
+ "HPbar_default" ""
+ "HPbar_mode" "2"
+ }
+ "3"
+ {
+ "HP_counter" "songbird_finale_health"
+ }
+ "4"
+ {
+ "HP_counter" "songbird_Health_BarHP"
+ "HPbar_counter" "songbird_Health_HP"
+ "HPbar_min" ""
+ "HPbar_max" "5"
+ "HPbar_default" ""
+ "HPbar_mode" "2"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_bisounours_party_go_v3fix.txt b/BossHP/configs/MapBossHP/ze_bisounours_party_go_v3fix.txt
new file mode 100644
index 0000000..be069c5
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_bisounours_party_go_v3fix.txt
@@ -0,0 +1,15 @@
+"math_counter"
+{
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "Pedobear_lvl1"
+ "CustomText" "Pedobear"
+ }
+ "2"
+ {
+ "Type" "breakable"
+ "BreakableName" "Pedobear_lvl2"
+ "CustomText" "Pedobear"
+ }
+}
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_bisounours_party_p2.txt b/BossHP/configs/MapBossHP/ze_bisounours_party_p2.txt
new file mode 100644
index 0000000..947a7bd
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_bisounours_party_p2.txt
@@ -0,0 +1,21 @@
+"math_counter"
+{
+ "0"
+ {
+ "Type" "breakable"
+ "BreakableName" "Statue"
+ "CustomText" "Statue"
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "Pedobear_lvl1"
+ "CustomText" "Pedobear"
+ }
+ "2"
+ {
+ "Type" "breakable"
+ "BreakableName" "Pedobear_lvl2"
+ "CustomText" "Pedobear"
+ }
+}
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_boatescape999_v4_4.txt b/BossHP/configs/MapBossHP/ze_boatescape999_v4_4.txt
new file mode 100644
index 0000000..4ad4d26
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_boatescape999_v4_4.txt
@@ -0,0 +1,33 @@
+"math_counter"
+{
+ "0"
+ {
+ "Type" "breakable"
+ "BreakableName" "Mode_8_Chaos_Box"
+ "CustomText" "Chaos - 轮回王"
+ }
+ "0"
+ {
+ "Type" "breakable"
+ "BreakableName" "Mode_7_Zodiark_Box"
+ "CustomText" "Zodiark - 戒律王"
+ }
+ "0"
+ {
+ "Type" "breakable"
+ "BreakableName" "Mode_5_Genesis_Box"
+ "CustomText" "Genesis - 杰内西斯"
+ }
+ "0"
+ {
+ "Type" "breakable"
+ "BreakableName" "Mode_2_Sephiroth_Box"
+ "CustomText" "Sephiroth - 萨菲罗斯"
+ }
+ "0"
+ {
+ "Type" "breakable"
+ "BreakableName" "Mode_1_Bahamut_Box"
+ "CustomText" "Bahamut - 巴哈姆特"
+ }
+}
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_boredom_p.txt b/BossHP/configs/MapBossHP/ze_boredom_p.txt
new file mode 100644
index 0000000..9c0df4c
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_boredom_p.txt
@@ -0,0 +1,27 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "CacoDemonHP"
+ }
+ "1"
+ {
+ "HP_counter" "LostSoulHP"
+ }
+ "2"
+ {
+ "HP_counter" "DemonHP"
+ }
+ "3"
+ {
+ "HP_counter" "ImpHP"
+ }
+ "4"
+ {
+ "HP_counter" "PaperCounter"
+ }
+ "5"
+ {
+ "HP_counter" "AssaHP"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_castlevania_p1_7.txt b/BossHP/configs/MapBossHP/ze_castlevania_p1_7.txt
new file mode 100644
index 0000000..5eaa5ba
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_castlevania_p1_7.txt
@@ -0,0 +1,12 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "boss_counter"
+ "HPbar_counter" "boss_hpbar_overlaycounter"
+ "HPbar_min" "0"
+ "HPbar_max" "10"
+ "HPbar_default" "10"
+ "HPbar_mode" "1" // OnHitMin=1 OnHitMax=2
+ }
+}
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_chaos_v7_4f.txt b/BossHP/configs/MapBossHP/ze_chaos_v7_4f.txt
new file mode 100644
index 0000000..535b1f5
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_chaos_v7_4f.txt
@@ -0,0 +1,27 @@
+"math_counter"
+{
+ //Stage 2 Boss HP
+ "0"
+ {
+ "HP_Group"
+ {
+ "0" "level2_counter_2"
+ "1" "level2_counter_2_1"
+ "2" "level2_counter_2_2"
+ "3" "level2_counter_2_3"
+ "4" "level2_counter_2_4"
+ }
+ }
+ //Stage 3 Boss HP
+ "1"
+ {
+ "HP_Group"
+ {
+ "0" "counter_2"
+ "1" "counter_2_1"
+ "2" "counter_2_2"
+ "3" "counter_2_3"
+ "4" "counter_2_4"
+ }
+ }
+}
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_chemical_weapons_depot_v3_1.txt b/BossHP/configs/MapBossHP/ze_chemical_weapons_depot_v3_1.txt
new file mode 100644
index 0000000..71d6e2d
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_chemical_weapons_depot_v3_1.txt
@@ -0,0 +1,13 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "HPCounter"
+ "HPbar_counter" "HPCounterIterator"
+ "HPinit_counter" "HPCounterBackUp"
+ "HPbar_min" ""
+ "HPbar_max" "40"
+ "HPbar_default" "40"
+ "HPbar_mode" "1"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_christmas_b2_1.txt b/BossHP/configs/MapBossHP/ze_christmas_b2_1.txt
new file mode 100644
index 0000000..b4f8a1b
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_christmas_b2_1.txt
@@ -0,0 +1,11 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "Boss_Health"
+ "HP_Mode" "1"
+ "HPbar_counter" "Boss_HealthCount"
+ "HPinit_counter" "Boss_HealthInit"
+ "HPbar_mode" "2"
+ }
+}
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_chroma_v0_4_csgo1.txt b/BossHP/configs/MapBossHP/ze_chroma_v0_4_csgo1.txt
new file mode 100644
index 0000000..6f24cab
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_chroma_v0_4_csgo1.txt
@@ -0,0 +1,57 @@
+"math_counter"
+{
+ "config"
+ {
+ "RoundEndShowTopDamage" "1"
+ "ShowTopDamageDuringBOSS" "0"
+ "ForceEnable" "1"
+ }
+ "1" //func_breakable or func_physbox
+ {
+ "Type" "breakable"
+ "BreakableName" "pbox_boss7"
+ "CustomText" "Boss"
+ }
+ "1" //func_breakable or func_physbox
+ {
+ "Type" "breakable"
+ "BreakableName" "pbox_boss6"
+ "CustomText" "Boss"
+ }
+ "1" //func_breakable or func_physbox
+ {
+ "Type" "breakable"
+ "BreakableName" "pbox_boss5"
+ "CustomText" "Boss"
+ }
+ "1" //func_breakable or func_physbox
+ {
+ "Type" "breakable"
+ "BreakableName" "pbox_boss4"
+ "CustomText" "Boss"
+ }
+ "1" //func_breakable or func_physbox
+ {
+ "Type" "breakable"
+ "BreakableName" "pbox_boss3"
+ "CustomText" "Boss"
+ }
+ "1" //func_breakable or func_physbox
+ {
+ "Type" "breakable"
+ "BreakableName" "pbox_boss2"
+ "CustomText" "Boss"
+ }
+ "1" //func_breakable or func_physbox
+ {
+ "Type" "breakable"
+ "BreakableName" "pbox_boss1"
+ "CustomText" "Boss"
+ }
+ "1" //func_breakable or func_physbox
+ {
+ "Type" "breakable"
+ "BreakableName" "pbox_boss"
+ "CustomText" "Boss"
+ }
+}
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_copy_escape_a01_15.txt b/BossHP/configs/MapBossHP/ze_copy_escape_a01_15.txt
new file mode 100644
index 0000000..b6a5828
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_copy_escape_a01_15.txt
@@ -0,0 +1,31 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "boss2_hp_add"
+ "HPbar_counter" "boss2_hp"
+ "HPbar_min" "0"
+ "HPbar_max" "10"
+ "HPbar_default" "0"
+ "HPbar_mode" "2"
+ }
+ "1"
+ {
+ "HP_counter" "cube_hp"
+ "CustomText" "Cube"
+ }
+ "1"
+ {
+ "HP_counter" "cube_hp_"
+ "CustomText" "Cube"
+ }
+ "1"
+ {
+ "HP_counter" "hp_counter"
+ "HPbar_counter" "hp"
+ "HPbar_min" "0"
+ "HPbar_max" "10"
+ "HPbar_default" "0"
+ "HPbar_mode" "2"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_copy_escape_a02_05.txt b/BossHP/configs/MapBossHP/ze_copy_escape_a02_05.txt
new file mode 100644
index 0000000..602b6ca
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_copy_escape_a02_05.txt
@@ -0,0 +1,35 @@
+"math_counter"
+{
+ "config"
+ {
+ "IsDynamicHP" "1"
+ }
+ "0"
+ {
+ "HP_counter" "boss2_hp_add"
+ "HPbar_counter" "boss2_hp"
+ "HPbar_min" "0"
+ "HPbar_max" "10"
+ "HPbar_default" "0"
+ "HPbar_mode" "2"
+ }
+ "1"
+ {
+ "HP_counter" "cube_hp"
+ "CustomText" "Cube"
+ }
+ "1"
+ {
+ "HP_counter" "cube_hp_"
+ "CustomText" "Cube"
+ }
+ "1"
+ {
+ "HP_counter" "hp_counter"
+ "HPbar_counter" "hp"
+ "HPbar_min" "0"
+ "HPbar_max" "10"
+ "HPbar_default" "0"
+ "HPbar_mode" "2"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_copy_escape_a03_19.txt b/BossHP/configs/MapBossHP/ze_copy_escape_a03_19.txt
new file mode 100644
index 0000000..602b6ca
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_copy_escape_a03_19.txt
@@ -0,0 +1,35 @@
+"math_counter"
+{
+ "config"
+ {
+ "IsDynamicHP" "1"
+ }
+ "0"
+ {
+ "HP_counter" "boss2_hp_add"
+ "HPbar_counter" "boss2_hp"
+ "HPbar_min" "0"
+ "HPbar_max" "10"
+ "HPbar_default" "0"
+ "HPbar_mode" "2"
+ }
+ "1"
+ {
+ "HP_counter" "cube_hp"
+ "CustomText" "Cube"
+ }
+ "1"
+ {
+ "HP_counter" "cube_hp_"
+ "CustomText" "Cube"
+ }
+ "1"
+ {
+ "HP_counter" "hp_counter"
+ "HPbar_counter" "hp"
+ "HPbar_min" "0"
+ "HPbar_max" "10"
+ "HPbar_default" "0"
+ "HPbar_mode" "2"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_copy_escape_v1_1.txt b/BossHP/configs/MapBossHP/ze_copy_escape_v1_1.txt
new file mode 100644
index 0000000..602b6ca
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_copy_escape_v1_1.txt
@@ -0,0 +1,35 @@
+"math_counter"
+{
+ "config"
+ {
+ "IsDynamicHP" "1"
+ }
+ "0"
+ {
+ "HP_counter" "boss2_hp_add"
+ "HPbar_counter" "boss2_hp"
+ "HPbar_min" "0"
+ "HPbar_max" "10"
+ "HPbar_default" "0"
+ "HPbar_mode" "2"
+ }
+ "1"
+ {
+ "HP_counter" "cube_hp"
+ "CustomText" "Cube"
+ }
+ "1"
+ {
+ "HP_counter" "cube_hp_"
+ "CustomText" "Cube"
+ }
+ "1"
+ {
+ "HP_counter" "hp_counter"
+ "HPbar_counter" "hp"
+ "HPbar_min" "0"
+ "HPbar_max" "10"
+ "HPbar_default" "0"
+ "HPbar_mode" "2"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_crazy_escape_v5_5_1.txt b/BossHP/configs/MapBossHP/ze_crazy_escape_v5_5_1.txt
new file mode 100644
index 0000000..5f8019d
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_crazy_escape_v5_5_1.txt
@@ -0,0 +1,38 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "naraka_counter"
+ "HPbar_counter" "naraka_hp_iterations"
+ "HPinit_counter" "naraka_hp_backup"
+ "HPbar_min" ""
+ "HPbar_max" "5"
+ "HPbar_default" "5"
+ "HPbar_mode" "1"
+ }
+ "1"
+ {
+ "HP_counter" "naraka_counter2"
+ "HPbar_counter" "naraka_hp_iterations2"
+ "HPinit_counter" "naraka_hp_backup2"
+ "HPbar_min" ""
+ "HPbar_max" "5"
+ "HPbar_default" "5"
+ "HPbar_mode" "1"
+ }
+ "2"
+ {
+ "HP_counter" "naraka_ultimate_counter"
+ "HPbar_counter" "naraka_ultimate_hp_iterations"
+ "HPinit_counter" "naraka_ultimate_hp_backup"
+ "HPbar_min" ""
+ "HPbar_max" "5"
+ "HPbar_default" "5"
+ "HPbar_mode" "1"
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "BossCage"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_dark_souls_ptd_v0_4_csgo.txt b/BossHP/configs/MapBossHP/ze_dark_souls_ptd_v0_4_csgo.txt
new file mode 100644
index 0000000..a9abce3
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_dark_souls_ptd_v0_4_csgo.txt
@@ -0,0 +1,43 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "Asylum_Demon_Counter"
+ "CustomText" "Asylum Demon"
+ }
+ "1"
+ {
+ "HP_counter" "Broadhead_Counter"
+ "CustomText" "Broad Head"
+ }
+ "2"
+ {
+ "HP_counter" "Golem_Counter"
+ "CustomText" "Golem"
+ }
+ "3"
+ {
+ "HP_counter" "Gwyndolin_Counter"
+ "CustomText" "Gwyndolin"
+ }
+ "4"
+ {
+ "HP_counter" "2Ornstein_Counter"
+ "CustomText" "Ornstein"
+ }
+ "5"
+ {
+ "HP_counter" "Phase2_Counter"
+ "CustomText" "Phase2"
+ }
+ "6"
+ {
+ "HP_counter" "Gargoyle_Counter"
+ "CustomText" "Gargoyle"
+ }
+ "7"
+ {
+ "HP_counter" "Gwyn_Counter"
+ "CustomText" "Gwyn"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_dark_souls_ptd_v0_4_csgo5.txt b/BossHP/configs/MapBossHP/ze_dark_souls_ptd_v0_4_csgo5.txt
new file mode 100644
index 0000000..a9abce3
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_dark_souls_ptd_v0_4_csgo5.txt
@@ -0,0 +1,43 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "Asylum_Demon_Counter"
+ "CustomText" "Asylum Demon"
+ }
+ "1"
+ {
+ "HP_counter" "Broadhead_Counter"
+ "CustomText" "Broad Head"
+ }
+ "2"
+ {
+ "HP_counter" "Golem_Counter"
+ "CustomText" "Golem"
+ }
+ "3"
+ {
+ "HP_counter" "Gwyndolin_Counter"
+ "CustomText" "Gwyndolin"
+ }
+ "4"
+ {
+ "HP_counter" "2Ornstein_Counter"
+ "CustomText" "Ornstein"
+ }
+ "5"
+ {
+ "HP_counter" "Phase2_Counter"
+ "CustomText" "Phase2"
+ }
+ "6"
+ {
+ "HP_counter" "Gargoyle_Counter"
+ "CustomText" "Gargoyle"
+ }
+ "7"
+ {
+ "HP_counter" "Gwyn_Counter"
+ "CustomText" "Gwyn"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_deadcore_c18.txt b/BossHP/configs/MapBossHP/ze_deadcore_c18.txt
new file mode 100644
index 0000000..e926799
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_deadcore_c18.txt
@@ -0,0 +1,12 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "radiation_hpcounter"
+ "HPbar_counter" "radiation_hpmasscounter"
+ "HPbar_min" ""
+ "HPbar_max" "10"
+ "HPbar_default" ""
+ "HPbar_mode" "2"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_deadcore_v1_3.txt b/BossHP/configs/MapBossHP/ze_deadcore_v1_3.txt
new file mode 100644
index 0000000..e926799
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_deadcore_v1_3.txt
@@ -0,0 +1,12 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "radiation_hpcounter"
+ "HPbar_counter" "radiation_hpmasscounter"
+ "HPbar_min" ""
+ "HPbar_max" "10"
+ "HPbar_default" ""
+ "HPbar_mode" "2"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_destruction_of_exorath_v4_lite.txt b/BossHP/configs/MapBossHP/ze_destruction_of_exorath_v4_lite.txt
new file mode 100644
index 0000000..0fceaf2
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_destruction_of_exorath_v4_lite.txt
@@ -0,0 +1,30 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "healbar_counter_extreme"
+ "HPbar_counter" "healbar_count_total2"
+ "HPbar_min" ""
+ "HPbar_max" "12"
+ "HPbar_default" ""
+ "HPbar_mode" "2"
+ }
+ "1"
+ {
+ "HP_counter" "healbar_counter_god"
+ "HPbar_counter" "healbar_count_total2"
+ "HPbar_min" ""
+ "HPbar_max" "12"
+ "HPbar_default" ""
+ "HPbar_mode" "2"
+ }
+ "2"
+ {
+ "HP_counter" "healbar_counter_impossible"
+ "HPbar_counter" "healbar_count_total2"
+ "HPbar_min" ""
+ "HPbar_max" "12"
+ "HPbar_default" ""
+ "HPbar_mode" "2"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_diddle_v3.txt b/BossHP/configs/MapBossHP/ze_diddle_v3.txt
new file mode 100644
index 0000000..d479c8d
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_diddle_v3.txt
@@ -0,0 +1,69 @@
+"math_counter"
+{
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "Ord_lvl_02_boss_break"
+ "CustomText" ""
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "X69XTurtleBossHP1"
+ "CustomText" ""
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "X69XTurtleBosshp2"
+ "CustomText" ""
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "X69XOrd_main_large_diglett_break"
+ "CustomText" ""
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "X69XOrd_main_mid_diglett_break"
+ "CustomText" ""
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "Ord_lvl_01_boss_break"
+ "CustomText" ""
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "X69XOrd_main_little_diglett_break"
+ "CustomText" ""
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "X69Xluff_npc_phys2gg"
+ "CustomText" ""
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "i_npc_hp_1"
+ "CustomText" ""
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "seal"
+ "CustomText" ""
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "dd_hp"
+ "CustomText" ""
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_doorhug_and_solo_v5_2_csgo.txt b/BossHP/configs/MapBossHP/ze_doorhug_and_solo_v5_2_csgo.txt
new file mode 100644
index 0000000..b80850f
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_doorhug_and_solo_v5_2_csgo.txt
@@ -0,0 +1,11 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "Boss_Counter"
+ }
+ "1"
+ {
+ "HP_counter" "Monster_ZM_Counter"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_dreamin_v1_9_1.txt b/BossHP/configs/MapBossHP/ze_dreamin_v1_9_1.txt
new file mode 100644
index 0000000..6aa92ed
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_dreamin_v1_9_1.txt
@@ -0,0 +1,16 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "blade_hp"
+ }
+ "1"
+ {
+ "HP_counter" "HPCounter2"
+ "HPbar_counter" "HPCounterIterator2"
+ "HPbar_min" ""
+ "HPbar_max" "8"
+ "HPbar_default" ""
+ "HPbar_mode" "2"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_dreamin_v2_1.txt b/BossHP/configs/MapBossHP/ze_dreamin_v2_1.txt
new file mode 100644
index 0000000..7c2ad6d
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_dreamin_v2_1.txt
@@ -0,0 +1,21 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "blade_hp"
+ }
+ "0"
+ {
+ "HP_counter" "st3_hp"
+ }
+ "0"
+ {
+ "HP_counter" "final_hp"
+ }
+ "1"
+ {
+ "HP_counter" "HPCounter2"
+ "HPbar_counter" "HPCounterIterator2"
+ "HPbar_mode" "1"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_dreamin_v2_3.txt b/BossHP/configs/MapBossHP/ze_dreamin_v2_3.txt
new file mode 100644
index 0000000..0a28437
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_dreamin_v2_3.txt
@@ -0,0 +1,27 @@
+"math_counter"
+{
+ "0"
+ {
+ "Type" "breakable"
+ "BreakableName" "st2_hitbox"
+ }
+ "1"
+ {
+ "HP_counter" "final_hp"
+ }
+ "2"
+ {
+ "HP_counter" "st3_hp"
+ }
+ "3"
+ {
+ "HP_counter" "HPCounter2"
+ "HP_Mode" "1"
+ "HPbar_counter" "HPCounterIterator2"
+ "HPbar_mode" "1"
+ }
+ "4"
+ {
+ "HP_counter" "blade_hp"
+ }
+}
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_dreamin_v2b.txt b/BossHP/configs/MapBossHP/ze_dreamin_v2b.txt
new file mode 100644
index 0000000..6aa92ed
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_dreamin_v2b.txt
@@ -0,0 +1,16 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "blade_hp"
+ }
+ "1"
+ {
+ "HP_counter" "HPCounter2"
+ "HPbar_counter" "HPCounterIterator2"
+ "HPbar_min" ""
+ "HPbar_max" "8"
+ "HPbar_default" ""
+ "HPbar_mode" "2"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_dreamin_v2c.txt b/BossHP/configs/MapBossHP/ze_dreamin_v2c.txt
new file mode 100644
index 0000000..7c2ad6d
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_dreamin_v2c.txt
@@ -0,0 +1,21 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "blade_hp"
+ }
+ "0"
+ {
+ "HP_counter" "st3_hp"
+ }
+ "0"
+ {
+ "HP_counter" "final_hp"
+ }
+ "1"
+ {
+ "HP_counter" "HPCounter2"
+ "HPbar_counter" "HPCounterIterator2"
+ "HPbar_mode" "1"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_eternal_grove_v3.txt b/BossHP/configs/MapBossHP/ze_eternal_grove_v3.txt
new file mode 100644
index 0000000..87c07bb
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_eternal_grove_v3.txt
@@ -0,0 +1,8 @@
+"math_counter"
+{
+ "0"
+ {
+ "Type" "breakable"
+ "BreakableName" "i_minotaurgod_hp"
+ }
+}
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_evernight_a2_4c.txt b/BossHP/configs/MapBossHP/ze_evernight_a2_4c.txt
new file mode 100644
index 0000000..a720131
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_evernight_a2_4c.txt
@@ -0,0 +1,11 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "imagebasileusis_hp"
+ }
+ "1"
+ {
+ "HP_counter" "act2_boss_hp"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_evernight_a3_1c.txt b/BossHP/configs/MapBossHP/ze_evernight_a3_1c.txt
new file mode 100644
index 0000000..c9d5b91
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_evernight_a3_1c.txt
@@ -0,0 +1,64 @@
+"math_counter"
+{
+ "config"
+ {
+ "MultBoss" "1"
+ }
+ "0"
+ {
+ "HP_counter" "Boss_1_Hp"
+ "HPbar_counter" "Boss_1_Hp_Overlay"
+ "HPinit_counter" "Boss_1_Hp_Init"
+ "CustomText" "Basil"
+ "HPbar_min" "0"
+ "HPbar_max" "10"
+ "HPbar_mode" "1"
+ }
+ "0"
+ {
+ "HP_counter" "Boss_2_Hp"
+ "HPbar_counter" "Boss_2_Hp_Overlay"
+ "HPinit_counter" "Boss_2_Hp_Init"
+ "CustomText" "Watcher(BOSS)"
+ "HPbar_min" "0"
+ "HPbar_max" "10"
+ "HPbar_mode" "1"
+ }
+ "0"
+ {
+ "HP_counter" "Boss_3_Hp"
+ "HPbar_counter" "Boss_3_Hp_Overlay"
+ "HPinit_counter" "Boss_3_Hp_Init"
+ "CustomText" "Gradyrat"
+ "HPbar_min" "0"
+ "HPbar_max" "10"
+ "HPbar_mode" "1"
+ }
+
+ "2"
+ {
+ "HP_counter" "Boss_2_Hp_Lava"
+ "CustomText" "Lava"
+ }
+ "3"
+ {
+ "HP_counter" "Boss_2_Hp_Blizzard"
+ "CustomText" "Blizzard"
+ }
+ "4"
+ {
+ "HP_counter" "Boss_2_Hp_Hurricane"
+ "CustomText" "Hurricane"
+ }
+ "5"
+ {
+ "HP_counter" "Boss_2_Hp_Arc"
+ "CustomText" "Arc"
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "Act_1_Crystal"
+ "CustomText" "Crystal"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_evernight_a3_1d.txt b/BossHP/configs/MapBossHP/ze_evernight_a3_1d.txt
new file mode 100644
index 0000000..7352370
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_evernight_a3_1d.txt
@@ -0,0 +1,64 @@
+"math_counter"
+{
+ "config"
+ {
+ "MultBoss" "1"
+ }
+ "0"
+ {
+ "HP_counter" "Boss_1_Hp"
+ "HPbar_counter" "Boss_1_Hp_Overlay"
+ "HPinit_counter" "Boss_1_Hp_Init"
+ "CustomText" "Basil"
+ "HPbar_min" "0"
+ "HPbar_max" "10"
+ "HPbar_mode" "1"
+ }
+ "0"
+ {
+ "HP_counter" "Boss_2_Hp"
+ "HPbar_counter" "Boss_2_Hp_Overlay"
+ "HPinit_counter" "Boss_2_Hp_Init"
+ "CustomText" "BOSS"
+ "HPbar_min" "0"
+ "HPbar_max" "10"
+ "HPbar_mode" "1"
+ }
+ "0"
+ {
+ "HP_counter" "Boss_3_Hp"
+ "HPbar_counter" "Boss_3_Hp_Overlay"
+ "HPinit_counter" "Boss_3_Hp_Init"
+ "CustomText" "Gradyrat"
+ "HPbar_min" "0"
+ "HPbar_max" "10"
+ "HPbar_mode" "1"
+ }
+
+ "2"
+ {
+ "HP_counter" "Boss_2_Hp_Lava"
+ "CustomText" "Lava"
+ }
+ "3"
+ {
+ "HP_counter" "Boss_2_Hp_Blizzard"
+ "CustomText" "Blizzard"
+ }
+ "4"
+ {
+ "HP_counter" "Boss_2_Hp_Hurricane"
+ "CustomText" "Hurricane"
+ }
+ "5"
+ {
+ "HP_counter" "Boss_2_Hp_Arc"
+ "CustomText" "Arc"
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "Act_1_Crystal"
+ "CustomText" "Crystal"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_evernight_a3_4.txt b/BossHP/configs/MapBossHP/ze_evernight_a3_4.txt
new file mode 100644
index 0000000..7352370
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_evernight_a3_4.txt
@@ -0,0 +1,64 @@
+"math_counter"
+{
+ "config"
+ {
+ "MultBoss" "1"
+ }
+ "0"
+ {
+ "HP_counter" "Boss_1_Hp"
+ "HPbar_counter" "Boss_1_Hp_Overlay"
+ "HPinit_counter" "Boss_1_Hp_Init"
+ "CustomText" "Basil"
+ "HPbar_min" "0"
+ "HPbar_max" "10"
+ "HPbar_mode" "1"
+ }
+ "0"
+ {
+ "HP_counter" "Boss_2_Hp"
+ "HPbar_counter" "Boss_2_Hp_Overlay"
+ "HPinit_counter" "Boss_2_Hp_Init"
+ "CustomText" "BOSS"
+ "HPbar_min" "0"
+ "HPbar_max" "10"
+ "HPbar_mode" "1"
+ }
+ "0"
+ {
+ "HP_counter" "Boss_3_Hp"
+ "HPbar_counter" "Boss_3_Hp_Overlay"
+ "HPinit_counter" "Boss_3_Hp_Init"
+ "CustomText" "Gradyrat"
+ "HPbar_min" "0"
+ "HPbar_max" "10"
+ "HPbar_mode" "1"
+ }
+
+ "2"
+ {
+ "HP_counter" "Boss_2_Hp_Lava"
+ "CustomText" "Lava"
+ }
+ "3"
+ {
+ "HP_counter" "Boss_2_Hp_Blizzard"
+ "CustomText" "Blizzard"
+ }
+ "4"
+ {
+ "HP_counter" "Boss_2_Hp_Hurricane"
+ "CustomText" "Hurricane"
+ }
+ "5"
+ {
+ "HP_counter" "Boss_2_Hp_Arc"
+ "CustomText" "Arc"
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "Act_1_Crystal"
+ "CustomText" "Crystal"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_fapescape_p5.txt b/BossHP/configs/MapBossHP/ze_fapescape_p5.txt
new file mode 100644
index 0000000..930f5e2
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_fapescape_p5.txt
@@ -0,0 +1,61 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "boss_hp"
+ "HPbar_counter" "boss_hp_iterations"
+ "HPinit_counter" "boss_hp_backup"
+ "HPbar_min" ""
+ "HPbar_max" "10"
+ "HPbar_default" "10"
+ "HPbar_mode" "1"
+ }
+ "1"
+ {
+ "HP_counter" "boss_hp2"
+ "HPbar_counter" "boss_hp_iterations2"
+ "HPinit_counter" "boss_hp2_backup"
+ "HPbar_min" ""
+ "HPbar_max" "10"
+ "HPbar_default" "10"
+ "HPbar_mode" "1"
+ }
+ "2"
+ {
+ "HP_counter" "boss_hp3"
+ "HPbar_counter" "boss_hp_iterations3"
+ "HPinit_counter" "boss_hp3_backup"
+ "HPbar_min" ""
+ "HPbar_max" "10"
+ "HPbar_default" "10"
+ "HPbar_mode" "1"
+ }
+ "3"
+ {
+ "HP_counter" "boss_hp4"
+ "HPbar_counter" "mouth_counter"
+ "HPinit_counter" "boss_hp4_backup"
+ "HPbar_min" ""
+ "HPbar_max" "10"
+ "HPbar_default" "10"
+ "HPbar_mode" "1"
+ }
+ "4"
+ {
+ "HP_counter" "boss_hp5"
+ "HPbar_counter" "boss_hp_iterations5"
+ "HPinit_counter" "boss_hp5_backup"
+ "HPbar_min" ""
+ "HPbar_max" "10"
+ "HPbar_default" "10"
+ "HPbar_mode" "1"
+ }
+ "5"
+ {
+ "HP_counter" "lastboss_moving"
+ }
+ "6"
+ {
+ "HP_counter" "lastboss_static"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_fapescape_rote_v1_3.txt b/BossHP/configs/MapBossHP/ze_fapescape_rote_v1_3.txt
new file mode 100644
index 0000000..fc2208a
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_fapescape_rote_v1_3.txt
@@ -0,0 +1,69 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "boss_hp"
+ "HPbar_counter" "boss_hp_iterations"
+ "HPinit_counter" "boss_hp_backup"
+ "HPbar_min" ""
+ "HPbar_max" "10"
+ "HPbar_default" "10"
+ "HPbar_mode" "1"
+ }
+ "1"
+ {
+ "HP_counter" "boss_hp_ex1"
+ "HPbar_counter" "boss_hp_ex1_iterations"
+ "HPinit_counter" "boss_hp_ex1_backup"
+ "HPbar_min" ""
+ "HPbar_max" "10"
+ "HPbar_default" "10"
+ "HPbar_mode" "1"
+ }
+ "2"
+ {
+ "HP_counter" "boss_hp_ex2"
+ "HPbar_counter" "boss_hp_ex2_iterations"
+ "HPinit_counter" "boss_hp_ex2_backup"
+ "HPbar_min" ""
+ "HPbar_max" "10"
+ "HPbar_default" "10"
+ "HPbar_mode" "1"
+ }
+ "3"
+ {
+ "HP_counter" "boss_hp2"
+ "HPbar_counter" "boss_hp2_iterations"
+ "HPinit_counter" "boss_hp2_backup"
+ "HPbar_min" ""
+ "HPbar_max" "10"
+ "HPbar_default" "10"
+ "HPbar_mode" "1"
+ }
+ "4"
+ {
+ "HP_counter" "boss_hp3"
+ "HPbar_counter" "boss_hp3_iterations"
+ "HPinit_counter" "boss_hp3_backup"
+ "HPbar_min" ""
+ "HPbar_max" "10"
+ "HPbar_default" "10"
+ "HPbar_mode" "1"
+ }
+ "5"
+ {
+ "HP_counter" "boss_hp4_phase1"
+ }
+ "6"
+ {
+ "HP_counter" "boss_hp4_phase2"
+ }
+ "7"
+ {
+ "HP_counter" "boss_hp4_phase3"
+ }
+ "8"
+ {
+ "HP_counter" "stage_2_ex_boss_37"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_ffvii_cosmo_canyon_go_t6.txt b/BossHP/configs/MapBossHP/ze_ffvii_cosmo_canyon_go_t6.txt
new file mode 100644
index 0000000..fd777b2
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_ffvii_cosmo_canyon_go_t6.txt
@@ -0,0 +1,45 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "Special_Health"
+ "HPbar_counter" "Special_HealthCount"
+ "HPinit_counter" "Special_HealthInit"
+ "HPbar_min" ""
+ "HPbar_max" "16"
+ "HPbar_default" ""
+ "HPbar_mode" "2"
+ }
+ "1"
+ {
+ "HP_counter" "lvl2_Gi_Nattak_Counter"
+ }
+ "2"
+ {
+ "HP_counter" "Genesis_Counter"
+ "CustomText" "Genesis"
+ }
+ "3"
+ {
+ "HP_counter" "Shinra_Ifrit_Counter"
+ "CustomText" "Ifrit"
+ }
+ "4"
+ {
+ "HP_counter" "Shinra_Jenova_Counter"
+ "CustomText" "Jenova"
+ }
+ "5"
+ {
+ "HP_counter" "Shinra_Shiva_Counter"
+ "CustomText" "Shiva"
+ }
+ "6"
+ {
+ "HP_counter" "Gi_Nattak_Counter"
+ }
+ "8"
+ {
+ "HP_counter" "Ifrit_Counter"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_ffvii_cosmo_canyon_v1_1_csgo.txt b/BossHP/configs/MapBossHP/ze_ffvii_cosmo_canyon_v1_1_csgo.txt
new file mode 100644
index 0000000..fd777b2
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_ffvii_cosmo_canyon_v1_1_csgo.txt
@@ -0,0 +1,45 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "Special_Health"
+ "HPbar_counter" "Special_HealthCount"
+ "HPinit_counter" "Special_HealthInit"
+ "HPbar_min" ""
+ "HPbar_max" "16"
+ "HPbar_default" ""
+ "HPbar_mode" "2"
+ }
+ "1"
+ {
+ "HP_counter" "lvl2_Gi_Nattak_Counter"
+ }
+ "2"
+ {
+ "HP_counter" "Genesis_Counter"
+ "CustomText" "Genesis"
+ }
+ "3"
+ {
+ "HP_counter" "Shinra_Ifrit_Counter"
+ "CustomText" "Ifrit"
+ }
+ "4"
+ {
+ "HP_counter" "Shinra_Jenova_Counter"
+ "CustomText" "Jenova"
+ }
+ "5"
+ {
+ "HP_counter" "Shinra_Shiva_Counter"
+ "CustomText" "Shiva"
+ }
+ "6"
+ {
+ "HP_counter" "Gi_Nattak_Counter"
+ }
+ "8"
+ {
+ "HP_counter" "Ifrit_Counter"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_ffvii_cosmo_canyon_v2_1_g12.txt b/BossHP/configs/MapBossHP/ze_ffvii_cosmo_canyon_v2_1_g12.txt
new file mode 100644
index 0000000..fd777b2
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_ffvii_cosmo_canyon_v2_1_g12.txt
@@ -0,0 +1,45 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "Special_Health"
+ "HPbar_counter" "Special_HealthCount"
+ "HPinit_counter" "Special_HealthInit"
+ "HPbar_min" ""
+ "HPbar_max" "16"
+ "HPbar_default" ""
+ "HPbar_mode" "2"
+ }
+ "1"
+ {
+ "HP_counter" "lvl2_Gi_Nattak_Counter"
+ }
+ "2"
+ {
+ "HP_counter" "Genesis_Counter"
+ "CustomText" "Genesis"
+ }
+ "3"
+ {
+ "HP_counter" "Shinra_Ifrit_Counter"
+ "CustomText" "Ifrit"
+ }
+ "4"
+ {
+ "HP_counter" "Shinra_Jenova_Counter"
+ "CustomText" "Jenova"
+ }
+ "5"
+ {
+ "HP_counter" "Shinra_Shiva_Counter"
+ "CustomText" "Shiva"
+ }
+ "6"
+ {
+ "HP_counter" "Gi_Nattak_Counter"
+ }
+ "8"
+ {
+ "HP_counter" "Ifrit_Counter"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_ffvii_cosmo_canyon_v4fix_ps4.txt b/BossHP/configs/MapBossHP/ze_ffvii_cosmo_canyon_v4fix_ps4.txt
new file mode 100644
index 0000000..fd777b2
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_ffvii_cosmo_canyon_v4fix_ps4.txt
@@ -0,0 +1,45 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "Special_Health"
+ "HPbar_counter" "Special_HealthCount"
+ "HPinit_counter" "Special_HealthInit"
+ "HPbar_min" ""
+ "HPbar_max" "16"
+ "HPbar_default" ""
+ "HPbar_mode" "2"
+ }
+ "1"
+ {
+ "HP_counter" "lvl2_Gi_Nattak_Counter"
+ }
+ "2"
+ {
+ "HP_counter" "Genesis_Counter"
+ "CustomText" "Genesis"
+ }
+ "3"
+ {
+ "HP_counter" "Shinra_Ifrit_Counter"
+ "CustomText" "Ifrit"
+ }
+ "4"
+ {
+ "HP_counter" "Shinra_Jenova_Counter"
+ "CustomText" "Jenova"
+ }
+ "5"
+ {
+ "HP_counter" "Shinra_Shiva_Counter"
+ "CustomText" "Shiva"
+ }
+ "6"
+ {
+ "HP_counter" "Gi_Nattak_Counter"
+ }
+ "8"
+ {
+ "HP_counter" "Ifrit_Counter"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_ffvii_cosmo_canyon_v5fix_b10k.txt b/BossHP/configs/MapBossHP/ze_ffvii_cosmo_canyon_v5fix_b10k.txt
new file mode 100644
index 0000000..fd777b2
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_ffvii_cosmo_canyon_v5fix_b10k.txt
@@ -0,0 +1,45 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "Special_Health"
+ "HPbar_counter" "Special_HealthCount"
+ "HPinit_counter" "Special_HealthInit"
+ "HPbar_min" ""
+ "HPbar_max" "16"
+ "HPbar_default" ""
+ "HPbar_mode" "2"
+ }
+ "1"
+ {
+ "HP_counter" "lvl2_Gi_Nattak_Counter"
+ }
+ "2"
+ {
+ "HP_counter" "Genesis_Counter"
+ "CustomText" "Genesis"
+ }
+ "3"
+ {
+ "HP_counter" "Shinra_Ifrit_Counter"
+ "CustomText" "Ifrit"
+ }
+ "4"
+ {
+ "HP_counter" "Shinra_Jenova_Counter"
+ "CustomText" "Jenova"
+ }
+ "5"
+ {
+ "HP_counter" "Shinra_Shiva_Counter"
+ "CustomText" "Shiva"
+ }
+ "6"
+ {
+ "HP_counter" "Gi_Nattak_Counter"
+ }
+ "8"
+ {
+ "HP_counter" "Ifrit_Counter"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_ffvii_cosmo_canyon_v5k.txt b/BossHP/configs/MapBossHP/ze_ffvii_cosmo_canyon_v5k.txt
new file mode 100644
index 0000000..fd777b2
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_ffvii_cosmo_canyon_v5k.txt
@@ -0,0 +1,45 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "Special_Health"
+ "HPbar_counter" "Special_HealthCount"
+ "HPinit_counter" "Special_HealthInit"
+ "HPbar_min" ""
+ "HPbar_max" "16"
+ "HPbar_default" ""
+ "HPbar_mode" "2"
+ }
+ "1"
+ {
+ "HP_counter" "lvl2_Gi_Nattak_Counter"
+ }
+ "2"
+ {
+ "HP_counter" "Genesis_Counter"
+ "CustomText" "Genesis"
+ }
+ "3"
+ {
+ "HP_counter" "Shinra_Ifrit_Counter"
+ "CustomText" "Ifrit"
+ }
+ "4"
+ {
+ "HP_counter" "Shinra_Jenova_Counter"
+ "CustomText" "Jenova"
+ }
+ "5"
+ {
+ "HP_counter" "Shinra_Shiva_Counter"
+ "CustomText" "Shiva"
+ }
+ "6"
+ {
+ "HP_counter" "Gi_Nattak_Counter"
+ }
+ "8"
+ {
+ "HP_counter" "Ifrit_Counter"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_ffvii_cosmo_canyon_v5k_fix.txt b/BossHP/configs/MapBossHP/ze_ffvii_cosmo_canyon_v5k_fix.txt
new file mode 100644
index 0000000..fd777b2
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_ffvii_cosmo_canyon_v5k_fix.txt
@@ -0,0 +1,45 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "Special_Health"
+ "HPbar_counter" "Special_HealthCount"
+ "HPinit_counter" "Special_HealthInit"
+ "HPbar_min" ""
+ "HPbar_max" "16"
+ "HPbar_default" ""
+ "HPbar_mode" "2"
+ }
+ "1"
+ {
+ "HP_counter" "lvl2_Gi_Nattak_Counter"
+ }
+ "2"
+ {
+ "HP_counter" "Genesis_Counter"
+ "CustomText" "Genesis"
+ }
+ "3"
+ {
+ "HP_counter" "Shinra_Ifrit_Counter"
+ "CustomText" "Ifrit"
+ }
+ "4"
+ {
+ "HP_counter" "Shinra_Jenova_Counter"
+ "CustomText" "Jenova"
+ }
+ "5"
+ {
+ "HP_counter" "Shinra_Shiva_Counter"
+ "CustomText" "Shiva"
+ }
+ "6"
+ {
+ "HP_counter" "Gi_Nattak_Counter"
+ }
+ "8"
+ {
+ "HP_counter" "Ifrit_Counter"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_ffvii_mako_reactor_p8.txt b/BossHP/configs/MapBossHP/ze_ffvii_mako_reactor_p8.txt
new file mode 100644
index 0000000..56fe782
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_ffvii_mako_reactor_p8.txt
@@ -0,0 +1,24 @@
+"math_counter"
+{
+ "config"
+ {
+ "ForceEnable" "0"
+ }
+ "0"
+ {
+ "HP_counter" "bahamut_vida"
+ "CustomText" "Bahamut"
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "Monstruo_Breakable"
+ "CustomText" "Monster"
+ }
+ "2"
+ {
+ "Type" "breakable"
+ "BreakableName" "bahamutend"
+ "CustomText" "Bahamut"
+ }
+}
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_ffvii_mako_reactor_v5_3_v5.txt b/BossHP/configs/MapBossHP/ze_ffvii_mako_reactor_v5_3_v5.txt
new file mode 100644
index 0000000..420b530
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_ffvii_mako_reactor_v5_3_v5.txt
@@ -0,0 +1,45 @@
+"math_counter"
+{
+ "config"
+ {
+ "ForceEnable" "0"
+ }
+ "0"
+ {
+ "HP_counter" "bahamut_vida"
+ "HPbar_counter" ""
+ "HPbar_min" ""
+ "HPbar_max" ""
+ "HPbar_default" ""
+ "HPbar_mode" "" // OnHitMin=1 OnHitMax=2
+ "CustomText" "Bahamut"
+ }
+
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "glassT"
+ "CustomText" "Sephiroth"
+ }
+
+ "2"
+ {
+ "Type" "breakable"
+ "BreakableName" "bahamutend"
+ "CustomText" "Bahamut"
+ }
+
+ "3"
+ {
+ "Type" "breakable"
+ "BreakableName" "bahamutend1"
+ "CustomText" "Sephiroth"
+ }
+
+ "4"
+ {
+ "Type" "breakable"
+ "BreakableName" "Monstruo_Breakable"
+ "CustomText" "Guard Scorpion"
+ }
+}
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_ffvii_mako_reactor_v6_b08_ps7.txt b/BossHP/configs/MapBossHP/ze_ffvii_mako_reactor_v6_b08_ps7.txt
new file mode 100644
index 0000000..e6aa14b
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_ffvii_mako_reactor_v6_b08_ps7.txt
@@ -0,0 +1,25 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "HPCounter"
+ "HPbar_counter" "HPCounterIterator"
+ "HPinit_counter" "HPCounterBackUp"
+ "HPbar_min" ""
+ "HPbar_max" "40"
+ "HPbar_default" "40"
+ "HPbar_mode" "1"
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "Final_Fulgor_Breakable"
+ "CustomText" "Bahamut"
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "Sephiroth_Final_Breakable"
+ "CustomText" "Sephiroth"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_ffvii_mako_reactor_v6_b08_ps8.txt b/BossHP/configs/MapBossHP/ze_ffvii_mako_reactor_v6_b08_ps8.txt
new file mode 100644
index 0000000..e6aa14b
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_ffvii_mako_reactor_v6_b08_ps8.txt
@@ -0,0 +1,25 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "HPCounter"
+ "HPbar_counter" "HPCounterIterator"
+ "HPinit_counter" "HPCounterBackUp"
+ "HPbar_min" ""
+ "HPbar_max" "40"
+ "HPbar_default" "40"
+ "HPbar_mode" "1"
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "Final_Fulgor_Breakable"
+ "CustomText" "Bahamut"
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "Sephiroth_Final_Breakable"
+ "CustomText" "Sephiroth"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_ffvii_temple_ancient_v4_3.txt b/BossHP/configs/MapBossHP/ze_ffvii_temple_ancient_v4_3.txt
new file mode 100644
index 0000000..a392de3
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_ffvii_temple_ancient_v4_3.txt
@@ -0,0 +1,55 @@
+"math_counter"
+{
+ "0"
+ {
+ "CustomText" "Dragon"
+ "HPbar_mode" "1"
+ "HPbar_counter" "counter_dragon_3"
+ "HP_counter" "counter_dragon_1"
+ "HPinit_counter" "counter_dragon_2"
+ }
+ "1"
+ {
+ "CustomText" "Dragon"
+ "HPbar_mode" "1"
+ "HPbar_counter" "counter_dragon_3_1"
+ "HP_counter" "counter_dragon_1"
+ "HPinit_counter" "counter_dragon_2"
+ }
+ "2"
+ {
+ "CustomText" "Gaulle"
+ "HP_counter" "counter_golem_3"
+ }
+ "3"
+ {
+ "CustomText" "Sephiroth"
+ "HPbar_mode" "1"
+ "HPbar_counter" "Edge_Health"
+ "HP_counter" "counter_edge_1"
+ "HPinit_counter" "counter_edge_2"
+ }
+ "4"
+ {
+ "CustomText" "Bomb"
+ "HP_counter" "bomb_1_counter"
+ }
+ "5"
+ {
+ "CustomText" "Bomb"
+ "HP_counter" "bomb_3_counter"
+ }
+ "6"
+ {
+ "CustomText" "Sephiroth"
+ "HP_counter" "counter_seph"
+ }
+ "7"
+ {
+ "CustomText" "Triface"
+ "HPbar_mode" "1"
+ "HPbar_counter" "counter_triface_3"
+ "HP_counter" "counter_triface_1"
+ "HPinit_counter" "counter_triface_2"
+ }
+}
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_ffxii_feywood_b3_1_e2_2.txt b/BossHP/configs/MapBossHP/ze_ffxii_feywood_b3_1_e2_2.txt
new file mode 100644
index 0000000..2a45dcf
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_ffxii_feywood_b3_1_e2_2.txt
@@ -0,0 +1,40 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "Boss_HP_2"
+ "HPbar_counter" "Boss_HPbar_Counter"
+ "HPbar_min" "1"
+ "HPbar_max" "7"
+ "HPbar_default" "1"
+ "HPbar_mode" "2"
+ }
+ "1"
+ {
+ "HP_counter" "lvl5_Boss_HP_2"
+ "HPbar_counter" "lvl5_Boss_HPbar_Counter"
+ "CustomText" "Zodiark"
+ "HPbar_min" "1"
+ "HPbar_max" "7"
+ "HPbar_default" "1"
+ "HPbar_mode" "2"
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "Glass_Ball_Break"
+ "CustomText" "Glass"
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "Tomb_01_Crystall_1"
+ "CustomText" "Crystall 1"
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "Tomb_01_Crystall_2"
+ "CustomText" "Crystall 2"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_ffxii_feywood_b3_1_x4.txt b/BossHP/configs/MapBossHP/ze_ffxii_feywood_b3_1_x4.txt
new file mode 100644
index 0000000..2a45dcf
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_ffxii_feywood_b3_1_x4.txt
@@ -0,0 +1,40 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "Boss_HP_2"
+ "HPbar_counter" "Boss_HPbar_Counter"
+ "HPbar_min" "1"
+ "HPbar_max" "7"
+ "HPbar_default" "1"
+ "HPbar_mode" "2"
+ }
+ "1"
+ {
+ "HP_counter" "lvl5_Boss_HP_2"
+ "HPbar_counter" "lvl5_Boss_HPbar_Counter"
+ "CustomText" "Zodiark"
+ "HPbar_min" "1"
+ "HPbar_max" "7"
+ "HPbar_default" "1"
+ "HPbar_mode" "2"
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "Glass_Ball_Break"
+ "CustomText" "Glass"
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "Tomb_01_Crystall_1"
+ "CustomText" "Crystall 1"
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "Tomb_01_Crystall_2"
+ "CustomText" "Crystall 2"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_ffxii_feywood_b6_1k.txt b/BossHP/configs/MapBossHP/ze_ffxii_feywood_b6_1k.txt
new file mode 100644
index 0000000..7330868
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_ffxii_feywood_b6_1k.txt
@@ -0,0 +1,47 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "Boss_HP_2"
+ "HPbar_counter" "Boss_HPbar_Counter"
+ "HPbar_min" "1"
+ "HPbar_max" "7"
+ "HPbar_default" "1"
+ "HPbar_mode" "2"
+ }
+ "1"
+ {
+ "HP_counter" "lvl5_Boss_HP_2"
+ "HPbar_counter" "lvl5_Boss_HPbar_Counter"
+ "CustomText" "Zodiark"
+ "HPbar_min" "1"
+ "HPbar_max" "7"
+ "HPbar_default" "1"
+ "HPbar_mode" "2"
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "Glass_Ball_Break"
+ "CustomText" "Glass"
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "Tomb_01_Crystall_1"
+ "CustomText" "Crystall 1"
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "Tomb_01_Crystall_2"
+ "CustomText" "Crystall 2"
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "boss_cactus_break"
+ "CustomText" "Cactus"
+ }
+
+}
diff --git a/BossHP/configs/MapBossHP/ze_ffxii_paramina_rift_csgo1.txt b/BossHP/configs/MapBossHP/ze_ffxii_paramina_rift_csgo1.txt
new file mode 100644
index 0000000..e5e79c3
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_ffxii_paramina_rift_csgo1.txt
@@ -0,0 +1,44 @@
+"math_counter"
+{
+ "config"
+ {
+ "MultBoss" ""
+ "IsDynamicHP" ""
+ "RoundEndShowTopDamage" ""
+ "ShowTopDamageDuringBOSS" ""
+ }
+ "0"
+ {
+ "HP_counter" "Boss_Health"
+ "HPbar_counter" "Boss_Overlay_Counter"
+ "HPinit_counter" "Boss_Health_Init"
+ "HPbar_min" ""
+ "HPbar_max" "11"
+ "HPbar_default" ""
+ "HPbar_mode" "2"
+ "CustomText" "Mateus"
+ "CustomText2" ""
+ }
+ "1"
+ {
+ "HP_counter" "Chaos_Health"
+ "HPbar_counter" "Chaos_Overlay_Counter"
+ "HPinit_counter" "Chaos_Health_Init"
+ "HPbar_min" ""
+ "HPbar_max" "11"
+ "HPbar_default" ""
+ "HPbar_mode" "2"
+ "CustomText" "Chaos"
+ "CustomText2" ""
+ }
+ "2"
+ {
+ "HP_counter" "Fin_Boss_Counter"
+ "CustomText" "Mateus"
+ }
+ "3"
+ {
+ "HP_counter" "Guardian_Counter"
+ "CustomText" "Guardian"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_ffxii_paramina_rift_csgo5.txt b/BossHP/configs/MapBossHP/ze_ffxii_paramina_rift_csgo5.txt
new file mode 100644
index 0000000..e5e79c3
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_ffxii_paramina_rift_csgo5.txt
@@ -0,0 +1,44 @@
+"math_counter"
+{
+ "config"
+ {
+ "MultBoss" ""
+ "IsDynamicHP" ""
+ "RoundEndShowTopDamage" ""
+ "ShowTopDamageDuringBOSS" ""
+ }
+ "0"
+ {
+ "HP_counter" "Boss_Health"
+ "HPbar_counter" "Boss_Overlay_Counter"
+ "HPinit_counter" "Boss_Health_Init"
+ "HPbar_min" ""
+ "HPbar_max" "11"
+ "HPbar_default" ""
+ "HPbar_mode" "2"
+ "CustomText" "Mateus"
+ "CustomText2" ""
+ }
+ "1"
+ {
+ "HP_counter" "Chaos_Health"
+ "HPbar_counter" "Chaos_Overlay_Counter"
+ "HPinit_counter" "Chaos_Health_Init"
+ "HPbar_min" ""
+ "HPbar_max" "11"
+ "HPbar_default" ""
+ "HPbar_mode" "2"
+ "CustomText" "Chaos"
+ "CustomText2" ""
+ }
+ "2"
+ {
+ "HP_counter" "Fin_Boss_Counter"
+ "CustomText" "Mateus"
+ }
+ "3"
+ {
+ "HP_counter" "Guardian_Counter"
+ "CustomText" "Guardian"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_ffxii_paramina_rift_r4.txt b/BossHP/configs/MapBossHP/ze_ffxii_paramina_rift_r4.txt
new file mode 100644
index 0000000..e5e79c3
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_ffxii_paramina_rift_r4.txt
@@ -0,0 +1,44 @@
+"math_counter"
+{
+ "config"
+ {
+ "MultBoss" ""
+ "IsDynamicHP" ""
+ "RoundEndShowTopDamage" ""
+ "ShowTopDamageDuringBOSS" ""
+ }
+ "0"
+ {
+ "HP_counter" "Boss_Health"
+ "HPbar_counter" "Boss_Overlay_Counter"
+ "HPinit_counter" "Boss_Health_Init"
+ "HPbar_min" ""
+ "HPbar_max" "11"
+ "HPbar_default" ""
+ "HPbar_mode" "2"
+ "CustomText" "Mateus"
+ "CustomText2" ""
+ }
+ "1"
+ {
+ "HP_counter" "Chaos_Health"
+ "HPbar_counter" "Chaos_Overlay_Counter"
+ "HPinit_counter" "Chaos_Health_Init"
+ "HPbar_min" ""
+ "HPbar_max" "11"
+ "HPbar_default" ""
+ "HPbar_mode" "2"
+ "CustomText" "Chaos"
+ "CustomText2" ""
+ }
+ "2"
+ {
+ "HP_counter" "Fin_Boss_Counter"
+ "CustomText" "Mateus"
+ }
+ "3"
+ {
+ "HP_counter" "Guardian_Counter"
+ "CustomText" "Guardian"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_ffxii_paramina_rift_v1_4_a7t.txt b/BossHP/configs/MapBossHP/ze_ffxii_paramina_rift_v1_4_a7t.txt
new file mode 100644
index 0000000..e5e79c3
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_ffxii_paramina_rift_v1_4_a7t.txt
@@ -0,0 +1,44 @@
+"math_counter"
+{
+ "config"
+ {
+ "MultBoss" ""
+ "IsDynamicHP" ""
+ "RoundEndShowTopDamage" ""
+ "ShowTopDamageDuringBOSS" ""
+ }
+ "0"
+ {
+ "HP_counter" "Boss_Health"
+ "HPbar_counter" "Boss_Overlay_Counter"
+ "HPinit_counter" "Boss_Health_Init"
+ "HPbar_min" ""
+ "HPbar_max" "11"
+ "HPbar_default" ""
+ "HPbar_mode" "2"
+ "CustomText" "Mateus"
+ "CustomText2" ""
+ }
+ "1"
+ {
+ "HP_counter" "Chaos_Health"
+ "HPbar_counter" "Chaos_Overlay_Counter"
+ "HPinit_counter" "Chaos_Health_Init"
+ "HPbar_min" ""
+ "HPbar_max" "11"
+ "HPbar_default" ""
+ "HPbar_mode" "2"
+ "CustomText" "Chaos"
+ "CustomText2" ""
+ }
+ "2"
+ {
+ "HP_counter" "Fin_Boss_Counter"
+ "CustomText" "Mateus"
+ }
+ "3"
+ {
+ "HP_counter" "Guardian_Counter"
+ "CustomText" "Guardian"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_ffxii_ridorana_cataract_b3_ps9.txt b/BossHP/configs/MapBossHP/ze_ffxii_ridorana_cataract_b3_ps9.txt
new file mode 100644
index 0000000..077af6c
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_ffxii_ridorana_cataract_b3_ps9.txt
@@ -0,0 +1,52 @@
+"math_counter"
+{
+ "config"
+ {
+ "MultBoss" "1"
+ }
+ "0"
+ {
+ "HP_counter" "Special_Health"
+ "HPbar_counter" "Special_HealthCount"
+ "HPinit_counter" "Special_HealthInit"
+ "HPbar_min" ""
+ "HPbar_max" "16"
+ "HPbar_default" ""
+ "HPbar_mode" "2"
+ }
+ "1"
+ {
+ "HP_counter" "Stage_13_End_Boss_Counter"
+ "CustomText" "Hydro"
+ }
+ "2"
+ {
+ "HP_counter" "Stage_2_End_Dragon_Counter"
+ "CustomText" "Hydro"
+ }
+ "3"
+ {
+ "HP_counter" "Stage_24_End_Famfrit_Counter"
+ "CustomText" "Famfrit"
+ }
+ "4"
+ {
+ "HP_counter" "Fat_Nigger_Counter"
+ "CustomText" "Cuchulainn"
+ }
+ "5"
+ {
+ "HP_counter" "Stage_4_End_Guard_Counter"
+ "CustomText" "Guardian"
+ }
+ "6"
+ {
+ "HP_counter" "Famfrit_Holy_Summon_Counter"
+ "CustomText" "Guardian(Holy)"
+ }
+ "7"
+ {
+ "HP_counter" "Famfrit_Fire_Summon_Counter"
+ "CustomText" "Guardian(Fire)"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_ffxii_ridorana_cataract_b4_ps8.txt b/BossHP/configs/MapBossHP/ze_ffxii_ridorana_cataract_b4_ps8.txt
new file mode 100644
index 0000000..077af6c
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_ffxii_ridorana_cataract_b4_ps8.txt
@@ -0,0 +1,52 @@
+"math_counter"
+{
+ "config"
+ {
+ "MultBoss" "1"
+ }
+ "0"
+ {
+ "HP_counter" "Special_Health"
+ "HPbar_counter" "Special_HealthCount"
+ "HPinit_counter" "Special_HealthInit"
+ "HPbar_min" ""
+ "HPbar_max" "16"
+ "HPbar_default" ""
+ "HPbar_mode" "2"
+ }
+ "1"
+ {
+ "HP_counter" "Stage_13_End_Boss_Counter"
+ "CustomText" "Hydro"
+ }
+ "2"
+ {
+ "HP_counter" "Stage_2_End_Dragon_Counter"
+ "CustomText" "Hydro"
+ }
+ "3"
+ {
+ "HP_counter" "Stage_24_End_Famfrit_Counter"
+ "CustomText" "Famfrit"
+ }
+ "4"
+ {
+ "HP_counter" "Fat_Nigger_Counter"
+ "CustomText" "Cuchulainn"
+ }
+ "5"
+ {
+ "HP_counter" "Stage_4_End_Guard_Counter"
+ "CustomText" "Guardian"
+ }
+ "6"
+ {
+ "HP_counter" "Famfrit_Holy_Summon_Counter"
+ "CustomText" "Guardian(Holy)"
+ }
+ "7"
+ {
+ "HP_counter" "Famfrit_Fire_Summon_Counter"
+ "CustomText" "Guardian(Fire)"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_ffxii_ridorana_cataract_t4_ps3.txt b/BossHP/configs/MapBossHP/ze_ffxii_ridorana_cataract_t4_ps3.txt
new file mode 100644
index 0000000..3df37ba
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_ffxii_ridorana_cataract_t4_ps3.txt
@@ -0,0 +1,72 @@
+"math_counter"
+{
+ "config"
+ {
+ "BossRewardMoney" "5"
+ }
+ "0"
+ {
+ "HP_counter" "Special_Health"
+ "HP_Mode" "1"
+ "HPbar_counter" "Special_HealthCount"
+ "HPinit_counter" "Special_HealthInit"
+ "HPbar_min" ""
+ "HPbar_max" "16"
+ "HPbar_default" ""
+ "HPbar_mode" "2"
+ }
+ "1"
+ {
+ "HP_counter" "Stage_13_End_Boss_Counter"
+ "HP_Mode" "1"
+ "CustomText" "Hydro"
+ }
+ "2"
+ {
+ "HP_counter" "Stage_2_End_Dragon_Counter"
+ "HP_Mode" "1"
+ "CustomText" "Hydro"
+ }
+ "3"
+ {
+ "HP_counter" "Stage_24_End_Famfrit_Counter"
+ "HP_Mode" "1"
+ "CustomText" "Famfrit"
+ }
+ "4"
+ {
+ "HP_counter" "Fat_Nigger_Counter"
+ "HP_Mode" "1"
+ "CustomText" "Zalera"
+ }
+ "5"
+ {
+ "HP_counter" "Stage_4_End_Guard_Counter"
+ "HP_Mode" "1"
+ "CustomText" "Gabranth"
+ }
+ "6"
+ {
+ "HP_counter" "Famfrit_Holy_Summon_Counter"
+ "HP_Mode" "1"
+ "CustomText" "Zargabaath(Holy)"
+ }
+ "7"
+ {
+ "HP_counter" "Famfrit_Fire_Summon_Counter"
+ "HP_Mode" "1"
+ "CustomText" "Bergan(Fire)"
+ }
+ "8"
+ {
+ "Type" "breakable"
+ "BreakableName" "Stage_1_Hold_3_Crystall_1"
+ "CustomText" ""Crystal - 1"
+ }
+ "9"
+ {
+ "Type" "breakable"
+ "BreakableName" "Stage_1_Hold_3_Crystall_2"
+ "CustomText" ""Crystal - 2"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_ffxii_westersand_v7_z9.txt b/BossHP/configs/MapBossHP/ze_ffxii_westersand_v7_z9.txt
new file mode 100644
index 0000000..2e1110c
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_ffxii_westersand_v7_z9.txt
@@ -0,0 +1,38 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "Boss_Health"
+ "HPbar_counter" "Boss_Overlay_Counter"
+ "HPinit_counter" "Boss_Health_Init"
+ "HPbar_min" "0"
+ "HPbar_max" "6"
+ "HPbar_default" "6"
+ "HPbar_mode" "1" // 1=降序 =2升序
+ }
+ "5"
+ {
+ "HP_counter" "Guard_2_Health"
+ "CustomText" "Healer"
+ }
+ "5"
+ {
+ "HP_counter" "Guard_3_Health"
+ "CustomText" "Battlemage"
+ }
+ "2"
+ {
+ "HP_counter" "Airship_Ending_Boss_Health"
+ "CustomText" "Chaos"
+ }
+ "3"
+ {
+ "HP_counter" "Ehe_Dragon_HP"
+ "CustomText" "Dragon"
+ }
+ "4"
+ {
+ "HP_counter" "Ehe_Guardian_HP"
+ "CustomText" "Guardian"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_ffxii_westersand_v8zeta1_b4k.txt b/BossHP/configs/MapBossHP/ze_ffxii_westersand_v8zeta1_b4k.txt
new file mode 100644
index 0000000..755328a
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_ffxii_westersand_v8zeta1_b4k.txt
@@ -0,0 +1,46 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "Boss_Health"
+ "HPbar_counter" "Boss_Overlay_Counter"
+ "HPinit_counter" "Boss_Health_Init"
+ "HPbar_min" "0"
+ "HPbar_max" "7"
+ "HPbar_default" "0"
+ "HPbar_mode" "2" // 1=降序 =2升序
+ }
+ "1"
+ {
+ "HP_counter" "Espers_Mateus_Counter"
+ "CustomText" "Mateus"
+ }
+ "2"
+ {
+ "HP_counter" "Espers_Belias_Counter"
+ "CustomText" "Belias"
+ }
+ "3"
+ {
+ "HP_counter" "Espers_Chaos_Counter"
+ "CustomText" "Chaos"
+ }
+ "4"
+ {
+ "Type" "breakable"
+ "BreakableName" "Mateus_Summon_Physbox"
+ "CustomText" "Mateus"
+ }
+ "5"
+ {
+ "Type" "breakable"
+ "BreakableName" "Chaos_Summon_Physbox"
+ "CustomText" "Chaos"
+ }
+ "6"
+ {
+ "Type" "breakable"
+ "BreakableName" "Belias_Summon_Physbox"
+ "CustomText" "Belias"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_ffxii_westersand_v8zeta1_b5k.txt b/BossHP/configs/MapBossHP/ze_ffxii_westersand_v8zeta1_b5k.txt
new file mode 100644
index 0000000..755328a
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_ffxii_westersand_v8zeta1_b5k.txt
@@ -0,0 +1,46 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "Boss_Health"
+ "HPbar_counter" "Boss_Overlay_Counter"
+ "HPinit_counter" "Boss_Health_Init"
+ "HPbar_min" "0"
+ "HPbar_max" "7"
+ "HPbar_default" "0"
+ "HPbar_mode" "2" // 1=降序 =2升序
+ }
+ "1"
+ {
+ "HP_counter" "Espers_Mateus_Counter"
+ "CustomText" "Mateus"
+ }
+ "2"
+ {
+ "HP_counter" "Espers_Belias_Counter"
+ "CustomText" "Belias"
+ }
+ "3"
+ {
+ "HP_counter" "Espers_Chaos_Counter"
+ "CustomText" "Chaos"
+ }
+ "4"
+ {
+ "Type" "breakable"
+ "BreakableName" "Mateus_Summon_Physbox"
+ "CustomText" "Mateus"
+ }
+ "5"
+ {
+ "Type" "breakable"
+ "BreakableName" "Chaos_Summon_Physbox"
+ "CustomText" "Chaos"
+ }
+ "6"
+ {
+ "Type" "breakable"
+ "BreakableName" "Belias_Summon_Physbox"
+ "CustomText" "Belias"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_ffxii_westersand_v8zeta1_x16.txt b/BossHP/configs/MapBossHP/ze_ffxii_westersand_v8zeta1_x16.txt
new file mode 100644
index 0000000..755328a
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_ffxii_westersand_v8zeta1_x16.txt
@@ -0,0 +1,46 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "Boss_Health"
+ "HPbar_counter" "Boss_Overlay_Counter"
+ "HPinit_counter" "Boss_Health_Init"
+ "HPbar_min" "0"
+ "HPbar_max" "7"
+ "HPbar_default" "0"
+ "HPbar_mode" "2" // 1=降序 =2升序
+ }
+ "1"
+ {
+ "HP_counter" "Espers_Mateus_Counter"
+ "CustomText" "Mateus"
+ }
+ "2"
+ {
+ "HP_counter" "Espers_Belias_Counter"
+ "CustomText" "Belias"
+ }
+ "3"
+ {
+ "HP_counter" "Espers_Chaos_Counter"
+ "CustomText" "Chaos"
+ }
+ "4"
+ {
+ "Type" "breakable"
+ "BreakableName" "Mateus_Summon_Physbox"
+ "CustomText" "Mateus"
+ }
+ "5"
+ {
+ "Type" "breakable"
+ "BreakableName" "Chaos_Summon_Physbox"
+ "CustomText" "Chaos"
+ }
+ "6"
+ {
+ "Type" "breakable"
+ "BreakableName" "Belias_Summon_Physbox"
+ "CustomText" "Belias"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_ffxiv_wanderers_palace_v2_8.txt b/BossHP/configs/MapBossHP/ze_ffxiv_wanderers_palace_v2_8.txt
new file mode 100644
index 0000000..d103a5a
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_ffxiv_wanderers_palace_v2_8.txt
@@ -0,0 +1,34 @@
+"math_counter"
+{
+ "1"
+ {
+ "HP_Group"
+ {
+ "0" "bahamut_hp_100"
+ "1" "bahamut_hp_75"
+ "2" "bahamut_hp_50"
+ "3" "bahamut_hp_25"
+ }
+ "CustomText" "Bahamut"
+ }
+ "5"
+ {
+ "HP_counter" "nael_hp"
+ "CustomText" "Nael Van Darnus"
+ }
+ "6"
+ {
+ "HP_counter" "ads_atack1_hp"
+ "CustomText" "ADS(Right)"
+ }
+ "7"
+ {
+ "HP_counter" "ads_atack2_hp"
+ "CustomText" "ADS(Left)"
+ }
+ "0"
+ {
+ "HP_counter" "ADS_HP"
+ "CustomText" "ADS"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_ffxiv_wanderers_palace_v2_va2.txt b/BossHP/configs/MapBossHP/ze_ffxiv_wanderers_palace_v2_va2.txt
new file mode 100644
index 0000000..d103a5a
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_ffxiv_wanderers_palace_v2_va2.txt
@@ -0,0 +1,34 @@
+"math_counter"
+{
+ "1"
+ {
+ "HP_Group"
+ {
+ "0" "bahamut_hp_100"
+ "1" "bahamut_hp_75"
+ "2" "bahamut_hp_50"
+ "3" "bahamut_hp_25"
+ }
+ "CustomText" "Bahamut"
+ }
+ "5"
+ {
+ "HP_counter" "nael_hp"
+ "CustomText" "Nael Van Darnus"
+ }
+ "6"
+ {
+ "HP_counter" "ads_atack1_hp"
+ "CustomText" "ADS(Right)"
+ }
+ "7"
+ {
+ "HP_counter" "ads_atack2_hp"
+ "CustomText" "ADS(Left)"
+ }
+ "0"
+ {
+ "HP_counter" "ADS_HP"
+ "CustomText" "ADS"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_ffxiv_wanderers_palace_v4_10.txt b/BossHP/configs/MapBossHP/ze_ffxiv_wanderers_palace_v4_10.txt
new file mode 100644
index 0000000..d41a012
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_ffxiv_wanderers_palace_v4_10.txt
@@ -0,0 +1,63 @@
+"math_counter"
+{
+ "0"
+ {
+ "CustomText" "Bahamut(true)"
+ "HP_Group"
+ {
+ "0" "true_bahamut_hp_100"
+ "1" "true_bahamut_hp_75"
+ "2" "true_bahamut_hp_50"
+ "3" "true_bahamut_hp_25"
+ }
+ }
+ "1"
+ {
+ "CustomText" "Bahamut"
+ "HP_Group"
+ {
+ "0" "bahamut_hp_100"
+ "1" "bahamut_hp_75"
+ "2" "bahamut_hp_50"
+ "3" "bahamut_hp_25"
+ }
+ }
+ "2"
+ {
+ "CustomText" "Dalamud"
+ "HP_Group"
+ {
+ "0" "dalamud_hp_100"
+ "1" "dalamud_hp_50"
+ }
+ }
+ "3"
+ {
+ "CustomText" "Behemoth"
+ "HP_Group"
+ {
+ "0" "behemoth_king_hp3_counter"
+ "1" "behemoth_king_hp2_counter"
+ "2" "behemoth_king_hp1_counter"
+ }
+ }
+ "4"
+ {
+ "HP_counter" "ads_hp"
+ "CustomText" "ADS"
+ }
+ "5"
+ {
+ "HP_counter" "ads_atack2_hp"
+ "CustomText" "ADS(Left)"
+ }
+ "6"
+ {
+ "HP_counter" "ads_atack1_hp"
+ "CustomText" "ADS(Right)"
+ }
+ "7"
+ {
+ "HP_counter" "lv3_nael_hp"
+ }
+}
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_ffxiv_wanderers_palace_v4_va2.txt b/BossHP/configs/MapBossHP/ze_ffxiv_wanderers_palace_v4_va2.txt
new file mode 100644
index 0000000..d41a012
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_ffxiv_wanderers_palace_v4_va2.txt
@@ -0,0 +1,63 @@
+"math_counter"
+{
+ "0"
+ {
+ "CustomText" "Bahamut(true)"
+ "HP_Group"
+ {
+ "0" "true_bahamut_hp_100"
+ "1" "true_bahamut_hp_75"
+ "2" "true_bahamut_hp_50"
+ "3" "true_bahamut_hp_25"
+ }
+ }
+ "1"
+ {
+ "CustomText" "Bahamut"
+ "HP_Group"
+ {
+ "0" "bahamut_hp_100"
+ "1" "bahamut_hp_75"
+ "2" "bahamut_hp_50"
+ "3" "bahamut_hp_25"
+ }
+ }
+ "2"
+ {
+ "CustomText" "Dalamud"
+ "HP_Group"
+ {
+ "0" "dalamud_hp_100"
+ "1" "dalamud_hp_50"
+ }
+ }
+ "3"
+ {
+ "CustomText" "Behemoth"
+ "HP_Group"
+ {
+ "0" "behemoth_king_hp3_counter"
+ "1" "behemoth_king_hp2_counter"
+ "2" "behemoth_king_hp1_counter"
+ }
+ }
+ "4"
+ {
+ "HP_counter" "ads_hp"
+ "CustomText" "ADS"
+ }
+ "5"
+ {
+ "HP_counter" "ads_atack2_hp"
+ "CustomText" "ADS(Left)"
+ }
+ "6"
+ {
+ "HP_counter" "ads_atack1_hp"
+ "CustomText" "ADS(Right)"
+ }
+ "7"
+ {
+ "HP_counter" "lv3_nael_hp"
+ }
+}
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_ffxiv_wanderers_palace_v5.txt b/BossHP/configs/MapBossHP/ze_ffxiv_wanderers_palace_v5.txt
new file mode 100644
index 0000000..80a8e25
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_ffxiv_wanderers_palace_v5.txt
@@ -0,0 +1,75 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "Behemoth_HP_Counter"
+ "HPinit_counter" "Behemoth_HP_Initial"
+ "HPbar_counter" "Behemoth_HP_Breakable_Counter"
+ "HPbar_min" "0"
+ "HPbar_max" "4"
+ "HPbar_default" "0"
+ "HPbar_mode" "2" // 1=降序 =2升序
+ "CustomText" "Behemoth"
+ }
+ "1"
+ {
+ "HP_counter" "Garland_HP_Counter"
+ "CustomText" "Garland"
+ }
+ "2"
+ {
+ "HP_counter" "KOH_HP_Counter"
+ "CustomText" "KOH"
+ }
+ "3"
+ {
+ "HP_counter" "Sanctuary_Keeper_HP_Counter"
+ "CustomText" "Sanctuary"
+ }
+
+ "4"
+ {
+ "HP_counter" "Odin_HP_Counter"
+ "CustomText" "Odin"
+ }
+ "5"
+ {
+ "HP_counter" "Seymour_Natus_HP_Counter"
+ "CustomText" "Seymour"
+ }
+ "3"
+ {
+ "HP_counter" "Seymour_Natus_Break_HP_Counter"
+ "CustomText" "Break Attack"
+ }
+ "6"
+ {
+ "HP_counter" "Garuda_HP_Counter"
+ "CustomText" "Garuda"
+ }
+ "7"
+ {
+ "HP_counter" "Serpent_HP_Counter"
+ "CustomText" "Serpent"
+ }
+ "8"
+ {
+ "HP_counter" "Iron_Giant_HP_Counter"
+ "CustomText" "Iron Giant"
+ }
+ "9"
+ {
+ "HP_counter" "Alteci_HP_Counter"
+ "CustomText" "Alteci"
+ }
+ "10"
+ {
+ "HP_counter" "Knight_HP_Counter"
+ "CustomText" "Knight"
+ }
+ "11"
+ {
+ "HP_counter" "Adrammelech_HP_Counter"
+ "CustomText" "Adrammelech"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_ffxiv_wanderers_palace_v5_1.txt b/BossHP/configs/MapBossHP/ze_ffxiv_wanderers_palace_v5_1.txt
new file mode 100644
index 0000000..021f129
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_ffxiv_wanderers_palace_v5_1.txt
@@ -0,0 +1,85 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "Knight_HP_Counter"
+ "HP_Mode" "1"
+ "CustomText" "Knight"
+ }
+ "1"
+ {
+ "HP_counter" "KOH_HP_Counter"
+ "HP_Mode" "1"
+ "CustomText" "Keeper of Halidom"
+ }
+ "2"
+ {
+ "HP_counter" "Behemoth_HP_Counter"
+ "HP_Mode" "1"
+ "HPbar_counter" "Behemoth_HP_Breakable_Counter"
+ "HPbar_max" "4"
+ "HPinit_counter" "Behemoth_HP_Initial"
+ "CustomText" "Behemoth"
+ "HPbar_mode" "2"
+ }
+ "3"
+ {
+ "HP_counter" "Seymour_Natus_HP_Counter"
+ "HP_Mode" "1"
+ "CustomText" "Seymour Natus"
+ }
+ "4"
+ {
+ "HP_counter" "Seymour_Natus_Break_HP_Counter"
+ "HP_Mode" "1"
+ "CustomText" "Mortibody"
+ }
+ "5"
+ {
+ "HP_counter" "Sanctuary_Keeper_HP_Counter"
+ "HP_Mode" "1"
+ "CustomText" "Sanctuary Keeper"
+ }
+ "6"
+ {
+ "HP_counter" "Odin_HP_Counter"
+ "HP_Mode" "1"
+ "CustomText" "Odin"
+ }
+ "7"
+ {
+ "HP_counter" "Castle_Bahamut_HP_Counter"
+ "HP_Mode" "1"
+ "CustomText" "Bahamut"
+ }
+ "8"
+ {
+ "HP_counter" "Ultima_Weapon_HP_Counter"
+ "HP_Mode" "1"
+ "CustomText" "Ultima Weapon"
+ }
+ "9"
+ {
+ "HP_counter" "Final_Bahamut_HP_Counter"
+ "HP_Mode" "1"
+ "CustomText" "Bahamut"
+ }
+ "10"
+ {
+ "HP_counter" "Garland_HP_Counter"
+ "HP_Mode" "1"
+ "CustomText" "Garland"
+ }
+ "11"
+ {
+ "HP_counter" "Iron_Giant_HP_Counter"
+ "HP_Mode" "1"
+ "CustomText" "Iron Giant"
+ }
+ "12"
+ {
+ "HP_counter" "Serpent_HP_Counter"
+ "HP_Mode" "1"
+ "CustomText" "Serpent"
+ }
+}
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_ffxiv_wanderers_palace_v5_2.txt b/BossHP/configs/MapBossHP/ze_ffxiv_wanderers_palace_v5_2.txt
new file mode 100644
index 0000000..5f1b517
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_ffxiv_wanderers_palace_v5_2.txt
@@ -0,0 +1,74 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "Knight_HP_Counter"
+ "CustomText" "Knight"
+ }
+ "1"
+ {
+ "HP_counter" "KOH_HP_Counter"
+ "CustomText" "Keeper of Halidom"
+ }
+ "2"
+ {
+ "HP_counter" "Behemoth_HP_Counter"
+ "HP_Mode" "1"
+ "HPbar_counter" "Behemoth_HP_Breakable_Counter"
+ "HPinit_counter" "Behemoth_HP_Initial"
+ "CustomText" "Behemoth"
+ "HPbar_mode" "2"
+ }
+ "3"
+ {
+ "HP_counter" "Seymour_Natus_HP_Counter"
+ "CustomText" "Seymour Natus"
+ }
+ "4"
+ {
+ "HP_counter" "Mortibody_HP_Counter"
+ "CustomText" "Mortibody"
+ }
+ "5"
+ {
+ "HP_counter" "Sanctuary_Keeper_HP_Counter"
+ "CustomText" "Sanctuary Keeper"
+ }
+ "6"
+ {
+ "HP_counter" "Odin_HP_Counter"
+ "CustomText" "Odin"
+ }
+ "7"
+ {
+ "HP_counter" "Castle_Bahamut_HP_Counter"
+ "CustomText" "Castle Bahamut"
+ }
+ "8"
+ {
+ "HP_counter" "Ultima_Weapon_HP_Counter"
+ "CustomText" "Ultima Weapon"
+ }
+ "9"
+ {
+ "HP_counter" "Final_Bahamut_HP_Counter"
+ "CustomText" "Final Bahamut"
+ }
+ "10"
+ {
+ "HP_counter" "Garland_HP_Counter"
+ "CustomText" "Garland"
+ }
+ "11"
+ {
+ "Type" "breakable"
+ "BreakableName" "Iron_Giant_Breakable"
+ "CustomText" "Iron Giant"
+ }
+ "12"
+ {
+ "Type" "breakable"
+ "BreakableName" "Serpent_Breakable"
+ "CustomText" "Serpent"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_forbidden_repository_a1_3.txt b/BossHP/configs/MapBossHP/ze_forbidden_repository_a1_3.txt
new file mode 100644
index 0000000..449f2be
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_forbidden_repository_a1_3.txt
@@ -0,0 +1,11 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "boss_hp"
+ }
+ "0"
+ {
+ "HP_counter" "boss2_hp"
+ }
+}
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_foreign_sand_mix_v2_fix.txt b/BossHP/configs/MapBossHP/ze_foreign_sand_mix_v2_fix.txt
new file mode 100644
index 0000000..64a0389
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_foreign_sand_mix_v2_fix.txt
@@ -0,0 +1,13 @@
+"math_counter"
+{
+ "0"
+ {
+ "Type" "breakable"
+ "BreakableName" "lolBoss"
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "Bahamut_clip"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_frostdrake_tower_v1.txt b/BossHP/configs/MapBossHP/ze_frostdrake_tower_v1.txt
new file mode 100644
index 0000000..344c2fd
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_frostdrake_tower_v1.txt
@@ -0,0 +1,9 @@
+"math_counter"
+{
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "drake_hp"
+ "CustomText" ""
+ }
+}
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_gameshow_v1_2_csgo1.txt b/BossHP/configs/MapBossHP/ze_gameshow_v1_2_csgo1.txt
new file mode 100644
index 0000000..a8726f7
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_gameshow_v1_2_csgo1.txt
@@ -0,0 +1,8 @@
+"math_counter"
+{
+ "0"
+ {
+ "Type" "breakable"
+ "BreakableName" "boss_break"
+ }
+}
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_grau_a03_1.txt b/BossHP/configs/MapBossHP/ze_grau_a03_1.txt
new file mode 100644
index 0000000..12991ef
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_grau_a03_1.txt
@@ -0,0 +1,16 @@
+"math_counter"
+{
+ "config"
+ {
+ "IsDynamicHP" "1"
+ }
+ "0"
+ {
+ "HP_counter" "counter_st3_boss_vida"
+ "HPbar_counter" "counter_st3_boss_vida_bar"
+ "HPbar_min" ""
+ "HPbar_max" "10"
+ "HPbar_default" ""
+ "HPbar_mode" "1"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_grau_a03_2.txt b/BossHP/configs/MapBossHP/ze_grau_a03_2.txt
new file mode 100644
index 0000000..12991ef
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_grau_a03_2.txt
@@ -0,0 +1,16 @@
+"math_counter"
+{
+ "config"
+ {
+ "IsDynamicHP" "1"
+ }
+ "0"
+ {
+ "HP_counter" "counter_st3_boss_vida"
+ "HPbar_counter" "counter_st3_boss_vida_bar"
+ "HPbar_min" ""
+ "HPbar_max" "10"
+ "HPbar_default" ""
+ "HPbar_mode" "1"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_grau_a03_4f.txt b/BossHP/configs/MapBossHP/ze_grau_a03_4f.txt
new file mode 100644
index 0000000..12991ef
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_grau_a03_4f.txt
@@ -0,0 +1,16 @@
+"math_counter"
+{
+ "config"
+ {
+ "IsDynamicHP" "1"
+ }
+ "0"
+ {
+ "HP_counter" "counter_st3_boss_vida"
+ "HPbar_counter" "counter_st3_boss_vida_bar"
+ "HPbar_min" ""
+ "HPbar_max" "10"
+ "HPbar_default" ""
+ "HPbar_mode" "1"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_gris_v1_13.txt b/BossHP/configs/MapBossHP/ze_gris_v1_13.txt
new file mode 100644
index 0000000..7fe7b11
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_gris_v1_13.txt
@@ -0,0 +1,43 @@
+"math_counter"
+{
+ "config"
+ {
+ "IsDynamicHP" "1"
+ }
+ "0"
+ {
+ "HP_counter" "counter_rtv_boss_vida"
+ "HPbar_counter" "counter_rtv_hp_bar"
+ "HPbar_min" ""
+ "HPbar_max" "15"
+ "HPbar_default" "15"
+ "HPbar_mode" "1"
+ }
+ "1"
+ {
+ "HP_counter" "counter_st4_boss_vida"
+ "HPbar_counter" "counter_st4_boss_vida_bar"
+ "HPbar_min" ""
+ "HPbar_max" "11"
+ "HPbar_default" "4"
+ "HPbar_mode" "1"
+ }
+ "2"
+ {
+ "HP_counter" "l4_boss_vida"
+ "HPbar_counter" "l4_boss_life_counter"
+ "HPbar_min" ""
+ "HPbar_max" "8"
+ "HPbar_default" "8"
+ "HPbar_mode" "1"
+ }
+ "3"
+ {
+ "HP_counter" "white_boss_vida"
+ "HPbar_counter" "white_boss_life_counter"
+ "HPbar_min" ""
+ "HPbar_max" "8"
+ "HPbar_default" "8"
+ "HPbar_mode" "1"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_harry_potter_v1_3.txt b/BossHP/configs/MapBossHP/ze_harry_potter_v1_3.txt
new file mode 100644
index 0000000..d5ce46d
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_harry_potter_v1_3.txt
@@ -0,0 +1,50 @@
+"math_counter"
+{
+ "config"
+ {
+ "BossHpKeepTime" "60"
+ "MaxLegalMathCounterHP" "150000"
+ }
+ "0"
+ {
+ "HP_counter" "map_boss_counter2"
+ "HP_Mode" "1"
+ "HPbar_counter" "map_boss_counter3"
+ "HPinit_counter" "map_boss_counter1"
+ "CustomText" ""
+ "HPbar_mode" "2"
+ }
+ "0"
+ {
+ "HP_counter" "stage4_miniboss_counter2"
+ "HP_Mode" "1"
+ "HPbar_counter" "stage4_miniboss_counter3"
+ "HPinit_counter" "stage4_miniboss_counter1"
+ "CustomText" "Mini spider"
+ "HPbar_mode" "2"
+ }
+ "0"
+ {
+ "HP_counter" "stage5_boss_d1_counter2"
+ "HP_Mode" "1"
+ "HPbar_counter" "stage5_boss_d1_counter3"
+ "HPinit_counter" "stage5_boss_d1_counter"
+ "CustomText" "DeathEater1"
+ "HPbar_mode" "2"
+ }
+ "0"
+ {
+ "HP_counter" "stage5_ex_d2_counter2"
+ "HP_Mode" "1"
+ "HPbar_counter" "stage5_ex_d2_counter3"
+ "HPinit_counter" "stage5_ex_d2_counter"
+ "CustomText" "DeathEater2"
+ "HPbar_mode" "2"
+ }
+ "0"
+ {
+ "HP_counter" "stage5_ending_counter2"
+ "HP_Mode" "1"
+ "CustomText" "DEMENTOR"
+ }
+}
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_hold_em_v10_p.txt b/BossHP/configs/MapBossHP/ze_hold_em_v10_p.txt
new file mode 100644
index 0000000..eaea9c9
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_hold_em_v10_p.txt
@@ -0,0 +1,7 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "boss_hp"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_hold_em_v8.txt b/BossHP/configs/MapBossHP/ze_hold_em_v8.txt
new file mode 100644
index 0000000..eaea9c9
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_hold_em_v8.txt
@@ -0,0 +1,7 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "boss_hp"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_industrial_dejavu_v3_3_1_e2.txt b/BossHP/configs/MapBossHP/ze_industrial_dejavu_v3_3_1_e2.txt
new file mode 100644
index 0000000..8e9708c
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_industrial_dejavu_v3_3_1_e2.txt
@@ -0,0 +1,18 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "BossHPBarPerPlayer"
+ "HP_Mode" "1"
+ "HPbar_counter" "BossHPBarPlayers"
+ "HPinit_counter" "BossHPBarInitial"
+ "CustomText" ""
+ "HPbar_mode" "1"
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "BossGlassWall"
+ "CustomText" "Glass"
+ }
+}
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_infected_sewers_v4_ps6.txt b/BossHP/configs/MapBossHP/ze_infected_sewers_v4_ps6.txt
new file mode 100644
index 0000000..b510bde
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_infected_sewers_v4_ps6.txt
@@ -0,0 +1,12 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "hpcount2"
+ "HPbar_counter" "hpcount3"
+ "HPbar_min" ""
+ "HPbar_max" "40"
+ "HPbar_default" ""
+ "HPbar_mode" "2"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_infected_sewers_v6_1_1.txt b/BossHP/configs/MapBossHP/ze_infected_sewers_v6_1_1.txt
new file mode 100644
index 0000000..b510bde
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_infected_sewers_v6_1_1.txt
@@ -0,0 +1,12 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "hpcount2"
+ "HPbar_counter" "hpcount3"
+ "HPbar_min" ""
+ "HPbar_max" "40"
+ "HPbar_default" ""
+ "HPbar_mode" "2"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_isla_nublar_p3.txt b/BossHP/configs/MapBossHP/ze_isla_nublar_p3.txt
new file mode 100644
index 0000000..04cb5d0
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_isla_nublar_p3.txt
@@ -0,0 +1,7 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "trexhitbased1"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_johnny_nukem_b8_1_csgo2.txt b/BossHP/configs/MapBossHP/ze_johnny_nukem_b8_1_csgo2.txt
new file mode 100644
index 0000000..3dc1381
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_johnny_nukem_b8_1_csgo2.txt
@@ -0,0 +1,15 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "Frog_Counter"
+ }
+ "1"
+ {
+ "HP_counter" "Frog2_Counter"
+ }
+ "2"
+ {
+ "HP_counter" "Solid_Paper_Counter"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_johnny_nukem_b8_1_csgo3.txt b/BossHP/configs/MapBossHP/ze_johnny_nukem_b8_1_csgo3.txt
new file mode 100644
index 0000000..1a5ab3b
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_johnny_nukem_b8_1_csgo3.txt
@@ -0,0 +1,18 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "Frog_Counter"
+ "CustomText" "Frog"
+ }
+ "1"
+ {
+ "HP_counter" "Frog2_Counter"
+ "CustomText" "Frog"
+ }
+ "2"
+ {
+ "HP_counter" "Solid_Paper_Counter"
+ "CustomText" "Solid Paper"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_johnny_nukem_b8_1_csgo4.txt b/BossHP/configs/MapBossHP/ze_johnny_nukem_b8_1_csgo4.txt
new file mode 100644
index 0000000..1a5ab3b
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_johnny_nukem_b8_1_csgo4.txt
@@ -0,0 +1,18 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "Frog_Counter"
+ "CustomText" "Frog"
+ }
+ "1"
+ {
+ "HP_counter" "Frog2_Counter"
+ "CustomText" "Frog"
+ }
+ "2"
+ {
+ "HP_counter" "Solid_Paper_Counter"
+ "CustomText" "Solid Paper"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_l0v0l_a7_csgo4.bak b/BossHP/configs/MapBossHP/ze_l0v0l_a7_csgo4.bak
new file mode 100644
index 0000000..c58709d
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_l0v0l_a7_csgo4.bak
@@ -0,0 +1,43 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "bosslvl3_counter1"
+ "HPbar_counter" "bosslvl3_counter3"
+ "HPinit_counter" "bosslvl3_counter2"
+ "HPbar_min" ""
+ "HPbar_max" "999999"
+ "HPbar_default" "10"
+ "HPbar_mode" "2"
+ }
+ "1"
+ {
+ "HP_counter" "bosslvl2_counter1"
+ "HPbar_counter" "bosslvl2_counter3"
+ "HPinit_counter" "bosslvl2_counter2"
+ "HPbar_min" ""
+ "HPbar_max" "999999"
+ "HPbar_default" "10"
+ "HPbar_mode" "2"
+ }
+ "2"
+ {
+ "HP_counter" "bosslvl3_end_counter1"
+ "HPbar_counter" "bosslvl3_end_counter3"
+ "HPinit_counter" "bosslvl3_end_counter2"
+ "HPbar_min" ""
+ "HPbar_max" "999999"
+ "HPbar_default" "10"
+ "HPbar_mode" "2"
+ }
+ "3"
+ {
+ "HP_counter" "bosslvl1_counter1"
+ "HPbar_counter" "bosslvl1_counter3"
+ "HPinit_counter" "bosslvl1_counter2"
+ "HPbar_min" ""
+ "HPbar_max" "999999"
+ "HPbar_default" "10"
+ "HPbar_mode" "2"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_l0v0l_a7_csgo4.txt b/BossHP/configs/MapBossHP/ze_l0v0l_a7_csgo4.txt
new file mode 100644
index 0000000..c58709d
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_l0v0l_a7_csgo4.txt
@@ -0,0 +1,43 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "bosslvl3_counter1"
+ "HPbar_counter" "bosslvl3_counter3"
+ "HPinit_counter" "bosslvl3_counter2"
+ "HPbar_min" ""
+ "HPbar_max" "999999"
+ "HPbar_default" "10"
+ "HPbar_mode" "2"
+ }
+ "1"
+ {
+ "HP_counter" "bosslvl2_counter1"
+ "HPbar_counter" "bosslvl2_counter3"
+ "HPinit_counter" "bosslvl2_counter2"
+ "HPbar_min" ""
+ "HPbar_max" "999999"
+ "HPbar_default" "10"
+ "HPbar_mode" "2"
+ }
+ "2"
+ {
+ "HP_counter" "bosslvl3_end_counter1"
+ "HPbar_counter" "bosslvl3_end_counter3"
+ "HPinit_counter" "bosslvl3_end_counter2"
+ "HPbar_min" ""
+ "HPbar_max" "999999"
+ "HPbar_default" "10"
+ "HPbar_mode" "2"
+ }
+ "3"
+ {
+ "HP_counter" "bosslvl1_counter1"
+ "HPbar_counter" "bosslvl1_counter3"
+ "HPinit_counter" "bosslvl1_counter2"
+ "HPbar_min" ""
+ "HPbar_max" "999999"
+ "HPbar_default" "10"
+ "HPbar_mode" "2"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_l0v0l_csgo4_fix.txt b/BossHP/configs/MapBossHP/ze_l0v0l_csgo4_fix.txt
new file mode 100644
index 0000000..5d38dc4
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_l0v0l_csgo4_fix.txt
@@ -0,0 +1,43 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "bosslvl1_counter1"
+ "HPbar_counter" "bosslvl1_counter3"
+ "HPinit_counter" "bosslvl1_counter2"
+ "HPbar_min" ""
+ "HPbar_max" "10"
+ "HPbar_default" "10"
+ "HPbar_mode" "1"
+ }
+ "1"
+ {
+ "HP_counter" "bosslvl2_counter1"
+ "HPbar_counter" "bosslvl2_counter3"
+ "HPinit_counter" "bosslvl2_counter2"
+ "HPbar_min" ""
+ "HPbar_max" "10"
+ "HPbar_default" "10"
+ "HPbar_mode" "1"
+ }
+ "2"
+ {
+ "HP_counter" "bosslvl3_counter1"
+ "HPbar_counter" "bosslvl3_counter3"
+ "HPinit_counter" "bosslvl3_counter2"
+ "HPbar_min" ""
+ "HPbar_max" "10"
+ "HPbar_default" "10"
+ "HPbar_mode" "1"
+ }
+ "3"
+ {
+ "HP_counter" "bosslvl3_end_counter1"
+ "HPbar_counter" "bosslvl3_end_counter3"
+ "HPinit_counter" "bosslvl3_end_counter2"
+ "HPbar_min" ""
+ "HPbar_max" "10"
+ "HPbar_default" "10"
+ "HPbar_mode" "1"
+ }
+}
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_l0v0l_v1_4_csgo1.txt b/BossHP/configs/MapBossHP/ze_l0v0l_v1_4_csgo1.txt
new file mode 100644
index 0000000..5d38dc4
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_l0v0l_v1_4_csgo1.txt
@@ -0,0 +1,43 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "bosslvl1_counter1"
+ "HPbar_counter" "bosslvl1_counter3"
+ "HPinit_counter" "bosslvl1_counter2"
+ "HPbar_min" ""
+ "HPbar_max" "10"
+ "HPbar_default" "10"
+ "HPbar_mode" "1"
+ }
+ "1"
+ {
+ "HP_counter" "bosslvl2_counter1"
+ "HPbar_counter" "bosslvl2_counter3"
+ "HPinit_counter" "bosslvl2_counter2"
+ "HPbar_min" ""
+ "HPbar_max" "10"
+ "HPbar_default" "10"
+ "HPbar_mode" "1"
+ }
+ "2"
+ {
+ "HP_counter" "bosslvl3_counter1"
+ "HPbar_counter" "bosslvl3_counter3"
+ "HPinit_counter" "bosslvl3_counter2"
+ "HPbar_min" ""
+ "HPbar_max" "10"
+ "HPbar_default" "10"
+ "HPbar_mode" "1"
+ }
+ "3"
+ {
+ "HP_counter" "bosslvl3_end_counter1"
+ "HPbar_counter" "bosslvl3_end_counter3"
+ "HPinit_counter" "bosslvl3_end_counter2"
+ "HPbar_min" ""
+ "HPbar_max" "10"
+ "HPbar_default" "10"
+ "HPbar_mode" "1"
+ }
+}
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_legoland_crackheads_p2.txt b/BossHP/configs/MapBossHP/ze_legoland_crackheads_p2.txt
new file mode 100644
index 0000000..abe93d1
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_legoland_crackheads_p2.txt
@@ -0,0 +1,7 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "ColorCounter"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_lila_panic_escape_v3.txt b/BossHP/configs/MapBossHP/ze_lila_panic_escape_v3.txt
new file mode 100644
index 0000000..34090df
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_lila_panic_escape_v3.txt
@@ -0,0 +1,13 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "Heli_HP"
+ "CustomText" "Helicopter"
+ }
+ "1"
+ {
+ "HP_counter" "boss_hp"
+ "CustomText" "Bear"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_lila_panic_escape_v3_3.txt b/BossHP/configs/MapBossHP/ze_lila_panic_escape_v3_3.txt
new file mode 100644
index 0000000..34090df
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_lila_panic_escape_v3_3.txt
@@ -0,0 +1,13 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "Heli_HP"
+ "CustomText" "Helicopter"
+ }
+ "1"
+ {
+ "HP_counter" "boss_hp"
+ "CustomText" "Bear"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_lotr_isengard_v2_3_x5.txt b/BossHP/configs/MapBossHP/ze_lotr_isengard_v2_3_x5.txt
new file mode 100644
index 0000000..1ad71b9
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_lotr_isengard_v2_3_x5.txt
@@ -0,0 +1,30 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "hp_controller_spider"
+ "HP_Mode" "2"
+ "HPbar_counter" "hp_counter_spider"
+ "HPinit_counter" ""
+ "CustomText" "Spider"
+ "HPbar_mode" "2"
+ }
+ "0"
+ {
+ "HP_counter" "hp_controller_yruk"
+ "HP_Mode" "2"
+ "HPbar_counter" "hp_counter_yruk"
+ "HPinit_counter" ""
+ "CustomText" "Uruk-hai"
+ "HPbar_mode" "2"
+ }
+ "0"
+ {
+ "HP_counter" "hp_controller_saruman"
+ "HP_Mode" "2"
+ "HPbar_counter" "hp_counter_saruman"
+ "HPinit_counter" ""
+ "CustomText" "Saruman"
+ "HPbar_mode" "2"
+ }
+}
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_minecraft_adventure_v1_3d.txt b/BossHP/configs/MapBossHP/ze_minecraft_adventure_v1_3d.txt
new file mode 100644
index 0000000..a678d2f
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_minecraft_adventure_v1_3d.txt
@@ -0,0 +1,30 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "boss_hp"
+ "HPbar_counter" "boss_hp_iterations"
+ "HPinit_counter" "boss_hp_backup"
+ "CustomText" "Ghast"
+ "HPbar_min" ""
+ "HPbar_max" "10"
+ "HPbar_default" "10"
+ "HPbar_mode" "1"
+ }
+ "1"
+ {
+ "HP_counter" "boss2_hp"
+ "HPbar_counter" "boss2_hp_iterations"
+ "HPinit_counter" "boss2_hp_backup"
+ "CustomText" "Dragon"
+ "HPbar_min" ""
+ "HPbar_max" "10"
+ "HPbar_default" "10"
+ "HPbar_mode" "1"
+ }
+ "2"
+ {
+ "HP_counter" "stronghold_final_boss_hp"
+ "CustomText" "HIM"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_notredame_p3.txt b/BossHP/configs/MapBossHP/ze_notredame_p3.txt
new file mode 100644
index 0000000..5415dc9
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_notredame_p3.txt
@@ -0,0 +1,8 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "boss_hp"
+ "CustomText" "Jack"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_omen_076.txt b/BossHP/configs/MapBossHP/ze_omen_076.txt
new file mode 100644
index 0000000..e18dd17
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_omen_076.txt
@@ -0,0 +1,24 @@
+"math_counter"
+{
+ "0"
+ {
+ "Type" "breakable"
+ "BreakableName" "l3_boss_end_hitbox"
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "l3_boss_hitbox"
+ }
+ "2"
+ {
+ "Type" "breakable"
+ "BreakableName" "l2_end_hitbox"
+ }
+ "3"
+ {
+ "Type" "breakable"
+ "BreakableName" "l1_plant_hitbox"
+ "CustomText" "Plant"
+ }
+}
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_omen_090.txt b/BossHP/configs/MapBossHP/ze_omen_090.txt
new file mode 100644
index 0000000..35ca890
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_omen_090.txt
@@ -0,0 +1,615 @@
+;fix warmup in Possession & ZombieDen warmup plugin
+filter:
+{
+ "targetname" "Warmup_Relay"
+ "classname" "logic_relay"
+ "hammerid" "599620"
+}
+add:
+{
+ "origin" "-11192 -13632 384"
+ "targetname" "Warmup_Relay"
+ "StartDisabled" "0"
+ "spawnflags" "0"
+ "classname" "logic_relay"
+ "hammerid" "599620"
+ "OnTrigger" "TitleMenuBGMPlaySound4-1"
+ "OnTrigger" "Level_mathSetValue130-1"
+ "OnTrigger" "No_damage_triggerEnable0-1"
+ "OnTrigger" "warmup_edict_killerTrigger0-1"
+ "OnTrigger" "!selfFireUser10-1"
+ "OnUser1" "PKMNCommandsay >>WARMUP<<0-1"
+ "OnUser1" "!selfFireUser15-1"
+}
+
+;--------------
+;神器Command重置
+;--------------
+;entadm2 0 "精灵球";entadm2 1 "精灵球";entadm2 3 "精灵球";entadm2 4 "精灵球"
+;----------
+;中文化技能
+;----------
+;-----------------------------
+;博士选择宝可梦的旁边增添选择提示
+;-----------------------------
+add:
+{
+ "classname" "vgui_world_text_panel"
+ "origin" "-10244 -14976 401"
+ "enabled" "1"
+ "displaytext" "小火龙 杰尼龟 妙蛙种子"
+ "targetname" "Doctor_choice"
+ "hammerid" "0"
+ "font" "DefaultLarge"
+ "width" "1024"
+ "height" "1024"
+ "angles" "0 90 0"
+ "textpanelwidth" "1024"
+ "textcolor" "0 255 255"
+}
+;-10244.5
+;------------------
+;人类的宝可梦技能提示
+;------------------
+add:
+{
+ "classname" "vgui_world_text_panel"
+ "origin" "1551.5 1151 3956"
+ "enabled" "1"
+ "displaytext" " "
+ "targetname" "Human_choice"
+ "hammerid" "4723658"
+ "font" "DefaultLarge"
+ "width" "2048"
+ "height" "2048"
+ "angles" "0 90 0"
+ "textpanelwidth" "2048"
+ "textcolor" "0 255 255"
+}
+;
+;可达鸭
+modify:
+{
+ match:
+ {
+ "classname" "logic_relay"
+ "targetname" "Psyduck_main_relay"
+ }
+ insert:
+ {
+ "OnTrigger" "Human_choiceSetDisplayText 抓 摇尾巴 念力01"
+ }
+}
+modify:
+{
+ match:
+ {
+ "classname" "logic_relay"
+ "targetname" "Psyduck_main_relay1"
+ }
+ insert:
+ {
+ "OnTrigger" "Human_choiceSetDisplayText 抓 摇尾巴 念力01"
+ }
+}
+;
+;烈雀
+modify:
+{
+ match:
+ {
+ "classname" "logic_relay"
+ "targetname" "Spearow_main_relay"
+ }
+ insert:
+ {
+ "OnTrigger" "Human_choiceSetDisplayText 啄 瞪眼01"
+ }
+}
+modify:
+{
+ match:
+ {
+ "classname" "logic_relay"
+ "targetname" "Spearow_main_relay1"
+ }
+ insert:
+ {
+ "OnTrigger" "Human_choiceSetDisplayText 啄 瞪眼01"
+ }
+}
+;
+;小火龙
+modify:
+{
+ match:
+ {
+ "classname" "logic_relay"
+ "targetname" "charmander_main_relay"
+ }
+ insert:
+ {
+ "OnTrigger" "Human_choiceSetDisplayText 火花 利爪 叫声0.011"
+ }
+}
+;
+;墨海马
+modify:
+{
+ match:
+ {
+ "classname" "logic_relay"
+ "targetname" "Horsea_main_relay"
+ }
+ insert:
+ {
+ "OnTrigger" "Human_choiceSetDisplayText 水枪 泡沫 瞪眼01"
+ }
+}
+modify:
+{
+ match:
+ {
+ "classname" "logic_relay"
+ "targetname" "Horsea_main_relay1"
+ }
+ insert:
+ {
+ "OnTrigger" "Human_choiceSetDisplayText 水枪 泡沫 瞪眼01"
+ }
+}
+;妙蛙种子
+modify:
+{
+ match:
+ {
+ "classname" "logic_relay"
+ "targetname" "bulbasaur_main_relay"
+ }
+ insert:
+ {
+ "OnTrigger" "Human_choiceSetDisplayText 藤鞭 撞击 寄生种子0.011"
+ }
+}
+;
+;独角虫
+modify:
+{
+ match:
+ {
+ "classname" "logic_relay"
+ "targetname" "Weedle_main_relay"
+ }
+ insert:
+ {
+ "OnTrigger" "Human_choiceSetDisplayText 毒针 撞击 虫咬 01"
+ }
+}
+modify:
+{
+ match:
+ {
+ "classname" "logic_relay"
+ "targetname" "Weedle_main_relay1"
+ }
+ insert:
+ {
+ "OnTrigger" "Human_choiceSetDisplayText 毒针 撞击 虫咬 01"
+ }
+}
+;
+;杰尼龟
+modify:
+{
+ match:
+ {
+ "classname" "logic_relay"
+ "targetname" "squirtle_main_relay"
+ }
+ insert:
+ {
+ "OnTrigger" "Human_choiceSetDisplayText 水枪 撞击 摇尾巴 0.011"
+ }
+}
+;
+;地鼠
+modify:
+{
+ match:
+ {
+ "classname" "logic_relay"
+ "targetname" "diglett_main_relay"
+ }
+ insert:
+ {
+ "OnTrigger" "Human_choiceSetDisplayText 掷泥 抓 叫声01"
+ }
+}
+modify:
+{
+ match:
+ {
+ "classname" "logic_relay"
+ "targetname" "diglett_main_relay1"
+ }
+ insert:
+ {
+ "OnTrigger" "Human_choiceSetDisplayText 掷泥 抓 叫声01"
+ }
+}
+;腕力
+;
+modify:
+{
+ match:
+ {
+ "classname" "logic_relay"
+ "targetname" "Machop_main_relay"
+ }
+ insert:
+ {
+ "OnTrigger" "Human_choiceSetDisplayText 空手劈 踢倒 聚气 01"
+ }
+}
+modify:
+{
+ match:
+ {
+ "classname" "logic_relay"
+ "targetname" "Machop_main_relay1"
+ }
+ insert:
+ {
+ "OnTrigger" "Human_choiceSetDisplayText 空手劈 踢倒 聚气 01"
+ }
+}
+;-----------
+;色彩修正修复
+;-----------
+add:
+{
+ "classname" "color_correction"
+ "spawnflags" "0"
+ "filename" "materials/correction/null.raw"
+ "StartDisabled" "0"
+ "minfalloff" "0"
+ "maxfalloff" "0"
+ "maxweight" "0.0"
+ "origin" "0 0 0"
+}
+;------------------
+;僵尸的宝可梦技能提示
+;------------------
+add:
+{
+ "classname" "vgui_world_text_panel"
+ "origin" "-1551.5 -1151 3936"
+ "enabled" "1"
+ "displaytext" " "
+ "targetname" "Zombie_choice"
+ "hammerid" "4723659"
+ "font" "DefaultLarge"
+ "width" "2048"
+ "height" "2048"
+ "angles" "0 -90 0"
+ "textpanelwidth" "2048"
+ "textcolor" "0 255 255"
+}
+;
+;可达鸭
+modify:
+{
+ match:
+ {
+ "classname" "logic_relay"
+ "targetname" "Psyduck_main_relay2"
+ }
+ insert:
+ {
+ "OnTrigger" "Zombie_choiceSetDisplayText 抓 摇尾巴 念力01"
+ }
+}
+modify:
+{
+ match:
+ {
+ "classname" "logic_relay"
+ "targetname" "Psyduck_main_relay3"
+ }
+ insert:
+ {
+ "OnTrigger" "Zombie_choiceSetDisplayText 抓 摇尾巴 念力01"
+ }
+}
+;
+;烈雀
+modify:
+{
+ match:
+ {
+ "classname" "logic_relay"
+ "targetname" "Spearow_main_relay2"
+ }
+ insert:
+ {
+ "OnTrigger" "Zombie_choiceSetDisplayText 啄 瞪眼01"
+ }
+}
+modify:
+{
+ match:
+ {
+ "classname" "logic_relay"
+ "targetname" "Spearow_main_relay3"
+ }
+ insert:
+ {
+ "OnTrigger" "Zombie_choiceSetDisplayText 啄 瞪眼01"
+ }
+}
+;小火龙
+modify:
+{
+ match:
+ {
+ "classname" "logic_relay"
+ "targetname" "charmander_main_relay1"
+ }
+ insert:
+ {
+ "OnTrigger" "Zombie_choiceSetDisplayText 火花 利爪 叫声0.011"
+ }
+}
+;
+;墨海马
+modify:
+{
+ match:
+ {
+ "classname" "logic_relay"
+ "targetname" "Horsea_main_relay2"
+ }
+ insert:
+ {
+ "OnTrigger" "Zombie_choiceSetDisplayText 水枪 泡沫 瞪眼01"
+ }
+}
+modify:
+{
+ match:
+ {
+ "classname" "logic_relay"
+ "targetname" "Horsea_main_relay3"
+ }
+ insert:
+ {
+ "OnTrigger" "Zombie_choiceSetDisplayText 水枪 泡沫 瞪眼01"
+ }
+}
+;妙蛙种子
+modify:
+{
+ match:
+ {
+ "classname" "logic_relay"
+ "targetname" "bulbasaur_main_relay1"
+ }
+ insert:
+ {
+ "OnTrigger" "Zombie_choiceSetDisplayText 藤鞭 撞击 寄生种子0.011"
+ }
+}
+;
+;独角虫
+modify:
+{
+ match:
+ {
+ "classname" "logic_relay"
+ "targetname" "Weedle_main_relay2"
+ }
+ insert:
+ {
+ "OnTrigger" "Zombie_choiceSetDisplayText 毒针 撞击 虫咬 01"
+ }
+}
+modify:
+{
+ match:
+ {
+ "classname" "logic_relay"
+ "targetname" "Weedle_main_relay3"
+ }
+ insert:
+ {
+ "OnTrigger" "Zombie_choiceSetDisplayText 毒针 撞击 虫咬 01"
+ }
+}
+;
+;杰尼龟
+modify:
+{
+ match:
+ {
+ "classname" "logic_relay"
+ "targetname" "squirtle_main_relay1"
+ }
+ insert:
+ {
+ "OnTrigger" "Zombie_choiceSetDisplayText 水枪 撞击 摇尾巴 0.011"
+ }
+}
+;
+;地鼠
+modify:
+{
+ match:
+ {
+ "classname" "logic_relay"
+ "targetname" "diglett_main_relay2"
+ }
+ insert:
+ {
+ "OnTrigger" "Zombie_choiceSetDisplayText 掷泥 抓 叫声01"
+ }
+}
+modify:
+{
+ match:
+ {
+ "classname" "logic_relay"
+ "targetname" "diglett_main_relay3"
+ }
+ insert:
+ {
+ "OnTrigger" "Zombie_choiceSetDisplayText 掷泥 抓 叫声01"
+ }
+}
+;
+;海星
+modify:
+{
+ match:
+ {
+ "classname" "logic_relay"
+ "targetname" "staryu_main_relay1"
+ }
+ insert:
+ {
+ "OnTrigger" "Zombie_choiceSetDisplayText 水枪 撞击 变硬 01"
+ }
+}
+;
+;小拳石
+modify:
+{
+ match:
+ {
+ "classname" "logic_relay"
+ "targetname" "geodude_main_relay1"
+ }
+ insert:
+ {
+ "OnTrigger" "Zombie_choiceSetDisplayText 落石 撞击 变硬 01"
+ }
+}
+;
+;腕力
+modify:
+{
+ match:
+ {
+ "classname" "logic_relay"
+ "targetname" "Machop_main_relay2"
+ }
+ insert:
+ {
+ "OnTrigger" "Zombie_choiceSetDisplayText 空手劈 踢倒 聚气 01"
+ }
+}
+modify:
+{
+ match:
+ {
+ "classname" "logic_relay"
+ "targetname" "Machop_main_relay3"
+ }
+ insert:
+ {
+ "OnTrigger" "Zombie_choiceSetDisplayText 空手劈 踢倒 聚气 01"
+ }
+}
+;
+;主宝可梦文本提示修复
+modify:
+{
+ match:
+ {
+ "classname" "logic_relay"
+ "targetname" "bulbasaur_noises"
+ "hammerid" "560409"
+ }
+ insert:
+ {
+ "OnTrigger" "Human_choiceSetDisplayText 藤鞭 撞击 寄生种子01"
+ }
+}
+modify:
+{
+ match:
+ {
+ "classname" "logic_relay"
+ "targetname" "bulbasaur_noises1"
+ "hammerid" "559603"
+ }
+ insert:
+ {
+ "OnTrigger" "Zombie_choiceSetDisplayText 藤鞭 撞击 寄生种子01"
+ }
+}
+modify:
+{
+ match:
+ {
+ "classname" "logic_relay"
+ "targetname" "charmander_noises"
+ "hammerid" "560405"
+ }
+ insert:
+ {
+ "OnTrigger" "Human_choiceSetDisplayText 火花 利爪 叫声01"
+ }
+}
+modify:
+{
+ match:
+ {
+ "classname" "logic_relay"
+ "targetname" "charmander_noises1"
+ "hammerid" "559587"
+ }
+ insert:
+ {
+ "OnTrigger" "Zombie_choiceSetDisplayText 火花 利爪 叫声01"
+ }
+}
+modify:
+{
+ match:
+ {
+ "classname" "logic_relay"
+ "targetname" "squirtle_noises"
+ "hammerid" "560407"
+ }
+ insert:
+ {
+ "OnTrigger" "Human_choiceSetDisplayText 水枪 撞击 摇尾巴 01"
+ }
+}
+modify:
+{
+ match:
+ {
+ "classname" "logic_relay"
+ "targetname" "squirtle_noises1"
+ "hammerid" "559601"
+ }
+ insert:
+ {
+ "OnTrigger" "Zombie_choiceSetDisplayText 水枪 撞击 摇尾巴 01"
+ }
+}termination."
+ {
+ "chi" "小刚:' 岩石系宝可梦有着真正的勇气 '"
+ "AutoTranslate" "我的口袋妖怪都是岩石坚硬的,有着真正的勇气。"
+ "normaltext" "1"
+ }
+ "Fuhaha! You're going to challenge me knowing that you'll lose?"
+ {
+ "chi" "小刚:' fu哈哈哈哈,挑战我你会输知道吗? '"
+ "AutoTranslate" "Fuhaha!你会挑战我知道你会输吗?"
+ "normaltext" "1"
+ }
+ "Fine, then! Show me your best!"
+ {
+ "chi" "小刚:' 看来你不打算放弃..好吧 把
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_omochix.txt b/BossHP/configs/MapBossHP/ze_omochix.txt
new file mode 100644
index 0000000..d4bd40a
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_omochix.txt
@@ -0,0 +1,11 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "normal_boss_counter"
+ }
+ "0"
+ {
+ "HP_counter" "Level2_blue_counter"
+ }
+}
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_omochix_v2.txt b/BossHP/configs/MapBossHP/ze_omochix_v2.txt
new file mode 100644
index 0000000..3d39af7
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_omochix_v2.txt
@@ -0,0 +1,15 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "normal_boss_counter"
+ }
+ "0"
+ {
+ "HP_counter" "Level2_blue_counter"
+ }
+ "0"
+ {
+ "HP_counter" "level2_crystal_counter"
+ }
+}
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_otakuroom_v5_6f.txt b/BossHP/configs/MapBossHP/ze_otakuroom_v5_6f.txt
new file mode 100644
index 0000000..8fc1acd
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_otakuroom_v5_6f.txt
@@ -0,0 +1,13 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "ts_hp"
+ "CustomText" "Tenshi"
+ }
+ "1"
+ {
+ "HP_counter" "lv3_ts_hp"
+ "CustomText" "Tenshi"
+ }
+}
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_otakuroom_v5_6f3.txt b/BossHP/configs/MapBossHP/ze_otakuroom_v5_6f3.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_otakuroom_v5_6f3.txt
@@ -0,0 +1 @@
+
diff --git a/BossHP/configs/MapBossHP/ze_otakuroom_v5_6f4.txt b/BossHP/configs/MapBossHP/ze_otakuroom_v5_6f4.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_otakuroom_v5_6f4.txt
@@ -0,0 +1 @@
+
diff --git a/BossHP/configs/MapBossHP/ze_paper_escaper_p7.txt b/BossHP/configs/MapBossHP/ze_paper_escaper_p7.txt
new file mode 100644
index 0000000..6f4b949
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_paper_escaper_p7.txt
@@ -0,0 +1,19 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "BossExtHitP"
+ }
+ "1"
+ {
+ "HP_counter" "BossMassHitP"
+ }
+ "2"
+ {
+ "HP_counter" "BossRageHitP"
+ }
+ "3"
+ {
+ "HP_counter" "PanicHPCounter"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_pidaras_v1_4fix3_e10.txt b/BossHP/configs/MapBossHP/ze_pidaras_v1_4fix3_e10.txt
new file mode 100644
index 0000000..31bcdcc
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_pidaras_v1_4fix3_e10.txt
@@ -0,0 +1,32 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "npc_bahamut_counter"
+ "CustomText" "Bahamut"
+ }
+ "1"
+ {
+ "HP_counter" "trigger_pyramid_counter"
+ "CustomText" "Pyramid Head"
+ }
+ "2"
+ {
+ "HP_Group"
+ {
+ "0" "space_counter1"
+ "1" "space_counter2"
+ }
+ "CustomText" "Space"
+ }
+ "4"
+ {
+ "HP_counter" "boss_hp"
+ "CustomText" "Ur"
+ }
+ "5"
+ {
+ "HP_counter" "roshi_counter"
+ "CustomText" "Roshi"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_pirates_port_royal_v5_6.txt b/BossHP/configs/MapBossHP/ze_pirates_port_royal_v5_6.txt
new file mode 100644
index 0000000..b792bc0
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_pirates_port_royal_v5_6.txt
@@ -0,0 +1,63 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "delo_counter"
+ "HPbar_counter" "boss_hp_iterations"
+ "HPbar_min" "0"
+ "HPbar_max" "5"
+ "HPbar_default" "5"
+ "HPbar_mode" "1" // OnHitMin=1 OnHitMax=2
+ "CustomText" "Delo"
+ }
+ "1"
+ {
+ "HP_counter" "pirate_counter"
+ "HPbar_counter" "pirate_hp_iterations"
+ "HPbar_min" "0"
+ "HPbar_max" "5"
+ "HPbar_default" "5"
+ "HPbar_mode" "1" // OnHitMin=1 OnHitMax=2
+ "CustomText" "Pirate"
+ }
+ "2"
+ {
+ "HP_counter" "barbossa_counter"
+ "HPbar_counter" "barbossa_hp_iterations"
+ "HPbar_min" "0"
+ "HPbar_max" "5"
+ "HPbar_default" "5"
+ "HPbar_mode" "1" // OnHitMin=1 OnHitMax=2
+ "CustomText" "Barbossa"
+ }
+ "3"
+ {
+ "HP_counter" "kraken_counter"
+ "HPbar_counter" "kraken_hp_iterations"
+ "HPbar_min" "0"
+ "HPbar_max" "8"
+ "HPbar_default" "8"
+ "HPbar_mode" "1" // OnHitMin=1 OnHitMax=2
+ "CustomText" "Kraken"
+ }
+ "4"
+ {
+ "HP_counter" "final_barbossa_counter2"
+ "HPbar_counter" ""
+ "HPbar_min" ""
+ "HPbar_max" ""
+ "HPbar_default" ""
+ "HPbar_mode" "" // OnHitMin=1 OnHitMax=2
+ "CustomText" "Barbossa"
+ }
+ "5"
+ {
+ "HP_counter" "final_barbossa_counter"
+ "HPbar_counter" ""
+ "HPbar_min" ""
+ "HPbar_max" ""
+ "HPbar_default" ""
+ "HPbar_mode" "" // OnHitMin=1 OnHitMax=2
+ "CustomText" "Barbossa"
+ }
+}
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_pizzatime_v9.txt b/BossHP/configs/MapBossHP/ze_pizzatime_v9.txt
new file mode 100644
index 0000000..559cdf6
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_pizzatime_v9.txt
@@ -0,0 +1,15 @@
+"math_counter"
+{
+ "0"
+ {
+ "Type" "breakable"
+ "BreakableName" "boss_ep_hp"
+ "CustomText" "Evil Pizza"
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "boss_jar_hp"
+ "CustomText" "JarJar Binks"
+ }
+}
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_pkmn_adventure_v9_3.txt b/BossHP/configs/MapBossHP/ze_pkmn_adventure_v9_3.txt
new file mode 100644
index 0000000..f077abd
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_pkmn_adventure_v9_3.txt
@@ -0,0 +1,127 @@
+"math_counter"
+{
+ // Stage 1 - Bosses
+ "21"
+ {
+ "HP_Group"
+ {
+ "0" "KirliaHP_1"
+ "1" "KirliaHP_2"
+ "2" "KirliaHP_3"
+ "3" "KirliaHP_4"
+ }
+ "CustomText" "Kirlia"
+ }
+ // Stage 2 - Bosses
+ "31"
+ {
+ "CustomText" "Noctowl"
+ "HP_counter" "NoctowlHP"
+ }
+ "32"
+ {
+ "CustomText" "Pidgeot"
+ "HP_counter" "PidgeotHP"
+ }
+ "33"
+ {
+ "CustomText" "Miltank"
+ "HP_counter" "MiltankHP"
+ }
+ // Stage 3 - Bosses
+ "2"
+ {
+ "CustomText" "Kirlia"
+ "Type" "breakable"
+ "BreakableName" "kirlia"
+ }
+ "3"
+ {
+ "CustomText" "Crobat"
+ "Type" "breakable"
+ "BreakableName" "Crobat"
+ }
+ "4"
+ {
+ "CustomText" "Groudon"
+ "HP_counter" "groudonhp"
+ }
+ "5"
+ {
+ "CustomText" "Kirlia"
+ "HP_counter" "finalkirlia_hp"
+ }
+ "45"
+ {
+ "CustomText" "Primal Groudon"
+ "HP_counter" "PrimalGroudonHP"
+ }
+ // Stage 4 - Bosses
+ "6"
+ {
+ "CustomText" "Skuntank"
+ "HP_counter" "skuntankhealth"
+ }
+ "7"
+ {
+ "CustomText" "Purugly"
+ "HP_counter" "puruglyhealth"
+ }
+ "8"
+ {
+ "CustomText" "Honchkrow"
+ "HP_counter" "honchkrowhp"
+ }
+ "9"
+ {
+ "CustomText" "Crobat"
+ "HP_counter" "crobatcyrushp"
+ }
+ "10"
+ {
+ "CustomText" "Weavile"
+ "HP_counter" "weavilehp"
+ }
+ "11"
+ {
+ "CustomText" "Giratina"
+ "HP_counter" "giratinahp"
+ }
+ "12"
+ {
+ "CustomText" "Crobat"
+ "HP_counter" "crobatfinal2_health"
+ }
+ "13"
+ {
+ "CustomText" "Weavile"
+ "HP_counter" "weavilefinalhp"
+ }
+ // Stage 5 - Bosses
+ "51"
+ {
+ "HP_Group"
+ {
+ "0" "ArceusHP_1"
+ "1" "ArceusHP_2"
+ "2" "ArceusHP_3"
+ "3" "ArceusHP_4"
+ }
+ "CustomText" "Arceus"
+ }
+ "52"
+ {
+ "CustomText" "Arceus Judgement"
+ "HP_counter" "Arceus_Judgement_HP"
+ }
+ "53"
+ {
+ "CustomText" "Darkrai"
+ "HP_counter" "DarkraiHP"
+ }
+ "54"
+ {
+ "CustomText" "Gallade"
+ "HP_counter" "Level5_GalladeHP"
+ }
+}
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_predator_ultimate_p7.txt b/BossHP/configs/MapBossHP/ze_predator_ultimate_p7.txt
new file mode 100644
index 0000000..30a2f30
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_predator_ultimate_p7.txt
@@ -0,0 +1,48 @@
+"math_counter"
+{
+ "config"
+ {
+ "BossHpKeepTime" "0"
+ "BossDieKeepTime" "0"
+ }
+ "0"
+ {
+ "HP_counter" "cboss_predatorhealth_counter"
+ "CustomText" "Predator"
+ }
+ "1"
+ {
+ "HP_counter" "bosshealth_endboss"
+ "CustomText" "Predator"
+ }
+ "2"
+ {
+ "HP_counter" "mob_grudge_math"
+ "CustomText" "Predator"
+ }
+ "3"
+ {
+ "HP_counter" "aztecboss_math_health"
+ "CustomText" "Predator"
+ }
+ "4"
+ {
+ "HP_counter" "aztecboss_math_health_2"
+ "CustomText" "Predator"
+ }
+ "5"
+ {
+ "HP_counter" "fboss_math_1"
+ "CustomText" "Predator(狂暴)"
+ }
+ "5"
+ {
+ "HP_counter" "fboss_math_2"
+ "CustomText" "Predator"
+ }
+ "6"
+ {
+ "HP_counter" "fboss_ee_math"
+ "CustomText" "Alien"
+ }
+}
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_project_alcaria_v3_2.txt b/BossHP/configs/MapBossHP/ze_project_alcaria_v3_2.txt
new file mode 100644
index 0000000..3cc2597
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_project_alcaria_v3_2.txt
@@ -0,0 +1,21 @@
+"math_counter"
+{
+ "0" //math_counter
+ {
+ "HP_counter" "naraka_counter2"
+ "HP_Mode" "1"
+ "HPbar_counter" "naraka_hp_iterations2"
+ "HPinit_counter" "naraka_hp_backup2"
+ "CustomText" ""
+ "HPbar_mode" "1"
+ }
+ "0" //math_counter
+ {
+ "HP_counter" "nrk2_naraka_counter"
+ "HP_Mode" "1"
+ "HPbar_counter" "nrk2_naraka_hp_iterations"
+ "HPinit_counter" "nrk2_naraka_hp_backup"
+ "CustomText" ""
+ "HPbar_mode" "1"
+ }
+}
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_project_alcaria_x.txt b/BossHP/configs/MapBossHP/ze_project_alcaria_x.txt
new file mode 100644
index 0000000..3cc2597
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_project_alcaria_x.txt
@@ -0,0 +1,21 @@
+"math_counter"
+{
+ "0" //math_counter
+ {
+ "HP_counter" "naraka_counter2"
+ "HP_Mode" "1"
+ "HPbar_counter" "naraka_hp_iterations2"
+ "HPinit_counter" "naraka_hp_backup2"
+ "CustomText" ""
+ "HPbar_mode" "1"
+ }
+ "0" //math_counter
+ {
+ "HP_counter" "nrk2_naraka_counter"
+ "HP_Mode" "1"
+ "HPbar_counter" "nrk2_naraka_hp_iterations"
+ "HPinit_counter" "nrk2_naraka_hp_backup"
+ "CustomText" ""
+ "HPbar_mode" "1"
+ }
+}
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_random_p2.txt b/BossHP/configs/MapBossHP/ze_random_p2.txt
new file mode 100644
index 0000000..ee73225
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_random_p2.txt
@@ -0,0 +1,9 @@
+"math_counter"
+{
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "FBK"
+ "CustomText" ""
+ }
+}
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_random_p2_fix.txt b/BossHP/configs/MapBossHP/ze_random_p2_fix.txt
new file mode 100644
index 0000000..ee73225
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_random_p2_fix.txt
@@ -0,0 +1,9 @@
+"math_counter"
+{
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "FBK"
+ "CustomText" ""
+ }
+}
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_reloaded_v1_e10.txt b/BossHP/configs/MapBossHP/ze_reloaded_v1_e10.txt
new file mode 100644
index 0000000..42ac441
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_reloaded_v1_e10.txt
@@ -0,0 +1,11 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "boss_hp"
+ }
+ "1"
+ {
+ "HP_counter" "boss_hp_Immense"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_reloaded_v1_ez2.txt b/BossHP/configs/MapBossHP/ze_reloaded_v1_ez2.txt
new file mode 100644
index 0000000..e9949af
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_reloaded_v1_ez2.txt
@@ -0,0 +1,15 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "boss_hp"
+ }
+ "1"
+ {
+ "HP_counter" "boss_hp_Immense"
+ "HP_Mode" "1"
+ "HPbar_counter" "hp_mat"
+ "HPinit_counter" "hp_backup"
+ "HPbar_mode" "1"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_rizomata_a45.txt b/BossHP/configs/MapBossHP/ze_rizomata_a45.txt
new file mode 100644
index 0000000..ed3eb93
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_rizomata_a45.txt
@@ -0,0 +1,29 @@
+"math_counter"
+{
+ "config"
+ {
+ "MultBoss" "0"
+ "IsDynamicHP" "1"
+ "RoundEndShowTopDamage" "1"
+ "ShowTopDamageDuringBOSS" "0"
+ "ForceEnable" "1"
+ }
+ "0"
+ {
+ "HP_counter" "2_boss_hpcounter"
+ "HPbar_counter" "2_boss_hpmasscounter"
+ "HPbar_min" ""
+ "HPbar_max" "10"
+ "HPbar_default" ""
+ "HPbar_mode" "2"
+ }
+ "1"
+ {
+ "HP_counter" "3_boss_hpcounter"
+ "HPbar_counter" "3_boss_hpmasscounter"
+ "HPbar_min" ""
+ "HPbar_max" "10"
+ "HPbar_default" ""
+ "HPbar_mode" "2"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_rizomata_b44.txt b/BossHP/configs/MapBossHP/ze_rizomata_b44.txt
new file mode 100644
index 0000000..8262ed8
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_rizomata_b44.txt
@@ -0,0 +1,34 @@
+"math_counter"
+{
+ "config"
+ {
+ "MultBoss" "0"
+ "IsDynamicHP" "1"
+ "RoundEndShowTopDamage" "1"
+ "ShowTopDamageDuringBOSS" "0"
+ "ForceEnable" "1"
+ }
+ "0"
+ {
+ "HP_counter" "4_boss_hpcounter"
+ "HPbar_counter" "4_boss_hpmasscounter"
+ "HPbar_min" ""
+ "HPbar_max" "10"
+ "HPbar_default" ""
+ "HPbar_mode" "2"
+ }
+ "1"
+ {
+ "HP_counter" "5_boss_hpcounter"
+ "HPbar_counter" "5_boss_hpmasscounter"
+ "HPbar_min" ""
+ "HPbar_max" "10"
+ "HPbar_default" ""
+ "HPbar_mode" "2"
+ }
+ "2"
+ {
+ "HP_counter" "5_boss_enragehpcounter"
+ "CustomText" "BOSS (ENRAGE)"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_rizomata_b45.txt b/BossHP/configs/MapBossHP/ze_rizomata_b45.txt
new file mode 100644
index 0000000..8262ed8
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_rizomata_b45.txt
@@ -0,0 +1,34 @@
+"math_counter"
+{
+ "config"
+ {
+ "MultBoss" "0"
+ "IsDynamicHP" "1"
+ "RoundEndShowTopDamage" "1"
+ "ShowTopDamageDuringBOSS" "0"
+ "ForceEnable" "1"
+ }
+ "0"
+ {
+ "HP_counter" "4_boss_hpcounter"
+ "HPbar_counter" "4_boss_hpmasscounter"
+ "HPbar_min" ""
+ "HPbar_max" "10"
+ "HPbar_default" ""
+ "HPbar_mode" "2"
+ }
+ "1"
+ {
+ "HP_counter" "5_boss_hpcounter"
+ "HPbar_counter" "5_boss_hpmasscounter"
+ "HPbar_min" ""
+ "HPbar_max" "10"
+ "HPbar_default" ""
+ "HPbar_mode" "2"
+ }
+ "2"
+ {
+ "HP_counter" "5_boss_enragehpcounter"
+ "CustomText" "BOSS (ENRAGE)"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_roof_adventure_v8f.txt b/BossHP/configs/MapBossHP/ze_roof_adventure_v8f.txt
new file mode 100644
index 0000000..7c6e85e
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_roof_adventure_v8f.txt
@@ -0,0 +1,11 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "counter_bosshp"
+ "HP_Mode" "1"
+ "HPbar_counter" "boss_hpcounter"
+ "HPbar_mode" "1"
+ "CustomText" ""
+ }
+}
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_sandstorm_go_v1_3.txt b/BossHP/configs/MapBossHP/ze_sandstorm_go_v1_3.txt
new file mode 100644
index 0000000..94a8417
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_sandstorm_go_v1_3.txt
@@ -0,0 +1,48 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "mutant_counter1"
+ "HPbar_counter" "mutant_hp_iterations1"
+ "HPbar_min" "0"
+ "HPbar_max" "10"
+ "HPbar_default" "10"
+ "HPbar_mode" "1" // OnHitMin=1 OnHitMax=2
+ }
+ "1"
+ {
+ "HP_counter" "grg_counter"
+ "HPbar_counter" "grg_hp_iterations"
+ "HPbar_min" "0"
+ "HPbar_max" "10"
+ "HPbar_default" "10"
+ "HPbar_mode" "1" // OnHitMin=1 OnHitMax=2
+ }
+ "2"
+ {
+ "HP_counter" "mutant_counter"
+ "HPbar_counter" "mutant_hp_iterations"
+ "HPbar_min" "0"
+ "HPbar_max" "10"
+ "HPbar_default" "10"
+ "HPbar_mode" "1" // OnHitMin=1 OnHitMax=2
+ }
+ "3"
+ {
+ "HP_counter" "garg_counter"
+ "HPbar_counter" "garg_hp_iterations"
+ "HPbar_min" "0"
+ "HPbar_max" "10"
+ "HPbar_default" "10"
+ "HPbar_mode" "1" // OnHitMin=1 OnHitMax=2
+ }
+ "4"
+ {
+ "HP_counter" "sss5_l_laser_counter"
+ "HPbar_counter" "sss5_l_laser_hp_interations"
+ "HPbar_min" "0"
+ "HPbar_max" "10"
+ "HPbar_default" "10"
+ "HPbar_mode" "1" // OnHitMin=1 OnHitMax=2
+ }
+}
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_sandstorm_go_v1_4.txt b/BossHP/configs/MapBossHP/ze_sandstorm_go_v1_4.txt
new file mode 100644
index 0000000..94a8417
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_sandstorm_go_v1_4.txt
@@ -0,0 +1,48 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "mutant_counter1"
+ "HPbar_counter" "mutant_hp_iterations1"
+ "HPbar_min" "0"
+ "HPbar_max" "10"
+ "HPbar_default" "10"
+ "HPbar_mode" "1" // OnHitMin=1 OnHitMax=2
+ }
+ "1"
+ {
+ "HP_counter" "grg_counter"
+ "HPbar_counter" "grg_hp_iterations"
+ "HPbar_min" "0"
+ "HPbar_max" "10"
+ "HPbar_default" "10"
+ "HPbar_mode" "1" // OnHitMin=1 OnHitMax=2
+ }
+ "2"
+ {
+ "HP_counter" "mutant_counter"
+ "HPbar_counter" "mutant_hp_iterations"
+ "HPbar_min" "0"
+ "HPbar_max" "10"
+ "HPbar_default" "10"
+ "HPbar_mode" "1" // OnHitMin=1 OnHitMax=2
+ }
+ "3"
+ {
+ "HP_counter" "garg_counter"
+ "HPbar_counter" "garg_hp_iterations"
+ "HPbar_min" "0"
+ "HPbar_max" "10"
+ "HPbar_default" "10"
+ "HPbar_mode" "1" // OnHitMin=1 OnHitMax=2
+ }
+ "4"
+ {
+ "HP_counter" "sss5_l_laser_counter"
+ "HPbar_counter" "sss5_l_laser_hp_interations"
+ "HPbar_min" "0"
+ "HPbar_max" "10"
+ "HPbar_default" "10"
+ "HPbar_mode" "1" // OnHitMin=1 OnHitMax=2
+ }
+}
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_santassination_v3.txt b/BossHP/configs/MapBossHP/ze_santassination_v3.txt
new file mode 100644
index 0000000..3bb4fc4
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_santassination_v3.txt
@@ -0,0 +1,21 @@
+"math_counter"
+{
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "bosss_hp"
+ "CustomText" ""
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "bosss_hp1"
+ "CustomText" ""
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "bosss_hp2"
+ "CustomText" ""
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_serpentis_temple_csgo.txt b/BossHP/configs/MapBossHP/ze_serpentis_temple_csgo.txt
new file mode 100644
index 0000000..a858716
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_serpentis_temple_csgo.txt
@@ -0,0 +1,33 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "HPCounter"
+ "HPbar_counter" "HPCounterIterator"
+ "HPinit_counter" "HPCounterBackUp"
+ "HPbar_min" ""
+ "HPbar_max" "30"
+ "HPbar_default" "30"
+ "HPbar_mode" "1"
+ }
+ "1"
+ {
+ "HP_counter" "Room4_Boss_Hp"
+ "HPbar_counter" "Room4_Boss_HpCounter"
+ "HPinit_counter" "Room4_Boss_HpBackup"
+ "HPbar_min" ""
+ "HPbar_max" "40"
+ "HPbar_default" "40"
+ "HPbar_mode" "1"
+ }
+ "2"
+ {
+ "HP_counter" "Room8_Boss_Hp"
+ "HPbar_counter" "Room8_Boss_HpCounter"
+ "HPinit_counter" "Room8_Boss_HpBackup"
+ "HPbar_min" ""
+ "HPbar_max" "40"
+ "HPbar_default" "40"
+ "HPbar_mode" "1"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_serpentis_temple_csgo1.txt b/BossHP/configs/MapBossHP/ze_serpentis_temple_csgo1.txt
new file mode 100644
index 0000000..a858716
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_serpentis_temple_csgo1.txt
@@ -0,0 +1,33 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "HPCounter"
+ "HPbar_counter" "HPCounterIterator"
+ "HPinit_counter" "HPCounterBackUp"
+ "HPbar_min" ""
+ "HPbar_max" "30"
+ "HPbar_default" "30"
+ "HPbar_mode" "1"
+ }
+ "1"
+ {
+ "HP_counter" "Room4_Boss_Hp"
+ "HPbar_counter" "Room4_Boss_HpCounter"
+ "HPinit_counter" "Room4_Boss_HpBackup"
+ "HPbar_min" ""
+ "HPbar_max" "40"
+ "HPbar_default" "40"
+ "HPbar_mode" "1"
+ }
+ "2"
+ {
+ "HP_counter" "Room8_Boss_Hp"
+ "HPbar_counter" "Room8_Boss_HpCounter"
+ "HPinit_counter" "Room8_Boss_HpBackup"
+ "HPbar_min" ""
+ "HPbar_max" "40"
+ "HPbar_default" "40"
+ "HPbar_mode" "1"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_shaurma_v3_b07_t5.txt b/BossHP/configs/MapBossHP/ze_shaurma_v3_b07_t5.txt
new file mode 100644
index 0000000..475e3f7
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_shaurma_v3_b07_t5.txt
@@ -0,0 +1,30 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "level1_boss_health"
+ "HP_Mode" "1"
+ "HPbar_counter" "level1_boss_health_counter"
+ "HPinit_counter" "level1_boss_health_backup"
+ "CustomText" ""
+ "HPbar_mode" "2"
+ }
+ "1"
+ {
+ "HP_counter" "level2_boss_health"
+ "HP_Mode" "1"
+ "HPbar_counter" "level2_boss_health_counter"
+ "HPinit_counter" "level2_boss_health_backup"
+ "CustomText" ""
+ "HPbar_mode" "2"
+ }
+ "2"
+ {
+ "HP_counter" "level3_boss_health"
+ "HP_Mode" "1"
+ "HPbar_counter" "level3_boss_health_counter"
+ "HPinit_counter" "level3_boss_health_backup"
+ "CustomText" ""
+ "HPbar_mode" "2"
+ }
+}
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_shroomforest2_p6.txt b/BossHP/configs/MapBossHP/ze_shroomforest2_p6.txt
new file mode 100644
index 0000000..6ba7a5b
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_shroomforest2_p6.txt
@@ -0,0 +1,23 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "Boss_Health"
+ "HPbar_counter" "Boss_HealthCount"
+ "HPinit_counter" "Boss_HealthInit"
+ "HPbar_min" "0"
+ "HPbar_max" "5"
+ "HPbar_default" "0"
+ "HPbar_mode" "2" // OnHitMin=1 OnHitMax=2
+ }
+ "1"
+ {
+ "HP_counter" "Satan_Health"
+ "HPbar_counter" "Satan_HealthCount"
+ "HPinit_counter" "Satan_HealthInit"
+ "HPbar_min" "0"
+ "HPbar_max" "5"
+ "HPbar_default" "0"
+ "HPbar_mode" "2" // OnHitMin=1 OnHitMax=2
+ }
+}
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_shroomforest_p6.txt b/BossHP/configs/MapBossHP/ze_shroomforest_p6.txt
new file mode 100644
index 0000000..5badb80
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_shroomforest_p6.txt
@@ -0,0 +1,8 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "dynamic_HP"
+ "HP_Mode" "2"
+ }
+}
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_sit_caelum_paradisus_b7_hdr.txt b/BossHP/configs/MapBossHP/ze_sit_caelum_paradisus_b7_hdr.txt
new file mode 100644
index 0000000..e69de29
diff --git a/BossHP/configs/MapBossHP/ze_sky_athletic_adv_v9_10.txt b/BossHP/configs/MapBossHP/ze_sky_athletic_adv_v9_10.txt
new file mode 100644
index 0000000..5514a5c
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_sky_athletic_adv_v9_10.txt
@@ -0,0 +1,53 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "betray_him_hp_count_now"
+ "HPbar_counter" "betray_him_hp_count"
+ "HPbar_min" ""
+ "HPbar_max" "8"
+ "HPbar_default" "8"
+ "HPbar_mode" "1"
+ }
+ "1"
+ {
+ "HP_counter" "crasher hp"
+ }
+ "2"
+ {
+ "HP_counter" "cute cloud hp"
+ }
+ "3"
+ {
+ "HP_counter" "ex1_girl_cloud_hp1"
+ }
+ "4"
+ {
+ "HP_counter" "ex1_girl_cloud_hp2"
+ }
+ "5"
+ {
+ "HP_counter" "ex2_boss_real_hp"
+ }
+ "6"
+ {
+ "HP_counter" "final_boss_ittanstop_counter"
+ }
+ "7"
+ {
+ "HP_counter" "final_boss_truehp_counter"
+ }
+ "8"
+ {
+ "HP_counter" "final_crasher_finale_final_hp_counter"
+ }
+ "9"
+ {
+ "HP_counter" "final_crasher_hp_counter_total"
+ "HPbar_counter" "final_crasher_hp_counter_10"
+ "HPbar_min" ""
+ "HPbar_max" "10"
+ "HPbar_default" "10"
+ "HPbar_mode" "1"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_sky_athletic_adv_v9_12.txt b/BossHP/configs/MapBossHP/ze_sky_athletic_adv_v9_12.txt
new file mode 100644
index 0000000..5514a5c
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_sky_athletic_adv_v9_12.txt
@@ -0,0 +1,53 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "betray_him_hp_count_now"
+ "HPbar_counter" "betray_him_hp_count"
+ "HPbar_min" ""
+ "HPbar_max" "8"
+ "HPbar_default" "8"
+ "HPbar_mode" "1"
+ }
+ "1"
+ {
+ "HP_counter" "crasher hp"
+ }
+ "2"
+ {
+ "HP_counter" "cute cloud hp"
+ }
+ "3"
+ {
+ "HP_counter" "ex1_girl_cloud_hp1"
+ }
+ "4"
+ {
+ "HP_counter" "ex1_girl_cloud_hp2"
+ }
+ "5"
+ {
+ "HP_counter" "ex2_boss_real_hp"
+ }
+ "6"
+ {
+ "HP_counter" "final_boss_ittanstop_counter"
+ }
+ "7"
+ {
+ "HP_counter" "final_boss_truehp_counter"
+ }
+ "8"
+ {
+ "HP_counter" "final_crasher_finale_final_hp_counter"
+ }
+ "9"
+ {
+ "HP_counter" "final_crasher_hp_counter_total"
+ "HPbar_counter" "final_crasher_hp_counter_10"
+ "HPbar_min" ""
+ "HPbar_max" "10"
+ "HPbar_default" "10"
+ "HPbar_mode" "1"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_stalker_ultimate_v1.txt b/BossHP/configs/MapBossHP/ze_stalker_ultimate_v1.txt
new file mode 100644
index 0000000..1137b0f
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_stalker_ultimate_v1.txt
@@ -0,0 +1,28 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "boss_hp"
+ }
+ "0"
+ {
+ "HP_counter" "boss3_health"
+ }
+ "0"
+ {
+ "HP_counter" "mob_grudge_math1"
+ }
+ "0"
+ {
+ "HP_counter" "mob_grudge_math"
+ "CustomText" "BOSS (幻境)"
+ }
+ "0"
+ {
+ "HP_counter" "mob_grudge_math_1"
+ }
+ "0"
+ {
+ "HP_counter" "boss4_hp"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_stalker_ultimate_v2_3_g3.txt b/BossHP/configs/MapBossHP/ze_stalker_ultimate_v2_3_g3.txt
new file mode 100644
index 0000000..49b4ae9
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_stalker_ultimate_v2_3_g3.txt
@@ -0,0 +1,28 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "mob_grudge_math1"
+ "CustomText" "Controller"
+ }
+ "1"
+ {
+ "HP_counter" "mob_grudge_math_1"
+ "CustomText" "Energy Ball"
+ }
+ "2"
+ {
+ "HP_counter" "boss3_health"
+ "CustomText" "Energy Ball"
+ }
+ "3"
+ {
+ "HP_counter" "boss_hp"
+ "CustomText" "Bloodsucker"
+ }
+ "4"
+ {
+ "HP_counter" "mob_grudge_math"
+ "CustomText" "Controller"
+ }
+}
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_stalker_ultimate_v2_3_g5.txt b/BossHP/configs/MapBossHP/ze_stalker_ultimate_v2_3_g5.txt
new file mode 100644
index 0000000..bbfc4d6
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_stalker_ultimate_v2_3_g5.txt
@@ -0,0 +1,42 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "mob_grudge_math1"
+ "CustomText" "Controller"
+ }
+ "1"
+ {
+ "HP_counter" "mob_grudge_math_1"
+ "CustomText" "Energy Ball"
+ }
+ "2"
+ {
+ "HP_counter" "boss3_health"
+ "CustomText" "Energy Ball"
+ }
+ "3"
+ {
+ "HP_counter" "boss_hp"
+ "CustomText" "Bloodsucker"
+ }
+ "4"
+ {
+ "HP_counter" "mob_grudge_math"
+ "CustomText" "Controller"
+ }
+ "4"
+ {
+ "HP_counter" "sphere_counter"
+ }
+ "4"
+ {
+ "HP_counter" "boss4_hp"
+ "CustomText" "Energy Ball"
+ }
+ "4"
+ {
+ "HP_counter" "boss5_hp"
+ "CustomText" "Energy Ball"
+ }
+}
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_stalker_ultimate_v2_3_g6.txt b/BossHP/configs/MapBossHP/ze_stalker_ultimate_v2_3_g6.txt
new file mode 100644
index 0000000..bbfc4d6
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_stalker_ultimate_v2_3_g6.txt
@@ -0,0 +1,42 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "mob_grudge_math1"
+ "CustomText" "Controller"
+ }
+ "1"
+ {
+ "HP_counter" "mob_grudge_math_1"
+ "CustomText" "Energy Ball"
+ }
+ "2"
+ {
+ "HP_counter" "boss3_health"
+ "CustomText" "Energy Ball"
+ }
+ "3"
+ {
+ "HP_counter" "boss_hp"
+ "CustomText" "Bloodsucker"
+ }
+ "4"
+ {
+ "HP_counter" "mob_grudge_math"
+ "CustomText" "Controller"
+ }
+ "4"
+ {
+ "HP_counter" "sphere_counter"
+ }
+ "4"
+ {
+ "HP_counter" "boss4_hp"
+ "CustomText" "Energy Ball"
+ }
+ "4"
+ {
+ "HP_counter" "boss5_hp"
+ "CustomText" "Energy Ball"
+ }
+}
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_stalker_ultimate_v4_4.txt b/BossHP/configs/MapBossHP/ze_stalker_ultimate_v4_4.txt
new file mode 100644
index 0000000..1dd560b
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_stalker_ultimate_v4_4.txt
@@ -0,0 +1,23 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "boss_hp"
+ }
+ "0"
+ {
+ "HP_counter" "boss3_health"
+ }
+ "0"
+ {
+ "HP_counter" "mob_grudge_math1"
+ }
+ "0"
+ {
+ "HP_counter" "mob_grudge_math"
+ }
+ "0"
+ {
+ "HP_counter" "mob_grudge_math_1"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_starwars_v1_5.txt b/BossHP/configs/MapBossHP/ze_starwars_v1_5.txt
new file mode 100644
index 0000000..a844925
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_starwars_v1_5.txt
@@ -0,0 +1,63 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "Boss_heal_tank"
+ }
+ "1"
+ {
+ "HP_counter" "Math_conter_station"
+ }
+ "2"
+ {
+ "HP_counter" "darth_vader_1"
+ "HPbar_counter" "darth_vader_3"
+ "HPinit_counter" "darth_vader_2"
+ "HPbar_min" ""
+ "HPbar_max" "8"
+ "HPbar_default" "8"
+ "HPbar_mode" "1"
+ }
+ "3"
+ {
+ "HP_counter" "darth_sid_1"
+ "HPbar_counter" "darth_sid_3"
+ "HPinit_counter" "darth_sid_2"
+ "HPbar_min" ""
+ "HPbar_max" "8"
+ "HPbar_default" "8"
+ "HPbar_mode" "1"
+ }
+ "4"
+ {
+ "HP_counter" "darth_mol_1"
+ "HPbar_counter" "darth_mol_3"
+ "HPinit_counter" "darth_mol_2"
+ "HPbar_min" ""
+ "HPbar_max" "8"
+ "HPbar_default" "8"
+ "HPbar_mode" "1"
+ }
+ "5"
+ {
+ "HP_counter" "darth_sphere_1"
+ "HPbar_counter" "darth_sphere_3"
+ "HPinit_counter" "darth_sphere_2"
+ "HPbar_min" ""
+ "HPbar_max" "8"
+ "HPbar_default" "8"
+ "HPbar_mode" "1"
+ }
+ "6"
+ {
+ "HP_counter" "Boss_heal_dart_maul"
+ }
+ "7"
+ {
+ "HP_counter" "Lvl_hard_heal"
+ }
+ "8"
+ {
+ "HP_counter" "Boss_heal_dart_vader"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_starwars_v2fix_csgo2.txt b/BossHP/configs/MapBossHP/ze_starwars_v2fix_csgo2.txt
new file mode 100644
index 0000000..a844925
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_starwars_v2fix_csgo2.txt
@@ -0,0 +1,63 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "Boss_heal_tank"
+ }
+ "1"
+ {
+ "HP_counter" "Math_conter_station"
+ }
+ "2"
+ {
+ "HP_counter" "darth_vader_1"
+ "HPbar_counter" "darth_vader_3"
+ "HPinit_counter" "darth_vader_2"
+ "HPbar_min" ""
+ "HPbar_max" "8"
+ "HPbar_default" "8"
+ "HPbar_mode" "1"
+ }
+ "3"
+ {
+ "HP_counter" "darth_sid_1"
+ "HPbar_counter" "darth_sid_3"
+ "HPinit_counter" "darth_sid_2"
+ "HPbar_min" ""
+ "HPbar_max" "8"
+ "HPbar_default" "8"
+ "HPbar_mode" "1"
+ }
+ "4"
+ {
+ "HP_counter" "darth_mol_1"
+ "HPbar_counter" "darth_mol_3"
+ "HPinit_counter" "darth_mol_2"
+ "HPbar_min" ""
+ "HPbar_max" "8"
+ "HPbar_default" "8"
+ "HPbar_mode" "1"
+ }
+ "5"
+ {
+ "HP_counter" "darth_sphere_1"
+ "HPbar_counter" "darth_sphere_3"
+ "HPinit_counter" "darth_sphere_2"
+ "HPbar_min" ""
+ "HPbar_max" "8"
+ "HPbar_default" "8"
+ "HPbar_mode" "1"
+ }
+ "6"
+ {
+ "HP_counter" "Boss_heal_dart_maul"
+ }
+ "7"
+ {
+ "HP_counter" "Lvl_hard_heal"
+ }
+ "8"
+ {
+ "HP_counter" "Boss_heal_dart_vader"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_sunkentemple_v3_1.txt b/BossHP/configs/MapBossHP/ze_sunkentemple_v3_1.txt
new file mode 100644
index 0000000..408cef4
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_sunkentemple_v3_1.txt
@@ -0,0 +1,7 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "Boss_Counter"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_sunlight_v2_0_p8_ps1.txt b/BossHP/configs/MapBossHP/ze_sunlight_v2_0_p8_ps1.txt
new file mode 100644
index 0000000..912a114
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_sunlight_v2_0_p8_ps1.txt
@@ -0,0 +1,12 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "counter_boss_health"
+ }
+ "1"
+ {
+ "HP_counter" "counter_dragonhealth"
+ "CustomText" "Dragon"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_surf_bona_a1_3.txt b/BossHP/configs/MapBossHP/ze_surf_bona_a1_3.txt
new file mode 100644
index 0000000..eaea9c9
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_surf_bona_a1_3.txt
@@ -0,0 +1,7 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "boss_hp"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_surf_froyo_v2_1.txt b/BossHP/configs/MapBossHP/ze_surf_froyo_v2_1.txt
new file mode 100644
index 0000000..b0fd980
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_surf_froyo_v2_1.txt
@@ -0,0 +1,15 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_Group"
+ {
+ "0" "boss_star_hitcounter1"
+ "1" "boss_star_hitcounter2"
+ "2" "boss_star_hitcounter3"
+ "3" "boss_star_hitcounter4"
+ "4" "boss_star_hitcounter5"
+ }
+ "CustomText" "Star"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_surf_froyo_v2_2.txt b/BossHP/configs/MapBossHP/ze_surf_froyo_v2_2.txt
new file mode 100644
index 0000000..b0fd980
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_surf_froyo_v2_2.txt
@@ -0,0 +1,15 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_Group"
+ {
+ "0" "boss_star_hitcounter1"
+ "1" "boss_star_hitcounter2"
+ "2" "boss_star_hitcounter3"
+ "3" "boss_star_hitcounter4"
+ "4" "boss_star_hitcounter5"
+ }
+ "CustomText" "Star"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_surf_gypt_v1_3_1f.txt b/BossHP/configs/MapBossHP/ze_surf_gypt_v1_3_1f.txt
new file mode 100644
index 0000000..b0fd980
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_surf_gypt_v1_3_1f.txt
@@ -0,0 +1,15 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_Group"
+ {
+ "0" "boss_star_hitcounter1"
+ "1" "boss_star_hitcounter2"
+ "2" "boss_star_hitcounter3"
+ "3" "boss_star_hitcounter4"
+ "4" "boss_star_hitcounter5"
+ }
+ "CustomText" "Star"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_surf_sahok_p3.txt b/BossHP/configs/MapBossHP/ze_surf_sahok_p3.txt
new file mode 100644
index 0000000..3d9f666
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_surf_sahok_p3.txt
@@ -0,0 +1,7 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "Boss_Health"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_surf_virtus_b1_2.txt b/BossHP/configs/MapBossHP/ze_surf_virtus_b1_2.txt
new file mode 100644
index 0000000..eaea9c9
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_surf_virtus_b1_2.txt
@@ -0,0 +1,7 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "boss_hp"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_temple_raider_b4_ps6.txt b/BossHP/configs/MapBossHP/ze_temple_raider_b4_ps6.txt
new file mode 100644
index 0000000..2ed79bf
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_temple_raider_b4_ps6.txt
@@ -0,0 +1,16 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "Boss_Health"
+ "HPbar_counter" "Boss_Health_Overlay_Counter"
+ "HPbar_min" ""
+ "HPbar_max" "10"
+ "HPbar_default" ""
+ "HPbar_mode" "2"
+ }
+ "1"
+ {
+ "HP_counter" "End_Boss_Health"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_tesv_skyrim_v5_6.txt b/BossHP/configs/MapBossHP/ze_tesv_skyrim_v5_6.txt
new file mode 100644
index 0000000..fb5dd09
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_tesv_skyrim_v5_6.txt
@@ -0,0 +1,53 @@
+"math_counter"
+{
+ "config"
+ {
+ "ForceEnable" "0"
+ }
+ "0"
+ {
+ "HP_counter" "counter_1"
+ "HPbar_counter" "BossHpIterations4"
+ "HPbar_min" "0"
+ "HPbar_max" "10"
+ "HPbar_default" "10"
+ "HPbar_mode" "1" // OnHitMin=1 OnHitMax=2
+ "CustomText" "Alduin"
+ }
+ "1"
+ {
+ "HP_counter" "counter_2"
+ "HPbar_counter" "BossHpIterations3"
+ "HPbar_min" "0"
+ "HPbar_max" "10"
+ "HPbar_default" "10"
+ "HPbar_mode" "1" // OnHitMin=1 OnHitMax=2
+ "CustomText" "Alduin"
+ }
+ "2"
+ {
+ "HP_counter" "dw_hp"
+ "HPbar_counter" "BossHpIterations2"
+ "HPbar_min" "0"
+ "HPbar_max" "10"
+ "HPbar_default" "10"
+ "HPbar_mode" "1" // OnHitMin=1 OnHitMax=2
+ "CustomText" "Dwarven Centurion"
+ }
+ "3"
+ {
+ "HP_counter" "counter_3"
+ "HPbar_counter" "BossHpIterations"
+ "HPbar_min" "0"
+ "HPbar_max" "10"
+ "HPbar_default" "10"
+ "HPbar_mode" "1" // OnHitMin=1 OnHitMax=2
+ "CustomText" "Alduin"
+ }
+ "4"
+ {
+ "BreakableName" "smalldwboss_physbox2"
+ "Type" "breakable"
+ "CustomText" "Small DC"
+ }
+}
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_timesplitters_p.txt b/BossHP/configs/MapBossHP/ze_timesplitters_p.txt
new file mode 100644
index 0000000..d65966a
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_timesplitters_p.txt
@@ -0,0 +1,7 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "BossHPCounter"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_timesplitters_p2.txt b/BossHP/configs/MapBossHP/ze_timesplitters_p2.txt
new file mode 100644
index 0000000..d65966a
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_timesplitters_p2.txt
@@ -0,0 +1,7 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "BossHPCounter"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_tloz_stone_tower_temple_v1_4.txt b/BossHP/configs/MapBossHP/ze_tloz_stone_tower_temple_v1_4.txt
new file mode 100644
index 0000000..4b09a8e
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_tloz_stone_tower_temple_v1_4.txt
@@ -0,0 +1,17 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "b_handhpcounter"
+ "HPinit_counter" "b_handhpbackup"
+ "CustomText" "Hand"
+ }
+ "1"
+ {
+ "HP_counter" "b_hpcounter"
+ }
+ "2"
+ {
+ "HP_counter" "garo_hpcounter"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_trials_v1_4.txt b/BossHP/configs/MapBossHP/ze_trials_v1_4.txt
new file mode 100644
index 0000000..bc5bdf4
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_trials_v1_4.txt
@@ -0,0 +1,39 @@
+"math_counter"
+{
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "Level_1_Boss_Breakable_3"
+ "CustomText" "BOSS (1/3)"
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "Level_1_Boss_Breakable_2"
+ "CustomText" "BOSS (2/3)"
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "Level_1_Boss_Breakable"
+ "CustomText" "BOSS (3/3)"
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "Level_3_Boss_Breakable_3"
+ "CustomText" "BOSS (1/3)"
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "Level_3_Boss_Breakable_2"
+ "CustomText" "BOSS (2/3)"
+ }
+ "1"
+ {
+ "Type" "breakable"
+ "BreakableName" "Level_3_Boss_Breakable"
+ "CustomText" "BOSS (3/3)"
+ }
+}
\ No newline at end of file
diff --git a/BossHP/configs/MapBossHP/ze_tyranny_v5_go3.txt b/BossHP/configs/MapBossHP/ze_tyranny_v5_go3.txt
new file mode 100644
index 0000000..8802bc6
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_tyranny_v5_go3.txt
@@ -0,0 +1,112 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "bosslvl1_counter1"
+ "HPbar_counter" "bosslvl1_counter3"
+ "HPinit_counter" "bosslvl1_counter2"
+ "CustomText" "Spider"
+ "HPbar_min" ""
+ "HPbar_max" "10"
+ "HPbar_default" "10"
+ "HPbar_mode" "1"
+ }
+ "1"
+ {
+ "HP_counter" "bosslvl2_counter1"
+ "HPbar_counter" "bosslvl2_counter3"
+ "HPinit_counter" "bosslvl2_counter2"
+ "CustomText" "Troll"
+ "HPbar_min" ""
+ "HPbar_max" "10"
+ "HPbar_default" "10"
+ "HPbar_mode" "1"
+ }
+ "2"
+ {
+ "HP_counter" "bosslvl2_end_counter1"
+ "HPbar_counter" "bosslvl2_end_counter3"
+ "HPinit_counter" "bosslvl2_end_counter2"
+ "CustomText" "Dragon"
+ "HPbar_min" ""
+ "HPbar_max" "10"
+ "HPbar_default" "10"
+ "HPbar_mode" "1"
+ }
+ "3"
+ {
+ "HP_counter" "bosslvl3_counter1"
+ "HPbar_counter" "bosslvl3_counter3"
+ "HPinit_counter" "bosslvl3_counter2"
+ "CustomText" "Dragon"
+ "HPbar_min" ""
+ "HPbar_max" "10"
+ "HPbar_default" "10"
+ "HPbar_mode" "1"
+ }
+ "4"
+ {
+ "HP_counter" "bosslvl3_end_counter1"
+ "HPbar_counter" "bosslvl3_end_counter3"
+ "HPinit_counter" "bosslvl3_end_counter2"
+ "CustomText" "Dragon"
+ "HPbar_min" ""
+ "HPbar_max" "10"
+ "HPbar_default" "10"
+ "HPbar_mode" "1"
+ }
+ "5"
+ {
+ "HP_counter" "bosslvl4_counter1"
+ "HPbar_counter" "bosslvl4_counter3"
+ "HPinit_counter" "bosslvl4_counter2"
+ "CustomText" "Titan"
+ "HPbar_min" ""
+ "HPbar_max" "10"
+ "HPbar_default" "10"
+ "HPbar_mode" "1"
+ }
+ "6"
+ {
+ "HP_counter" "bosslvl5_counter1"
+ "HPbar_counter" "bosslvl5_counter3"
+ "HPinit_counter" "bosslvl5_counter2"
+ "CustomText" "Barlog"
+ "HPbar_min" ""
+ "HPbar_max" "10"
+ "HPbar_default" "10"
+ "HPbar_mode" "1"
+ }
+ "7"
+ {
+ "HP_counter" "bosslvl5_end_counter1"
+ "HPbar_counter" "bosslvl5_end_counter3"
+ "HPinit_counter" "bosslvl5_end_counter2"
+ "CustomText" "Dragon"
+ "HPbar_min" ""
+ "HPbar_max" "10"
+ "HPbar_default" "10"
+ "HPbar_mode" "1"
+ }
+ "8"
+ {
+ "HP_counter" "bosslvl5_garg_counter1"
+ "HPbar_counter" "bosslvl5_garg_counter3"
+ "HPinit_counter" "bosslvl5_garg_counter2"
+ "CustomText" "Titan"
+ "HPbar_min" ""
+ "HPbar_max" "10"
+ "HPbar_default" "10"
+ "HPbar_mode" "1"
+ }
+ "9"
+ {
+ "HP_counter" "bosslvl5_laser_counter"
+ "CustomText" "Barlog"
+ }
+ "10"
+ {
+ "HP_counter" "bosslvl6_counter"
+ "CustomText" "Titan"
+ }
+}
diff --git a/BossHP/configs/MapBossHP/ze_zk_fapescape_p3.txt b/BossHP/configs/MapBossHP/ze_zk_fapescape_p3.txt
new file mode 100644
index 0000000..120a299
--- /dev/null
+++ b/BossHP/configs/MapBossHP/ze_zk_fapescape_p3.txt
@@ -0,0 +1,12 @@
+"math_counter"
+{
+ "0"
+ {
+ "HP_counter" "boss_hp"
+ "HP_Mode" "1"
+ "HPbar_counter" "boss_hp_iterations"
+ "HPinit_counter" "boss_hp_backup"
+ "CustomText" ""
+ "HPbar_mode" "1"
+ }
+}
\ No newline at end of file
diff --git a/BossHP/scripting/BossHP.sp b/BossHP/scripting/BossHP.sp
new file mode 100644
index 0000000..7c13609
--- /dev/null
+++ b/BossHP/scripting/BossHP.sp
@@ -0,0 +1,1679 @@
+#pragma semicolon 1
+#pragma newdecls required
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#undef REQUIRE_PLUGIN
+#tryinclude
+#define REQUIRE_PLUGIN
+
+//#define DEBUG
+
+#define LoopIngamePlayers(%1) for (int %1 = 1; %1 <= MaxClients; ++%1)\
+ if (IsClientInGame(%1))
+
+public Plugin myinfo = {
+ name = "[ZE] BOSS HP",
+ author = "CrazyKid @僵尸乐园 ZombiEden.CN + PŠΣ™ SHUFEN",
+ description = "",
+ version = "2.7 PŠΣ™",
+ url = "http://ZombiEden.CN + https://possession.jp"
+};
+
+#define MAX_BOSS_NAME_LENGTH 32
+#define MathCounterSize 32
+#define MathCounterBackupSize 10
+#define BreakableSize 32
+#define MAX_MATHCOUNTER_NAME_LENGTH 48
+#define MAX_BREAKABLE_NAME_LENGTH 48
+#define DEFAULT_BOSSNAME_CSS "BOSS HP"
+#define DEFAULT_BOSSNAME_CSGO "BOSS"
+
+enum struct Array_MathCounter {
+ char BossName[MAX_BOSS_NAME_LENGTH];
+ char sHP[MAX_MATHCOUNTER_NAME_LENGTH];
+ char sHPBar[MAX_MATHCOUNTER_NAME_LENGTH];
+ char sHPInit[MAX_MATHCOUNTER_NAME_LENGTH];
+ int HP;
+ int HP_Mode;
+ int HP_Min;
+ int HP_Max;
+ int HP_StartValue;
+ int HPBar_Min;
+ int HPBar_Max;
+ int HPBar_StartValue;
+ int HPBar_Mode;
+ int HPInit;
+ int HPInit_Min;
+ int HPInit_Max;
+ int HPInit_StartValue;
+ int Multiply;
+ int LastHP;
+ int LastHPShow;
+ int LastValue;
+ float LastChangeTime;
+ float LastAddTime;
+ bool IsSetDefaultMultiply;
+ bool IsSetDefaultInit;
+ int BossHP;
+ int MaxBossHP;
+ int HpGroupCount;
+}
+
+enum struct Array_MathCounter_Group {
+ char sName[MAX_MATHCOUNTER_NAME_LENGTH];
+ int HP;
+ int Min;
+ int Max;
+ bool Stats; //true=enable, false=disabled
+ bool StartDisabled;
+ bool Kill;
+ bool RunOut;
+ int StartValue;
+ float LastAddTime;
+}
+
+enum struct Array_ClientLastShootBreakable {
+ char sName[MAX_BREAKABLE_NAME_LENGTH];
+ int EntityIndex;
+}
+
+enum struct Array_Breakable {
+ char BossName[MAX_BOSS_NAME_LENGTH];
+ char HitboxName[MAX_BREAKABLE_NAME_LENGTH];
+ float LastChangeTime;
+ int BossHP;
+ int MaxBossHP;
+ int Index;
+}
+
+enum struct Array_Count {
+ int Math_Counter;
+ int Breakable;
+}
+
+enum struct Array_BossDisplay {
+ ArrayList BossName;
+ ArrayList HP;
+ ArrayList MaxHP;
+}
+
+bool csgo = false;
+char g_Mapname[128];
+char sConfig[PLATFORM_MAX_PATH];
+bool IsConfigLoad = false;
+
+ConVar hCVAR_ForceShowBossHP = null;
+ConVar hCVAR_UpperCaseInForceEnable = null;
+ConVar hCVAR_RoundEndShowBossDamageRank = null;
+ConVar hCVAR_ShowTopDamageDuringBOSS = null;
+ConVar hCVAR_BossBeatenShowBossDamageRank = null;
+ConVar hCVAR_CrosshairChannel = null;
+ConVar hCVAR_BossRewardMoney = null;
+ConVar hCVAR_BossHpKeepTime = null;
+ConVar hCVAR_BossDieKeepTime = null;
+ConVar hCVAR_DisplayWhenHPAdded = null;
+ConVar hCVAR_MaxLegalBreakableHP = null;
+ConVar hCVAR_MaxLegalMathCounterHP = null;
+
+bool g_bForceShowBossHP;
+bool g_bUpperCaseInForceEnable;
+bool g_bRoundEndShowBossDamageRank;
+bool g_bShowTopDamageDuringBOSS;
+bool g_bBossBeatenShowBossDamageRank;
+int g_CrosshairChannel;
+int g_RewardMoney;
+float g_BossHpKeepTime;
+float g_BossDieKeepTime;
+bool g_DisplayWhenHPAdded;
+int g_MaxLegalBreakableHP;
+int g_MaxLegalMathCounterHP;
+
+Array_MathCounter g_MathCounter[MathCounterSize];
+Array_MathCounter_Group g_MathCounter_HPgroup[MathCounterSize][MathCounterBackupSize];
+Array_ClientLastShootBreakable g_ClientLastShootBreakable[MAXPLAYERS+1];
+Array_Breakable g_Breakable[BreakableSize];
+Array_BossDisplay g_BossDisplay;
+Array_Count g_Count;
+
+float LastShootHitbox[MAXPLAYERS+1];
+float LastShowBossHP;
+float LastForceShowBossHP;
+float LastShowTopDamage;
+char HPcolor[7];
+
+float g_LastShowCenterText[MAXPLAYERS+1];
+
+//Dhook
+Handle hAcceptInput = INVALID_HANDLE;
+
+Handle BossHP_Cookie = null;
+int g_iStatus[MAXPLAYERS+1] = {0, ...};
+
+int iLastBossEnt = -1;
+
+bool g_bUIManager = false;
+
+public void OnPluginStart() {
+ /* ====== CSGO Check ====== */
+ char theFolder[40];
+ GetGameFolderName(theFolder, sizeof(theFolder));
+ if (StrEqual(theFolder, "csgo")) csgo = true;
+
+ /* ====== BossDisplay Array ====== */
+ g_BossDisplay.BossName = new ArrayList(MAX_BOSS_NAME_LENGTH);
+ g_BossDisplay.HP = new ArrayList();
+ g_BossDisplay.MaxHP = new ArrayList();
+
+ /* ====== Hook ====== */
+ HookEntityOutput("math_counter", "OutValue", MathCounterHook_OutValue);
+ HookEntityOutput("func_physbox_multiplayer", "OnDamaged", HitboxHook_Breakable);
+ HookEntityOutput("func_physbox", "OnHealthChanged", HitboxHook_Breakable);
+ HookEntityOutput("func_breakable", "OnHealthChanged", HitboxHook_Breakable);
+ HookEntityOutput("prop_dynamic", "OnHealthChanged", HitboxHook);
+
+ HookUserMessage(GetUserMessageId("TextMsg"), UserMessageHook_TextMsg, true);
+ HookUserMessage(GetUserMessageId("HintText"), UserMessageHook_HintText, true);
+
+ /* ====== CVAR ====== */
+ hCVAR_ForceShowBossHP = CreateConVar("BossHP_ForceEnable", "1", "Force display math_counter and func_breakable's valve without BossHP config (bhud function)", _, true, 0.0, true, 1.0);
+ g_bForceShowBossHP = hCVAR_ForceShowBossHP.BoolValue;
+ hCVAR_ForceShowBossHP.AddChangeHook(OnConVarChange);
+
+ hCVAR_UpperCaseInForceEnable = CreateConVar("BossHP_ForceEnableUpperCase", "1", "Covert boss name to upper case in force display (bhud function)", _, true, 0.0, true, 1.0);
+ g_bUpperCaseInForceEnable = hCVAR_UpperCaseInForceEnable.BoolValue;
+ hCVAR_UpperCaseInForceEnable.AddChangeHook(OnConVarChange);
+
+ hCVAR_RoundEndShowBossDamageRank = CreateConVar("BossHP_RoundEndShowTopDamage", "0", "Show OnRoundEnd", _, true, 0.0, true, 1.0);
+ g_bRoundEndShowBossDamageRank = hCVAR_RoundEndShowBossDamageRank.BoolValue;
+ hCVAR_RoundEndShowBossDamageRank.AddChangeHook(OnConVarChange);
+
+ hCVAR_ShowTopDamageDuringBOSS = CreateConVar("BossHP_ShowTopDamageDuringBOSS", "0", "Show during boss fight", _, true, 0.0, true, 1.0);
+ g_bShowTopDamageDuringBOSS = hCVAR_ShowTopDamageDuringBOSS.BoolValue;
+ hCVAR_ShowTopDamageDuringBOSS.AddChangeHook(OnConVarChange);
+
+ hCVAR_BossBeatenShowBossDamageRank = CreateConVar("BossHP_BossBeatenShowTopDamage", "1", "Show when boss has beaten", _, true, 0.0, true, 1.0);
+ g_bBossBeatenShowBossDamageRank = hCVAR_BossBeatenShowBossDamageRank.BoolValue;
+ hCVAR_BossBeatenShowBossDamageRank.AddChangeHook(OnConVarChange);
+
+ hCVAR_CrosshairChannel = CreateConVar("BossHP_CrosshairChannel", "4", "Crosshair marker display channel", _, true, 0.0, true, 6.0);
+ g_CrosshairChannel = hCVAR_CrosshairChannel.IntValue;
+ hCVAR_CrosshairChannel.AddChangeHook(OnConVarChange);
+
+ hCVAR_BossRewardMoney = CreateConVar("BossHP_BossRewardMoney", "10", "Reward money to players when shoot the boss (per hit)", _, true, 0.0, false, _);
+ g_RewardMoney = hCVAR_BossRewardMoney.IntValue;
+ hCVAR_BossRewardMoney.AddChangeHook(OnConVarChange);
+
+ hCVAR_BossHpKeepTime = CreateConVar("BossHP_KeepTime", "15.0", "Boss Alive HP keep time", _, true, 0.0, false, _);
+ g_BossHpKeepTime = hCVAR_BossHpKeepTime.FloatValue;
+ hCVAR_BossHpKeepTime.AddChangeHook(OnConVarChange);
+
+ hCVAR_BossDieKeepTime = CreateConVar("BossHP_DieKeepTime", "1.0", "Boss Die HP keep time (must be under Alive KeepTime)", _, true, 0.0, false, _);
+ g_BossDieKeepTime = hCVAR_BossDieKeepTime.FloatValue;
+ hCVAR_BossDieKeepTime.AddChangeHook(OnConVarChange);
+
+ hCVAR_DisplayWhenHPAdded = CreateConVar("BossHP_DisplayWhenHPAdded", "0", "Display Boss HP When Boss HP Added", _, true, 0.0, true, 1.0);
+ g_DisplayWhenHPAdded = hCVAR_DisplayWhenHPAdded.BoolValue;
+ hCVAR_DisplayWhenHPAdded.AddChangeHook(OnConVarChange);
+
+ hCVAR_MaxLegalBreakableHP = CreateConVar("BossHP_MaxLegalBreakableHP", "500000", "", _, true, 0.0, false, _);
+ g_MaxLegalBreakableHP = hCVAR_MaxLegalBreakableHP.IntValue;
+ hCVAR_MaxLegalBreakableHP.AddChangeHook(OnConVarChange);
+
+ hCVAR_MaxLegalMathCounterHP = CreateConVar("BossHP_MaxLegalMathCounterHP", "40000", "", _, true, 0.0, false, _);
+ g_MaxLegalMathCounterHP = hCVAR_MaxLegalMathCounterHP.IntValue;
+ hCVAR_MaxLegalMathCounterHP.AddChangeHook(OnConVarChange);
+
+ /* ====== Commands ====== */
+ RegAdminCmd("reloadbosshp", ReloadBossHP, ADMFLAG_RCON);
+ RegConsoleCmd("sm_bossdamage", Command_ShowTopDamage); //Allow client view boss damage rank
+
+ RegAdminCmd("sm_shp", Command_SubtractHP, ADMFLAG_RCON, "Subtract Current Boss HP");
+ RegAdminCmd("sm_subtracthp", Command_SubtractHP, ADMFLAG_RCON, "Subtract Current Boss HP");
+
+ /* ====== DEBUG Commands ====== */
+ RegAdminCmd("debug_bosshp_saveconfig", DEBUG_SaveConfig, ADMFLAG_RCON);
+ RegAdminCmd("debug_bosshp_getarrayinfo", DEBUG_GetArrayInfo, ADMFLAG_RCON);
+ RegAdminCmd("debug_bosshp_printvar", DEBUG_PrintVar, ADMFLAG_RCON);
+
+ /* ====== Events ====== */
+ HookEvent("round_start", OnRoundStart);
+ HookEvent("round_end", OnRoundEnd);
+
+ /* ====== Translate ====== */
+ LoadTranslations("BossHP.phrases");
+
+ /* ====== DHook ====== */
+ if (csgo) {
+ char tmpOffset[148];
+ switch (GetEngineVersion()) {
+ case Engine_CSGO:
+ tmpOffset = "sdktools.games\\engine.csgo";
+ case Engine_CSS:
+ tmpOffset = "sdktools.games\\engine.css";
+ }
+ Handle temp = LoadGameConfigFile(tmpOffset);
+ if (temp == INVALID_HANDLE) {
+ SetFailState("Why you no has gamedata?");
+ } else {
+ int offset = GameConfGetOffset(temp, "AcceptInput");
+ hAcceptInput = DHookCreate(offset, HookType_Entity, ReturnType_Bool, ThisPointer_CBaseEntity, AcceptInput);
+ DHookAddParam(hAcceptInput, HookParamType_CharPtr);
+ DHookAddParam(hAcceptInput, HookParamType_CBaseEntity);
+ DHookAddParam(hAcceptInput, HookParamType_CBaseEntity);
+ DHookAddParam(hAcceptInput, HookParamType_Object, 20, DHookPass_ByVal|DHookPass_ODTOR|DHookPass_OCTOR|DHookPass_OASSIGNOP); //varaint_t is a union of 12 (float[3]) plus two int type params 12 + 8 = 20
+ DHookAddParam(hAcceptInput, HookParamType_Int);
+ }
+ CloseHandle(temp);
+ }
+
+ /* ====== Clients ====== */
+ RegConsoleCmd("sm_bhp", Command_BossHP, "Toggle BossHP");
+ RegConsoleCmd("sm_bhud", Command_BossHP, "Toggle BossHP");
+ RegConsoleCmd("sm_boss", Command_BossHP, "Toggle BossHP");
+ RegConsoleCmd("sm_bosshp", Command_BossHP, "Toggle BossHP");
+ RegConsoleCmd("sm_bosshud", Command_BossHP, "Toggle BossHP");
+
+ BossHP_Cookie = RegClientCookie("bosshp_status", "Status of BossHP", CookieAccess_Private);
+ SetCookieMenuItem(PrefMenu, 0, "Boss HP");
+
+ for(int i = 1; i <= MaxClients; i++) {
+ if (IsClientInGame(i)) {
+ if (!AreClientCookiesCached(i))
+ continue;
+ OnClientCookiesCached(i);
+ }
+ }
+
+ /* ====== Init ====== */
+ //GetCurrentMap(g_Mapname, sizeof(g_Mapname));
+ //LoadConfig();
+}
+
+public void OnAllPluginsLoaded() {
+ g_bUIManager = LibraryExists("UIManager");
+}
+
+public void OnLibraryAdded(const char[] name) {
+ if (StrEqual(name, "UIManager"))
+ g_bUIManager = true;
+}
+
+public void OnLibraryRemoved(const char[] name) {
+ if (StrEqual(name, "UIManager"))
+ g_bUIManager = false;
+}
+
+public void OnConVarChange(ConVar hCvar, const char[] oldValue, const char[] newValue) {
+ if (hCvar == hCVAR_ForceShowBossHP)
+ g_bForceShowBossHP = view_as(StringToInt(newValue));
+ else if (hCvar == hCVAR_UpperCaseInForceEnable)
+ g_bUpperCaseInForceEnable = view_as(StringToInt(newValue));
+ else if (hCvar == hCVAR_RoundEndShowBossDamageRank)
+ g_bRoundEndShowBossDamageRank = view_as(StringToInt(newValue));
+ else if (hCvar == hCVAR_ShowTopDamageDuringBOSS)
+ g_bShowTopDamageDuringBOSS = view_as(StringToInt(newValue));
+ else if (hCvar == hCVAR_BossBeatenShowBossDamageRank)
+ g_bBossBeatenShowBossDamageRank = view_as(StringToInt(newValue));
+ else if (hCvar == hCVAR_CrosshairChannel)
+ g_CrosshairChannel = StringToInt(newValue);
+ else if (hCvar == hCVAR_BossRewardMoney)
+ g_RewardMoney = StringToInt(newValue);
+ else if (hCvar == hCVAR_DisplayWhenHPAdded)
+ g_DisplayWhenHPAdded = view_as(StringToInt(newValue));
+ else if (hCvar == hCVAR_MaxLegalBreakableHP)
+ g_MaxLegalBreakableHP = StringToInt(newValue);
+ else if (hCvar == hCVAR_MaxLegalMathCounterHP)
+ g_MaxLegalMathCounterHP = StringToInt(newValue);
+ else if (hCvar == hCVAR_BossHpKeepTime) {
+ g_BossHpKeepTime = StringToFloat(newValue);
+ if (g_BossHpKeepTime == 0.0)
+ g_BossHpKeepTime = 0.01;
+ if (g_BossHpKeepTime < g_BossDieKeepTime)
+ g_BossDieKeepTime = g_BossHpKeepTime - 0.01;
+ }
+ else if (hCvar == hCVAR_BossDieKeepTime) {
+ g_BossDieKeepTime = StringToFloat(newValue);
+ if (g_BossHpKeepTime < g_BossDieKeepTime)
+ g_BossDieKeepTime = g_BossHpKeepTime - 0.01;
+ }
+}
+
+public void OnClientConnected(int client) {
+ g_iStatus[client] = 0;
+}
+
+public void OnClientCookiesCached(int client) {
+ char sValue[8];
+ GetClientCookie(client, BossHP_Cookie, sValue, sizeof(sValue));
+ if(sValue[0] == '\0') {
+ SetClientCookie(client, BossHP_Cookie, "0");
+ strcopy(sValue, sizeof(sValue), "0");
+ }
+ g_iStatus[client] = StringToInt(sValue);
+}
+
+public void PrefMenu(int client, CookieMenuAction actions, any info, char[] buffer, int maxlen) {
+ if (actions == CookieMenuAction_DisplayOption) {
+ switch(g_iStatus[client]) {
+ case 0: FormatEx(buffer, maxlen, "%T: %T", "BossHP", client, "FullEnabled", client);
+ case 1: FormatEx(buffer, maxlen, "%T: %T", "BossHP", client, "OnlyHP", client);
+ case 2: FormatEx(buffer, maxlen, "%T: %T", "BossHP", client, "OnlyHitmarker", client);
+ case 3: FormatEx(buffer, maxlen, "%T: %T", "BossHP", client, "Disabled", client);
+ }
+ }
+
+ if (actions == CookieMenuAction_SelectOption) {
+ ToggleBossHP(client);
+ ShowCookieMenu(client);
+ }
+}
+
+public Action Command_BossHP(int client, int argc) {
+ if(client < 1 || client > MaxClients)
+ return Plugin_Handled;
+
+ ToggleBossHP(client);
+ return Plugin_Handled;
+}
+
+void ToggleBossHP(int client) {
+ switch(g_iStatus[client]) {
+ case 0: {
+ g_iStatus[client] = 1;
+ CPrintToChat(client, "%t", "OnlyHPMsg");
+ }
+ case 1: {
+ g_iStatus[client] = 2;
+ CPrintToChat(client, "%t", "OnlyHitmarkerMsg");
+ }
+ case 2: {
+ g_iStatus[client] = 3;
+ CPrintToChat(client, "%t", "DisabledMsg");
+ }
+ case 3: {
+ g_iStatus[client] = 0;
+ CPrintToChat(client, "%t", "FullEnabledMsg");
+ }
+ }
+
+ char sCookieValue[2];
+ IntToString(g_iStatus[client], sCookieValue, sizeof(sCookieValue));
+ SetClientCookie(client, BossHP_Cookie, sCookieValue);
+}
+
+public Action Command_SubtractHP(int client, int argc) {
+ if (!IsValidEntity(iLastBossEnt)) {
+ CReplyToCommand(client, "\x04[SM]\x01 Last boss entity is invalid (ID: %i)", iLastBossEnt);
+ return Plugin_Handled;
+ }
+
+ if (argc < 1) {
+ CReplyToCommand(client, "\x04[SM]\x01 Usage: sm_subtracthp ");
+ return Plugin_Handled;
+ }
+
+ char szName[64], szType[64], arg[8];
+ int health;
+
+ GetEntityClassname(iLastBossEnt, szType, sizeof(szType));
+ GetEntPropString(iLastBossEnt, Prop_Data, "m_iName", szName, sizeof(szName));
+ GetCmdArg(1, arg, sizeof(arg));
+ SetVariantInt(StringToInt(arg));
+
+ if (StrEqual(szType, "math_counter", false)) {
+ static int offset = -1;
+ if (offset == -1)
+ offset = FindDataMapInfo(iLastBossEnt, "m_OutValue");
+
+ health = RoundFloat(GetEntDataFloat(iLastBossEnt, offset));
+ AcceptEntityInput(iLastBossEnt, "Subtract", client, client);
+ CReplyToCommand(client, "\x04[SM]\x01 %i health subtracted from \"%s\" (%i HP to %i HP)", StringToInt(arg), szName, health, health - StringToInt(arg));
+ } else {
+ health = GetEntProp(iLastBossEnt, Prop_Data, "m_iHealth");
+ AcceptEntityInput(iLastBossEnt, "RemoveHealth", client, client);
+ CReplyToCommand(client, "\x04[SM]\x01 %i health subtracted from \"%s\" (%i HP to %i HP)", StringToInt(arg), szName, health, health - StringToInt(arg));
+ }
+
+ return Plugin_Handled;
+}
+
+public void OnRoundStart(Event event, const char[] name, bool dontBroadcast) {
+ if (IsConfigLoad) {
+ for (int i = 0; i < g_Count.Math_Counter; i++) {
+ g_MathCounter[i].BossHP = 0;
+ g_MathCounter[i].MaxBossHP = 0;
+ g_MathCounter[i].Multiply = 1;
+ g_MathCounter[i].HPInit = 0;
+ g_MathCounter[i].IsSetDefaultMultiply = false;
+ g_MathCounter[i].IsSetDefaultInit = false;
+ g_MathCounter[i].LastValue = 0;
+ g_MathCounter[i].LastHP = 0;
+ g_MathCounter[i].LastHPShow = 0;
+
+ for (int x=0; x < g_MathCounter[i].HpGroupCount; x++) {
+ g_MathCounter_HPgroup[i][x].Kill = false;
+ g_MathCounter_HPgroup[i][x].RunOut = false;
+
+ }
+ }
+
+ for (int i = 0; i < g_Count.Breakable; i++) {
+ g_Breakable[i].MaxBossHP = 0;
+ g_Breakable[i].Index = -1;
+ }
+
+ LoopIngamePlayers(i) {
+ if (csgo)
+ CS_SetClientAssists(i, 0);
+ else
+ SetEntProp(i, Prop_Data, "m_iDeaths", 0);
+
+ g_ClientLastShootBreakable[i].EntityIndex = -1;
+ g_ClientLastShootBreakable[i].sName[0] = '\0';
+ }
+ CreateTimer(5.0, Timer_OnRoundStartPost);
+ }
+}
+
+public void OnRoundEnd(Event event, const char[] name, bool dontBroadcast) {
+ if (csgo && IsConfigLoad && g_bRoundEndShowBossDamageRank)
+ ShowBossTopDamage(0);
+}
+
+public Action Timer_OnRoundStartPost(Handle timer) {
+ if (csgo)
+ CPrintToChatAll("%t", "RoundStart_Message_CSGO");
+ else
+ CPrintToChatAll("%t", "RoundStart_Message_CSS");
+ return Plugin_Stop;
+}
+
+public void OnMapStart() {
+ GetCurrentMap(g_Mapname, sizeof(g_Mapname));
+ LoadConfig();
+}
+
+public void OnMapEnd() {
+ iLastBossEnt = -1;
+}
+
+public Action ReloadBossHP(int client, int args) {
+ LoadConfig();
+ ReplyToCommand(client, "[Z-BossHP] Config Reloaded");
+ return Plugin_Handled;
+}
+
+public Action DEBUG_SaveConfig(int client, int args) {
+ SaveConfig();
+ ReplyToCommand(client, "[Z-BossHP] Config Saved");
+ return Plugin_Handled;
+}
+
+public Action Command_ShowTopDamage(int client, int args) {
+ if (IsConfigLoad)
+ ShowBossTopDamage(client);
+ return Plugin_Handled;
+}
+
+stock void LoadConfig() {
+ g_Count.Math_Counter = 0;
+ g_Count.Breakable = 0;
+ IsConfigLoad = false;
+
+ char tempStr[16];
+ int tempNum;
+
+ BuildPath(Path_SM, sConfig, PLATFORM_MAX_PATH, "configs/MapBossHP/%s.txt", g_Mapname);
+
+ KeyValues kv = new KeyValues("math_counter");
+ kv.ImportFromFile(sConfig);
+
+ if (kv.GotoFirstSubKey()) {
+ do {
+ kv.GetSectionName(tempStr, sizeof(tempStr));
+ if (StrEqual(tempStr, "config", false)) {
+ tempNum = kv.GetNum("ForceEnable", 1);
+ hCVAR_ForceShowBossHP.SetBool(view_as(tempNum));
+
+ tempNum = kv.GetNum("ForceEnableUpperCase", 1);
+ hCVAR_UpperCaseInForceEnable.SetBool(view_as(tempNum));
+
+ tempNum = kv.GetNum("RoundEndShowTopDamage", 0);
+ hCVAR_RoundEndShowBossDamageRank.SetBool(view_as(tempNum));
+
+ tempNum = kv.GetNum("ShowTopDamageDuringBOSS", 0);
+ hCVAR_ShowTopDamageDuringBOSS.SetBool(view_as(tempNum));
+
+ tempNum = kv.GetNum("BossBeatenShowTopDamage", 1);
+ hCVAR_BossBeatenShowBossDamageRank.SetBool(view_as(tempNum));
+
+ tempNum = kv.GetNum("CrosshairChannel", 4);
+ if (tempNum >= 1 && tempNum <= 6)
+ hCVAR_CrosshairChannel.SetInt(tempNum);
+
+ tempNum = kv.GetNum("BossRewardMoney", 10);
+ if (tempNum > 0)
+ hCVAR_BossRewardMoney.SetInt(tempNum);
+
+ tempNum = kv.GetNum("BossHpKeepTime", 15);
+ hCVAR_BossHpKeepTime.SetInt(tempNum);
+
+ tempNum = kv.GetNum("BossDieKeepTime", 1);
+ hCVAR_BossDieKeepTime.SetInt(tempNum);
+
+ tempNum = kv.GetNum("DisplayWhenHPAdded", 0);
+ hCVAR_DisplayWhenHPAdded.SetBool(view_as(tempNum));
+
+ tempNum = kv.GetNum("MaxLegalBreakableHP", 500000);
+ hCVAR_MaxLegalBreakableHP.SetInt(tempNum);
+
+ tempNum = kv.GetNum("MaxLegalMathCounterHP", 40000);
+ hCVAR_MaxLegalMathCounterHP.SetInt(tempNum);
+
+ if (g_BossHpKeepTime == 0.0)
+ g_BossHpKeepTime = 0.01;
+ if (g_BossHpKeepTime < g_BossDieKeepTime)
+ g_BossDieKeepTime = g_BossHpKeepTime - 0.01;
+ } else {
+ kv.GetString("Type", tempStr, sizeof(tempStr));
+ if (StrEqual(tempStr, "breakable", false)) {
+ kv.GetString("BreakableName", g_Breakable[g_Count.Breakable].HitboxName, sizeof(Array_Breakable::HitboxName));
+ kv.GetString("CustomText", g_Breakable[g_Count.Breakable].BossName, sizeof(Array_Breakable::BossName));
+ if (g_Breakable[g_Count.Breakable].BossName[0] == '\0')
+ Format(g_Breakable[g_Count.Breakable].BossName, sizeof(Array_Breakable::BossName), "%s", csgo ? DEFAULT_BOSSNAME_CSGO : DEFAULT_BOSSNAME_CSS);
+
+ #if defined DEBUG
+ CPrintToChatAll("{pink}[BossHP-DEBUG] kv read: BreakableName:%s", g_Breakable[g_Count.Breakable].HitboxName); //debug
+ #endif
+
+ ++g_Count.Breakable;
+ } else {
+ kv.GetString("HP_Counter", g_MathCounter[g_Count.Math_Counter].sHP, sizeof(Array_MathCounter::sHP));
+ kv.GetString("HPinit_Counter", g_MathCounter[g_Count.Math_Counter].sHPInit, sizeof(Array_MathCounter::sHPInit));
+ kv.GetString("HPbar_Counter", g_MathCounter[g_Count.Math_Counter].sHPBar, sizeof(Array_MathCounter::sHPBar));
+ kv.GetString("CustomText", g_MathCounter[g_Count.Math_Counter].BossName, sizeof(Array_MathCounter::BossName));
+ if (g_MathCounter[g_Count.Math_Counter].BossName[0] == '\0')
+ Format(g_MathCounter[g_Count.Math_Counter].BossName, sizeof(Array_MathCounter::BossName), "%s", csgo ? DEFAULT_BOSSNAME_CSGO : DEFAULT_BOSSNAME_CSS);
+
+ #if defined DEBUG
+ CPrintToChatAll("{pink}[BossHP-DEBUG] kv read: HP_Counter:%s", g_MathCounter[g_Count.Math_Counter].sHP); //debug
+ #endif
+
+ g_MathCounter[g_Count.Math_Counter].HpGroupCount = 0;
+ if (kv.JumpToKey("HP_Group", false)) {
+ for (int i = 0; i < sizeof(g_MathCounter_HPgroup[]); i++) {
+ IntToString(i, tempStr, sizeof(tempStr));
+ kv.GetString(tempStr, g_MathCounter_HPgroup[g_Count.Math_Counter][i].sName, sizeof(Array_MathCounter_Group::sName));
+
+ if (g_MathCounter_HPgroup[g_Count.Math_Counter][i].sName[0] == '\0')
+ break;
+
+ g_MathCounter[g_Count.Math_Counter].HpGroupCount++;
+
+ #if defined DEBUG
+ CPrintToChatAll("{pink}[BossHP-DEBUG] kv read: BackupCounter(%d):%s", i, g_MathCounter_HPgroup[g_Count.Math_Counter][i].sName); //debug
+ #endif
+ }
+ kv.GoBack();
+ }
+ ++g_Count.Math_Counter;
+ }
+ }
+ } while (kv.GotoNextKey());
+ }
+ delete kv;
+
+ if (g_Count.Math_Counter == 0 && g_Count.Breakable == 0)
+ IsConfigLoad = false;
+ else
+ IsConfigLoad = true;
+}
+
+stock void SaveConfig() {
+ if (!IsConfigLoad)
+ return;
+
+ KeyValues kv = new KeyValues("math_counter");
+ int index = 0;
+ char tempStr[16];
+
+ kv.JumpToKey("config", true);
+ //kv.SetSectionName("config");
+ if (!g_bForceShowBossHP)
+ kv.SetNum("ForceEnable", 0);
+ if (!g_bUpperCaseInForceEnable)
+ kv.SetNum("ForceEnableUpperCase", 0);
+ if (g_bRoundEndShowBossDamageRank)
+ kv.SetNum("RoundEndShowTopDamage", 1);
+ if (g_bShowTopDamageDuringBOSS)
+ kv.SetNum("ShowTopDamageDuringBOSS", 1);
+ if (!g_bBossBeatenShowBossDamageRank)
+ kv.SetNum("BossBeatenShowTopDamage", 0);
+ if (g_CrosshairChannel != 4 && g_CrosshairChannel >= 1 && g_CrosshairChannel <= 6)
+ kv.SetNum("CrosshairChannel", g_CrosshairChannel);
+ if (g_RewardMoney != 10 && g_RewardMoney > 0)
+ kv.SetNum("BossRewardMoney", g_RewardMoney);
+ if (g_BossHpKeepTime != 15.0)
+ kv.SetFloat("BossHpKeepTime", g_BossHpKeepTime);
+ if (g_BossDieKeepTime != 1.0)
+ kv.SetFloat("BossDieKeepTime", g_BossDieKeepTime);
+ if (g_DisplayWhenHPAdded)
+ kv.SetNum("DisplayWhenHPAdded", 1);
+ if (g_MaxLegalBreakableHP != 500000)
+ kv.SetNum("MaxLegalBreakableHP", g_MaxLegalBreakableHP);
+ if (g_MaxLegalMathCounterHP != 40000)
+ kv.SetNum("MaxLegalMathCounterHP", g_MaxLegalMathCounterHP);
+ kv.Rewind();
+
+ for (int i = 0; i < g_Count.Breakable; i++) {
+ IntToString(index, tempStr, sizeof(tempStr));
+ kv.JumpToKey(tempStr, true);
+ //kv.SetSectionName(tempStr);
+ kv.SetString("BreakableName", g_Breakable[i].HitboxName);
+ if ( ( csgo && !StrEqual(g_Breakable[i].BossName, DEFAULT_BOSSNAME_CSGO) ) || (!csgo && !StrEqual(g_Breakable[i].BossName, DEFAULT_BOSSNAME_CSS) ) )
+ kv.SetString("CustomText", g_Breakable[i].BossName);
+ kv.Rewind();
+ index++;
+ }
+
+ for (int i = 0; i < g_Count.Math_Counter; i++) {
+ IntToString(index, tempStr, sizeof(tempStr));
+ kv.JumpToKey(tempStr, true);
+ //kv.SetSectionName(tempStr);
+ kv.SetString("HP_Counter", g_MathCounter[i].sHP);
+ kv.SetString("HPinit_Counter", g_MathCounter[i].sHPInit);
+ kv.SetString("HPbar_Counter", g_MathCounter[i].sHPBar);
+ if ( ( csgo && !StrEqual(g_MathCounter[i].BossName, DEFAULT_BOSSNAME_CSGO) ) || (!csgo && !StrEqual(g_MathCounter[i].BossName, DEFAULT_BOSSNAME_CSS) ) )
+ kv.SetString("CustomText", g_MathCounter[i].BossName);
+
+ if (g_MathCounter[i].HpGroupCount > 0) {
+ kv.JumpToKey("HP_Group", true);
+ for (int x = 0; x < g_MathCounter[i].HpGroupCount; x++) {
+ IntToString(x, tempStr, sizeof(tempStr));
+ kv.SetString(tempStr, g_MathCounter_HPgroup[i][x].sName);
+ }
+ kv.GoBack();
+ }
+
+ kv.Rewind();
+ index++;
+ }
+ kv.ExportToFile(sConfig);
+ delete kv;
+}
+
+public void HitboxHook(const char[] output, int entity, int activator, float delay) {
+ if (activator > 0 && activator < MAXPLAYERS)
+ LastShootHitbox[activator] = GetEngineTime();
+}
+
+public void HitboxHook_Breakable(const char[] output, int entity, int activator, float delay) {
+ if (activator < 1 || activator > MAXPLAYERS)
+ return;
+
+ LastShootHitbox[activator] = GetEngineTime();
+
+ int CurrentValue;
+ CurrentValue = GetEntProp(entity, Prop_Data, "m_iHealth");
+
+ if (CurrentValue > g_MaxLegalBreakableHP)
+ return;
+
+ if (IsConfigLoad) {
+ char targetname[MAX_BREAKABLE_NAME_LENGTH];
+ GetEntPropString(entity, Prop_Data, "m_iName", targetname, sizeof(targetname));
+
+ #if defined DEBUG
+ // CPrintToChatAll("{green}[BossHP-DEBUG] Breakable:%s Value:%d Activator:%d", g_Breakable[i].EntityName, CurrentValue, activator); //debug
+ #endif
+
+ for (int i = 0; i < g_Count.Breakable; i++) {
+ if (g_Breakable[i].Index == entity || StrEqual(targetname, g_Breakable[i].HitboxName, false)) {
+ if (csgo)
+ CS_SetClientAssists(activator, CS_GetClientAssists(activator) + 1);
+ else
+ SetEntProp(activator, Prop_Data, "m_iDeaths", GetEntProp(activator, Prop_Data, "m_iDeaths") - 1);
+
+ //Give cash to players, 1hit = $10
+ SetEntProp(activator, Prop_Send, "m_iAccount", GetEntProp(activator, Prop_Send, "m_iAccount") + g_RewardMoney);
+
+ //Show HitMarker when hit the boss
+ //if (g_iStatus[activator] == 0 || g_iStatus[activator] == 2) {
+ // if (g_bUIManager)
+ // SendHudText(activator, g_CrosshairChannel, 5, -1.0, -1.0, {255, 0, 0, 50}, {255, 0, 0, 50}, 0, 0.1, 0.1, 0.1, 0.1, "◞ ◟\n◝ ◜");
+ // else {
+ // SetHudTextParamsEx(-1.0, -1.0, 0.1, {255, 0, 0, 50}, {255, 0, 0, 50}, 0, 0.1, 0.1, 0.1);
+ // ShowHudText(activator, g_CrosshairChannel, "◞ ◟\n◝ ◜");
+ // }
+ //}
+
+ //Show HitMarker to player who is spectating attacker
+ /*
+ for (new x = 1; x <= MaxClients; x++) {
+ if (IsClientInGame(x) && !IsPlayerAlive(x)) {
+ if (GetEntProp(x, Prop_Send, "m_iObserverMode") == 4) {
+ if (activator == GetEntPropEnt(x, Prop_Send, "m_hObserverTarget")) {
+ if (g_iStatus[x] == 0 || g_iStatus[x] == 2) {
+ SetHudTextParamsEx(-1.0, -1.0, 0.1, {255, 0, 0, 50}, {255, 0, 0, 50}, 0, 0.1, 0.1, 0.1);
+ ShowHudText(x, g_CrosshairChannel, "◞ ◟\n◝ ◜");
+ }
+ }
+ }
+ }
+ }
+ */
+
+ if (CurrentValue <= 0) {
+ iLastBossEnt = -1;
+
+ CurrentValue = 0; //to prevent from display negative number
+ g_Breakable[i].LastChangeTime = GetEngineTime() - ( g_BossHpKeepTime - g_BossDieKeepTime );
+ } else {
+ iLastBossEnt = entity;
+
+ g_Breakable[i].LastChangeTime = GetEngineTime();
+ }
+
+ if (g_DisplayWhenHPAdded || CurrentValue < g_Breakable[i].BossHP) { //Only display when BossHP is subtracted.
+ g_Breakable[i].BossHP = CurrentValue;
+ PrintHP(activator, CurrentValue);
+ } else {
+ g_Breakable[i].BossHP = CurrentValue;
+ }
+
+ g_Breakable[i].Index = entity; //Need to store Breakable's entity index, because if it's broke, we can't get his targetname.
+
+ return;
+ }
+ }
+ }
+
+ //bhud function
+ if (g_bForceShowBossHP &&
+ LastShowBossHP + 3.0 < GetEngineTime() && // If BossHP was show in the past 3sec, block this function
+ LastShootHitbox[activator] > GetEngineTime() - 0.2) { //if players didn't shoot to breakable, block this function
+ if (g_ClientLastShootBreakable[activator].EntityIndex != entity) {
+ GetEntPropString(entity, Prop_Data, "m_iName", g_ClientLastShootBreakable[activator].sName, sizeof(Array_ClientLastShootBreakable::sName));
+ if (g_ClientLastShootBreakable[activator].sName[0] == '\0')
+ Format(g_ClientLastShootBreakable[activator].sName, sizeof(Array_ClientLastShootBreakable::sName), "HP");
+ g_ClientLastShootBreakable[activator].EntityIndex = entity;
+ }
+ if (CurrentValue <= 0) { //to prevent from display negative number
+ iLastBossEnt = -1;
+
+ PrintHP_Force(activator, entity, g_ClientLastShootBreakable[activator].sName, 0);
+ } else {
+ iLastBossEnt = entity;
+
+ PrintHP_Force(activator, entity, g_ClientLastShootBreakable[activator].sName, CurrentValue);
+ }
+ }
+}
+
+public void MathCounterHook_OutValue(const char[] output, int entity, int activator, float delay) {
+ #if defined DEBUG
+ if (IsValidEntity(entity) || IsValidEdict(entity)) {
+ char targetname[32];
+ int offset, CurrentValue;
+ GetEntPropString(entity, Prop_Data, "m_iName", targetname, sizeof(targetname));
+ offset = FindDataMapInfo(entity, "m_OutValue");
+ if (offset == -1)
+ return;
+ CurrentValue = RoundFloat(GetEntDataFloat(entity, offset));
+ CPrintToChatAll("%s I:%d N:%s V:%d A:%d O:%d", output, entity, targetname, CurrentValue, activator, offset);
+ }
+ #endif
+
+ //if (activator < 0) return;
+ if (IsConfigLoad && (IsValidEntity(entity) || IsValidEdict(entity))) {
+ #if !defined DEBUG
+ char targetname[32];
+ int offset, CurrentValue;
+ GetEntPropString(entity, Prop_Data, "m_iName", targetname, sizeof(targetname));
+ offset = FindDataMapInfo(entity, "m_OutValue");
+ if (offset == -1)
+ return;
+ CurrentValue = RoundFloat(GetEntDataFloat(entity, offset));
+ #endif
+
+ #if defined DEBUG
+ CPrintToChatAll("{green}[BossHP-DEBUG] Counter:%s Value:%d Activator:%d", targetname, CurrentValue, activator); //debug
+ #endif
+
+ for (int i = 0; i < g_Count.Math_Counter; i++) {
+ if (StrEqual(targetname, g_MathCounter[i].sHP, false)) {
+ if (g_MathCounter[i].sHPBar[0] != '\0') { //If this boss has HPBar counter
+ //Need to give a default multiply value
+ if (!g_MathCounter[i].IsSetDefaultMultiply) {
+ g_MathCounter[i].IsSetDefaultMultiply = true;
+ if (g_MathCounter[i].HPBar_Mode == 1) { //Boss_end_relay is triggered by OnHitMin
+ g_MathCounter[i].Multiply = g_MathCounter[i].HPBar_StartValue - g_MathCounter[i].HPBar_Min;
+ }
+ else if (g_MathCounter[i].HPBar_Mode == 2) { //Boss_end_relay is triggered by OnHitMax
+ g_MathCounter[i].Multiply = g_MathCounter[i].HPBar_Max - g_MathCounter[i].HPBar_StartValue;
+ }
+ #if defined DEBUG
+ CPrintToChatAll("{red}[BossHP-DEBUG] Set default multiply: %d", g_MathCounter[i].Multiply); //debug
+ #endif
+ }
+ }
+ if (g_MathCounter[i].Multiply <= 0) {
+ g_MathCounter[i].BossHP = 0; //to prevent from display negative number
+ } else {
+ if (g_MathCounter[i].HP_Mode == 1)
+ g_MathCounter[i].BossHP = (g_MathCounter[i].Multiply - 1) * g_MathCounter[i].HPInit + (CurrentValue - g_MathCounter[i].HP_Min);
+ else
+ g_MathCounter[i].BossHP = (g_MathCounter[i].Multiply - 1) * g_MathCounter[i].HPInit + (g_MathCounter[i].HP_Max - CurrentValue);
+ }
+
+ if (g_DisplayWhenHPAdded || g_MathCounter[i].BossHP < g_MathCounter[i].LastHP) { //Only display when BossHP is subtracted.
+ if ((g_MathCounter[i].HP_Mode == 1 && g_MathCounter[i].BossHP <= g_MathCounter[i].HP_Min) || g_MathCounter[i].BossHP <= 1) { //in some maps like ze_Predator_ultimate, boss's math_counter MinValve is not 0 but 1.
+ g_MathCounter[i].LastChangeTime = GetEngineTime() - ( g_BossHpKeepTime - g_BossDieKeepTime ) ; // when BossHP hit 0, keep more 1s display time.(default value)
+
+ iLastBossEnt = -1;
+
+ g_MathCounter[i].BossHP = 0;
+ g_MathCounter[i].IsSetDefaultInit = false; // When a Boss die, reset it to false
+ } else {
+ iLastBossEnt = entity;
+
+ g_MathCounter[i].LastChangeTime = GetEngineTime();
+ if (g_MathCounter[i].BossHP < g_MaxLegalMathCounterHP && activator > 0 && activator <= MAXPLAYERS) {
+ if (csgo)
+ CS_SetClientAssists(activator, CS_GetClientAssists(activator) + 1);
+ else
+ SetEntProp(activator, Prop_Data, "m_iDeaths", GetEntProp(activator, Prop_Data, "m_iDeaths") - 1);
+
+ //Give cash to players, 1hit = $10
+ SetEntProp(activator, Prop_Send, "m_iAccount", GetEntProp(activator, Prop_Send, "m_iAccount") + g_RewardMoney);
+
+ ////Show HitMarker when hit the boss
+ //if (g_iStatus[activator] == 0 || g_iStatus[activator] == 2) {
+ // if (g_bUIManager)
+ // SendHudText(activator, g_CrosshairChannel, 5, -1.0, -1.0, {255, 0, 0, 50}, {255, 0, 0, 50}, 0, 0.1, 0.1, 0.1, 0.1, "◞ ◟\n◝ ◜");
+ // else {
+ // SetHudTextParamsEx(-1.0, -1.0, 0.1, {255, 0, 0, 50}, {255, 0, 0, 50}, 0, 0.1, 0.1, 0.1);
+ // ShowHudText(activator, g_CrosshairChannel, "◞ ◟\n◝ ◜");
+ // }
+ //}
+
+ //Show HitMarker to player who is spectating attacker
+ /*
+ for (new z = 1; z <= MaxClients; z++) {
+ if (IsClientInGame(z) && !IsPlayerAlive(z)) {
+ if (GetEntProp(z, Prop_Send, "m_iObserverMode") == 4) {
+ if (activator == GetEntPropEnt(z, Prop_Send, "m_hObserverTarget")) {
+ if (g_iStatus[z] == 0 || g_iStatus[z] == 2) {
+ SetHudTextParamsEx(-1.0, -1.0, 0.1, {255, 0, 0, 50}, {255, 0, 0, 50}, 0, 0.1, 0.1, 0.1);
+ ShowHudText(z, g_CrosshairChannel, "◞ ◟\n◝ ◜");
+ }
+ }
+ }
+ }
+ }
+ */
+ }
+ }
+ if (g_MathCounter[i].BossHP < g_MaxLegalMathCounterHP && activator > 0 && activator <= MAXPLAYERS) {
+ PrintHP(activator, g_MathCounter[i].BossHP);
+ }
+ g_MathCounter[i].LastHPShow = g_MathCounter[i].BossHP;
+ }
+ g_MathCounter[i].LastHP = g_MathCounter[i].BossHP;
+
+ if (!g_MathCounter[i].IsSetDefaultInit && (
+ (g_MathCounter[i].HP_Mode == 1 && CurrentValue > g_MathCounter[i].LastValue) || (g_MathCounter[i].HP_Mode != 1 && CurrentValue < g_MathCounter[i].LastValue)
+ )) {
+ if (g_MathCounter[i].LastHPShow < 2 /* Some maps do not have HP_Init counter, so need to transfer HPMaxValue to HPinit */
+ || g_MathCounter[i].LastAddTime > GetEngineTime() - 0.1 ) { //Some maps will recalculate BossHP when HPbar is subtracted (ze_dreamin, ze_copy, ze_grau, ze_gris etc)
+ if (g_MathCounter[i].HP_Mode == 1 && CurrentValue - 5 >= g_MathCounter[i].LastValue) {
+ g_MathCounter[i].HPInit = CurrentValue;
+
+ #if defined DEBUG
+ CPrintToChatAll("{blue}[BossHP-DEBUG] Set HP init: %d (HP Lastshow:%d Last HPadd interval:%.2f)", g_MathCounter[i].HPInit, g_MathCounter[i].LastHPShow, GetEngineTime() - g_MathCounter[i].LastAddTime); //debug
+ #endif
+ }
+ else if (g_MathCounter[i].HP_Mode != 1 && CurrentValue < g_MathCounter[i].LastValue)
+ {
+ g_MathCounter[i].HPInit = g_MathCounter[i].HP_Max;
+
+ #if defined DEBUG
+ CPrintToChatAll("{blue}[BossHP-DEBUG] Set HP init: %d (HP Lastshow:%d Last HPadd interval:%.2f)", g_MathCounter[i].HPInit, g_MathCounter[i].LastHPShow, GetEngineTime() - g_MathCounter[i].LastAddTime); //debug
+ #endif
+ }
+ }
+ g_MathCounter[i].LastAddTime = GetEngineTime();
+ }
+ g_MathCounter[i].LastValue = CurrentValue;
+ break;
+ }
+
+ for (int x = 0; x < g_MathCounter[i].HpGroupCount; x++) {
+ if (StrEqual(targetname, g_MathCounter_HPgroup[i][x].sName, false)) {
+ if (g_MathCounter_HPgroup[i][x].RunOut)
+ return;
+
+ g_MathCounter_HPgroup[i][x].HP = CurrentValue;
+
+ if (CurrentValue == 0)
+ g_MathCounter_HPgroup[i][x].RunOut = true;
+
+ g_MathCounter[i].BossHP = 0;
+ for (int z = 0; z < g_MathCounter[i].HpGroupCount; z++) {
+ g_MathCounter[i].BossHP += g_MathCounter_HPgroup[i][z].HP;
+
+ #if defined DEBUG
+ CPrintToChatAll("{purple}[BossHP-DEBUG] HPgroup(%s)'s CurrentValue:%d", g_MathCounter_HPgroup[i][z].sName, g_MathCounter_HPgroup[i][z].HP); //debug
+ #endif
+ }
+
+ if (g_DisplayWhenHPAdded || g_MathCounter[i].BossHP < g_MathCounter[i].LastHP) { //Only display when BossHP is subtracted.
+ if (g_MathCounter[i].BossHP <= 1) { //in some maps like ze_Predator_ultimate, boss's math_counter MinValve is not 0 but 1.
+ g_MathCounter[i].LastChangeTime = GetEngineTime() - ( g_BossHpKeepTime - g_BossDieKeepTime ) ; // when BossHP hit 0, keep more 1s display time.
+ iLastBossEnt = -1;
+
+ g_MathCounter[i].BossHP = 0;
+ } else {
+ iLastBossEnt = entity;
+
+ g_MathCounter[i].LastChangeTime = GetEngineTime();
+ if (g_MathCounter[i].BossHP < g_MaxLegalMathCounterHP && activator > 0 && activator <= MAXPLAYERS) {
+ if (csgo)
+ CS_SetClientAssists(activator, CS_GetClientAssists(activator) + 1);
+ else
+ SetEntProp(activator, Prop_Data, "m_iDeaths", GetEntProp(activator, Prop_Data, "m_iDeaths") - 1);
+
+ //Give cash to players, 1hit = $10
+ SetEntProp(activator, Prop_Send, "m_iAccount", GetEntProp(activator, Prop_Send, "m_iAccount") + g_RewardMoney);
+
+ ////Crosshair when hit the boss
+ //if (g_iStatus[activator] == 0 || g_iStatus[activator] == 2) {
+ // if (g_bUIManager)
+ // SendHudText(activator, g_CrosshairChannel, 5, -1.0, -1.0, {255, 0, 0, 50}, {255, 0, 0, 50}, 0, 0.1, 0.1, 0.1, 0.1, "◞ ◟\n◝ ◜");
+ // else {
+ // SetHudTextParamsEx(-1.0, -1.0, 0.1, {255, 0, 0, 50}, {255, 0, 0, 50}, 0, 0.1, 0.1, 0.1);
+ // ShowHudText(activator, g_CrosshairChannel, "◞ ◟\n◝ ◜");
+ // }
+ //}
+ }
+ }
+ if (g_MathCounter[i].BossHP < g_MaxLegalMathCounterHP && activator > 0 && activator <= MAXPLAYERS) {
+ PrintHP(activator, g_MathCounter[i].BossHP);
+ }
+ }
+ g_MathCounter[i].LastHP = g_MathCounter[i].BossHP;
+ break;
+ }
+ }
+
+ if (StrEqual(targetname, g_MathCounter[i].sHPBar, false)) {
+ if (g_MathCounter[i].HPBar_Mode == 1) {
+ g_MathCounter[i].Multiply = CurrentValue - g_MathCounter[i].HPBar_Min;
+ }
+ else if (g_MathCounter[i].HPBar_Mode == 2)
+ {
+ g_MathCounter[i].Multiply = g_MathCounter[i].HPBar_Max - CurrentValue;
+ }
+ g_MathCounter[i].IsSetDefaultMultiply = true;
+
+ #if defined DEBUG
+ CPrintToChatAll("{pink}[BossHP-DEBUG] Set multiply:%d (triggered by HPbar Counter:%s)", g_MathCounter[i].Multiply, targetname); //debug
+ #endif
+ }
+ if (StrEqual(targetname, g_MathCounter[i].sHPInit, false)) {
+ g_MathCounter[i].HPInit = CurrentValue;
+ g_MathCounter[i].IsSetDefaultInit = true;
+
+ #if defined DEBUG
+ CPrintToChatAll("{blue}[BossHP-DEBUG] Set HP init:%d (triggered by HPinit Counter:%s)", g_MathCounter[i].HPInit, targetname); //debug
+ #endif
+ }
+ }
+ }
+
+ //bhud function
+ if (g_bForceShowBossHP &&
+ LastShowBossHP + 3.0 < GetEngineTime() && // If BossHP was show in the past 3sec, block this function
+ (IsValidEntity(entity) || IsValidEdict(entity)) &&
+ activator > 0 && activator <= MAXPLAYERS) {
+ if (LastShootHitbox[activator] < GetEngineTime() - 0.1)
+ return; //if players didn't shoot to hitbox, block this function
+
+ int CurrentValue = RoundFloat(GetEntDataFloat(entity, FindDataMapInfo(entity, "m_OutValue")));
+ GetEntPropString(entity, Prop_Data, "m_iName", g_ClientLastShootBreakable[activator].sName, sizeof(Array_ClientLastShootBreakable::sName));
+ g_ClientLastShootBreakable[activator].EntityIndex = 0;
+ if (CurrentValue > 0) {
+ iLastBossEnt = entity;
+
+ PrintHP_Force(activator, 0, g_ClientLastShootBreakable[activator].sName, CurrentValue);
+ } else{
+ iLastBossEnt = -1;
+
+ //PrintHP_Force(activator, 0, g_ClientLastShootBreakable[activator].sName, 0);
+ }
+ }
+}
+
+public Action UserMessageHook_TextMsg(UserMsg msg_id, Handle pb, const int[] players, int playersNum, bool reliable, bool init) {
+ if (csgo) {
+ if (PbReadInt(pb, "msg_dst") != 4)
+ return Plugin_Continue;
+
+ for (int i; i < playersNum; i++) {
+ g_LastShowCenterText[players[i]] = GetEngineTime() + 2.0;
+ }
+
+ }
+ return Plugin_Continue;
+}
+
+public Action UserMessageHook_HintText(UserMsg msg_id, Handle pb, const int[] players, int playersNum, bool reliable, bool init) {
+//
+ if (csgo) {
+ char szBuffer[255];
+ PbReadString(pb, "text", szBuffer, sizeof(szBuffer));
+ if (StrContains(szBuffer, "HP") > -1) {
+ return Plugin_Continue;
+ }
+ for (int i; i< playersNum; i++) {
+ g_LastShowCenterText[players[i]] = GetEngineTime();
+ }
+ }
+ return Plugin_Continue;
+}
+
+char PrintText_Hint[255];
+//char PrintText_HUD[255];
+char CurrentBossName[32];
+float CurrentTime;
+int CurrentHP;
+int MaxHP;
+int CTcount;
+int count;
+
+//bhud function
+void PrintHP_Force(int client, int entity, const char[] entityname, int hp) {
+ CurrentTime = GetEngineTime();
+ if ( (LastShootHitbox[client] > CurrentTime - 3.0 && LastForceShowBossHP + 0.1 < CurrentTime) || hp == 0 ) {
+ count = 0;
+ CTcount = 0;
+ LoopIngamePlayers(i) {
+ if (GetClientTeam(i) == CS_TEAM_CT) {
+ CTcount++;
+ if (LastShootHitbox[i] > CurrentTime - 7.0 && g_ClientLastShootBreakable[i].EntityIndex == entity && StrEqual(g_ClientLastShootBreakable[i].sName, entityname)) {
+ count++;
+ }
+ }
+ }
+
+ char sBuffer[MAX_BREAKABLE_NAME_LENGTH];
+ strcopy(sBuffer, sizeof(sBuffer), entityname);
+ if (g_bUpperCaseInForceEnable) {
+ int and = -1;
+ if ((and = FindCharInString(sBuffer, '&', true)) > 0)
+ sBuffer[and] = '\0';
+ ReplaceString(sBuffer, sizeof(sBuffer), "_", " ");
+ for (int x = 0; x < strlen(sBuffer); x++) {
+ if (IsCharLower(sBuffer[x]))
+ sBuffer[x] = CharToUpper(sBuffer[x]);
+ }
+ }
+
+ if (count > CTcount / 2) {
+ if (csgo) {
+ LoopIngamePlayers(i) {
+ if (g_iStatus[i] == 0 || g_iStatus[i] == 1)
+ PrintHintText(i, "%s: %d", sBuffer, hp);
+ }
+ } else {
+ LoopIngamePlayers(i) {
+ if (g_iStatus[i] == 0 || g_iStatus[i] == 1)
+ PrintHintText(i, "%s: %d", sBuffer, hp);
+ }
+ }
+ } else {
+ LoopIngamePlayers(i) {
+ if (g_iStatus[i] == 0 || g_iStatus[i] == 1) {
+ if (LastShootHitbox[i] > CurrentTime - 7.0 && g_ClientLastShootBreakable[i].EntityIndex == entity && StrEqual(g_ClientLastShootBreakable[i].sName, entityname)) {
+ if (csgo) {
+ PrintHintText(i, "%s: %d", sBuffer, hp);
+ } else {
+ PrintHintText(i, "%s: %d", sBuffer, hp);
+ }
+ }
+ }
+ }
+ }
+ LastForceShowBossHP = CurrentTime;
+ }
+}
+
+void PrintHP(int client, int hp) {
+ CurrentTime = GetEngineTime();
+
+ if ( (LastShootHitbox[client] > CurrentTime - 3.0 && LastShowBossHP + 0.1 < CurrentTime) || hp == 0 || g_DisplayWhenHPAdded ) {
+ g_BossDisplay.BossName.Clear();
+ g_BossDisplay.HP.Clear();
+ g_BossDisplay.MaxHP.Clear();
+ PrintText_Hint = "";
+ //PrintText_HUD = "";
+
+ for (int i = 0; i < g_Count.Math_Counter; i++) {
+ if (g_MathCounter[i].BossHP > g_MathCounter[i].MaxBossHP)
+ g_MathCounter[i].MaxBossHP = g_MathCounter[i].BossHP;
+ if (g_MathCounter[i].LastChangeTime + g_BossHpKeepTime > CurrentTime) {
+ g_BossDisplay.BossName.PushString(g_MathCounter[i].BossName);
+ g_BossDisplay.HP.Push(g_MathCounter[i].BossHP);
+ g_BossDisplay.MaxHP.Push(g_MathCounter[i].MaxBossHP);
+ }
+ }
+
+ for (int i = 0; i < g_Count.Breakable; i++) {
+ if (g_Breakable[i].BossHP > g_Breakable[i].MaxBossHP)
+ g_Breakable[i].MaxBossHP = g_Breakable[i].BossHP;
+ if (g_Breakable[i].LastChangeTime + g_BossHpKeepTime > CurrentTime) {
+ g_BossDisplay.BossName.PushString(g_Breakable[i].BossName);
+ g_BossDisplay.HP.Push(g_Breakable[i].BossHP);
+ g_BossDisplay.MaxHP.Push(g_Breakable[i].MaxBossHP);
+ }
+ }
+
+ for (int i = 0; i < g_BossDisplay.HP.Length; i++) {
+ g_BossDisplay.BossName.GetString(i, CurrentBossName, sizeof(CurrentBossName));
+ CurrentHP = g_BossDisplay.HP.Get(i);
+ MaxHP = g_BossDisplay.MaxHP.Get(i);
+
+ if (csgo) {
+ float fCurrentRatio = float(CurrentHP) / float(MaxHP);
+ if (fCurrentRatio < 0.2)
+ HPcolor = "FF0000"; //red
+ else if (fCurrentRatio < 0.4)
+ HPcolor = "FFFF00"; //yellow
+ else
+ HPcolor = "00FF00"; //green
+ if (g_BossDisplay.HP.Length == 1) { //Single BossHP display style
+ int iBar = (hp == 0) ? 0 : RoundToCeil(fCurrentRatio * 20.0);
+ if (iBar > 20) iBar = 20;
+ char sBar[64], sBlank[64];
+ for (int j = 0; j < iBar - 1; j++)
+ StrCat(sBar, sizeof(sBar), "█"); //░▒▓█
+ for (int k = 0; k < 20 - iBar; k++)
+ StrCat(sBlank, sizeof(sBlank), "░");
+ //%s
+ Format(PrintText_Hint, sizeof(PrintText_Hint), "►%s◄ HP: %d\n%s%s%s%s\n", CurrentBossName, HPcolor, CurrentHP, sBar, CurrentHP <= 0 ? "" : (CurrentHP < MaxHP ? "▒" : "█"), CurrentHP <= 0 ? "░" : "", sBlank);
+ }
+ else if (g_BossDisplay.HP.Length <= 3) { //Mult BossHP display style
+ Format(PrintText_Hint, sizeof(PrintText_Hint), "%s%s: %dHP\n", PrintText_Hint, CurrentBossName, HPcolor, CurrentHP);
+ }
+ else // more than 3 BossHP display style
+ {
+ Format(PrintText_Hint, sizeof(PrintText_Hint), "%s%s: %dHP%s", PrintText_Hint, CurrentBossName, HPcolor, CurrentHP, i % 2 ? "\n" : " ");
+ }
+ } else {
+ Format(PrintText_Hint, sizeof(PrintText_Hint), "%s%s: %d%s", PrintText_Hint, CurrentBossName, CurrentHP, i == g_BossDisplay.HP.Length - 1 ? "" : "\n");
+ }
+ //Format(PrintText_HUD, sizeof(PrintText_HUD), "%s%s: %d%s", PrintText_HUD, CurrentBossName, CurrentHP, "HP\n");
+ }
+
+ LoopIngamePlayers(i) {
+ if (g_iStatus[i] == 0 || g_iStatus[i] == 1) {
+ if (CurrentTime - 3.0 < g_LastShowCenterText[i]) {
+ //SetHudTextParamsEx(-1.0, 0.66 - 0.03 * (g_BossDisplay.HP.Length - 1), 1.0, {255, 0, 255, 230}, {255, 0, 255, 230}, 1, 0.0, 0.1, 0.1);
+ //ShowHudText(i, 1, "%s", PrintText_HUD);
+ } else {
+ PrintHintText(i, "%s", PrintText_Hint);
+ }
+ }
+ }
+
+ LastShowBossHP = CurrentTime;
+
+ if (LastShowTopDamage + 1.0 < CurrentTime) {
+ if (g_bShowTopDamageDuringBOSS) {
+ ShowBossTopDamage(0, -1.0, 0.76);
+ LastShowTopDamage = CurrentTime;
+ } else if (g_bBossBeatenShowBossDamageRank && hp == 0) {
+ ShowBossTopDamage(0, -1.0, 0.76);
+ LastShowTopDamage = CurrentTime;
+ }
+ }
+ }
+}
+
+public Action DEBUG_PrintVar(int client, int args) {
+ if (!client)
+ return Plugin_Handled;
+
+ ReplyToCommand(client, "g_bForceShowBossHP: %b", g_bForceShowBossHP);
+ ReplyToCommand(client, "g_BossHpKeepTime: %.1f", g_BossHpKeepTime);
+ ReplyToCommand(client, "g_BossDieKeepTime: %.1f", g_BossDieKeepTime);
+ ReplyToCommand(client, "g_MaxLegalBreakableHP: %d", g_MaxLegalBreakableHP);
+ ReplyToCommand(client, "g_MaxLegalMathCounterHP: %d", g_MaxLegalMathCounterHP);
+ ReplyToCommand(client, "g_DisplayWhenHPAdded: %b", g_DisplayWhenHPAdded);
+ ReplyToCommand(client, "g_LastShowCenterText: %.1f", g_LastShowCenterText);
+ ReplyToCommand(client, "GetEngineTime(): %.2f", GetEngineTime());
+ return Plugin_Handled;
+}
+
+public void OnEntityCreated(int entity, const char[] classname) {
+ if (!IsConfigLoad) return;
+
+ if (StrEqual(classname, "math_counter", false)) {
+ if (hAcceptInput != INVALID_HANDLE)
+ DHookEntity(hAcceptInput, false, entity);
+ RequestFrame(Timer_InitMathCounterInfo, entity);
+ }
+}
+
+void Timer_InitMathCounterInfo(int entity) {
+ if (!IsValidEntity(entity) && !IsValidEdict(entity))
+ return;
+
+ char EntityName[64];
+ GetEntPropString(entity, Prop_Data, "m_iName", EntityName, sizeof(EntityName));
+
+ for (int i = 0; i < g_Count.Math_Counter; i++) {
+ if (StrEqual(EntityName, g_MathCounter[i].sHP, false)) {
+ g_MathCounter[i].HP_Min = RoundFloat(GetEntPropFloat(entity, Prop_Data, "m_flMin"));
+ g_MathCounter[i].HP_Max = RoundFloat(GetEntPropFloat(entity, Prop_Data, "m_flMax"));
+ g_MathCounter[i].HP_StartValue = RoundFloat(GetEntDataFloat(entity, FindDataMapInfo(entity, "m_OutValue")));
+ int iOnHitMinCount = GetOutputCount(entity, "m_OnHitMin");
+ int iOnHitMaxCount = GetOutputCount(entity, "m_OnHitMax");
+ g_MathCounter[i].HP_Mode = iOnHitMaxCount > iOnHitMinCount ? 2 : 1;
+ break;
+ }
+
+ for (int x = 0; x < g_MathCounter[i].HpGroupCount; x++) {
+ if (StrEqual(EntityName, g_MathCounter_HPgroup[i][x].sName, false)) {
+ g_MathCounter_HPgroup[i][x].Min = RoundFloat(GetEntPropFloat(entity, Prop_Data, "m_flMin"));
+ g_MathCounter_HPgroup[i][x].Max = RoundFloat(GetEntPropFloat(entity, Prop_Data, "m_flMax"));
+ g_MathCounter_HPgroup[i][x].HP = RoundFloat(GetEntDataFloat(entity, FindDataMapInfo(entity, "m_OutValue")));
+ g_MathCounter_HPgroup[i][x].StartValue = RoundFloat(GetEntDataFloat(entity, FindDataMapInfo(entity, "m_OutValue")));
+ g_MathCounter_HPgroup[i][x].StartDisabled = view_as(GetEntProp(entity, Prop_Data, "m_bDisabled"));
+ g_MathCounter_HPgroup[i][x].Stats = !g_MathCounter_HPgroup[i][x].StartDisabled;
+
+ break;
+ }
+ }
+
+ if (StrEqual(EntityName, g_MathCounter[i].sHPBar, false)) {
+ g_MathCounter[i].HPBar_Min = RoundFloat(GetEntPropFloat(entity, Prop_Data, "m_flMin"));
+ g_MathCounter[i].HPBar_Max = RoundFloat(GetEntPropFloat(entity, Prop_Data, "m_flMax"));
+ g_MathCounter[i].HPBar_StartValue = RoundFloat(GetEntDataFloat(entity, FindDataMapInfo(entity, "m_OutValue")));
+ int iOnHitMinCount = GetOutputCount(entity, "m_OnHitMin");
+ int iOnHitMaxCount = GetOutputCount(entity, "m_OnHitMax");
+ g_MathCounter[i].HPBar_Mode = iOnHitMaxCount > iOnHitMinCount ? 2 : 1;
+ break;
+ }
+
+ if (StrEqual(EntityName, g_MathCounter[i].sHPInit, false)) {
+ g_MathCounter[i].HPInit_Min = RoundFloat(GetEntPropFloat(entity, Prop_Data, "m_flMin"));
+ g_MathCounter[i].HPInit_Max = RoundFloat(GetEntPropFloat(entity, Prop_Data, "m_flMax"));
+ g_MathCounter[i].HPInit_StartValue = RoundFloat(GetEntDataFloat(entity, FindDataMapInfo(entity, "m_OutValue")));
+ break;
+ }
+ }
+
+ #if defined DEBUG
+ if (StrContains(EntityName, "behemoth_", false) > -1) {
+ PrintToChatAll("EntityName: %s", EntityName);
+ PrintToChatAll("m_bHitMax: %d", GetEntProp(entity, Prop_Data, "m_bHitMax"));
+ PrintToChatAll("m_bHitMin: %d", GetEntProp(entity, Prop_Data, "m_bHitMin"));
+ PrintToChatAll("m_flMin: %d", RoundFloat(GetEntPropFloat(entity, Prop_Data, "m_flMin")));
+ PrintToChatAll("m_flMax: %d", RoundFloat(GetEntPropFloat(entity, Prop_Data, "m_flMax")));
+ PrintToChatAll("m_bDisabled: %d", GetEntProp(entity, Prop_Data, "m_bDisabled"));
+ PrintToChatAll("m_OutValue: %d", RoundFloat(GetEntDataFloat(entity, FindDataMapInfo(entity, "m_OutValue"))));
+ PrintToChatAll("--");
+ }
+ #endif
+}
+
+public Action DEBUG_GetArrayInfo(int client, int args) {
+ if (args != 1)
+ return Plugin_Handled;
+ char Arg1[32];
+ GetCmdArg(1, Arg1, 32);
+ for (int i = 0; i < g_Count.Math_Counter; i++) {
+ if (StrEqual(Arg1, g_MathCounter[i].sHP, false)) {
+ ReplyToCommand(client, "Type: g_MathCounter[i].sHP");
+ ReplyToCommand(client, "Min:%d", g_MathCounter[i].HP_Min);
+ ReplyToCommand(client, "Max:%d", g_MathCounter[i].HP_Max);
+ ReplyToCommand(client, "StartValue:%d", g_MathCounter[i].HP_StartValue);
+
+ break;
+ }
+
+ for (int x = 0; x < g_MathCounter[i].HpGroupCount; x++) {
+ if (StrEqual(Arg1, g_MathCounter_HPgroup[i][x].sName, false)) {
+ ReplyToCommand(client, "Type: g_MathCounter_HPgroup[i][x].sName");
+ ReplyToCommand(client, "Min:%d", g_MathCounter_HPgroup[i][x].Min);
+ ReplyToCommand(client, "Max:%d", g_MathCounter_HPgroup[i][x].Max);
+ ReplyToCommand(client, "HP:%d", g_MathCounter_HPgroup[i][x].HP);
+ ReplyToCommand(client, "StartValue:%d", g_MathCounter_HPgroup[i][x].StartValue);
+ ReplyToCommand(client, "StartDisabled:%b", g_MathCounter_HPgroup[i][x].StartDisabled);
+ ReplyToCommand(client, "Stats:%d", g_MathCounter_HPgroup[i][x].Stats);
+
+ break;
+ }
+ }
+
+ if (StrEqual(Arg1, g_MathCounter[i].sHPBar, false)) {
+ ReplyToCommand(client, "Type: g_MathCounter[i].sHPBar");
+ ReplyToCommand(client, "Min:%d", g_MathCounter[i].HPBar_Min);
+ ReplyToCommand(client, "Max:%d", g_MathCounter[i].HPBar_Max);
+ ReplyToCommand(client, "StartValue:%b", g_MathCounter[i].HPBar_StartValue);
+
+ break;
+ }
+
+ if (StrEqual(Arg1, g_MathCounter[i].sHPInit, false)) {
+ ReplyToCommand(client, "Type: g_MathCounter[i].sHPInit");
+ ReplyToCommand(client, "Min:%d", g_MathCounter[i].HPInit_Min);
+ ReplyToCommand(client, "Max:%d", g_MathCounter[i].HPInit_Max);
+ ReplyToCommand(client, "StartValue:%b", g_MathCounter[i].HPInit_StartValue);
+
+ break;
+ }
+ }
+ return Plugin_Handled;
+}
+
+public MRESReturn AcceptInput(int entity, Handle hReturn, Handle hParams) {
+ if (!IsValidEntity(entity))
+ return MRES_Ignored;
+
+ char eEntityName[64], eCommand[16], eParam[16];
+ GetEntPropString(entity, Prop_Data, "m_iName", eEntityName, 64);
+
+ DHookGetParamString(hParams, 1, eCommand, 16);
+ int type = -1, Param = 0;
+ type = DHookGetParamObjectPtrVar(hParams, 4, 16, ObjectValueType_Int);
+ if (type == 1)
+ Param = DHookGetParamObjectPtrVar(hParams, 4, 0, ObjectValueType_Int);
+ else if (type == 2) {
+ DHookGetParamObjectPtrString(hParams, 4, 0, ObjectValueType_String, eParam, 16);
+ StringToIntEx(eParam, Param);
+ }
+
+ if (StrEqual(eCommand, "SetValueNoFire", false)) {
+ for (int i = 0; i < g_Count.Math_Counter; i++) {
+ if (StrEqual(eEntityName, g_MathCounter[i].sHPBar, false)) {
+ if (g_MathCounter[i].HPBar_Mode == 1)
+ g_MathCounter[i].Multiply = Param - g_MathCounter[i].HPBar_Min;
+ else if (g_MathCounter[i].HPBar_Mode == 2)
+ g_MathCounter[i].Multiply = g_MathCounter[i].HPBar_Max - Param;
+ g_MathCounter[i].IsSetDefaultMultiply = true;
+
+ #if defined DEBUG
+ CPrintToChatAll("{purple}[BossHP-DEBUG] (SetValueNoFire)Set multiply:%d (triggered by HPbar Counter:%s)", g_MathCounter[i].Multiply, eEntityName); //debug
+ #endif
+
+ break;
+ }
+ if (StrEqual(eEntityName, g_MathCounter[i].sHPInit, false)) {
+ g_MathCounter[i].HPInit = Param;
+ g_MathCounter[i].IsSetDefaultInit = true;
+
+ #if defined DEBUG
+ CPrintToChatAll("{purple}[BossHP-DEBUG] (SetValueNoFire)Set HP init:%d (triggered by HPinit Counter:%s)", g_MathCounter[i].HPInit, eEntityName); //debug
+ #endif
+
+ break;
+ }
+ }
+ }
+ else if (StrEqual(eCommand, "Add", false)) {
+ for (int i = 0; i < g_Count.Math_Counter; i++) {
+ for (int x = 0; x < g_MathCounter[i].HpGroupCount; x++) {
+ if (StrEqual(eEntityName, g_MathCounter_HPgroup[i][x].sName, false)) {
+ if (g_MathCounter_HPgroup[i][x].Kill || g_MathCounter_HPgroup[i][x].RunOut || g_MathCounter_HPgroup[i][x].Stats)
+ return MRES_Ignored;
+
+ if (g_MathCounter_HPgroup[i][x].LastAddTime < GetEngineTime() - 1.0) {
+ g_MathCounter_HPgroup[i][x].HP = g_MathCounter_HPgroup[i][x].StartValue;
+
+ #if defined DEBUG
+ CPrintToChatAll("{purple}[BossHP-DEBUG] Set Default HPgroup(%s):%d CurrentValue:%d", eEntityName, g_MathCounter_HPgroup[i][x].StartValue, g_MathCounter_HPgroup[i][x].HP); //debug
+ #endif
+ }
+
+ g_MathCounter_HPgroup[i][x].HP += Param;
+ g_MathCounter_HPgroup[i][x].LastAddTime = GetEngineTime();
+
+ #if defined DEBUG
+ CPrintToChatAll("{purple}[BossHP-DEBUG] Add to HPgroup(%s):%d CurrentValue:%d", eEntityName, Param, g_MathCounter_HPgroup[i][x].HP); //debug
+ #endif
+
+ break;
+ }
+ }
+ }
+ }
+ else if (StrEqual(eCommand, "SetHitMax", false)) {
+ for (int i = 0; i < g_Count.Math_Counter; i++) {
+ if (StrEqual(eEntityName, g_MathCounter[i].sHP, false)) {
+ g_MathCounter[i].HP_Max = Param;
+
+ #if defined DEBUG
+ CPrintToChatAll("{purple}[BossHP-DEBUG] (SetHitMax)Set HP Max:%d", Param); //debug
+ #endif
+
+ break;
+ }
+ if (StrEqual(eEntityName, g_MathCounter[i].sHPBar, false)) {
+ g_MathCounter[i].HPBar_Max = Param;
+
+ #if defined DEBUG
+ CPrintToChatAll("{purple}[BossHP-DEBUG] (SetHitMax)Set HPbar Max:%d", Param); //debug
+ #endif
+
+ break;
+ }
+ if (StrEqual(eEntityName, g_MathCounter[i].sHPInit, false)) {
+ g_MathCounter[i].HPInit_Max = Param;
+
+ #if defined DEBUG
+ CPrintToChatAll("{purple}[BossHP-DEBUG] (SetHitMax)Set HPInit Max:%d", Param); //debug
+ #endif
+
+ break;
+ }
+ for (int x = 0; x < g_MathCounter[i].HpGroupCount; x++) {
+ if (StrEqual(eEntityName, g_MathCounter_HPgroup[i][x].sName, false)) {
+ g_MathCounter_HPgroup[i][x].Max = Param;
+
+ #if defined DEBUG
+ CPrintToChatAll("{purple}[BossHP-DEBUG] (SetHitMax)Set HPgroup(%d) Max:%d", x, Param); //debug
+ #endif
+
+ break;
+ }
+ }
+ }
+ }
+ else if (StrEqual(eCommand, "SetHitMin", false)) {
+ for (int i = 0; i < g_Count.Math_Counter; i++) {
+ if (StrEqual(eEntityName, g_MathCounter[i].sHP, false)) {
+ g_MathCounter[i].HP_Min = Param;
+
+ #if defined DEBUG
+ CPrintToChatAll("{purple}[BossHP-DEBUG] (SetHitMin)Set HP Min:%d", Param); //debug
+ #endif
+
+ break;
+ }
+ if (StrEqual(eEntityName, g_MathCounter[i].sHPBar, false)) {
+ g_MathCounter[i].HPBar_Min = Param;
+
+ #if defined DEBUG
+ CPrintToChatAll("{purple}[BossHP-DEBUG] (SetHitMin)Set HPbar Min:%d", Param); //debug
+ #endif
+
+ break;
+ }
+ if (StrEqual(eEntityName, g_MathCounter[i].sHPInit, false)) {
+ g_MathCounter[i].HPInit_Min = Param;
+
+ #if defined DEBUG
+ CPrintToChatAll("{purple}[BossHP-DEBUG] (SetHitMin)Set HPInit Min:%d", Param); //debug
+ #endif
+
+ break;
+ }
+ for (int x = 0; x < g_MathCounter[i].HpGroupCount; x++) {
+ if (StrEqual(eEntityName, g_MathCounter_HPgroup[i][x].sName, false)) {
+ g_MathCounter_HPgroup[i][x].Min = Param;
+
+ #if defined DEBUG
+ CPrintToChatAll("{purple}[BossHP-DEBUG] (SetHitMin)Set HPgroup(%d) Min:%d", x, Param); //debug
+ #endif
+
+ break;
+ }
+ }
+ }
+ }
+ //else if (StrEqual(eCommand, "SetMaxValueNoFire", false)) {} //(New with Portal 2, Unknown if it's exist in CSGO or CSS)
+ //else if (StrEqual(eCommand, "SetMinValueNoFire", false)) {} //(New with Portal 2, Unknown if it's exist in CSGO or CSS)
+ else if (StrEqual(eCommand, "Enable", false)) {
+ for (int i = 0; i < g_Count.Math_Counter; i++) {
+ for (int x = 0; x < g_MathCounter[i].HpGroupCount; x++) {
+ if (StrEqual(eEntityName, g_MathCounter_HPgroup[i][x].sName, false)) {
+ g_MathCounter_HPgroup[i][x].Stats = true;
+
+ #if defined DEBUG
+ CPrintToChatAll("{purple}[BossHP-DEBUG] Enable HPgroup: %s", eEntityName); //debug
+ #endif
+
+ break;
+ }
+ }
+ }
+ }
+ else if (StrEqual(eCommand, "Disable", false)) {
+ for (int i = 0; i < g_Count.Math_Counter; i++) {
+ for (int x = 0; x < g_MathCounter[i].HpGroupCount; x++) {
+ if (StrEqual(eEntityName, g_MathCounter_HPgroup[i][x].sName, false)) {
+ g_MathCounter_HPgroup[i][x].Stats = false;
+
+ #if defined DEBUG
+ CPrintToChatAll("{purple}[BossHP-DEBUG] Disabled(kill) HPgroup: %s", eEntityName); //debug
+ #endif
+
+ break;
+ }
+ }
+ }
+ }
+ else if (StrEqual(eCommand, "Kill", false)) {
+ for (int i = 0; i < g_Count.Math_Counter; i++) {
+ for (int x = 0; x < g_MathCounter[i].HpGroupCount; x++) {
+ if (StrEqual(eEntityName, g_MathCounter_HPgroup[i][x].sName, false)) {
+ g_MathCounter_HPgroup[i][x].Stats = false;
+ g_MathCounter_HPgroup[i][x].Kill = true;
+
+ #if defined DEBUG
+ CPrintToChatAll("{purple}[BossHP-DEBUG] Disabled HPgroup: %s", eEntityName); //debug
+ #endif
+
+ break;
+ }
+ }
+ }
+ }
+
+ return MRES_Ignored;
+}
+
+stock void q_sort(int[] numbers, int left, int right, int[] subarr) {
+ int pivot, l_hold, r_hold, subpiv;
+
+ l_hold = left;
+ r_hold = right;
+ pivot = numbers[left];
+ subpiv = subarr[left];
+ while (left < right) {
+ while ((numbers[right] >= pivot) && (left < right))
+ right--;
+ if (left != right) {
+ numbers[left] = numbers[right];
+ subarr[left] = subarr[right];
+ left++;
+ }
+ while ((numbers[left] <= pivot) && (left < right))
+ left++;
+ if (left != right) {
+ numbers[right] = numbers[left];
+ subarr[right] = subarr[left];
+ right--;
+ }
+ }
+ numbers[left] = pivot;
+ subarr[left] = subpiv;
+ pivot = left;
+ left = l_hold;
+ right = r_hold;
+ if (left < pivot)
+ q_sort(numbers, left, pivot - 1, subarr);
+ if (right > pivot)
+ q_sort(numbers, pivot + 1, right, subarr);
+}
+
+stock void QuickSort(int[] arr, int size, int[] subarr) {
+ q_sort(arr, 0, size - 1, subarr);
+}
+
+void ShowBossTopDamage(int client, const float x = -1.0, const float y = 0.26) {
+ int[] damagelist = new int[MaxClients+1];
+ int[] playerlist = new int[MaxClients+1];
+
+ for (int i = 1; i < MaxClients; i++) {
+ if (IsClientInGame(i)) {
+ damagelist[i] = csgo ? CS_GetClientAssists(i) : GetEntProp(i, Prop_Data, "m_iDeaths") * -1;
+ playerlist[i] = i;
+ }
+ }
+
+ QuickSort(damagelist, MaxClients+1, playerlist);
+
+ char damagelist_text[255];
+ int rank = 1;
+ for (int j = MaxClients; j >= 0; j--, rank++) {
+ if (rank > 5 || damagelist[j] < 1 || playerlist[j] < 1) break;
+ Format(damagelist_text, sizeof(damagelist_text), "%s\n%i. %N: %d HITs", damagelist_text, rank, playerlist[j], damagelist[j]);
+ }
+ if (damagelist_text[0] != '\0') {
+ if (g_bUIManager) {
+ //if (client == 0) {
+ // SendHudTextToAll(3, 5, x, y, {255, 201, 14, 230}, _, 1, 0.3, 2.0, 10.0, 0.0, "%t%s", "DamageRank_Title", damagelist_text);
+ //}
+ //else {
+ // SendHudText(client, 3, 5, x, y, {255, 201, 14, 230}, _, 1, 0.3, 2.0, 10.0, 0.0, "%t%s", "DamageRank_Title", damagelist_text);
+ //}
+ } else {
+ SetHudTextParams(x, y, 10.0, 255, 201, 14, 230, 1, 0.0, 0.3, 2.0);
+
+ char text[255];
+
+ if (client == 0) {
+ LoopIngamePlayers(i) {
+ FormatEx(text, sizeof(text), "%T", "DamageRank_Title", i);
+ Format(text, sizeof(text), "%s%s", text, damagelist_text);
+ ShowHudText(i, 3, "%s", text);
+ }
+ }
+ else {
+ FormatEx(text, sizeof(text), "%T", "DamageRank_Title", client);
+ Format(text, sizeof(text), "%s%s", text, damagelist_text);
+ ShowHudText(client, 3, "%s", text);
+ }
+ }
+ }
+}
diff --git a/BossHP/translations/BossHP.phrases.txt b/BossHP/translations/BossHP.phrases.txt
new file mode 100644
index 0000000..015cafb
--- /dev/null
+++ b/BossHP/translations/BossHP.phrases.txt
@@ -0,0 +1,87 @@
+"Phrases"
+{
+ "RoundStart_Message_CSGO"
+ {
+ "en" "{orange}[{yellow}BossHP{orange}]{olive} This map is supported by this plugin. Shoot the boss will add your [Assists] count."
+ "jp" "{orange}[{yellow}BossHP{orange}]{olive} このマップは BossHP プラグインが動作しています. ボスを撃つとあなたの [Assists] カウントが上昇します."
+ "chi" "{orange}[{yellow}BossHP{orange}]{olive} 当前地图支持 BOSS HP 显示. 助攻数为本局您对 BOSS 造成的伤害"
+ "zho" "{orange}[{yellow}BossHP{orange}]{olive} 當前地圖支援 BOSS HP 顯示. 助攻數為本局您對 BOSS 造成的傷害"
+ }
+ "RoundStart_Message_CSS"
+ {
+ "en" "{orange}[{yellow}BossHP{orange}]{olive} This map is supported by this plugin. Shoot the boss will add your [Death] count."
+ "jp" "{orange}[{yellow}BossHP{orange}]{olive} このマップは BossHP プラグインが動作しています. ボスを撃つとあなたの [Death] カウントが上昇します."
+ "chi" "{orange}[{yellow}BossHP{orange}]{olive} 当前地图支持 BOSS HP 显示. 死亡数为本局您对 BOSS 造成的伤害"
+ "zho" "{orange}[{yellow}BossHP{orange}]{olive} 當前地圖支援 BOSS HP 顯示. 死亡數為本局您對 BOSS 造成的傷害"
+ }
+ "DamageRank_Title"
+ {
+ "en" "*** Rank of Damage to BOSS ***"
+ "jp" "*** BOSS ダメージランキング ***"
+ "chi" "*** 本局对 BOSS 输出排行 ***"
+ "zho" "*** 本局對 BOSS 輸出排行 ***"
+ }
+ "BossHP"
+ {
+ "en" "Show Boss HP"
+ "jp" "Boss HP (ボスHP表示)"
+ "chi" "显示 Boss HP"
+ "zho" "顯示 Boss HP"
+ }
+ "Disabled"
+ {
+ "en" "Disabled"
+ "jp" "無効"
+ "chi" "停用"
+ "zho" "停用"
+ }
+ "OnlyHP"
+ {
+ "en" "Only HP Display"
+ "jp" "HP表示のみ"
+ "chi" "只有 HP 显示"
+ "zho" "只有 HP 顯示"
+ }
+ "FullEnabled"
+ {
+ "en" "Enabled (with Hitmarker)"
+ "jp" "有効 (ヒットマーカー付き)"
+ "chi" "启用 (附带击中标记)"
+ "zho" "啟用 (附帶擊中標記)"
+ }
+ "OnlyHitmarker"
+ {
+ "en" "Only Hitmarker"
+ "jp" "ヒットマーカーのみ"
+ "chi" "只有击中标记"
+ "zho" "只有擊中標記"
+ }
+ "DisabledMsg"
+ {
+ "en" "{green}[BossHP]{default} Show Boss HP has been {olive}Disabled{default}."
+ "jp" "{green}[BossHP]{default} ボスHP表示を {olive}無効{default} にしました."
+ "chi" "{green}[BossHP]{default} 显示Boss HP机能已被{olive}停用{default}。"
+ "zho" "{green}[BossHP]{default} 顯示Boss HP功能已被{olive}停用{default}。"
+ }
+ "OnlyHPMsg"
+ {
+ "en" "{green}[BossHP]{default} Show Boss HP has been {olive}Set to only HP display{default}."
+ "jp" "{green}[BossHP]{default} ボスHP表示を {olive}HP表示のみ{default} にしました."
+ "chi" "{green}[BossHP]{default} 显示Boss HP机能已设置为{olive}只有 HP 显示{default}。"
+ "zho" "{green}[BossHP]{default} 顯示Boss HP功能已設定為{olive}只有 HP 顯示{default}。"
+ }
+ "FullEnabledMsg"
+ {
+ "en" "{green}[BossHP]{default} Show Boss HP has been {olive}Enabled with Hitmarker{default}."
+ "jp" "{green}[BossHP]{default} ボスHP表示を {olive}有効 (ヒットマーカー付き){default} にしました."
+ "chi" "{green}[BossHP]{default} 显示Boss HP机能已被{olive}启用 (附带击中标记){default}。"
+ "zho" "{green}[BossHP]{default} 顯示Boss HP功能已被{olive}啟用 (附帶擊中標記){default}。"
+ }
+ "OnlyHitmarkerMsg"
+ {
+ "en" "{green}[BossHP]{default} Show Boss HP has been {olive}Set to only Hitmarker{default}."
+ "jp" "{green}[BossHP]{default} ボスHP表示を {olive}ヒットマーカーのみ{default} にしました."
+ "chi" "{green}[BossHP]{default} 显示Boss HP机能已设置为{olive}只有击中标记{default}。"
+ "zho" "{green}[BossHP]{default} 顯示Boss HP功能已設定為{olive}只有擊中標記{default}。"
+ }
+}
\ No newline at end of file
diff --git a/BumpWeaponFix/gamedata/BumpWeaponFix.games.txt b/BumpWeaponFix/gamedata/BumpWeaponFix.games.txt
new file mode 100644
index 0000000..3999a87
--- /dev/null
+++ b/BumpWeaponFix/gamedata/BumpWeaponFix.games.txt
@@ -0,0 +1,15 @@
+"Games"
+{
+ "csgo"
+ {
+ "Signatures"
+ {
+ "ValidateLineOfSight"
+ {
+ "library" "server"
+ "windows" "\x55\x8B\xEC\x83\xE4\xF8\x81\xEC\xF8\x00\x00\x00\x56\x8B\x75\x08"
+ "linux" "\x55\x89\xE5\x57\x56\x53\x81\xEC\x7C\x01\x00\x00\x8B\x5D\x0C\x8B\x75\x08"
+ }
+ }
+ }
+}
diff --git a/BumpWeaponFix/scripting/BumpWeaponFix.sp b/BumpWeaponFix/scripting/BumpWeaponFix.sp
new file mode 100644
index 0000000..f140932
--- /dev/null
+++ b/BumpWeaponFix/scripting/BumpWeaponFix.sp
@@ -0,0 +1,47 @@
+#pragma semicolon 1
+#pragma newdecls required
+
+#include
+#include
+#include
+
+Handle g_hValidateLineOfSight = null;
+
+public Plugin myinfo = {
+ name = "[CS:GO] BumpWeapon Fix",
+ author = "SHUFEN from POSSESSION.tokyo",
+ description = "Ignore to validate line-of-sight when pick up weapons",
+ version = "20190331",
+ url = "https://possession.tokyo"
+};
+
+public void OnPluginStart() {
+ Handle hGameConf = LoadGameConfigFile("BumpWeaponFix.games");
+ if (hGameConf == null) {
+ SetFailState("Couldn't load BumpWeaponFix.games game config!");
+ return;
+ }
+
+ // ValidateLineOfSight
+ g_hValidateLineOfSight = DHookCreateDetour(Address_Null, CallConv_THISCALL, ReturnType_Bool, ThisPointer_CBaseEntity);
+ if (!g_hValidateLineOfSight) {
+ delete hGameConf;
+ SetFailState("Failed to setup detour for \"ValidateLineOfSight\"");
+ }
+ if (!DHookSetFromConf(g_hValidateLineOfSight, hGameConf, SDKConf_Signature, "ValidateLineOfSight")) {
+ delete hGameConf;
+ SetFailState("Failed to load \"ValidateLineOfSight\" signature from gamedata");
+ }
+ DHookAddParam(g_hValidateLineOfSight, HookParamType_Int);
+ if (!DHookEnableDetour(g_hValidateLineOfSight, false, Detour_ValidateLineOfSight)) {
+ delete hGameConf;
+ SetFailState("Failed to detour \"ValidateLineOfSight\"");
+ }
+
+ delete hGameConf;
+}
+
+public MRESReturn Detour_ValidateLineOfSight(Address pThis, Handle hReturn, Handle hParams) {
+ DHookSetReturn(hReturn, true);
+ return MRES_ChangedOverride;
+}
\ No newline at end of file
diff --git a/ButtonPresser/scripting/ButtonPresser.sp b/ButtonPresser/scripting/ButtonPresser.sp
new file mode 100644
index 0000000..494ba75
--- /dev/null
+++ b/ButtonPresser/scripting/ButtonPresser.sp
@@ -0,0 +1,78 @@
+#include
+#include
+#include
+
+//----------------------------------------------------------------------------------------------------
+// Purpose:
+//----------------------------------------------------------------------------------------------------
+public Plugin:myinfo =
+{
+ name = "Button Presser",
+ description = "Notify admins when buttons are pressed",
+ author = "zaCade (lost the original source btw)",
+ version = "1.0",
+ url = ""
+};
+
+//----------------------------------------------------------------------------------------------------
+// Purpose:
+//----------------------------------------------------------------------------------------------------
+public void OnPluginStart()
+{
+ int iEntity = INVALID_ENT_REFERENCE;
+
+ while ((iEntity = FindEntityByClassname(iEntity, "*")) != INVALID_ENT_REFERENCE)
+ {
+ OnEntityCreated(iEntity, "");
+ }
+}
+
+//----------------------------------------------------------------------------------------------------
+// Purpose:
+//----------------------------------------------------------------------------------------------------
+public void OnEntityCreated(int iEntity, const char[] sClassname)
+{
+ if (!IsValidEdict(iEntity))
+ return;
+
+ char sClassname2[64];
+ GetEdictClassname(iEntity, sClassname2, sizeof(sClassname2))
+
+ if (StrEqual(sClassname2, "func_button") || StrEqual(sClassname2, "func_rot_button"))
+ SDKHook(iEntity, SDKHook_Use, OnPressed);
+}
+
+//----------------------------------------------------------------------------------------------------
+// Purpose:
+//----------------------------------------------------------------------------------------------------
+public Action OnPressed(int iEntity, int iActivator, int iCaller, UseType type, float fValue)
+{
+ if (IsValidClient(iActivator))
+ {
+ char sSteamID[32];
+ if (!GetClientAuthId(iActivator, AuthId_Steam2, sSteamID, sizeof(sSteamID)))
+ {
+ sSteamID = "UNKNOWN";
+ }
+ char sTargetname[128];
+ GetEntPropString(iEntity, Prop_Data, "m_iName", sTargetname, sizeof(sTargetname));
+
+ for(int i = 1; i <= MaxClients; i++)
+ {
+ if(IsValidClient(i) && CheckCommandAccess(i, "", ADMFLAG_GENERIC))
+ PrintToConsole(i, "%N (%s) Pressed button: %s", iActivator, sSteamID, sTargetname);
+ }
+ }
+ return Plugin_Continue;
+}
+
+//----------------------------------------------------------------------------------------------------
+// Purpose:
+//----------------------------------------------------------------------------------------------------
+stock int IsValidClient(int client, bool nobots = true)
+{
+ if (client <= 0 || client > MaxClients || !IsClientConnected(client) || (nobots && IsFakeClient(client)))
+ return false;
+
+ return IsClientInGame(client);
+}
diff --git a/CSGOMovementUnlocker/gamedata/CSGOMovementUnlocker.games.txt b/CSGOMovementUnlocker/gamedata/CSGOMovementUnlocker.games.txt
new file mode 100644
index 0000000..c811587
--- /dev/null
+++ b/CSGOMovementUnlocker/gamedata/CSGOMovementUnlocker.games.txt
@@ -0,0 +1,43 @@
+"Games"
+{
+ "csgo"
+ {
+ "Addresses"
+ {
+ "WalkMoveMaxSpeed"
+ {
+ "windows"
+ {
+ "signature" "CGameMovement::WalkMove"
+ }
+ "linux"
+ {
+ "signature" "CGameMovement::WalkMove"
+ }
+ }
+ }
+
+ "Signatures"
+ {
+ "CGameMovement::WalkMove"
+ {
+ "library" "server"
+ "windows" "\xF3\x0F\x59\xC0\xF3\x0F\x59\xD2\xF3\x0F\x59\xC9\xF3\x0F\x58\xD0\xF3\x0F\x58\xD1\x0F\x28\xC2\xF3\x0F\x51\xC0\xF3\x0F\x5E\xD8"
+ "linux" "\xF3\x0F\x10\xF0\x0F\x28\xC6\xF3\x0F\x51\xC6\xF3\x0F\x5E\xE8"
+ }
+ }
+ "Offsets"
+ {
+ "CappingOffset"
+ {
+ "windows" "31"
+ "linux" "27"
+ }
+ "PatchBytes"
+ {
+ "windows" "42"
+ "linux" "15"
+ }
+ }
+ }
+}
diff --git a/CSGOMovementUnlocker/scripting/CSGOMovementUnlocker.sp b/CSGOMovementUnlocker/scripting/CSGOMovementUnlocker.sp
new file mode 100644
index 0000000..fe0c578
--- /dev/null
+++ b/CSGOMovementUnlocker/scripting/CSGOMovementUnlocker.sp
@@ -0,0 +1,85 @@
+#pragma semicolon 1
+#include
+#include
+
+new Address:g_iPatchAddress;
+new g_iPatchRestore[100];
+new g_iPatchRestoreBytes;
+
+#define PLUGIN_VERSION "1.0"
+
+public Plugin:myinfo =
+{
+ name = "CS:GO Movement Unlocker",
+ author = "Peace-Maker",
+ description = "Removes max speed limitation from players on the ground. Feels like CS:S.",
+ version = PLUGIN_VERSION,
+ url = "http://www.wcfan.de/"
+}
+
+public OnPluginStart()
+{
+ // Load the gamedata file.
+ new Handle:hGameConf = LoadGameConfigFile("CSGOMovementUnlocker.games");
+ if(hGameConf == INVALID_HANDLE)
+ SetFailState("Can't find CSGOMovementUnlocker.games.txt gamedata.");
+
+ // Get the address near our patch area inside CGameMovement::WalkMove
+ new Address:iAddr = GameConfGetAddress(hGameConf, "WalkMoveMaxSpeed");
+ if(iAddr == Address_Null)
+ {
+ CloseHandle(hGameConf);
+ SetFailState("Can't find WalkMoveMaxSpeed address.");
+ }
+
+ // Get the offset from the start of the signature to the start of our patch area.
+ new iCapOffset = GameConfGetOffset(hGameConf, "CappingOffset");
+ if(iCapOffset == -1)
+ {
+ CloseHandle(hGameConf);
+ SetFailState("Can't find CappingOffset in gamedata.");
+ }
+
+ // Move right in front of the instructions we want to NOP.
+ iAddr += Address:iCapOffset;
+ g_iPatchAddress = iAddr;
+
+ // Get how many bytes we want to NOP.
+ g_iPatchRestoreBytes = GameConfGetOffset(hGameConf, "PatchBytes");
+ if(g_iPatchRestoreBytes == -1)
+ {
+ CloseHandle(hGameConf);
+ SetFailState("Can't find PatchBytes in gamedata.");
+ }
+ CloseHandle(hGameConf);
+
+ //PrintToServer("CGameMovement::WalkMove VectorScale(wishvel, mv->m_flMaxSpeed/wishspeed, wishvel); ... at address %x", g_iPatchAddress);
+
+ new iData;
+ for(new i=0;i
+#include
+#include
+#include
+
+#include
+
+//#define Debug
+
+methodmap CPlayer < Basic {
+ public CPlayer(int client) {
+ Basic myclass = new Basic();
+ myclass.SetInt("iClient", client);
+ myclass.SetHandle("hEntities", new ArrayList(1));
+ myclass.SetBool("bForceRise", false);
+ return view_as(myclass);
+ }
+
+ property int iClient {
+ public get() {
+ return this.GetInt("iClient");
+ }
+ public set(int value) {
+ this.SetInt("iClient", value);
+ }
+ }
+
+ property ArrayList hEntities {
+ public get() {
+ return view_as(this.GetHandle("hEntities"));
+ }
+ public set(ArrayList value) {
+ this.SetHandle("hEntities", value);
+ }
+ }
+
+ property bool bForceRise {
+ public get() {
+ return this.GetBool("bForceRise");
+ }
+ public set(bool value) {
+ this.SetBool("bForceRise", value);
+ }
+ }
+
+ public void Dispose(bool disposemembers = true) {
+ if (disposemembers) {
+ ArrayList hEntities = this.hEntities;
+ delete hEntities;
+ }
+ delete this;
+ }
+}
+
+enum {
+ SF_TRIGGER_ALLOW_CLIENTS = 0x01, // Players can fire this trigger
+ SF_TRIGGER_ALLOW_NPCS = 0x02, // NPCS can fire this trigger
+ SF_TRIGGER_ALLOW_PUSHABLES = 0x04, // Pushables can fire this trigger
+ SF_TRIGGER_ALLOW_PHYSICS = 0x08, // Physics objects can fire this trigger
+ SF_TRIGGER_ONLY_PLAYER_ALLY_NPCS = 0x10, // *if* NPCs can fire this trigger, this flag means only player allies do so
+ SF_TRIGGER_ONLY_CLIENTS_IN_VEHICLES = 0x20, // *if* Players can fire this trigger, this flag means only players inside vehicles can
+ SF_TRIGGER_ALLOW_ALL = 0x40, // Everything can fire this trigger EXCEPT DEBRIS!
+ SF_TRIGGER_ONLY_CLIENTS_OUT_OF_VEHICLES = 0x200, // *if* Players can fire this trigger, this flag means only players outside vehicles can
+ SF_TRIG_PUSH_ONCE = 0x80, // trigger_push removes itself after firing once
+ SF_TRIG_PUSH_AFFECT_PLAYER_ON_LADDER = 0x100, // if pushed object is player on a ladder, then this disengages them from the ladder (HL2only)
+ SF_TRIG_TOUCH_DEBRIS = 0x400, // Will touch physics debris objects
+ SF_TRIGGER_ONLY_NPCS_IN_VEHICLES = 0x800, // *if* NPCs can fire this trigger, only NPCs in vehicles do so (respects player ally flag too)
+ SF_TRIGGER_PUSH_USE_MASS = 0x1000, // Correctly account for an entity's mass (CTriggerPush::Touch used to assume 100Kg)
+};
+
+Handle hTriggerPushPassesTriggerFilters;
+
+ConVar g_hTriggerPushGround_Scale;
+ConVar g_hTriggerPushRising_Scale;
+ConVar g_hTriggerPushLagFixEnable;
+float g_fTriggerPushGround_Scale;
+float g_fTriggerPushRising_Scale;
+bool g_bTriggerPushLagFixEnable;
+
+int iOffsVelocity;
+int iOffsAbsVel;
+int iOffsBaseVel;
+
+CPlayer g_aPlayers[MAXPLAYERS+1];
+
+bool bLateLoad = false;
+
+public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max) {
+ RegPluginLibrary("CSGOPushFix");
+
+ bLateLoad = late;
+ return APLRes_Success;
+}
+
+public Plugin myinfo = {
+ name = "Trigger_push Fix",
+ author = "uuz + PŠΣ™ SHUFEN + Based from Mev, George, & Blacky | Slidy & rio Edit",
+ description = "Removes lag from trigger_push and fixes of velocity bug",
+ version = "4.2",
+ url = "http://bbs.zombieden.cn/ & https://possession.jp & http://steamcommunity.com/id/mevv/ & http://steamcommunity.com/profiles/76561197975854215/ & http://steamcommunity.com/id/blaackyy/"
+}
+
+public void OnPluginStart() {
+ iOffsVelocity = FindSendPropInfo("CBasePlayer", "m_vecVelocity[0]");
+ if (iOffsVelocity == -1) {
+ SetFailState("[Trigger_push Fix] Could not find CBasePlayer::m_vecVelocity[0]");
+ }
+
+ Handle hGameConf = LoadGameConfigFile("CSGOPushFix.games");
+
+ StartPrepSDKCall(SDKCall_Entity);
+ PrepSDKCall_SetFromConf(hGameConf, SDKConf_Virtual, "CBaseTrigger::PassesTriggerFilters");
+ PrepSDKCall_SetReturnInfo(SDKType_Bool, SDKPass_Plain);
+ PrepSDKCall_AddParameter(SDKType_CBaseEntity, SDKPass_Pointer);
+ hTriggerPushPassesTriggerFilters = EndPrepSDKCall();
+
+ delete hGameConf;
+
+ g_hTriggerPushGround_Scale = CreateConVar("triggerpushfix_ground_scale", "1.0", "Scale trigger_push Ground.", FCVAR_NOTIFY, true, 0.0, true, 1.0);
+ g_hTriggerPushRising_Scale = CreateConVar("triggerpushfix_ground_rising", "1.0", "Scale trigger_push Rising.", FCVAR_NOTIFY, true, 0.0, true, 1.0);
+ g_hTriggerPushLagFixEnable = CreateConVar("triggerpushlagfix_enable", "1", "Enables trigger push fix.", FCVAR_NOTIFY, true, 0.0, true, 1.0);
+ g_hTriggerPushGround_Scale.AddChangeHook(OnConVarChanged);
+ g_hTriggerPushRising_Scale.AddChangeHook(OnConVarChanged);
+ g_hTriggerPushLagFixEnable.AddChangeHook(OnConVarChanged);
+
+ if (bLateLoad) {
+ for (int client = 1; client <= MaxClients; client++) {
+ if (IsClientConnected(client)) {
+ if (IsClientInGame(client))
+ OnClientPutInServer(client);
+ }
+ }
+ int entity = INVALID_ENT_REFERENCE;
+ while ((entity = FindEntityByClassname(entity, "trigger_push")) != INVALID_ENT_REFERENCE) {
+ OnEntityCreated(entity, "trigger_push");
+ }
+ }
+}
+
+public void OnConfigsExecuted() {
+ iOffsAbsVel = FindDataMapInfo(0, "m_vecAbsVelocity");
+ if (iOffsAbsVel == -1)
+ SetFailState("[Trigger_push Fix] Could not find m_vecAbsVelocity");
+
+ iOffsBaseVel = FindDataMapInfo(0, "m_vecBaseVelocity");
+ if (iOffsBaseVel == -1)
+ SetFailState("[Trigger_push Fix] Could not find m_vecBaseVelocity");
+
+ g_fTriggerPushGround_Scale = g_hTriggerPushGround_Scale.FloatValue;
+ g_fTriggerPushRising_Scale = g_hTriggerPushRising_Scale.FloatValue;
+ g_bTriggerPushLagFixEnable = g_hTriggerPushLagFixEnable.BoolValue;
+}
+
+public void OnConVarChanged(ConVar convar, const char[] oldValue, const char[] newValue) {
+ if (convar == g_hTriggerPushGround_Scale)
+ g_fTriggerPushGround_Scale = StringToFloat(newValue);
+ else if (convar == g_hTriggerPushRising_Scale)
+ g_fTriggerPushRising_Scale = StringToFloat(newValue);
+ else if (convar == g_hTriggerPushLagFixEnable)
+ g_bTriggerPushLagFixEnable = view_as(StringToInt(newValue));
+}
+
+public void OnClientPutInServer(int client) {
+ if (!g_aPlayers[client])
+ g_aPlayers[client] = new CPlayer(client);
+}
+
+public void OnClientDisconnect(int client) {
+ if (g_aPlayers[client]) {
+ g_aPlayers[client].Dispose();
+ g_aPlayers[client] = null;
+ }
+}
+
+public void OnEntityCreated(int entity, const char[] classname) {
+ if (StrEqual(classname, "trigger_push", false)) {
+ SDKHook(entity, SDKHook_SpawnPost, OnEntitySpawn_Post);
+ } else {
+ for (int i = 1; i <= MaxClients; i++)
+ if (g_aPlayers[i]) {
+ ArrayList hEntities = g_aPlayers[i].hEntities;
+ int index = hEntities.FindValue(entity);
+ if (index > -1)
+ hEntities.Erase(index);
+ }
+ }
+}
+
+public void OnEntityDestroyed(int entity) {
+ for (int i = 1; i <= MaxClients; i++)
+ if (g_aPlayers[i]) {
+ ArrayList hEntities = g_aPlayers[i].hEntities;
+ int index = hEntities.FindValue(entity);
+ if (index > -1)
+ hEntities.Erase(index);
+ }
+}
+
+public void OnEntitySpawn_Post(int entity) {
+ float m_vecPushDir[3];
+ GetEntPropVector(entity, Prop_Data, "m_vecPushDir", m_vecPushDir);
+
+ float fPushSpeed = GetEntPropFloat(entity, Prop_Data, "m_flSpeed");
+ if (fPushSpeed > 250) {
+ if (RoundToNearest(m_vecPushDir[2]) != 0) {
+ if (g_fTriggerPushRising_Scale != 1.0)
+ SetEntPropFloat(entity, Prop_Data, "m_flSpeed", fPushSpeed * g_fTriggerPushRising_Scale);
+ } else {
+ if (g_fTriggerPushGround_Scale != 1.0)
+ SetEntPropFloat(entity, Prop_Data, "m_flSpeed", fPushSpeed * g_fTriggerPushGround_Scale);
+ }
+ }
+
+ SDKHook(entity, SDKHook_Touch, OnTouch);
+ SDKHook(entity, SDKHook_StartTouch, StartTouch);
+ SDKHook(entity, SDKHook_EndTouch, EndTouch);
+}
+
+public Action OnTouch(int entity, int other) {
+ if (g_bTriggerPushLagFixEnable && 0 < other <= MaxClients) {
+ if (!PassesTriggerFilters(entity, other)) {
+ #if defined Debug
+ PrintToChatAll("push not pass: %i => Client %N", entity, other);
+ #endif
+ return Plugin_Handled;
+ }
+
+ bool bDisabled = view_as(GetEntProp(entity, Prop_Data, "m_bDisabled"));
+ int iSpawnflags = GetEntProp(entity, Prop_Data, "m_spawnflags");
+
+ // dont move player if they're on ladder
+ if (GetEntityMoveType(other) == MOVETYPE_LADDER && !(iSpawnflags & SF_TRIG_PUSH_AFFECT_PLAYER_ON_LADDER)) {
+ return Plugin_Handled;
+ }
+
+ if (iSpawnflags == 1 && !bDisabled) {
+ #if defined Debug
+ float fGameTime = GetGameTime();
+ PrintToChatAll("push pass: %i => Client %N @%.2f", entity, other, fGameTime);
+ #endif
+ DoPush(other, (iSpawnflags & SF_TRIG_PUSH_ONCE) ? entity : -1);
+
+ return Plugin_Handled;
+ }
+ }
+ return Plugin_Continue;
+}
+
+public Action StartTouch(int entity, int other) {
+ if (g_bTriggerPushLagFixEnable && 0 < other <= MaxClients && PassesTriggerFilters(entity, other)) {
+ if (g_aPlayers[other]) {
+ if (IsClientOnObject(other))
+ g_aPlayers[other].bForceRise = true;
+ ArrayList hEntities = g_aPlayers[other].hEntities;
+ int index = hEntities.FindValue(entity);
+ if (index == -1)
+ hEntities.Push(entity);
+ }
+ #if defined Debug
+ PrintToChatAll("start touch: %i => Client %N [HammerID: %i]", entity, other, GetHammerIdOfEntity(entity));
+ #endif
+ }
+ return Plugin_Continue;
+}
+
+public Action EndTouch(int entity, int other) {
+ if (g_bTriggerPushLagFixEnable && 0 < other <= MaxClients && PassesTriggerFilters(entity, other)) {
+ if (g_aPlayers[other]) {
+ ArrayList hEntities = g_aPlayers[other].hEntities;
+ int index = hEntities.FindValue(entity);
+ if (index > -1)
+ hEntities.Erase(index);
+ }
+ #if defined Debug
+ PrintToChatAll("end touch: %i => Client %N [HammerID: %i]", entity, other, GetHammerIdOfEntity(entity));
+ #endif
+ }
+ return Plugin_Continue;
+}
+
+void DoPush(int other, int onceent = -1) {
+ float vecAbsDirTotal[3];
+
+ if (g_aPlayers[other]) {
+ ArrayList hEntities = g_aPlayers[other].hEntities;
+ for (int i = 0; i < hEntities.Length; i++) {
+ int entity = hEntities.Get(i);
+
+ float m_vecPushDir[3], angRotation[3], fPushSpeed;
+
+ fPushSpeed = GetEntPropFloat(entity, Prop_Data, "m_flSpeed");
+ GetEntPropVector(entity, Prop_Data, "m_vecPushDir", m_vecPushDir);
+
+ FindEntityParent_Main(entity, angRotation, false);
+
+ // Rotate vector according to world
+ float sr, sp, sy, cr, cp, cy;
+ float matrix[3][4];
+
+ SinCos(DegToRad(angRotation[1]), sy, cy);
+ SinCos(DegToRad(angRotation[0]), sp, cp);
+ SinCos(DegToRad(angRotation[2]), sr, cr);
+
+ matrix[0][0] = cp*cy;
+ matrix[1][0] = cp*sy;
+ matrix[2][0] = -sp;
+
+ float crcy = cr*cy;
+ float crsy = cr*sy;
+ float srcy = sr*cy;
+ float srsy = sr*sy;
+
+ matrix[0][1] = sp*srcy-crsy;
+ matrix[1][1] = sp*srsy+crcy;
+ matrix[2][1] = sr*cp;
+
+ matrix[0][2] = (sp*crcy+srsy);
+ matrix[1][2] = (sp*crsy-srcy);
+ matrix[2][2] = cr*cp;
+
+ matrix[0][3] = angRotation[0];
+ matrix[1][3] = angRotation[1];
+ matrix[2][3] = angRotation[2];
+
+ float vecAbsDir[3];
+ vecAbsDir[0] = m_vecPushDir[0]*matrix[0][0] + m_vecPushDir[1]*matrix[0][1] + m_vecPushDir[2]*matrix[0][2];
+ vecAbsDir[1] = m_vecPushDir[0]*matrix[1][0] + m_vecPushDir[1]*matrix[1][1] + m_vecPushDir[2]*matrix[1][2];
+ vecAbsDir[2] = m_vecPushDir[0]*matrix[2][0] + m_vecPushDir[1]*matrix[2][1] + m_vecPushDir[2]*matrix[2][2];
+
+ ScaleVector(vecAbsDir, fPushSpeed);
+
+ AddVectors(vecAbsDirTotal, vecAbsDir, vecAbsDirTotal);
+ }
+ }
+
+ float newVelocity[3];
+
+ if (onceent != -1) {
+ for (int x = 0; x < 3; x++) {
+ newVelocity[x] = GetEntDataFloat(other, iOffsVelocity + (x * 4));
+ }
+ AddVectors(newVelocity, vecAbsDirTotal, newVelocity);
+
+ SetEntDataVector(other, iOffsAbsVel, newVelocity);
+ SetEntDataVector(other, iOffsBaseVel, NULL_VECTOR);
+
+ if (vecAbsDirTotal[2] > 0.0) {
+ SetEntPropEnt(other, Prop_Data, "m_hGroundEntity", -1);
+ }
+
+ AcceptEntityInput(onceent, "Kill"); // remove the trigger so it only applies once
+
+ return;
+ }
+
+ // Apply the base velocity directly to abs velocity
+ for (int x = 0; x < 3; x++) {
+ newVelocity[x] = GetEntDataFloat(other, iOffsVelocity + (x * 4));
+ }
+
+ newVelocity[2] += vecAbsDirTotal[2] * GetTickInterval() * GetEntPropFloat(other, Prop_Data, "m_flLaggedMovementValue"); // frametime = tick_interval * laggedmovementvalue
+
+ if (g_aPlayers[other].bForceRise) {
+ if (IsClientOnObject(other) && 0.0 < newVelocity[2] <= 250.0) {
+ newVelocity[2] = 250.1;
+ #if defined Debug
+ PrintToChatAll("force rise: Client %N", other);
+ #endif
+ }
+ g_aPlayers[other].bForceRise = false;
+ }
+
+ SetEntDataVector(other, iOffsAbsVel, newVelocity);
+ SetEntDataVector(other, iOffsBaseVel, NULL_VECTOR);
+
+ // apply x, y as a base velocity so we travel at constant speed on conveyors
+ // Remove the base velocity z height so abs velocity can do it and add old base velocity if there is any
+ vecAbsDirTotal[2] = 0.0;
+
+ if (GetEntityFlags(other) & FL_BASEVELOCITY) {
+ float vecBaseVel[3];
+ GetEntDataVector(other, iOffsBaseVel, vecBaseVel);
+ AddVectors(vecAbsDirTotal, vecBaseVel, vecAbsDirTotal);
+ }
+
+ SetEntDataVector(other, iOffsBaseVel, vecAbsDirTotal);
+ SetEntityFlags(other, GetEntityFlags(other) | FL_BASEVELOCITY);
+}
+
+stock int FindEntityParent_Main(int entity, float Ang[3], bool inloop) {
+ int TempEntity;
+ float TempAng[3];
+
+ if (!inloop)
+ GetEntPropVector(entity, Prop_Data, "m_angRotation", Ang);
+
+ TempEntity = GetEntPropEnt(entity, Prop_Data, "m_hParent");
+ if (TempEntity == -1) {
+ if (!inloop)
+ return -1;
+ else
+ return entity;
+ }
+
+ GetEntPropVector(TempEntity, Prop_Data, "m_angRotation", TempAng);
+ AddVectors(Ang, TempAng, Ang);
+
+ if (Ang[1] > 360.0)
+ Ang[1] -= 360.0;
+
+ return FindEntityParent_Main(TempEntity, Ang, true);
+}
+
+stock void SinCos(float radians, float &sine, float &cosine) {
+ sine = Sine(radians);
+ cosine = Cosine(radians);
+}
+
+/**
+ * Return whether a client is standing on an object
+ *
+ * @param Client index
+ * @return True if client is standing on an object. False otherwise.
+ */
+stock bool IsClientOnObject(int client) {
+ return GetEntPropEnt(client, Prop_Send, "m_hGroundEntity") > -1 ? true : false;
+}
+
+stock int GetHammerIdOfEntity(int entity) {
+ if (IsValidEntity(entity)) {
+ return GetEntProp(entity, Prop_Data, "m_iHammerID");
+ }
+ return -1;
+}
+
+stock bool PassesTriggerFilters(int entity, int client) {
+ return SDKCall(hTriggerPushPassesTriggerFilters, entity, client);
+}
\ No newline at end of file
diff --git a/CSGO_ParticleSystemFix/gamedata/CSGO_ParticleSystemFix.games.txt b/CSGO_ParticleSystemFix/gamedata/CSGO_ParticleSystemFix.games.txt
new file mode 100644
index 0000000..de9803c
--- /dev/null
+++ b/CSGO_ParticleSystemFix/gamedata/CSGO_ParticleSystemFix.games.txt
@@ -0,0 +1,93 @@
+"Games"
+{
+ "#default"
+ {
+ "#supported"
+ {
+ "game" "csgo"
+ }
+
+ "Keys"
+ {
+ "VEngineServerStringTable" "VEngineServerStringTable001"
+ }
+
+ "Offsets"
+ {
+ "CServer::OS"
+ {
+ "windows" "1"
+ "linux" "2"
+ }
+ "CParticleSystemDictionary::Count" // Str: "PrecacheStandardParticleSystems()"
+ {
+ "windows" "38"
+ "linux" "38"
+ }
+ // @link https://github.com/VSES/SourceEngine2007/blob/43a5c90a5ada1e69ca044595383be67f40b33c61/src_main/particles/particles.cpp#L2659
+ "CNetworkStringTableContainer::FindTable"
+ {
+ "windows" "3"
+ "linux" "4"
+ }
+ }
+
+ // Sigs from the lib ( https://forums.alliedmods.net/showthread.php?t=309074 )
+ // You can update them only by yourself using tutorial in the link
+ "Signatures"
+ {
+ "CreateInterface"
+ {
+ "library" "engine"
+ "windows" "@CreateInterface"
+ "linux" "@CreateInterface"
+ "mac" "@CreateInterface"
+ }
+
+ /*
+ * Info: Every custom particle precached during a map is not removed from precache table on the map end.
+ * Then, if a lot of maps that uses custom particles are running in my server the precache table will be filled
+ * and the custom particles used on the next maps will not show right but erros will appear in their place.
+ */
+ "CParticleSystemDictionary::~CParticleSystemDictionary" // Str: "CParticleSystemMgr::InitAttributeTable has an out-of-date attribute list! (element %d not set up)\n" | "CParticleSystemMgr::InitAttributeTable" -> "CParticleSystemMgr::CParticleSystemMgr" -> "CParticleSystemMgr::~CParticleSystemMgr"
+ {
+ "library" "server"
+ "windows" "\x55\x8B\xEC\x51\x56\x57\x8B\xF9\x33\xF6\x8B\x47\x58"
+ "linux" "\x55\x89\xE5\x57\x56\x53\x83\xEC\x2C\x8B\x7D\x08\x8B\x47\x58\x85\xC0"
+ }
+ "CParticleSystemDefinition::ParseChildren" // Str: "DmeParticleSystemDefinition" and "children" and "preventNameBasedLookup"
+ {
+ "library" "server"
+ "windows" "\x55\x8B\xEC\x83\xEC\x20\x53\x56\x57\x8B\xF9\x51"
+ "linux" "\x55\x89\xE5\x57\x56\x53\x83\xEC\x2C\x8B\x45\x0C\xC7\x44\x24\x04"
+ }
+ "CNetworkStringTable::DeleteAllStrings" // Str: "___clientsideitemsplaceholder0___"
+ {
+ "library" "engine"
+ "windows" "\x56\x8B\xF1\x57\x8B\x4E\x40"
+ "linux" "\x55\x89\xE5\x53\x83\xEC\x14\x8B\x5D\x08\x8B\x43\x40"
+ }
+ }
+
+ // Addr from the lib ( https://forums.alliedmods.net/showthread.php?t=309074 )
+ // You can update them only by yourself using tutorial in the link
+ "Addresses"
+ {
+ "m_pParticleSystemDictionary"
+ {
+ "signature" "CParticleSystemDefinition::ParseChildren"
+ "linux"
+ {
+ "read" "375"
+ "read" "0"
+ "read" "140"
+ }
+ "windows"
+ {
+ "read" "401"
+ "read" "0"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/CSGO_ParticleSystemFix/scripting/CSGO_ParticleSystemFix.sp b/CSGO_ParticleSystemFix/scripting/CSGO_ParticleSystemFix.sp
new file mode 100644
index 0000000..38ee0ec
--- /dev/null
+++ b/CSGO_ParticleSystemFix/scripting/CSGO_ParticleSystemFix.sp
@@ -0,0 +1,468 @@
+#pragma semicolon 1
+#pragma newdecls required
+
+#include
+
+#define PLATFORM_LINE_LENGTH 1024
+#define NORMAL_LINE_LENGTH 256
+#define PLUGIN_CONFIG "CSGO_ParticleSystemFix.games"
+#define PLUGIN_LOGFILE "logs/CSGO_ParticleSystemFix.log"
+
+/**
+ * @section List of operation systems.
+ **/
+enum EngineOS {
+ OS_Unknown,
+ OS_Windows,
+ OS_Linux
+};
+
+/**
+ * @section Struct of operation types for server arrays.
+ **/
+enum struct ServerData
+{
+ /* Internal Particles */
+ ArrayList Particles;
+
+ /* OS */
+ EngineOS Platform;
+
+ /* Gamedata */
+ Handle Config;
+}
+/**
+ * @endsection
+ **/
+
+ServerData gServerData;
+
+/**
+ * Variables to store SDK calls handlers.
+ **/
+Handle hSDKCallDestructorParticleDictionary;
+Handle hSDKCallTableDeleteAllStrings;
+
+/**
+ * Variables to store virtual SDK offsets.
+ **/
+Address pParticleSystemDictionary;
+int ParticleSystem_Count;
+
+char g_sLogPath[PLATFORM_MAX_PATH];
+
+public Plugin myinfo = {
+ name = "[CS:GO] Particle System Fix",
+ description = "",
+ author = "gubka && PŠΣ™ SHUFEN",
+ version = "1.0",
+ url = "https://forums.alliedmods.net/showthread.php?t=313951 && https://possession.jp"
+};
+
+public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max) {
+ RegPluginLibrary("CSGO_ParticleSystemFix");
+ CreateNative("UncacheAllParticleSystems", Native_UncacheAllParticleSystems);
+ return APLRes_Success;
+}
+
+public int Native_UncacheAllParticleSystems(Handle plugin, int numParams) {
+ ParticlesOnPurge();
+}
+
+/**
+ * @brief Particles module init function.
+ **/
+public void OnPluginStart() {
+ BuildPath(Path_SM, g_sLogPath, sizeof(g_sLogPath), PLUGIN_LOGFILE);
+
+ if (GetEngineVersion() != Engine_CSGO) {
+ LogToFileEx(g_sLogPath, "[System Init] Engine error: This plugin only works on Counter-Strike: Global Offensive.");
+ return;
+ }
+
+ gServerData.Config = LoadGameConfigFile(PLUGIN_CONFIG);
+
+ /*_________________________________________________________________________________________________________________________________________*/
+
+ // Starts the preparation of an SDK call
+ StartPrepSDKCall(SDKCall_Raw);
+ PrepSDKCall_SetFromConf(gServerData.Config, SDKConf_Signature, "CParticleSystemDictionary::~CParticleSystemDictionary");
+
+ // Validate call
+ if ((hSDKCallDestructorParticleDictionary = EndPrepSDKCall()) == null) {
+ // Log failure
+ LogToFileEx(g_sLogPath, "[GameData Validation] Failed to load SDK call \"CParticleSystemDictionary::~CParticleSystemDictionary\". Update signature in \"%s\"", PLUGIN_CONFIG);
+ return;
+ }
+
+ /*_________________________________________________________________________________________________________________________________________*/
+
+ // Starts the preparation of an SDK call
+ StartPrepSDKCall(SDKCall_Raw);
+ PrepSDKCall_SetFromConf(gServerData.Config, SDKConf_Signature, "CNetworkStringTable::DeleteAllStrings");
+
+ // Validate call
+ if ((hSDKCallTableDeleteAllStrings = EndPrepSDKCall()) == null) {
+ // Log failure
+ LogToFileEx(g_sLogPath, "[GameData Validation] Failed to load SDK call \"CNetworkStringTable::DeleteAllStrings\". Update signature in \"%s\"", PLUGIN_CONFIG);
+ return;
+ }
+
+ /*_________________________________________________________________________________________________________________________________________*/
+
+ // Load other offsets
+ fnInitGameConfAddress(gServerData.Config, pParticleSystemDictionary, "m_pParticleSystemDictionary");
+ fnInitGameConfOffset(gServerData.Config, ParticleSystem_Count, "CParticleSystemDictionary::Count");
+
+ /*_________________________________________________________________________________________________________________________________________*/
+
+ //fnInitGameConfOffset(gServerData.Config, view_as(gServerData.Platform), "CServer::OS");
+ LogToFileEx(g_sLogPath, "[System Init] Loaded \"Particle System Fix\"");
+}
+
+public void OnMapStart() {
+ // Precache CS:GO internal particles
+ ParticlesOnLoad();
+
+ // Load map particles
+ LoadMapExtraFiles();
+}
+
+public void OnMapEnd() {
+ ParticlesOnPurge();
+}
+
+/**
+ * @brief Particles module load function.
+ **/
+void ParticlesOnLoad() {
+ // Initialize buffer char
+ static char sBuffer[PLATFORM_LINE_LENGTH];
+
+ // Validate that particles wasn't precache yet
+ bool bSave = LockStringTables(false);
+ Address pTable = CNetworkStringTableContainer_FindTable("ParticleEffectNames");
+ int iCount = LoadFromAddress(pParticleSystemDictionary + view_as(ParticleSystem_Count), NumberType_Int16);
+ if (pTable != Address_Null && !iCount) { /// Validate that table is exist and it empty
+ // Opens the file
+ File hFile = OpenFile("particles/particles_manifest.txt", "rt", true);
+
+ // If doesn't exist stop
+ if (hFile == null) {
+ LogToFileEx(g_sLogPath, "[Config Validation] Error opening file: \"particles/particles_manifest.txt\"");
+ return;
+ }
+
+ // Read lines in the file
+ while (hFile.ReadLine(sBuffer, sizeof(sBuffer))) {
+ // Checks if string has correct quotes
+ int iQuotes = CountCharInString(sBuffer, '"');
+ if (iQuotes == 4) {
+ // Trim string
+ TrimString(sBuffer);
+
+ // Copy value string
+ strcopy(sBuffer, sizeof(sBuffer), sBuffer[strlen("\"file\"")]);
+
+ // Trim string
+ TrimString(sBuffer);
+
+ // Strips a quote pair off a string
+ StripQuotes(sBuffer);
+
+ // Precache model
+ int i = 0; if (sBuffer[i] == '!') i++;
+ PrecacheGeneric(sBuffer[i], true);
+ SDKCall(hSDKCallTableDeleteAllStrings, pTable); /// HACK~HACK
+ /// Clear tables after each file because some of them contains
+ /// huge amount of particles and we work around the limit
+ }
+ }
+
+ delete hFile;
+ }
+
+ // Initialize the table index
+ static int tableIndex = INVALID_STRING_TABLE;
+
+ // Validate table
+ if (tableIndex == INVALID_STRING_TABLE) {
+ // Searches for a string table
+ tableIndex = FindStringTable("ParticleEffectNames");
+ }
+
+ // If array hasn't been created, then create
+ if (gServerData.Particles == null) {
+ // Initialize a particle list array
+ gServerData.Particles = CreateArray(NORMAL_LINE_LENGTH);
+
+ // i = table string
+ iCount = GetStringTableNumStrings(tableIndex);
+ for (int i = 0; i < iCount; i++) {
+ // Gets the string at a given index
+ ReadStringTable(tableIndex, i, sBuffer, sizeof(sBuffer));
+
+ // Push data into array
+ gServerData.Particles.PushString(sBuffer);
+ }
+ } else {
+ // i = particle name
+ iCount = gServerData.Particles.Length;
+ for (int i = 0; i < iCount; i++) {
+ // Gets the string at a given index
+ gServerData.Particles.GetString(i, sBuffer, sizeof(sBuffer));
+
+ // Push data into table
+ AddToStringTable(tableIndex, sBuffer);
+ }
+ }
+
+ /*
+ // Refresh tables
+ pTable = CNetworkStringTableContainer_FindTable("ExtraParticleFilesTable");
+ if (pTable != Address_Null) {
+ SDKCall(hSDKCallTableDeleteAllStrings, pTable);
+ }
+
+ pTable = CNetworkStringTableContainer_FindTable("genericprecache");
+ if (pTable != Address_Null) {
+ SDKCall(hSDKCallTableDeleteAllStrings, pTable);
+ }
+ */
+ LockStringTables(bSave);
+}
+
+void LoadMapExtraFiles() {
+ char sMapName[PLATFORM_MAX_PATH];
+ GetCurrentMap(sMapName, sizeof(sMapName));
+
+ LoadPerMapParticleManifest(sMapName);
+}
+
+void LoadPerMapParticleManifest(const char[] sMapName) {
+ KeyValues hKv = GetParticleManifestKv(sMapName);
+ if (hKv == null) {
+ return;
+ }
+
+ ParseParticleManifestKv(hKv, true, true);
+
+ delete hKv;
+}
+
+char sDirExt[][][] = { {
+ "particles/", "maps/", "particles/", "maps/"
+ }, {
+ "_manifest_override.txt", "_particles_override.txt", "_manifest.txt", "_particles.txt"
+ }
+};
+
+KeyValues GetParticleManifestKv(const char[] sMapName) {
+ char sFileName[PLATFORM_MAX_PATH];
+
+ for (int i = 0; i < sizeof(sDirExt[]); i++) {
+ Format(sFileName, sizeof(sFileName), "%s%s%s", sDirExt[0][i], sMapName, sDirExt[1][i]);
+ if (FileExists(sFileName, true)) {
+ if (FileExists(sFileName, false))
+ AddFileToDownloadsTable(sFileName);
+
+ return CreateManifestKv(sFileName);
+ }
+ }
+
+ return null;
+}
+
+KeyValues CreateManifestKv(const char[] sPath) {
+ KeyValues hKv = CreateKeyValues("particles_manifest");
+
+ //hKv.SetEscapeSequences(true);
+ if (hKv.ImportFromFile(sPath)) {
+ return hKv;
+ }
+
+ return null;
+}
+
+void ParseParticleManifestKv(KeyValues hKv, bool perMap = false, bool awayPreloads = false) {
+ char sPCF[PLATFORM_MAX_PATH];
+ if (hKv.GotoFirstSubKey(false))
+ do {
+ hKv.GetString(NULL_STRING, sPCF, sizeof(sPCF));
+ if (sPCF[0] == '\0')
+ continue;
+
+ bool preload = FindCharInString(sPCF, '!') == 0;
+ if (preload)
+ strcopy(sPCF, sizeof(sPCF), sPCF[1]);
+ if (FileExists(sPCF, true)) {
+ if (perMap && FileExists(sPCF, false))
+ AddFileToDownloadsTable(sPCF);
+ PrecacheGeneric(sPCF, awayPreloads || preload);
+ }
+ } while (hKv.GotoNextKey(false));
+}
+
+/**
+ * @brief Particles module purge function.
+ **/
+void ParticlesOnPurge() {
+ // @link https://github.com/VSES/SourceEngine2007/blob/43a5c90a5ada1e69ca044595383be67f40b33c61/src_main/particles/particles.cpp#L81
+ SDKCall(hSDKCallDestructorParticleDictionary, pParticleSystemDictionary);
+
+ /*_________________________________________________________________________________________________________________________________________*/
+
+ // Clear particles in the effect table
+ bool bSave = LockStringTables(false);
+ Address pTable = CNetworkStringTableContainer_FindTable("ParticleEffectNames");
+ if (pTable != Address_Null) {
+ SDKCall(hSDKCallTableDeleteAllStrings, pTable);
+ }
+
+ // Clear particles in the extra effect table
+ pTable = CNetworkStringTableContainer_FindTable("ExtraParticleFilesTable");
+ if (pTable != Address_Null) {
+ SDKCall(hSDKCallTableDeleteAllStrings, pTable);
+ }
+
+ // Clear particles in the generic precache table
+ pTable = CNetworkStringTableContainer_FindTable("genericprecache");
+ if (pTable != Address_Null) {
+ SDKCall(hSDKCallTableDeleteAllStrings, pTable);
+ }
+ LockStringTables(bSave);
+}
+
+stock Address CNetworkStringTableContainer_FindTable(const char[] tableName) {
+ Address pNetworkstringtable = GetNetworkStringTableAddr();
+ if (pNetworkstringtable == Address_Null)
+ return Address_Null;
+
+ static Handle hFindTable = INVALID_HANDLE;
+ if (hFindTable == INVALID_HANDLE) {
+ if (gServerData.Config == INVALID_HANDLE)
+ return Address_Null;
+
+ StartPrepSDKCall(SDKCall_Raw);
+ if (!PrepSDKCall_SetFromConf(gServerData.Config, SDKConf_Virtual, "CNetworkStringTableContainer::FindTable")) {
+ LogToFileEx(g_sLogPath, "[Find Table] Cant find the method CNetworkStringTableContainer::FindTable.");
+ return Address_Null;
+ }
+ PrepSDKCall_AddParameter(SDKType_String, SDKPass_Pointer); // tableName
+ PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain);
+ hFindTable = EndPrepSDKCall();
+ if (hFindTable == INVALID_HANDLE) {
+ LogToFileEx(g_sLogPath, "[Find Table] Method CNetworkStringTableContainer::FindTable was not loaded right.");
+ return Address_Null;
+ }
+ }
+
+ return SDKCall(hFindTable, pNetworkstringtable, tableName);
+}
+
+stock Address GetNetworkStringTableAddr() {
+ static Address pEngineServerStringTable = Address_Null;
+ if (pEngineServerStringTable == Address_Null) {
+ if (gServerData.Config == null)
+ return Address_Null;
+
+ char sInterfaceName[64];
+ if (!GameConfGetKeyValue(gServerData.Config, "VEngineServerStringTable", sInterfaceName, sizeof(sInterfaceName)))
+ strcopy(sInterfaceName, sizeof(sInterfaceName), "VEngineServerStringTable001");
+ pEngineServerStringTable = CreateEngineInterface(sInterfaceName);
+ }
+
+ return pEngineServerStringTable;
+}
+
+stock Address CreateEngineInterface(const char[] sInterfaceKey, Address ptr = Address_Null) {
+ static Handle hCreateInterface = null;
+ if (hCreateInterface == null) {
+ if (gServerData.Config == null)
+ return Address_Null;
+
+ StartPrepSDKCall(SDKCall_Static);
+ if (!PrepSDKCall_SetFromConf(gServerData.Config, SDKConf_Signature, "CreateInterface")) {
+ LogToFileEx(g_sLogPath, "[Create Engine Interface] Failed to get CreateInterface");
+ return Address_Null;
+ }
+
+ PrepSDKCall_AddParameter(SDKType_String, SDKPass_Pointer);
+ PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Plain, VDECODE_FLAG_ALLOWNULL);
+ PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain);
+
+ hCreateInterface = EndPrepSDKCall();
+ if (hCreateInterface == null) {
+ LogToFileEx(g_sLogPath, "[Create Engine Interface] Function CreateInterface was not loaded right.");
+ return Address_Null;
+ }
+ }
+
+ if (gServerData.Config == null)
+ return Address_Null;
+
+ char sInterfaceName[64];
+ if (!GameConfGetKeyValue(gServerData.Config, sInterfaceKey, sInterfaceName, sizeof(sInterfaceName)))
+ strcopy(sInterfaceName, sizeof(sInterfaceName), sInterfaceKey);
+
+ Address addr = SDKCall(hCreateInterface, sInterfaceName, ptr);
+ if (addr == Address_Null) {
+ LogToFileEx(g_sLogPath, "[Create Engine Interface] Failed to get pointer to interface %s(%s)", sInterfaceKey, sInterfaceName);
+ return Address_Null;
+ }
+
+ return addr;
+}
+
+/**
+ * @brief Finds the amount of all occurrences of a character in a string.
+ *
+ * @param sBuffer Input string buffer.
+ * @param cSymbol The character to search for.
+ * @return The amount of characters in the string, or -1 if the characters were not found.
+ */
+int CountCharInString(char[] sBuffer, char cSymbol) {
+ // Initialize index
+ int iCount;
+
+ // i = char index
+ int iLen = strlen(sBuffer);
+ for (int i = 0; i < iLen; i++) {
+ // Validate char
+ if (sBuffer[i] == cSymbol) {
+ // Increment amount
+ iCount++;
+ }
+ }
+
+ // Return amount
+ return iCount ? iCount : -1;
+}
+
+/**
+ * @brief Returns an offset value from a given config.
+ *
+ * @param gameConf The game config handle.
+ * @param iOffset An offset, or -1 on failure.
+ * @param sKey Key to retrieve from the offset section.
+ **/
+stock void fnInitGameConfOffset(Handle gameConf, int &iOffset, char[] sKey) {
+ // Validate offset
+ if ((iOffset = GameConfGetOffset(gameConf, sKey)) == -1) {
+ LogToFileEx(g_sLogPath, "[GameData Validation] Failed to get offset: \"%s\"", sKey);
+ }
+}
+
+/**
+ * @brief Returns an address value from a given config.
+ *
+ * @param gameConf The game config handle.
+ * @param pAddress An address, or null on failure.
+ * @param sKey Key to retrieve from the address section.
+ **/
+stock void fnInitGameConfAddress(Handle gameConf, Address &pAddress, char[] sKey) {
+ // Validate address
+ if ((pAddress = GameConfGetAddress(gameConf, sKey)) == Address_Null) {
+ LogToFileEx(g_sLogPath, "[GameData Validation] Failed to get address: \"%s\"", sKey);
+ }
+}
\ No newline at end of file
diff --git a/ChatTags/Instructions.txt b/ChatTags/Instructions.txt
new file mode 100644
index 0000000..8919c48
--- /dev/null
+++ b/ChatTags/Instructions.txt
@@ -0,0 +1,14 @@
+A few explanations:
+You will need to set up a database config in addons/sourcemod/configs/databases.cfg. There is a file (db info to add.txt) with example setups for either mysql or sqlite. The plugin supports both.
+
+ChatTags_blocked.cfg: Each line in this file is a separate sub-phrase that is blocked for all players who do not have the configured admin flag. e.g. if "owner" is a line, then "owner", "growner", or even "addwdaownercqdq" are blocked for anyone w/o the admin flag. (non-case sensitive).
+
+ChatTags_colors_csgo.cfg, ChatTags_colors_ins.cfg and ChatTags_colors.cfg: ChatTags_colors_csgo is for csgo, ChatTags_colors_ins.cfg is for insurgency, and the other is for all other games. No need to install the ones that dont apply. For ChatTags_colors.cfg, you can add as many hex colors as you want (http://www.colorpicker.com/ is a good site to make them). The cs:go one has no other colors available (well, there is ONE more, but it causes formatting issues, so it is hidden). The insurgency just has 7 colors at this time.
+
+Similar to the config files, there are translation files for several games. While it doesnt hurt to add them all, the only one that will be used is the one matching your game (e.g. scp.cstrike.phrases.txt for CS:S, or scp.csgo.phrases.txt for CS:GO).
+
+ChatTags_groups.cfg is the main "setup" config other than the cvar file that is generated. Be sure to read the info at the top for a full explanation of all the ways it can be used/configured.
+
+The web stuff is in its own folder and has further instructions inside.
+
+If you have more questions or any issues, let me know!
\ No newline at end of file
diff --git a/ChatTags/configs/ChatTags_blocked.cfg b/ChatTags/configs/ChatTags_blocked.cfg
new file mode 100644
index 0000000..aa6b5a2
--- /dev/null
+++ b/ChatTags/configs/ChatTags_blocked.cfg
@@ -0,0 +1,4 @@
+Founder
+Admin
+console
+Shop
\ No newline at end of file
diff --git a/ChatTags/configs/ChatTags_colors.cfg b/ChatTags/configs/ChatTags_colors.cfg
new file mode 100644
index 0000000..c088c7c
--- /dev/null
+++ b/ChatTags/configs/ChatTags_colors.cfg
@@ -0,0 +1,783 @@
+"Tag Colors"
+{
+ "1"
+ {
+ "name" "Alice Blue"
+ "color" "#F0F8FF"
+ }
+ "2"
+ {
+ "name" "Allies"
+ "color" "#4D7942"
+ }
+ "3"
+ {
+ "name" "Antique White"
+ "color" "#FAEBD7"
+ }
+ "4"
+ {
+ "name" "Aqua"
+ "color" "#00FFFF"
+ }
+ "5"
+ {
+ "name" "Aquamarine"
+ "color" "#7FFFD4"
+ }
+ "6"
+ {
+ "name" "Axis"
+ "color" "#FF4040"
+ }
+ "7"
+ {
+ "name" "Azure"
+ "color" "#007FFF"
+ }
+ "8"
+ {
+ "name" "Beige"
+ "color" "#F5F5DC"
+ }
+ "9"
+ {
+ "name" "Bisque"
+ "color" "#FFE4C4"
+ }
+ "10"
+ {
+ "name" "Black"
+ "color" "#000000"
+ }
+ "11"
+ {
+ "name" "Blanched Almond"
+ "color" "#FFEBCD"
+ }
+ "12"
+ {
+ "name" "Blue"
+ "color" "#99CCFF"
+ }
+ "13"
+ {
+ "name" "Blue Violet"
+ "color" "#8A2BE2"
+ }
+ "14"
+ {
+ "name" "Brown"
+ "color" "#A52A2A"
+ }
+ "15"
+ {
+ "name" "Burlywood"
+ "color" "#DEB887"
+ }
+ "16"
+ {
+ "name" "Cadet Blue"
+ "color" "#5F9EA0"
+ }
+ "17"
+ {
+ "name" "Chartreuse"
+ "color" "#7FFF00"
+ }
+ "18"
+ {
+ "name" "Chocolate"
+ "color" "#D2691E"
+ }
+ "19"
+ {
+ "name" "Community"
+ "color" "#70B04A"
+ }
+ "20"
+ {
+ "name" "Coral"
+ "color" "#FF7F50"
+ }
+ "21"
+ {
+ "name" "Cornflower Blue"
+ "color" "#6495ED"
+ }
+ "22"
+ {
+ "name" "Cornsilk"
+ "color" "#FFF8DC"
+ }
+ "23"
+ {
+ "name" "Crimson"
+ "color" "#DC143C"
+ }
+ "24"
+ {
+ "name" "Cyan"
+ "color" "#00FFFF"
+ }
+ "25"
+ {
+ "name" "Dark Blue"
+ "color" "#00008B"
+ }
+ "26"
+ {
+ "name" "Dark Cyan"
+ "color" "#008B8B"
+ }
+ "27"
+ {
+ "name" "Dark Golden Rod"
+ "color" "#B8860B"
+ }
+ "29"
+ {
+ "name" "Dark Grey"
+ "color" "#A9A9A9"
+ }
+ "30"
+ {
+ "name" "Dark Green"
+ "color" "#006400"
+ }
+ "31"
+ {
+ "name" "Dark Khaki"
+ "color" "#BDB76B"
+ }
+ "32"
+ {
+ "name" "Dark Magenta"
+ "color" "#8B008B"
+ }
+ "33"
+ {
+ "name" "Dark Olive Green"
+ "color" "#556B2F"
+ }
+ "34"
+ {
+ "name" "Dark Orange"
+ "color" "#FF8C00"
+ }
+ "35"
+ {
+ "name" "Dark Orchid"
+ "color" "#9932CC"
+ }
+ "36"
+ {
+ "name" "Dark Red"
+ "color" "#8B0000"
+ }
+ "37"
+ {
+ "name" "Dark Salmon"
+ "color" "#E9967A"
+ }
+ "38"
+ {
+ "name" "Dark Sea Green"
+ "color" "#8FBC8F"
+ }
+ "39"
+ {
+ "name" "Dark Slate Blue"
+ "color" "#483D8B"
+ }
+ "41"
+ {
+ "name" "Dark Slate Grey"
+ "color" "#2F4F4F"
+ }
+ "42"
+ {
+ "name" "Dark Turquoise"
+ "color" "#00CED1"
+ }
+ "43"
+ {
+ "name" "Dark Violet"
+ "color" "#9400D3"
+ }
+ "44"
+ {
+ "name" "Deep Pink"
+ "color" "#FF1493"
+ }
+ "45"
+ {
+ "name" "Deep Sky Blue"
+ "color" "#00BFFF"
+ }
+ "46"
+ {
+ "name" "Dim Grey"
+ "color" "#696969"
+ }
+ "48"
+ {
+ "name" "Dodger Blue"
+ "color" "#1E90FF"
+ }
+ "49"
+ {
+ "name" "Firebrick"
+ "color" "#B22222"
+ }
+ "50"
+ {
+ "name" "Floral White"
+ "color" "#FFFAF0"
+ }
+ "51"
+ {
+ "name" "Forest Green"
+ "color" "#228B22"
+ }
+ "52"
+ {
+ "name" "Fuchsia"
+ "color" "#FF00FF"
+ }
+ "53"
+ {
+ "name" "Full Blue"
+ "color" "#0000FF"
+ }
+ "54"
+ {
+ "name" "Full Red"
+ "color" "#FF0000"
+ }
+ "55"
+ {
+ "name" "Gainsboro"
+ "color" "#DCDCDC"
+ }
+ "56"
+ {
+ "name" "Genuine"
+ "color" "#4D7455"
+ }
+ "57"
+ {
+ "name" "Ghost White"
+ "color" "#F8F8FF"
+ }
+ "58"
+ {
+ "name" "Gold"
+ "color" "#FFD700"
+ }
+ "59"
+ {
+ "name" "Goldenrod"
+ "color" "#DAA520"
+ }
+ "60"
+ {
+ "name" "Gray"
+ "color" "#CCCCCC"
+ }
+ "61"
+ {
+ "name" "Green"
+ "color" "#3EFF3E"
+ }
+ "62"
+ {
+ "name" "Green Yellow"
+ "color" "#ADFF2F"
+ }
+ "63"
+ {
+ "name" "Haunted"
+ "color" "#38F3AB"
+ }
+ "64"
+ {
+ "name" "Honeydew"
+ "color" "#F0FFF0"
+ }
+ "65"
+ {
+ "name" "Hot Pink"
+ "color" "#FF69B4"
+ }
+ "66"
+ {
+ "name" "Indian Red"
+ "color" "#CD5C5C"
+ }
+ "67"
+ {
+ "name" "Indigo"
+ "color" "#4B0082"
+ }
+ "68"
+ {
+ "name" "Ivory"
+ "color" "#FFFFF0"
+ }
+ "69"
+ {
+ "name" "Khaki"
+ "color" "#F0E68C"
+ }
+ "70"
+ {
+ "name" "Lavender"
+ "color" "#E6E6FA"
+ }
+ "71"
+ {
+ "name" "Lavender Blush"
+ "color" "#FFF0F5"
+ }
+ "72"
+ {
+ "name" "Lawn Green"
+ "color" "#7CFC00"
+ }
+ "73"
+ {
+ "name" "Lemon Chiffon"
+ "color" "#FFFACD"
+ }
+ "74"
+ {
+ "name" "Light Blue"
+ "color" "#ADD8E6"
+ }
+ "75"
+ {
+ "name" "Light Coral"
+ "color" "#F08080"
+ }
+ "76"
+ {
+ "name" "Light Cyan"
+ "color" "#E0FFFF"
+ }
+ "77"
+ {
+ "name" "Light Goldenrod Yellow"
+ "color" "#FAFAD2"
+ }
+ "78"
+ {
+ "name" "Light Grey"
+ "color" "#D3D3D3"
+ }
+ "80"
+ {
+ "name" "Light Green"
+ "color" "#99FF99"
+ }
+ "81"
+ {
+ "name" "Light Pink"
+ "color" "#FFB6C1"
+ }
+ "82"
+ {
+ "name" "Light Salmon"
+ "color" "#FFA07A"
+ }
+ "83"
+ {
+ "name" "Light Sea Green"
+ "color" "#20B2AA"
+ }
+ "84"
+ {
+ "name" "Light Sky Blue"
+ "color" "#87CEFA"
+ }
+ "85"
+ {
+ "name" "Light Slate Grey"
+ "color" "#778899"
+ }
+ "86"
+ {
+ "name" "Light Slate Grey"
+ "color" "#778899"
+ }
+ "87"
+ {
+ "name" "Light Steel Blue"
+ "color" "#B0C4DE"
+ }
+ "88"
+ {
+ "name" "Light Yellow"
+ "color" "#FFFFE0"
+ }
+ "89"
+ {
+ "name" "Lime"
+ "color" "#00FF00"
+ }
+ "90"
+ {
+ "name" "Lime Green"
+ "color" "#32CD32"
+ }
+ "91"
+ {
+ "name" "Linen"
+ "color" "#FAF0E6"
+ }
+ "92"
+ {
+ "name" "Magenta"
+ "color" "#FF00FF"
+ }
+ "93"
+ {
+ "name" "Maroon"
+ "color" "#800000"
+ }
+ "94"
+ {
+ "name" "Medium Aquamarine"
+ "color" "#66CDAA"
+ }
+ "95"
+ {
+ "name" "Medium Blue"
+ "color" "#0000CD"
+ }
+ "96"
+ {
+ "name" "Medium Orchid"
+ "color" "#BA55D3"
+ }
+ "97"
+ {
+ "name" "Medium Purple"
+ "color" "#9370D8"
+ }
+ "98"
+ {
+ "name" "Mediumsea Green"
+ "color" "#3CB371"
+ }
+ "99"
+ {
+ "name" "Mediumslate Blue"
+ "color" "#7B68EE"
+ }
+ "100"
+ {
+ "name" "Medium Spring Green"
+ "color" "#00FA9A"
+ }
+ "101"
+ {
+ "name" "Medium Turquoise"
+ "color" "#48D1CC"
+ }
+ "102"
+ {
+ "name" "Medium Violet Red"
+ "color" "#C71585"
+ }
+ "103"
+ {
+ "name" "Midnight Blue"
+ "color" "#191970"
+ }
+ "104"
+ {
+ "name" "Mint Cream"
+ "color" "#F5FFFA"
+ }
+ "105"
+ {
+ "name" "Misty Rose"
+ "color" "#FFE4E1"
+ }
+ "106"
+ {
+ "name" "Moccasin"
+ "color" "#FFE4B5"
+ }
+ "107"
+ {
+ "name" "Navajo White"
+ "color" "#FFDEAD"
+ }
+ "108"
+ {
+ "name" "Navy"
+ "color" "#000080"
+ }
+ "109"
+ {
+ "name" "Normal"
+ "color" "#B2B2B2"
+ }
+ "110"
+ {
+ "name" "Old Lace"
+ "color" "#FDF5E6"
+ }
+ "111"
+ {
+ "name" "Olive"
+ "color" "#9EC34F"
+ }
+ "112"
+ {
+ "name" "Olive Drab"
+ "color" "#6B8E23"
+ }
+ "113"
+ {
+ "name" "Orange"
+ "color" "#FFA500"
+ }
+ "114"
+ {
+ "name" "Orange Red"
+ "color" "#FF4500"
+ }
+ "115"
+ {
+ "name" "Orchid"
+ "color" "#DA70D6"
+ }
+ "116"
+ {
+ "name" "Pale Goldenrod"
+ "color" "#EEE8AA"
+ }
+ "117"
+ {
+ "name" "Pale Green"
+ "color" "#98FB98"
+ }
+ "118"
+ {
+ "name" "Pale Turquoise"
+ "color" "#AFEEEE"
+ }
+ "119"
+ {
+ "name" "Pale Violet Red"
+ "color" "#D87093"
+ }
+ "120"
+ {
+ "name" "Papaya Whip"
+ "color" "#FFEFD5"
+ }
+ "121"
+ {
+ "name" "Peach Puff"
+ "color" "#FFDAB9"
+ }
+ "122"
+ {
+ "name" "Peru"
+ "color" "#CD853F"
+ }
+ "123"
+ {
+ "name" "Pink"
+ "color" "#FFC0CB"
+ }
+ "124"
+ {
+ "name" "Plum"
+ "color" "#DDA0DD"
+ }
+ "125"
+ {
+ "name" "Powder Blue"
+ "color" "#B0E0E6"
+ }
+ "126"
+ {
+ "name" "Purple"
+ "color" "#800080"
+ }
+ "127"
+ {
+ "name" "Red"
+ "color" "#FF4040"
+ }
+ "128"
+ {
+ "name" "Rosybrown"
+ "color" "#BC8F8F"
+ }
+ "129"
+ {
+ "name" "Royal Blue"
+ "color" "#4169E1"
+ }
+ "130"
+ {
+ "name" "Saddle Brown"
+ "color" "#8B4513"
+ }
+ "131"
+ {
+ "name" "Salmon"
+ "color" "#FA8072"
+ }
+ "132"
+ {
+ "name" "Sandy Brown"
+ "color" "#F4A460"
+ }
+ "133"
+ {
+ "name" "Sea Green"
+ "color" "#2E8B57"
+ }
+ "134"
+ {
+ "name" "Seashell"
+ "color" "#FFF5EE"
+ }
+ "135"
+ {
+ "name" "Selfmade"
+ "color" "#70B04A"
+ }
+ "136"
+ {
+ "name" "Sienna"
+ "color" "#A0522D"
+ }
+ "137"
+ {
+ "name" "Silver"
+ "color" "#C0C0C0"
+ }
+ "138"
+ {
+ "name" "Sky Blue"
+ "color" "#87CEEB"
+ }
+ "139"
+ {
+ "name" "Slate Blue"
+ "color" "#6A5ACD"
+ }
+ "140"
+ {
+ "name" "Slate Grey"
+ "color" "#708090"
+ }
+ "141"
+ {
+ "name" "Slate Grey"
+ "color" "#708090"
+ }
+ "142"
+ {
+ "name" "Snow"
+ "color" "#FFFAFA"
+ }
+ "143"
+ {
+ "name" "Spring Green"
+ "color" "#00FF7F"
+ }
+ "144"
+ {
+ "name" "Steel Blue"
+ "color" "#4682B4"
+ }
+ "145"
+ {
+ "name" "Strange"
+ "color" "#CF6A32"
+ }
+ "146"
+ {
+ "name" "Tan"
+ "color" "#D2B48C"
+ }
+ "147"
+ {
+ "name" "Teal"
+ "color" "#008080"
+ }
+ "148"
+ {
+ "name" "Thistle"
+ "color" "#D8BFD8"
+ }
+ "149"
+ {
+ "name" "Tomato"
+ "color" "#FF6347"
+ }
+ "150"
+ {
+ "name" "Turquoise"
+ "color" "#40E0D0"
+ }
+ "151"
+ {
+ "name" "Unique"
+ "color" "#FFD700"
+ }
+ "152"
+ {
+ "name" "Unusual"
+ "color" "#8650AC"
+ }
+ "153"
+ {
+ "name" "Valve"
+ "color" "#A50F79"
+ }
+ "154"
+ {
+ "name" "Vintage"
+ "color" "#476291"
+ }
+ "155"
+ {
+ "name" "Violet"
+ "color" "#EE82EE"
+ }
+ "156"
+ {
+ "name" "Wheat"
+ "color" "#F5DEB3"
+ }
+ "157"
+ {
+ "name" "White"
+ "color" "#FFFFFF"
+ }
+ "158"
+ {
+ "name" "Whitesmoke"
+ "color" "#F5F5F5"
+ }
+ "159"
+ {
+ "name" "Yellow"
+ "color" "#FFFF00"
+ }
+ "160"
+ {
+ "name" "Yellow Green"
+ "color" "#9ACD32"
+ }
+}
\ No newline at end of file
diff --git a/ChatTags/configs/ChatTags_colors_csgo.cfg b/ChatTags/configs/ChatTags_colors_csgo.cfg
new file mode 100644
index 0000000..776efc7
--- /dev/null
+++ b/ChatTags/configs/ChatTags_colors_csgo.cfg
@@ -0,0 +1,83 @@
+"Tag Colors"
+{
+ "1"
+ {
+ "name" "White"
+ "color" "1"
+ }
+ "2"
+ {
+ "name" "Dark Red (Disabled)"
+ "color" "-1"
+ }
+ "3"
+ {
+ "name" "Team Colors"
+ "color" "3"
+ }
+ "4"
+ {
+ "name" "Lime Green"
+ "color" "4"
+ }
+ "5"
+ {
+ "name" "Light Green"
+ "color" "5"
+ }
+ "6"
+ {
+ "name" "Olive"
+ "color" "6"
+ }
+ "7"
+ {
+ "name" "Light Red"
+ "color" "7"
+ }
+ "8"
+ {
+ "name" "Grey"
+ "color" "8"
+ }
+ "9"
+ {
+ "name" "Yellow"
+ "color" "9"
+ }
+ "10"
+ {
+ "name" "Light Blue"
+ "color" "10"
+ }
+ "11"
+ {
+ "name" "Blue"
+ "color" "11"
+ }
+ "12"
+ {
+ "name" "Dark Blue"
+ "color" "12"
+ }
+ "13"
+ {
+ "name" "Another Blue"
+ "color" "13"
+ }
+ "14"
+ {
+ "name" "Purple"
+ "color" "14"
+ }
+ "15"
+ {
+ "name" "Orange Red"
+ "color" "15"
+ }
+ "16"
+ {
+ "name" "Orange"
+ "color" "16"
+ }
+}
\ No newline at end of file
diff --git a/ChatTags/configs/ChatTags_colors_ins.cfg b/ChatTags/configs/ChatTags_colors_ins.cfg
new file mode 100644
index 0000000..f481961
--- /dev/null
+++ b/ChatTags/configs/ChatTags_colors_ins.cfg
@@ -0,0 +1,38 @@
+"Tag Colors"
+{
+ "1"
+ {
+ "name" "White"
+ "color" "1"
+ }
+ "2"
+ {
+ "name" "Team Colors"
+ "color" "2"
+ }
+ "3"
+ {
+ "name" "Lime Green"
+ "color" "3"
+ }
+ "4"
+ {
+ "name" "Light Green"
+ "color" "4"
+ }
+ "5"
+ {
+ "name" "Olive Black"
+ "color" "5"
+ }
+ "6"
+ {
+ "name" "Banana Yellow"
+ "color" "6"
+ }
+ "7"
+ {
+ "name" "Dark Yellow"
+ "color" "7"
+ }
+}
\ No newline at end of file
diff --git a/ChatTags/configs/ChatTags_groups.cfg b/ChatTags/configs/ChatTags_groups.cfg
new file mode 100644
index 0000000..a32341b
--- /dev/null
+++ b/ChatTags/configs/ChatTags_groups.cfg
@@ -0,0 +1,131 @@
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// EXPLANATION OF SETUPS:
+//
+// "Group Name" <<< See GROUP NAME EXPLANATION below.
+// {
+// "flags" "st" <<< Flags required to be considered a matching setup. See FLAGS EXPLANATION below.
+// "tagstring" "[Donator]" <<< Define the tag text.
+// "tagcolor" "9" <<< Color to use for the tag text, if applicable (see COLOR SETTINGS EXPLANATION below).
+// "namecolor" "5" <<< Color to use for the players name (see COLOR SETTINGS EXPLANATION below).
+// "chatcolor" "6" <<< Color to use for chat message text (see COLOR SETTINGS EXPLANATION below).
+// }
+//
+//////////////////////////////////////////////////////////////////////////////////
+//
+// ORDER OF OPERATIONS: Players get the first matching setup. Order them accordingly!
+//
+// For all setups, be sure to make check which setup first applies. e.g. if admins have flags 'b' and 's' and donators have 's',
+// make sure the admin setup comes first, else they will get the donator setup
+//
+//////////////////////////////////////////////////////////////////////////////////
+// FLAGS EXPLANATION: Access can be set to be a single flag, a set of required flags, or even sets of sets.
+//
+// e.g. Setting the flag as "a" requires players to have the "a" flag to be considered a match.
+// e.g. "at" requires players to have both the "a" AND "t" flags to be considered a match.
+// e.g. "a;t" requires players to have either the "a" OR "t" flags to be considered a match.
+// e.g. "at;b" requires players to have EITHER: (both the "a" AND "t" flags), OR the "b" flag. If either of the two conditions apply, they are considered a match.
+// A few more inputs: "none" restricts access for all. "public" or empty quotes ("") make the access available to all (if the "flags" key-value is omitted in any non-steam ID group, "public" is assumed).
+//
+//////////////////////////////////////////////////////////////////////////////////
+// GROUP NAME EXPLANATION:
+//
+// Names for the setups can be anything, but there are a few special names that can be used:
+// * Set it to a player's Steam ID (STEAM_X:Y:ZZZZZZZZ (AuthId_Steam2) or [U:Y:ZZZZZZZZ] (AuthId_Steam3) or XXXXXXXXXXXXXXXXX (AuthId_SteamID64)) to make one specific for that player.
+// Note: It will identify steam IDs as any section name with ":" in it (AuthId_Steam2 or AuthId_Steam3), or that is only numbers (AuthId_SteamID64).
+//
+// * Set it to TEAM_# (replace # with a team number) to make the setup apply to anyone on that team.
+// e.g. TEAM_2 would be team 2, which in CS:S/CS:GO is the Terrorist team. TEAM_3 would be the Counter-Terrorist team.
+// Note: If the "flags" key-value is set, then both are applied. e.g. A setup can specify Team 2 players with flag "a".
+//
+//////////////////////////////////////////////////////////////////////////////////
+// COLOR SETTINGS EXPLANATION:
+//
+// Note: The same colors below are required for the plugin cvars that ask you to specify colors. Lavender
+//
+// INSURGENCY COLORS:
+// 1 - White 2 - Team Colors 3 - Lime Green 4 - Light Green
+// 5 - Olive Black 6 - Banana Yellow 7 - Dark Yellow 8 - Grey
+//
+// CS:GO COLORS:
+// 1 - White 2 - Dark Red 3 - Team Colors 4 - Lime Green
+// 5 - Light Green 6 - Olive 7 - Light Red 8 - Grey
+// 9 - Yellow 10 - Light Blue 11 - Blue 12 - Dark Blue
+// 13 - Another Blue 14 - Purple 15 - Orange Red
+//
+// ALL OTHER GAMES:
+// Use hex code. e.g. Red = FF0000. To generate hex code, either look in ChatTags_colors.cfg for examples, or use a website like http://www.colorpicker.com/
+//
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+"Setups"
+{
+ "Root Admins"
+ {
+ "flags" "z"
+ "tagstring" "[Root Admin]"
+ "tagcolor" "7"
+ "namecolor" "6"
+ "chatcolor" "9"
+ }
+
+ "Normal Admins"
+ {
+ "flags" "s"
+ "tagstring" "[Admin]"
+ "tagcolor" "7"
+ "namecolor" "6"
+ "chatcolor" "9"
+ }
+
+ "Donators"
+ {
+ "flags" "o"
+ "tagstring" "[Donator]"
+ "tagcolor" "4"
+ "namecolor" "5"
+ "chatcolor" "1"
+ }
+
+ "Vip"
+ {
+ "flags" "opq"
+ "tagstring" "[Vip]"
+ "tagcolor" "4"
+ "namecolor" "5"
+ "chatcolor" "1"
+ }
+
+ "Mapper"
+ {
+ "flags" "opqr"
+ "tagstring" "[Mapper]"
+ "tagcolor" "16"
+ "namecolor" "9"
+ "chatcolor" "1"
+ }
+
+ "Event Winner"
+ {
+ "flags" "t"
+ "tagstring" "[Event Winner]"
+ "tagcolor" "12"
+ "namecolor" "11"
+ "chatcolor" "1"
+ }
+
+ //"TEAM_2"
+ //{
+ // "tagstring" "[TERRORIST]"
+ // "tagcolor" "5"
+ // "namecolor" "1"
+ // "chatcolor" "9"
+ //}
+
+ //"TEAM_3"
+ //{
+ // "tagstring" "[CT]"
+ // "tagcolor" "5"
+ // "namecolor" "1"
+ // "chatcolor" "9"
+ //}
+}
\ No newline at end of file
diff --git a/ChatTags/configs/db info to add.txt b/ChatTags/configs/db info to add.txt
new file mode 100644
index 0000000..9cc6b25
--- /dev/null
+++ b/ChatTags/configs/db info to add.txt
@@ -0,0 +1,24 @@
+"Databases"
+{
+ "ChatTags"
+ {
+ "driver" "mysql"
+ "host" "YOUR HOST IP HERE"
+ "database" "YOUR DB NAME HERE"
+ "user" "DB USERNAME HERE"
+ "pass" "USERNAME PASSWORD HERE"
+ }
+
+ //Use the above setup example if connecting to a MySQL DB.
+ //======== OR ========
+ //Use the below setup example if connecting to a local SQLite DB.
+
+ "ChatTags"
+ {
+ "driver" "sqlite"
+ "host" "localhost"
+ "database" "ChatTags"
+ "user" "root"
+ "pass" ""
+ }
+}
diff --git a/ChatTags/scripting/ChatTags.sp b/ChatTags/scripting/ChatTags.sp
new file mode 100644
index 0000000..76e0bab
--- /dev/null
+++ b/ChatTags/scripting/ChatTags.sp
@@ -0,0 +1,4911 @@
+/*
+Potential To Do:
+ * Make cvar for if players with required flag are restricted by default or not. (i.e., they have access, but have to be unrestricted first).
+ * If color setting no longer exists (via config), set player setup to "" if that is their cookie setting.
+ * Add to color config file the ability to specify color access via flags or to disable/enable certain colors.
+ * Add natives to plugin to allow other plugins to specify client, and section name of a group setup to apply that setup to a player. Make a "flags" keyvalue that specifies that the setup isnt public or flag/ID based, but for external use (i.e. N/A).
+ * Re-add Admin see-all.
+ Add client indexes that are admin and are not part of msg recipients to datapack w/ msg (already formatted with names, etc)
+ and execute msg on next game frame (or 0.1s timer?).
+ * Make secondary tag usable through groups config with another kv.
+ * Natives for external plugins to set a clients tag/colors.
+
+Requests:
+ * Force bracket color cfg in groups txt file?
+
+To Do:
+ Fix !blockchat
+ Only using a 1-D array, should be 2D...need to fix
+
+===========================================
+=========== CHANGELOG AT BOTTOM ===========
+===========================================
+*/
+
+#pragma semicolon 1
+#pragma dynamic 131072 //increase stack space to from 4 kB to 131072 cells (or 512KB, a cell is 4 bytes).
+
+#define PLUGIN_VERSION "4.9.3" //CHANGELOG AT BOTTOM
+#define MAXTAGSIZE 22
+#define INS_GREEN "\x01"
+#define CSGO_RED "\x07"
+#define CSS_RED "\x07FF0000"
+#define CSGO_WHITE "\x01"
+
+#define LoopValidPlayers(%1) for (int %1 = 1; %1 <= MaxClients; ++%1) if (IsValidClient(%1))
+
+#include
+#include
+#include
+#include
+#include
+#include
+//#include
+#include
+#include
+#include
+#include
+#undef REQUIRE_PLUGIN
+#tryinclude
+#define REQUIRE_PLUGIN
+
+#pragma newdecls required
+
+ConVar g_cAccessFlag = null;
+char g_sAccessFlag[120];
+ConVar g_cAdminFlag = null;
+char g_sAdminFlag[120];
+ConVar g_cSpamIgnoreFlag = null;
+char g_sSpamIgnoreFlag[120];
+ConVar g_cAdminFlag_Force = null;
+char g_sAdminFlag_Force[120];
+ConVar g_cAdminUnloadFlag = null;
+char g_sAdminUnloadFlag[120];
+ConVar g_cBracketColors = null;
+char g_sBracketColors[32];
+ConVar g_cDatabaseName = null;
+char g_sDatabaseName[60];
+ConVar g_cDBTableName = null;
+char g_sDBTableName[60];
+//console and team colors
+ConVar g_cConsoleTag = null;
+char g_sConsoleTag[50];
+ConVar g_cConsoleTagColor = null;
+char g_sConsoleTagColor[32];
+ConVar g_cConsoleName = null;
+char g_sConsoleName[50];
+ConVar g_cConsoleNameColor = null;
+char g_sConsoleNameColor[32];
+ConVar g_cConsoleChatColor = null;
+char g_sConsoleChatColor[32];
+ConVar g_cCTChatColor = null;
+char g_sCTChatColor[32];
+ConVar g_cTChatColor = null;
+char g_sTChatColor[32];
+ConVar g_cCTNameColor = null;
+char g_sCTNameColor[32];
+ConVar g_cTNameColor = null;
+char g_sTNameColor[32];
+ConVar g_cSpamDetectDuration = null;
+ConVar g_cGrpsAfterRemove = null;
+ConVar g_cSpamGagDetectDuration = null;
+ConVar g_cSpamMsgCnt = null;
+ConVar g_cSpamMsgGagCnt = null;
+ConVar g_cConvertTriggerCases = null;
+ConVar g_cEnableTags = null;
+ConVar g_cEnableTagColors = null;
+ConVar g_cEnableNameColors = null;
+ConVar g_cEnableChatColors = null;
+ConVar g_cHideChatTriggers = null;
+ConVar g_cLog = null;
+ConVar g_cEnableSpamBlock = null;
+ConVar g_cEnableSpamGag = null;
+ConVar g_cAllowBlockChat = null;
+ConVar g_cExternalPos = null;
+ConVar g_cForceBrackets = null;
+
+//player settings
+int gaa_iAdminOvrd[MAXPLAYERS + 1][4];
+int ga_iTagVisible[MAXPLAYERS + 1] = {0, ...}; //0 = hidden, 1 = cfg file, 2 = custom setup, 3 = admin forced setup
+int ga_iIsRestricted[MAXPLAYERS + 1] = {0, ...};
+int ga_iIsLoaded[MAXPLAYERS + 1] = {0, ...};
+int ga_iEntOverride[MAXPLAYERS + 1] = {0, ...};
+char gaa_sSteamID[MAXPLAYERS + 1][4][65];
+char ga_sName[MAXPLAYERS + 1][MAX_NAME_LENGTH];
+char ga_sEscapedName[MAXPLAYERS + 1][MAX_NAME_LENGTH*2 + 1];
+char ga_sTagColor[MAXPLAYERS + 1][32];
+char ga_sNameColor[MAXPLAYERS + 1][32];
+char ga_sChatColor[MAXPLAYERS + 1][32];
+char ga_sTag[MAXPLAYERS + 1][MAXTAGSIZE];
+char gaa_sCleanSetupText[MAXPLAYERS + 1][4][32];
+char ga_sExtTag[MAXPLAYERS + 1][30];
+char ga_sExtTagColor[MAXPLAYERS + 1][32];
+int ga_iTagColorAccess[MAXPLAYERS + 1] = {-1, ...};
+int ga_iNameColorAccess[MAXPLAYERS + 1] = {-1, ...};
+int ga_iChatColorAccess[MAXPLAYERS + 1] = {-1, ...};
+int ga_iSetTagAccess[MAXPLAYERS + 1] = {-1, ...};
+int ga_iGroupMatch[MAXPLAYERS + 1] = {0, ...};
+bool ga_bChatBlocked[MAXPLAYERS + 1] = {false, ...};
+
+//chat spam blocker
+int ga_iChatMsgCnt[MAXPLAYERS + 1] = {0, ...};
+int ga_iChatSpamCnt[MAXPLAYERS + 1] = {0, ...};
+
+ArrayList g_aTranslationNames;
+ArrayList g_aColorName;
+ArrayList g_aColorCode;
+ArrayList g_aBlockedTags;
+ArrayList g_aMessages;
+
+Handle g_hLoadFwd = INVALID_HANDLE;
+Handle g_hClientLoadFwd = INVALID_HANDLE;
+Handle g_hClientReloadFwd = INVALID_HANDLE;
+TopMenu g_oTopMenu;
+Regex g_oRegexHex;
+Database g_oDatabase;
+
+char g_sPath[PLATFORM_MAX_PATH]; //cfg file data
+char g_sGroupPath[PLATFORM_MAX_PATH]; //cfg file data
+char g_sChatLogPath[PLATFORM_MAX_PATH]; //chat logger
+char g_sTag[MAXTAGSIZE];
+char g_sMapName[128] = "";
+char g_sServerIP[64] = "";
+
+bool g_bLateLoad;
+bool g_bCSGO = false;
+bool g_bIns = false;
+bool g_bMySQL = false;
+
+//chat ignoring
+bool g_Ignored[(MAXPLAYERS + 1) * (MAXPLAYERS + 1)] = {false, ...};
+
+bool b_InGroup[MAXPLAYERS+1] = {false, ...};
+ConVar g_cGroupTag = null;
+ConVar g_cCTGroupTagColor = null;
+char g_sCTGroupTagColor[32];
+ConVar g_cTGroupTagColor = null;
+char g_sTGroupTagColor[32];
+
+bool g_bPOSSESSION = false;
+
+public Plugin myinfo =
+{
+ name = "Chat Tags",
+ author = "That One Guy + PŠΣ™ SHUFEN",
+ description = "Gives players with designated flag the ability to set their own custom tags, and much much more.",
+ version = PLUGIN_VERSION,
+ url = ""
+}
+
+public APLRes AskPluginLoad2(Handle hMyself, bool bLate, char[] sError, int err_max)
+{
+ g_bLateLoad = bLate;
+
+ CreateNative("CT_SetExtTag", Native_SetExtTag);
+ CreateNative("CT_SetSetTagAccess", Native_SetSetTagAccess);
+ CreateNative("CT_SetTagColorAccess", Native_SetTagColorAccess);
+ CreateNative("CT_SetNameColorAccess", Native_SetNameColorAccess);
+ CreateNative("CT_SetChatColorAccess", Native_SetChatColorAccess);
+ CreateNative("CT_SetCompleteAccess", Native_SetCompleteAccess);
+
+ //chat ignoring
+ CreateNative("CT_UpdateIgnoredArray", Native_UpdateIgnoredArray);
+
+ RegPluginLibrary("ChatTags");
+
+ return APLRes_Success;
+}
+
+public void OnPluginStart()
+{
+ LoadTranslations("ChatTags.phrases");
+
+ char sGameFolder[32], sTranslation[PLATFORM_MAX_PATH], sDescription[64];
+ GetGameDescription(sDescription, sizeof(sDescription), true);
+ GetGameFolderName(sGameFolder, sizeof(sGameFolder));
+ if ((StrContains(sGameFolder, "csgo", false) != -1) || (StrContains(sDescription, "Counter-Strike: Global Offensive", false) != -1))
+ {
+ g_bCSGO = true;
+ }
+ else if ((StrContains(sGameFolder, "insurgency", false) != -1) || StrEqual(sGameFolder, "ins", false) || (StrContains(sDescription, "Insurgency", false) != -1))
+ {
+ g_bIns = true;
+ }
+
+ g_aTranslationNames = new ArrayList(64);
+ Format(sTranslation, sizeof(sTranslation), "scp.%s.phrases.txt", sGameFolder);
+ LoadTranslations(sTranslation);
+ BuildPath(Path_SM, sTranslation, sizeof(sTranslation), "translations/%s", sTranslation);
+ if (!FileExists(sTranslation))
+ {
+ SetFailState("Translation file missing! %s", sTranslation);
+ }
+ GetTranslationNames(sTranslation);
+
+ g_hLoadFwd = CreateGlobalForward("CTLoaded", ET_Ignore);
+ g_hClientLoadFwd = CreateGlobalForward("CTClientLoaded", ET_Event, Param_Cell);
+ g_hClientReloadFwd = CreateGlobalForward("CTClientReloaded", ET_Event, Param_Cell);
+
+ AutoExecConfig_SetFile("ChatTags");
+ AutoExecConfig_CreateConVar("ct_version", PLUGIN_VERSION, "Chat Tags: Version", FCVAR_NOTIFY|FCVAR_DONTRECORD);
+
+ LoadTranslations("core.phrases");
+ LoadTranslations("common.phrases");
+
+ g_cAccessFlag = AutoExecConfig_CreateConVar("ct_accessflag", "q", "If \"\", everyone can change their tags, \"none\" restricted access (other than external plugin use), otherwise, only players with the listed flag(s) can access plugin features.", _);
+ g_cAccessFlag.GetString(g_sAccessFlag, sizeof(g_sAccessFlag));
+ g_cAccessFlag.AddChangeHook(OnCVarChange);
+
+ g_cAdminFlag = AutoExecConfig_CreateConVar("ct_adminflag", "s", "Only players with this flag can restrict/remove tags of players.", _);
+ g_cAdminFlag.GetString(g_sAdminFlag, sizeof(g_sAdminFlag));
+ g_cAdminFlag.AddChangeHook(OnCVarChange);
+
+ g_cSpamIgnoreFlag = AutoExecConfig_CreateConVar("ct_spamignoreflag", "s", "Players with this flag will be ignored by the spam blocker.", _);
+ g_cSpamIgnoreFlag.GetString(g_sSpamIgnoreFlag, sizeof(g_sSpamIgnoreFlag));
+ g_cSpamIgnoreFlag.AddChangeHook(OnCVarChange);
+
+ g_cAdminFlag_Force = AutoExecConfig_CreateConVar("ct_adminflag_force", "s", "Only players with this flag can force tags/colors for other players.", _);
+ g_cAdminFlag_Force.GetString(g_sAdminFlag_Force, sizeof(g_sAdminFlag_Force));
+ g_cAdminFlag_Force.AddChangeHook(OnCVarChange);
+
+ g_cAdminUnloadFlag = AutoExecConfig_CreateConVar("ct_unloadflag", "z", "Only players with this flag can unload the entire plugin until map change.", _);
+ g_cAdminUnloadFlag.GetString(g_sAdminUnloadFlag, sizeof(g_sAdminUnloadFlag));
+ g_cAdminUnloadFlag.AddChangeHook(OnCVarChange);
+
+ g_cConsoleTag = AutoExecConfig_CreateConVar("ct_console_tag", "", "Tag to use for console.", FCVAR_NONE);
+ g_cConsoleTag.GetString(g_sConsoleTag, sizeof(g_sConsoleTag));
+ g_cConsoleTag.AddChangeHook(OnCVarChange);
+
+ g_cConsoleName = AutoExecConfig_CreateConVar("ct_console_name", ":::CONSOLE:::", "Name to use for console.", FCVAR_NONE);
+ g_cConsoleName.GetString(g_sConsoleName, sizeof(g_sConsoleName));
+ g_cConsoleName.AddChangeHook(OnCVarChange);
+
+ g_cDatabaseName = AutoExecConfig_CreateConVar("ct_dbname", "ChatTags", "Name of the database setup for the plugin.");
+ g_cDatabaseName.GetString(g_sDatabaseName, sizeof(g_sDatabaseName));
+ g_cDatabaseName.AddChangeHook(OnCVarChange);
+
+ g_cDBTableName = AutoExecConfig_CreateConVar("ct_dbtblname", "ChatTags", "Name of the database table for the plugin.");
+ g_cDBTableName.GetString(g_sDBTableName, sizeof(g_sDBTableName));
+ g_cDBTableName.AddChangeHook(OnCVarChange);
+
+ g_cConvertTriggerCases = AutoExecConfig_CreateConVar("ct_triggercase", "1", "Convert chat triggers to lowercase if theyre uppercase. (1 = enabled, 0 = disabled)", FCVAR_NONE, true, 0.0, true, 1.0);
+ g_cLog = AutoExecConfig_CreateConVar("ct_log", "1", "Enable chat logger. (1 = enabled, 0 = disabled)", FCVAR_NONE, true, 0.0, true, 1.0);
+ g_cExternalPos = AutoExecConfig_CreateConVar("ct_exttagspos", "0", "0 = external tags applied on left of normal tags, 1 = on right, 2 = Only one tag can show, ext tag is preferenced, 3 = Only one tag can show, personal is preferenced.", FCVAR_NONE, true, 0.0, true, 3.0);
+ g_cForceBrackets = AutoExecConfig_CreateConVar("ct_forcebrackets", "0", "0 = disabled, 1 = wrap personal tags in {}, 2 = wrap personal tags in []. Note: Tags from the cfg file are not forced to have brackets.", FCVAR_NONE, true, 0.0, true, 2.0);
+ //spam blocker
+ g_cEnableSpamBlock = AutoExecConfig_CreateConVar("ct_spam_enable", "1", "Enable blocking chat spam (0 = disabled).", FCVAR_NONE, true, 0.0, true, 1.0);
+ g_cSpamDetectDuration = AutoExecConfig_CreateConVar("ct_spam_duration_short", "3", "Number of seconds used for the initial spam detection. If messages sent within this time frame exceed the count set by ct_spam_count_short, it blocks them and marks them as spam.", FCVAR_NONE, true, 1.0);
+ g_cSpamMsgCnt = AutoExecConfig_CreateConVar("ct_spam_count_short", "3", "Number of messages within the time interval set by ct_spam_duration_short for it to be considered spam.", FCVAR_NONE, true, 2.0);
+ g_cEnableSpamGag = AutoExecConfig_CreateConVar("ct_spam_enablegag", "0", "Enable muting chat spammers after spam detections exceed ct_spam_count_long within time set by ct_spam_duration_long? (1 = enabled, 0 = disabled).", FCVAR_NONE, true, 0.0, true, 1.0);
+ g_cSpamGagDetectDuration = AutoExecConfig_CreateConVar("ct_spam_duration_long", "60", "Number of spam detections within the time interval set by ct_spam_duration_long before auto-gag is issued.", FCVAR_NONE, true, 1.0);
+ g_cSpamMsgGagCnt = AutoExecConfig_CreateConVar("ct_spam_count_long", "30", "Number of spam detections within the time interval set by ct_spam_duration_long before auto-gag is issued.", FCVAR_NONE, true, 2.0);
+ g_cAllowBlockChat = AutoExecConfig_CreateConVar("ct_allowblockchat", "0", "Allow players to use !blockchat command (1 = enabled, 0 = disabled).", FCVAR_NONE, true, 0.0, true, 1.0);
+ g_cGrpsAfterRemove = AutoExecConfig_CreateConVar("ct_grps_after_remove", "1", "Apply group file configs to player after an admin removes their tags? (1 = enabled, 0 = disabled)", FCVAR_NONE, true, 0.0, true, 1.0);
+ g_cEnableTags = AutoExecConfig_CreateConVar("ct_enabletags", "1", "Enable being able to set a tags if you have access (1 = enabled, 0 = disabled).", FCVAR_NONE, true, 0.0, true, 1.0);
+ g_cEnableTagColors = AutoExecConfig_CreateConVar("ct_enabletagcolors", "1", "Enable being able to set tag colors (1 = enabled, 0 = disabled).", FCVAR_NONE, true, 0.0, true, 1.0);
+ g_cEnableNameColors = AutoExecConfig_CreateConVar("ct_enablenamecolors", "1", "Enable being able to set name colors (1 = enabled, 0 = disabled).", FCVAR_NONE, true, 0.0, true, 1.0);
+ g_cEnableChatColors = AutoExecConfig_CreateConVar("ct_enablechatcolors", "1", "Enable being able to set chat colors (1 = enabled, 0 = disabled).", FCVAR_NONE, true, 0.0, true, 1.0);
+ g_cHideChatTriggers = AutoExecConfig_CreateConVar("ct_hidechattriggers", "0", "Hides registered chat commands and messages starting with ! or / (1 = enabled, 0 = disabled).", FCVAR_NONE, true, 0.0, true, 1.0);
+
+ if (g_bCSGO) //CS:GO
+ {
+ Format(g_sTag, sizeof(g_sTag), " \x04[ChatTags] "); //includes space
+ g_cCTChatColor = AutoExecConfig_CreateConVar("ct_chatcolor_ct", "1", "Color to use as default chat color for CTs, if nothing else applies (check color cfg file for #s).", FCVAR_NONE);
+ g_cTChatColor = AutoExecConfig_CreateConVar("ct_chatcolor_t", "1", "Color to use as default chat color for Ts, if nothing else applies (check color cfg file for #s).", FCVAR_NONE);
+ g_cCTNameColor = AutoExecConfig_CreateConVar("ct_namecolor_ct", "11", "Color to use as default name color for CTs, if nothing else applies (check color cfg file for #s).", FCVAR_NONE);
+ g_cTNameColor = AutoExecConfig_CreateConVar("ct_namecolor_t", "15", "Color to use as default name color for Ts, if nothing else applies (check color cfg file for #s).", FCVAR_NONE);
+ g_cConsoleTagColor = AutoExecConfig_CreateConVar("ct_console_tagcolor", "2", "Color to use for console tag color (should be sourcepawn format).", FCVAR_NONE);
+ g_cConsoleNameColor = AutoExecConfig_CreateConVar("ct_console_namecolor", "2", "Color to use for console name color (should be sourcepawn format).", FCVAR_NONE);
+ g_cConsoleChatColor = AutoExecConfig_CreateConVar("ct_console_chatcolor", "2", "Color to use for console chat color (should be sourcepawn format).", FCVAR_NONE);
+ g_cBracketColors = AutoExecConfig_CreateConVar("ct_bracketcolor", "", "Color to use for brackets if ct_forcebrackets is enabled (check color cfg file for #s - Blank = match tag color).", FCVAR_NONE);
+ }
+ else if (g_bIns) //Insurgency
+ {
+ Format(g_sTag, sizeof(g_sTag), " \x04[ChatTags] "); //includes space
+ g_cCTChatColor = AutoExecConfig_CreateConVar("ct_chatcolor_ct", "1", "Color to use as default chat color for CTs, if nothing else applies (check color cfg file for #s).", FCVAR_NONE);
+ g_cTChatColor = AutoExecConfig_CreateConVar("ct_chatcolor_t", "1", "Color to use as default chat color for Ts, if nothing else applies (check color cfg file for #s).", FCVAR_NONE);
+ g_cCTNameColor = AutoExecConfig_CreateConVar("ct_namecolor_ct", "2", "Color to use as default name color for CTs, if nothing else applies (check color cfg file for #s).", FCVAR_NONE);
+ g_cTNameColor = AutoExecConfig_CreateConVar("ct_namecolor_t", "2", "Color to use as default name color for Ts, if nothing else applies (check color cfg file for #s).", FCVAR_NONE);
+ g_cConsoleTagColor = AutoExecConfig_CreateConVar("ct_console_tagcolor", "1", "Color to use for console tag color (check color cfg file for #s).", FCVAR_NONE);
+ g_cConsoleNameColor = AutoExecConfig_CreateConVar("ct_console_namecolor", "3", "Color to use for console name color (check color cfg file for #s).", FCVAR_NONE);
+ g_cConsoleChatColor = AutoExecConfig_CreateConVar("ct_console_chatcolor", "6", "Color to use for console chat color (check color cfg file for #s).", FCVAR_NONE);
+ g_cBracketColors = AutoExecConfig_CreateConVar("ct_bracketcolor", "", "Color to use for brackets if ct_forcebrackets is enabled (check color cfg file for #s - Blank = match tag color).", FCVAR_NONE);
+ }
+ else
+ {
+ Format(g_sTag, sizeof(g_sTag), "\x04[ChatTags] "); //no space added
+ g_cCTChatColor = AutoExecConfig_CreateConVar("ct_chatcolor_ct", "", "Color to use as default chat color for CTs, if nothing else applies (check color cfg file for #s).", FCVAR_NONE);
+ g_cTChatColor = AutoExecConfig_CreateConVar("ct_chatcolor_t", "", "Color to use as default chat color for Ts, if nothing else applies (check color cfg file for #s).", FCVAR_NONE);
+ g_cCTNameColor = AutoExecConfig_CreateConVar("ct_namecolor_ct", "99CCFF", "Color to use as default name color for CTs, if nothing else applies (check color cfg file for #s).", FCVAR_NONE);
+ g_cTNameColor = AutoExecConfig_CreateConVar("ct_namecolor_t", "FF4040", "Color to use as default name color for Ts, if nothing else applies (check color cfg file for #s).", FCVAR_NONE);
+ g_cConsoleTagColor = AutoExecConfig_CreateConVar("ct_console_tagcolor", "FFFFFF", "Color to use for console tag color (check color cfg file for #s).", FCVAR_NONE);
+ g_cConsoleNameColor = AutoExecConfig_CreateConVar("ct_console_namecolor", "FF0000", "Color to use for console name color (check color cfg file for #s).", FCVAR_NONE);
+ g_cConsoleChatColor = AutoExecConfig_CreateConVar("ct_console_chatcolor", "FF0000", "Color to use for console chat color (check color cfg file for #s).", FCVAR_NONE);
+ g_cBracketColors = AutoExecConfig_CreateConVar("ct_bracketcolor", "", "Color to use for brackets if ct_forcebrackets is enabled (check color cfg file for #s - Blank = match tag color).", FCVAR_NONE);
+ }
+
+ g_cGroupTag = AutoExecConfig_CreateConVar("ct_grouptag", "1", "Add symbol prefix for steam group member (1 = enabled, 0 = disabled).", FCVAR_NONE, true, 0.0, true, 1.0);
+ g_cCTGroupTagColor = AutoExecConfig_CreateConVar("ct_grouptagcolor_ct", "12", "Color to use as group tag color for CTs, if nothing else applies (check color cfg file for #s).", FCVAR_NONE);
+ g_cTGroupTagColor = AutoExecConfig_CreateConVar("ct_grouptagcolor_t", "7", "Color to use as group tag color for Ts, if nothing else applies (check color cfg file for #s).", FCVAR_NONE);
+ g_cCTGroupTagColor.GetString(g_sCTGroupTagColor, sizeof(g_sCTGroupTagColor));
+ g_cCTGroupTagColor.AddChangeHook(OnCVarChange);
+ g_cTGroupTagColor.GetString(g_sTGroupTagColor, sizeof(g_sTGroupTagColor));
+ g_cTGroupTagColor.AddChangeHook(OnCVarChange);
+
+ g_cCTChatColor.GetString(g_sCTChatColor, sizeof(g_sCTChatColor));
+ g_cCTChatColor.AddChangeHook(OnCVarChange);
+
+ g_cTChatColor.GetString(g_sTChatColor, sizeof(g_sTChatColor));
+ g_cTChatColor.AddChangeHook(OnCVarChange);
+
+ g_cCTNameColor.GetString(g_sCTNameColor, sizeof(g_sCTNameColor));
+ g_cCTNameColor.AddChangeHook(OnCVarChange);
+
+ g_cTNameColor.GetString(g_sTNameColor, sizeof(g_sTNameColor));
+ g_cTNameColor.AddChangeHook(OnCVarChange);
+
+ g_cBracketColors.GetString(g_sBracketColors, sizeof(g_sBracketColors));
+ g_cBracketColors.AddChangeHook(OnCVarChange);
+
+ g_cConsoleTagColor.GetString(g_sConsoleTagColor, sizeof(g_sConsoleTagColor));
+ g_cConsoleTagColor.AddChangeHook(OnCVarChange);
+
+ g_cConsoleNameColor.GetString(g_sConsoleNameColor, sizeof(g_sConsoleNameColor));
+ g_cConsoleNameColor.AddChangeHook(OnCVarChange);
+
+ g_cConsoleChatColor.GetString(g_sConsoleChatColor, sizeof(g_sConsoleChatColor));
+ g_cConsoleChatColor.AddChangeHook(OnCVarChange);
+
+ AutoExecConfig_ExecuteFile();
+ AutoExecConfig_CleanFile();
+
+ SetDBHandle();
+
+ //player commands
+ RegConsoleCmd("sm_tags", Command_Tag, "Opens Chat Tags Menu.");
+ RegConsoleCmd("sm_chatmenu", Command_Tag, "Opens Chat Tags Menu.");
+ RegConsoleCmd("sm_chatcolor", Command_Tag, "Opens Chat Tags Menu.");
+ RegConsoleCmd("sm_tagmenu", Command_Tag, "Opens Chat Tags Menu.");
+ RegConsoleCmd("sm_tagcolor", Command_Tag, "Opens Chat Tags Menu.");
+ RegConsoleCmd("sm_namemenu", Command_Tag, "Opens Chat Tags Menu.");
+ RegConsoleCmd("sm_namecolor", Command_Tag, "Opens Chat Tags Menu.");
+ RegConsoleCmd("sm_settag", Command_SetText, "Change tag text.");
+ RegConsoleCmd("sm_tag", Command_SetText, "Change tag text.");
+ RegConsoleCmd("sm_checktag", Command_CheckTag, "Check tag settings of another player.");
+ RegConsoleCmd("sm_blockchat", Command_BlockChat, "Block player from seeing chat from others (if command is allowed).");
+ //non-CS:GO commands
+ RegConsoleCmd("sm_tagcolor", Command_TagColor, "Change tag color to a specified hexadecimal value.");
+ RegConsoleCmd("sm_namecolor", Command_NameColor, "Change name color to a specified hexadecimal value.");
+ RegConsoleCmd("sm_chatcolor", Command_ChatColor, "Change chat color to a specified hexadecimal value.");
+
+ //admin commands - RegConsoleCmd used to allow setting access via cvar "ct_adminflag"
+ RegConsoleCmd("sm_reloadtagcolors", Cmd_Reload, "Reloads color cfg file for tags.");
+ RegConsoleCmd("sm_unrestricttag", Cmd_Unrestrict, "Unrestrict player from setting their chat tags.");
+ RegConsoleCmd("sm_restricttag", Cmd_Restrict, "Restrict player from setting their chat tags.");
+ RegConsoleCmd("sm_removetag", Cmd_RemoveTag, "Removes a players tag setup.");
+ RegConsoleCmd("sm_unloadtags", Cmd_Unload, "Unloads the entire plugin for the current map.");
+ //admin commands - RegConsoleCmd used to allow setting access via cvar "ct_adminflag_force"
+ RegConsoleCmd("sm_forcetag", Cmd_ForceTag, "Force tag setup on a player.");
+ RegConsoleCmd("sm_removeoverride", Cmd_RemoveOverride, "Remove admin overrides from a player.");
+
+ AddCommandListener(Command_Say, "say");
+ AddCommandListener(Command_SayTeam, "say_team");
+ if (g_bIns)
+ {
+ AddCommandListener(Command_Say, "say2");
+ }
+
+ //hook admin chat commands for chat logging
+ AddCommandListener(Command_AdminChat, "sm_say");
+ AddCommandListener(Command_AdminOnlyChat, "sm_chat");
+ AddCommandListener(Command_CSay, "sm_csay");
+ AddCommandListener(Command_TSay, "sm_tsay");
+ AddCommandListener(Command_MSay, "sm_msay");
+ AddCommandListener(Command_HSay, "sm_hsay");
+ AddCommandListener(Command_PSay, "sm_psay");
+
+ HookEvent("player_changename", Event_NameChange);
+ UserMsg umSayText2 = GetUserMessageId("SayText2");
+ if (umSayText2 != INVALID_MESSAGE_ID)
+ {
+ HookUserMessage(umSayText2, OnSayText2, true);
+ }
+ else
+ {
+ UserMsg umSayText = GetUserMessageId("SayText");
+ if (umSayText != INVALID_MESSAGE_ID)
+ {
+ HookUserMessage(umSayText, OnSayText2, true);
+ }
+ else
+ {
+ LogError("Unable to hook either SayText2 or SayText. This game is not supported!");
+ SetFailState("Unable to hook either SayText2 or SayText. This game is not supported!");
+ }
+ }
+
+ //client prefs and cookies
+ SetCookieMenuItem(Menu_ClientPrefs, 0, "Chat Tags");
+
+ //admin menu - Account for late loading
+ TopMenu hTopMenu;
+ if (LibraryExists("adminmenu") && ((hTopMenu = GetAdminTopMenu()) != INVALID_HANDLE))
+ {
+ OnAdminMenuReady(hTopMenu);
+ }
+
+ //color file
+ g_aColorName = new ArrayList(32);
+ g_aColorCode = new ArrayList(32);
+ if (g_bCSGO)
+ {
+ BuildPath(Path_SM, g_sPath, sizeof(g_sPath), "configs/ChatTags_colors_csgo.cfg");
+ }
+ else if (g_bIns)
+ {
+ BuildPath(Path_SM, g_sPath, sizeof(g_sPath), "configs/ChatTags_colors_ins.cfg");
+ }
+ else
+ {
+ BuildPath(Path_SM, g_sPath, sizeof(g_sPath), "configs/ChatTags_colors.cfg");
+ g_oRegexHex = new Regex("([A-Fa-f0-9]{6})");
+ }
+
+ BuildPath(Path_SM, g_sGroupPath, sizeof(g_sGroupPath), "configs/ChatTags_groups.cfg");
+
+ if (g_bCSGO)
+ {
+ ConvertConsoleColor(g_sConsoleTagColor, sizeof(g_sConsoleTagColor));
+ ConvertConsoleColor(g_sConsoleNameColor, sizeof(g_sConsoleNameColor));
+ ConvertConsoleColor(g_sConsoleChatColor, sizeof(g_sConsoleChatColor));
+ }
+ else
+ {
+ ConvertColor(g_sConsoleTagColor, sizeof(g_sConsoleTagColor));
+ ConvertColor(g_sConsoleNameColor, sizeof(g_sConsoleNameColor));
+ ConvertColor(g_sConsoleChatColor, sizeof(g_sConsoleChatColor));
+ }
+ ConvertColor(g_sCTChatColor, sizeof(g_sCTChatColor));
+ ConvertColor(g_sTChatColor, sizeof(g_sTChatColor));
+ ConvertColor(g_sCTNameColor, sizeof(g_sCTNameColor));
+ ConvertColor(g_sTNameColor, sizeof(g_sTNameColor));
+ ConvertColor(g_sBracketColors, sizeof(g_sBracketColors));
+
+ ConvertColor(g_sCTGroupTagColor, sizeof(g_sCTGroupTagColor));
+ ConvertColor(g_sTGroupTagColor, sizeof(g_sTGroupTagColor));
+
+ //overwrite cookies if they are cached
+ for (int i = 1; i <= MaxClients; i++)
+ {
+ if (IsClientInGame(i) && AreClientCookiesCached(i) && IsClientAuthorized(i))
+ {
+ SetDefaults(i);
+ LoadClientData(i);
+ }
+ }
+
+ GetServerIP();
+}
+
+public void OnAllPluginsLoaded() {
+ g_bPOSSESSION = LibraryExists("POSSESSION");
+}
+
+public void OnLibraryAdded(const char[] name) {
+ if (StrEqual(name, "POSSESSION", false)) g_bPOSSESSION = true;
+}
+
+public void OnLibraryRemoved(const char[] name) {
+ if (StrEqual(name, "POSSESSION", false)) g_bPOSSESSION = false;
+}
+
+public void OnCVarChange(ConVar hCVar, const char[] sOldValue, const char[] sNewValue)
+{
+ if (hCVar == g_cDatabaseName)
+ {
+ g_cDatabaseName.GetString(g_sDatabaseName, sizeof(g_sDatabaseName));
+ }
+ else if (hCVar == g_cDBTableName)
+ {
+ g_cDBTableName.GetString(g_sDBTableName, sizeof(g_sDBTableName));
+ }
+ else if (hCVar == g_cAccessFlag)
+ {
+ g_cAccessFlag.GetString(g_sAccessFlag, sizeof(g_sAccessFlag));
+ }
+ else if (hCVar == g_cAdminFlag)
+ {
+ g_cAdminFlag.GetString(g_sAdminFlag, sizeof(g_sAdminFlag));
+ }
+ else if (hCVar == g_cSpamIgnoreFlag)
+ {
+ g_cSpamIgnoreFlag.GetString(g_sSpamIgnoreFlag, sizeof(g_sSpamIgnoreFlag));
+ }
+ else if (hCVar == g_cAdminFlag_Force)
+ {
+ g_cAdminFlag_Force.GetString(g_sAdminFlag_Force, sizeof(g_sAdminFlag_Force));
+ }
+ else if (hCVar == g_cAdminUnloadFlag)
+ {
+ g_cAdminUnloadFlag.GetString(g_sAdminUnloadFlag, sizeof(g_sAdminUnloadFlag));
+ }
+ else if (hCVar == g_cConsoleTag)
+ {
+ g_cConsoleTag.GetString(g_sConsoleTag, sizeof(g_sConsoleTag));
+ }
+ else if (hCVar == g_cConsoleTagColor)
+ {
+ GetConVarString(g_cConsoleTagColor, g_sConsoleTagColor, sizeof(g_sConsoleTagColor));
+ if (g_bCSGO)
+ ConvertConsoleColor(g_sConsoleTagColor, sizeof(g_sConsoleTagColor));
+ else
+ ConvertColor(g_sConsoleTagColor, sizeof(g_sConsoleTagColor));
+ }
+ else if (hCVar == g_cConsoleName)
+ {
+ g_cConsoleName.GetString(g_sConsoleName, sizeof(g_sConsoleName));
+ }
+ else if (hCVar == g_cConsoleNameColor)
+ {
+ GetConVarString(g_cConsoleNameColor, g_sConsoleNameColor, sizeof(g_sConsoleNameColor));
+ if (g_bCSGO)
+ ConvertConsoleColor(g_sConsoleNameColor, sizeof(g_sConsoleNameColor));
+ else
+ ConvertColor(g_sConsoleNameColor, sizeof(g_sConsoleNameColor));
+ }
+ else if (hCVar == g_cConsoleChatColor)
+ {
+ GetConVarString(g_cConsoleChatColor, g_sConsoleChatColor, sizeof(g_sConsoleChatColor));
+ if (g_bCSGO)
+ ConvertConsoleColor(g_sConsoleChatColor, sizeof(g_sConsoleChatColor));
+ else
+ ConvertColor(g_sConsoleChatColor, sizeof(g_sConsoleChatColor));
+ }
+ else if (hCVar == g_cCTChatColor)
+ {
+ g_cCTChatColor.GetString(g_sCTChatColor, sizeof(g_sCTChatColor));
+ ConvertColor(g_sCTChatColor, sizeof(g_sCTChatColor));
+ }
+ else if (hCVar == g_cTChatColor)
+ {
+ g_cTChatColor.GetString(g_sTChatColor, sizeof(g_sTChatColor));
+ ConvertColor(g_sTChatColor, sizeof(g_sTChatColor));
+ }
+ else if (hCVar == g_cCTNameColor)
+ {
+ g_cCTNameColor.GetString(g_sCTNameColor, sizeof(g_sCTNameColor));
+ ConvertColor(g_sCTNameColor, sizeof(g_sCTNameColor));
+ }
+ else if (hCVar == g_cTNameColor)
+ {
+ g_cTNameColor.GetString(g_sTNameColor, sizeof(g_sTNameColor));
+ ConvertColor(g_sTNameColor, sizeof(g_sTNameColor));
+ }
+ else if (hCVar == g_cBracketColors)
+ {
+ g_cBracketColors.GetString(g_sBracketColors, sizeof(g_sBracketColors));
+ ConvertColor(g_sBracketColors, sizeof(g_sBracketColors));
+ }
+
+ else if (hCVar == g_cCTGroupTagColor)
+ {
+ g_cCTGroupTagColor.GetString(g_sCTGroupTagColor, sizeof(g_sCTGroupTagColor));
+ ConvertColor(g_sCTGroupTagColor, sizeof(g_sCTGroupTagColor));
+ }
+ else if (hCVar == g_cTGroupTagColor)
+ {
+ g_cTGroupTagColor.GetString(g_sTGroupTagColor, sizeof(g_sTGroupTagColor));
+ ConvertColor(g_sTGroupTagColor, sizeof(g_sTGroupTagColor));
+ }
+}
+
+void SetDBHandle()
+{
+ if (g_oDatabase != null)
+ {
+ delete g_oDatabase;
+ g_oDatabase = null;
+ }
+ Database.Connect(SQLCallback_Connect, g_sDatabaseName);
+}
+
+public void SQLCallback_Connect(Database oDB, const char[] sError, any data)
+{
+ if (oDB == null)
+ {
+ SetFailState("Error connecting to main database. %s", sError);
+ }
+ else
+ {
+ g_oDatabase = oDB;
+ char sDriver[64], sQuery[1000], sQueryBuffer[1000];
+ DBDriver oDriver = g_oDatabase.Driver;
+ oDriver.GetIdentifier(sDriver, sizeof(sDriver));
+ delete oDriver;
+
+ Format(sQueryBuffer, sizeof(sQueryBuffer), " `steamid` VARCHAR(65) NOT NULL, \
+ `tagtext` VARCHAR(32) NOT NULL, \
+ `visible` INT(2) NOT NULL, \
+ `restricted` INT(2) NOT NULL, \
+ `tagcolor` VARCHAR(10) NOT NULL, \
+ `namecolor` VARCHAR(10) NOT NULL, \
+ `chatcolor` VARCHAR(10) NOT NULL, \
+ `ovrd_ttext` INT(2) NOT NULL, \
+ `ovrd_tcolor` INT(2) NOT NULL, \
+ `ovrd_ncolor` INT(2) NOT NULL, \
+ `ovrd_ccolor` INT(2) NOT NULL");
+ FormatQueryByDriver(sDriver, g_sDBTableName, sQuery, sizeof(sQuery), sQueryBuffer);
+ g_oDatabase.Query(SQLCallback_Void, sQuery, 1);
+
+ if (!StrEqual(sDriver, "sqlite"))
+ {
+ Format(sQuery, sizeof(sQuery), "CREATE TABLE IF NOT EXISTS `ct_chatlogs` ( `id` INT(20) NOT NULL AUTO_INCREMENT PRIMARY KEY, \
+ `steamid` VARCHAR(65) NULL, \
+ `mapname` VARCHAR(128) NULL, \
+ `server` VARCHAR(32) NULL, \
+ `playername` VARCHAR(65) NULL, \
+ `playerip` VARCHAR(32) NULL, \
+ `ip_country` VARCHAR(45) NULL, \
+ `chatmsg` VARCHAR(300) NULL, \
+ `chatgrp` VARCHAR(20) NULL, \
+ `logdate` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP() \
+ )");
+ g_oDatabase.Query(SQLCallback_Void, sQuery, 5);
+ g_bMySQL = true;
+ }
+ else //if sqlite, use flat files
+ {
+ char sBuffer[PLATFORM_MAX_PATH];
+ BuildPath(Path_SM, sBuffer, sizeof(sBuffer), "logs/chatlogger/");
+ if (!DirExists(sBuffer))
+ {
+ CreateDirectory(sBuffer, 777);
+ }
+ FormatTime(sBuffer, sizeof(sBuffer), "%m%d%y");
+ Format(sBuffer, sizeof(sBuffer), "logs/chatlogger/chatlogs_%s.log", sBuffer);
+ BuildPath(Path_SM, g_sChatLogPath, sizeof(g_sChatLogPath), sBuffer);
+ CreateTimer(60.0, Timer_UpdatePath, _, TIMER_REPEAT);
+ }
+ }
+ GetCurrentMap(g_sMapName, sizeof(g_sMapName)); //redundancy to make sure this has a value
+}
+
+void FormatQueryByDriver(char[] sDriver, char[] sTblName, char[] sRtnQuery, int iSize, char[] sQuery)
+{
+ if (StrEqual(sDriver, "sqlite", false))
+ {
+ Format(sRtnQuery, iSize, "CREATE TABLE IF NOT EXISTS `%s` (`id` int(20) PRIMARY KEY, %s, PRIMARY KEY (`id`)) DEFAULT AUTO_INCREMENT=1", sTblName, sQuery);
+ }
+ else
+ {
+ Format(sRtnQuery, iSize, "CREATE TABLE IF NOT EXISTS `%s` (`id` int(20) NOT NULL AUTO_INCREMENT PRIMARY KEY, %s)", sTblName, sQuery);
+ }
+}
+
+public void SQLCallback_Void(Database oDB, DBResultSet oHndl, const char[] sError, any iValue)
+{
+ if (oHndl == null)
+ {
+ //SetFailState("Error (%i): %s", iValue, sError);
+ LogMessage("Error (%i): %s", iValue, sError);
+ }
+}
+
+public void OnMapStart()
+{
+ if (g_bCSGO)
+ {
+ ConvertConsoleColor(g_sConsoleTagColor, sizeof(g_sConsoleTagColor));
+ ConvertConsoleColor(g_sConsoleNameColor, sizeof(g_sConsoleNameColor));
+ ConvertConsoleColor(g_sConsoleChatColor, sizeof(g_sConsoleChatColor));
+ }
+ else
+ {
+ ConvertColor(g_sConsoleTagColor, sizeof(g_sConsoleTagColor));
+ ConvertColor(g_sConsoleNameColor, sizeof(g_sConsoleNameColor));
+ ConvertColor(g_sConsoleChatColor, sizeof(g_sConsoleChatColor));
+ }
+ ConvertColor(g_sCTChatColor, sizeof(g_sCTChatColor));
+ ConvertColor(g_sTChatColor, sizeof(g_sTChatColor));
+ ConvertColor(g_sCTNameColor, sizeof(g_sCTNameColor));
+ ConvertColor(g_sTNameColor, sizeof(g_sTNameColor));
+ ConvertColor(g_sBracketColors, sizeof(g_sBracketColors));
+
+ ConvertColor(g_sCTGroupTagColor, sizeof(g_sCTGroupTagColor));
+ ConvertColor(g_sTGroupTagColor, sizeof(g_sTGroupTagColor));
+
+ LoadColorCfg();
+ LoadCustomConfigs();
+
+ GetCurrentMap(g_sMapName, sizeof(g_sMapName)); //redundancy to make sure this has a value
+
+ if (g_cLog.BoolValue && (g_oDatabase != null))
+ {
+ if (!g_bMySQL) //map is already noted in MySQL DB, so this logging is not necessary.
+ {
+ LogToFileEx(g_sChatLogPath, " >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> New map started: %s <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<", g_sMapName);
+ }
+ }
+}
+
+void GetServerIP()
+{
+ int a_iArray[4];
+ /*int iLongIP = GetConVarInt(FindConVar("hostip"));
+ a_iArray[0] = (iLongIP >> 24) & 0x000000FF;
+ a_iArray[1] = (iLongIP >> 16) & 0x000000FF;
+ a_iArray[2] = (iLongIP >> 8) & 0x000000FF;
+ a_iArray[3] = iLongIP & 0x000000FF;*/
+ SteamWorks_GetPublicIP(a_iArray);
+ Format(g_sServerIP, sizeof(g_sServerIP), "%d.%d.%d.%d:%i", a_iArray[0], a_iArray[1], a_iArray[2], a_iArray[3], GetConVarInt(FindConVar("hostport")));
+}
+
+public Action Timer_UpdatePath(Handle hTimer)
+{
+ char sBuffer[256];
+ FormatTime(sBuffer, sizeof(sBuffer), "%m%d%y");
+ Format(sBuffer, sizeof(sBuffer), "logs/chatlogger/chatlogs_%s.log", sBuffer);
+ BuildPath(Path_SM, g_sChatLogPath, sizeof(g_sChatLogPath), sBuffer);
+}
+
+public void OnConfigsExecuted()
+{
+ LoadColorCfg();
+ LoadCustomConfigs();
+
+ if (g_bLateLoad)
+ {
+ Reload();
+ /*if (g_cLog.BoolValue && !g_bMySQL)
+ {
+ CreateTimer(60.0, Timer_UpdatePath, _, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE);
+ }*/
+ }
+
+ GetServerIP();
+}
+
+public void LoadColorCfg()
+{
+ if (!FileExists(g_sPath))
+ {
+ SetFailState("Configuration file %s not found!", g_sPath);
+ return;
+ }
+
+ KeyValues oKeyValues = new KeyValues("Tag Colors");
+
+ if (!oKeyValues.ImportFromFile(g_sPath))
+ {
+ SetFailState("Improper structure for configuration file %s!", g_sPath);
+ return;
+ }
+
+ if (!oKeyValues.GotoFirstSubKey(true))
+ {
+ SetFailState("Can't find configuration file %s!", g_sPath);
+ return;
+ }
+
+ g_aColorName.Clear();
+ g_aColorCode.Clear();
+
+ char sName[32], sCode[32];
+ do
+ {
+ oKeyValues.GetString("name", sName, sizeof(sName));
+ oKeyValues.GetString("color", sCode, sizeof(sCode));
+ ReplaceString(sCode, sizeof(sCode), "#", "", false);
+
+ if (!g_bCSGO && !g_bIns)
+ {
+ if (!IsValidHex(sCode))
+ {
+ LogError("Invalid hexadecimal value for color %s: %s.", sName, sCode);
+ continue;
+ }
+ }
+
+ g_aColorName.PushString(sName);
+ g_aColorCode.PushString(sCode);
+ }
+ while (oKeyValues.GotoNextKey(false));
+ delete oKeyValues;
+}
+
+public void LoadCustomConfigs()
+{
+ if (g_aBlockedTags != null)
+ delete g_aBlockedTags;
+ if (g_aMessages != null)
+ delete g_aMessages;
+ g_aBlockedTags = new ArrayList(64);
+ g_aMessages = new ArrayList();
+ char sBuffer[PLATFORM_MAX_PATH], sFile[PLATFORM_MAX_PATH];
+ BuildPath(Path_SM, sFile, PLATFORM_MAX_PATH, "configs/ChatTags_blocked.cfg");
+ File oFile = OpenFile(sFile, "r");
+ if (oFile != null)
+ {
+ while (oFile.ReadLine(sBuffer, sizeof(sBuffer)))
+ {
+ TrimString(sBuffer); //remove spaces and tabs at both ends of string
+ if ((StrContains(sBuffer, "//") == -1) && (!StrEqual(sBuffer, ""))) //filter out comments and blank lines
+ {
+ g_aBlockedTags.PushString(sBuffer);
+ }
+ }
+ }
+ else
+ {
+ LogError("File does not exist: \"%s\"", sFile);
+ }
+
+ delete oFile;
+}
+
+public int Native_SetExtTag(Handle hPlugin, int iNumParams)
+{
+ int client = GetNativeCell(1);
+ if (IsValidClient(client))
+ {
+ GetNativeString(2, ga_sExtTag[client], sizeof(ga_sExtTag[]));
+ GetNativeString(3, ga_sExtTagColor[client], sizeof(ga_sExtTagColor[]));
+ FormatColors(client);
+ return true;
+ }
+ return false;
+}
+
+public int Native_SetSetTagAccess(Handle hPlugin, int iNumParams)
+{
+ int client = GetNativeCell(1);
+
+ if (IsValidClient(client))
+ {
+ ga_iSetTagAccess[client] = GetNativeCell(2);
+ return true;
+ }
+
+ return false;
+}
+
+public int Native_SetTagColorAccess(Handle hPlugin, int iNumParams)
+{
+ int client = GetNativeCell(1);
+
+ if (IsValidClient(client))
+ {
+ ga_iTagColorAccess[client] = GetNativeCell(2);
+ return true;
+ }
+
+ return false;
+}
+
+public int Native_SetNameColorAccess(Handle hPlugin, int iNumParams)
+{
+ int client = GetNativeCell(1);
+
+ if (IsValidClient(client))
+ {
+ ga_iNameColorAccess[client] = GetNativeCell(2);
+ return true;
+ }
+
+ return false;
+}
+
+public int Native_SetChatColorAccess(Handle hPlugin, int iNumParams)
+{
+ int client = GetNativeCell(1);
+
+ if (IsValidClient(client))
+ {
+ ga_iChatColorAccess[client] = GetNativeCell(2);
+ return true;
+ }
+
+ return false;
+}
+
+public int Native_SetCompleteAccess(Handle hPlugin, int iNumParams)
+{
+ int client = GetNativeCell(1);
+
+ if (IsValidClient(client))
+ {
+ int iAccess = GetNativeCell(2);
+ ga_iTagColorAccess[client] = iAccess;
+ ga_iNameColorAccess[client] = iAccess;
+ ga_iChatColorAccess[client] = iAccess;
+ ga_iSetTagAccess[client] = iAccess;
+ return true;
+ }
+
+ return false;
+}
+
+//chat ignoring
+public int Native_UpdateIgnoredArray(Handle plugin, int numParams)
+{
+ GetNativeArray(1, g_Ignored, sizeof(g_Ignored));
+
+ return 1;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+///////////////////////////// Client Connections /////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+void SetDefaults(int client)
+{
+ gaa_sSteamID[client][0] = "";
+ gaa_sSteamID[client][1] = "";
+ gaa_sSteamID[client][2] = "";
+ gaa_sSteamID[client][3] = "";
+ ga_sName[client] = "";
+ ga_sEscapedName[client] = "";
+ ga_bChatBlocked[client] = false;
+ ga_iTagVisible[client] = 0;
+ ga_iIsRestricted[client] = 0;
+ ga_iIsLoaded[client] = 0;
+ ga_iEntOverride[client] = 0;
+ gaa_iAdminOvrd[client][0] = 0;
+ gaa_iAdminOvrd[client][1] = 0;
+ gaa_iAdminOvrd[client][2] = 0;
+ gaa_iAdminOvrd[client][3] = 0;
+ gaa_sCleanSetupText[client][0] = "";
+ gaa_sCleanSetupText[client][1] = "";
+ gaa_sCleanSetupText[client][2] = "";
+ gaa_sCleanSetupText[client][3] = "";
+ ga_iChatMsgCnt[client] = 0;
+ ga_iChatSpamCnt[client] = 0;
+
+ ga_sTagColor[client] = "";
+ ga_sNameColor[client] = "";
+ ga_sChatColor[client] = "";
+ ga_sTag[client] = "";
+ ga_sExtTag[client] = "";
+ ga_sExtTagColor[client] = "";
+ ga_iTagColorAccess[client] = -1;
+ ga_iNameColorAccess[client] = -1;
+ ga_iChatColorAccess[client] = -1;
+ ga_iSetTagAccess[client] = -1;
+
+ b_InGroup[client] = false;
+}
+
+public void OnClientConnected(int client) //get names as soon as they connect
+{
+ SetDefaults(client);
+}
+
+public void OnClientDisconnect(int client)
+{
+ SetDefaults(client);
+}
+
+public void OnClientPostAdminCheck(int client)
+{
+ if (IsFakeClient(client))
+ {
+ Format(gaa_sSteamID[client][0], sizeof(gaa_sSteamID[][]), "BOT");
+ Format(gaa_sSteamID[client][1], sizeof(gaa_sSteamID[][]), "BOT");
+ Format(gaa_sSteamID[client][2], sizeof(gaa_sSteamID[][]), "BOT");
+ Format(gaa_sSteamID[client][3], sizeof(gaa_sSteamID[][]), "BOT");
+ return;
+ }
+
+ GetClientAuthId(client, AuthId_Steam2, gaa_sSteamID[client][0], sizeof(gaa_sSteamID[][]));
+ ReplaceString(gaa_sSteamID[client][0], sizeof(gaa_sSteamID[][]), "STEAM_1", "STEAM_0", false);
+ GetClientAuthId(client, AuthId_Steam2, gaa_sSteamID[client][1], sizeof(gaa_sSteamID[][]));
+ ReplaceString(gaa_sSteamID[client][1], sizeof(gaa_sSteamID[][]), "STEAM_0", "STEAM_1", false);
+ GetClientAuthId(client, AuthId_Steam3, gaa_sSteamID[client][2], sizeof(gaa_sSteamID[][]));
+ GetClientAuthId(client, AuthId_SteamID64, gaa_sSteamID[client][3], sizeof(gaa_sSteamID[][]));
+
+ if (StrContains(gaa_sSteamID[client][0], "STEAM_", true) == -1) //invalid - retry again
+ {
+ CreateTimer(10.0, RefreshSteamID, GetClientUserId(client), TIMER_FLAG_NO_MAPCHANGE);
+ }
+ else
+ {
+ LoadClientData(client);
+ }
+}
+
+public Action RefreshSteamID(Handle hTimer, any iUserID)
+{
+ int client = GetClientOfUserId(iUserID);
+ if (!IsValidClient(client))
+ {
+ return;
+ }
+
+ GetClientAuthId(client, AuthId_Steam2, gaa_sSteamID[client][0], sizeof(gaa_sSteamID[][]));
+ ReplaceString(gaa_sSteamID[client][0], sizeof(gaa_sSteamID[][]), "STEAM_1", "STEAM_0", false);
+ GetClientAuthId(client, AuthId_Steam2, gaa_sSteamID[client][1], sizeof(gaa_sSteamID[][]));
+ ReplaceString(gaa_sSteamID[client][1], sizeof(gaa_sSteamID[][]), "STEAM_0", "STEAM_1", false);
+ GetClientAuthId(client, AuthId_Steam3, gaa_sSteamID[client][2], sizeof(gaa_sSteamID[][]));
+ GetClientAuthId(client, AuthId_SteamID64, gaa_sSteamID[client][3], sizeof(gaa_sSteamID[][]));
+
+ if (StrContains(gaa_sSteamID[client][0], "STEAM_", true) == -1) //still invalid - retry again
+ {
+ CreateTimer(10.0, RefreshSteamID, GetClientUserId(client), TIMER_FLAG_NO_MAPCHANGE);
+ }
+ else
+ {
+ LoadClientData(client);
+ }
+}
+
+public Action RefreshSteamID_SendData(Handle hTimer, any iUserID)
+{
+ int client = GetClientOfUserId(iUserID);
+ if (!IsValidClient(client))
+ {
+ return;
+ }
+
+ GetClientAuthId(client, AuthId_Steam2, gaa_sSteamID[client][0], sizeof(gaa_sSteamID[][]));
+ ReplaceString(gaa_sSteamID[client][0], sizeof(gaa_sSteamID[][]), "STEAM_1", "STEAM_0", false);
+ GetClientAuthId(client, AuthId_Steam2, gaa_sSteamID[client][1], sizeof(gaa_sSteamID[][]));
+ ReplaceString(gaa_sSteamID[client][1], sizeof(gaa_sSteamID[][]), "STEAM_0", "STEAM_1", false);
+ GetClientAuthId(client, AuthId_Steam3, gaa_sSteamID[client][2], sizeof(gaa_sSteamID[][]));
+ GetClientAuthId(client, AuthId_SteamID64, gaa_sSteamID[client][3], sizeof(gaa_sSteamID[][]));
+
+ if (StrContains(gaa_sSteamID[client][0], "STEAM_", true) == -1) //still invalid - retry again
+ {
+ CreateTimer(10.0, RefreshSteamID_SendData, GetClientUserId(client), TIMER_FLAG_NO_MAPCHANGE);
+ }
+ else
+ {
+ SendClientSetupToDB(client);
+ }
+}
+
+public Action TimerCB_RetrySendData(Handle hTimer, any iUserID)
+{
+ int client = GetClientOfUserId(iUserID);
+ if (!IsValidClient(client))
+ {
+ return;
+ }
+
+ if (g_oDatabase != null) //still invalid - retry again
+ {
+ CreateTimer(5.0, TimerCB_RetrySendData, GetClientUserId(client), TIMER_FLAG_NO_MAPCHANGE);
+ }
+ else
+ {
+ SendClientSetupToDB(client);
+ }
+}
+
+public Action RepeatCheck(Handle hTimer, any iUserID)
+{
+ int client = GetClientOfUserId(iUserID);
+ if (IsValidClient(client))
+ {
+ LoadClientData(client);
+ }
+}
+
+bool HasFlags(int client, char[] sFlags)
+{
+ if (StrEqual(sFlags, "public", false) || StrEqual(sFlags, "", false))
+ {
+ return true;
+ }
+ else if (StrEqual(sFlags, "none", false)) //useful for some plugins
+ {
+ return false;
+ }
+ else if (!client) //if rcon
+ {
+ return true;
+ }
+ else if (CheckCommandAccess(client, "sm_not_a_command", ADMFLAG_ROOT, true))
+ {
+ return true;
+ }
+
+ AdminId id = GetUserAdmin(client);
+ if (id == INVALID_ADMIN_ID)
+ {
+ return false;
+ }
+ int flags, clientflags;
+ clientflags = GetUserFlagBits(client);
+
+ if (StrContains(sFlags, ";", false) != -1) //check if multiple strings
+ {
+ int i = 0, iStrCount = 0;
+ while (sFlags[i] != '\0')
+ {
+ if (sFlags[i++] == ';')
+ {
+ iStrCount++;
+ }
+ }
+ iStrCount++; //add one more for stuff after last comma
+
+ char[][] a_sTempArray = new char[iStrCount][30];
+ ExplodeString(sFlags, ";", a_sTempArray, iStrCount, 30);
+ bool bMatching = true;
+
+ for (i = 0; i < iStrCount; i++)
+ {
+ bMatching = true;
+ flags = ReadFlagString(a_sTempArray[i]);
+ for (int j = 0; j <= 20; j++)
+ {
+ if (bMatching) //if still matching, continue loop
+ {
+ if (flags & (1< g_cSpamMsgCnt.IntValue)
+ {
+ CreateTimer(0.1, TimerCB_MsgsTooFast, GetClientUserId(client), TIMER_FLAG_NO_MAPCHANGE);
+ if (g_cEnableSpamGag.BoolValue)
+ {
+ ga_iChatSpamCnt[client]++;
+ CreateTimer(g_cSpamGagDetectDuration.FloatValue, TimerCB_ReduceSpamCnt, GetClientUserId(client), TIMER_FLAG_NO_MAPCHANGE);
+ if (ga_iChatSpamCnt[client] > g_cSpamMsgGagCnt.IntValue)
+ {
+ BaseComm_SetClientGag(client, true);
+
+ if (!BaseComm_IsClientGagged(client)) //check if not already gagged - you *shouldnt* be able to get here if gagged, but sometimes if the server sends SayText2 msgs enough, it might send you here
+ {
+ CreateTimer(0.1, TimerCB_Muted, GetClientUserId(client), TIMER_FLAG_NO_MAPCHANGE);
+ }
+ }
+ }
+
+ return 0;
+ }
+ }
+ }
+
+ return 1;
+}
+
+public Action TimerCB_ReduceMsgCnt(Handle hTimer, any iUserID)
+{
+ int client = GetClientOfUserId(iUserID);
+ if (IsValidClient(client))
+ {
+ ga_iChatMsgCnt[client]--;
+ }
+}
+
+public Action TimerCB_ReduceSpamCnt(Handle hTimer, any iUserID)
+{
+ int client = GetClientOfUserId(iUserID);
+ if (IsValidClient(client))
+ {
+ ga_iChatSpamCnt[client]--;
+ }
+}
+
+public Action TimerCB_Gagged(Handle hTimer, any iUserID)
+{
+ int client = GetClientOfUserId(iUserID);
+ if (IsValidClient(client))
+ {
+ PrintToChat(client, "=================================");
+ PrintToChat(client, " ƪ(ツ)ノ Nice Try! ( ͡° ͜ʖ ͡°)");
+ PrintToChat(client, "--------- You're gagged and cannot speak. --------");
+ PrintToChat(client, "(ノಠ益ಠ)ノ彡┻━┻ YOU MAD? ლ(ಠ益ಠლ)");
+ PrintToChat(client, "=================================");
+ }
+}
+
+public Action TimerCB_MsgsTooFast(Handle hTimer, any iUserID)
+{
+ int client = GetClientOfUserId(iUserID);
+ if (IsValidClient(client))
+ {
+ PrintToChat(client, "%s%s%t", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), "TooFast");
+ }
+}
+
+public Action TimerCB_Muted(Handle hTimer, any iUserID)
+{
+ int client = GetClientOfUserId(iUserID);
+ if (IsValidClient(client))
+ {
+ PrintToChatAll("%s%s%N %t", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), client, "HasBeenGagged");
+ }
+}
+
+public Action Command_AdminChat(int client, const char[] sCommand, int iArgC)
+{
+ if (!g_cLog.BoolValue)
+ {
+ return Plugin_Continue;
+ }
+
+ char sBuffer[128], sName[MAX_NAME_LENGTH], sID[MAX_NAME_LENGTH];
+ GetCmdArgString(sBuffer, sizeof(sBuffer));
+
+ if (g_oDatabase != null)
+ {
+ if (!g_bMySQL)
+ {
+ if (IsValidClient(client))
+ {
+ strcopy(sID, sizeof(sID), gaa_sSteamID[client][0]);
+ GetClientName(client, sName, sizeof(sName));
+ }
+ else
+ {
+ Format(sID, sizeof(sID), "CONSOLE");
+ Format(sName, sizeof(sName), "CONSOLE");
+ }
+
+ int iNamePadding = 33 - strlen(sName);
+ char[] sPad2 = new char[iNamePadding];
+
+ char sLogMsg[256], sTeam[12];
+ Format(sPad2, iNamePadding, " ");
+ Format(sLogMsg, sizeof(sLogMsg), "%s%s", sPad2, sName);
+ Format(sTeam, sizeof(sTeam), " ADMIN ");
+ Format(sLogMsg, sizeof(sLogMsg), "[%20s][%s]%s: %s", sID, sTeam, sLogMsg, sBuffer);
+ LogToFileEx(g_sChatLogPath, sLogMsg);
+ }
+ else
+ {
+ SendChatToDB(client, sBuffer, sizeof(sBuffer), "ADMIN ALL CHAT");
+ }
+ }
+ return Plugin_Continue;
+}
+
+public Action Command_AdminOnlyChat(int client, const char[] sCommand, int iArgC)
+{
+ if (!g_cLog.BoolValue)
+ {
+ return Plugin_Continue;
+ }
+
+ char sBuffer[128], sName[MAX_NAME_LENGTH], sID[MAX_NAME_LENGTH];
+ GetCmdArgString(sBuffer, sizeof(sBuffer));
+
+ if (g_oDatabase != null)
+ {
+ if (!g_bMySQL)
+ {
+ if (IsValidClient(client))
+ {
+ strcopy(sID, sizeof(sID), gaa_sSteamID[client][0]);
+ GetClientName(client, sName, sizeof(sName));
+ }
+ else
+ {
+ Format(sID, sizeof(sID), "CONSOLE");
+ Format(sName, sizeof(sName), "CONSOLE");
+ }
+
+ int iNamePadding = 33 - strlen(sName);
+ char[] sPad2 = new char[iNamePadding];
+ char sLogMsg[256], sTeam[12];
+ Format(sPad2, iNamePadding, " ");
+ Format(sLogMsg, sizeof(sLogMsg), "%s%s", sPad2, sName);
+ Format(sTeam, sizeof(sTeam), "ADMIN ONLY");
+ Format(sLogMsg, sizeof(sLogMsg), "[%20s][%s]%s: %s", sID, sTeam, sLogMsg, sBuffer);
+ LogToFileEx(g_sChatLogPath, sLogMsg);
+ }
+ else
+ {
+ SendChatToDB(client, sBuffer, sizeof(sBuffer), "ADMIN ONLY");
+ }
+ }
+ return Plugin_Continue;
+}
+
+public Action Command_CSay(int client, const char[] sCommand, int iArgC)
+{
+ if (!g_cLog.BoolValue)
+ {
+ return Plugin_Continue;
+ }
+
+ char sBuffer[128], sName[MAX_NAME_LENGTH], sID[MAX_NAME_LENGTH];
+ GetCmdArgString(sBuffer, sizeof(sBuffer));
+
+ if (g_oDatabase != null)
+ {
+ if (!g_bMySQL)
+ {
+ if (IsValidClient(client))
+ {
+ strcopy(sID, sizeof(sID), gaa_sSteamID[client][0]);
+ GetClientName(client, sName, sizeof(sName));
+ }
+ else
+ {
+ Format(sID, sizeof(sID), "CONSOLE");
+ Format(sName, sizeof(sName), "CONSOLE");
+ }
+
+ int iNamePadding = 33 - strlen(sName);
+ char[] sPad2 = new char[iNamePadding];
+ char sLogMsg[256], sTeam[12];
+ Format(sPad2, iNamePadding, " ");
+ Format(sLogMsg, sizeof(sLogMsg), "%s%s", sPad2, sName);
+ Format(sTeam, sizeof(sTeam), " CSAY ");
+ Format(sLogMsg, sizeof(sLogMsg), "[%20s][%s]%s: %s", sID, sTeam, sLogMsg, sBuffer);
+ LogToFileEx(g_sChatLogPath, sLogMsg);
+ }
+ else
+ {
+ SendChatToDB(client, sBuffer, sizeof(sBuffer), "CENTER MSG");
+ }
+ }
+ return Plugin_Continue;
+}
+
+public Action Command_TSay(int client, const char[] sCommand, int iArgC)
+{
+ if (!g_cLog.BoolValue)
+ {
+ return Plugin_Continue;
+ }
+
+ char sBuffer[128], sName[MAX_NAME_LENGTH], sID[MAX_NAME_LENGTH];
+ GetCmdArgString(sBuffer, sizeof(sBuffer));
+
+ if (g_oDatabase != null)
+ {
+ if (!g_bMySQL)
+ {
+ if (IsValidClient(client))
+ {
+ strcopy(sID, sizeof(sID), gaa_sSteamID[client][0]);
+ GetClientName(client, sName, sizeof(sName));
+ }
+ else
+ {
+ Format(sID, sizeof(sID), "CONSOLE");
+ Format(sName, sizeof(sName), "CONSOLE");
+ }
+
+ int iNamePadding = 33 - strlen(sName);
+ char[] sPad2 = new char[iNamePadding];
+ char sLogMsg[256], sTeam[12];
+ Format(sPad2, iNamePadding, " ");
+ Format(sLogMsg, sizeof(sLogMsg), "%s%s", sPad2, sName);
+ Format(sTeam, sizeof(sTeam), " TSAY ");
+ Format(sLogMsg, sizeof(sLogMsg), "[%20s][%s]%s: %s", sID, sTeam, sLogMsg, sBuffer);
+ LogToFileEx(g_sChatLogPath, sLogMsg);
+ }
+ else
+ {
+ SendChatToDB(client, sBuffer, sizeof(sBuffer), "TOP MSG");
+ }
+ }
+
+ return Plugin_Continue;
+}
+
+public Action Command_MSay(int client, const char[] sCommand, int iArgC)
+{
+ if (!g_cLog.BoolValue)
+ {
+ return Plugin_Continue;
+ }
+
+ char sBuffer[128], sName[MAX_NAME_LENGTH], sID[MAX_NAME_LENGTH];
+ GetCmdArgString(sBuffer, sizeof(sBuffer));
+
+ if (g_oDatabase != null)
+ {
+ if (!g_bMySQL)
+ {
+ if (IsValidClient(client))
+ {
+ strcopy(sID, sizeof(sID), gaa_sSteamID[client][0]);
+ GetClientName(client, sName, sizeof(sName));
+ }
+ else
+ {
+ Format(sID, sizeof(sID), "CONSOLE");
+ Format(sName, sizeof(sName), "CONSOLE");
+ }
+
+ int iNamePadding = 33 - strlen(sName);
+ char[] sPad2 = new char[iNamePadding];
+ char sLogMsg[256], sTeam[12];
+ Format(sPad2, iNamePadding, " ");
+ Format(sLogMsg, sizeof(sLogMsg), "%s%s", sPad2, sName);
+ Format(sTeam, sizeof(sTeam), " MSAY ");
+ Format(sLogMsg, sizeof(sLogMsg), "[%20s][%s]%s: %s", sID, sTeam, sLogMsg, sBuffer);
+ LogToFileEx(g_sChatLogPath, sLogMsg);
+ }
+ else
+ {
+ SendChatToDB(client, sBuffer, sizeof(sBuffer), "MENU MSG");
+ }
+ }
+
+ return Plugin_Continue;
+}
+
+public Action Command_HSay(int client, const char[] sCommand, int iArgC)
+{
+ if (!g_cLog.BoolValue)
+ {
+ return Plugin_Continue;
+ }
+
+ char sBuffer[128], sName[MAX_NAME_LENGTH], sID[MAX_NAME_LENGTH];
+ GetCmdArgString(sBuffer, sizeof(sBuffer));
+
+ if (g_oDatabase != null)
+ {
+ if (!g_bMySQL)
+ {
+ if (IsValidClient(client))
+ {
+ strcopy(sID, sizeof(sID), gaa_sSteamID[client][0]);
+ GetClientName(client, sName, sizeof(sName));
+ }
+ else
+ {
+ Format(sID, sizeof(sID), "CONSOLE");
+ Format(sName, sizeof(sName), "CONSOLE");
+ }
+
+ int iNamePadding = 33 - strlen(sName);
+ char[] sPad2 = new char[iNamePadding];
+ char sLogMsg[256], sTeam[12];
+ Format(sPad2, iNamePadding, " ");
+ Format(sLogMsg, sizeof(sLogMsg), "%s%s", sPad2, sName);
+ Format(sTeam, sizeof(sTeam), " HSAY ");
+ Format(sLogMsg, sizeof(sLogMsg), "[%20s][%s]%s: %s", sID, sTeam, sLogMsg, sBuffer);
+ LogToFileEx(g_sChatLogPath, sLogMsg);
+ }
+ else
+ {
+ SendChatToDB(client, sBuffer, sizeof(sBuffer), "HINT MSG");
+ }
+ }
+
+ return Plugin_Continue;
+}
+
+public Action Command_PSay(int client, const char[] sCommand, int iArgC)
+{
+ if (!g_cLog.BoolValue)
+ {
+ return Plugin_Continue;
+ }
+
+ char sBuffer[128], sName[MAX_NAME_LENGTH], sID[MAX_NAME_LENGTH];
+ GetCmdArgString(sBuffer, sizeof(sBuffer));
+
+ if (g_oDatabase != null)
+ {
+ if (!g_bMySQL)
+ {
+ if (IsValidClient(client))
+ {
+ strcopy(sID, sizeof(sID), gaa_sSteamID[client][0]);
+ GetClientName(client, sName, sizeof(sName));
+ }
+ else
+ {
+ Format(sID, sizeof(sID), "CONSOLE");
+ Format(sName, sizeof(sName), "CONSOLE");
+ }
+
+ int iNamePadding = 33 - strlen(sName);
+ char[] sPad2 = new char[iNamePadding];
+ char sLogMsg[256], sTeam[12];
+ Format(sPad2, iNamePadding, " ");
+ Format(sLogMsg, sizeof(sLogMsg), "%s%s", sPad2, sName);
+ Format(sTeam, sizeof(sTeam), " PSAY ");
+ Format(sLogMsg, sizeof(sLogMsg), "[%20s][%s]%s: %s", sID, sTeam, sLogMsg, sBuffer);
+ LogToFileEx(g_sChatLogPath, sLogMsg);
+ }
+ else
+ {
+ SendChatToDB(client, sBuffer, sizeof(sBuffer), "PRIVATE MSG");
+ }
+ }
+
+ return Plugin_Continue;
+}
+
+void SendChatToDB(int client, char[] sMsg, int iSize, char[] sChatGrp)
+{
+ StripQuotes(sMsg);
+ if (StrEqual(sMsg, "", false))
+ {
+ return;
+ }
+ int iEscapeSize = 2*iSize + 1;
+ char[] sEscapedMsg = new char[iEscapeSize];
+ g_oDatabase.Escape(sMsg, sEscapedMsg, iEscapeSize);
+ char sIP[MAX_NAME_LENGTH], sCountry[45], sName[MAX_NAME_LENGTH], sSteamID[65];
+ char sQuery[1000];
+ if (IsValidClient(client, true))
+ {
+ if (IsFakeClient(client))
+ {
+ sIP = "BOT";
+ sCountry = "BOT";
+ sSteamID = "BOT";
+ }
+ else
+ {
+ GetClientIP(client, sIP, sizeof(sIP));
+ GeoipCountry(sIP, sCountry, sizeof(sCountry));
+ strcopy(sSteamID, sizeof(sSteamID), gaa_sSteamID[client][0]);
+ }
+ strcopy(sName, sizeof(sName), ga_sEscapedName[client]);
+ if (!StrEqual(sName, "", false))
+ {
+ GetClientName(client, ga_sEscapedName[client], sizeof(ga_sEscapedName[]));
+ CleanStringForSQL(ga_sEscapedName[client], sizeof(ga_sEscapedName[]));
+ strcopy(sName, sizeof(sName), ga_sEscapedName[client]);
+ }
+ }
+ else
+ {
+ sIP = "CONSOLE";
+ sCountry = "CONSOLE";
+ sSteamID = "CONSOLE";
+ sName = "CONSOLE";
+ }
+
+ CleanStringForSQL(sCountry, sizeof(sCountry));
+ //Format(sQuery, sizeof(sQuery), "INSERT INTO `ct_chatlogs` (steamid, mapname, server, playername, playerip, ip_country, chatmsg, chatgrp) VALUES ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s');", sSteamID, g_sMapName, g_sServerIP, sName, sIP, sCountry, sEscapedMsg, sChatGrp);
+ Format(sQuery, sizeof(sQuery), "INSERT INTO `ct_chatlogs` (steamid, server, playername, playerip, ip_country, chatmsg, chatgrp) VALUES ('%s', '%s', '%s', '%s', '%s', '%s', '%s');", sSteamID, g_sServerIP, sName, sIP, sCountry, sEscapedMsg, sChatGrp);
+ g_oDatabase.Query(SQLCallback_Void, sQuery, 4);
+}
+
+public Action Event_NameChange(Handle hEvent, const char[] sName, bool bDontBroadcast)
+{
+ int client = GetClientOfUserId(GetEventInt(hEvent, "userid"));
+ if (IsValidClient(client))
+ {
+ if (g_oDatabase != null)
+ {
+ GetClientName(client, ga_sEscapedName[client], sizeof(ga_sEscapedName[]));
+ strcopy(ga_sName[client], sizeof(ga_sName[]), ga_sEscapedName[client]);
+ CleanStringForSQL(ga_sEscapedName[client], sizeof(ga_sEscapedName[]));
+ }
+ }
+ return Plugin_Continue;
+}
+
+void Reload()
+{
+ LoadColorCfg();
+ LoadCustomConfigs();
+ for (int i = 1; i <= MaxClients; i++)
+ {
+ if (IsValidClient(i) && AreClientCookiesCached(i) && IsClientAuthorized(i))
+ {
+ OnClientConnected(i);
+ LoadClientData(i);
+ }
+ }
+
+ Call_StartForward(g_hLoadFwd);
+ Call_Finish();
+}
+
+public void OnClientSettingsChanged(int client)
+{
+ if (IsValidClient(client))
+ {
+ if (g_oDatabase != null)
+ {
+ GetClientName(client, ga_sEscapedName[client], sizeof(ga_sEscapedName[]));
+ strcopy(ga_sName[client], sizeof(ga_sName[]), ga_sEscapedName[client]);
+ CleanStringForSQL(ga_sEscapedName[client], sizeof(ga_sEscapedName[]));
+ CheckTag(client);
+ }
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+///////////////////////////// Admin Commands /////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+public Action Cmd_Reload(int client, int iArgs)
+{
+ if (client != 0)
+ {
+ if (!HasFlags(client, g_sAdminFlag))
+ {
+ PrintToConsole(client, "%sYou do not have access to this command!", g_sTag);
+ PrintToChat(client, "%s%sYou do not have access to this command!", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED));
+ return Plugin_Handled;
+ }
+ }
+
+ Reload();
+
+ ReplyToCommand(client, "%s%sColors setups are now reloaded.", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED));
+
+ return Plugin_Handled;
+}
+
+public Action Cmd_Unload(int client, int iArgs)
+{
+ if (client != 0)
+ {
+ if (!HasFlags(client, g_sAdminFlag))
+ {
+ PrintToConsole(client, "%sYou do not have access to this command!", g_sTag);
+ PrintToChat(client, "%s%sYou do not have access to this command!", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED));
+ return Plugin_Handled;
+ }
+ }
+
+ ReplyToCommand(client, "%s%sChat Tags is now unloaded until map change!", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED));
+
+ char sPluginName[128];
+ GetPluginFilename(INVALID_HANDLE, sPluginName, sizeof(sPluginName));
+ ServerCommand("sm plugins unload %s", sPluginName);
+
+ return Plugin_Handled;
+}
+
+public Action Cmd_RemoveOverride(int client, int iArgs)
+{
+ if (client != 0)
+ {
+ if (!HasFlags(client, g_sAdminFlag_Force))
+ {
+ PrintToConsole(client, "%sYou do not have access to this command!", g_sTag);
+ PrintToChat(client, "%s%sYou do not have access to this command!", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED));
+ return Plugin_Handled;
+ }
+ }
+
+ if (iArgs != 1)
+ {
+ if (client != 0)
+ {
+ PrintToConsole(client, "%sUsage: sm_removeoverride ", g_sTag);
+ PrintToChat(client, "%s%sUsage: sm_removeoverride ", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED));
+ }
+ else
+ {
+ ReplyToCommand(client, "%s%sUsage: sm_removeoverride ", g_sTag, CSGO_WHITE);
+ }
+ return Plugin_Handled;
+ }
+
+ char sTarget[65], sTargetName[MAX_TARGET_LENGTH];
+ GetCmdArg(1, sTarget, sizeof(sTarget));
+ int a_iTargets[MAXPLAYERS], iTargetCount;
+ bool bTN_ML;
+ if ((iTargetCount = ProcessTargetString(sTarget, client, a_iTargets, MAXPLAYERS, COMMAND_FILTER_NO_IMMUNITY, sTargetName, sizeof(sTargetName), bTN_ML)) <= 0)
+ {
+ ReplyToCommand(client, "%s%sNot found or invalid parameter.", g_sTag, CSGO_WHITE);
+ return Plugin_Handled;
+ }
+
+ for (int i = 0; i < iTargetCount; i++)
+ {
+ int target = a_iTargets[i];
+ if (IsValidClient(target))
+ {
+ gaa_iAdminOvrd[target][0] = 0;
+ gaa_iAdminOvrd[target][1] = 0;
+ gaa_iAdminOvrd[target][2] = 0;
+ gaa_iAdminOvrd[target][3] = 0;
+ SendClientSetupToDB(target);
+
+ LogMessage("%L has removed the admin overrides for player %L", client, target);
+ ReplyToCommand(client, "%s%sRemoved setup for player: %N", g_sTag, CSGO_WHITE);
+ }
+ }
+
+ return Plugin_Handled;
+}
+
+public Action Cmd_ForceTag(int client, int iArgs)
+{
+ if (client != 0)
+ {
+ if (!HasFlags(client, g_sAdminFlag_Force))
+ {
+ PrintToConsole(client, "%sYou do not have access to this command!", g_sTag);
+ PrintToChat(client, "%s%sYou do not have access to this command!", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED));
+ return Plugin_Handled;
+ }
+ }
+
+ if (iArgs < 2)
+ {
+ if (client != 0)
+ {
+ PrintToConsole(client, "%sUsage: sm_forcetag (pass \"skip\" to skip overriding one, or \"remove\" to reset it - omitted args assume skip).", g_sTag);
+ PrintToChat(client, "%s%sUsage: sm_forcetag (pass \"skip\" to skip overriding one, or \"remove\" to reset it - omitted args assume skip).", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED));
+ return Plugin_Handled;
+ }
+ else
+ {
+ ReplyToCommand(client, "%s%sUsage: sm_forcetag (pass \"skip\" to skip overriding one, or \"remove\" to reset it - omitted args assume skip).", g_sTag, CSGO_WHITE);
+ return Plugin_Handled;
+ }
+ }
+
+ char sTarget[65], sTargetName[MAX_TARGET_LENGTH];
+ GetCmdArg(1, sTarget, sizeof(sTarget));
+ int a_iTargets[MAXPLAYERS], iTargetCount;
+ bool bTN_ML;
+ if ((iTargetCount = ProcessTargetString(sTarget, client, a_iTargets, MAXPLAYERS, COMMAND_FILTER_NO_IMMUNITY, sTargetName, sizeof(sTargetName), bTN_ML)) <= 0)
+ {
+ ReplyToCommand(client, "%s%sNot found or invalid parameter.", g_sTag, CSGO_WHITE);
+ return Plugin_Handled;
+ }
+
+ int iSize = MAXTAGSIZE;
+ if (iSize < 30)
+ {
+ iSize = 30;
+ }
+
+ char[] sTag = new char[iSize];
+ char sTagColor[32], sNameColor[32], sChatColor[32];
+
+ GetCmdArg(2, sTag, iSize);
+
+ if (iArgs > 2)
+ {
+ GetCmdArg(3, sTagColor, sizeof(sTagColor));
+ }
+ else
+ {
+ Format(sTagColor, sizeof(sTagColor), "skip");
+ }
+
+ if (iArgs > 3)
+ {
+ GetCmdArg(4, sNameColor, sizeof(sNameColor));
+ }
+ else
+ {
+ Format(sNameColor, sizeof(sNameColor), "skip");
+ }
+
+ if (iArgs > 4)
+ {
+ GetCmdArg(5, sChatColor, sizeof(sChatColor));
+ }
+ else
+ {
+ Format(sChatColor, sizeof(sChatColor), "skip");
+ }
+
+ for (int i = 0; i < iTargetCount; i++)
+ {
+ int target = a_iTargets[i];
+ if (IsValidClient(target))
+ {
+ if (StrEqual(sTag, "remove", false))
+ {
+ ga_iTagVisible[target] = 0;
+ ga_sTag[target] = "";
+ gaa_iAdminOvrd[target][0] = 1;
+ gaa_sCleanSetupText[target][0] = "";
+ }
+ else if (!StrEqual(sTag, "skip", false))
+ {
+ ga_iTagVisible[target] = 3;
+ strcopy(ga_sTag[target], sizeof(ga_sTag[]), sTag);
+ strcopy(gaa_sCleanSetupText[target][0], sizeof(gaa_sCleanSetupText[][]), sTag);
+ gaa_iAdminOvrd[target][0] = 1;
+ gaa_sCleanSetupText[target][0] = "";
+ }
+
+ if (StrEqual(sTagColor, "remove", false))
+ {
+ ga_sTagColor[target] = "";
+ gaa_sCleanSetupText[target][1] = "";
+ gaa_iAdminOvrd[target][1] = 1;
+ }
+ else if (!StrEqual(sTagColor, "skip", false))
+ {
+ strcopy(ga_sTagColor[target], sizeof(ga_sTagColor[]), sTagColor);
+ strcopy(gaa_sCleanSetupText[target][1], sizeof(gaa_sCleanSetupText[][]), sTagColor);
+ gaa_iAdminOvrd[target][1] = 1;
+ }
+
+ if (StrEqual(sNameColor, "remove", false))
+ {
+ ga_sNameColor[target] = "";
+ gaa_sCleanSetupText[target][2] = "";
+ gaa_iAdminOvrd[target][2] = 1;
+ }
+ else if (!StrEqual(sNameColor, "skip", false))
+ {
+ strcopy(ga_sNameColor[target], sizeof(ga_sNameColor[]), sNameColor);
+ strcopy(gaa_sCleanSetupText[target][2], sizeof(gaa_sCleanSetupText[][]), sNameColor);
+ gaa_iAdminOvrd[target][2] = 1;
+ }
+
+ if (StrEqual(sChatColor, "remove", false))
+ {
+ ga_sChatColor[target] = "";
+ gaa_sCleanSetupText[target][3] = "";
+ gaa_iAdminOvrd[target][3] = 1;
+ }
+ else if (!StrEqual(sChatColor, "skip", false))
+ {
+ strcopy(ga_sChatColor[target], sizeof(ga_sChatColor[]), sChatColor);
+ strcopy(gaa_sCleanSetupText[target][3], sizeof(gaa_sCleanSetupText[][]), sChatColor);
+ gaa_iAdminOvrd[target][3] = 1;
+ }
+
+ FormatColors(target);
+ SendClientSetupToDB(target);
+
+ if (IsValidClient(client))
+ {
+ PrintToChat(client, "%s%sTags/colors successfully set to: %s%s %s%N: %sChat colors...", g_sTag, CSGO_WHITE, ga_sTagColor[target], ga_sTag[target], ga_sNameColor[target], target, ga_sChatColor[target]);
+ }
+
+ LogMessage("%L has set an admin overrides for player %L: %s%s %s%N: %sChat colors...", client, target, ga_sTagColor[target], ga_sTag[target], ga_sNameColor[target], target, ga_sChatColor[target]);
+ }
+ }
+
+ return Plugin_Handled;
+}
+
+public Action Cmd_RemoveTag(int client, int iArgs)
+{
+ if (!IsValidClient(client))
+ {
+ ReplyToCommand(client, "%s%sMust be in the server to execute command!", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED));
+ return Plugin_Handled;
+ }
+
+ if (iArgs != 1)
+ {
+ ReplyToCommand(client, "%s%sUsage: sm_removetag ", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED));
+ return Plugin_Handled;
+ }
+
+ if (!HasFlags(client, g_sAdminFlag))
+ {
+ PrintToConsole(client, "%s%sYou do not have access to this command!", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED));
+ PrintToChat(client, "%s%sYou do not have access to this command!", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED));
+ return Plugin_Handled;
+ }
+
+ char sTargetArg[MAX_NAME_LENGTH];
+ GetCmdArg(1,sTargetArg,sizeof(sTargetArg));
+
+ int iPlayers = SearchForPlayer(sTargetArg);
+ if (iPlayers == 0)
+ {
+ ReplyToCommand(client, "%s%sNo valid clients found!", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED));
+ return Plugin_Handled;
+ }
+ else if (iPlayers > 1)
+ {
+ ReplyToCommand(client, "%s%sMore than one matching player found!", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED));
+ return Plugin_Handled;
+ }
+
+ int target = 0;
+
+ if (iPlayers == -1)
+ {
+ ReplaceString(sTargetArg, sizeof(sTargetArg), "#", "", false);
+ target = GetClientOfUserId(StringToInt(sTargetArg));
+ }
+ else
+ {
+ target = FindTarget(client, sTargetArg, true);
+ }
+
+ if (!IsValidClient(target))
+ {
+ ReplyToCommand(client, "%s%sInvalid target!", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED));
+ return Plugin_Handled;
+ }
+
+ if (IsFakeClient(target))
+ {
+ ReplyToCommand(client, "%s%sCannot target bots!", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED));
+ return Plugin_Handled;
+ }
+
+ RemoveSetup(target);
+ ReplyToCommand(client, "%s%sTag settings for player '%s' are now set to default.", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), ga_sEscapedName[target]);
+ SendClientSetupToDB(target);
+
+ return Plugin_Handled;
+}
+
+void RemoveSetup(int client)
+{
+ if (!IsValidClient(client))
+ {
+ return;
+ }
+
+ ga_iTagVisible[client] = 0;
+ //ga_iIsRestricted[client] = 0;
+ ga_sTagColor[client] = "";
+ ga_sNameColor[client] = "";
+ ga_sChatColor[client] = "";
+ gaa_sCleanSetupText[client][0] = "";
+ gaa_sCleanSetupText[client][1] = "";
+ gaa_sCleanSetupText[client][2] = "";
+ gaa_sCleanSetupText[client][3] = "";
+ ga_sTag[client] = "";
+
+ if (g_cGrpsAfterRemove.BoolValue)
+ {
+ CheckForGroups(client);
+ }
+
+ FormatColors(client);
+ SendClientSetupToDB(client);
+}
+
+public Action Cmd_Restrict(int client, int iArgs)
+{
+ if (client == 0)
+ {
+ ReplyToCommand(client, "%s%sMust be in the server to execute command!", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED));
+ return Plugin_Handled;
+ }
+
+ if (iArgs != 1)
+ {
+ ReplyToCommand(client, "%s%sUsage: sm_restricttag ", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED));
+ return Plugin_Handled;
+ }
+
+ if (!HasFlags(client, g_sAdminFlag))
+ {
+ PrintToConsole(client, "%s%sYou do not have access to this command!", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED));
+ PrintToChat(client, "%s%sYou do not have access to this command!", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED));
+ return Plugin_Handled;
+ }
+
+ char sTargetArg[MAX_NAME_LENGTH];
+ GetCmdArg(1,sTargetArg,sizeof(sTargetArg));
+
+ int iPlayers = SearchForPlayer(sTargetArg);
+ if (iPlayers == 0)
+ {
+ ReplyToCommand(client, "%s%sNo valid clients found!", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED));
+ return Plugin_Handled;
+ }
+ else if (iPlayers > 1)
+ {
+ ReplyToCommand(client, "%s%sMore than one matching player found!", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED));
+ return Plugin_Handled;
+ }
+
+ int target = 0;
+
+ if (iPlayers == -1)
+ {
+ ReplaceString(sTargetArg, sizeof(sTargetArg), "#", "", false);
+ target = GetClientOfUserId(StringToInt(sTargetArg));
+ }
+ else
+ {
+ target = FindTarget(client, sTargetArg, true);
+ }
+
+ if (!IsValidClient(target))
+ {
+ ReplyToCommand(client, "%s%sInvalid target!", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED));
+ return Plugin_Handled;
+ }
+
+ if (IsFakeClient(target))
+ {
+ ReplyToCommand(client, "%s%sCannot target bots!", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED));
+ return Plugin_Handled;
+ }
+
+ RestrictPlayer(client,target);
+ SendClientSetupToDB(target);
+
+ return Plugin_Handled;
+}
+
+void RestrictPlayer(int client, int target)
+{
+ if (!IsValidClient(target))
+ {
+ PrintToConsole(client, "%s%sTarget '%s' is either not in game, or is a bot!", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), ga_sEscapedName[target]);
+ PrintToChat(client, "%s%sTarget '%s' is either not in game, or is a bot!", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), ga_sEscapedName[target]);
+ return;
+ }
+ else if (ga_iIsRestricted[target] == 1)
+ {
+ PrintToConsole(client, "%s%sTarget '%s' is already restricted!", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), ga_sEscapedName[target]);
+ PrintToChat(client, "%s%sTarget '%s' is already restricted!", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), ga_sEscapedName[target]);
+ return;
+ }
+ else
+ {
+ PrintToConsole(client, "%s%s'%s' is now restricted from changing their chat tag!", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), ga_sEscapedName[target]);
+ PrintToChatAll("%s%s%s%s has restricted \x01%s%s from changing their chat tag!", g_sTag, CSGO_WHITE, ga_sEscapedName[client], g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), ga_sEscapedName[target], g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED));
+
+ ga_iIsRestricted[target] = 1;
+ SendClientSetupToDB(target);
+ }
+}
+
+public Action Cmd_Unrestrict(int client, int iArgs)
+{
+ if (client == 0)
+ {
+ ReplyToCommand(client, "%s%sMust be in the server to execute command!", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED));
+ return Plugin_Handled;
+ }
+
+ if (iArgs != 1)
+ {
+ ReplyToCommand(client, "%s%sUsage: sm_unrestricttag ", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED));
+ return Plugin_Handled;
+ }
+
+ if (!HasFlags(client, g_sAdminFlag))
+ {
+ PrintToConsole(client, "%s%sYou do not have access to this command!", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED));
+ PrintToChat(client, "%s%sYou do not have access to this command!", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED));
+ return Plugin_Handled;
+ }
+
+ char sTargetArg[MAX_NAME_LENGTH];
+ GetCmdArg(1,sTargetArg,sizeof(sTargetArg));
+
+ int iPlayers = SearchForPlayer(sTargetArg);
+ if (iPlayers == 0)
+ {
+ ReplyToCommand(client, "%s%sNo valid clients found!", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED));
+ return Plugin_Handled;
+ }
+ else if (iPlayers > 1)
+ {
+ ReplyToCommand(client, "%s%sMore than one matching player found!", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED));
+ return Plugin_Handled;
+ }
+
+ int target = 0;
+
+ if (iPlayers == -1)
+ {
+ ReplaceString(sTargetArg, sizeof(sTargetArg), "#", "", false);
+ target = GetClientOfUserId(StringToInt(sTargetArg));
+ }
+ else
+ {
+ target = FindTarget(client, sTargetArg, true);
+ }
+
+ if (!IsValidClient(target))
+ {
+ ReplyToCommand(client, "%s%sInvalid target!", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED));
+ return Plugin_Handled;
+ }
+
+ if (IsFakeClient(target))
+ {
+ ReplyToCommand(client, "%s%sCannot target bots!", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED));
+ return Plugin_Handled;
+ }
+
+ UnrestrictPlayer(client,target);
+ SendClientSetupToDB(target);
+
+ return Plugin_Handled;
+}
+
+void UnrestrictPlayer(int client, int target)
+{
+ if (!IsValidClient(target))
+ {
+ PrintToConsole(client, "%s%sTarget '%s' is either not in game, or is a bot!", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), ga_sEscapedName[target]);
+ PrintToChat(client, "%s%sTarget '%s' is either not in game, or is a bot!", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), ga_sEscapedName[target]);
+ return;
+ }
+ else if (ga_iIsRestricted[target] == 0)
+ {
+ PrintToConsole(client, "%s%sTarget '%s' is not restricted!", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), ga_sEscapedName[target]);
+ PrintToChat(client, "%s%sTarget '%s' is not restricted!", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), ga_sEscapedName[target]);
+ return;
+ }
+ else
+ {
+ PrintToConsole(client, "%s%sTarget '%s' is now unrestricted from changing their chat tag!", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), ga_sEscapedName[target]);
+ PrintToChatAll("%s%s%s%s has unrestricted \x01%s%s from changing their chat tag!", g_sTag, CSGO_WHITE, ga_sEscapedName[client], g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), ga_sEscapedName[target], g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED));
+
+ ga_iIsRestricted[target] = 0;
+ SendClientSetupToDB(client);
+ }
+}
+
+////////////////////////////////////////////////////////////////////
+///////////////////////////// Commands /////////////////////////////
+////////////////////////////////////////////////////////////////////
+
+public Action Command_Tag(int client, int iArgs)
+{
+ if (!IsValidClient(client))
+ {
+ ReplyToCommand(client, "%s%s%t", g_sTag, CSGO_WHITE, "MustBeInGame");
+ return Plugin_Handled;
+ }
+
+ if (ga_iIsRestricted[client])
+ {
+ PrintToChat(client, "%s%s%t", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), "RestrictedChangingTags");
+ return Plugin_Handled;
+ }
+ if (!ga_iIsLoaded[client])
+ {
+ PrintToChat(client, "%s%s%t", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), "DisabledUntilCookiesCached");
+ return Plugin_Handled;
+ }
+
+ Menu_MainTag(client);
+ return Plugin_Handled;
+}
+
+public Action Command_BlockChat(int client, int iArgs)
+{
+ if (!IsValidClient(client))
+ {
+ ReplyToCommand(client, "%s%s%t", g_sTag, CSGO_WHITE, "MustBeInGame");
+ return Plugin_Handled;
+ }
+
+ if (!g_cAllowBlockChat.BoolValue)
+ {
+ ReplyToCommand(client, "%s%s%t", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), "DisabledByServerManager");
+ return Plugin_Handled;
+ }
+
+ if (ga_bChatBlocked[client])
+ {
+ ga_bChatBlocked[client] = false;
+ ReplyToCommand(client, "%s%s%t", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), "EnabledChatBlocker");
+ }
+ else
+ {
+ ga_bChatBlocked[client] = true;
+ ReplyToCommand(client, "%s%s%t", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), "DisabledChatBlocker");
+ }
+
+ return Plugin_Handled;
+}
+
+public Action Command_SetText(int client, int iArgs)
+{
+ if (!IsValidClient(client))
+ {
+ ReplyToCommand(client, "%s%s%t", g_sTag, CSGO_WHITE, "MustBeInGame");
+ return Plugin_Handled;
+ }
+
+ if (!HasFlags(client, g_sAccessFlag) && (ga_iSetTagAccess[client] != 1))
+ {
+ PrintToChat(client, "%s%s%t", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), "DoNotHaveAccess");
+ return Plugin_Handled;
+ }
+
+ if (ga_iIsRestricted[client])
+ {
+ PrintToChat(client, "%s%s%t", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), "RestrictedChangingTags");
+ return Plugin_Handled;
+ }
+
+ if (!ga_iSetTagAccess[client])
+ {
+ PrintToChat(client, "%s%s%t", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), "DeniedChangeTagByExternalPlugin");
+ return Plugin_Handled;
+ }
+
+ if (!ga_iIsLoaded[client])
+ {
+ PrintToChat(client, "%s%s%t", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), "DisabledUntilCookiesCached");
+ return Plugin_Handled;
+ }
+
+ if (!g_cEnableTags.BoolValue)
+ {
+ PrintToChat(client, "%s%s%t", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), "DisabledForEveryoneByServerManager");
+ return Plugin_Handled;
+ }
+
+ //char sArg[MAXTAGSIZE];
+ char sArg[128];
+ GetCmdArgString(sArg, sizeof(sArg));
+
+ int iBlockedName = 0;
+
+ for (int i = 0; i < g_aBlockedTags.Length; i++)
+ {
+ char sBuffer[75];
+ g_aBlockedTags.GetString(i, sBuffer, sizeof(sBuffer));
+ if (StrContains(sArg, sBuffer, false) != -1)
+ {
+ iBlockedName = 1;
+ }
+ }
+
+ if (iBlockedName)
+ {
+ if (!HasFlags(client, g_sAdminFlag))
+ {
+ PrintToChat(client, "%s%s%t", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), "TagBlockedFromUse");
+ return Plugin_Handled;
+ }
+ }
+
+ if (CheckTag(client))
+ {
+ return Plugin_Handled;
+ }
+
+ //pS Mod
+ if (HasFlags(client, g_sAccessFlag) || (ga_iTagColorAccess[client] == 1))
+ CFormatColor(sArg, sizeof(sArg), client, false);
+
+ PrintToChat(client, "%s%s%t %s", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), "TagSetTo", sArg);
+ strcopy(ga_sTag[client], sizeof(ga_sTag[]), sArg);
+ strcopy(gaa_sCleanSetupText[client][0], sizeof(gaa_sCleanSetupText[][]), sArg);
+ ga_iTagVisible[client] = 1;
+ FormatColors(client);
+ SendClientSetupToDB(client);
+
+ return Plugin_Handled;
+}
+
+public Action Command_TagColor(int client, int iArgs)
+{
+ if (!IsValidClient(client))
+ {
+ ReplyToCommand(client, "%s%s%t", g_sTag, CSGO_WHITE, "MustBeInGame");
+ return Plugin_Handled;
+ }
+
+ if (g_bCSGO)
+ {
+ ReplyToCommand(client, "%s\x03%t", g_sTag, "NotAvailableForCSGO");
+ return Plugin_Handled;
+ }
+ else if (g_bIns)
+ {
+ ReplyToCommand(client, "%s\x03%t", g_sTag, "NotAvailableForInsurgency");
+ return Plugin_Handled;
+ }
+
+ if (iArgs != 1)
+ {
+ ReplyToCommand(client, "%s\x03%t sm_tagcolor ", g_sTag, "Usage");
+ return Plugin_Handled;
+ }
+
+ if (!HasFlags(client, g_sAccessFlag) && (ga_iTagColorAccess[client] != 1))
+ {
+ PrintToChat(client, "%s\x03%t", g_sTag, "DoNotHaveAccess");
+ return Plugin_Handled;
+ }
+
+ if (!ga_iTagColorAccess[client])
+ {
+ PrintToChat(client, "%s%s%t", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), "DeniedChangeTagColorByExternalPlugin");
+ return Plugin_Handled;
+ }
+
+ if (ga_iIsRestricted[client])
+ {
+ PrintToChat(client, "%s\x03%t", g_sTag, "RestrictedChangingTagColors");
+ return Plugin_Handled;
+ }
+
+ if (!ga_iIsLoaded[client])
+ {
+ PrintToChat(client, "%s\x03%t", g_sTag, "DisabledUntilCookiesCached");
+ return Plugin_Handled;
+ }
+
+ if (!g_cEnableTagColors.BoolValue || !g_cEnableTags.BoolValue)
+ {
+ PrintToChat(client, "%s\x03%t", g_sTag, "DisabledForEveryoneByServerManager");
+ return Plugin_Handled;
+ }
+
+ char sArg[32];
+ GetCmdArgString(sArg, sizeof(sArg));
+ ReplaceString(sArg, sizeof(sArg), "#", "", false);
+
+ if (!IsValidHex(sArg))
+ {
+ ReplyToCommand(client, "%s\x03%t %t sm_tagcolor ", g_sTag, "InvalidHex", "Usage");
+ return Plugin_Handled;
+ }
+
+
+ if (CheckTag(client))
+ {
+ return Plugin_Handled;
+ }
+
+ PrintToChat(client, "\x01%s\x03%t \x07%s %s", g_sTag, "TagColorSetTo", sArg, sArg);
+ strcopy(ga_sTagColor[client], sizeof(ga_sTagColor[]), sArg);
+ strcopy(gaa_sCleanSetupText[client][1], sizeof(gaa_sCleanSetupText[][]), sArg);
+ FormatColors(client);
+ SendClientSetupToDB(client);
+
+ return Plugin_Handled;
+}
+
+public Action Command_NameColor(int client, int iArgs)
+{
+ if (!IsValidClient(client))
+ {
+ ReplyToCommand(client, "%s%s%t", g_sTag, CSGO_WHITE, "MustBeInGame");
+ return Plugin_Handled;
+ }
+
+ if (g_bCSGO)
+ {
+ ReplyToCommand(client, "%s\x03%t", g_sTag, "NotAvailableForCSGO");
+ return Plugin_Handled;
+ }
+ else if (g_bIns)
+ {
+ ReplyToCommand(client, "%s\x03%t", g_sTag, "NotAvailableForInsurgency");
+ return Plugin_Handled;
+ }
+
+ if (iArgs != 1)
+ {
+ ReplyToCommand(client, "%s\x03%t sm_namecolor ", g_sTag, "Usage");
+ return Plugin_Handled;
+ }
+
+ if (!HasFlags(client, g_sAccessFlag) && (ga_iNameColorAccess[client] != 1))
+ {
+ PrintToChat(client, "%s\x03%t", g_sTag, "DoNotHaveAccess");
+ return Plugin_Handled;
+ }
+
+ if (!ga_iNameColorAccess[client])
+ {
+ PrintToChat(client, "%s%s%t", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), "DeniedChangeNameColorByExternalPlugin");
+ return Plugin_Handled;
+ }
+
+ if (ga_iIsRestricted[client])
+ {
+ PrintToChat(client, "%s\x03%t", g_sTag, "RestrictedChangingNameColors");
+ return Plugin_Handled;
+ }
+
+ if (!ga_iIsLoaded[client])
+ {
+ PrintToChat(client, "%s\x03%t", g_sTag, "DisabledUntilCookiesCached");
+ return Plugin_Handled;
+ }
+
+ if (!g_cEnableNameColors.BoolValue)
+ {
+ PrintToChat(client, "%s\x03%t", g_sTag, "DisabledForEveryoneByServerManager");
+ return Plugin_Handled;
+ }
+
+ char sArg[32];
+ GetCmdArgString(sArg, sizeof(sArg));
+ ReplaceString(sArg, sizeof(sArg), "#", "", false);
+
+ if (!IsValidHex(sArg))
+ {
+ ReplyToCommand(client, "%s\x03%t %t sm_tagcolor ", g_sTag, "InvalidHex", "Usage");
+ return Plugin_Handled;
+ }
+
+ if (CheckTag(client))
+ {
+ return Plugin_Handled;
+ }
+
+ PrintToChat(client, "\x01%s\x03%t \x07%s %s", g_sTag, "NameColorSetTo", sArg, sArg);
+ strcopy(ga_sNameColor[client], sizeof(ga_sNameColor[]), sArg);
+ strcopy(gaa_sCleanSetupText[client][2], sizeof(gaa_sCleanSetupText[][]), sArg);
+ FormatColors(client);
+ SendClientSetupToDB(client);
+
+ return Plugin_Handled;
+}
+
+public Action Command_ChatColor(int client, int iArgs)
+{
+ if (!IsValidClient(client))
+ {
+ ReplyToCommand(client, "%s%s%t", g_sTag, CSGO_WHITE, "MustBeInGame");
+ return Plugin_Handled;
+ }
+
+ if (g_bCSGO)
+ {
+ ReplyToCommand(client, "%s\x03%t", g_sTag, "NotAvailableForCSGO");
+ return Plugin_Handled;
+ }
+ else if (g_bIns)
+ {
+ ReplyToCommand(client, "%s\x03%t", g_sTag, "NotAvailableForInsurgency");
+ return Plugin_Handled;
+ }
+
+ if (iArgs != 1)
+ {
+ ReplyToCommand(client, "%s\x03%t sm_chatcolor ", g_sTag, "Usage");
+ return Plugin_Handled;
+ }
+
+ if (!HasFlags(client, g_sAccessFlag) && (ga_iChatColorAccess[client] != 1))
+ {
+ PrintToChat(client, "%s\x03%t", g_sTag, "DoNotHaveAccess");
+ return Plugin_Handled;
+ }
+
+ if (!ga_iChatColorAccess[client])
+ {
+ PrintToChat(client, "%s%s%t", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), "DeniedChangeChatColorByExternalPlugin");
+ return Plugin_Handled;
+ }
+
+ if (ga_iIsRestricted[client])
+ {
+ PrintToChat(client, "%s\x03%t", g_sTag, "RestrictedChangingChatColors");
+ return Plugin_Handled;
+ }
+
+ if (!ga_iIsLoaded[client])
+ {
+ PrintToChat(client, "%s\x03%t", g_sTag, "DisabledUntilCookiesCached");
+ return Plugin_Handled;
+ }
+
+ if (!g_cEnableChatColors.BoolValue)
+ {
+ PrintToChat(client, "%s\x03%t", g_sTag, "DisabledForEveryoneByServerManager");
+ return Plugin_Handled;
+ }
+
+ char sArg[32];
+ GetCmdArgString(sArg, sizeof(sArg));
+ ReplaceString(sArg, sizeof(sArg), "#", "", false);
+
+ if (!IsValidHex(sArg))
+ {
+ ReplyToCommand(client, "%s\x03%t %t sm_tagcolor ", g_sTag, "InvalidHex", "Usage");
+ return Plugin_Handled;
+ }
+
+ if (CheckTag(client))
+ {
+ return Plugin_Handled;
+ }
+
+ PrintToChat(client, "\x01%s\x03%t \x07%s %s", g_sTag, "ChatColorSetTo", sArg, sArg);
+ strcopy(ga_sChatColor[client], sizeof(ga_sChatColor[]), sArg);
+ strcopy(gaa_sCleanSetupText[client][3], sizeof(gaa_sCleanSetupText[][]), ga_sChatColor[client]);
+ FormatColors(client);
+ SendClientSetupToDB(client);
+
+ return Plugin_Handled;
+}
+
+public Action Command_CheckTag(int client, int iArgs)
+{
+ if (iArgs != 1)
+ {
+ ReplyToCommand(client, "%s%s%t sm_checktag ", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), "Usage");
+ return Plugin_Handled;
+ }
+
+ char sTarget[65], sTargetName[MAX_TARGET_LENGTH];
+ GetCmdArg(1, sTarget, sizeof(sTarget));
+ int a_iTargets[MAXPLAYERS], iTargetCount;
+ bool bTN_ML;
+ if ((iTargetCount = ProcessTargetString(sTarget, client, a_iTargets, MAXPLAYERS, COMMAND_FILTER_NO_IMMUNITY, sTargetName, sizeof(sTargetName), bTN_ML)) <= 0)
+ {
+ ReplyToCommand(client, "%t", "NotFoundOrInvalidParameter");
+ return Plugin_Handled;
+ }
+
+ for (int i = 0; i < iTargetCount; i++)
+ {
+ int target = a_iTargets[i];
+ if (IsValidClient(target))
+ {
+ char sHiddenTag[10], sRestricted[24], sSetTag[10], sTagColor[10], sNameColor[10], sChatColor[10];
+ if (ga_iTagVisible[target])
+ {
+ sHiddenTag = "Visible";
+ }
+ else
+ {
+ sHiddenTag = "Hidden";
+ }
+
+ if (ga_iIsRestricted[target])
+ {
+ sRestricted = "Restricted";
+ }
+ else
+ {
+ sRestricted = "Not Restricted";
+ }
+
+ if (!ga_iSetTagAccess[target])
+ {
+ sSetTag = "Denied";
+ }
+ else if (ga_iSetTagAccess[target] == 1)
+ {
+ sSetTag = "Granted";
+ }
+ else
+ {
+ sSetTag = "Default";
+ }
+
+ if (!ga_iTagColorAccess[target])
+ {
+ sTagColor = "Denied";
+ }
+ else if (ga_iTagColorAccess[target] == 1)
+ {
+ sTagColor = "Granted";
+ }
+ else
+ {
+ sTagColor = "Default";
+ }
+
+ if (!ga_iNameColorAccess[target])
+ {
+ sNameColor = "Denied";
+ }
+ else if (ga_iNameColorAccess[target] == 1)
+ {
+ sNameColor = "Granted";
+ }
+ else
+ {
+ sNameColor = "Default";
+ }
+
+ if (!ga_iChatColorAccess[target])
+ {
+ sChatColor = "Denied";
+ }
+ else if (ga_iChatColorAccess[target] == 1)
+ {
+ sChatColor = "Granted";
+ }
+ else
+ {
+ sChatColor = "Default";
+ }
+
+ if (IsValidClient(client))
+ {
+ PrintToConsole(client, "-------------------------- PLAYER TAG INFO --------------------------");
+ PrintToConsole(client, "Player: %L, Status: \"%s\", Tag status: \"%s\"", target, sRestricted, sHiddenTag);
+ PrintToConsole(client, "Tag Color: \"%s\", Name Color: \"%s\", Chat Color: \"%s\"", gaa_sCleanSetupText[target][1], gaa_sCleanSetupText[target][2], gaa_sCleanSetupText[target][3]);
+ PrintToConsole(client, "Access overrides - Set Tag: %s, Tag color: %s", sSetTag, sTagColor);
+ PrintToConsole(client, "Access overrides - Name color: %s, Chat color: %s", sNameColor, sChatColor);
+ }
+ else
+ {
+ ReplyToCommand(client, "-------------------------- PLAYER TAG INFO --------------------------");
+ ReplyToCommand(client, "Player: %L, Status: \"%s\", Tag status: \"%s\"", target, sRestricted, sHiddenTag);
+ ReplyToCommand(client, "Tag Color: \"%s\", Name Color: \"%s\", Chat Color: \"%s\"", gaa_sCleanSetupText[target][1], gaa_sCleanSetupText[target][2], gaa_sCleanSetupText[target][3]);
+ ReplyToCommand(client, "Access overrides - Set Tag: %s, Tag color: %s", sSetTag, sTagColor);
+ ReplyToCommand(client, "Access overrides - Name color: %s, Chat color: %s", sNameColor, sChatColor);
+ }
+ }
+ }
+
+ if (IsValidClient(client))
+ {
+ PrintToChat(client, "%s%s%t", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), "CheckConsole");
+ }
+
+ return Plugin_Handled;
+}
+
+int SearchForPlayer(const char[] sTarget)
+{
+ if (sTarget[0] == '#')
+ {
+ bool bUserID = true;
+ for (int i = 1; i < strlen(sTarget); i++)
+ {
+ if (!IsCharNumeric(sTarget[i]))
+ {
+ bUserID = false;
+ break;
+ }
+ }
+
+ if (bUserID)
+ {
+ return -1;
+ }
+ }
+
+ char sName[MAX_NAME_LENGTH];
+ int iNumberFound = 0;
+
+ for (int i = 1; i <= MaxClients; i++)
+ {
+ if (IsValidClient(i))
+ {
+ GetClientName(i, sName, sizeof(sName));
+
+ if (StrContains(sName, sTarget, false) != -1)
+ {
+ iNumberFound++;
+ }
+ }
+ }
+ return iNumberFound;
+}
+
+//check if name/tag combo should be allowed - this section can be used to define setups that are not allowed
+bool CheckTag(int client)
+{
+ //check if imitating console
+ char sName[MAX_NAME_LENGTH];
+ GetClientName(client, sName, sizeof(sName));
+ TrimString(sName);
+ if (StrEqual(sName, g_sConsoleName, false))
+ {
+ RemoveSetup(client);
+ PrintToChat(client, "%s\x07%t", g_sTag, "MimickingCONSOLE");
+ return true;
+ }
+
+ return false;
+}
+
+///////////////////////////////////////////////////////////////////
+///////////////////////////// Cookies /////////////////////////////
+///////////////////////////////////////////////////////////////////
+
+void LoadClientData(int client)
+{
+ if (!IsValidClient(client))
+ {
+ return;
+ }
+
+ if (StrContains(gaa_sSteamID[client][0], "STEAM_", true) == -1) //invalid
+ {
+ CreateTimer(2.0, RefreshSteamID, GetClientUserId(client), TIMER_FLAG_NO_MAPCHANGE);
+ return;
+ }
+
+ if (g_oDatabase != null)
+ {
+ GetClientName(client, ga_sEscapedName[client], sizeof(ga_sEscapedName[]));
+ strcopy(ga_sName[client], sizeof(ga_sName[]), ga_sEscapedName[client]);
+ CleanStringForSQL(ga_sEscapedName[client], sizeof(ga_sEscapedName[]));
+
+ char sQuery[300];
+ Format(sQuery, sizeof(sQuery), "SELECT `visible`, `restricted`, `tagtext`, `tagcolor`, `namecolor`, `chatcolor`, `ovrd_ttext`, `ovrd_tcolor`, `ovrd_ncolor`, `ovrd_ccolor` FROM `%s` WHERE (`steamid` = '%s') ORDER BY `id` LIMIT 1", g_sDBTableName, gaa_sSteamID[client][0]);
+ g_oDatabase.Query(SQLCallback_LoadPlayer, sQuery, GetClientUserId(client));
+ }
+ else
+ {
+ CreateTimer(5.0, RepeatCheck, GetClientUserId(client), TIMER_FLAG_NO_MAPCHANGE);
+ }
+}
+
+public void SQLCallback_LoadPlayer(Database oDB, DBResultSet oResults, const char[] sError, any iUserID)
+{
+ if (oResults == INVALID_HANDLE)
+ {
+ //SetFailState("Player load callback error: %s", sError);
+ LogMessage("Player load callback error: %s", sError);
+ return;
+ }
+
+ int client = GetClientOfUserId(iUserID);
+ if (!IsValidClient(client))
+ {
+ return;
+ }
+ else
+ {
+ if (oResults.RowCount == 1)
+ {
+ /* TABLE SETUP:
+ `id` int(20) PRIMARY KEY
+ `steamid` VARCHAR(32) NOT NULL
+ `tagtext` VARCHAR(32) NOT NULL
+ `visible` INT(2) NOT NULL
+ `restricted` INT(2) NOT NULL
+ `tagcolor` VARCHAR(10) NOT NULL
+ `namecolor` VARCHAR(10) NOT NULL
+ `chatcolor` VARCHAR(10) NOT NULL
+ `ovrd_ttext` INT(2) NOT NULL
+ `ovrd_tcolor` INT(2) NOT NULL
+ `ovrd_ncolor` INT(2) NOT NULL
+ `ovrd_ccolor` INT(2) NOT NULL
+ QUERY ORDER:
+ `visible`, `restricted`, `tagtext`, `tagcolor`, `namecolor`, `chatcolor`, `ovrd_ttext`, `ovrd_tcolor`, `ovrd_ncolor`, `ovrd_ccolor`
+ */
+ char sBuffer[128];
+ oResults.FetchRow();
+ IntToString(oResults.FetchInt(0), sBuffer, sizeof(sBuffer));
+ if (StrEqual(sBuffer, "", false) || (StrEqual(sBuffer, "0", false) && !ga_iTagVisible[client])) //if they dont have access and the DB has it saved as disabled
+ {
+ ga_iTagVisible[client] = 0;
+ }
+ else
+ {
+ ga_iTagVisible[client] = StringToInt(sBuffer);
+ }
+
+ IntToString(oResults.FetchInt(1), sBuffer, sizeof(sBuffer));
+ if (StrEqual(sBuffer, "", false))
+ {
+ ga_iIsRestricted[client] = 0;
+ }
+ else
+ {
+ ga_iIsRestricted[client] = StringToInt(sBuffer);
+ }
+ oResults.FetchString(2, ga_sTag[client], sizeof(ga_sTag[]));
+ oResults.FetchString(3, ga_sTagColor[client], sizeof(ga_sTagColor[]));
+ oResults.FetchString(4, ga_sNameColor[client], sizeof(ga_sNameColor[]));
+ oResults.FetchString(5, ga_sChatColor[client], sizeof(ga_sChatColor[]));
+ gaa_iAdminOvrd[client][0] = oResults.FetchInt(6);
+ gaa_iAdminOvrd[client][1] = oResults.FetchInt(7);
+ gaa_iAdminOvrd[client][2] = oResults.FetchInt(8);
+ gaa_iAdminOvrd[client][3] = oResults.FetchInt(9);
+
+ CheckTag(client); //this is put before group tags so that group ones can bypass this if the manager wants it (e.g. have root admins be tagged "CONSOLE"?)
+ //load group setups if they dont have access per defined access flags.
+ if (!HasFlags(client, g_sAccessFlag))
+ {
+ CheckForGroups(client);
+ }
+ else if (!ga_iTagVisible[client]) //has flags, but "disabled" (if they dont want a tag, they can set the text to "").
+ { //This isnt combined with the above check since they might not have the flag, but their cookie says "enabled". That would block the groups for such a situation.
+ CheckForGroups(client);
+ }
+
+ FormatColors(client);
+ ga_iIsLoaded[client] = 1;
+ Call_StartForward(g_hClientLoadFwd);
+ Call_PushCell(client);
+ Call_Finish();
+ }
+ else if (!oResults.RowCount)
+ {
+ SendClientSetupToDB(client, false, true);
+ //load group setups if they dont have access per defined access flags.
+ if (!HasFlags(client, g_sAccessFlag))
+ {
+ CheckForGroups(client);
+ }
+ else if (!ga_iTagVisible[client]) //has flags, but "disabled" (if they dont want a tag, they can set the text to "").
+ { //This isnt combined with the above check since they might not have the flag, but their cookie says "enabled". That would block the groups for such a situation.
+ CheckForGroups(client);
+ }
+
+ FormatColors(client);
+ ga_iIsLoaded[client] = 1;
+ Call_StartForward(g_hClientLoadFwd);
+ Call_PushCell(client);
+ Call_Finish();
+ }
+ else if (g_oDatabase == null)
+ {
+ CreateTimer(5.0, RepeatCheck, GetClientUserId(client), TIMER_FLAG_NO_MAPCHANGE);
+ }
+ }
+}
+
+void SendClientSetupToDB(int client, bool bBlockAccess = false, bool bDefault = false)
+{
+ if (!IsValidClient(client))
+ {
+ return;
+ }
+
+ if (StrContains(gaa_sSteamID[client][0], "STEAM_", true) == -1) //invalid
+ {
+ CreateTimer(2.0, RefreshSteamID_SendData, GetClientUserId(client), TIMER_FLAG_NO_MAPCHANGE);
+ return;
+ }
+
+ if (g_oDatabase != null)
+ {
+ /* TABLE SETUP:
+ `id` INT(20) PRIMARY KEY
+ `steamid` VARCHAR(32) NOT NULL
+ `tagtext` VARCHAR(32) NOT NULL
+ `visible` INT(2) NOT NULL
+ `restricted` INT(2) NOT NULL
+ `tagcolor` VARCHAR(10) NOT NULL
+ `namecolor` VARCHAR(10) NOT NULL
+ `chatcolor` VARCHAR(10) NOT NULL
+ `ovrd_ttext` INT(2) NOT NULL
+ `ovrd_tcolor` INT(2) NOT NULL
+ `ovrd_ncolor` INT(2) NOT NULL
+ `ovrd_ccolor` INT(2) NOT NULL
+ */
+
+ char sQuery[750], sTagText[MAX_NAME_LENGTH * 2 + 1], sTagColor[MAX_NAME_LENGTH * 2 + 1], sNameColor[MAX_NAME_LENGTH * 2 + 1], sChatColor[MAX_NAME_LENGTH * 2 + 1];
+ if (bDefault)
+ {
+ Format(sQuery, sizeof(sQuery), "INSERT INTO `%s` (`steamid`, `tagtext`, `visible`, `restricted`, `tagcolor`, `namecolor`, `chatcolor`, `ovrd_ttext`, `ovrd_tcolor`, `ovrd_ncolor`, `ovrd_ccolor`) VALUES('%s', '', 0, 0, '', '', '', 0, 0, 0, 0)", g_sDBTableName, gaa_sSteamID[client][0]);
+ g_oDatabase.Query(SQLCallback_Void, sQuery, 2);
+ }
+ else
+ {
+ g_oDatabase.Escape(ga_sTag[client], sTagText, sizeof(sTagText));
+ g_oDatabase.Escape(gaa_sCleanSetupText[client][1], sTagColor, sizeof(sTagColor));
+ g_oDatabase.Escape(gaa_sCleanSetupText[client][2], sNameColor, sizeof(sNameColor));
+ g_oDatabase.Escape(gaa_sCleanSetupText[client][3], sChatColor, sizeof(sChatColor));
+ Format(sQuery, sizeof(sQuery), "UPDATE `%s` SET `tagtext`='%s', `visible`=%i, `restricted`=%i, `tagcolor`='%s', `namecolor`='%s', `chatcolor`='%s', `ovrd_ttext`=%i, `ovrd_tcolor`=%i, `ovrd_ncolor`=%i, `ovrd_ccolor`=%i WHERE `steamid` = '%s'", g_sDBTableName, sTagText, ((ga_iTagVisible[client] && !bBlockAccess) ? 1 : 0), ga_iIsRestricted[client], sTagColor, sNameColor, sChatColor, gaa_iAdminOvrd[client][0], gaa_iAdminOvrd[client][1], gaa_iAdminOvrd[client][2], gaa_iAdminOvrd[client][3], gaa_sSteamID[client][0]);
+ g_oDatabase.Query(SQLCallback_Void, sQuery, 3);
+ }
+ }
+ else
+ {
+ CreateTimer(5.0, TimerCB_RetrySendData, GetClientUserId(client), TIMER_FLAG_NO_MAPCHANGE);
+ }
+}
+
+//////////////////////////////////////////////////////////////////
+///////////////////////////// Setups /////////////////////////////
+//////////////////////////////////////////////////////////////////
+
+void FormatColors(int client)
+{
+ ConvertColor(ga_sExtTagColor[client], sizeof(ga_sExtTagColor[]));
+ ConvertColor(ga_sTagColor[client], sizeof(ga_sTagColor[])/*, client*/);
+ ConvertColor(ga_sNameColor[client], sizeof(ga_sNameColor[])/*, client*/);
+ ConvertColor(ga_sChatColor[client], sizeof(ga_sChatColor[])/*, client*/);
+
+ if (!gaa_iAdminOvrd[client][0] && (!g_cEnableTags.BoolValue || (!HasFlags(client, g_sAccessFlag) && (ga_iSetTagAccess[client] != 1) && !ga_iGroupMatch[client]) || (ga_iSetTagAccess[client] == 0) || !ga_iTagVisible[client])) //remove tag if no access or custom configs disabled by server manager or disabled by user
+ {
+ Format(ga_sTag[client], sizeof(ga_sTag[]), "");
+ gaa_sCleanSetupText[client][0] = "";
+ }
+
+ if (!gaa_iAdminOvrd[client][1] && (!g_cEnableTagColors.BoolValue || (!HasFlags(client, g_sAccessFlag) && (ga_iTagColorAccess[client] != 1) && !ga_iGroupMatch[client]) || (ga_iTagColorAccess[client] == 0) || !ga_iTagVisible[client])) //remove tag color if no access or custom tag colors disabled by server manager or disabled by user
+ {
+ Format(ga_sTagColor[client], sizeof(ga_sTagColor[]), "");
+ gaa_sCleanSetupText[client][1] = "";
+ }
+
+ if (!gaa_iAdminOvrd[client][2] && (!g_cEnableNameColors.BoolValue || (!HasFlags(client, g_sAccessFlag) && (ga_iNameColorAccess[client] != 1) && !ga_iGroupMatch[client]) || (ga_iNameColorAccess[client] == 0) || !ga_iTagVisible[client])) //remove name color if no access or custom name colors disabled by server manager or disabled by user
+ {
+ Format(ga_sNameColor[client], sizeof(ga_sNameColor[]), "");
+ gaa_sCleanSetupText[client][2] = "";
+ }
+
+ if (!gaa_iAdminOvrd[client][3] && (!g_cEnableChatColors.BoolValue || (!HasFlags(client, g_sAccessFlag) && (ga_iChatColorAccess[client] != 1) && !ga_iGroupMatch[client]) || (ga_iChatColorAccess[client] == 0) || !ga_iTagVisible[client])) //remove chat color if no access or custom chat colors disabled by server manager or disabled by user
+ {
+ Format(ga_sChatColor[client], sizeof(ga_sChatColor[]), "");
+ gaa_sCleanSetupText[client][3] = "";
+ }
+}
+
+void ConvertColor(char[] sString, int iSize/*, client = 0*/)
+{
+ if (StrEqual(sString, "", false))
+ {
+ return;
+ }
+
+ if (g_bCSGO)
+ {
+ bool bBuffer = true; //checking if numeric only
+ for (int i = 1; i < strlen(sString); i++)
+ {
+ if (!IsCharNumeric(sString[i]))
+ {
+ bBuffer = false;
+ break;
+ }
+ }
+
+ if (!bBuffer) //convert text into numbers
+ {
+ char sBuffer[32];
+ for (int i = 0; i < g_aColorName.Length; i++)
+ {
+ g_aColorName.GetString(i, sBuffer, sizeof(sBuffer));
+ if (StrEqual(sBuffer, sString, false))
+ {
+ g_aColorCode.GetString(i, sBuffer, sizeof(sBuffer));
+ strcopy(sString, iSize, sBuffer);
+ bBuffer = true;
+ break;
+ }
+ }
+ }
+
+ if (!bBuffer)
+ {
+ return;
+ }
+
+ if ((strlen(sString) <= 3) && !StrEqual(sString, "", false))
+ {
+ switch(StringToInt(sString))
+ {
+ case 1:
+ {
+ Format(sString, iSize, "\x01");
+ }
+ case 2:
+ {
+ Format(sString, iSize, "\x02");
+ }
+ case 3:
+ {
+ Format(sString, iSize, "\x03");
+ }
+ case 4:
+ {
+ Format(sString, iSize, "\x04");
+ }
+ case 5:
+ {
+ Format(sString, iSize, "\x05");
+ }
+ case 6:
+ {
+ Format(sString, iSize, "\x06");
+ }
+ case 7:
+ {
+ Format(sString, iSize, "\x07");
+ }
+ case 8:
+ {
+ Format(sString, iSize, "\x08");
+ }
+ case 9:
+ {
+ Format(sString, iSize, "\x09");
+ }
+ case 10:
+ {
+ Format(sString, iSize, "\x0A");
+ }
+ case 11:
+ {
+ Format(sString, iSize, "\x0B");
+ }
+ case 12:
+ {
+ Format(sString, iSize, "\x0C");
+ }
+ case 13:
+ {
+ Format(sString, iSize, "\x0D");
+ }
+ case 14:
+ {
+ Format(sString, iSize, "\x0E");
+ }
+ case 15:
+ {
+ Format(sString, iSize, "\x0F");
+ }
+ case 16: //not recommended - messes with formatting
+ {
+ Format(sString, iSize, "\x10");
+ }
+ case -1:
+ {
+ Format(sString, iSize, "\x01");
+ }
+ }
+ }
+ }
+ else if (g_bIns)
+ {
+ bool bBuffer = true; //checking if numeric only
+ for (int i = 1; i < strlen(sString); i++)
+ {
+ if (!IsCharNumeric(sString[i]))
+ {
+ bBuffer = false;
+ break;
+ }
+ }
+
+ if (!bBuffer) //convert text into numbers
+ {
+ char sBuffer[32];
+ for (int i = 0; i < g_aColorName.Length; i++)
+ {
+ g_aColorName.GetString(i, sBuffer, sizeof(sBuffer));
+ if (StrEqual(sBuffer, sString, false))
+ {
+ g_aColorCode.GetString(i, sBuffer, sizeof(sBuffer));
+ strcopy(sString, iSize, sBuffer);
+ bBuffer = true;
+ break;
+ }
+ }
+ }
+
+ if (!bBuffer)
+ {
+ return;
+ }
+ if ((strlen(sString) <= 3) && !StrEqual(sString, "", false))
+ {
+ switch(StringToInt(sString))
+ {
+ case 1: //white
+ {
+ Format(sString, iSize, "\x01");
+ }
+ case 2: //team
+ {
+ Format(sString, iSize, "\x03");
+ }
+ case 3: //lime
+ {
+ Format(sString, iSize, "\x04");
+ }
+ case 4: //light green
+ {
+ Format(sString, iSize, "\x05");
+ }
+ case 5: //olive
+ {
+ Format(sString, iSize, "\x06");
+ }
+ case 6: //banana yellow
+ {
+ Format(sString, iSize, "\x11");
+ }
+ case 7: //Dark yellow
+ {
+ Format(sString, iSize, "\x12");
+ }
+ /*case 8: //light blue
+ {
+ Format(sString, iSize, "\x03");
+ if (IsValidClient(client))
+ {
+ ga_iEntOverride[client] = 1;
+ }
+ }
+ case 9: //attempt
+ {
+ Format(sString, iSize, "{redblue}");
+ //Format(sString, iSize, "\x03");
+ if (IsValidClient(client))
+ {
+ ga_iEntOverride[client] = 3;
+ }
+ }*/
+ case -1:
+ {
+ Format(sString, iSize, "\x01");
+ }
+ }
+ }
+ }
+ else
+ {
+ if (strlen(sString) == 6)
+ {
+ if (IsValidHex(sString))
+ {
+ Format(sString, iSize, "\x07%s", sString);
+ }
+ else
+ {
+ char sBuffer[32];
+ for (int i = 0; i < g_aColorName.Length; i++)
+ {
+ g_aColorName.GetString(i, sBuffer, sizeof(sBuffer));
+ if (StrEqual(sBuffer, sString, false))
+ {
+ g_aColorCode.GetString(i, sBuffer, sizeof(sBuffer));
+ Format(sString, iSize, "\x07%s", sBuffer);
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+void ConvertConsoleColor(char[] sString, int iSize)
+{
+ if (g_bCSGO)
+ {
+ bool bBuffer = true; //checking if numeric only
+ for (int i = 1; i < strlen(sString); i++)
+ {
+ if (!IsCharNumeric(sString[i]))
+ {
+ bBuffer = false;
+ break;
+ }
+ }
+
+ if (!bBuffer)
+ {
+ return;
+ }
+
+ if ((strlen(sString) <= 3) && !StrEqual(sString, "", false))
+ {
+ switch(StringToInt(sString))
+ {
+ case 1:
+ {
+ Format(sString, iSize, "\x01");
+ }
+ case 2:
+ {
+ Format(sString, iSize, "\x02");
+ }
+ case 3:
+ {
+ Format(sString, iSize, "\x03");
+ }
+ case 4:
+ {
+ Format(sString, iSize, "\x04");
+ }
+ case 5:
+ {
+ Format(sString, iSize, "\x05");
+ }
+ case 6:
+ {
+ Format(sString, iSize, "\x06");
+ }
+ case 7:
+ {
+ Format(sString, iSize, "\x07");
+ }
+ case 8:
+ {
+ Format(sString, iSize, "\x08");
+ }
+ case 9:
+ {
+ Format(sString, iSize, "\x09");
+ }
+ case 10:
+ {
+ Format(sString, iSize, "\x0A");
+ }
+ case 11:
+ {
+ Format(sString, iSize, "\x0B");
+ }
+ case 12:
+ {
+ Format(sString, iSize, "\x0C");
+ }
+ case 13:
+ {
+ Format(sString, iSize, "\x0D");
+ }
+ case 14:
+ {
+ Format(sString, iSize, "\x0E");
+ }
+ case 15:
+ {
+ Format(sString, iSize, "\x0F");
+ }
+ case 16: //not recommended - messes with formatting
+ {
+ Format(sString, iSize, "\x10");
+ }
+ }
+ }
+ }
+}
+
+void CheckForGroups(int client)
+{
+ KeyValues oKeyValues = new KeyValues("Setups");
+
+ if (!FileExists(g_sGroupPath))
+ {
+ SetFailState("Configuration file %s not found!", g_sGroupPath);
+ return;
+ }
+
+ if (!oKeyValues.ImportFromFile(g_sGroupPath))
+ {
+ SetFailState("Improper structure for configuration file %s!", g_sGroupPath);
+ return;
+ }
+
+ if (oKeyValues.GotoFirstSubKey(true))
+ {
+ do
+ {
+ char sFlags[30], sSectionName[100];
+ oKeyValues.GetSectionName(sSectionName, sizeof(sSectionName));
+ oKeyValues.GetString("flags", sFlags, sizeof(sFlags), "public");
+
+ if (!StrEqual(sSectionName, gaa_sSteamID[client][0], false) && !StrEqual(sSectionName, gaa_sSteamID[client][1], false) && !StrEqual(sSectionName, gaa_sSteamID[client][2], false) && !StrEqual(sSectionName, gaa_sSteamID[client][3], false))
+ {
+ if (HasOnlyNumbers(sSectionName) || (StrContains(sSectionName, ":", false) != -1)) //if steam ID //if it's a steam ID, and not theirs, skip
+ {
+ continue;
+ }
+
+ if (StrContains(sSectionName, "TEAM_", false) == 0) //if the string STARTS with TEAM_ , check if team matches - Note: need to check if at start, else "STEAM_" would trigger it
+ {
+ char sTeam[32];
+ strcopy(sTeam, sizeof(sTeam), sSectionName);
+ ReplaceString(sTeam, sizeof(sTeam), "TEAM_", "", false);
+ if (IsNumeric(sTeam))
+ {
+ int iTeam = StringToInt(sTeam);
+ if (GetClientTeam(client) != iTeam)
+ {
+ continue;
+ }
+ }
+ }
+
+ if (!StrEqual(sFlags, "public", false) || !StrEqual(sFlags, "", false)) //not a steam ID or team setup, so check if public
+ {
+ if (!HasFlags(client, sFlags)) //not public - check flags required. This one is on a separate line in case HasFlags might error while checking "public" (since there is no 'u' flag)
+ {
+ continue;
+ }
+ }
+ }
+ //match found - get setup
+ oKeyValues.GetString("tagstring", ga_sTag[client], sizeof(ga_sTag[]), "");
+ oKeyValues.GetString("tagcolor", ga_sTagColor[client], sizeof(ga_sTagColor[]), "");
+ oKeyValues.GetString("namecolor", ga_sNameColor[client], sizeof(ga_sNameColor[]), "");
+ oKeyValues.GetString("chatcolor", ga_sChatColor[client], sizeof(ga_sChatColor[]), "");
+ strcopy(gaa_sCleanSetupText[client][0], sizeof(gaa_sCleanSetupText[][]), ga_sTag[client]);
+ strcopy(gaa_sCleanSetupText[client][1], sizeof(gaa_sCleanSetupText[][]), ga_sTagColor[client]);
+ strcopy(gaa_sCleanSetupText[client][2], sizeof(gaa_sCleanSetupText[][]), ga_sNameColor[client]);
+ strcopy(gaa_sCleanSetupText[client][3], sizeof(gaa_sCleanSetupText[][]), ga_sChatColor[client]);
+ ga_iGroupMatch[client] = 1;
+ ga_iTagVisible[client] = 2;
+ break; //break loop to avoid excess processing if a matching setup is found
+ }
+ while (oKeyValues.GotoNextKey(false));
+ oKeyValues.GoBack(); //go back one level (to main level) to leave for other functions using kv tree - may not be needed here since we re-parse each time players connect, but is good practice.
+ }
+ else
+ {
+ //SetFailState("Can't find first subkey in configuration file %s!", g_sGroupPath); //commented out to allow zero setups
+ PrintToServer("Can't find first subkey in configuration file %s!", g_sGroupPath);
+ }
+ delete oKeyValues;
+}
+
+bool HasOnlyNumbers(char[] sString)
+{
+ for (int i = 0; i < strlen(sString); i++)
+ {
+ if (!IsCharNumeric(sString[i]))
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool IsNumeric(char[] sString)
+{
+ for (int i = 0; i < strlen(sString); i++)
+ {
+ if (!IsCharNumeric(sString[i]))
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool IsValidClient(int client, bool bAllowBots = false, bool bAllowDead = true)
+{
+ if (!(1 <= client <= MaxClients) || !IsClientInGame(client) || (IsFakeClient(client) && !bAllowBots) || IsClientSourceTV(client) || IsClientReplay(client) || (!IsPlayerAlive(client) && !bAllowDead))
+ {
+ return false;
+ }
+ return true;
+}
+
+bool IsValidHex(const char[] sHex)
+{
+ if (g_oRegexHex.Match(sHex))
+ {
+ return true;
+ }
+ return false;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+///////////////////////////// Client Prefs Menu /////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+stock void SetPanelTitleEx(Panel panel, bool onlyIfEmpty = false, const char[] text, any ...)
+{
+ char sBuffer[256];
+ VFormat(sBuffer, sizeof(sBuffer), text, 4);
+ panel.SetTitle(sBuffer, onlyIfEmpty);
+}
+
+stock int DrawPanelItemEx(Panel panel, int style = ITEMDRAW_DEFAULT, const char[] text, any ...)
+{
+ char sBuffer[256];
+ VFormat(sBuffer, sizeof(sBuffer), text, 4);
+ return panel.DrawItem(sBuffer, style);
+}
+
+stock bool AddMenuItemEx(Menu menu, int style = ITEMDRAW_DEFAULT, const char[] info, const char[] display, any ...)
+{
+ char sBuffer[256];
+ VFormat(sBuffer, sizeof(sBuffer), display, 5);
+ return menu.AddItem(info, sBuffer, style);
+}
+
+public void Menu_ClientPrefs(int client, CookieMenuAction action, any info, char[] sBuffer, int iMaxLen)
+{
+ if (action == CookieMenuAction_DisplayOption)
+ {
+ FormatEx(sBuffer, iMaxLen, "%T", "ClientPrefs Title", client);
+ }
+ if (action == CookieMenuAction_SelectOption)
+ {
+ if (ga_iIsRestricted[client])
+ {
+ PrintToChat(client, "%s%s%t", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), "RestrictedChangingTags");
+ return;
+ }
+ else
+ {
+ Menu_MainTag(client);
+ }
+ }
+}
+
+int Menu_MainTag(int client)
+{
+ Panel hPanel = CreatePanel();
+ SetPanelTitleEx(hPanel, _, "%T", "Chat Tags", client);
+ if ((HasFlags(client, g_sAccessFlag) || (ga_iSetTagAccess[client] == 1)) && ga_iSetTagAccess[client] && (g_cEnableTags.BoolValue || (ga_iSetTagAccess[client] == 1)))
+ {
+ if (ga_iTagVisible[client])
+ {
+ DrawPanelItemEx(hPanel, _, "%T", "Disable Tag", client);
+ }
+ else
+ {
+ DrawPanelItemEx(hPanel, _, "%T", "Enable Tag", client);
+ }
+ }
+ else
+ {
+ DrawPanelItemEx(hPanel, ITEMDRAW_DISABLED, "%T", "Enable Tag", client);
+ }
+
+ if ((HasFlags(client, g_sAccessFlag) || (ga_iTagColorAccess[client] == 1)) && ga_iTagColorAccess[client] && (g_cEnableTagColors.BoolValue || (ga_iTagColorAccess[client] == 1)))
+ {
+ DrawPanelItemEx(hPanel, _, "%T", "Tag Colors", client);
+ }
+ else
+ {
+ DrawPanelItemEx(hPanel, ITEMDRAW_DISABLED, "%T", "Tag Colors", client);
+ }
+
+ //name colors menu
+ if ((HasFlags(client, g_sAccessFlag) || (ga_iNameColorAccess[client] == 1)) && ga_iNameColorAccess[client] && (g_cEnableNameColors.BoolValue || (ga_iNameColorAccess[client] == 1)))
+ {
+ DrawPanelItemEx(hPanel, _, "%T", "Name Colors", client);
+ }
+ else
+ {
+ DrawPanelItemEx(hPanel, ITEMDRAW_DISABLED, "%T", "Name Colors", client);
+ }
+ //chat colors menu
+ if ((HasFlags(client, g_sAccessFlag) || (ga_iChatColorAccess[client] == 1)) && ga_iChatColorAccess[client] && (g_cEnableChatColors.BoolValue || (ga_iChatColorAccess[client] == 1)))
+ {
+ DrawPanelItemEx(hPanel, _, "%T", "Chat Colors", client);
+ }
+ else
+ {
+ DrawPanelItemEx(hPanel, ITEMDRAW_DISABLED, "%T", "Chat Colors", client);
+ }
+
+ DrawPanelItemEx(hPanel, _, "%T", "Check Setup of Player", client);
+ hPanel.DrawItem("------------------------", ITEMDRAW_RAWLINE);
+ DrawPanelItemEx(hPanel, ITEMDRAW_RAWLINE, "%T", "Chat Command To Change Tag", client);
+ DrawPanelItemEx(hPanel, ITEMDRAW_RAWLINE, "%T", "Tag Text You Want", client);
+ DrawPanelItemEx(hPanel, ITEMDRAW_RAWLINE, "%T", "Characters Max", client, MAXTAGSIZE);
+ hPanel.DrawItem("", ITEMDRAW_SPACER);
+ hPanel.DrawItem("Back", ITEMDRAW_CONTROL);
+ hPanel.DrawItem("", ITEMDRAW_SPACER);
+ hPanel.DrawItem("Exit", ITEMDRAW_CONTROL);
+
+ hPanel.Send(client, PanelHandler_MenuMainTag, MENU_TIME_FOREVER);
+ delete hPanel;
+
+ return 2;
+}
+
+public int PanelHandler_MenuMainTag(Menu oMenu, MenuAction action, int client, int param2)
+{
+ switch(action)
+ {
+ case MenuAction_End:
+ {
+ EmitSoundToClient(client, "buttons/combine_button7.wav");
+ delete oMenu;
+ }
+ case MenuAction_Cancel:
+ {
+ if (param2 == MenuCancel_ExitBack)
+ {
+ ShowCookieMenu(client);
+ }
+ }
+ case MenuAction_Select:
+ {
+ switch(param2)
+ {
+ case 1:
+ {
+ if (HasFlags(client, g_sAccessFlag) || (ga_iSetTagAccess[client] == 1) || (ga_iTagColorAccess[client] == 1))
+ {
+ EmitSoundToClient(client, "buttons/button14.wav");
+ if (!ga_iTagVisible[client])
+ {
+ ga_iTagVisible[client] = 1;
+ PrintToChat(client, "%s%s%t", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), "TagEnabled");
+ RecheckSetup(client, true);
+ }
+ else
+ {
+ ga_iTagVisible[client] = 0;
+ PrintToChat(client, "%s%s%t", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), "TagDisabled");
+ RecheckSetup(client, true);
+ }
+ Menu_MainTag(client);
+ }
+ else
+ {
+ EmitSoundToClient(client, "buttons/button14.wav");
+ PrintToChat(client, "%s%s%t", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), "DoNotHaveAccess");
+ Menu_MainTag(client);
+ }
+ }
+ case 2:
+ {
+ if (HasFlags(client, g_sAccessFlag) || (ga_iTagColorAccess[client] == 1))
+ {
+ EmitSoundToClient(client, "buttons/button14.wav");
+ Menu_TagColor(client);
+ }
+ else
+ {
+ EmitSoundToClient(client, "buttons/button14.wav");
+ PrintToChat(client, "%s%s%t", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), "DoNotHaveAccess");
+ Menu_MainTag(client);
+ }
+ }
+ case 3:
+ {
+ if (HasFlags(client, g_sAccessFlag) || (ga_iNameColorAccess[client] == 1))
+ {
+ EmitSoundToClient(client, "buttons/button14.wav");
+ Menu_NameColor(client);
+ }
+ else
+ {
+ EmitSoundToClient(client, "buttons/button14.wav");
+ PrintToChat(client, "%s%s%t", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), "DoNotHaveAccess");
+ Menu_MainTag(client);
+ }
+ }
+ case 4:
+ {
+ if (HasFlags(client, g_sAccessFlag) || (ga_iChatColorAccess[client] == 1))
+ {
+ EmitSoundToClient(client, "buttons/button14.wav");
+ Menu_ChatColor(client);
+ }
+ else
+ {
+ EmitSoundToClient(client, "buttons/button14.wav");
+ PrintToChat(client, "%s%s%t", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), "DoNotHaveAccess");
+ Menu_MainTag(client);
+ }
+ }
+ case 5:
+ {
+ if (HasFlags(client, g_sAdminFlag))
+ {
+ EmitSoundToClient(client, "buttons/button14.wav");
+ Displaymenu_Player(client, "sm_checktag", "%t", "Check Tag Setup For");
+ }
+ else
+ {
+ EmitSoundToClient(client, "buttons/button14.wav");
+ PrintToChat(client, "%s%s%t", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), "DoNotHaveAccess");
+ Menu_MainTag(client);
+ }
+ }
+ case 7:
+ {
+ EmitSoundToClient(client, "buttons/button14.wav");
+ ShowCookieMenu(client);
+ }
+ case 9:
+ {
+ EmitSoundToClient(client, "buttons/combine_button7.wav");
+ }
+ }
+ }
+ }
+
+ return;
+}
+
+void RecheckSetup(int client, bool bBlockAccess = false)
+{
+ CheckTag(client); //this is put before group tags so that group ones can bypass this if the manager wants it (e.g. have root admins be tagged "CONSOLE"?)
+
+ //load group setups if they dont have access per defined access flags.
+ if (!(HasFlags(client, g_sAccessFlag) || StrEqual(g_sAccessFlag, "", false)))
+ {
+ CheckForGroups(client);
+ }
+ else if (ga_iTagVisible[client] != 1) //has flags, but "disabled" (if they dont want a tag, they can set the text to "").
+ { //This isnt combined with the above check since they might not have the flag, but their cookie says "enabled". That would block the groups for such a situation.
+ CheckForGroups(client);
+ }
+
+ FormatColors(client);
+ SendClientSetupToDB(client, bBlockAccess);
+
+ Call_StartForward(g_hClientReloadFwd);
+ Call_PushCell(client);
+ Call_Finish();
+}
+
+public void Menu_TagColor(int client)
+{
+ if (ga_iIsRestricted[client])
+ {
+ PrintToChat(client, "%s%s%t", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), "RestrictedChangingTagColors");
+ return;
+ }
+
+ if (!ga_iChatColorAccess[client])
+ {
+ PrintToChat(client, "%s%s%t", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), "DeniedChangeChatColorByExternalPlugin");
+ return;
+ }
+
+ if (!ga_iTagColorAccess[client])
+ {
+ PrintToChat(client, "%s%s%t", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), "DeniedChangeTagColorByExternalPlugin");
+ return;
+ }
+
+ if (!g_cEnableTagColors.BoolValue || !g_cEnableTags.BoolValue)
+ {
+ PrintToChat(client, "%s%s%t", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), "DisabledForEveryoneByServerManager");
+ return;
+ }
+
+ Menu oMenu = new Menu(MenuCallback_TagColor);
+ oMenu.SetTitle("%T", "Tag Colors", client);
+ oMenu.ExitBackButton = true;
+ oMenu.Pagination = 6;
+
+ AddMenuItemEx(oMenu, _, "Reset", "%T", "Reset", client);
+ if (!g_bCSGO && !g_bIns)
+ {
+ AddMenuItemEx(oMenu, _, "SetManually", "%T", "Define Your Own Color", client);
+ }
+
+ char sColorIndex[5], sColorName[32], sBuffer[32];
+ for (int i = 0; i < g_aColorName.Length; i++)
+ {
+ IntToString(i, sColorIndex, sizeof(sColorIndex));
+ g_aColorName.GetString(i, sColorName, sizeof(sColorName));
+ g_aColorCode.GetString(i, sBuffer, sizeof(sBuffer));
+ if (StringToInt(sBuffer) < 0)
+ oMenu.AddItem(sColorIndex, sColorName, ITEMDRAW_DISABLED);
+ else
+ oMenu.AddItem(sColorIndex, sColorName);
+ }
+
+ oMenu.Display(client, MENU_TIME_FOREVER);
+}
+
+public int MenuCallback_TagColor(Menu oMenu, MenuAction action, int client, int param2)
+{
+ if (action == MenuAction_End)
+ {
+ delete oMenu;
+ return;
+ }
+
+ if (action == MenuAction_Cancel && param2 == MenuCancel_ExitBack)
+ {
+ Menu_MainTag(client);
+ return;
+ }
+
+ if (action == MenuAction_Select)
+ {
+ char sBuffer[32];
+ oMenu.GetItem(param2, sBuffer, sizeof(sBuffer));
+
+ if (StrEqual(sBuffer, "Reset"))
+ {
+ PrintToChat(client, "%s%s%t", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), "ResetTagColor");
+ ga_sTagColor[client] = "";
+ gaa_sCleanSetupText[client][1] = "";
+ FormatColors(client);
+ SendClientSetupToDB(client);
+ }
+ else if (StrEqual(sBuffer, "SetManually"))
+ {
+ PrintToChat(client, "%s\x03%t", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), "ToDefineYourOwnTagColor");
+ }
+ else
+ {
+ int iColorIndex = StringToInt(sBuffer);
+ g_aColorCode.GetString(iColorIndex, sBuffer, sizeof(sBuffer));
+ strcopy(ga_sTagColor[client], sizeof(ga_sTagColor[]), sBuffer);
+ strcopy(gaa_sCleanSetupText[client][1], sizeof(gaa_sCleanSetupText[][]), ga_sTagColor[client]);
+ FormatColors(client);
+ g_aColorName.GetString(iColorIndex, sBuffer, sizeof(sBuffer));
+ PrintToChat(client, "\x01%s%s%t %s%s", g_sTag, CSGO_WHITE, "TagColorSetTo", ga_sTagColor[client], sBuffer);
+ SendClientSetupToDB(client);
+ }
+
+ Menu_MainTag(client);
+ }
+}
+
+public void Menu_NameColor(int client)
+{
+ if (ga_iIsRestricted[client])
+ {
+ PrintToChat(client, "%s%s%t", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), "RestrictedChangingNameColors");
+ return;
+ }
+
+ if (!ga_iNameColorAccess[client])
+ {
+ PrintToChat(client, "%s%s%t", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), "DeniedChangeNameColorByExternalPlugin");
+ return;
+ }
+
+ if (!g_cEnableNameColors.BoolValue)
+ {
+ PrintToChat(client, "%s%s%t", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), "DisabledForEveryoneByServerManager");
+ return;
+ }
+
+ Menu oMenu = new Menu(MenuCallback_NameColor);
+ oMenu.SetTitle("%T", "Name Colors", client);
+ oMenu.ExitBackButton = true;
+ oMenu.Pagination = 6;
+
+ AddMenuItemEx(oMenu, _, "Reset", "%T", "Reset", client);
+ if (!g_bCSGO && !g_bIns)
+ {
+ AddMenuItemEx(oMenu, _, "SetManually", "%T", "Define Your Own Color", client);
+ }
+
+ char sColorIndex[5], sColorName[32], sBuffer[32];
+ for (int i = 0; i < g_aColorName.Length; i++)
+ {
+ IntToString(i, sColorIndex, sizeof(sColorIndex));
+ g_aColorName.GetString(i, sColorName, sizeof(sColorName));
+ g_aColorCode.GetString(i, sBuffer, sizeof(sBuffer));
+ if (StringToInt(sBuffer) < 0)
+ oMenu.AddItem(sColorIndex, sColorName, ITEMDRAW_DISABLED);
+ else
+ oMenu.AddItem(sColorIndex, sColorName);
+ }
+
+ oMenu.Display(client, MENU_TIME_FOREVER);
+}
+
+public int MenuCallback_NameColor(Menu oMenu, MenuAction action, int client, int param2)
+{
+ if (action == MenuAction_End)
+ {
+ delete oMenu;
+ return;
+ }
+
+ if (action == MenuAction_Cancel && param2 == MenuCancel_ExitBack)
+ {
+ Menu_MainTag(client);
+ return;
+ }
+
+ if (action == MenuAction_Select)
+ {
+ char sBuffer[32];
+ oMenu.GetItem(param2, sBuffer, sizeof(sBuffer));
+
+ if (StrEqual(sBuffer, "Reset"))
+ {
+ PrintToChat(client, "%s%s%t", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), "ResetNameColor");
+ ga_sNameColor[client] = "";
+ gaa_sCleanSetupText[client][2] = "";
+ FormatColors(client);
+ SendClientSetupToDB(client);
+ }
+ else if (StrEqual(sBuffer, "SetManually"))
+ {
+ PrintToChat(client, "%s\x03%t", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), "ToDefineYourOwnNameColor");
+ }
+ else
+ {
+ int iColorIndex = StringToInt(sBuffer);
+ g_aColorCode.GetString(iColorIndex, sBuffer, sizeof(sBuffer));
+ strcopy(ga_sNameColor[client], sizeof(ga_sNameColor[]), sBuffer);
+ strcopy(gaa_sCleanSetupText[client][2], sizeof(gaa_sCleanSetupText[][]), ga_sNameColor[client]);
+ FormatColors(client);
+ g_aColorName.GetString(iColorIndex, sBuffer, sizeof(sBuffer));
+ PrintToChat(client, "\x01%s%s%t %s%s", g_sTag, CSGO_WHITE, "NameColorSetTo", ga_sNameColor[client], sBuffer);
+ SendClientSetupToDB(client);
+ }
+ Menu_MainTag(client);
+ }
+}
+
+public void Menu_ChatColor(int client)
+{
+ if (ga_iIsRestricted[client])
+ {
+ PrintToChat(client, "%s%s%t", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), "RestrictedChangingChatColors");
+ return;
+ }
+
+ if (!g_cEnableChatColors.BoolValue)
+ {
+ PrintToChat(client, "%s%s%t", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), "DisabledForEveryoneByServerManager");
+ return;
+ }
+
+ Menu oMenu = new Menu(MenuCallback_ChatColor);
+ oMenu.SetTitle("%T", "Chat Colors", client);
+ oMenu.ExitBackButton = true;
+ oMenu.Pagination = 6;
+
+ AddMenuItemEx(oMenu, _, "Reset", "%T", "Reset", client);
+ if (!g_bCSGO && !g_bIns)
+ {
+ AddMenuItemEx(oMenu, _, "SetManually", "%T", "Define Your Own Color", client);
+ }
+
+ char sColorIndex[5], sColorName[32], sBuffer[32];
+ for (int i = 0; i < g_aColorName.Length; i++)
+ {
+ IntToString(i, sColorIndex, sizeof(sColorIndex));
+ g_aColorName.GetString(i, sColorName, sizeof(sColorName));
+ g_aColorCode.GetString(i, sBuffer, sizeof(sBuffer));
+ if (StringToInt(sBuffer) < 0)
+ oMenu.AddItem(sColorIndex, sColorName, ITEMDRAW_DISABLED);
+ else
+ oMenu.AddItem(sColorIndex, sColorName);
+ }
+
+ oMenu.Display(client, MENU_TIME_FOREVER);
+}
+
+public int MenuCallback_ChatColor(Menu oMenu, MenuAction action, int client, int param2)
+{
+ if (action == MenuAction_End)
+ {
+ delete oMenu;
+ return;
+ }
+
+ if (action == MenuAction_Cancel && param2 == MenuCancel_ExitBack)
+ {
+ Menu_MainTag(client);
+ return;
+ }
+
+ if (action == MenuAction_Select)
+ {
+ char sBuffer[32];
+ oMenu.GetItem(param2, sBuffer, sizeof(sBuffer));
+
+ if (StrEqual(sBuffer, "Reset"))
+ {
+ PrintToChat(client, "%s%s%t", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), "ResetChatColor");
+ ga_sChatColor[client] = "";
+ gaa_sCleanSetupText[client][3] = "";
+ FormatColors(client);
+ SendClientSetupToDB(client);
+ }
+ else if (StrEqual(sBuffer, "SetManually"))
+ {
+ PrintToChat(client, "%s\x03%t", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED), "ToDefineYourOwnChatColor");
+ }
+ else
+ {
+ int iColorIndex = StringToInt(sBuffer);
+ g_aColorCode.GetString(iColorIndex, sBuffer, sizeof(sBuffer));
+ strcopy(ga_sChatColor[client], sizeof(ga_sChatColor[]), sBuffer);
+ strcopy(gaa_sCleanSetupText[client][3], sizeof(gaa_sCleanSetupText[][]), ga_sChatColor[client]);
+ FormatColors(client);
+ g_aColorName.GetString(iColorIndex, sBuffer, sizeof(sBuffer));
+ PrintToChat(client, "\x01%s%s%t %s%s", g_sTag, CSGO_WHITE, "ChatColorSetTo", ga_sChatColor[client], sBuffer);
+ SendClientSetupToDB(client);
+ }
+
+ Menu_MainTag(client);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////
+///////////////////////////// Admin Menu /////////////////////////////
+//////////////////////////////////////////////////////////////////////
+
+public void OnAdminMenuReady(Handle hTopMenu)
+{
+ TopMenu oTopMenu = TopMenu.FromHandle(hTopMenu);
+
+ /* Block us from being called twice */
+ if (oTopMenu == g_oTopMenu)
+ {
+ return;
+ }
+
+ /* Save the Handle */
+ g_oTopMenu = oTopMenu;
+
+ //TopMenuObject oMenuObject = AddToTopMenu(hTopMenu, "ChatTags", TopMenuObject_Category, Handle_Commands, INVALID_TOPMENUOBJECT);
+ TopMenuObject oMenuObject = g_oTopMenu.AddCategory("ChatTags", Handle_Commands, "sm_tagadmin", ReadFlagString(g_sAdminFlag), "mainmenu");
+ if (oMenuObject == INVALID_TOPMENUOBJECT)
+ {
+ return;
+ }
+
+ g_oTopMenu.AddItem("sm_reloadtags", AdminMenu_Command, oMenuObject, "sm_reloadtags", ReadFlagString(g_sAdminFlag));
+ g_oTopMenu.AddItem("sm_restricttag", Adminmenu_Player, oMenuObject, "sm_restricttag", ReadFlagString(g_sAdminFlag), "Restrict Tags");
+ g_oTopMenu.AddItem("sm_unrestricttag", Adminmenu_Player, oMenuObject, "sm_unrestricttag", ReadFlagString(g_sAdminFlag), "Unrestrict Tags");
+ g_oTopMenu.AddItem("sm_removetag", Adminmenu_Player, oMenuObject, "sm_removetag", ReadFlagString(g_sAdminFlag), "Remove Tags");
+ g_oTopMenu.AddItem("sm_unloadtags", AdminMenu_Unload, oMenuObject, "sm_unloadtags", ReadFlagString(g_sAdminUnloadFlag));
+}
+
+public void Handle_Commands(TopMenu oMenu, TopMenuAction action, TopMenuObject object_id, int client, char[] sBuffer, int iMaxLen)
+{
+ switch(action)
+ {
+ case TopMenuAction_DisplayOption:
+ {
+ Format(sBuffer, iMaxLen, "Chat Tags");
+ }
+ case TopMenuAction_DisplayTitle:
+ {
+ Format(sBuffer, iMaxLen, "Chat Tags");
+ }
+ }
+}
+
+public void AdminMenu_Unload(TopMenu oMenu, TopMenuAction action, TopMenuObject object_id, int client, char[] sBuffer, int iMaxLen) //command via admin menu
+{
+ if (action == TopMenuAction_DisplayOption)
+ {
+ Format(sBuffer, iMaxLen, "Unload plugin until map change");
+ }
+ else if (action == TopMenuAction_SelectOption)
+ {
+ PrintToChat(client, "%s%sChat Tags is now unloaded until map change!", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED));
+ char sPluginName[128];
+ GetPluginFilename(INVALID_HANDLE, sPluginName, sizeof(sPluginName));
+ ServerCommand("sm plugins unload %s", sPluginName);
+ }
+}
+
+public void AdminMenu_Command(TopMenu oTopMenu, TopMenuAction action, TopMenuObject object_id, int client, char[] sBuffer, int iMaxLen) //command via admin menu
+{
+ if (action == TopMenuAction_DisplayOption)
+ {
+ Format(sBuffer, iMaxLen, "Reload Chat Tag Colors");
+ }
+ else if (action == TopMenuAction_SelectOption)
+ {
+ Reload();
+
+ PrintToChat(client, "%s%sColors setups are now reloaded.", g_sTag, g_bCSGO ? CSGO_RED : (g_bIns ? INS_GREEN : CSS_RED));
+ RedisplayAdminMenu(oTopMenu, client);
+ }
+}
+
+public void Adminmenu_Player(TopMenu oTopMenu, TopMenuAction action, TopMenuObject object_id, int client, char[] sBuffer, int iMaxLength)
+{
+ char sCommand[MAX_NAME_LENGTH], sTitle[128];
+ GetTopMenuObjName(oTopMenu, object_id, sCommand, sizeof(sCommand));
+ GetTopMenuInfoString(oTopMenu, object_id, sTitle, sizeof(sTitle));
+
+ switch(action)
+ {
+ case(TopMenuAction_DisplayOption):
+ {
+ Format(sBuffer, iMaxLength, sTitle);
+ }
+ case(TopMenuAction_SelectOption):
+ {
+ Displaymenu_Player(client, sCommand, sTitle);
+ }
+ }
+}
+
+public void Displaymenu_Player(int client, char[] sCommand, char[] sTitle, any ...)
+{
+ Menu oMenu = new Menu(Commandmenu_Player);
+ char sBuffer[256];
+ SetGlobalTransTarget(client);
+ VFormat(sBuffer, sizeof(sBuffer), sTitle, 4);
+ oMenu.SetTitle(sBuffer);
+ oMenu.ExitBackButton = true;
+
+ for (int i = 1; i <= MaxClients; i++)
+ {
+ if (IsValidClient(i))
+ {
+ char sInfoBuffer[256], sName[MAX_NAME_LENGTH], sUserID[MAX_NAME_LENGTH], sDisplay[128];
+ IntToString(GetClientUserId(i), sUserID, sizeof(sUserID));
+ GetClientName(i, sName, sizeof(sName));
+ Format(sDisplay, sizeof(sDisplay), "%s (%s)", sName, sUserID);
+ Format(sInfoBuffer, sizeof(sInfoBuffer), "%s %s", sCommand, sUserID);
+ oMenu.AddItem(sInfoBuffer, sDisplay);
+ }
+ }
+
+ oMenu.Display(client, MENU_TIME_FOREVER);
+}
+
+
+public int Commandmenu_Player(Menu oMenu, MenuAction Selection, int client, int param2)
+{
+ switch(Selection)
+ {
+ case(MenuAction_End):
+ {
+ delete oMenu;
+ }
+ case(MenuAction_Cancel):
+ {
+ char sInfo[64];
+ oMenu.GetItem(param2, sInfo, sizeof(sInfo));
+ char sTempArray[2][32];
+ ExplodeString(sInfo, " ", sTempArray, sizeof(sTempArray), sizeof(sTempArray[]));
+
+ if (StrEqual(sTempArray[0],"sm_checktag",false))
+ {
+ Menu_MainTag(client);
+ }
+ else
+ {
+ DisplayTopMenu(g_oTopMenu, client, TopMenuPosition_LastCategory);
+ }
+ }
+ case(MenuAction_Select):
+ {
+ char sInfo[64];
+ oMenu.GetItem(param2, sInfo, sizeof(sInfo));
+ char sTempArray[2][32];
+ ExplodeString(sInfo, " ", sTempArray, sizeof(sTempArray), sizeof(sTempArray[]));
+
+ if (!IsValidClient(GetClientOfUserId(StringToInt(sTempArray[1]))))
+ {
+ ReplyToCommand(client, "%s%sTarget is now invalid.", g_sTag, CSGO_WHITE);
+ }
+ else
+ {
+ char sCommand[300];
+ Format(sCommand, sizeof(sCommand), "%s #%i", sTempArray[0], StringToInt(sTempArray[1]));
+ FakeClientCommandEx(client, sCommand);
+ }
+ }
+ }
+}
+
+void CleanStringForSQL(char[] sString, int iSize)
+{
+ int iEscapeSize = 2*iSize + 1;
+ char[] sEscapedText = new char[iEscapeSize];
+ g_oDatabase.Escape(sString, sEscapedText, iEscapeSize);
+ strcopy(sString, iSize, sEscapedText);
+
+ /*char[] sBuffer = new char[iSize];
+ strcopy(sBuffer, iSize, sString);
+ ReplaceString(sBuffer, iSize, "}", "");
+ ReplaceString(sBuffer, iSize, "{", "");
+ ReplaceString(sBuffer, iSize, "|", "");
+ ReplaceString(sBuffer, iSize, "'", "");
+ ReplaceString(sBuffer, iSize, "\%27", ""); // '
+ ReplaceString(sBuffer, iSize, "\"", "");
+ ReplaceString(sBuffer, iSize, "\%22", ""); // "
+ ReplaceString(sBuffer, iSize, "`", "");
+ ReplaceString(sBuffer, iSize, "\%60", ""); // `
+ ReplaceString(sBuffer, iSize, "\\", "");
+ ReplaceString(sBuffer, iSize, "\%5C", ""); // backslash
+ ReplaceString(sBuffer, iSize, "#", "");
+ ReplaceString(sBuffer, iSize, "\%23", ""); // #
+ ReplaceString(sBuffer, iSize, "--", "");
+ ReplaceString(sBuffer, iSize, "\%2D-", ""); // --
+ ReplaceString(sBuffer, iSize, "-\%2D", ""); // --
+ ReplaceString(sBuffer, iSize, "\%2D\%2D", ""); // --
+ ReplaceString(sBuffer, iSize, "=", "");
+ ReplaceString(sBuffer, iSize, "\%3D", ""); // =
+ ReplaceString(sBuffer, iSize, ";", "");
+ ReplaceString(sBuffer, iSize, "\%3B", ""); // ;
+ ReplaceString(sBuffer, iSize, "^", "");
+ ReplaceString(sBuffer, iSize, "\%5E", ""); // ^
+ ReplaceString(sBuffer, iSize, "%", "");
+ ReplaceString(sBuffer, iSize, "\%25", ""); // %
+ strcopy(sString, iSize, sBuffer); */
+}
+
+stock void Log(char[] sPath, const char[] sMsg, any ...) //logging function - path is relative to logs folder.
+{
+ char sLogFilePath[PLATFORM_MAX_PATH], sFormattedMsg[1500];
+ BuildPath(Path_SM, sLogFilePath, sizeof(sLogFilePath), "logs/%s", sPath);
+ VFormat(sFormattedMsg, sizeof(sFormattedMsg), sMsg, 3);
+ LogToFileEx(sLogFilePath, "%s", sFormattedMsg);
+}
+
+/*
+CHANGELOG:
+ 2.1:
+ * Added spam blocker
+ * Added console color cvars
+ 2.2:
+ * Converted team names to read team name...was using CSS ones before.
+ 2.3:
+ * Added auto-gag after detected for spam 3x, with cvar for time span it all occurs, if it is even on, and added cvar to disable spam detection period.
+ 2.5:
+ * Moved return for ignored text after the spam blockers.
+ 2.6:
+ * Fixed the check tags command - now handles groups, and fixed that it was returning the setup of the person sending the command, not the target. Also made the command executable from rcon.
+ * Edited formatting for [ChatTags] on all replys.
+ * Added checks to make sure they arent mimicking console and have an easy place to add checks for bad names (and remove if they're found to be).
+ 2.7:
+ * Created CS:GO version (currently not public).
+ * Converted back to PrintToChat from morecolor's CPrintToChat, due to the ability to glitch their function and color text by using the tag codes in your message (e.g. "{fullred}Hey look! My text is red!")
+ * Added a function to format the team names so that the first letter is capitolized, and letters after hyphens, a space, or a first parenthesis are capitolized. All else are lower case.
+ * Fixed cvar names.
+ * Added cvars to disable any of the 4 main tag/color functions (tags, tag colors, name colors, and chat colors).
+ * Changed kv key from "hex" to "colors" to be more generic for use with CS:GO, and simplicity/similarity between the two versions.
+ * Removed g_iTagSetting, and replaced with conditional formatting.
+ * One cvar was missing a hook to it being change. Added in.
+ * Added code to return Plugin_Continue if message was blank.
+ 2.8:
+ * Added config setups for groups or individuals.
+ 3.0.3:
+ * Fixed setting individual setups in ftp cfg being applied as public.
+ * Made it so that if server managers put the wrong steam universe in IDs (STEAM_0), it will still work, despite their fail -.- .
+ 3.1:
+ * Added code to allow external plugins to set additional tags.
+ * Shortened cfg filenames.
+ * Added a few lines to help protect against multiple messages spamming chat when gagging a client.
+ 3.1.2:
+ * Added ability to set the access flag to "public" to make it available to all.
+ 3.1.3:
+ * Added line at top to increase stack space.
+ 3.1.4:
+ * Updated HasFlags function to allow more versatility/configurability.
+ 3.1.5:
+ * Added cvars for default CT and T colors for names and chat, when no other setups apply.
+ 4.0:
+ * Added natives for access overrides.
+ * Edited HasFlags to be able to pass "none" to block all access (leaving tags only available to external plugins).
+ * Added forward for plugin reload.
+ * Renamed a lot of variables to use my current nomenclatures, and made global integers into booleans where there's only 2 options.
+ * Combined the CS:S and CS:GO versions
+ * Redid some of the admin menu to combine functions using techniques/code I made for my other plugins.
+ 4.1
+ * Stable version with all bugs worked out from the 4.0 conversion.
+ 4.1.1:
+ * Added more CheckClientLoad to combat the OnClientCookiesCached event not always firing (not sure if that's a sourcemod bug or what...).
+ 4.1.2:
+ * Created Fwd for when a client finishes loading.
+ 4.2:
+ * Added missing flag check for unload cmd.
+ * Added cvars and cmd for an admin (configurable flag) to set another player's tag/color settings.
+ * Removed resetting ga_iIsRestricted in RemoveSetup.
+ * Rebuilt cfg file to use ADT arrays for storing colors. Didnt realize I wasnt doing this (that piece was coded a long while back).
+ * Edited ConvertColor to also allow the names from the cfg file and to convert them accordingly. Increased all tag buffers to 32 to allow this.
+ * Added 4 more cookies to keep track of if settings for a client were an admin override.
+ * Added cmd to remove all admin overrides from a client.
+ * Changed default for ga_iTagVisible to 0.
+ 4.2.1:
+ * Edited g_iExternalPos to make it so they can have just one tag, if configured to be that, and preference one or the other.
+ * Removed FCVAR_PLUGIN due to it being depreciated.
+ 4.3.0:
+ * Added code from SCP to filter out translations.
+ 4.3.1:
+ * Scrapped everything added from SCP for 4.3.0, and wrote my own stuff that functions better and avoids the bad translation file parsing they use, etc.
+ 4.3.2:
+ * Edited using names to specify colors being forced. Still not tested, but noticed that it was still inside the check for string length < 3, and fixed that. Should be good now.
+ 4.3.3:
+ * Added a SetFailState for missing translation.
+ * Added CreateDirectory if they didnt make the logs/chatlogger/ folder.
+ 4.3.4:
+ * Edited cancel button when picking players players via Displaymenu_Player function. Since it is also used in admin menu, apparently the back button allows going to the admin menu. Now, it checks the command to determine if it should draw the tags menu or admin menu.
+ 4.4.0:
+ * Added code so that the group configs can specify team groups (e.g. TEAM_2 would be terrorists in CS:S/CS:GO).
+ 4.4.1:
+ * Added cvar ct_hidechattriggers and supporting code to hide chat triggers, per request.
+ 4.4.2:
+ * Added cvar ct_forcebrackets and supporting code, per request.
+ 4.4.3:
+ * Added cvar ct_bracketcolor and supporting code, per request.
+ * Removed include, since it wasnt being used (and hasnt been for a while).
+ 4.4.4:
+ * Minor edit to move the bracket adding inside the check for if they get tags.
+ 4.5.0:
+ * Added support for Insurgency.
+ * Removed "ct_enabled" cvar, since they should just unload/reload plugin to enable/disable.
+ * Changed player settings to store in SQL database instead of client cookies.
+ * Added forward for when clients reload (called every time they change their setup) and their info is sent to the database.
+ 4.5.1:
+ * Added a few colors to insurgency settings: Banana yellow, dark yellow. Added iEntIDOverride in SayText2 to add red color for insurgency.
+ * Added code to paginate the colors better.
+ 4.5.2:
+ * Flipped the ga_iTagHidden variable to ga_iTagVisible, and changed the DB column from `hidden` to `visible`. Flipped the logic on that variable throughout the plugin. The purpose of this was to fix the tags menu functionality around if the first option in the menu says "Disable tag", etc.
+ 4.5.3:
+ * Added code for !blockchat command to allow players to disable all chat from others. I havent tested this feature yet though.
+ 4.5.4:
+ * Added CleanStringForSQL(ga_sEscapedName[client], sizeof(ga_sEscapedName[])); in a couple locations where the name was being re-grabbed.
+ 4.5.5:
+ * Fixed an error that showed up in recent edits around the ga_iTagVisible (previously ga_iTagHidden) variable. It caused players to get cfg setup even when they set their own.
+ 4.6.0:
+ * Converted plugin to 1.8 syntax and made use of classes, etc. Plugin not tested.
+ 4.6.1:
+ * Upped buffer from 32 to 120 for cvar flag caches.
+ * Added cvar and code for admin flags for the spam blocker to ignore.
+ * Added cvar and code so that after an admin removes someones setup, it will check the groups config file for a default setup (if enabled).
+ * Made it so that the groups config file supports AuthId_Steam2, AuthId_Steam3, and AuthId_SteamID64. The database will use AuthId_Steam2 with steam universe = 0.
+ 4.7.0:
+ * Attempted rainbow chat after being harassed by several people to add it. Figured out that it truncates long messages due to character limit. Rolled back changes.
+ * Edited out SetFailState for key-values config for groups, allowing it to be blank inside setups. Replaced with PrintToServer msg.
+ * Moved chat logger to database table if using MySQL. For SQLite, it still uses flatfiles.
+ * Modified CleanStringForSQL to just use the Escape. Should change into prepared statements in the future... EDIT: Looked into prepared statements, and they still arent available threaded :( .
+ * Added separate cache for escaped and unescaped player names (unescaped is used in SayText2).
+ * Added g_cHideChatTriggers check in Say_Team hook (it was only in regular say hook before).
+ * Moved timer to update chat logs flatfile path to be inside DB connect when it decides it is sqlite (part of migration to MySQL logs).
+ * Created web panel for displaying chat logs, grouped by server. Web page is all relative urls and the only edit needed is the database info!
+ 4.7.1:
+ * Minor edit to incorporate the 1.8 syntax Database class fully. This does not effect the plugin in any way.
+ * Made it so that CleanStringForSQL cant be called when the database is null.
+ 4.7.2
+ * Minor edit to enforce some boundaries on some cvars.
+ 4.8.0
+ * Made the name of the database table into a cvar so that a single database can be used with separate tables for separate servers (per request).
+ * Restructured the table creation code for the database so that the bulk of the query is only written in the code once, and is more readable.
+ 4.8.1
+ * Missed some of the queries being updated to use the new cvar tablename from 4.8.0. Edited.
+ * Changed the unload cmds to auto-detect the plugin name.
+ 4.9.0
+ * Revamped spam protection to make it more configurable. All cvars renamed accordingly.
+ * Renamed some variables and functions.
+ * Converted the last of the timers to pass userid instead of client index. The only ones that were still there were 0.1 second timers, so I didnt bother it using the extra resources to be safe on such a short timer, but now I changed it.
+ 4.9.1
+ * Removed include - wasnt being used.
+ 4.9.2
+ * Edit so that cfg sections with numbers wouldnt be skipped by being falsely identified as steam ids (64).
+ 4.9.3
+ * Minor edit in SQLCallback_Connect that has no change to functionality. It is simply a cleanup of code that I want to use in the future for database connections where sqlite is allowed.
+*/
\ No newline at end of file
diff --git a/ChatTags/translations/ChatTags.phrases.txt b/ChatTags/translations/ChatTags.phrases.txt
new file mode 100644
index 0000000..d3db4ae
--- /dev/null
+++ b/ChatTags/translations/ChatTags.phrases.txt
@@ -0,0 +1,361 @@
+"Phrases"
+{
+ "ClientPrefs Title"
+ {
+ "en" "[Donator] Chat Tags"
+ "jp" "[ドネーター] Chat Tags (チャットタグ)"
+ "chi" "[捐助者] Chat Tags (聊天标签)"
+ "zho" "[捐助者] Chat Tags (聊天標籤)"
+ }
+ "CheckConsole"
+ {
+ "en" "Check console for output!"
+ "jp" "コンソールの出力を確認してください!"
+ //"chi" ""
+ //"zho" ""
+ }
+ "NotFoundOrInvalidParameter"
+ {
+ "en" "Not found or invalid parameter."
+ "jp" "見つからなかったか無効なパラメータです."
+ //"chi" ""
+ //"zho" ""
+ }
+ "InvalidHex"
+ {
+ "en" "Invalid hex."
+ "jp" "無効なHEX."
+ //"chi" ""
+ //"zho" ""
+ }
+ "Usage"
+ {
+ "en" "Usage:"
+ "jp" "使用方法:"
+ //"chi" ""
+ //"zho" ""
+ }
+ "NotAvailableForCSGO"
+ {
+ "en" "This command is not available for CS:GO!"
+ "jp" "このコマンドは CS:GO では使用できません!"
+ //"chi" ""
+ //"zho" ""
+ }
+ "NotAvailableForInsurgency"
+ {
+ "en" "This command is not available for Insurgency!"
+ "jp" "このコマンドは Insurgency では使用できません!"
+ //"chi" ""
+ //"zho" ""
+ }
+ "DisabledByServerManager"
+ {
+ "en" "This feature has been disabled by the server manager!"
+ "jp" "この機能はサーバー管理者によって無効化されています!"
+ //"chi" ""
+ //"zho" ""
+ }
+ "DisabledForEveryoneByServerManager"
+ {
+ "en" "This feature has been disabled for everyone by the server manager!"
+ "jp" "この機能はサーバー管理者によってプレイヤー全体で無効化されています!"
+ //"chi" ""
+ //"zho" ""
+ }
+ "MustBeInGame"
+ {
+ "en" "You must be in game to use this command!"
+ "jp" "このコマンドを使用するにはゲーム内である必要があります!"
+ //"chi" ""
+ //"zho" ""
+ }
+ "DoNotHaveAccess"
+ {
+ "en" "You do not have access to this feature!"
+ "jp" "あなたはこの機能にアクセスできません!"
+ //"chi" ""
+ //"zho" ""
+ }
+ "DisabledUntilCookiesCached"
+ {
+ "en" "This feature is disabled until your cookies have cached!"
+ "jp" "この機能はあなたのクッキーがキャッシュされるまで使用できません!"
+ //"chi" ""
+ //"zho" ""
+ }
+ "TagEnabled"
+ {
+ "en" "Your tag is now enabled!"
+ "jp" "あなたのタグが有効になりました!"
+ //"chi" ""
+ //"zho" ""
+ }
+ "TagDisabled"
+ {
+ "en" "Your tag is now disabled!"
+ "jp" "あなたのタグが無効になりました!"
+ //"chi" ""
+ //"zho" ""
+ }
+ "RestrictedChangingTags"
+ {
+ "en" "You are currently restricted from changing your tags!"
+ "jp" "あなたは現在タグの変更が制限されています!"
+ //"chi" ""
+ //"zho" ""
+ }
+ "RestrictedChangingTagColors"
+ {
+ "en" "You are currently restricted from changing your tag colors!"
+ "jp" "あなたは現在タグの色の変更が制限されています!"
+ //"chi" ""
+ //"zho" ""
+ }
+ "RestrictedChangingNameColors"
+ {
+ "en" "You are currently restricted from changing your name colors!"
+ "jp" "あなたは現在名前の色の変更が制限されています!"
+ //"chi" ""
+ //"zho" ""
+ }
+ "RestrictedChangingChatColors"
+ {
+ "en" "You are currently restricted from changing your chat colors!"
+ "jp" "あなたは現在チャットの色の変更が制限されています!"
+ //"chi" ""
+ //"zho" ""
+ }
+ "EnabledChatBlocker"
+ {
+ "en" "You have enabled chat blocker! You will no longer see chat from other players. To re-enable it, type !blockchat."
+ "jp" "チャットブロックを有効にしました! 他のプレイヤーのチャットが見えなくなります. 再度 !blockchar を入力で元に戻します."
+ //"chi" ""
+ //"zho" ""
+ }
+ "DisabledChatBlocker"
+ {
+ "en" "You have disabled chat blocker! You can now see chat. To disable chat again, type !blockchat."
+ "jp" "チャットブロックを無効にしました! チャットが見えるようになります. 再度 !blockchar を入力でチャットを無効化します."
+ //"chi" ""
+ //"zho" ""
+ }
+ "DeniedChangeTagByExternalPlugin"
+ {
+ "en" "Your access to change your tag text has been denied by override by an external plugin!"
+ "jp" "他のプラグインが優先制御している為, タグテキストの変更が拒否されました!"
+ //"chi" ""
+ //"zho" ""
+ }
+ "DeniedChangeTagColorByExternalPlugin"
+ {
+ "en" "Your access to change your tag colors has been denied by override by an external plugin!"
+ "jp" "他のプラグインが優先制御している為, タグの色の変更が拒否されました!"
+ //"chi" ""
+ //"zho" ""
+ }
+ "DeniedChangeNameColorByExternalPlugin"
+ {
+ "en" "Your access to change your name colors has been denied by override by an external plugin!"
+ "jp" "他のプラグインが優先制御している為, 名前の色の変更が拒否されました!"
+ //"chi" ""
+ //"zho" ""
+ }
+ "DeniedChangeChatColorByExternalPlugin"
+ {
+ "en" "Your access to change your chat colors has been denied by override by an external plugin!"
+ "jp" "他のプラグインが優先制御している為, チャットの色の変更が拒否されました!"
+ //"chi" ""
+ //"zho" ""
+ }
+ "TagBlockedFromUse"
+ {
+ "en" "Nice try! This tag is blocked from use."
+ "jp" "いい試みですね! このタグの使用はブロックされています."
+ //"chi" ""
+ //"zho" ""
+ }
+ "TagSetTo"
+ {
+ "en" "Your tag is now visible and is set to:"
+ "jp" "あなたのタグが設定されました:"
+ //"chi" ""
+ //"zho" ""
+ }
+ "TagColorSetTo"
+ {
+ "en" "Your tag color is now set to:"
+ "jp" "あなたのタグの色が設定されました:"
+ //"chi" ""
+ //"zho" ""
+ }
+ "NameColorSetTo"
+ {
+ "en" "Your name color is now set to:"
+ "jp" "あなたの名前の色が設定されました:"
+ //"chi" ""
+ //"zho" ""
+ }
+ "ChatColorSetTo"
+ {
+ "en" "Your chat color is now set to:"
+ "jp" "あなたのチャットの色が設定されました:"
+ //"chi" ""
+ //"zho" ""
+ }
+ "ResetTagColor"
+ {
+ "en" "Your tag color is now reset to default."
+ "jp" "あなたのタグの色が初期値にリセットされました."
+ //"chi" ""
+ //"zho" ""
+ }
+ "ResetNameColor"
+ {
+ "en" "Your name color is now reset to default."
+ "jp" "あなたの名前の色が初期値にリセットされました."
+ //"chi" ""
+ //"zho" ""
+ }
+ "ResetChatColor"
+ {
+ "en" "Your chat color is now reset to default."
+ "jp" "あなたのチャットの色が初期値にリセットされました."
+ //"chi" ""
+ //"zho" ""
+ }
+ "TooFast"
+ {
+ "en" "You are sending messages too fast!"
+ "jp" "メッセージの間隔が短かすぎます!"
+ //"chi" ""
+ //"zho" ""
+ }
+ "HasBeenGagged"
+ {
+ "en" "has been gagged for spamming chat."
+ "jp" "がチャットスパムによってギャグされました."
+ //"chi" ""
+ //"zho" ""
+ }
+ "MimickingCONSOLE"
+ {
+ "en" "Your chat tags setup has been removed due to mimicking CONSOLE (change your name)!"
+ "jp" "あなたはCONSOLE表示を真似しようとしたためタグの設定が消去されました (名前を変更してください)!"
+ //"chi" ""
+ //"zho" ""
+ }
+ "ToDefineYourOwnTagColor"
+ {
+ "en" "To define your own tag color, type !tagcolor (e.g. !tagcolor FFFFFF)."
+ "jp" "自分の好みのタグの色を定義するには, !tagcolor を入力してください (例. !tagcolor FFFFFF)."
+ //"chi" ""
+ //"zho" ""
+ }
+ "ToDefineYourOwnNameColor"
+ {
+ "en" "To define your own name color, type !namecolor (e.g. !namecolor FFFFFF)."
+ "jp" "自分の好みの名前の色を定義するには, !namecolor を入力してください (例. !namecolor FFFFFF)."
+ //"chi" ""
+ //"zho" ""
+ }
+ "ToDefineYourOwnChatColor"
+ {
+ "en" "To define your own chat color, type !chatcolor (e.g. !chatcolor FFFFFF)."
+ "jp" "自分の好みのチャットの色を定義するには, !chatcolor を入力してください (例. !chatcolor FFFFFF)."
+ //"chi" ""
+ //"zho" ""
+ }
+ "Chat Tags"
+ {
+ "en" "Chat Tags"
+ "jp" "チャットタグ"
+ //"chi" ""
+ //"zho" ""
+ }
+ "Disable Tag"
+ {
+ "en" "Disable Tag"
+ "jp" "タグを無効化"
+ //"chi" ""
+ //"zho" ""
+ }
+ "Enable Tag"
+ {
+ "en" "Enable Tag"
+ "jp" "タグを有効化"
+ //"chi" ""
+ //"zho" ""
+ }
+ "Tag Colors"
+ {
+ "en" "Tag Colors"
+ "jp" "タグの色"
+ //"chi" ""
+ //"zho" ""
+ }
+ "Name Colors"
+ {
+ "en" "Name Colors"
+ "jp" "名前の色"
+ //"chi" ""
+ //"zho" ""
+ }
+ "Chat Colors"
+ {
+ "en" "Chat Colors"
+ "jp" "チャットの色"
+ //"chi" ""
+ //"zho" ""
+ }
+ "Check Setup of Player"
+ {
+ "en" "Check Setup of Player"
+ "jp" "プレイヤーの設定値を確認"
+ //"chi" ""
+ //"zho" ""
+ }
+ "Chat Command To Change Tag"
+ {
+ "en" "Chat command to change tag:"
+ "jp" "タグを変更するコマンド:"
+ //"chi" ""
+ //"zho" ""
+ }
+ "Tag Text You Want"
+ {
+ "en" "!tag "
+ "jp" "!tag <設定したいテキスト>"
+ //"chi" ""
+ //"zho" ""
+ }
+ "Characters Max"
+ {
+ "#format" "{1:i}"
+ "en" "({1} Characters Max)"
+ "jp" "(最大 {1} 文字)"
+ //"chi" ""
+ //"zho" ""
+ }
+ "Check Tag Setup For"
+ {
+ "en" "Check Tag Setup for:"
+ "jp" "タグの設定値を確認:"
+ //"chi" ""
+ //"zho" ""
+ }
+ "Reset"
+ {
+ "en" "Reset"
+ "jp" "リセット"
+ //"chi" ""
+ //"zho" ""
+ }
+ "Define Your Own Color"
+ {
+ "en" "Define Your Own Color"
+ "jp" "自分の好みの色を定義"
+ //"chi" ""
+ //"zho" ""
+ }
+}
\ No newline at end of file
diff --git a/ChatTags/translations/scp.csgo.phrases.txt b/ChatTags/translations/scp.csgo.phrases.txt
new file mode 100644
index 0000000..27a8398
--- /dev/null
+++ b/ChatTags/translations/scp.csgo.phrases.txt
@@ -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}"
+ }
+}
\ No newline at end of file
diff --git a/ChatTags/translations/scp.cstrike.phrases.txt b/ChatTags/translations/scp.cstrike.phrases.txt
new file mode 100644
index 0000000..27a8398
--- /dev/null
+++ b/ChatTags/translations/scp.cstrike.phrases.txt
@@ -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}"
+ }
+}
\ No newline at end of file
diff --git a/ChatTags/translations/scp.insurgency.phrases.txt b/ChatTags/translations/scp.insurgency.phrases.txt
new file mode 100644
index 0000000..700be47
--- /dev/null
+++ b/ChatTags/translations/scp.insurgency.phrases.txt
@@ -0,0 +1,68 @@
+"Phrases"
+{
+ "Game_radio"
+ {
+ "#format" "{1:s},{2:s}"
+ "en" " {1} (RADIO): {2}"
+ }
+ "Game_radio_location"
+ {
+ "#format" "{1:s},{2:s}"
+ "en" " {1} (RADIO): {2}"
+ }
+ "INS_Chat_T1_Loc"
+ {
+ "#format" "{1:s},{2:s}"
+ "en" "(Security) {1} : {2}"
+ }
+ "INS_Chat_T1"
+ {
+ "#format" "{1:s},{2:s}"
+ "en" "(Security) {1}: {2}"
+ }
+ "INS_Chat_T2_Loc"
+ {
+ "#format" "{1:s},{2:s}"
+ "en" "(Insurgents) {1}: {2}"
+ }
+ "INS_Chat_T2"
+ {
+ "#format" "{1:s},{2:s}"
+ "en" "(Insurgents) {1}: {2}"
+ }
+ "INS_Chat_T1_Dead"
+ {
+ "#format" "{1:s},{2:s}"
+ "en" "*DEAD*(Security) {1}: {2}"
+ }
+ "INS_Chat_T2_Dead"
+ {
+ "#format" "{1:s},{2:s}"
+ "en" "*DEAD*(Insurgents) {1} : {2}"
+ }
+ "INS_Chat_Spec"
+ {
+ "#format" "{1:s},{2:s}"
+ "en" "(Spectator) {1} : {2}"
+ }
+ "INS_Chat_All"
+ {
+ "#format" "{1:s},{2:s}"
+ "en" " {1} : {2}"
+ }
+ "INS_Chat_AllDead"
+ {
+ "#format" "{1:s},{2:s}"
+ "en" "*DEAD* {1} : {2}"
+ }
+ "INS_Chat_AllSpec"
+ {
+ "#format" "{1:s},{2:s}"
+ "en" "*SPEC* {1} : {2}"
+ }
+ "INS_Chat_Party"
+ {
+ "#format" "{1:s},{2:s}"
+ "en" "(Party) {1}"
+ }
+}
\ No newline at end of file
diff --git a/ChatTags/translations/scp.l4d.phrases.txt b/ChatTags/translations/scp.l4d.phrases.txt
new file mode 100644
index 0000000..41d70d1
--- /dev/null
+++ b/ChatTags/translations/scp.l4d.phrases.txt
@@ -0,0 +1,43 @@
+"Phrases"
+{
+ "L4D_Chat_Infected"
+ {
+ "#format" "{1:s},{2:s}"
+ "en" "(Infected) {1} : {2}"
+ }
+ "L4D_Chat_Survivor"
+ {
+ "#format" "{1:s},{2:s}"
+ "en" "(Survivor) {1} : {2}"
+ }
+ "L4D_Chat_Infected_Dead"
+ {
+ "#format" "{1:s},{2:s}"
+ "en" "*DEAD*(Infected) {1} : {2}"
+ }
+ "L4D_Chat_Survivor_Dead"
+ {
+ "#format" "{1:s},{2:s}"
+ "en" "*DEAD*(Survivor) {1} : {2}"
+ }
+ "L4D_Chat_Spec"
+ {
+ "#format" "{1:s},{2:s}"
+ "en" "(Spectator) {1} : {2}"
+ }
+ "L4D_Chat_All"
+ {
+ "#format" "{1:s},{2:s}"
+ "en" "{1} : {2}"
+ }
+ "L4D_Chat_AllDead"
+ {
+ "#format" "{1:s},{2:s}"
+ "en" "*DEAD* {1} : {2}"
+ }
+ "L4D_Chat_AllSpec"
+ {
+ "#format" "{1:s},{2:s}"
+ "en" "*SPEC* {1} : {2}"
+ }
+}
\ No newline at end of file
diff --git a/ChatTags/translations/scp.l4d2.phrases.txt b/ChatTags/translations/scp.l4d2.phrases.txt
new file mode 100644
index 0000000..41d70d1
--- /dev/null
+++ b/ChatTags/translations/scp.l4d2.phrases.txt
@@ -0,0 +1,43 @@
+"Phrases"
+{
+ "L4D_Chat_Infected"
+ {
+ "#format" "{1:s},{2:s}"
+ "en" "(Infected) {1} : {2}"
+ }
+ "L4D_Chat_Survivor"
+ {
+ "#format" "{1:s},{2:s}"
+ "en" "(Survivor) {1} : {2}"
+ }
+ "L4D_Chat_Infected_Dead"
+ {
+ "#format" "{1:s},{2:s}"
+ "en" "*DEAD*(Infected) {1} : {2}"
+ }
+ "L4D_Chat_Survivor_Dead"
+ {
+ "#format" "{1:s},{2:s}"
+ "en" "*DEAD*(Survivor) {1} : {2}"
+ }
+ "L4D_Chat_Spec"
+ {
+ "#format" "{1:s},{2:s}"
+ "en" "(Spectator) {1} : {2}"
+ }
+ "L4D_Chat_All"
+ {
+ "#format" "{1:s},{2:s}"
+ "en" "{1} : {2}"
+ }
+ "L4D_Chat_AllDead"
+ {
+ "#format" "{1:s},{2:s}"
+ "en" "*DEAD* {1} : {2}"
+ }
+ "L4D_Chat_AllSpec"
+ {
+ "#format" "{1:s},{2:s}"
+ "en" "*SPEC* {1} : {2}"
+ }
+}
\ No newline at end of file
diff --git a/ChatTags/translations/scp.tf.phrases.txt b/ChatTags/translations/scp.tf.phrases.txt
new file mode 100644
index 0000000..6ecc614
--- /dev/null
+++ b/ChatTags/translations/scp.tf.phrases.txt
@@ -0,0 +1,43 @@
+"Phrases"
+{
+ "TF_Chat_Team_Loc"
+ {
+ "#format" "{1:s},{2:s}"
+ "en" "(TEAM) {1} : {2}"
+ }
+ "TF_Chat_Team"
+ {
+ "#format" "{1:s},{2:s}"
+ "en" "(TEAM) {1} : {2}"
+ }
+ "TF_Chat_Team_Dead"
+ {
+ "#format" "{1:s},{2:s}"
+ "en" "*DEAD*(TEAM) {1} : {2}"
+ }
+ "TF_Chat_Spec"
+ {
+ "#format" "{1:s},{2:s}"
+ "en" "(Spectator) {1} : {2}"
+ }
+ "TF_Chat_All"
+ {
+ "#format" "{1:s},{2:s}"
+ "en" "{1} : {2}"
+ }
+ "TF_Chat_AllDead"
+ {
+ "#format" "{1:s},{2:s}"
+ "en" "*DEAD* {1} : {2}"
+ }
+ "TF_Chat_AllSpec"
+ {
+ "#format" "{1:s},{2:s}"
+ "en" "*SPEC* {1} : {2}"
+ }
+ "TF_Chat_Coach"
+ {
+ "#format" "{1:s},{2:s}"
+ "en" "(Coach) {1} : {2}"
+ }
+}
diff --git a/ChatTags/web/Read Me.txt b/ChatTags/web/Read Me.txt
new file mode 100644
index 0000000..4e15637
--- /dev/null
+++ b/ChatTags/web/Read Me.txt
@@ -0,0 +1,30 @@
+Drop the "session" and "chattags" folders onto your website in the public section.
+Drop the "steamauth" folder in your root directory.
+The paths in the plugin assume:
+//ROOT:
+ * steamauth/
+ * public/
+ * chatlogs/
+ * sessions/
+
+If your structure differs from this, you may want to edit the following lines:
+ In "chatlogs/index.php", lines 11-13 may need to be adjusted. Here's some explanation of the existing code:
+ * $_SERVER['DOCUMENT_ROOT'] [line 11] gets the path to the public folder.
+ * str_replace("/public", "", $_SERVER['DOCUMENT_ROOT']) [line 11] removes "/public" from the above path. Given the structure shown above, that puts us at the ROOT folder.
+ If yours is different, or if your public folder is named differently, this would need to be edited.
+ * define('ROOT_FOLDER', str_replace("/public", "", $_SERVER['DOCUMENT_ROOT'])); [line 11] defines the above path as a named constant 'ROOT_FOLDER'.
+ * define('STEAM_AUTH_FOLDER', ROOT_FOLDER.'/steamauth/'); [line 12] defines 'STEAM_AUTH_FOLDER' as the root path with "/steamauth/" appended.
+ * session_save_path($_SERVER['DOCUMENT_ROOT'].'/sessions'); [line 13] says that the session data for a visitor are saved in the public folder in the "sessions" subfolder.
+
+In "chatlogs/index.php", add admins by adding them as text (inside quotes) into the array on line 15. This will give access to IP searches and seeing IP info.
+
+In "steamauth/SteamConfig.php", fill in line 3 and 4 (follow the comments to the right of the lines).
+
+In "chatlogs/runquery.php",
+ * Set your database info on lines 2-5.
+ * Line 6 sets the number of rows from the database to show per page.
+ * Around line 300, you will see where you can manipulate the names of the tabs from being server IPs, to whatever else you want it to be (names presumably).
+
+Fin. Make edits to banners, backgrounds, logos, and/or text as your see fit.
+
+Note: The server validation file is only included if you wish to set up server validation via a database. It is a bit complex to set up, so see me if you wish to enable this.
\ No newline at end of file
diff --git a/ChatTags/web/chatlogs/formatting.css b/ChatTags/web/chatlogs/formatting.css
new file mode 100644
index 0000000..5f055bb
--- /dev/null
+++ b/ChatTags/web/chatlogs/formatting.css
@@ -0,0 +1,221 @@
+body
+{
+ background:#1b1b1b url(img/bg.jpg) top center no-repeat;
+ color:#bbb;
+ font-size:12px;
+ font-family:Verdana, Geneva, sans-serif;
+ margin:0px 0px 0px 0px;
+ line-height:18px;
+ overflow:auto;
+}
+
+#wrap
+{
+ width:auto;
+ margin:0 auto;
+ min-height:100px;
+ padding:20px 20px 20px 20px;
+ position:relative;
+ overflow:auto;
+}
+
+.infobox
+{
+ width:auto;
+ height:auto;
+ position:relative;
+ background:url(img/tranbg2.png);
+ border-radius:10px;
+ padding:10px 15px 10px 15px;
+ box-shadow: 5px 5px 10px #121212;
+ overflow:auto;
+ margin-left: auto;
+ margin-right: auto;
+}
+
+.infobox2
+{
+ width:auto;
+ height:auto;
+ /*position:relative;*/
+ background:url(img/tranbg2.png);
+ border-radius:10px;
+ padding:10px 15px 10px 15px;
+ box-shadow: 5px 5px 10px #121212;
+ overflow:auto;
+ margin-left: auto;
+ margin-right: auto;
+ float:right;
+}
+
+.headpoint1
+{
+ font-size:16px;
+ font-weight:bold;
+ color:#ddd;
+}
+
+.headpoint2
+{
+ font-size:30px;
+ font-weight:bold;
+ color:#ddd;
+}
+
+.headpoint3
+{
+ font-size:18px;
+ font-weight:bold;
+ color:#ddd;
+}
+
+.headpoint4
+{
+ font-size:14px;
+ color:#ddd;
+}
+
+.headpoint5
+{
+ font-size:12px;
+ color:#ddd;
+}
+
+ul.rules li
+{
+ padding-top:1px;
+ padding-bottom:1px;
+}
+
+
+
+.cf:before, .cf:after{
+ content:"";
+ display:table;
+}
+
+.cf:after{
+ clear:both;
+}
+
+.cf{
+ zoom:1;
+}
+/* Form wrapper styling */
+.form-wrapper {
+ /*width: 295px;*/
+ width: auto;
+ height: auto;
+ margin: 2px auto 2px auto;
+ background: #444;
+ background: rgba(0,0,0,.2);
+ border-radius: 10px;
+ box-shadow: 0 1px 1px rgba(0,0,0,.4) inset, 0 1px 0 rgba(255,255,255,.2);
+}
+
+/* Form wrapper styling */
+.form-wrapper {
+ /*width: 295px;*/
+ width: auto;
+ height: auto;
+ margin: 2px auto 2px auto;
+ background: #444;
+ background: rgba(0,0,0,.2);
+ border-radius: 10px;
+ box-shadow: 0 1px 1px rgba(0,0,0,.4) inset, 0 1px 0 rgba(255,255,255,.2);
+}
+
+/* Form text input */
+
+.form-wrapper input {
+ width: 200px;
+ height: 16px;
+ padding: 5px 1px;
+ float: left;
+ font: bold 15px 'lucida sans', 'trebuchet MS', 'Tahoma';
+ border: 0;
+ background: #eee;
+ border-radius: 0;
+}
+
+.form-wrapper input:focus {
+ outline: 0;
+ background: #fff;
+ box-shadow: 0 0 2px rgba(0,0,0,.8) inset;
+}
+
+.form-wrapper input::-webkit-input-placeholder {
+ color: #999;
+ font-weight: normal;
+ font-style: italic;
+}
+
+.form-wrapper input:-moz-placeholder {
+ color: #999;
+ font-weight: normal;
+ font-style: italic;
+}
+
+.form-wrapper input:-ms-input-placeholder {
+ color: #999;
+ font-weight: normal;
+ font-style: italic;
+}
+
+/* Form submit button */
+.form-wrapper button {
+ overflow: visible;
+ position: relative;
+ float: right;
+ border: 0;
+ padding: 0;
+ cursor: pointer;
+ height: 26px;
+ width: 75px;
+ font: bold 12px/20px 'lucida sans', 'trebuchet MS', 'Tahoma';
+ color: #fff;
+ text-transform: uppercase;
+ background: #d83c3c;
+ border-radius: 0 3px 3px 0;
+ text-shadow: 0 -1px 0 rgba(0, 0 ,0, .3);
+}
+
+.form-wrapper button:hover{
+ background: #e54040;
+}
+
+.form-wrapper button:active,
+.form-wrapper button:focus{
+ background: #c42f2f;
+ outline: 0;
+}
+
+.form-wrapper button:before { /* left arrow */
+ content: '';
+ position: absolute;
+ border-width: 8px 8px 8px 0;
+ border-style: solid solid solid none;
+ border-color: transparent #d83c3c transparent;
+ top: 5px;
+ left: -6px;
+}
+
+.form-wrapper button:hover:before{
+ border-right-color: #e54040;
+}
+
+.form-wrapper button:focus:before,
+.form-wrapper button:active:before{
+ border-right-color: #c42f2f;
+}
+
+.form-wrapper button::-moz-focus-inner { /* remove extra button spacing for Mozilla Firefox */
+ border: 0;
+ padding: 0;
+}
\ No newline at end of file
diff --git a/ChatTags/web/chatlogs/img/YOUR_LOGO_HERE.png b/ChatTags/web/chatlogs/img/YOUR_LOGO_HERE.png
new file mode 100644
index 0000000..4ca2269
Binary files /dev/null and b/ChatTags/web/chatlogs/img/YOUR_LOGO_HERE.png differ
diff --git a/ChatTags/web/chatlogs/img/bg.jpg b/ChatTags/web/chatlogs/img/bg.jpg
new file mode 100644
index 0000000..630f081
Binary files /dev/null and b/ChatTags/web/chatlogs/img/bg.jpg differ
diff --git a/ChatTags/web/chatlogs/img/bg.png b/ChatTags/web/chatlogs/img/bg.png
new file mode 100644
index 0000000..4b3b087
Binary files /dev/null and b/ChatTags/web/chatlogs/img/bg.png differ
diff --git a/ChatTags/web/chatlogs/img/example.gif b/ChatTags/web/chatlogs/img/example.gif
new file mode 100644
index 0000000..0e3f80d
Binary files /dev/null and b/ChatTags/web/chatlogs/img/example.gif differ
diff --git a/ChatTags/web/chatlogs/img/fire.gif b/ChatTags/web/chatlogs/img/fire.gif
new file mode 100644
index 0000000..004e171
Binary files /dev/null and b/ChatTags/web/chatlogs/img/fire.gif differ
diff --git a/ChatTags/web/chatlogs/img/logout.png b/ChatTags/web/chatlogs/img/logout.png
new file mode 100644
index 0000000..5b1b88a
Binary files /dev/null and b/ChatTags/web/chatlogs/img/logout.png differ
diff --git a/ChatTags/web/chatlogs/img/tranbg2.png b/ChatTags/web/chatlogs/img/tranbg2.png
new file mode 100644
index 0000000..18b05f4
Binary files /dev/null and b/ChatTags/web/chatlogs/img/tranbg2.png differ
diff --git a/ChatTags/web/chatlogs/index.html b/ChatTags/web/chatlogs/index.html
new file mode 100644
index 0000000..39c2ad5
--- /dev/null
+++ b/ChatTags/web/chatlogs/index.html
@@ -0,0 +1,10 @@
+
+
+ Chat Tags: Chat Logs
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ChatTags/web/chatlogs/index.php b/ChatTags/web/chatlogs/index.php
new file mode 100644
index 0000000..5a5c535
--- /dev/null
+++ b/ChatTags/web/chatlogs/index.php
@@ -0,0 +1,486 @@
+
+
+
+
+ Chat Tags - Chat Logs
+
+
+
+
+ = 16)
+ {
+ $z = bcdiv(bcsub($id, '76561197960265728'), '2');
+ }
+ elseif (is_numeric($id))
+ {
+ $z = bcdiv($id, '2'); // Actually new User ID format
+ }
+ else
+ {
+ return $id; // We have no idea what this is, so just return it.
+ }
+ $y = bcmod($id, '2');
+ return 'STEAM_0:' . $y . ':' . floor($z);
+ }
+ }
+
+ function LogConnectedSteamID($sSteamID, $sSteamName, $servername, $username, $password, $dbname)
+ {
+ try
+ {
+ $conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
+ $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+
+ $stmt = $conn->prepare("CREATE TABLE IF NOT EXISTS `chatlogs_connections` (`id` int(20) PRIMARY KEY AUTO_INCREMENT, `steamid` VARCHAR(65) NOT NULL, `steamname` VARCHAR(65) NOT NULL) DEFAULT CHARSET=latin1");
+ $stmt->execute();
+
+ $stmt = $conn->prepare("INSERT INTO chatlogs_connections (steamid,steamname) VALUES (:steamid,:steamname)");
+ $stmt->bindValue(":steamid", $sSteamID, PDO::PARAM_STR);
+ $stmt->bindValue(":steamname", $sSteamName, PDO::PARAM_STR);
+ $stmt->execute();
+
+ $conn = null;
+ }
+ catch(PDOException $e)
+ {
+ echo "Error: " . $e->getMessage();
+ }
+ }
+ ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+     
[Log In for Additional Options]';
+ if(defined(REQUIRE_AUTH_FOR_LOGS) == true)
+ {
+ $_SESSION['chatlogs_admin'] = "NOT AUTHORIZED";
+ }
+ }
+ else
+ {
+ include_once (STEAM_AUTH_FOLDER.'userInfo.php'); //To access the $steamprofile array
+ $_SESSION['steamid2'] = toSteamID($steamprofile['steamid']);
+ echo '
Logged in as: '.$steamprofile['personaname'].'('.$_SESSION['steamid2'].')';
+ $_SESSION['chatlogs_admin'] = "NOT ADMIN";
+ if(in_array($_SESSION['steamid2'], $admins))
+ {
+ $_SESSION['chatlogs_admin'] = "ADMIN";
+ }
+ else if(defined(REQUIRE_AUTH_FOR_LOGS) == true)
+ {
+ $_SESSION['chatlogs_admin'] = "NOT AUTHORIZED";
+ }
+ echo '
['.$_SESSION['chatlogs_admin'].']';
+ echo '
'; //logoutbutton();
+ LogConnectedSteamID(toSteamID($steamprofile['steamid']), $steamprofile['personaname'], $servername, $username, $password, $dbname);
+ }
+ ?>
+
+
+
+
+
+
+ ';
+ }
+ ?>
+
+
+
+
+
+
+
+
+
+
+ ';
+ include_once('runquery.php');
+ echo '';
+ ?>
+
+
+
+
+
Page created by That One Guy.
+
+
+
\ No newline at end of file
diff --git a/ChatTags/web/chatlogs/runquery.php b/ChatTags/web/chatlogs/runquery.php
new file mode 100644
index 0000000..e3180a6
--- /dev/null
+++ b/ChatTags/web/chatlogs/runquery.php
@@ -0,0 +1,620 @@
+You must be logged in as an admin to view the chat logs!
';
+ die;
+ }
+
+ function noHTML($input, $encoding = 'UTF-8')
+ {
+ return htmlentities($input, ENT_QUOTES | ENT_HTML5, $encoding);
+ }
+
+ function GetSteamID64($steamid)
+ {
+ if(preg_match('/^STEAM_[0-9]:[0-9]:[0-9]{1,}/i', $steamid)) // Valid?
+ {
+ // Convert
+ $steamid = str_replace("_", ":", $steamid);
+ list($part_one, $part_two, $part_three, $part_four) = explode(':', $steamid);
+ $result = bcadd('76561197960265728', $part_four * 2);
+ return bcadd($result, $part_three);
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ if(!function_exists('toSteamID'))
+ {
+ function toSteamID($id) //https://gist.github.com/rannmann/49c1321b3239e00f442c
+ {
+ if(is_numeric($id) && strlen($id) >= 16)
+ {
+ $z = bcdiv(bcsub($id, '76561197960265728'), '2');
+ }
+ elseif (is_numeric($id))
+ {
+ $z = bcdiv($id, '2'); // Actually new User ID format
+ }
+ else
+ {
+ return $id; // We have no idea what this is, so just return it.
+ }
+ $y = bcmod($id, '2');
+ return 'STEAM_0:' . $y . ':' . floor($z);
+ }
+ }
+
+ $a_sColNames;
+ $a_sColNames = array();
+ $a_sServers;
+ $a_sServers = array();
+
+ define('ROOT_FOLDER', str_replace("/public", "", $_SERVER['DOCUMENT_ROOT']));
+ define('STEAM_AUTH_FOLDER', ROOT_FOLDER.'/steamauth/');
+
+ /*if(isset($_SESSION['steamid']))
+ {
+ include_once (STEAM_AUTH_FOLDER.'userInfo.php'); //To access the $steamprofile array
+ LogConnectedSteamID(toSteamID($steamprofile['steamid']), $steamprofile['personaname'], $servername, $username, $password, $dbname);
+ }*/
+ //echo 'session id: '.$_SESSION['steamid2'].'';
+ //include_once STEAM_AUTH_FOLDER.'steamauth.php';
+ //include_once (STEAM_AUTH_FOLDER.'userInfo.php'); //To access the $steamprofile array
+
+ //$_SESSION['steamid2'] = toSteamID($steamprofile['steamid']);
+ //$GLOBALS['steamid2']
+ //echo "";
+
+ if(isset($_GET["page"]))
+ {
+ $currentpage = urldecode($_GET["page"]);
+ }
+ else
+ {
+ $currentpage = 1;
+ };
+
+ if(isset($_GET["server"]))
+ {
+ $server = urldecode($_GET["server"]);
+ }
+ else
+ {
+ $server = 1;
+ };
+
+ if(isset($_GET["input"]) && isset($_GET["inputcol"]))
+ {
+ $input = urldecode($_GET["input"]);
+ $inputcol = urldecode($_GET["inputcol"]);
+ if($_SESSION['chatlogs_admin'] != "ADMIN")
+ {
+ if(($inputcol == "playerip"))
+ {
+ $input = "";
+ $inputcol = "";
+ }
+ }
+ }
+ else
+ {
+ $input = "";
+ $inputcol = "";
+ //echo "";
+ };
+
+ if(isset($_GET["ordercol"]))
+ {
+ $ordercol = urldecode($_GET["ordercol"]);
+ }
+ else
+ {
+ $ordercol = "id";
+ };
+
+ if(isset($_GET["reverse"]))
+ {
+ $reverse = urldecode($_GET["reverse"]);
+ }
+ else
+ {
+ $reverse = "";
+ };
+
+ class TableHeaders extends RecursiveIteratorIterator
+ {
+ function __construct($it)
+ {
+ parent::__construct($it, self::LEAVES_ONLY);
+ }
+
+ function current()
+ {
+ $colname = parent::current();
+ if(($colname == "playername"))
+ {
+ $minwidth = 200;
+ }
+ else if(($colname == "ip_country") || ($colname == "logdate"))
+ {
+ $minwidth = 110;
+ }
+ else if(($colname == "chatmsg"))
+ {
+ $minwidth = 250;
+ }
+ else if(($colname == "chatgrp"))
+ {
+ $minwidth = 75;
+ }
+ else if(($colname == "mapname") || ($colname == "server") || ($colname == "steamid"))
+ {
+ $minwidth = 140;
+ }
+ else
+ {
+ $minwidth = 0;
+ }
+
+ $colname = str_replace("_", " ", $colname);
+ if($colname == "mapname")
+ {
+ $colname = "Map Name";
+ }
+ else if($colname == "steamid")
+ {
+ $colname = "Steam ID";
+ }
+ else if($colname == "server")
+ {
+ $colname = "Server IP";
+ }
+ else if($colname == "playername")
+ {
+ $colname = "Player Name";
+ }
+ else if($colname == "playerip")
+ {
+ $colname = "Player IP";
+ }
+ else if($colname == "chatmsg")
+ {
+ $colname = "Chat Message";
+ }
+ else if($colname == "ip country")
+ {
+ $colname = "Country";
+ }
+ else if($colname == "ip_country")
+ {
+ $colname = "Country";
+ }
+ else if($colname == "chatgrp")
+ {
+ $colname = "Message Type";
+ }
+ else if($colname == "logdate")
+ {
+ $colname = "Message Date";
+ }
+
+ if(isset($_GET["ordercol"])) //if set
+ {
+ $ordercol = urldecode($_GET["ordercol"]);
+ if(!empty($ordercol)) //if not set to blank
+ {
+ if($ordercol == parent::current()) //if the current one we're setting, check for reverse
+ {
+ if(!isset($_GET["reverse"]))
+ {
+ //return "".$colname. " ▼ | ";
+ return "".$colname. " ▼ | ";
+ }
+ else
+ {
+ $reverse = urldecode($_GET["reverse"]);
+ if(($reverse == "false") || empty($reverse))
+ {
+ //return "".$colname. " ▼ | ";
+ return "".$colname. " ▼ | ";
+ }
+ else
+ {
+ //return "".$colname. " ▲ | ";
+ return "".$colname. " ▼ | ";
+ }
+ }
+ }
+ }
+ }
+ //return "".$colname. " | ";
+ return "".$colname. " | ";
+ }
+
+ function beginChildren()
+ {
+ echo "";
+ }
+
+ function endChildren()
+ {
+ echo "
";
+ }
+ }
+
+ class TableRows extends RecursiveIteratorIterator
+ {
+ function __construct($it)
+ {
+ parent::__construct($it, self::LEAVES_ONLY);
+ }
+
+ function current()
+ {
+ if(parent::current() == "")
+ {
+ $value = "-";
+ }
+ else
+ {
+ $value = noHTML(parent::current());
+ }
+ //return "".$value. " | ";
+ if(strpos($value, "STEAM_") === false)
+ {
+ return "".$value. " | ";
+ }
+ else
+ {
+ return '' .$value. ' | ';
+ }
+ }
+
+ function beginChildren()
+ {
+ echo "";
+ }
+
+ function endChildren()
+ {
+ echo "
" . "\n";
+ }
+ }
+
+ try
+ {
+ $conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
+ $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+
+ $stmt = $conn->prepare("SELECT DISTINCT server FROM ".$tblname);
+ $stmt->execute();
+ $result = $stmt->setFetchMode(PDO::FETCH_ASSOC);
+ $result = $stmt->fetchAll();
+ foreach ($result as $key => $value)
+ {
+ $a_sServers[] = $value['server'];
+ }
+
+ //create tabs
+ echo '';
+ echo '
';
+ echo '
';
+ foreach($a_sServers as $sServer)
+ {
+ $sServerName = $sServer;
+ if($sServerName == "13.73.0.133:27019")
+ {
+ $sServerName = "Test Server(".$sServerName.")";
+ }
+ else if($sServerName == "13.73.0.133:27017")
+ {
+ $sServerName = "Some Fake Server(".$sServerName.")";
+ }
+ echo '- '.$sServerName.'
';
+ }
+ echo '
';
+ echo '
';
+ echo '
';
+
+ foreach($a_sServers as $sServer)
+ {
+ $sServerDiv = str_replace(".", "_", str_replace(":", "_", $sServer));
+ $server = $sServer;
+
+ echo ' ';
+ /*echo '
';
+ echo '';
+ echo 'Server IP | Map Name | Steam ID | Player Name | ';
+ echo 'Country | Message Type | Message | Message Date |
';
+ */
+ //$stmt = $conn->prepare("SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '".$tblname."'");
+ $sQuery = "SELECT 'server','mapname','steamid','playername'";
+ if($_SESSION['chatlogs_admin'] == "ADMIN")
+ {
+ $sQuery .=",'playerip'";
+ }
+ $sQuery .=",'ip_country','chatgrp','chatmsg','logdate'";
+ $stmt = $conn->prepare($sQuery);
+ $stmt->execute();
+ // set the resulting array to associative
+ $result = $stmt->setFetchMode(PDO::FETCH_ASSOC);
+ $result = $stmt->fetchAll();
+ foreach ($result as $key => $value)
+ {
+ //$a_sColNames[] = $value['COLUMN_NAME'];
+ $a_sColNames[] = "server";
+ $a_sColNames[] = "mapname";
+ $a_sColNames[] = "steamid";
+ $a_sColNames[] = "playername";
+ $a_sColNames[] = "playerip";
+ $a_sColNames[] = "ip_country";
+ $a_sColNames[] = "chatgrp";
+ $a_sColNames[] = "chatmsg";
+ $a_sColNames[] = "logdate";
+ }
+ $headers = '';
+ foreach(new TableHeaders(new RecursiveArrayIterator($result)) as $key=>$value)
+ {
+ $headers = $headers.$value;
+ }
+ //echo "";
+ echo "";
+ echo $headers;
+
+ $start_from = ($currentpage - 1) * $num_rec_per_page;
+ if(empty($reverse) || ($reverse == "false"))
+ {
+ $orderdir = "DESC";
+ }
+ else
+ {
+ $orderdir = "ASC";
+ }
+ if($_SESSION['chatlogs_admin'] == "ADMIN")
+ {
+ //echo "";
+ $query = "SELECT server,mapname,steamid,playername,playerip,ip_country,chatgrp,chatmsg,logdate FROM ".$tblname." ";
+ }
+ else
+ {
+ //echo "";
+ $query = "SELECT server,mapname,steamid,playername,ip_country,chatgrp,chatmsg,logdate FROM ".$tblname." ";
+ }
+ $bWhere = false;
+
+ if(!empty($inputcol))
+ {
+ $bValid = false;
+ foreach($a_sColNames as $sColName)
+ {
+ if($sColName == $inputcol)
+ {
+ $bValid = true;
+ break;
+ }
+ }
+
+ if($bValid == false)
+ {
+ $inputcol = "";
+ }
+ }
+
+ $bValid = false;
+ foreach($a_sColNames as $sColName)
+ {
+ if($sColName == $ordercol)
+ {
+ $bValid = true;
+ break;
+ }
+ }
+ if($bValid == false)
+ {
+ $ordercol = "id";
+ }
+
+ if(!(empty($input) || empty($inputcol)))
+ {
+ $bWhere = true;
+ if(($inputcol == "playername") || ($inputcol == "playerip") || ($inputcol == "steamid") || ($inputcol == "chatmsg"))
+ {
+ $query = $query."WHERE (".$inputcol." LIKE :inputstr) ";
+ $inputtemp = '%'.$input.'%';
+ }
+ else
+ {
+ $query = $query."WHERE (".$inputcol." = :inputstr) ";
+ }
+ }
+
+ if(!empty($server))
+ {
+ if($bWhere === false)
+ {
+ $query = $query."WHERE (server = :server) ";
+ }
+ else
+ {
+ $query = $query."AND (server = :server) ";
+ }
+ $bWhere = true;
+ }
+
+ $query = $query." ORDER BY ".$ordercol." ".$orderdir." LIMIT :startpgnum, ".$num_rec_per_page;
+ //echo $query;
+ $stmt = $conn->prepare($query);
+ if(!(empty($input) || empty($inputcol)))
+ {
+ $stmt->bindValue(":inputstr", $inputtemp, PDO::PARAM_STR);
+ }
+ if(!empty($server))
+ {
+ $stmt->bindValue(":server", $server, PDO::PARAM_STR);
+ }
+ $stmt->bindValue(":startpgnum", $start_from, PDO::PARAM_INT);
+ $stmt->execute();
+
+ // set the resulting array to associative
+ $result = $stmt->setFetchMode(PDO::FETCH_ASSOC);
+
+ foreach(new TableRows(new RecursiveArrayIterator($stmt->fetchAll())) as $k=>$v)
+ {
+ echo $v;
+ }
+ echo "
";
+
+ //page numbers
+ if(empty($input) || empty($inputcol))
+ {
+ if(!empty($server))
+ {
+ $query = "SELECT * FROM ".$tblname." WHERE server = :server";
+ }
+ else
+ {
+ $query = "SELECT * FROM ".$tblname;
+ }
+ }
+ else
+ {
+ if(($inputcol == "playername") || ($inputcol == "playerip") || ($inputcol == "steamid") || ($inputcol == "chatmsg"))
+ {
+ $query = "SELECT * FROM ".$tblname." WHERE ".$inputcol." LIKE :inputstr";
+ $inputtemp = '%'.$input.'%';
+ }
+ else
+ {
+ $query = "SELECT * FROM ".$tblname." WHERE ".$inputcol." = :inputstr";
+ }
+ if(!empty($server))
+ {
+ $query = $query." AND server = :server";
+ }
+ }
+ $stmt = $conn->prepare($query);
+ if(!(empty($input) || empty($inputcol)))
+ {
+ $stmt->bindValue(":inputstr", $inputtemp, PDO::PARAM_STR);
+ }
+ if(!empty($server))
+ {
+ $stmt->bindValue(":server", $server, PDO::PARAM_STR);
+ }
+ $stmt->execute();
+ $i_count = $stmt->rowCount();
+ $total_pages = ceil($i_count / $num_rec_per_page);
+
+ echo "Page: ";
+ if($total_pages <= 10)
+ {
+ for($i = 1; $i <= $total_pages; $i++)
+ {
+ if($i == $currentpage)
+ {
+ echo "".$i."";
+ }
+ else
+ {
+ echo ''.$i.'';
+ }
+ echo " ";
+ };
+ }
+ else
+ {
+ if($currentpage < 8) //7 or less, then list first 10
+ {
+ for($i = 1; $i <= 9; $i++)
+ {
+ if($i == $currentpage)
+ {
+ echo "".$i."";
+ }
+ else
+ {
+ echo ''.$i.'';
+ }
+ echo " ";
+ };
+ echo '>'; // Goto next page at end of list
+ echo " ... ";
+ echo ''.$total_pages.''; // Goto last page
+ }
+ else
+ {
+ echo '1'; // Goto 1st page
+ echo ' 2';
+ echo ' 3';
+ echo ' ... ';
+ $i_temp = $currentpage - 2;
+ echo ''.$i_temp.' '; //2 less
+ $i_temp++;
+ echo ''.$i_temp.' '; //1 less
+ $i_temp++;
+ echo "".$i_temp.""; //current
+ echo " ";
+ $i_temp++;
+ if($i_temp <= $total_pages) //if not past last, continue
+ {
+ echo ''.$i_temp.' '; //1 past current
+ $i_temp++;
+ if($i_temp <= $total_pages) //if not past last, continue
+ {
+ echo ''.$i_temp.' '; //2 past current
+ $i_temp++;
+ if($i_temp <= $total_pages) //if not past last, show 'next'
+ {
+ if(($i_temp + 1 == $total_pages) || ($i_temp == $total_pages)) //show number if within last 2
+ {
+ echo ''.$i_temp.'';
+ }
+ else //show symbol for next instead of number
+ {
+ echo '>';
+ }
+ $i_temp++;
+
+ if($i_temp <= $total_pages) //if not past last, show last
+ {
+ if($i_temp < $total_pages)
+ {
+ echo " ... ";
+ }
+ else
+ {
+ echo " ";
+ }
+
+ echo ''.$total_pages.''; // Goto last page
+ }
+ }
+ }
+ }
+ }
+ }
+ echo '';
+ }
+ }
+ catch(PDOException $e)
+ {
+ echo "Error: " . $e->getMessage();
+ }
+ $conn = null;
+?>
\ No newline at end of file
diff --git a/ChatTags/web/servervalidation/Instructions.txt b/ChatTags/web/servervalidation/Instructions.txt
new file mode 100644
index 0000000..394454b
--- /dev/null
+++ b/ChatTags/web/servervalidation/Instructions.txt
@@ -0,0 +1,54 @@
+1. Create a database, username, and password for the plugin validation table.
+
+////////////////////////////////////////////////////////////////////
+2. Run the query to create the validation table. It is stored in Validation Database Table Creation Query.sql
+ You can certainly add additional columns for keeping notes, as required. The notes column isnt actually used by the validation, so you can leave that out if you wish as well.
+
+////////////////////////////////////////////////////////////////////
+3. Edit lines 2-5 of validationdatabase_web.php to be the database information set up in step 1.
+
+////////////////////////////////////////////////////////////////////
+4. Edit the include for the plugin: servervalidation.inc
+ Change the line: #define VALIDATION_PHP_URL "http://www.domain.com/servervalidation/validationdatabase_web.php"
+ Set it to the path for wherever you installed the servervalidation folder.
+
+////////////////////////////////////////////////////////////////////
+5. Look for the following lines near the top of the plugin that is to be validated. If they dont exist, add them:
+
+#if defined(VALIDATION_TIME) || defined(VALIDATION_IP) || defined(VALIDATION_HOSTNAME) || defined(VALIDATION_DATABASE)
+ #include
+#endif
+
+Directly above these lines, add this line:
+
+#define VALIDATION_DATABASE
+
+////////////////////////////////////////////////////////////////////
+6. Search in the plugin for: public void OnPluginStart().
+ Note: The word void may or may not be included in the line if it is old syntax.
+ Inside of this function, add the following code (if it doesnt already exist):
+
+#if defined(VALIDATION_TIME) || defined(VALIDATION_IP) || defined(VALIDATION_HOSTNAME) || defined(VALIDATION_DATABASE)
+ ValidateServer("SOME PLUGIN KEY HERE");
+#endif
+
+ Note: Replace "SOME PLUGIN KEY HERE" with some custom key for further validation that is harder to spoof.
+ Leave as empty quotes to exclude the additional check (though there is no reason not to use it).
+
+////////////////////////////////////////////////////////////////////
+7. Recompile the plugin.
+
+////////////////////////////////////////////////////////////////////
+8. In the database, insert a row with the server IP under `serveraddr`, the plugin file name under `pluginname`, and the key you made in step 6 under `pluginkey`.
+ At this time, the port is not checked in the validation.
+ For the plugin name, you dont need to include .smx, but it wont break the validation if you do.
+ The validaiton query will look for the pluginname with wildcards on either side, so if the database has .smx included, it will still find a match.
+
+ Note: The whole PHP page is coded using prepared statements to protect against SQL injection.
+////////////////////////////////////////////////////////////////////
+9. Install socket extension on the game server. This extension is used to communicate with the web page. You can find the extension here:
+https://forums.alliedmods.net/showthread.php?t=67640
+
+////////////////////////////////////////////////////////////////////
+10. Put the plugin on the server and reload it via RCon (sm plugins reload YOUR_PLUGINS_NAME_HERE).
+ If you changed anything in your databases.cfg file for the plugin, you will need to restart the server.
diff --git a/ChatTags/web/servervalidation/Validation Database Table Creation Query.sql b/ChatTags/web/servervalidation/Validation Database Table Creation Query.sql
new file mode 100644
index 0000000..c78b72a
--- /dev/null
+++ b/ChatTags/web/servervalidation/Validation Database Table Creation Query.sql
@@ -0,0 +1,8 @@
+CREATE TABLE IF NOT EXISTS `validatedplugins` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `serveraddr` varchar(60) NOT NULL,
+ `pluginname` varchar(200) NOT NULL,
+ `pluginkey` varchar(200) DEFAULT NULL,
+ `notes` varchar(200) DEFAULT NULL,
+ PRIMARY KEY (`id`)
+) DEFAULT CHARSET=utf8;
\ No newline at end of file
diff --git a/ChatTags/web/servervalidation/validationdatabase_web.php b/ChatTags/web/servervalidation/validationdatabase_web.php
new file mode 100644
index 0000000..f350489
--- /dev/null
+++ b/ChatTags/web/servervalidation/validationdatabase_web.php
@@ -0,0 +1,62 @@
+setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+
+ if(isset($_GET["pluginkey"]))
+ {
+ $pluginkey = $_GET["pluginkey"];
+ $stmt = $conn->prepare("SELECT serveraddr,pluginname,pluginkey FROM validatedplugins WHERE (serveraddr LIKE :serveraddr) AND (pluginname LIKE :pluginname) AND (pluginkey = :pluginkey);");
+ $stmt->bindValue(':serveraddr', "%{$serveraddr}%");
+ $stmt->bindValue(':pluginname', "%{$pluginname}%");
+ $stmt->bindValue(':pluginkey', $pluginkey);
+ }
+ else
+ {
+ $stmt = $conn->prepare("SELECT serveraddr,pluginname FROM validatedplugins WHERE (serveraddr LIKE :serveraddr) AND (pluginname LIKE :pluginname);");
+ $stmt->bindValue(':serveraddr', "%{$serveraddr}%");
+ $stmt->bindValue(':pluginname', "%{$pluginname}%");
+ }
+
+ $stmt->execute();
+ $row = $stmt->fetch(PDO::FETCH_ASSOC); //$row = $stmt->fetch();
+ $pos = strpos($row['pluginname'], $pluginname);
+ if(!($pos === false) && ($row['serveraddr'] == $serveraddr))
+ {
+ echo "PLUGIN IS VALID";
+ }
+ else
+ {
+ echo "PLUGIN IS INVALID!!!";
+ }
+ //var_dump($stmt);
+ //var_dump($row);
+ //$result = $stmt->setFetchMode(PDO::FETCH_ASSOC); // set the resulting array to associative
+ //echo "Plugin Valid: $result['pluginname']";
+ //echo $result['pluginname'];
+ //echo "";
+ }
+ catch(PDOException $e)
+ {
+ echo "Error: " . $e->getMessage();
+ }
+
+ $conn = null;
+ $stmt = null;
+?>
\ No newline at end of file
diff --git a/ChatTags/web/steamauth/SteamConfig.php b/ChatTags/web/steamauth/SteamConfig.php
new file mode 100644
index 0000000..561ff81
--- /dev/null
+++ b/ChatTags/web/steamauth/SteamConfig.php
@@ -0,0 +1,13 @@
+SteamAuth:
Please supply an API-Key!");}
+if (empty($steamauth['domainname'])) {$steamauth['domainname'] = $_SERVER['SERVER_NAME'];}
+if (empty($steamauth['logoutpage'])) {$steamauth['logoutpage'] = $_SERVER['PHP_SELF'];}
+if (empty($steamauth['loginpage'])) {$steamauth['loginpage'] = $_SERVER['PHP_SELF'];}
+?>
diff --git a/ChatTags/web/steamauth/openid.php b/ChatTags/web/steamauth/openid.php
new file mode 100644
index 0000000..d160236
--- /dev/null
+++ b/ChatTags/web/steamauth/openid.php
@@ -0,0 +1,1076 @@
+= 5.1.2 with cURL or HTTP/HTTPS stream wrappers enabled.
+ *
+ * @version v1.3.1 (2016-03-04)
+ * @link https://code.google.com/p/lightopenid/ Project URL
+ * @link https://github.com/iignatov/LightOpenID GitHub Repo
+ * @author Mewp
+ * @copyright Copyright (c) 2013 Mewp
+ * @license http://opensource.org/licenses/mit-license.php MIT License
+ */
+class LightOpenID
+{
+ public $returnUrl
+ , $required = array()
+ , $optional = array()
+ , $verify_peer = null
+ , $capath = null
+ , $cainfo = null
+ , $cnmatch = null
+ , $data
+ , $oauth = array()
+ , $curl_time_out = 30 // in seconds
+ , $curl_connect_time_out = 30; // in seconds
+ private $identity, $claimed_id;
+ protected $server, $version, $trustRoot, $aliases, $identifier_select = false
+ , $ax = false, $sreg = false, $setup_url = null, $headers = array()
+ , $proxy = null, $user_agent = 'LightOpenID'
+ , $xrds_override_pattern = null, $xrds_override_replacement = null;
+ static protected $ax_to_sreg = array(
+ 'namePerson/friendly' => 'nickname',
+ 'contact/email' => 'email',
+ 'namePerson' => 'fullname',
+ 'birthDate' => 'dob',
+ 'person/gender' => 'gender',
+ 'contact/postalCode/home' => 'postcode',
+ 'contact/country/home' => 'country',
+ 'pref/language' => 'language',
+ 'pref/timezone' => 'timezone',
+ );
+
+ function __construct($host, $proxy = null)
+ {
+ $this->set_realm($host);
+ $this->set_proxy($proxy);
+
+ $uri = rtrim(preg_replace('#((?<=\?)|&)openid\.[^&]+#', '', $_SERVER['REQUEST_URI']), '?');
+ $this->returnUrl = $this->trustRoot . $uri;
+
+ $this->data = ($_SERVER['REQUEST_METHOD'] === 'POST') ? $_POST : $_GET;
+
+ if(!function_exists('curl_init') && !in_array('https', stream_get_wrappers())) {
+ throw new ErrorException('You must have either https wrappers or curl enabled.');
+ }
+ }
+
+ function __isset($name)
+ {
+ return in_array($name, array('identity', 'trustRoot', 'realm', 'xrdsOverride', 'mode'));
+ }
+
+ function __set($name, $value)
+ {
+ switch ($name) {
+ case 'identity':
+ if (strlen($value = trim((String) $value))) {
+ if (preg_match('#^xri:/*#i', $value, $m)) {
+ $value = substr($value, strlen($m[0]));
+ } elseif (!preg_match('/^(?:[=@+\$!\(]|https?:)/i', $value)) {
+ $value = "http://$value";
+ }
+ if (preg_match('#^https?://[^/]+$#i', $value, $m)) {
+ $value .= '/';
+ }
+ }
+ $this->$name = $this->claimed_id = $value;
+ break;
+ case 'trustRoot':
+ case 'realm':
+ $this->trustRoot = trim($value);
+ break;
+ case 'xrdsOverride':
+ if (is_array($value)) {
+ list($pattern, $replacement) = $value;
+ $this->xrds_override_pattern = $pattern;
+ $this->xrds_override_replacement = $replacement;
+ } else {
+ trigger_error('Invalid value specified for "xrdsOverride".', E_USER_ERROR);
+ }
+ break;
+ }
+ }
+
+ function __get($name)
+ {
+ switch ($name) {
+ case 'identity':
+ # We return claimed_id instead of identity,
+ # because the developer should see the claimed identifier,
+ # i.e. what he set as identity, not the op-local identifier (which is what we verify)
+ return $this->claimed_id;
+ case 'trustRoot':
+ case 'realm':
+ return $this->trustRoot;
+ case 'mode':
+ return empty($this->data['openid_mode']) ? null : $this->data['openid_mode'];
+ }
+ }
+
+ function set_proxy($proxy)
+ {
+ if (!empty($proxy)) {
+ // When the proxy is a string - try to parse it.
+ if (!is_array($proxy)) {
+ $proxy = parse_url($proxy);
+ }
+
+ // Check if $proxy is valid after the parsing.
+ if ($proxy && !empty($proxy['host'])) {
+ // Make sure that a valid port number is specified.
+ if (array_key_exists('port', $proxy)) {
+ if (!is_int($proxy['port'])) {
+ $proxy['port'] = is_numeric($proxy['port']) ? intval($proxy['port']) : 0;
+ }
+
+ if ($proxy['port'] <= 0) {
+ throw new ErrorException('The specified proxy port number is invalid.');
+ }
+ }
+
+ $this->proxy = $proxy;
+ }
+ }
+ }
+
+ /**
+ * Checks if the server specified in the url exists.
+ *
+ * @param $url url to check
+ * @return true, if the server exists; false otherwise
+ */
+ function hostExists($url)
+ {
+ if (strpos($url, '/') === false) {
+ $server = $url;
+ } else {
+ $server = @parse_url($url, PHP_URL_HOST);
+ }
+
+ if (!$server) {
+ return false;
+ }
+
+ return !!gethostbynamel($server);
+ }
+
+ protected function set_realm($uri)
+ {
+ $realm = '';
+
+ # Set a protocol, if not specified.
+ $realm .= (($offset = strpos($uri, '://')) === false) ? $this->get_realm_protocol() : '';
+
+ # Set the offset properly.
+ $offset = (($offset !== false) ? $offset + 3 : 0);
+
+ # Get only the root, without the path.
+ $realm .= (($end = strpos($uri, '/', $offset)) === false) ? $uri : substr($uri, 0, $end);
+
+ $this->trustRoot = $realm;
+ }
+
+ protected function get_realm_protocol()
+ {
+ if (!empty($_SERVER['HTTPS'])) {
+ $use_secure_protocol = ($_SERVER['HTTPS'] != 'off');
+ } else if (isset($_SERVER['HTTP_X_FORWARDED_PROTO'])) {
+ $use_secure_protocol = ($_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https');
+ } else if (isset($_SERVER['HTTP__WSSC'])) {
+ $use_secure_protocol = ($_SERVER['HTTP__WSSC'] == 'https');
+ } else {
+ $use_secure_protocol = false;
+ }
+
+ return $use_secure_protocol ? 'https://' : 'http://';
+ }
+
+ protected function request_curl($url, $method='GET', $params=array(), $update_claimed_id)
+ {
+ $params = http_build_query($params, '', '&');
+ $curl = curl_init($url . ($method == 'GET' && $params ? '?' . $params : ''));
+ curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
+ curl_setopt($curl, CURLOPT_HEADER, false);
+ curl_setopt($curl, CURLOPT_USERAGENT, $this->user_agent);
+ curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
+
+ if ($method == 'POST') {
+ curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-type: application/x-www-form-urlencoded'));
+ } else {
+ curl_setopt($curl, CURLOPT_HTTPHEADER, array('Accept: application/xrds+xml, */*'));
+ }
+
+ curl_setopt($curl, CURLOPT_TIMEOUT, $this->curl_time_out); // defaults to infinite
+ curl_setopt($curl, CURLOPT_CONNECTTIMEOUT , $this->curl_connect_time_out); // defaults to 300s
+
+ if (!empty($this->proxy)) {
+ curl_setopt($curl, CURLOPT_PROXY, $this->proxy['host']);
+
+ if (!empty($this->proxy['port'])) {
+ curl_setopt($curl, CURLOPT_PROXYPORT, $this->proxy['port']);
+ }
+
+ if (!empty($this->proxy['user'])) {
+ curl_setopt($curl, CURLOPT_PROXYUSERPWD, $this->proxy['user'] . ':' . $this->proxy['pass']);
+ }
+ }
+
+ if($this->verify_peer !== null) {
+ curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, $this->verify_peer);
+ if($this->capath) {
+ curl_setopt($curl, CURLOPT_CAPATH, $this->capath);
+ }
+
+ if($this->cainfo) {
+ curl_setopt($curl, CURLOPT_CAINFO, $this->cainfo);
+ }
+ }
+
+ if ($method == 'POST') {
+ curl_setopt($curl, CURLOPT_POST, true);
+ curl_setopt($curl, CURLOPT_POSTFIELDS, $params);
+ } elseif ($method == 'HEAD') {
+ curl_setopt($curl, CURLOPT_HEADER, true);
+ curl_setopt($curl, CURLOPT_NOBODY, true);
+ } else {
+ curl_setopt($curl, CURLOPT_HEADER, true);
+ curl_setopt($curl, CURLOPT_HTTPGET, true);
+ }
+ $response = curl_exec($curl);
+
+ if($method == 'HEAD' && curl_getinfo($curl, CURLINFO_HTTP_CODE) == 405) {
+ curl_setopt($curl, CURLOPT_HTTPGET, true);
+ $response = curl_exec($curl);
+ $response = substr($response, 0, strpos($response, "\r\n\r\n"));
+ }
+
+ if($method == 'HEAD' || $method == 'GET') {
+ $header_response = $response;
+
+ # If it's a GET request, we want to only parse the header part.
+ if($method == 'GET') {
+ $header_response = substr($response, 0, strpos($response, "\r\n\r\n"));
+ }
+
+ $headers = array();
+ foreach(explode("\n", $header_response) as $header) {
+ $pos = strpos($header,':');
+ if ($pos !== false) {
+ $name = strtolower(trim(substr($header, 0, $pos)));
+ $headers[$name] = trim(substr($header, $pos+1));
+ }
+ }
+
+ if($update_claimed_id) {
+ # Update the claimed_id value in case of redirections.
+ $effective_url = curl_getinfo($curl, CURLINFO_EFFECTIVE_URL);
+ # Ignore the fragment (some cURL versions don't handle it well).
+ if (strtok($effective_url, '#') != strtok($url, '#')) {
+ $this->identity = $this->claimed_id = $effective_url;
+ }
+ }
+
+ if($method == 'HEAD') {
+ return $headers;
+ } else {
+ $this->headers = $headers;
+ }
+ }
+
+ if (curl_errno($curl)) {
+ throw new ErrorException(curl_error($curl), curl_errno($curl));
+ }
+
+ return $response;
+ }
+
+ protected function parse_header_array($array, $update_claimed_id)
+ {
+ $headers = array();
+ foreach($array as $header) {
+ $pos = strpos($header,':');
+ if ($pos !== false) {
+ $name = strtolower(trim(substr($header, 0, $pos)));
+ $headers[$name] = trim(substr($header, $pos+1));
+
+ # Following possible redirections. The point is just to have
+ # claimed_id change with them, because the redirections
+ # are followed automatically.
+ # We ignore redirections with relative paths.
+ # If any known provider uses them, file a bug report.
+ if($name == 'location' && $update_claimed_id) {
+ if(strpos($headers[$name], 'http') === 0) {
+ $this->identity = $this->claimed_id = $headers[$name];
+ } elseif($headers[$name][0] == '/') {
+ $parsed_url = parse_url($this->claimed_id);
+ $this->identity =
+ $this->claimed_id = $parsed_url['scheme'] . '://'
+ . $parsed_url['host']
+ . $headers[$name];
+ }
+ }
+ }
+ }
+ return $headers;
+ }
+
+ protected function request_streams($url, $method='GET', $params=array(), $update_claimed_id)
+ {
+ if(!$this->hostExists($url)) {
+ throw new ErrorException("Could not connect to $url.", 404);
+ }
+
+ if (empty($this->cnmatch)) {
+ $this->cnmatch = parse_url($url, PHP_URL_HOST);
+ }
+
+ $params = http_build_query($params, '', '&');
+ switch($method) {
+ case 'GET':
+ $opts = array(
+ 'http' => array(
+ 'method' => 'GET',
+ 'header' => 'Accept: application/xrds+xml, */*',
+ 'user_agent' => $this->user_agent,
+ 'ignore_errors' => true,
+ ),
+ 'ssl' => array(
+ 'CN_match' => $this->cnmatch
+ )
+ );
+ $url = $url . ($params ? '?' . $params : '');
+ if (!empty($this->proxy)) {
+ $opts['http']['proxy'] = $this->proxy_url();
+ }
+ break;
+ case 'POST':
+ $opts = array(
+ 'http' => array(
+ 'method' => 'POST',
+ 'header' => 'Content-type: application/x-www-form-urlencoded',
+ 'user_agent' => $this->user_agent,
+ 'content' => $params,
+ 'ignore_errors' => true,
+ ),
+ 'ssl' => array(
+ 'CN_match' => $this->cnmatch
+ )
+ );
+ if (!empty($this->proxy)) {
+ $opts['http']['proxy'] = $this->proxy_url();
+ }
+ break;
+ case 'HEAD':
+ // We want to send a HEAD request, but since get_headers() doesn't
+ // accept $context parameter, we have to change the defaults.
+ $default = stream_context_get_options(stream_context_get_default());
+
+ // PHP does not reset all options. Instead, it just sets the options
+ // available in the passed array, therefore set the defaults manually.
+ $default += array(
+ 'http' => array(),
+ 'ssl' => array()
+ );
+ $default['http'] += array(
+ 'method' => 'GET',
+ 'header' => '',
+ 'user_agent' => '',
+ 'ignore_errors' => false
+ );
+ $default['ssl'] += array(
+ 'CN_match' => ''
+ );
+
+ $opts = array(
+ 'http' => array(
+ 'method' => 'HEAD',
+ 'header' => 'Accept: application/xrds+xml, */*',
+ 'user_agent' => $this->user_agent,
+ 'ignore_errors' => true,
+ ),
+ 'ssl' => array(
+ 'CN_match' => $this->cnmatch
+ )
+ );
+
+ // Enable validation of the SSL certificates.
+ if ($this->verify_peer) {
+ $default['ssl'] += array(
+ 'verify_peer' => false,
+ 'capath' => '',
+ 'cafile' => ''
+ );
+ $opts['ssl'] += array(
+ 'verify_peer' => true,
+ 'capath' => $this->capath,
+ 'cafile' => $this->cainfo
+ );
+ }
+
+ // Change the stream context options.
+ stream_context_get_default($opts);
+
+ $headers = get_headers($url . ($params ? '?' . $params : ''));
+
+ // Restore the stream context options.
+ stream_context_get_default($default);
+
+ if (!empty($headers)) {
+ if (intval(substr($headers[0], strlen('HTTP/1.1 '))) == 405) {
+ // The server doesn't support HEAD - emulate it with a GET.
+ $args = func_get_args();
+ $args[1] = 'GET';
+ call_user_func_array(array($this, 'request_streams'), $args);
+ $headers = $this->headers;
+ } else {
+ $headers = $this->parse_header_array($headers, $update_claimed_id);
+ }
+ } else {
+ $headers = array();
+ }
+
+ return $headers;
+ }
+
+ if ($this->verify_peer) {
+ $opts['ssl'] += array(
+ 'verify_peer' => true,
+ 'capath' => $this->capath,
+ 'cafile' => $this->cainfo
+ );
+ }
+
+ $context = stream_context_create ($opts);
+ $data = file_get_contents($url, false, $context);
+ # This is a hack for providers who don't support HEAD requests.
+ # It just creates the headers array for the last request in $this->headers.
+ if(isset($http_response_header)) {
+ $this->headers = $this->parse_header_array($http_response_header, $update_claimed_id);
+ }
+
+ return $data;
+ }
+
+ protected function request($url, $method='GET', $params=array(), $update_claimed_id=false)
+ {
+ $use_curl = false;
+
+ if (function_exists('curl_init')) {
+ if (!$use_curl) {
+ # When allow_url_fopen is disabled, PHP streams will not work.
+ $use_curl = !ini_get('allow_url_fopen');
+ }
+
+ if (!$use_curl) {
+ # When there is no HTTPS wrapper, PHP streams cannott be used.
+ $use_curl = !in_array('https', stream_get_wrappers());
+ }
+
+ if (!$use_curl) {
+ # With open_basedir or safe_mode set, cURL can't follow redirects.
+ $use_curl = !(ini_get('safe_mode') || ini_get('open_basedir'));
+ }
+ }
+
+ return
+ $use_curl
+ ? $this->request_curl($url, $method, $params, $update_claimed_id)
+ : $this->request_streams($url, $method, $params, $update_claimed_id);
+ }
+
+ protected function proxy_url()
+ {
+ $result = '';
+
+ if (!empty($this->proxy)) {
+ $result = $this->proxy['host'];
+
+ if (!empty($this->proxy['port'])) {
+ $result = $result . ':' . $this->proxy['port'];
+ }
+
+ if (!empty($this->proxy['user'])) {
+ $result = $this->proxy['user'] . ':' . $this->proxy['pass'] . '@' . $result;
+ }
+
+ $result = 'http://' . $result;
+ }
+
+ return $result;
+ }
+
+ protected function build_url($url, $parts)
+ {
+ if (isset($url['query'], $parts['query'])) {
+ $parts['query'] = $url['query'] . '&' . $parts['query'];
+ }
+
+ $url = $parts + $url;
+ $url = $url['scheme'] . '://'
+ . (empty($url['username'])?''
+ :(empty($url['password'])? "{$url['username']}@"
+ :"{$url['username']}:{$url['password']}@"))
+ . $url['host']
+ . (empty($url['port'])?'':":{$url['port']}")
+ . (empty($url['path'])?'':$url['path'])
+ . (empty($url['query'])?'':"?{$url['query']}")
+ . (empty($url['fragment'])?'':"#{$url['fragment']}");
+ return $url;
+ }
+
+ /**
+ * Helper function used to scan for / tags and extract information
+ * from them
+ */
+ protected function htmlTag($content, $tag, $attrName, $attrValue, $valueName)
+ {
+ preg_match_all("#<{$tag}[^>]*$attrName=['\"].*?$attrValue.*?['\"][^>]*$valueName=['\"](.+?)['\"][^>]*/?>#i", $content, $matches1);
+ preg_match_all("#<{$tag}[^>]*$valueName=['\"](.+?)['\"][^>]*$attrName=['\"].*?$attrValue.*?['\"][^>]*/?>#i", $content, $matches2);
+
+ $result = array_merge($matches1[1], $matches2[1]);
+ return empty($result)?false:$result[0];
+ }
+
+ /**
+ * Performs Yadis and HTML discovery. Normally not used.
+ * @param $url Identity URL.
+ * @return String OP Endpoint (i.e. OpenID provider address).
+ * @throws ErrorException
+ */
+ function discover($url)
+ {
+ if (!$url) throw new ErrorException('No identity supplied.');
+ # Use xri.net proxy to resolve i-name identities
+ if (!preg_match('#^https?:#', $url)) {
+ $url = "https://xri.net/$url";
+ }
+
+ # We save the original url in case of Yadis discovery failure.
+ # It can happen when we'll be lead to an XRDS document
+ # which does not have any OpenID2 services.
+ $originalUrl = $url;
+
+ # A flag to disable yadis discovery in case of failure in headers.
+ $yadis = true;
+
+ # Allows optional regex replacement of the URL, e.g. to use Google Apps
+ # as an OpenID provider without setting up XRDS on the domain hosting.
+ if (!is_null($this->xrds_override_pattern) && !is_null($this->xrds_override_replacement)) {
+ $url = preg_replace($this->xrds_override_pattern, $this->xrds_override_replacement, $url);
+ }
+
+ # We'll jump a maximum of 5 times, to avoid endless redirections.
+ for ($i = 0; $i < 5; $i ++) {
+ if ($yadis) {
+ $headers = $this->request($url, 'HEAD', array(), true);
+
+ $next = false;
+ if (isset($headers['x-xrds-location'])) {
+ $url = $this->build_url(parse_url($url), parse_url(trim($headers['x-xrds-location'])));
+ $next = true;
+ }
+
+ if (isset($headers['content-type']) && $this->is_allowed_type($headers['content-type'])) {
+ # Found an XRDS document, now let's find the server, and optionally delegate.
+ $content = $this->request($url, 'GET');
+
+ preg_match_all('#(.*?)#s', $content, $m);
+ foreach($m[1] as $content) {
+ $content = ' ' . $content; # The space is added, so that strpos doesn't return 0.
+
+ # OpenID 2
+ $ns = preg_quote('http://specs.openid.net/auth/2.0/', '#');
+ if(preg_match('#\s*'.$ns.'(server|signon)\s*#s', $content, $type)) {
+ if ($type[1] == 'server') $this->identifier_select = true;
+
+ preg_match('#(.*)#', $content, $server);
+ preg_match('#<(Local|Canonical)ID>(.*)\1ID>#', $content, $delegate);
+ if (empty($server)) {
+ return false;
+ }
+ # Does the server advertise support for either AX or SREG?
+ $this->ax = (bool) strpos($content, 'http://openid.net/srv/ax/1.0');
+ $this->sreg = strpos($content, 'http://openid.net/sreg/1.0')
+ || strpos($content, 'http://openid.net/extensions/sreg/1.1');
+
+ $server = $server[1];
+ if (isset($delegate[2])) $this->identity = trim($delegate[2]);
+ $this->version = 2;
+
+ $this->server = $server;
+ return $server;
+ }
+
+ # OpenID 1.1
+ $ns = preg_quote('http://openid.net/signon/1.1', '#');
+ if (preg_match('#\s*'.$ns.'\s*#s', $content)) {
+
+ preg_match('#(.*)#', $content, $server);
+ preg_match('#<.*?Delegate>(.*)#', $content, $delegate);
+ if (empty($server)) {
+ return false;
+ }
+ # AX can be used only with OpenID 2.0, so checking only SREG
+ $this->sreg = strpos($content, 'http://openid.net/sreg/1.0')
+ || strpos($content, 'http://openid.net/extensions/sreg/1.1');
+
+ $server = $server[1];
+ if (isset($delegate[1])) $this->identity = $delegate[1];
+ $this->version = 1;
+
+ $this->server = $server;
+ return $server;
+ }
+ }
+
+ $next = true;
+ $yadis = false;
+ $url = $originalUrl;
+ $content = null;
+ break;
+ }
+ if ($next) continue;
+
+ # There are no relevant information in headers, so we search the body.
+ $content = $this->request($url, 'GET', array(), true);
+
+ if (isset($this->headers['x-xrds-location'])) {
+ $url = $this->build_url(parse_url($url), parse_url(trim($this->headers['x-xrds-location'])));
+ continue;
+ }
+
+ $location = $this->htmlTag($content, 'meta', 'http-equiv', 'X-XRDS-Location', 'content');
+ if ($location) {
+ $url = $this->build_url(parse_url($url), parse_url($location));
+ continue;
+ }
+ }
+
+ if (!$content) $content = $this->request($url, 'GET');
+
+ # At this point, the YADIS Discovery has failed, so we'll switch
+ # to openid2 HTML discovery, then fallback to openid 1.1 discovery.
+ $server = $this->htmlTag($content, 'link', 'rel', 'openid2.provider', 'href');
+ $delegate = $this->htmlTag($content, 'link', 'rel', 'openid2.local_id', 'href');
+ $this->version = 2;
+
+ if (!$server) {
+ # The same with openid 1.1
+ $server = $this->htmlTag($content, 'link', 'rel', 'openid.server', 'href');
+ $delegate = $this->htmlTag($content, 'link', 'rel', 'openid.delegate', 'href');
+ $this->version = 1;
+ }
+
+ if ($server) {
+ # We found an OpenID2 OP Endpoint
+ if ($delegate) {
+ # We have also found an OP-Local ID.
+ $this->identity = $delegate;
+ }
+ $this->server = $server;
+ return $server;
+ }
+
+ throw new ErrorException("No OpenID Server found at $url", 404);
+ }
+ throw new ErrorException('Endless redirection!', 500);
+ }
+
+ protected function is_allowed_type($content_type) {
+ # Apparently, some providers return XRDS documents as text/html.
+ # While it is against the spec, allowing this here shouldn't break
+ # compatibility with anything.
+ $allowed_types = array('application/xrds+xml', 'text/xml');
+
+ # Only allow text/html content type for the Yahoo logins, since
+ # it might cause an endless redirection for the other providers.
+ if ($this->get_provider_name($this->claimed_id) == 'yahoo') {
+ $allowed_types[] = 'text/html';
+ }
+
+ foreach ($allowed_types as $type) {
+ if (strpos($content_type, $type) !== false) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ protected function get_provider_name($provider_url) {
+ $result = '';
+
+ if (!empty($provider_url)) {
+ $tokens = array_reverse(
+ explode('.', parse_url($provider_url, PHP_URL_HOST))
+ );
+ $result = strtolower(
+ (count($tokens) > 1 && strlen($tokens[1]) > 3)
+ ? $tokens[1]
+ : (count($tokens) > 2 ? $tokens[2] : '')
+ );
+ }
+
+ return $result;
+ }
+
+ protected function sregParams()
+ {
+ $params = array();
+ # We always use SREG 1.1, even if the server is advertising only support for 1.0.
+ # That's because it's fully backwards compatible with 1.0, and some providers
+ # advertise 1.0 even if they accept only 1.1. One such provider is myopenid.com
+ $params['openid.ns.sreg'] = 'http://openid.net/extensions/sreg/1.1';
+ if ($this->required) {
+ $params['openid.sreg.required'] = array();
+ foreach ($this->required as $required) {
+ if (!isset(self::$ax_to_sreg[$required])) continue;
+ $params['openid.sreg.required'][] = self::$ax_to_sreg[$required];
+ }
+ $params['openid.sreg.required'] = implode(',', $params['openid.sreg.required']);
+ }
+
+ if ($this->optional) {
+ $params['openid.sreg.optional'] = array();
+ foreach ($this->optional as $optional) {
+ if (!isset(self::$ax_to_sreg[$optional])) continue;
+ $params['openid.sreg.optional'][] = self::$ax_to_sreg[$optional];
+ }
+ $params['openid.sreg.optional'] = implode(',', $params['openid.sreg.optional']);
+ }
+ return $params;
+ }
+
+ protected function axParams()
+ {
+ $params = array();
+ if ($this->required || $this->optional) {
+ $params['openid.ns.ax'] = 'http://openid.net/srv/ax/1.0';
+ $params['openid.ax.mode'] = 'fetch_request';
+ $this->aliases = array();
+ $counts = array();
+ $required = array();
+ $optional = array();
+ foreach (array('required','optional') as $type) {
+ foreach ($this->$type as $alias => $field) {
+ if (is_int($alias)) $alias = strtr($field, '/', '_');
+ $this->aliases[$alias] = 'http://axschema.org/' . $field;
+ if (empty($counts[$alias])) $counts[$alias] = 0;
+ $counts[$alias] += 1;
+ ${$type}[] = $alias;
+ }
+ }
+ foreach ($this->aliases as $alias => $ns) {
+ $params['openid.ax.type.' . $alias] = $ns;
+ }
+ foreach ($counts as $alias => $count) {
+ if ($count == 1) continue;
+ $params['openid.ax.count.' . $alias] = $count;
+ }
+
+ # Don't send empty ax.required and ax.if_available.
+ # Google and possibly other providers refuse to support ax when one of these is empty.
+ if($required) {
+ $params['openid.ax.required'] = implode(',', $required);
+ }
+ if($optional) {
+ $params['openid.ax.if_available'] = implode(',', $optional);
+ }
+ }
+ return $params;
+ }
+
+ protected function authUrl_v1($immediate)
+ {
+ $returnUrl = $this->returnUrl;
+ # If we have an openid.delegate that is different from our claimed id,
+ # we need to somehow preserve the claimed id between requests.
+ # The simplest way is to just send it along with the return_to url.
+ if($this->identity != $this->claimed_id) {
+ $returnUrl .= (strpos($returnUrl, '?') ? '&' : '?') . 'openid.claimed_id=' . $this->claimed_id;
+ }
+
+ $params = array(
+ 'openid.return_to' => $returnUrl,
+ 'openid.mode' => $immediate ? 'checkid_immediate' : 'checkid_setup',
+ 'openid.identity' => $this->identity,
+ 'openid.trust_root' => $this->trustRoot,
+ ) + $this->sregParams();
+
+ return $this->build_url(parse_url($this->server)
+ , array('query' => http_build_query($params, '', '&')));
+ }
+
+ protected function authUrl_v2($immediate)
+ {
+ $params = array(
+ 'openid.ns' => 'http://specs.openid.net/auth/2.0',
+ 'openid.mode' => $immediate ? 'checkid_immediate' : 'checkid_setup',
+ 'openid.return_to' => $this->returnUrl,
+ 'openid.realm' => $this->trustRoot,
+ );
+
+ if ($this->ax) {
+ $params += $this->axParams();
+ }
+
+ if ($this->sreg) {
+ $params += $this->sregParams();
+ }
+
+ if (!$this->ax && !$this->sreg) {
+ # If OP doesn't advertise either SREG, nor AX, let's send them both
+ # in worst case we don't get anything in return.
+ $params += $this->axParams() + $this->sregParams();
+ }
+
+ if (!empty($this->oauth) && is_array($this->oauth)) {
+ $params['openid.ns.oauth'] = 'http://specs.openid.net/extensions/oauth/1.0';
+ $params['openid.oauth.consumer'] = str_replace(array('http://', 'https://'), '', $this->trustRoot);
+ $params['openid.oauth.scope'] = implode(' ', $this->oauth);
+ }
+
+ if ($this->identifier_select) {
+ $params['openid.identity'] = $params['openid.claimed_id']
+ = 'http://specs.openid.net/auth/2.0/identifier_select';
+ } else {
+ $params['openid.identity'] = $this->identity;
+ $params['openid.claimed_id'] = $this->claimed_id;
+ }
+
+ return $this->build_url(parse_url($this->server)
+ , array('query' => http_build_query($params, '', '&')));
+ }
+
+ /**
+ * Returns authentication url. Usually, you want to redirect your user to it.
+ * @return String The authentication url.
+ * @param String $select_identifier Whether to request OP to select identity for an user in OpenID 2. Does not affect OpenID 1.
+ * @throws ErrorException
+ */
+ function authUrl($immediate = false)
+ {
+ if ($this->setup_url && !$immediate) return $this->setup_url;
+ if (!$this->server) $this->discover($this->identity);
+
+ if ($this->version == 2) {
+ return $this->authUrl_v2($immediate);
+ }
+ return $this->authUrl_v1($immediate);
+ }
+
+ /**
+ * Performs OpenID verification with the OP.
+ * @return Bool Whether the verification was successful.
+ * @throws ErrorException
+ */
+ function validate()
+ {
+ # If the request was using immediate mode, a failure may be reported
+ # by presenting user_setup_url (for 1.1) or reporting
+ # mode 'setup_needed' (for 2.0). Also catching all modes other than
+ # id_res, in order to avoid throwing errors.
+ if(isset($this->data['openid_user_setup_url'])) {
+ $this->setup_url = $this->data['openid_user_setup_url'];
+ return false;
+ }
+ if($this->mode != 'id_res') {
+ return false;
+ }
+
+ $this->claimed_id = isset($this->data['openid_claimed_id'])?$this->data['openid_claimed_id']:$this->data['openid_identity'];
+ $params = array(
+ 'openid.assoc_handle' => $this->data['openid_assoc_handle'],
+ 'openid.signed' => $this->data['openid_signed'],
+ 'openid.sig' => $this->data['openid_sig'],
+ );
+
+ if (isset($this->data['openid_ns'])) {
+ # We're dealing with an OpenID 2.0 server, so let's set an ns
+ # Even though we should know location of the endpoint,
+ # we still need to verify it by discovery, so $server is not set here
+ $params['openid.ns'] = 'http://specs.openid.net/auth/2.0';
+ } elseif (isset($this->data['openid_claimed_id'])
+ && $this->data['openid_claimed_id'] != $this->data['openid_identity']
+ ) {
+ # If it's an OpenID 1 provider, and we've got claimed_id,
+ # we have to append it to the returnUrl, like authUrl_v1 does.
+ $this->returnUrl .= (strpos($this->returnUrl, '?') ? '&' : '?')
+ . 'openid.claimed_id=' . $this->claimed_id;
+ }
+
+ if ($this->data['openid_return_to'] != $this->returnUrl) {
+ # The return_to url must match the url of current request.
+ # I'm assuming that no one will set the returnUrl to something that doesn't make sense.
+ return false;
+ }
+
+ $server = $this->discover($this->claimed_id);
+
+ foreach (explode(',', $this->data['openid_signed']) as $item) {
+ # Checking whether magic_quotes_gpc is turned on, because
+ # the function may fail if it is. For example, when fetching
+ # AX namePerson, it might contain an apostrophe, which will be escaped.
+ # In such case, validation would fail, since we'd send different data than OP
+ # wants to verify. stripslashes() should solve that problem, but we can't
+ # use it when magic_quotes is off.
+ $value = $this->data['openid_' . str_replace('.','_',$item)];
+ $params['openid.' . $item] = function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc() ? stripslashes($value) : $value;
+
+ }
+
+ $params['openid.mode'] = 'check_authentication';
+
+ $response = $this->request($server, 'POST', $params);
+
+ return preg_match('/is_valid\s*:\s*true/i', $response);
+ }
+
+ protected function getAxAttributes()
+ {
+ $result = array();
+
+ if ($alias = $this->getNamespaceAlias('http://openid.net/srv/ax/1.0', 'ax')) {
+ $prefix = 'openid_' . $alias;
+ $length = strlen('http://axschema.org/');
+
+ foreach (explode(',', $this->data['openid_signed']) as $key) {
+ $keyMatch = $alias . '.type.';
+
+ if (strncmp($key, $keyMatch, strlen($keyMatch)) !== 0) {
+ continue;
+ }
+
+ $key = substr($key, strlen($keyMatch));
+ $idv = $prefix . '_value_' . $key;
+ $idc = $prefix . '_count_' . $key;
+ $key = substr($this->getItem($prefix . '_type_' . $key), $length);
+
+ if (!empty($key)) {
+ if (($count = intval($this->getItem($idc))) > 0) {
+ $value = array();
+
+ for ($i = 1; $i <= $count; $i++) {
+ $value[] = $this->getItem($idv . '_' . $i);
+ }
+
+ $value = ($count == 1) ? reset($value) : $value;
+ } else {
+ $value = $this->getItem($idv);
+ }
+
+ if (!is_null($value)) {
+ $result[$key] = $value;
+ }
+ }
+ }
+ } else {
+ // No alias for the AX schema has been found,
+ // so there is no AX data in the OP's response.
+ }
+
+ return $result;
+ }
+
+ protected function getSregAttributes()
+ {
+ $attributes = array();
+ $sreg_to_ax = array_flip(self::$ax_to_sreg);
+ foreach (explode(',', $this->data['openid_signed']) as $key) {
+ $keyMatch = 'sreg.';
+ if (strncmp($key, $keyMatch, strlen($keyMatch)) !== 0) {
+ continue;
+ }
+ $key = substr($key, strlen($keyMatch));
+ if (!isset($sreg_to_ax[$key])) {
+ # The field name isn't part of the SREG spec, so we ignore it.
+ continue;
+ }
+ $attributes[$sreg_to_ax[$key]] = $this->data['openid_sreg_' . $key];
+ }
+ return $attributes;
+ }
+
+ /**
+ * Gets AX/SREG attributes provided by OP. should be used only after successful validation.
+ * Note that it does not guarantee that any of the required/optional parameters will be present,
+ * or that there will be no other attributes besides those specified.
+ * In other words. OP may provide whatever information it wants to.
+ * * SREG names will be mapped to AX names.
+ * * @return Array Array of attributes with keys being the AX schema names, e.g. 'contact/email'
+ * @see http://www.axschema.org/types/
+ */
+ function getAttributes()
+ {
+ if (isset($this->data['openid_ns'])
+ && $this->data['openid_ns'] == 'http://specs.openid.net/auth/2.0'
+ ) { # OpenID 2.0
+ # We search for both AX and SREG attributes, with AX taking precedence.
+ return $this->getAxAttributes() + $this->getSregAttributes();
+ }
+ return $this->getSregAttributes();
+ }
+
+ /**
+ * Gets an OAuth request token if the OpenID+OAuth hybrid protocol has been used.
+ *
+ * In order to use the OpenID+OAuth hybrid protocol, you need to add at least one
+ * scope to the $openid->oauth array before you get the call to getAuthUrl(), e.g.:
+ * $openid->oauth[] = 'https://www.googleapis.com/auth/plus.me';
+ *
+ * Furthermore the registered consumer name must fit the OpenID realm.
+ * To register an OpenID consumer at Google use: https://www.google.com/accounts/ManageDomains
+ *
+ * @return string|bool OAuth request token on success, FALSE if no token was provided.
+ */
+ function getOAuthRequestToken()
+ {
+ $alias = $this->getNamespaceAlias('http://specs.openid.net/extensions/oauth/1.0');
+
+ return !empty($alias) ? $this->data['openid_' . $alias . '_request_token'] : false;
+ }
+
+ /**
+ * Gets the alias for the specified namespace, if it's present.
+ *
+ * @param string $namespace The namespace for which an alias is needed.
+ * @param string $hint Common alias of this namespace, used for optimization.
+ * @return string|null The namespace alias if found, otherwise - NULL.
+ */
+ private function getNamespaceAlias($namespace, $hint = null)
+ {
+ $result = null;
+
+ if (empty($hint) || $this->getItem('openid_ns_' . $hint) != $namespace) {
+ // The common alias is either undefined or points to
+ // some other extension - search for another alias..
+ $prefix = 'openid_ns_';
+ $length = strlen($prefix);
+
+ foreach ($this->data as $key => $val) {
+ if (strncmp($key, $prefix, $length) === 0 && $val === $namespace) {
+ $result = trim(substr($key, $length));
+ break;
+ }
+ }
+ } else {
+ $result = $hint;
+ }
+
+ return $result;
+ }
+
+ /**
+ * Gets an item from the $data array by the specified id.
+ *
+ * @param string $id The id of the desired item.
+ * @return string|null The item if found, otherwise - NULL.
+ */
+ private function getItem($id)
+ {
+ return isset($this->data[$id]) ? $this->data[$id] : null;
+ }
+}
\ No newline at end of file
diff --git a/ChatTags/web/steamauth/steamauth.php b/ChatTags/web/steamauth/steamauth.php
new file mode 100644
index 0000000..b820527
--- /dev/null
+++ b/ChatTags/web/steamauth/steamauth.php
@@ -0,0 +1,77 @@
+"; //logout button
+}
+
+function loginbutton($buttonstyle = "square")
+{
+ $button['rectangle'] = "01";
+ $button['square'] = "02";
+ $button = "";
+
+ echo $button;
+}
+
+if (isset($_GET['login'])){
+ require 'openid.php';
+ try {
+ require 'SteamConfig.php';
+ $openid = new LightOpenID($steamauth['domainname']);
+
+ if(!$openid->mode) {
+ $openid->identity = 'http://steamcommunity.com/openid';
+ header('Location: ' . $openid->authUrl());
+ } elseif ($openid->mode == 'cancel') {
+ echo 'User has canceled authentication!';
+ } else {
+ if($openid->validate()) {
+ $id = $openid->identity;
+ $ptn = "/^http:\/\/steamcommunity\.com\/openid\/id\/(7[0-9]{15,25}+)$/";
+ preg_match($ptn, $id, $matches);
+
+ $_SESSION['steamid'] = $matches[1];
+ if (!headers_sent()) {
+ header('Location: '.$steamauth['loginpage']);
+ exit;
+ } else {
+ ?>
+
+
+ getMessage();
+ }
+}
+
+if (isset($_GET['logout'])){
+ require 'SteamConfig.php';
+ session_unset();
+ session_destroy();
+ header('Location: '.$steamauth['logoutpage']);
+ exit;
+}
+
+if (isset($_GET['update']) || !empty($_SESSION['steam_uptodate']) && $_SESSION['steam_uptodate']+(24*60*60) < time()){
+ unset($_SESSION['steam_uptodate']);
+ require 'userInfo.php';
+ header('Location: '.$_SERVER['PHP_SELF']);
+ exit;
+}
+
+// Version 3.2
+
+?>
diff --git a/ChatTags/web/steamauth/userInfo.php b/ChatTags/web/steamauth/userInfo.php
new file mode 100644
index 0000000..5003a81
--- /dev/null
+++ b/ChatTags/web/steamauth/userInfo.php
@@ -0,0 +1,43 @@
+
+
diff --git a/Extend/gamedata/Extend.games.txt b/Extend/gamedata/Extend.games.txt
new file mode 100644
index 0000000..9c9ecf7
--- /dev/null
+++ b/Extend/gamedata/Extend.games.txt
@@ -0,0 +1,48 @@
+"Games"
+{
+ "cstrike"
+ {
+ "Addresses"
+ {
+ "GameOver"
+ {
+ "linux"
+ {
+ "signature" "g_fGameOver"
+ }
+ }
+ }
+
+ "Signatures"
+ {
+ "g_fGameOver"
+ {
+ "library" "server"
+ "linux" "@g_fGameOver"
+ }
+ }
+ }
+ "csgo"
+ {
+ "Addresses"
+ {
+ "GameOver"
+ {
+ "linux"
+ {
+ "signature" "g_fGameOver"
+ "read" "16"
+ }
+ }
+ }
+
+ "Signatures"
+ {
+ "g_fGameOver"
+ {
+ "library" "server"
+ "linux" "\x55\x89\xE5\x57\x56\x53\x31\xDB\x81\xEC\x2A\x2A\x2A\x2A\x80\x3D\x2A\x2A\x2A\x2A\x2A"
+ }
+ }
+ }
+}
diff --git a/Extend/scripting/Extend.sp b/Extend/scripting/Extend.sp
new file mode 100644
index 0000000..6ea08cf
--- /dev/null
+++ b/Extend/scripting/Extend.sp
@@ -0,0 +1,389 @@
+#pragma semicolon 1
+#pragma newdecls required
+
+#include
+#include
+
+#define VOTE_NO "###no###"
+#define VOTE_YES "###yes###"
+
+ConVar g_cvarExtendVoteTime = null;
+ConVar g_cvarExtendVotePercent = null;
+ConVar g_cvarMpMaxRounds = null;
+ConVar g_cvarMpFragLimit = null;
+ConVar g_cvarMpWinLimit = null;
+ConVar g_cvarMpTimeLimit = null;
+
+bool g_bGameOver = false;
+Address g_pGameOver;
+
+public Plugin myinfo =
+{
+ name = "Map extend tools",
+ author = "Obus + BotoX",
+ description = "Adds map extension commands.",
+ version = "1.0",
+ url = ""
+};
+
+public void OnPluginStart()
+{
+ LoadTranslations("common.phrases");
+ LoadTranslations("basevotes.phrases");
+
+ g_cvarMpMaxRounds = FindConVar("mp_maxrounds");
+ g_cvarMpFragLimit = FindConVar("mp_fraglimit");
+ g_cvarMpWinLimit = FindConVar("mp_winlimit");
+ g_cvarMpTimeLimit = FindConVar("mp_timelimit");
+
+ g_cvarExtendVoteTime = CreateConVar("sm_extendvote_time", "15", "Time that will be added to mp_timelimit shall the extend vote succeed", FCVAR_NONE, true, 1.0);
+ g_cvarExtendVotePercent = CreateConVar("sm_extendvote_percent", "0.6", "Percentage of \"yes\" votes required to consider the vote successful", FCVAR_NONE, true, 0.05, true, 1.0);
+
+ AutoExecConfig(true, "plugin.Extend");
+
+ if (g_cvarMpMaxRounds != null)
+ RegAdminCmd("sm_extend_rounds", Command_Extend_Rounds, ADMFLAG_GENERIC, "Add more rounds to mp_maxrounds");
+ else
+ LogMessage("Failed to find \"mp_maxrounds\" console variable, related commands will be disabled.");
+
+ if (g_cvarMpFragLimit != null)
+ RegAdminCmd("sm_extend_frags", Command_Extend_Frags, ADMFLAG_GENERIC, "Add more frags to mp_fraglimit");
+ else
+ LogMessage("Failed to find \"mp_fraglimit\" console variable, related commands will be disabled.");
+
+ if (g_cvarMpWinLimit != null)
+ RegAdminCmd("sm_extend_wins", Command_Extend_Wins, ADMFLAG_GENERIC, "Add more wins to mp_winlimit");
+ else
+ LogMessage("Failed to find \"mp_winlimit\" console variable, related commands will be disabled.");
+
+ if (g_cvarMpTimeLimit != null)
+ {
+ RegAdminCmd("sm_extend", Command_Extend, ADMFLAG_GENERIC, "Add more time to mp_timelimit");
+ RegAdminCmd("sm_extend_time", Command_Extend, ADMFLAG_GENERIC, "Add more time to mp_timelimit");
+ RegAdminCmd("sm_extendvote", Command_ExtendVote, ADMFLAG_GENERIC, "sm_extendvote [time] - Start an extendvote");
+ RegAdminCmd("sm_voteextend", Command_ExtendVote, ADMFLAG_GENERIC, "sm_voteextend [time] - Start an extendvote");
+ RegAdminCmd("sm_extend_vote", Command_ExtendVote, ADMFLAG_GENERIC, "sm_extend_vote [time] - Start an extendvote");
+ }
+ else
+ {
+ LogMessage("Failed to find \"mp_timelimit\" console variable, related commands will be disabled.");
+ }
+
+ Handle hGameConf = LoadGameConfigFile("Extend.games");
+ if(hGameConf == INVALID_HANDLE)
+ {
+ g_bGameOver = false;
+ LogError("Couldn't load Extend.games game config! GameOver cancel disabled.");
+ return;
+ }
+
+ if(!(g_pGameOver = GameConfGetAddress(hGameConf, "GameOver")))
+ {
+ g_bGameOver = false;
+ delete hGameConf;
+ LogError("Couldn't get GameOver address from game config! GameOver cancel disabled.");
+ return;
+ }
+
+ g_bGameOver = true;
+ delete hGameConf;
+}
+
+public Action Command_Extend_Rounds(int client, int argc)
+{
+ if (argc < 1)
+ {
+ ReplyToCommand(client, "[SM] Usage: sm_extend_rounds ");
+ return Plugin_Handled;
+ }
+
+ char sArgs[16];
+
+ GetCmdArg(1, sArgs, sizeof(sArgs));
+
+ if (sArgs[0] == '-')
+ {
+ int iRoundsToDeduct;
+
+ if (!StringToIntEx(sArgs[1], iRoundsToDeduct))
+ {
+ ReplyToCommand(client, "[SM] Invalid value");
+ return Plugin_Handled;
+ }
+
+ g_cvarMpMaxRounds.IntValue -= iRoundsToDeduct;
+
+ LogAction(client, -1, "\"%L\" deducted \"%d\" rounds from \"mp_maxrounds\"", client, iRoundsToDeduct);
+
+ return Plugin_Handled;
+ }
+
+ int iRoundsToAdd;
+
+ if (!StringToIntEx(sArgs, iRoundsToAdd))
+ {
+ ReplyToCommand(client, "[SM] Invalid value");
+ return Plugin_Handled;
+ }
+
+ g_cvarMpMaxRounds.IntValue += iRoundsToAdd;
+ CancelGameOver();
+
+ LogAction(client, -1, "\"%L\" added \"%d\" rounds to \"mp_maxrounds\"", client, iRoundsToAdd);
+
+ return Plugin_Handled;
+}
+
+public Action Command_Extend_Frags(int client, int argc)
+{
+ if (argc < 1)
+ {
+ ReplyToCommand(client, "[SM] Usage: sm_extend_frags ");
+ return Plugin_Handled;
+ }
+
+ char sArgs[16];
+
+ GetCmdArg(1, sArgs, sizeof(sArgs));
+
+ if (sArgs[0] == '-')
+ {
+ int iFragsToDeduct;
+
+ if (!StringToIntEx(sArgs[1], iFragsToDeduct))
+ {
+ ReplyToCommand(client, "[SM] Invalid value");
+ return Plugin_Handled;
+ }
+
+ g_cvarMpFragLimit.IntValue -= iFragsToDeduct;
+
+ LogAction(client, -1, "\"%L\" deducted \"%d\" frags from \"mp_fraglimit\"", client, iFragsToDeduct);
+
+ return Plugin_Handled;
+ }
+
+ int iFragsToAdd;
+
+ if (!StringToIntEx(sArgs, iFragsToAdd))
+ {
+ ReplyToCommand(client, "[SM] Invalid value");
+ return Plugin_Handled;
+ }
+
+ g_cvarMpFragLimit.IntValue += iFragsToAdd;
+ CancelGameOver();
+
+ LogAction(client, -1, "\"%L\" added \"%d\" frags to \"mp_fraglimit\"", client, iFragsToAdd);
+
+ return Plugin_Handled;
+}
+
+public Action Command_Extend_Wins(int client, int argc)
+{
+ if (argc < 1)
+ {
+ ReplyToCommand(client, "[SM] Usage: sm_extend_wins ");
+ return Plugin_Handled;
+ }
+
+ char sArgs[16];
+
+ GetCmdArg(1, sArgs, sizeof(sArgs));
+
+ if (sArgs[0] == '-')
+ {
+ int iWinsToDeduct;
+
+ if (!StringToIntEx(sArgs[1], iWinsToDeduct))
+ {
+ ReplyToCommand(client, "[SM] Invalid value");
+ return Plugin_Handled;
+ }
+
+ g_cvarMpWinLimit.IntValue -= iWinsToDeduct;
+
+ LogAction(client, -1, "\"%L\" deducted \"%d\" wins from \"mp_winlimit\"", client, iWinsToDeduct);
+
+ return Plugin_Handled;
+ }
+
+ int iWinsToAdd;
+
+ if (!StringToIntEx(sArgs, iWinsToAdd))
+ {
+ ReplyToCommand(client, "[SM] Invalid value");
+ return Plugin_Handled;
+ }
+
+ g_cvarMpWinLimit.IntValue += iWinsToAdd;
+ CancelGameOver();
+
+ LogAction(client, -1, "\"%L\" added \"%d\" wins to \"mp_winlimit\"", client, iWinsToAdd);
+
+ return Plugin_Handled;
+}
+
+public Action Command_Extend(int client, int argc)
+{
+ if (argc < 1)
+ {
+ ReplyToCommand(client, "[SM] Usage: sm_extend