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