New plugin ScoreboardUnlocker: Increases the frags limit in the scoreboard
This commit is contained in:
@@ -0,0 +1,97 @@
|
|||||||
|
"Games"
|
||||||
|
{
|
||||||
|
"cstrike"
|
||||||
|
{
|
||||||
|
"Keys"
|
||||||
|
{
|
||||||
|
"INTERFACEVERSION_SERVERGAMEDLL" "ServerGameDLL012"
|
||||||
|
}
|
||||||
|
|
||||||
|
"Signatures"
|
||||||
|
{
|
||||||
|
"CreateInterface_Server"
|
||||||
|
{
|
||||||
|
"library" "server"
|
||||||
|
"linux" "@CreateInterface"
|
||||||
|
"windows" "@CreateInterface"
|
||||||
|
}
|
||||||
|
|
||||||
|
"g_SendTableCRC"
|
||||||
|
{
|
||||||
|
"library" "engine"
|
||||||
|
"linux" "@g_SendTableCRC"
|
||||||
|
// IDK
|
||||||
|
//"windows" ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
"Offsets"
|
||||||
|
{
|
||||||
|
"IServerGameDLL::GetAllServerClasses"
|
||||||
|
{
|
||||||
|
"linux" "11"
|
||||||
|
"windows" "11"
|
||||||
|
}
|
||||||
|
|
||||||
|
"ServerClass::m_pNext"
|
||||||
|
{
|
||||||
|
"linux" "8"
|
||||||
|
"windows" "8"
|
||||||
|
}
|
||||||
|
|
||||||
|
"ServerClass::m_pTable"
|
||||||
|
{
|
||||||
|
"linux" "4"
|
||||||
|
"windows" "4"
|
||||||
|
}
|
||||||
|
|
||||||
|
"SendTable::m_pNetTableName"
|
||||||
|
{
|
||||||
|
"linux" "8"
|
||||||
|
"windows" "8"
|
||||||
|
}
|
||||||
|
|
||||||
|
"SendTable::m_nProps"
|
||||||
|
{
|
||||||
|
"linux" "4"
|
||||||
|
"windows" "4"
|
||||||
|
}
|
||||||
|
|
||||||
|
"SendTable::m_pProps"
|
||||||
|
{
|
||||||
|
"linux" "0"
|
||||||
|
"windows" "0"
|
||||||
|
}
|
||||||
|
|
||||||
|
"SendProp::m_Type"
|
||||||
|
{
|
||||||
|
"linux" "8"
|
||||||
|
"windows" "8"
|
||||||
|
}
|
||||||
|
|
||||||
|
"SendProp::m_pDataTable"
|
||||||
|
{
|
||||||
|
"linux" "68"
|
||||||
|
"windows" "68"
|
||||||
|
}
|
||||||
|
|
||||||
|
"SendProp::m_pVarName"
|
||||||
|
{
|
||||||
|
"linux" "48"
|
||||||
|
"windows" "48"
|
||||||
|
}
|
||||||
|
|
||||||
|
"SendProp::m_nBits"
|
||||||
|
{
|
||||||
|
"linux" "12"
|
||||||
|
"windows" "12"
|
||||||
|
}
|
||||||
|
|
||||||
|
"SendProp::sizeof"
|
||||||
|
{
|
||||||
|
"linux" "80"
|
||||||
|
"windows" "80"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,267 @@
|
|||||||
|
#pragma semicolon 1
|
||||||
|
#pragma newdecls required
|
||||||
|
|
||||||
|
#include <sourcemod>
|
||||||
|
#include <sdktools>
|
||||||
|
|
||||||
|
#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<Address>(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<Address>(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<Address>(g_iServerClass_m_pNext), NumberType_Int32))
|
||||||
|
{
|
||||||
|
Address pTable = LoadFromAddress(pServerClass + view_as<Address>(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<Address>(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<Address>(g_iSendTable_m_nProps), NumberType_Int32);
|
||||||
|
for (int i = 0; i < nProps; i++)
|
||||||
|
{
|
||||||
|
Address pProp = LoadFromAddress(pTable + view_as<Address>(g_iSendTable_m_pProps), NumberType_Int32) + (i * g_iSendProp_sizeof);
|
||||||
|
Address pPropTable = LoadFromAddress(pProp + view_as<Address>(g_iSendProp_m_pDataTable), NumberType_Int32);
|
||||||
|
int propType = LoadFromAddress(pProp + view_as<Address>(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<Address>(g_iSendTable_m_nProps), NumberType_Int32);
|
||||||
|
for (int i = 0; i < nProps; i++)
|
||||||
|
{
|
||||||
|
Address pProp = LoadFromAddress(pTable + view_as<Address>(g_iSendTable_m_pProps), NumberType_Int32) + (i * g_iSendProp_sizeof);
|
||||||
|
char propName[64];
|
||||||
|
Address pName = LoadFromAddress(pProp + view_as<Address>(g_iSendProp_m_pVarName), NumberType_Int32);
|
||||||
|
LoadStringFromAddress(propName, sizeof(propName), pName);
|
||||||
|
int propType = LoadFromAddress(pProp + view_as<Address>(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<Address>(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;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user