Added natives to CStrike ext to access assists/score in CSGO (bug 5525, r=asherkin).
1.1 --- a/extensions/cstrike/natives.cpp Fri Dec 14 15:18:30 2012 -0500
1.2 +++ b/extensions/cstrike/natives.cpp Sat Dec 15 14:36:52 2012 -0500
1.3 @@ -600,74 +600,136 @@
1.4 return pContext->ThrowNativeError("Invalid team index passed (%i).", params[1]);
1.5 }
1.6
1.7 -static cell_t CS_SetMVPCount(IPluginContext *pContext, const cell_t *params)
1.8 +template <typename T>
1.9 +static inline T *GetPlayerVarAddressOrError(const char *pszGamedataName, IPluginContext *pContext, CBaseEntity *pPlayerEntity)
1.10 {
1.11 - static void *addr;
1.12 - if (!addr)
1.13 + char szBaseName[128];
1.14 + g_pSM->Format(szBaseName, sizeof(szBaseName), "%sBase", pszGamedataName);
1.15 +
1.16 + const char *pszBaseVar = g_pGameConf->GetKeyValue(szBaseName);
1.17 + if (pszBaseVar == NULL)
1.18 + {
1.19 + pContext->ThrowNativeError("Failed to locate %s key in gamedata", szBaseName);
1.20 + return NULL;
1.21 + }
1.22 +
1.23 + int interimOffset = 0;
1.24 + sm_sendprop_info_t info;
1.25 + if (gamehelpers->FindSendPropInfo("CCSPlayer", pszBaseVar, &info))
1.26 {
1.27 - if (!g_pGameConf->GetMemSig("IncrementNumMVPs", &addr) || !addr)
1.28 + interimOffset = info.actual_offset;
1.29 + }
1.30 + else
1.31 + {
1.32 + datamap_t *pMap = gamehelpers->GetDataMap(pPlayerEntity);
1.33 + typedescription_t *td = gamehelpers->FindInDataMap(pMap, pszBaseVar);
1.34 + if (td)
1.35 {
1.36 - return pContext->ThrowNativeError("Failed to locate IncrementNumMVPs function");
1.37 +#if SOURCE_ENGINE >= SE_LEFT4DEAD
1.38 + interimOffset = td->fieldOffset;
1.39 +#else
1.40 + interimOffset = td->fieldOffset[TD_OFFSET_NORMAL];
1.41 +#endif
1.42 }
1.43 }
1.44
1.45 - CBaseEntity *pEntity;
1.46 - if (!(pEntity = GetCBaseEntity(params[1], true)))
1.47 + if (interimOffset == 0)
1.48 + {
1.49 + pContext->ThrowNativeError("Failed to find property \"%s\" on player.", pszBaseVar);
1.50 + return NULL;
1.51 + }
1.52 +
1.53 +
1.54 + int tempOffset;
1.55 + if (!g_pGameConf->GetOffset(pszGamedataName, &tempOffset))
1.56 + {
1.57 + pContext->ThrowNativeError("Failed to locate %s offset in gamedata", pszGamedataName);
1.58 + return NULL;
1.59 + }
1.60 +
1.61 + return (T *)((intptr_t)pPlayerEntity + interimOffset + tempOffset);
1.62 +}
1.63 +
1.64 +template <typename T>
1.65 +static inline cell_t GetPlayerVar(IPluginContext *pContext, const cell_t *params, const char *varName)
1.66 +{
1.67 + CBaseEntity *pPlayer = GetCBaseEntity(params[1], true);
1.68 + if (!pPlayer)
1.69 {
1.70 return pContext->ThrowNativeError("Client index %d is not valid", params[1]);
1.71 }
1.72
1.73 - static int mvpOffsetOffset = -1;
1.74 - static int mvpOffset;
1.75 -
1.76 - if (mvpOffsetOffset == -1)
1.77 - {
1.78 - if (!g_pGameConf->GetOffset("MVPCountOffset", &mvpOffsetOffset))
1.79 - {
1.80 - mvpOffsetOffset = -1;
1.81 - return pContext->ThrowNativeError("Unable to find MVPCountOffset gamedata");
1.82 - }
1.83 -
1.84 - mvpOffset = *(int *)((intptr_t)addr + mvpOffsetOffset);
1.85 + T *pVar = GetPlayerVarAddressOrError<T>(varName, pContext, pPlayer);
1.86 + if (pVar)
1.87 + {
1.88 + return (cell_t)*pVar;
1.89 }
1.90
1.91 - *(int *)((intptr_t)pEntity + mvpOffset) = params[2];
1.92 + return 0;
1.93 +}
1.94 +
1.95 +template <typename T>
1.96 +static inline cell_t SetPlayerVar(IPluginContext *pContext, const cell_t *params, const char *varName)
1.97 +{
1.98 + CBaseEntity *pPlayer = GetCBaseEntity(params[1], true);
1.99 + if (!pPlayer)
1.100 + {
1.101 + return pContext->ThrowNativeError("Client index %d is not valid", params[1]);
1.102 + }
1.103
1.104 - return 1;
1.105 + T *pVar = GetPlayerVarAddressOrError<T>(varName, pContext, pPlayer);
1.106 + if (pVar)
1.107 + {
1.108 + *pVar = (T)params[2];
1.109 + }
1.110 +
1.111 + return 0;
1.112 +}
1.113 +
1.114 +static cell_t CS_SetMVPCount(IPluginContext *pContext, const cell_t *params)
1.115 +{
1.116 + return SetPlayerVar<int>(pContext, params, "MVPs");
1.117 }
1.118
1.119 static cell_t CS_GetMVPCount(IPluginContext *pContext, const cell_t *params)
1.120 {
1.121 - static void *addr;
1.122 - if (!addr)
1.123 - {
1.124 - if (!g_pGameConf->GetMemSig("IncrementNumMVPs", &addr) || !addr)
1.125 - {
1.126 - return pContext->ThrowNativeError("Failed to locate IncrementNumMVPs function");
1.127 - }
1.128 - }
1.129 + return GetPlayerVar<int>(pContext, params, "MVPs");
1.130 +}
1.131
1.132 - CBaseEntity *pEntity;
1.133 - if (!(pEntity = GetCBaseEntity(params[1], true)))
1.134 - {
1.135 - return pContext->ThrowNativeError("Client index %d is not valid", params[1]);
1.136 - }
1.137 +static cell_t CS_SetClientContributionScore(IPluginContext *pContext, const cell_t *params)
1.138 +{
1.139 +#if SOURCE_ENGINE == SE_CSGO
1.140 + return SetPlayerVar<int>(pContext, params, "CScore");
1.141 +#else
1.142 + return pContext->ThrowNativeError("SetClientContributionScore is not supported on this game");
1.143 +#endif
1.144 +}
1.145
1.146 - static int mvpOffsetOffset = -1;
1.147 - static int mvpOffset;
1.148 +static cell_t CS_GetClientContributionScore(IPluginContext *pContext, const cell_t *params)
1.149 +{
1.150 +#if SOURCE_ENGINE == SE_CSGO
1.151 + return GetPlayerVar<int>(pContext, params, "CScore");
1.152 +#else
1.153 + return pContext->ThrowNativeError("GetClientContributionScore is not supported on this game");
1.154 +#endif
1.155 +}
1.156
1.157 - if (mvpOffsetOffset == -1)
1.158 - {
1.159 - if (!g_pGameConf->GetOffset("MVPCountOffset", &mvpOffsetOffset))
1.160 - {
1.161 - mvpOffsetOffset = -1;
1.162 - return pContext->ThrowNativeError("Unable to find MVPCountOffset gamedata");
1.163 - }
1.164 +static cell_t CS_SetClientAssists(IPluginContext *pContext, const cell_t *params)
1.165 +{
1.166 +#if SOURCE_ENGINE == SE_CSGO
1.167 + return SetPlayerVar<int>(pContext, params, "Assists");
1.168 +#else
1.169 + return pContext->ThrowNativeError("SetClientAssists is not supported on this game");
1.170 +#endif
1.171 +}
1.172
1.173 - mvpOffset = *(int *)((intptr_t)addr + mvpOffsetOffset);
1.174 - }
1.175 -
1.176 - return *(int *)((intptr_t)pEntity + mvpOffset);
1.177 +static cell_t CS_GetClientAssists(IPluginContext *pContext, const cell_t *params)
1.178 +{
1.179 +#if SOURCE_ENGINE == SE_CSGO
1.180 + return GetPlayerVar<int>(pContext, params, "Assists");
1.181 +#else
1.182 + return pContext->ThrowNativeError("GetClientAssists is not supported on this game");
1.183 +#endif
1.184 }
1.185
1.186 sp_nativeinfo_t g_CSNatives[] =
1.187 @@ -686,6 +748,10 @@
1.188 {"CS_GetMVPCount", CS_GetMVPCount},
1.189 {"CS_SetMVPCount", CS_SetMVPCount},
1.190 {"CS_WeaponIDToAlias", CS_WeaponIDToAlias},
1.191 + {"CS_GetClientContributionScore", CS_GetClientContributionScore},
1.192 + {"CS_SetClientContributionScore", CS_SetClientContributionScore},
1.193 + {"CS_GetClientAssists", CS_GetClientAssists},
1.194 + {"CS_SetClientAssists", CS_SetClientAssists},
1.195 {NULL, NULL}
1.196 };
1.197
2.1 --- a/gamedata/sm-cstrike.games/game.csgo.txt Fri Dec 14 15:18:30 2012 -0500
2.2 +++ b/gamedata/sm-cstrike.games/game.csgo.txt Sat Dec 15 14:36:52 2012 -0500
2.3 @@ -42,13 +42,6 @@
2.4 "linux" "159"
2.5 "mac" "185"
2.6 }
2.7 - //Offset into IncrementNumMVPs to find MVP count offset from player
2.8 - "MVPCountOffset"
2.9 - {
2.10 - "windows" "46"
2.11 - "linux" "47"
2.12 - "mac" "61"
2.13 - }
2.14 "ClanTagOffset"
2.15 {
2.16 "windows" "15"
2.17 @@ -115,13 +108,6 @@
2.18 "linux" "@_ZN12CCSGameRules17CheckRestartRoundEv"
2.19 "mac" "@_ZN12CCSGameRules17CheckRestartRoundEv"
2.20 }
2.21 - "IncrementNumMVPs"
2.22 - {
2.23 - "library" "server"
2.24 - "windows" "\x55\x8B\xEC\xA1\x2A\x2A\x2A\x2A\x8B\x50\x34\x81\xEC\x2A\x2A\x2A\x2A\x57\x8B\xF9\xB9\x2A\x2A\x2A\x2A\xFF\xD2\x85\xC0\x74"
2.25 - "linux" "@_ZN9CCSPlayer16IncrementNumMVPsE13CSMvpReason_t"
2.26 - "mac" "@_ZN9CCSPlayer16IncrementNumMVPsE13CSMvpReason_t"
2.27 - }
2.28 "AliasToWeaponID"
2.29 {
2.30 "library" "server"
2.31 @@ -145,4 +131,60 @@
2.32 }
2.33 }
2.34 }
2.35 +
2.36 + "csgo"
2.37 + {
2.38 + "Keys"
2.39 + {
2.40 + "AssistsBase" "m_iFrags"
2.41 + }
2.42 +
2.43 + "Offsets"
2.44 + {
2.45 + "Assists"
2.46 + {
2.47 + "windows" "4"
2.48 + "linux" "4"
2.49 + "mac" "4"
2.50 + }
2.51 + }
2.52 + }
2.53 +
2.54 + "csgo"
2.55 + {
2.56 + "Keys"
2.57 + {
2.58 + "CScoreBase" "m_iWeaponPurchasesThisRound"
2.59 + }
2.60 +
2.61 + "Offsets"
2.62 + {
2.63 + /* factors in 256 (size of m_iWeaponPurchasesThisRound array (int size * 64 maxplayers)) */
2.64 + "CScore"
2.65 + {
2.66 + "windows" "276"
2.67 + "linux" "276"
2.68 + "mac" "276"
2.69 + }
2.70 + }
2.71 + }
2.72 +
2.73 + "csgo"
2.74 + {
2.75 + "Keys"
2.76 + {
2.77 + "MVPsBase" "m_iWeaponPurchasesThisRound"
2.78 + }
2.79 +
2.80 + "Offsets"
2.81 + {
2.82 + "MVPs"
2.83 + {
2.84 + /* factors in 256 (size of m_iWeaponPurchasesThisRound array (int size * 64 maxplayers)) */
2.85 + "windows" "256"
2.86 + "linux" "256"
2.87 + "mac" "256"
2.88 + }
2.89 + }
2.90 + }
2.91 }
3.1 --- a/gamedata/sm-cstrike.games/game.css.txt Fri Dec 14 15:18:30 2012 -0500
3.2 +++ b/gamedata/sm-cstrike.games/game.css.txt Sat Dec 15 14:36:52 2012 -0500
3.3 @@ -49,13 +49,6 @@
3.4 "linux" "57"
3.5 "mac" "481"
3.6 }
3.7 - //Offset into IncrementNumMVPs to find MVP count offset from player
3.8 - "MVPCountOffset"
3.9 - {
3.10 - "windows" "60"
3.11 - "linux" "49"
3.12 - "mac" "62"
3.13 - }
3.14 }
3.15 "Signatures"
3.16 {
3.17 @@ -145,12 +138,25 @@
3.18 "linux" "@_ZN12CCSGameRules13CheckWinLimitEv"
3.19 "mac" "@_ZN12CCSGameRules5ThinkEv"
3.20 }
3.21 - "IncrementNumMVPs"
3.22 + }
3.23 + }
3.24 +
3.25 + "cstrike"
3.26 + {
3.27 + "Keys"
3.28 + {
3.29 + "MVPsBase" "m_bPlayerDominatingMe"
3.30 + }
3.31 +
3.32 + "Offsets"
3.33 + {
3.34 + "MVPs"
3.35 {
3.36 - "library" "server"
3.37 - "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"
3.38 - "linux" "@_ZN9CCSPlayer16IncrementNumMVPsE13CSMvpReason_t"
3.39 - "mac" "@_ZN9CCSPlayer16IncrementNumMVPsE13CSMvpReason_t"
3.40 + /* factors in 66 (size of m_bPlayerDominatingMe array (bool size * (65 maxplayers + 1)))
3.41 + ... plus another 3 because alignment(?) lolidk */
3.42 + "windows" "69"
3.43 + "linux" "69"
3.44 + "mac" "69"
3.45 }
3.46 }
3.47 }
4.1 --- a/plugins/include/cstrike.inc Fri Dec 14 15:18:30 2012 -0500
4.2 +++ b/plugins/include/cstrike.inc Sat Dec 15 14:36:52 2012 -0500
4.3 @@ -285,8 +285,8 @@
4.4
4.5 /**
4.6 * Gets a client's mvp count
4.7 - * @param client Client index to set mvp count for.
4.8 - * @return Returns the clients internal MVP count.
4.9 + * @param client Client index to get mvp count of.
4.10 + * @return Returns the client's internal MVP count.
4.11 *
4.12 * @error Invalid client.
4.13 */
4.14 @@ -295,7 +295,7 @@
4.15 /**
4.16 * Sets a client's mvp count
4.17 * @param client Client index to set mvp count for.
4.18 - * @param value Value to set clients mvp count as.
4.19 + * @param value Value to set client's mvp count as.
4.20 * @noreturn
4.21 *
4.22 * @error Invalid client.
4.23 @@ -303,6 +303,44 @@
4.24 native CS_SetMVPCount(client, value);
4.25
4.26 /**
4.27 + * Gets a client's contribution score (CS:GO only)
4.28 + * @param client Client index to get score of.
4.29 + * @return Returns the client's score.
4.30 + *
4.31 + * @error Invalid client.
4.32 + */
4.33 +native CS_GetClientContributionScore(client);
4.34 +
4.35 +/**
4.36 + * Sets a client's contribution score (CS:GO only)
4.37 + * @param client Client index to set score for.
4.38 + * @param value Value to set client's score as.
4.39 + * @noreturn
4.40 + *
4.41 + * @error Invalid client.
4.42 + */
4.43 +native CS_SetClientContributionScore(client, value);
4.44 +
4.45 +/**
4.46 + * Gets a client's assists (CS:GO only)
4.47 + * @param client Client index to get assists of.
4.48 + * @return Returns the client's assists.
4.49 + *
4.50 + * @error Invalid client.
4.51 + */
4.52 +native CS_GetClientAssists(client);
4.53 +
4.54 +/**
4.55 + * Sets a client's assists (CS:GO only)
4.56 + * @param client Client index to set assists for.
4.57 + * @param value Value to set client's assists as.
4.58 + * @noreturn
4.59 + *
4.60 + * @error Invalid client.
4.61 + */
4.62 +native CS_SetClientAssists(client, value);
4.63 +
4.64 +/**
4.65 * Gets a weaponID from a alias
4.66 * @param alias Weapon alias to attempt to get an id for.
4.67 * @return Returns a weapon id or 0 if failed to find a match.
4.68 @@ -350,6 +388,10 @@
4.69 MarkNativeAsOptional("CS_SetTeamScore");
4.70 MarkNativeAsOptional("CS_GetMVPCount");
4.71 MarkNativeAsOptional("CS_SetMVPCount");
4.72 + MarkNativeAsOptional("CS_GetClientContributionScore");
4.73 + MarkNativeAsOptional("CS_SetClientContributionScore");
4.74 + MarkNativeAsOptional("CS_GetClientAssists");
4.75 + MarkNativeAsOptional("CS_SetClientAssists");
4.76 MarkNativeAsOptional("CS_AliasToWeaponID");
4.77 }
4.78 #endif
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/plugins/testsuite/cstrike-test.sp Sat Dec 15 14:36:52 2012 -0500
5.3 @@ -0,0 +1,94 @@
5.4 +#include <sourcemod>
5.5 +#include <cstrike>
5.6 +
5.7 +stock GET_ARG_INT( arg, maxSize=64 )
5.8 +{
5.9 + decl String:tempvar[maxSize];
5.10 + GetCmdArg( arg, tempvar, maxSize );
5.11 + return StringToInt( tempvar );
5.12 +}
5.13 +
5.14 +public OnPluginStart()
5.15 +{
5.16 + RegConsoleCmd( "get_mvps", get_mvps );
5.17 + RegConsoleCmd( "set_mvps", set_mvps );
5.18 + RegConsoleCmd( "get_score", get_score );
5.19 + RegConsoleCmd( "set_score", set_score );
5.20 + RegConsoleCmd( "get_assists", get_assists );
5.21 + RegConsoleCmd( "set_assists", set_assists );
5.22 +}
5.23 +
5.24 +public Action:get_mvps( client, argc )
5.25 +{
5.26 + ReplyToCommand( client, "Your MVP count is %d", CS_GetMVPCount( client ) );
5.27 +
5.28 + return Plugin_Handled;
5.29 +}
5.30 +
5.31 +public Action:set_mvps( client, argc )
5.32 +{
5.33 + new count = GET_ARG_INT( 1 );
5.34 +
5.35 + CS_SetMVPCount( client, count );
5.36 + ReplyToCommand( client, "Set your MVP count to %d", count );
5.37 +
5.38 + return Plugin_Handled;
5.39 +}
5.40 +
5.41 +public Action:get_score( client, argc )
5.42 +{
5.43 + if( GuessSDKVersion() != SOURCE_SDK_CSGO )
5.44 + {
5.45 + ReplyToCommand( client, "This command is only intended for CS:GO" );
5.46 + return Plugin_Handled;
5.47 + }
5.48 +
5.49 + ReplyToCommand( client, "Your contribution score is %d", CS_GetClientContributionScore( client ) );
5.50 +
5.51 + return Plugin_Handled;
5.52 +}
5.53 +
5.54 +public Action:set_score( client, argc )
5.55 +{
5.56 + if( GuessSDKVersion() != SOURCE_SDK_CSGO )
5.57 + {
5.58 + ReplyToCommand( client, "This command is only intended for CS:GO" );
5.59 + return Plugin_Handled;
5.60 + }
5.61 +
5.62 + new count = GET_ARG_INT( 1 );
5.63 +
5.64 + CS_SetClientContributionScore( client, count );
5.65 + ReplyToCommand( client, "Set your contribution score to %d", count );
5.66 +
5.67 + return Plugin_Handled;
5.68 +}
5.69 +
5.70 +public Action:get_assists( client, argc )
5.71 +{
5.72 + if( GuessSDKVersion() != SOURCE_SDK_CSGO )
5.73 + {
5.74 + ReplyToCommand( client, "This command is only intended for CS:GO" );
5.75 + return Plugin_Handled;
5.76 + }
5.77 +
5.78 + ReplyToCommand( client, "Your assist count is %d", CS_GetClientAssists( client ) );
5.79 +
5.80 + return Plugin_Handled;
5.81 +}
5.82 +
5.83 +public Action:set_assists( client, argc )
5.84 +{
5.85 + if( GuessSDKVersion() != SOURCE_SDK_CSGO )
5.86 + {
5.87 + ReplyToCommand( client, "This command is only intended for CS:GO" );
5.88 + return Plugin_Handled;
5.89 + }
5.90 +
5.91 + new count = GET_ARG_INT( 1 );
5.92 +
5.93 + CS_SetClientAssists( client, count );
5.94 + ReplyToCommand( client, "Set your assist count to %d", count );
5.95 +
5.96 + return Plugin_Handled;
5.97 +}