From 5610aeb9175ed3167ed4de70536e5fd122ba9cd2 Mon Sep 17 00:00:00 2001 From: Drifter Date: Sun, 27 May 2012 19:07:44 -0400 Subject: [PATCH] Added natives for changing team score and mvp stars on CSS/CSGO (bug 5295, r=psychonic). --- extensions/cstrike/natives.cpp | 208 ++++++++++++++++++++++++ gamedata/sm-cstrike.games/game.csgo.txt | 34 ++++ gamedata/sm-cstrike.games/game.css.txt | 37 +++++ plugins/include/cstrike.inc | 45 ++++- 4 files changed, 323 insertions(+), 1 deletion(-) diff --git a/extensions/cstrike/natives.cpp b/extensions/cstrike/natives.cpp index 7f972538..c50137ca 100644 --- a/extensions/cstrike/natives.cpp +++ b/extensions/cstrike/natives.cpp @@ -460,6 +460,210 @@ static cell_t CS_AliasToWeaponID(IPluginContext *pContext, const cell_t *params) return GetFakeWeaponID(AliasToWeaponID(weapon)); } +static cell_t CS_SetTeamScore(IPluginContext *pContext, const cell_t *params) +{ + if (g_pSDKTools == NULL) + { + smutils->LogError(myself, "SDKTools interface not found. CS_SetTeamScore native disabled."); + } + else if (g_pSDKTools->GetInterfaceVersion() < 2) + { + // THIS ISN'T DA LIMBO STICK. LOW IS BAD + return pContext->ThrowNativeError("SDKTools interface is outdated. CS_SetTeamScore native disabled."); + } + + static void *addr; + if (!addr) + { + if (!g_pGameConf->GetMemSig("CheckWinLimit", &addr) || !addr) + { + return pContext->ThrowNativeError("Failed to locate CheckWinLimit function"); + } + } + + static int ctTeamOffsetOffset = -1; + static int ctTeamOffset; + + static int tTeamOffsetOffset = -1; + static int tTeamOffset; + + if (ctTeamOffsetOffset == -1) + { + if (!g_pGameConf->GetOffset("CTTeamScoreOffset", &ctTeamOffsetOffset)) + { + ctTeamOffsetOffset = -1; + return pContext->ThrowNativeError("Unable to find CTTeamOffset gamedata"); + } + + ctTeamOffset = *(int *)((intptr_t)addr + ctTeamOffsetOffset); + } + + if (tTeamOffsetOffset == -1) + { + if (!g_pGameConf->GetOffset("TTeamScoreOffset", &tTeamOffsetOffset)) + { + tTeamOffsetOffset = -1; + return pContext->ThrowNativeError("Unable to find CTTeamOffset gamedata"); + } + + tTeamOffset = *(int *)((intptr_t)addr + tTeamOffsetOffset); + } + + void *gamerules = g_pSDKTools->GetGameRules(); + if (gamerules == NULL) + { + return pContext->ThrowNativeError("GameRules not available. CS_SetTeamScore native disabled."); + } + + if (params[1] == 3) + { + *(int16_t *)((intptr_t)gamerules+ctTeamOffset) = params[2]; + return 1; + } + else if (params[1] == 2) + { + *(int16_t *)((intptr_t)gamerules+tTeamOffset) = params[2]; + return 1; + } + return pContext->ThrowNativeError("Invalid team index passed (%i).", params[1]); +} + +static cell_t CS_GetTeamScore(IPluginContext *pContext, const cell_t *params) +{ + if (g_pSDKTools == NULL) + { + smutils->LogError(myself, "SDKTools interface not found. CS_GetTeamScore native disabled."); + } + else if (g_pSDKTools->GetInterfaceVersion() < 2) + { + // THIS ISN'T DA LIMBO STICK. LOW IS BAD + return pContext->ThrowNativeError("SDKTools interface is outdated. CS_GetTeamScore native disabled."); + } + + static void *addr; + if (!addr) + { + if (!g_pGameConf->GetMemSig("CheckWinLimit", &addr) || !addr) + { + return pContext->ThrowNativeError("Failed to locate CheckWinLimit function"); + } + } + + static int ctTeamOffsetOffset = -1; + static int ctTeamOffset; + + static int tTeamOffsetOffset = -1; + static int tTeamOffset; + + if (ctTeamOffsetOffset == -1) + { + if (!g_pGameConf->GetOffset("CTTeamScoreOffset", &ctTeamOffsetOffset)) + { + ctTeamOffsetOffset = -1; + return pContext->ThrowNativeError("Unable to find CTTeamOffset gamedata"); + } + + ctTeamOffset = *(int *)((intptr_t)addr + ctTeamOffsetOffset); + } + + if (tTeamOffsetOffset == -1) + { + if (!g_pGameConf->GetOffset("TTeamScoreOffset", &tTeamOffsetOffset)) + { + tTeamOffsetOffset = -1; + return pContext->ThrowNativeError("Unable to find CTTeamOffset gamedata"); + } + + tTeamOffset = *(int *)((intptr_t)addr + tTeamOffsetOffset); + } + + void *gamerules = g_pSDKTools->GetGameRules(); + if (gamerules == NULL) + { + return pContext->ThrowNativeError("GameRules not available. CS_GetTeamScore native disabled."); + } + + if (params[1] == 3) + { + return *(int16_t *)((intptr_t)gamerules+ctTeamOffset); + } + else if (params[1] == 2) + { + return *(int16_t *)((intptr_t)gamerules+tTeamOffset); + } + return pContext->ThrowNativeError("Invalid team index passed (%i).", params[1]); +} + +static cell_t CS_SetMVPCount(IPluginContext *pContext, const cell_t *params) +{ + static void *addr; + if (!addr) + { + if (!g_pGameConf->GetMemSig("IncrementNumMVPs", &addr) || !addr) + { + return pContext->ThrowNativeError("Failed to locate IncrementNumMVPs function"); + } + } + + CBaseEntity *pEntity; + if (!(pEntity = GetCBaseEntity(params[1], true))) + { + return pContext->ThrowNativeError("Client index %d is not valid", params[1]); + } + + static int mvpOffsetOffset = -1; + static int mvpOffset; + + if (mvpOffsetOffset == -1) + { + if (!g_pGameConf->GetOffset("MVPCountOffset", &mvpOffsetOffset)) + { + mvpOffsetOffset = -1; + return pContext->ThrowNativeError("Unable to find MVPCountOffset gamedata"); + } + + mvpOffset = *(int *)((intptr_t)addr + mvpOffsetOffset); + } + + *(int *)((intptr_t)pEntity + mvpOffset) = params[2]; + + return 1; +} + +static cell_t CS_GetMVPCount(IPluginContext *pContext, const cell_t *params) +{ + static void *addr; + if (!addr) + { + if (!g_pGameConf->GetMemSig("IncrementNumMVPs", &addr) || !addr) + { + return pContext->ThrowNativeError("Failed to locate IncrementNumMVPs function"); + } + } + + CBaseEntity *pEntity; + if (!(pEntity = GetCBaseEntity(params[1], true))) + { + return pContext->ThrowNativeError("Client index %d is not valid", params[1]); + } + + static int mvpOffsetOffset = -1; + static int mvpOffset; + + if (mvpOffsetOffset == -1) + { + if (!g_pGameConf->GetOffset("MVPCountOffset", &mvpOffsetOffset)) + { + mvpOffsetOffset = -1; + return pContext->ThrowNativeError("Unable to find MVPCountOffset gamedata"); + } + + mvpOffset = *(int *)((intptr_t)addr + mvpOffsetOffset); + } + + return *(int *)((intptr_t)pEntity + mvpOffset); +} + sp_nativeinfo_t g_CSNatives[] = { {"CS_RespawnPlayer", CS_RespawnPlayer}, @@ -471,6 +675,10 @@ sp_nativeinfo_t g_CSNatives[] = {"CS_GetClientClanTag", CS_GetClientClanTag}, {"CS_SetClientClanTag", CS_SetClientClanTag}, {"CS_AliasToWeaponID", CS_AliasToWeaponID}, + {"CS_GetTeamScore", CS_GetTeamScore}, + {"CS_SetTeamScore", CS_SetTeamScore}, + {"CS_GetMVPCount", CS_GetMVPCount}, + {"CS_SetMVPCount", CS_SetMVPCount}, {NULL, NULL} }; diff --git a/gamedata/sm-cstrike.games/game.csgo.txt b/gamedata/sm-cstrike.games/game.csgo.txt index d4f76663..d10c6649 100644 --- a/gamedata/sm-cstrike.games/game.csgo.txt +++ b/gamedata/sm-cstrike.games/game.csgo.txt @@ -27,6 +27,27 @@ "windows" "2700" "linux" "2700" } + //Offset into CheckRestartRound + //Only Windows/Linux for now. + "CTTeamScoreOffset" + { + "windows" "82" + "linux" "117" + } + //Offset into CheckRestartRound + //Only Windows/Linux for now. + "TTeamScoreOffset" + { + "windows" "107" + "linux" "152" + } + //Offset into IncrementNumMVPs to find MVP count offset from player + //Only Windows/Linux for now. + "MVPCountOffset" + { + "windows" "42" + "linux" "46" + } } "Signatures" { @@ -72,6 +93,19 @@ "windows" "\x55\x8B\xEC\x8B\x4D\x2A\x33\xC0\x85\xC9\x74" "linux" "@_Z13GetWeaponInfo10CSWeaponID" } + //In CS:GO this is actually CCSGameRules::CheckRestartRound(void) but to keep same gamedata as cs:s. + "CheckWinLimit" + { + "library" "server" + "windows" "\x55\x8B\xEC\xA1\x2A\x2A\x2A\x2A\x83\xEC\x2A\x57\x8B\xF9\x85\xC0\x0F\x84\x2A\x2A\x00\x00" + "linux" "@_ZN12CCSGameRules17CheckRestartRoundEv" + } + "IncrementNumMVPs" + { + "library" "server" + "windows" "\x55\x8B\xEC\xA1\x2A\x2A\x2A\x2A\x57\x8B\xF9\x85\x2A\x74\x2A\x83\x2A\x2A\x00\x74\x2A\x68\x50" + "linux" "@_ZN9CCSPlayer16IncrementNumMVPsE13CSMvpReason_t" + } "AliasToWeaponID" { "library" "server" diff --git a/gamedata/sm-cstrike.games/game.css.txt b/gamedata/sm-cstrike.games/game.css.txt index f36deb3c..e9e4f29e 100644 --- a/gamedata/sm-cstrike.games/game.css.txt +++ b/gamedata/sm-cstrike.games/game.css.txt @@ -35,6 +35,27 @@ "linux" "42" "mac" "29" } + //Offset into CheckWinLimit to find CT team score offset from gamerules. For mac this is an offset into CCSGameRules::Think + "CTTeamScoreOffset" + { + "windows" "18" + "linux" "46" + "mac" "466" + } + //Offset into CheckWinLimit to find T team score offset from gamerules. For mac this is an offset into CCSGameRules::Think + "TTeamScoreOffset" + { + "windows" "40" + "linux" "57" + "mac" "481" + } + //Offset into IncrementNumMVPs to find MVP count offset from player + "MVPCountOffset" + { + "windows" "60" + "linux" "49" + "mac" "62" + } } "Signatures" { @@ -108,6 +129,22 @@ "linux" "@_Z15AliasToWeaponIDPKc" "mac" "@_Z15AliasToWeaponIDPKc" } + + //For mac we use think since CheckWinLimit dosnt exist on mac. + "CheckWinLimit" + { + "library" "server" + "windows" "\xA1\x2A\x2A\x2A\x2A\x8B\x40\x2A\x85\xC0\x56\x8B\xF1\x74" + "linux" "@_ZN12CCSGameRules13CheckWinLimitEv" + "mac" "@_ZN12CCSGameRules5ThinkEv" + } + "IncrementNumMVPs" + { + "library" "server" + "windows" "\x55\x8B\xEC\x83\xEC\x2A\x89\x2A\x2A\xA1\x2A\x2A\x2A\x2A\x8B\x48\x2A\x89\x2A\x2A\x33\xD2\x83\x7D\x2A\x00\x0F\x95\xC2\x0F\xB6\xC2\x85\xC0\x74\x2A\x68" + "linux" "@_ZN9CCSPlayer16IncrementNumMVPsE13CSMvpReason_t" + "mac" "@_ZN9CCSPlayer16IncrementNumMVPsE13CSMvpReason_t" + } } } } diff --git a/plugins/include/cstrike.inc b/plugins/include/cstrike.inc index 3f8449ce..b888de14 100644 --- a/plugins/include/cstrike.inc +++ b/plugins/include/cstrike.inc @@ -264,7 +264,46 @@ native CS_GetClientClanTag(client, String:buffer[], size); * @note Only supported on CS:S. Has no effect on CS:GO. */ native CS_SetClientClanTag(client, const String:tag[]); - + +/** + * Gets a team's score + * @param team Team index to get score for. + * @return Returns the internal team score. + * + * @error Invalid team index. + */ +native CS_GetTeamScore(team); + +/** + * Sets a team's score + * @param team Team index to set score for. + * @param value Value to set teams score as. + * @noreturn + * + * @error Invalid team index. + * @note This will update the scoreboard only after the scoreboard update function is called. Use SetTeamScore plus this to update the scoreboard instantly and save values correctly. + */ +native CS_SetTeamScore(team, value); + +/** + * Gets a client's mvp count + * @param client Client index to set mvp count for. + * @return Returns the clients internal MVP count. + * + * @error Invalid client. + */ +native CS_GetMVPCount(client); + +/** + * Sets a client's mvp count + * @param client Client index to set mvp count for. + * @param value Value to set clients mvp count as. + * @noreturn + * + * @error Invalid client. + */ +native CS_SetMVPCount(client, value); + /** * Gets a weaponID from a alias * @param alias Weapon alias to attempt to get an id for. @@ -300,6 +339,10 @@ public __ext_cstrike_SetNTVOptional() MarkNativeAsOptional("CS_GetWeaponPrice"); MarkNativeAsOptional("CS_GetClientClanTag"); MarkNativeAsOptional("CS_SetClientClanTag"); + MarkNativeAsOptional("CS_GetTeamScore"); + MarkNativeAsOptional("CS_SetTeamScore"); + MarkNativeAsOptional("CS_GetMVPCount"); + MarkNativeAsOptional("CS_SetMVPCount"); MakrNativeAsOptional("CS_AliasToWeaponID"); } #endif