diff --git a/addons/sourcemod/scripting/l4d2_static_shotgun_spread.sp b/addons/sourcemod/scripting/l4d2_static_shotgun_spread.sp index 548395893..6ef644f8a 100644 --- a/addons/sourcemod/scripting/l4d2_static_shotgun_spread.sp +++ b/addons/sourcemod/scripting/l4d2_static_shotgun_spread.sp @@ -4,10 +4,9 @@ #include #include -#define GAMEDATA_FILE "code_patcher" -#define KEY_SGSPREAD "sgspread" -#define BULLET_MAX_SIZE 4 -#define DEBUG 0 +#define BULLET_MAX_SIZE 3 +#define GAMEDATA_FILE "code_patcher" +#define KEY_SGSPREAD "sgspread" // Original code & Notes: https://github.com/Jahze/l4d2_plugins/tree/master/spread_patch // Static Shotgun Spread leverages code_patcher (code_patcher.txt gamedata) @@ -22,153 +21,177 @@ enum eWindows = 0, eLinux, /* eMac, joke:) */ + ePlatform_Size -} +}; int - g_ePlatform; + g_ePlatform = eLinux; static const int - g_BulletOffsets[ePlatform_Size][BULLET_MAX_SIZE] = { - { 0xf, 0x21, 0x30, 0x3f }, // Windows - { 0x11, 0x22, 0x2f, 0x43 } // Linux + g_iBulletOffsets[ePlatform_Size][BULLET_MAX_SIZE] = { + { 0xf, 0x21, 0x30 }, // Windows + { 0x11, 0x22, 0x2f } // Linux }, - g_FactorOffset[ePlatform_Size] = { + g_iDegreeOffsets[ePlatform_Size] = { + 0x3f, // Windows + 0x43 // Linux + }, + g_iFactorOffset[ePlatform_Size] = { 0x36, // Windows 0x34 // Linux }, - g_CenterPelletOffset[ePlatform_Size] = { + g_iCenterPelletOffset[ePlatform_Size] = { -0x36, // Windows -0x1c // Linux }; +Address + g_pBullets[BULLET_MAX_SIZE] = {Address_Null, ...}, + g_pDegree = Address_Null, + g_pFactor = Address_Null, + g_pCenterPellet = Address_Null; + MemoryPatch - g_hPatch_sgspread; + g_hPatchSgSpread = null; ConVar - hRing1BulletsCvar, - hRing1FactorCvar, - hCenterPelletCvar; + g_hCvarRing1Bullets = null, + g_hCvarRing1Factor = null, + g_hCvarCenterPellet = null; -public Plugin myinfo = +public Plugin myinfo = { name = "L4D2 Static Shotgun Spread", author = "Jahze, Visor, A1m`, Rena", - version = "1.6.1", + version = "1.6.5", description = "Changes the values in the sgspread patch", url = "https://github.com/SirPlease/L4D2-Competitive-Rework" }; public void OnPluginStart() { - Handle conf = LoadGameConfigFile(GAMEDATA_FILE); - if (conf == null) { + InitGameData(); + + g_hCvarRing1Bullets = CreateConVar("sgspread_ring1_bullets", "3", "Number of bullets for the first ring, the remaining bullets will be in the second ring."); + g_hCvarRing1Factor = CreateConVar("sgspread_ring1_factor", "2", "Determines how far or closer the bullets will be from the center for the first ring."); + g_hCvarCenterPellet = CreateConVar("sgspread_center_pellet", "1", "Center pellet: 0 - off, 1 - on.", _, true, 0.0, true, 1.0); + + InitPlugin(); +} + +void InitGameData() +{ + Handle hConf = LoadGameConfigFile(GAMEDATA_FILE); + if (hConf == null) { SetFailState("Missing gamedata \"" ... GAMEDATA_FILE ... "\""); } - - g_hPatch_sgspread = MemoryPatch.CreateFromConf(conf, KEY_SGSPREAD); - if (g_hPatch_sgspread == null || !g_hPatch_sgspread.Validate()) { + + g_ePlatform = GameConfGetOffset(hConf, "OS"); + if (g_ePlatform == -1) { + SetFailState("Failed to retrieve offset \"OS\""); + } + + g_hPatchSgSpread = MemoryPatch.CreateFromConf(hConf, KEY_SGSPREAD); + if (g_hPatchSgSpread == null || !g_hPatchSgSpread.Validate()) { SetFailState("Failed to validate MemoryPatch \"" ... KEY_SGSPREAD ... "\""); } - - if (!g_hPatch_sgspread.Enable()) { - SetFailState("Failed to enable MemoryPatch \"" ... KEY_SGSPREAD ... "\""); + + Address pFinalAddr = g_hPatchSgSpread.Address + view_as
(g_iCenterPelletOffset[g_ePlatform]); + int iCurrentValue = LoadFromAddress(pFinalAddr, NumberType_Int8); + if (iCurrentValue != 1) { + SetFailState("Center pellet offset is uncorrect! CheckByte: %x", iCurrentValue); } - - g_ePlatform = GameConfGetOffset(conf, "OS"); - if (g_ePlatform == -1) { - SetFailState("Failed to retrieve offset \"OS\""); + + if (!g_hPatchSgSpread.Enable()) { + SetFailState("Failed to enable MemoryPatch \"" ... KEY_SGSPREAD ... "\""); } - - delete conf; - - hRing1BulletsCvar = CreateConVar("sgspread_ring1_bullets", "3", "Number of bullets for the first ring, the remaining bullets will be in the second ring."); - hRing1FactorCvar = CreateConVar("sgspread_ring1_factor", "2", "Determines how far or closer the bullets will be from the center for the first ring."); - hCenterPelletCvar = CreateConVar("sgspread_center_pellet", "1", "Center pellet: 0 - off, 1 - on.", _, true, 0.0, true, 1.0); - - hRing1BulletsCvar.AddChangeHook(OnRing1BulletsChange); - hRing1FactorCvar.AddChangeHook(OnRing1FactorChange); - hCenterPelletCvar.AddChangeHook(OnCenterPelletChange); - - HotPatchBullets(hRing1BulletsCvar.IntValue); - HotPatchFactor(hRing1FactorCvar.IntValue); - HotPatchCenterPellet(hCenterPelletCvar.BoolValue); + + delete hConf; } -static void HotPatchCenterPellet(bool newValue) +void InitPlugin() { - Address pAddr = g_hPatch_sgspread.Address; - - int currentValue = LoadFromAddress(pAddr + view_as
(g_CenterPelletOffset[g_ePlatform]), NumberType_Int8); - - int bullets = hRing1BulletsCvar.IntValue; - - #if DEBUG - static bool IsFirstPatch = false; - if (!IsFirstPatch) { - PrintToServer("Center pellet offset is %s! CheckByte: %x", (currentValue == 0x01) ? "correct ": "uncorrect", currentValue); - PrintToChatAll("Center pellet offset is %s! CheckByte: %x", (currentValue == 0x01) ? "correct ": "uncorrect", currentValue); - IsFirstPatch = true; + for (int i = 0; i < BULLET_MAX_SIZE; i++) { + g_pBullets[i] = g_hPatchSgSpread.Address + view_as
(g_iBulletOffsets[g_ePlatform][i]); } - #endif - - if (!!currentValue == newValue) { - return; - } - - StoreToAddress(pAddr + view_as
(g_CenterPelletOffset[g_ePlatform]), view_as(newValue), NumberType_Int8); - - StoreToAddress(pAddr + view_as
(g_BulletOffsets[g_ePlatform][0]), bullets + (1 - view_as(!newValue)), NumberType_Int8); - StoreToAddress(pAddr + view_as
(g_BulletOffsets[g_ePlatform][1]), bullets + (1 - view_as(!newValue)), NumberType_Int8); - StoreToAddress(pAddr + view_as
(g_BulletOffsets[g_ePlatform][2]), bullets + (2 - view_as(!newValue)), NumberType_Int8); + + g_pDegree = g_hPatchSgSpread.Address + view_as
(g_iDegreeOffsets[g_ePlatform]); + g_pFactor = g_hPatchSgSpread.Address + view_as
(g_iFactorOffset[g_ePlatform]); + g_pCenterPellet = g_hPatchSgSpread.Address + view_as
(g_iCenterPelletOffset[g_ePlatform]); + + HotPatchBullets(g_hCvarRing1Bullets.IntValue); + HotPatchFactor(g_hCvarRing1Factor.IntValue); + HotPatchCenterPellet(g_hCvarCenterPellet.BoolValue); + + g_hCvarRing1Bullets.AddChangeHook(OnRing1BulletsChange); + g_hCvarRing1Factor.AddChangeHook(OnRing1FactorChange); + g_hCvarCenterPellet.AddChangeHook(OnCenterPelletChange); } -static void HotPatchBullets(int nBullets) +public void OnPluginEnd() { - bool centerpellet = !hCenterPelletCvar.BoolValue; - float degree = 0.0; - - if (g_ePlatform == eWindows) { - degree = 360.0 / float(nBullets); - } else { - degree = 360.0 / (2.0 * float(nBullets)); + if (g_pCenterPellet != Address_Null) { + int iCurrentValue = LoadFromAddress(g_pCenterPellet, NumberType_Int8); + + if (iCurrentValue != 1) { + StoreToAddress(g_pCenterPellet, 1, NumberType_Int8); + } } - - Address pAddr = g_hPatch_sgspread.Address; - - StoreToAddress(pAddr + view_as
(g_BulletOffsets[g_ePlatform][0]), nBullets + (1 - view_as(centerpellet)), NumberType_Int8); - StoreToAddress(pAddr + view_as
(g_BulletOffsets[g_ePlatform][1]), nBullets + (1 - view_as(centerpellet)), NumberType_Int8); - StoreToAddress(pAddr + view_as
(g_BulletOffsets[g_ePlatform][2]), nBullets + (2 - view_as(centerpellet)), NumberType_Int8); - - StoreToAddress(pAddr + view_as
(g_BulletOffsets[g_ePlatform][3]), view_as(degree), NumberType_Int32); } -static void HotPatchFactor(int factor) +void OnRing1BulletsChange(ConVar hConVar, const char[] sOldValue, const char[] sNewValue) { - Address pAddr = g_hPatch_sgspread.Address; + HotPatchBullets(hConVar.IntValue); +} - if (g_ePlatform == eWindows) { - StoreToAddress(pAddr + view_as
(g_FactorOffset[eWindows]), view_as(float(factor)), NumberType_Int32); //On windows need the float type !!! - return; +void OnRing1FactorChange(ConVar hConVar, const char[] sOldValue, const char[] sNewValue) +{ + HotPatchFactor(hConVar.IntValue); +} + +void OnCenterPelletChange(ConVar hConVar, const char[] sOldValue, const char[] sNewValue) +{ + HotPatchCenterPellet(hConVar.BoolValue); +} + +void HotPatchBullets(int iBullets) +{ + PatchBullets(iBullets, g_hCvarCenterPellet.BoolValue); + + float fBullets = float(iBullets); + if (g_ePlatform == eLinux) { + fBullets *= 2.0; } - - StoreToAddress(pAddr + view_as
(g_FactorOffset[eLinux]), factor, NumberType_Int32); + + StoreToAddress(g_pDegree, view_as(360.0 / fBullets), NumberType_Int32); } -void OnRing1BulletsChange(ConVar hCvar, const char[] oldVal, const char[] newVal) +void HotPatchFactor(int iFactor) { - int nBullets = StringToInt(newVal); - HotPatchBullets(nBullets); + // Asm patch on windows need the float type ! + int iSetFactor = (g_ePlatform == eWindows) ? view_as(float(iFactor)) : iFactor; + StoreToAddress(g_pFactor, iSetFactor, NumberType_Int32); } -void OnRing1FactorChange(ConVar hCvar, const char[] oldVal, const char[] newVal) +void HotPatchCenterPellet(bool bNewValue) { - int factor = StringToInt(newVal); - HotPatchFactor(factor); + bool iCurrentValue = LoadFromAddress(g_pCenterPellet, NumberType_Int8); + if (iCurrentValue == bNewValue) { + return; + } + + StoreToAddress(g_pCenterPellet, view_as(bNewValue), NumberType_Int8); + + PatchBullets(g_hCvarRing1Bullets.IntValue, bNewValue); } -void OnCenterPelletChange(ConVar hCvar, const char[] oldVal, const char[] newVal) +void PatchBullets(int iBullets, bool bCenterPellet) { - bool value = !!StringToInt(newVal); - HotPatchCenterPellet(value); + int iOffset1 = iBullets + (bCenterPellet ? 1 : 0); + int iOffset2 = iBullets + (bCenterPellet ? 2 : 1); + + StoreToAddress(g_pBullets[0], iOffset1, NumberType_Int8); + StoreToAddress(g_pBullets[1], iOffset1, NumberType_Int8); + StoreToAddress(g_pBullets[2], iOffset2, NumberType_Int8); }