- 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

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); SH_ADD_HOOK_MEMFUNC(IServerGameDLL, LevelInit, gamedll, this, &SDKTools::LevelInit, true);
MathLib_Init(2.2f, 2.2f, 0.0f, 2);
return true; return true;
} }

View File

@ -34,6 +34,7 @@
CallHelper s_Teleport; CallHelper s_Teleport;
CallHelper s_GetVelocity; CallHelper s_GetVelocity;
CallHelper s_EyeAngles;
bool SetupTeleport() bool SetupTeleport()
{ {
@ -53,7 +54,7 @@ bool SetupTeleport()
s_Teleport.call = g_pBinTools->CreateVCall(offset, 0, 0, NULL, info, 3); 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; s_Teleport.supported = true;
} }
@ -101,7 +102,7 @@ bool SetupGetVelocity()
s_GetVelocity.call = g_pBinTools->CreateVCall(offset, 0, 0, NULL, info, 2); 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; s_GetVelocity.supported = true;
} }
@ -130,6 +131,65 @@ bool IsGetVelocitySupported()
return SetupGetVelocity(); 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() void ShutdownHelpers()
{ {
s_Teleport.Shutdown(); s_Teleport.Shutdown();

View File

@ -63,6 +63,9 @@ bool IsTeleportSupported();
void GetVelocity(CBaseEntity *pEntity, Vector *velocity, AngularImpulse *angvelocity); void GetVelocity(CBaseEntity *pEntity, Vector *velocity, AngularImpulse *angvelocity);
bool IsGetVelocitySupported(); bool IsGetVelocitySupported();
bool GetEyeAngles(CBaseEntity *pEntity, QAngle *pAngles);
bool IsEyeAnglesSupported();
void ShutdownHelpers(); void ShutdownHelpers();
#endif //_INCLUDE_SDKTOOLS_VHELPERS_H_ #endif //_INCLUDE_SDKTOOLS_VHELPERS_H_

View File

@ -113,6 +113,23 @@ bool CreateBaseCall(const char *name,
return false; 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) 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 cell_t GetClientEyeAngles(IPluginContext *pContext, const cell_t *params)
{ {
static ValveCall *pCall = NULL; int client = params[1];
if (!pCall) IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(client);
if (!pPlayer)
{ {
ValvePassInfo retinfo[1]; return pContext->ThrowNativeError("Invalid client index %d", client);
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");
} }
else if (!pPlayer->IsInGame())
{
return pContext->ThrowNativeError("Client %d is not in game", client);
} }
QAngle *ang; edict_t *pEdict = pPlayer->GetEdict();
START_CALL(); CBaseEntity *pEntity = pEdict->GetUnknown() ? pEdict->GetUnknown()->GetBaseEntity() : NULL;
DECODE_VALVE_PARAM(1, thisinfo, 0);
FINISH_CALL_SIMPLE(&ang); /* 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; cell_t *addr;
pContext->LocalToPhysAddr(params[2], &addr); pContext->LocalToPhysAddr(params[2], &addr);
addr[0] = sp_ftoc(ang->x); addr[0] = sp_ftoc(angles.x);
addr[1] = sp_ftoc(ang->y); addr[1] = sp_ftoc(angles.y);
addr[2] = sp_ftoc(ang->z); addr[2] = sp_ftoc(angles.z);
return 1; return got_angles ? 1 : 0;
} }
static cell_t FindEntityByClassname(IPluginContext *pContext, const cell_t *params) 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) if (player == NULL)
{ {
return pContext->ThrowNativeError("Invalid client index %d", params[1]); 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]); 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; 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[] = sp_nativeinfo_t g_Natives[] =
{ {
{"ExtinguishPlayer", ExtinguishEntity}, {"ExtinguishPlayer", ExtinguishEntity},
@ -838,5 +936,6 @@ sp_nativeinfo_t g_Natives[] =
{"DispatchKeyValue", DispatchKeyValue}, {"DispatchKeyValue", DispatchKeyValue},
{"DispatchKeyValueFloat", DispatchKeyValueFloat}, {"DispatchKeyValueFloat", DispatchKeyValueFloat},
{"DispatchKeyValueVector", DispatchKeyValueVector}, {"DispatchKeyValueVector", DispatchKeyValueVector},
{"GetClientAimTarget", GetClientAimTarget},
{NULL, NULL}, {NULL, NULL},
}; };

View File

@ -137,10 +137,10 @@ native FindEntityByClassname(startEnt, const String:classname[]);
* *
* @param client Player's index. * @param client Player's index.
* @param ang Destination vector to store the client's eye angles. * @param ang Destination vector to store the client's eye angles.
* @noreturn * @return True on success, false on failure.
* @error Invalid client index, client not in game, or no mod support. * @error Invalid client index, client not in game, or no mod support.
*/ */
native GetClientEyeAngles(client, Float:ang[3]); native bool:GetClientEyeAngles(client, Float:ang[3]);
/** /**
* Returns if the client is alive or dead. * Returns if the client is alive or dead.
@ -205,6 +205,18 @@ native bool:DispatchKeyValueFloat(entity, const String:keyName[], Float:value);
*/ */
native bool:DispatchKeyValueVector(entity, const String:keyName[], const Float:vector[3]); native bool:DispatchKeyValueVector(entity, const String:keyName[], const Float:vector[3]);
/**
* Returns the entity a client is aiming at.
*
* @param client Client performing the aiming.
* @param only_clients True to exclude all entities but clients.
* @return Entity index being aimed at.
* -1 if no entity is being aimed at.
* -2 if the function is not supported.
* @error Invalid client index.
*/
native GetClientAimTarget(client, bool:only_clients=true);
/** /**
* @deprecated * @deprecated
*/ */