#pragma semicolon 1 #pragma newdecls required #include #include #define PLUGIN_NAME "ScoreboardUnlocker" #define PLUGIN_AUTHOR "Irineu" #define PLUGIN_VERSION "1.0" #define DPT_DataTable 6 public Plugin myinfo = { name = PLUGIN_NAME, author = PLUGIN_AUTHOR, description = "Increases the frags limit in the scoreboard", version = PLUGIN_VERSION, url = "" }; bool g_bLate = false; Address serverGameDLL = 0; Address g_pSendTableCRC = 0; int g_iServerClass_m_pNext = -1; int g_iServerClass_m_pTable = -1; int g_iSendTable_m_pNetTableName = -1; int g_iSendTable_m_nProps = -1; int g_iSendTable_m_pProps = -1; int g_iSendProp_m_Type = -1; int g_iSendProp_m_pDataTable = -1; int g_iSendProp_m_pVarName = -1; int g_iSendProp_m_nBits = -1; int g_iSendProp_sizeof = -1; Handle g_hGetAllServerClasses = INVALID_HANDLE; public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max) { g_bLate = late; return APLRes_Success; } public void OnPluginStart() { GameData gd = new GameData("ScoreboardUnlocker"); if (!gd) SetFailState("Missing gamedata file"); StartPrepSDKCall(SDKCall_Static); if (!PrepSDKCall_SetFromConf(gd, SDKConf_Signature, "CreateInterface_Server")) SetFailState("Failed to get CreateInterface_Server"); PrepSDKCall_AddParameter(SDKType_String, SDKPass_Pointer); PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Pointer, VDECODE_FLAG_ALLOWNULL); PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain); Handle call = EndPrepSDKCall(); StartPrepSDKCall(SDKCall_Raw); if (!PrepSDKCall_SetFromConf(gd, SDKConf_Virtual, "IServerGameDLL::GetAllServerClasses")) SetFailState("Failed to get IServerGameDLL::GetAllServerClasses"); PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain); g_hGetAllServerClasses = EndPrepSDKCall(); char GameDLLInterfaceName[64]; if (!gd.GetKeyValue("INTERFACEVERSION_SERVERGAMEDLL", GameDLLInterfaceName, sizeof(GameDLLInterfaceName))) SetFailState("Failed to get gamedll interface name"); serverGameDLL = SDKCall(call, GameDLLInterfaceName, 0); if (serverGameDLL == Address_Null) SetFailState("Failed to get gamedll interface"); g_pSendTableCRC = gd.GetMemSig("g_SendTableCRC"); if (g_pSendTableCRC == Address_Null) SetFailState("Failed to get g_SendTableCRC"); g_iServerClass_m_pNext = GetRequiredOffset(gd, "ServerClass::m_pNext"); g_iServerClass_m_pTable = GetRequiredOffset(gd, "ServerClass::m_pTable"); g_iSendTable_m_pNetTableName = GetRequiredOffset(gd, "SendTable::m_pNetTableName"); g_iSendTable_m_nProps = GetRequiredOffset(gd, "SendTable::m_nProps"); g_iSendTable_m_pProps = GetRequiredOffset(gd, "SendTable::m_pProps"); g_iSendProp_m_Type = GetRequiredOffset(gd, "SendProp::m_Type"); g_iSendProp_m_pDataTable = GetRequiredOffset(gd, "SendProp::m_pDataTable"); g_iSendProp_m_pVarName = GetRequiredOffset(gd, "SendProp::m_pVarName"); g_iSendProp_m_nBits = GetRequiredOffset(gd, "SendProp::m_nBits"); g_iSendProp_sizeof = GetRequiredOffset(gd, "SendProp::sizeof"); ConVar sv_sendtables = FindConVar("sv_sendtables"); if (!sv_sendtables) SetFailState("Failed to find sv_sendtables"); sv_sendtables.BoolValue = true; if (!g_bLate) FulfillMyPurpose(); CloseHandle(call); CloseHandle(gd); } public void OnMapInit(const char[] mapName) { if (g_bLate) { FulfillMyPurpose(); g_bLate = false; } } void FulfillMyPurpose() { Address pTable = FindSendTable("DT_PlayerResource"); if (pTable == Address_Null) SetFailState("Failed to find DT_PlayerResource"); for (int i = 1; i <= MaxClients; i++) { char name[64]; Format(name, sizeof(name), "m_iScore.%03d", i); Address pProp = FindSendProp(pTable, name); if (pProp != Address_Null) StoreToAddress(pProp + view_as
(g_iSendProp_m_nBits), 32, NumberType_Int32, false); else SetFailState("Failed to find m_iScore.%03d", i); } int crc = LoadFromAddress(g_pSendTableCRC, NumberType_Int32); StoreToAddress(g_pSendTableCRC, crc + 1, NumberType_Int32, false); } int GetRequiredOffset(GameData gd, const char[] name) { int ret = gd.GetOffset(name); if (ret == -1) SetFailState("Missing offset %s from gamedata file", name); return ret; } void LoadStringFromAddress(char[] buf, int bufSize, Address address) { for (int i = 0; i < bufSize; i++) { char c = LoadFromAddress(address + view_as
(i), NumberType_Int8); if (c == 0) break; buf[i] = c; } buf[bufSize - 1] = 0; } enum struct bazinga { Address pAddr; } Address FindSendTable(const char[] name) { ArrayList sendTables = new ArrayList(); for (Address pServerClass = SDKCall(g_hGetAllServerClasses, serverGameDLL); pServerClass != Address_Null; pServerClass = LoadFromAddress(pServerClass + view_as
(g_iServerClass_m_pNext), NumberType_Int32)) { Address pTable = LoadFromAddress(pServerClass + view_as
(g_iServerClass_m_pTable), NumberType_Int32); if (pTable != Address_Null) { bazinga thing; thing.pAddr = pTable; sendTables.PushArray(thing, sizeof(bazinga)); } } while (sendTables.Length > 0) { bazinga thing; sendTables.GetArray(0, thing, sizeof(bazinga)); Address pTable = thing.pAddr; sendTables.Erase(0); char tableName[64]; Address pName = LoadFromAddress(pTable + view_as
(g_iSendTable_m_pNetTableName), NumberType_Int32); LoadStringFromAddress(tableName, sizeof(tableName), pName); if (strcmp(tableName, name) == 0) { delete sendTables; return pTable; } else { int nProps = LoadFromAddress(pTable + view_as
(g_iSendTable_m_nProps), NumberType_Int32); for (int i = 0; i < nProps; i++) { Address pProp = LoadFromAddress(pTable + view_as
(g_iSendTable_m_pProps), NumberType_Int32) + (i * g_iSendProp_sizeof); Address pPropTable = LoadFromAddress(pProp + view_as
(g_iSendProp_m_pDataTable), NumberType_Int32); int propType = LoadFromAddress(pProp + view_as
(g_iSendProp_m_Type), NumberType_Int32); if (propType == DPT_DataTable && pPropTable != Address_Null) { thing.pAddr = pPropTable; sendTables.PushArray(thing, sizeof(bazinga)); } } } } delete sendTables; return Address_Null; } Address FindInSendTable(Address pTable, const char[] name, int requiredType = -1) { int nProps = LoadFromAddress(pTable + view_as
(g_iSendTable_m_nProps), NumberType_Int32); for (int i = 0; i < nProps; i++) { Address pProp = LoadFromAddress(pTable + view_as
(g_iSendTable_m_pProps), NumberType_Int32) + (i * g_iSendProp_sizeof); char propName[64]; Address pName = LoadFromAddress(pProp + view_as
(g_iSendProp_m_pVarName), NumberType_Int32); LoadStringFromAddress(propName, sizeof(propName), pName); int propType = LoadFromAddress(pProp + view_as
(g_iSendProp_m_Type), NumberType_Int32); if (strcmp(propName, name) == 0 && (propType == requiredType || requiredType == -1)) return pProp; } return Address_Null; } Address FindSendProp(Address pTable, const char[] name, int requiredType = -1) { char propNames[16][64]; int nameCount = ExplodeString(name, ".", propNames, 16, 64); Address pProp = Address_Null; // Please don't ever reuse parameters for local variables in this stupid language again, future me. Address pTable2 = pTable; for (int i = 0; i < nameCount; ) { if (pProp != Address_Null) { Address pPropTable = LoadFromAddress(pProp + view_as
(g_iSendProp_m_pDataTable), NumberType_Int32); if (pPropTable != Address_Null) pTable2 = pPropTable; } int type = i == (nameCount - 1) ? requiredType : DPT_DataTable; pProp = FindInSendTable(pTable2, propNames[i], type); if (pProp == Address_Null) { if (i == 0) { pProp = FindInSendTable(pTable2, "baseclass", DPT_DataTable); if (pProp == Address_Null) break; } else { break; } } else { i++; } } return pProp; }