Added natives to CStrike ext to access assists/score in CSGO (bug 5525, r=asherkin).

This commit is contained in:
Nicholas Hastings 2012-12-15 14:36:52 -05:00
parent c0b91dd107
commit ba2915ce4e
5 changed files with 326 additions and 76 deletions

View File

@ -600,74 +600,136 @@ static cell_t CS_GetTeamScore(IPluginContext *pContext, const cell_t *params)
return pContext->ThrowNativeError("Invalid team index passed (%i).", params[1]);
}
static cell_t CS_SetMVPCount(IPluginContext *pContext, const cell_t *params)
template <typename T>
static inline T *GetPlayerVarAddressOrError(const char *pszGamedataName, IPluginContext *pContext, CBaseEntity *pPlayerEntity)
{
static void *addr;
if (!addr)
char szBaseName[128];
g_pSM->Format(szBaseName, sizeof(szBaseName), "%sBase", pszGamedataName);
const char *pszBaseVar = g_pGameConf->GetKeyValue(szBaseName);
if (pszBaseVar == NULL)
{
if (!g_pGameConf->GetMemSig("IncrementNumMVPs", &addr) || !addr)
pContext->ThrowNativeError("Failed to locate %s key in gamedata", szBaseName);
return NULL;
}
int interimOffset = 0;
sm_sendprop_info_t info;
if (gamehelpers->FindSendPropInfo("CCSPlayer", pszBaseVar, &info))
{
interimOffset = info.actual_offset;
}
else
{
datamap_t *pMap = gamehelpers->GetDataMap(pPlayerEntity);
typedescription_t *td = gamehelpers->FindInDataMap(pMap, pszBaseVar);
if (td)
{
return pContext->ThrowNativeError("Failed to locate IncrementNumMVPs function");
#if SOURCE_ENGINE >= SE_LEFT4DEAD
interimOffset = td->fieldOffset;
#else
interimOffset = td->fieldOffset[TD_OFFSET_NORMAL];
#endif
}
}
CBaseEntity *pEntity;
if (!(pEntity = GetCBaseEntity(params[1], true)))
if (interimOffset == 0)
{
pContext->ThrowNativeError("Failed to find property \"%s\" on player.", pszBaseVar);
return NULL;
}
int tempOffset;
if (!g_pGameConf->GetOffset(pszGamedataName, &tempOffset))
{
pContext->ThrowNativeError("Failed to locate %s offset in gamedata", pszGamedataName);
return NULL;
}
return (T *)((intptr_t)pPlayerEntity + interimOffset + tempOffset);
}
template <typename T>
static inline cell_t GetPlayerVar(IPluginContext *pContext, const cell_t *params, const char *varName)
{
CBaseEntity *pPlayer = GetCBaseEntity(params[1], true);
if (!pPlayer)
{
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);
T *pVar = GetPlayerVarAddressOrError<T>(varName, pContext, pPlayer);
if (pVar)
{
return (cell_t)*pVar;
}
*(int *)((intptr_t)pEntity + mvpOffset) = params[2];
return 0;
}
return 1;
template <typename T>
static inline cell_t SetPlayerVar(IPluginContext *pContext, const cell_t *params, const char *varName)
{
CBaseEntity *pPlayer = GetCBaseEntity(params[1], true);
if (!pPlayer)
{
return pContext->ThrowNativeError("Client index %d is not valid", params[1]);
}
T *pVar = GetPlayerVarAddressOrError<T>(varName, pContext, pPlayer);
if (pVar)
{
*pVar = (T)params[2];
}
return 0;
}
static cell_t CS_SetMVPCount(IPluginContext *pContext, const cell_t *params)
{
return SetPlayerVar<int>(pContext, params, "MVPs");
}
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");
}
}
return GetPlayerVar<int>(pContext, params, "MVPs");
}
CBaseEntity *pEntity;
if (!(pEntity = GetCBaseEntity(params[1], true)))
{
return pContext->ThrowNativeError("Client index %d is not valid", params[1]);
}
static cell_t CS_SetClientContributionScore(IPluginContext *pContext, const cell_t *params)
{
#if SOURCE_ENGINE == SE_CSGO
return SetPlayerVar<int>(pContext, params, "CScore");
#else
return pContext->ThrowNativeError("SetClientContributionScore is not supported on this game");
#endif
}
static int mvpOffsetOffset = -1;
static int mvpOffset;
static cell_t CS_GetClientContributionScore(IPluginContext *pContext, const cell_t *params)
{
#if SOURCE_ENGINE == SE_CSGO
return GetPlayerVar<int>(pContext, params, "CScore");
#else
return pContext->ThrowNativeError("GetClientContributionScore is not supported on this game");
#endif
}
if (mvpOffsetOffset == -1)
{
if (!g_pGameConf->GetOffset("MVPCountOffset", &mvpOffsetOffset))
{
mvpOffsetOffset = -1;
return pContext->ThrowNativeError("Unable to find MVPCountOffset gamedata");
}
static cell_t CS_SetClientAssists(IPluginContext *pContext, const cell_t *params)
{
#if SOURCE_ENGINE == SE_CSGO
return SetPlayerVar<int>(pContext, params, "Assists");
#else
return pContext->ThrowNativeError("SetClientAssists is not supported on this game");
#endif
}
mvpOffset = *(int *)((intptr_t)addr + mvpOffsetOffset);
}
return *(int *)((intptr_t)pEntity + mvpOffset);
static cell_t CS_GetClientAssists(IPluginContext *pContext, const cell_t *params)
{
#if SOURCE_ENGINE == SE_CSGO
return GetPlayerVar<int>(pContext, params, "Assists");
#else
return pContext->ThrowNativeError("GetClientAssists is not supported on this game");
#endif
}
sp_nativeinfo_t g_CSNatives[] =
@ -686,6 +748,10 @@ sp_nativeinfo_t g_CSNatives[] =
{"CS_GetMVPCount", CS_GetMVPCount},
{"CS_SetMVPCount", CS_SetMVPCount},
{"CS_WeaponIDToAlias", CS_WeaponIDToAlias},
{"CS_GetClientContributionScore", CS_GetClientContributionScore},
{"CS_SetClientContributionScore", CS_SetClientContributionScore},
{"CS_GetClientAssists", CS_GetClientAssists},
{"CS_SetClientAssists", CS_SetClientAssists},
{NULL, NULL}
};

View File

@ -42,13 +42,6 @@
"linux" "159"
"mac" "185"
}
//Offset into IncrementNumMVPs to find MVP count offset from player
"MVPCountOffset"
{
"windows" "46"
"linux" "47"
"mac" "61"
}
"ClanTagOffset"
{
"windows" "15"
@ -115,13 +108,6 @@
"linux" "@_ZN12CCSGameRules17CheckRestartRoundEv"
"mac" "@_ZN12CCSGameRules17CheckRestartRoundEv"
}
"IncrementNumMVPs"
{
"library" "server"
"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"
"linux" "@_ZN9CCSPlayer16IncrementNumMVPsE13CSMvpReason_t"
"mac" "@_ZN9CCSPlayer16IncrementNumMVPsE13CSMvpReason_t"
}
"AliasToWeaponID"
{
"library" "server"
@ -145,4 +131,60 @@
}
}
}
"csgo"
{
"Keys"
{
"AssistsBase" "m_iFrags"
}
"Offsets"
{
"Assists"
{
"windows" "4"
"linux" "4"
"mac" "4"
}
}
}
"csgo"
{
"Keys"
{
"CScoreBase" "m_iWeaponPurchasesThisRound"
}
"Offsets"
{
/* factors in 256 (size of m_iWeaponPurchasesThisRound array (int size * 64 maxplayers)) */
"CScore"
{
"windows" "276"
"linux" "276"
"mac" "276"
}
}
}
"csgo"
{
"Keys"
{
"MVPsBase" "m_iWeaponPurchasesThisRound"
}
"Offsets"
{
"MVPs"
{
/* factors in 256 (size of m_iWeaponPurchasesThisRound array (int size * 64 maxplayers)) */
"windows" "256"
"linux" "256"
"mac" "256"
}
}
}
}

View File

@ -49,13 +49,6 @@
"linux" "57"
"mac" "481"
}
//Offset into IncrementNumMVPs to find MVP count offset from player
"MVPCountOffset"
{
"windows" "60"
"linux" "49"
"mac" "62"
}
}
"Signatures"
{
@ -145,12 +138,25 @@
"linux" "@_ZN12CCSGameRules13CheckWinLimitEv"
"mac" "@_ZN12CCSGameRules5ThinkEv"
}
"IncrementNumMVPs"
}
}
"cstrike"
{
"Keys"
{
"MVPsBase" "m_bPlayerDominatingMe"
}
"Offsets"
{
"MVPs"
{
"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"
/* factors in 66 (size of m_bPlayerDominatingMe array (bool size * (65 maxplayers + 1)))
... plus another 3 because alignment(?) lolidk */
"windows" "69"
"linux" "69"
"mac" "69"
}
}
}

View File

@ -285,8 +285,8 @@ 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.
* @param client Client index to get mvp count of.
* @return Returns the client's internal MVP count.
*
* @error Invalid client.
*/
@ -295,13 +295,51 @@ 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.
* @param value Value to set client's mvp count as.
* @noreturn
*
* @error Invalid client.
*/
native CS_SetMVPCount(client, value);
/**
* Gets a client's contribution score (CS:GO only)
* @param client Client index to get score of.
* @return Returns the client's score.
*
* @error Invalid client.
*/
native CS_GetClientContributionScore(client);
/**
* Sets a client's contribution score (CS:GO only)
* @param client Client index to set score for.
* @param value Value to set client's score as.
* @noreturn
*
* @error Invalid client.
*/
native CS_SetClientContributionScore(client, value);
/**
* Gets a client's assists (CS:GO only)
* @param client Client index to get assists of.
* @return Returns the client's assists.
*
* @error Invalid client.
*/
native CS_GetClientAssists(client);
/**
* Sets a client's assists (CS:GO only)
* @param client Client index to set assists for.
* @param value Value to set client's assists as.
* @noreturn
*
* @error Invalid client.
*/
native CS_SetClientAssists(client, value);
/**
* Gets a weaponID from a alias
* @param alias Weapon alias to attempt to get an id for.
@ -350,6 +388,10 @@ public __ext_cstrike_SetNTVOptional()
MarkNativeAsOptional("CS_SetTeamScore");
MarkNativeAsOptional("CS_GetMVPCount");
MarkNativeAsOptional("CS_SetMVPCount");
MarkNativeAsOptional("CS_GetClientContributionScore");
MarkNativeAsOptional("CS_SetClientContributionScore");
MarkNativeAsOptional("CS_GetClientAssists");
MarkNativeAsOptional("CS_SetClientAssists");
MarkNativeAsOptional("CS_AliasToWeaponID");
}
#endif

View File

@ -0,0 +1,94 @@
#include <sourcemod>
#include <cstrike>
stock GET_ARG_INT( arg, maxSize=64 )
{
decl String:tempvar[maxSize];
GetCmdArg( arg, tempvar, maxSize );
return StringToInt( tempvar );
}
public OnPluginStart()
{
RegConsoleCmd( "get_mvps", get_mvps );
RegConsoleCmd( "set_mvps", set_mvps );
RegConsoleCmd( "get_score", get_score );
RegConsoleCmd( "set_score", set_score );
RegConsoleCmd( "get_assists", get_assists );
RegConsoleCmd( "set_assists", set_assists );
}
public Action:get_mvps( client, argc )
{
ReplyToCommand( client, "Your MVP count is %d", CS_GetMVPCount( client ) );
return Plugin_Handled;
}
public Action:set_mvps( client, argc )
{
new count = GET_ARG_INT( 1 );
CS_SetMVPCount( client, count );
ReplyToCommand( client, "Set your MVP count to %d", count );
return Plugin_Handled;
}
public Action:get_score( client, argc )
{
if( GuessSDKVersion() != SOURCE_SDK_CSGO )
{
ReplyToCommand( client, "This command is only intended for CS:GO" );
return Plugin_Handled;
}
ReplyToCommand( client, "Your contribution score is %d", CS_GetClientContributionScore( client ) );
return Plugin_Handled;
}
public Action:set_score( client, argc )
{
if( GuessSDKVersion() != SOURCE_SDK_CSGO )
{
ReplyToCommand( client, "This command is only intended for CS:GO" );
return Plugin_Handled;
}
new count = GET_ARG_INT( 1 );
CS_SetClientContributionScore( client, count );
ReplyToCommand( client, "Set your contribution score to %d", count );
return Plugin_Handled;
}
public Action:get_assists( client, argc )
{
if( GuessSDKVersion() != SOURCE_SDK_CSGO )
{
ReplyToCommand( client, "This command is only intended for CS:GO" );
return Plugin_Handled;
}
ReplyToCommand( client, "Your assist count is %d", CS_GetClientAssists( client ) );
return Plugin_Handled;
}
public Action:set_assists( client, argc )
{
if( GuessSDKVersion() != SOURCE_SDK_CSGO )
{
ReplyToCommand( client, "This command is only intended for CS:GO" );
return Plugin_Handled;
}
new count = GET_ARG_INT( 1 );
CS_SetClientAssists( client, count );
ReplyToCommand( client, "Set your assist count to %d", count );
return Plugin_Handled;
}