- added GetClientAimTarget()

- fixed a bug where GetClientEyeAngles() was basically bogus

--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%401617
This commit is contained in:
David Anderson
2007-10-19 08:51:05 +00:00
parent ab8f67fc42
commit c2644b2f94
5 changed files with 211 additions and 35 deletions
+2
View File
@@ -104,6 +104,8 @@ bool SDKTools::SDK_OnLoad(char *error, size_t maxlength, bool late)
SH_ADD_HOOK_MEMFUNC(IServerGameDLL, LevelInit, gamedll, this, &SDKTools::LevelInit, true);
MathLib_Init(2.2f, 2.2f, 0.0f, 2);
return true;
}
+62 -2
View File
@@ -34,6 +34,7 @@
CallHelper s_Teleport;
CallHelper s_GetVelocity;
CallHelper s_EyeAngles;
bool SetupTeleport()
{
@@ -53,7 +54,7 @@ bool SetupTeleport()
s_Teleport.call = g_pBinTools->CreateVCall(offset, 0, 0, NULL, info, 3);
if (s_Teleport.call)
if (s_Teleport.call != NULL)
{
s_Teleport.supported = true;
}
@@ -101,7 +102,7 @@ bool SetupGetVelocity()
s_GetVelocity.call = g_pBinTools->CreateVCall(offset, 0, 0, NULL, info, 2);
if (s_GetVelocity.call)
if (s_GetVelocity.call != NULL)
{
s_GetVelocity.supported = true;
}
@@ -130,6 +131,65 @@ bool IsGetVelocitySupported()
return SetupGetVelocity();
}
bool SetupGetEyeAngles()
{
if (s_EyeAngles.setup)
{
return s_EyeAngles.supported;
}
int offset;
if (g_pGameConf->GetOffset("EyeAngles", &offset))
{
PassInfo info[2];
info[0].flags = info[1].flags = PASSFLAG_BYVAL;
info[0].size = info[1].size = sizeof(void *);
info[0].type = info[1].type = PassType_Basic;
s_EyeAngles.call = g_pBinTools->CreateVCall(offset, 0, 0, &info[0], &info[1], 1);
if (s_EyeAngles.call != NULL)
{
s_EyeAngles.supported = true;
}
}
s_EyeAngles.setup = true;
return s_EyeAngles.supported;
}
bool GetEyeAngles(CBaseEntity *pEntity, QAngle *pAngles)
{
if (!IsEyeAnglesSupported())
{
return false;
}
QAngle *pRetAngle = NULL;
unsigned char params[sizeof(void *)];
unsigned char *vptr = params;
*(CBaseEntity **)vptr = pEntity;
vptr += sizeof(CBaseEntity *);
s_EyeAngles.call->Execute(params, &pRetAngle);
if (pRetAngle == NULL)
{
return false;
}
*pAngles = *pRetAngle;
return true;
}
bool IsEyeAnglesSupported()
{
return SetupGetEyeAngles();
}
void ShutdownHelpers()
{
s_Teleport.Shutdown();
+3
View File
@@ -63,6 +63,9 @@ bool IsTeleportSupported();
void GetVelocity(CBaseEntity *pEntity, Vector *velocity, AngularImpulse *angvelocity);
bool IsGetVelocitySupported();
bool GetEyeAngles(CBaseEntity *pEntity, QAngle *pAngles);
bool IsEyeAnglesSupported();
void ShutdownHelpers();
#endif //_INCLUDE_SDKTOOLS_VHELPERS_H_
+118 -19
View File
@@ -113,6 +113,23 @@ bool CreateBaseCall(const char *name,
return false;
}
class CTraceFilterSimple : public CTraceFilterEntitiesOnly
{
public:
CTraceFilterSimple(const IHandleEntity *passentity): m_pPassEnt(passentity)
{
}
virtual bool ShouldHitEntity(IHandleEntity *pServerEntity, int contentsMask)
{
if (pServerEntity == m_pPassEnt)
{
return false;
}
return true;
}
private:
const IHandleEntity *m_pPassEnt;
};
static cell_t RemovePlayerItem(IPluginContext *pContext, const cell_t *params)
{
@@ -567,31 +584,39 @@ static cell_t GetClientEyePosition(IPluginContext *pContext, const cell_t *param
static cell_t GetClientEyeAngles(IPluginContext *pContext, const cell_t *params)
{
static ValveCall *pCall = NULL;
if (!pCall)
int client = params[1];
IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(client);
if (!pPlayer)
{
ValvePassInfo retinfo[1];
InitPass(retinfo[0], Valve_POD, PassType_Basic, PASSFLAG_BYVAL);
if (!CreateBaseCall("EyeAngles", ValveCall_Player, retinfo, NULL, 0, &pCall))
{
return pContext->ThrowNativeError("\"EyeAngles\" not supported by this mod");
} else if (!pCall) {
return pContext->ThrowNativeError("\"EyeAngles\" wrapper failed to initialized");
}
return pContext->ThrowNativeError("Invalid client index %d", client);
}
else if (!pPlayer->IsInGame())
{
return pContext->ThrowNativeError("Client %d is not in game", client);
}
QAngle *ang;
START_CALL();
DECODE_VALVE_PARAM(1, thisinfo, 0);
FINISH_CALL_SIMPLE(&ang);
edict_t *pEdict = pPlayer->GetEdict();
CBaseEntity *pEntity = pEdict->GetUnknown() ? pEdict->GetUnknown()->GetBaseEntity() : NULL;
/* We always set the angles for backwards compatibility --
* The original function had no return value.
*/
QAngle angles;
bool got_angles = false;
if (pEntity == NULL)
{
got_angles = GetEyeAngles(pEntity, &angles);
}
cell_t *addr;
pContext->LocalToPhysAddr(params[2], &addr);
addr[0] = sp_ftoc(ang->x);
addr[1] = sp_ftoc(ang->y);
addr[2] = sp_ftoc(ang->z);
addr[0] = sp_ftoc(angles.x);
addr[1] = sp_ftoc(angles.y);
addr[2] = sp_ftoc(angles.z);
return 1;
return got_angles ? 1 : 0;
}
static cell_t FindEntityByClassname(IPluginContext *pContext, const cell_t *params)
@@ -638,7 +663,8 @@ static cell_t IsPlayerAlive(IPluginContext *pContext, const cell_t *params)
if (player == NULL)
{
return pContext->ThrowNativeError("Invalid client index %d", params[1]);
} else if (!player->IsInGame())
}
else if (!player->IsInGame())
{
return pContext->ThrowNativeError("Client %d is not in game", params[1]);
}
@@ -814,6 +840,78 @@ static cell_t DispatchKeyValueVector(IPluginContext *pContext, const cell_t *par
return (ret) ? 1 : 0;
}
static cell_t GetClientAimTarget(IPluginContext *pContext, const cell_t *params)
{
int client = params[1];
IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(client);
if (!pPlayer)
{
return pContext->ThrowNativeError("Invalid client index %d", client);
}
else if (!pPlayer->IsInGame())
{
return pContext->ThrowNativeError("Client %d is not in game", client);
}
edict_t *pEdict = pPlayer->GetEdict();
CBaseEntity *pEntity = pEdict->GetUnknown() ? pEdict->GetUnknown()->GetBaseEntity() : NULL;
if (pEntity == NULL)
{
return -1;
}
Vector eye_position;
QAngle eye_angles;
/* Get the private information we need */
serverClients->ClientEarPosition(pEdict, &eye_position);
if (!GetEyeAngles(pEntity, &eye_angles))
{
return -2;
}
Vector aim_dir;
AngleVectors(eye_angles, &aim_dir);
VectorNormalize(aim_dir);
Vector vec_end = eye_position + aim_dir * 8000;
Ray_t ray;
ray.Init(eye_position, vec_end);
trace_t tr;
CTraceFilterSimple simple(pEdict->GetIServerEntity());
enginetrace->TraceRay(ray, MASK_SOLID|CONTENTS_DEBRIS|CONTENTS_HITBOX, &simple, &tr);
if (tr.fraction == 1.0f || tr.m_pEnt == NULL)
{
return -1;
}
edict_t *pTarget = gameents->BaseEntityToEdict(tr.m_pEnt);
if (pTarget == NULL)
{
return -1;
}
int ent_index = engine->IndexOfEdict(pTarget);
IGamePlayer *pTargetPlayer = playerhelpers->GetGamePlayer(ent_index);
if (pTargetPlayer != NULL && !pTargetPlayer->IsInGame())
{
return -1;
}
else if (params[2] && pTargetPlayer == NULL)
{
return -1;
}
return ent_index;
}
sp_nativeinfo_t g_Natives[] =
{
{"ExtinguishPlayer", ExtinguishEntity},
@@ -838,5 +936,6 @@ sp_nativeinfo_t g_Natives[] =
{"DispatchKeyValue", DispatchKeyValue},
{"DispatchKeyValueFloat", DispatchKeyValueFloat},
{"DispatchKeyValueVector", DispatchKeyValueVector},
{"GetClientAimTarget", GetClientAimTarget},
{NULL, NULL},
};