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]); 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; char szBaseName[128];
if (!addr) 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 (interimOffset == 0)
if (!(pEntity = GetCBaseEntity(params[1], true))) {
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]); return pContext->ThrowNativeError("Client index %d is not valid", params[1]);
} }
static int mvpOffsetOffset = -1; T *pVar = GetPlayerVarAddressOrError<T>(varName, pContext, pPlayer);
static int mvpOffset; if (pVar)
if (mvpOffsetOffset == -1)
{ {
if (!g_pGameConf->GetOffset("MVPCountOffset", &mvpOffsetOffset)) return (cell_t)*pVar;
{
mvpOffsetOffset = -1;
return pContext->ThrowNativeError("Unable to find MVPCountOffset gamedata");
}
mvpOffset = *(int *)((intptr_t)addr + mvpOffsetOffset);
} }
*(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 cell_t CS_GetMVPCount(IPluginContext *pContext, const cell_t *params)
{ {
static void *addr; return GetPlayerVar<int>(pContext, params, "MVPs");
if (!addr) }
{
if (!g_pGameConf->GetMemSig("IncrementNumMVPs", &addr) || !addr)
{
return pContext->ThrowNativeError("Failed to locate IncrementNumMVPs function");
}
}
CBaseEntity *pEntity; static cell_t CS_SetClientContributionScore(IPluginContext *pContext, const cell_t *params)
if (!(pEntity = GetCBaseEntity(params[1], true))) {
{ #if SOURCE_ENGINE == SE_CSGO
return pContext->ThrowNativeError("Client index %d is not valid", params[1]); return SetPlayerVar<int>(pContext, params, "CScore");
} #else
return pContext->ThrowNativeError("SetClientContributionScore is not supported on this game");
#endif
}
static int mvpOffsetOffset = -1; static cell_t CS_GetClientContributionScore(IPluginContext *pContext, const cell_t *params)
static int mvpOffset; {
#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) static cell_t CS_SetClientAssists(IPluginContext *pContext, const cell_t *params)
{ {
if (!g_pGameConf->GetOffset("MVPCountOffset", &mvpOffsetOffset)) #if SOURCE_ENGINE == SE_CSGO
{ return SetPlayerVar<int>(pContext, params, "Assists");
mvpOffsetOffset = -1; #else
return pContext->ThrowNativeError("Unable to find MVPCountOffset gamedata"); return pContext->ThrowNativeError("SetClientAssists is not supported on this game");
} #endif
}
mvpOffset = *(int *)((intptr_t)addr + mvpOffsetOffset); static cell_t CS_GetClientAssists(IPluginContext *pContext, const cell_t *params)
} {
#if SOURCE_ENGINE == SE_CSGO
return *(int *)((intptr_t)pEntity + mvpOffset); return GetPlayerVar<int>(pContext, params, "Assists");
#else
return pContext->ThrowNativeError("GetClientAssists is not supported on this game");
#endif
} }
sp_nativeinfo_t g_CSNatives[] = sp_nativeinfo_t g_CSNatives[] =
@ -686,6 +748,10 @@ sp_nativeinfo_t g_CSNatives[] =
{"CS_GetMVPCount", CS_GetMVPCount}, {"CS_GetMVPCount", CS_GetMVPCount},
{"CS_SetMVPCount", CS_SetMVPCount}, {"CS_SetMVPCount", CS_SetMVPCount},
{"CS_WeaponIDToAlias", CS_WeaponIDToAlias}, {"CS_WeaponIDToAlias", CS_WeaponIDToAlias},
{"CS_GetClientContributionScore", CS_GetClientContributionScore},
{"CS_SetClientContributionScore", CS_SetClientContributionScore},
{"CS_GetClientAssists", CS_GetClientAssists},
{"CS_SetClientAssists", CS_SetClientAssists},
{NULL, NULL} {NULL, NULL}
}; };

View File

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

View File

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