extensions/cstrike/natives.cpp
changeset 3706 54f55b538cb2
parent 3702 a0256b609078
child 3710 5559ea22b6b5
     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