- 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);
MathLib_Init(2.2f, 2.2f, 0.0f, 2);
return true;
}

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();

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_

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},
};

View File

@ -137,16 +137,16 @@ native FindEntityByClassname(startEnt, const String:classname[]);
*
* @param client Player's index.
* @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.
*/
native GetClientEyeAngles(client, Float:ang[3]);
native bool:GetClientEyeAngles(client, Float:ang[3]);
/**
* Returns if the client is alive or dead.
*
* @param client Player's index.
* @return True if the client is alive, false otherwise.
* @return True if the client is alive, false otherwise.
* @error Invalid client index, client not in game, or no mod support.
*/
native bool:IsPlayerAlive(client);
@ -156,10 +156,10 @@ native bool:IsPlayerAlive(client);
* If ForceEdictIndex is not -1, then it will use the edict by that index. If the index is
* invalid or there is already an edict using that index, it will error out.
*
* @param classname Entity classname.
* @param classname Entity classname.
* @param ForceEdictIndex Edict index used by the created entity.
* @return Entity index on success, or -1 on failure.
* @error Invalid edict index, or no mod support.
* @return Entity index on success, or -1 on failure.
* @error Invalid edict index, or no mod support.
*/
native CreateEntityByName(const String:classname[], ForceEdictIndex=-1);
@ -167,8 +167,8 @@ native CreateEntityByName(const String:classname[], ForceEdictIndex=-1);
* Spawns an entity into the game.
*
* @param entity Entity index of the created entity.
* @return True on success, false otherwise.
* @error Invalid entity index, or no mod support.
* @return True on success, false otherwise.
* @error Invalid entity index, or no mod support.
*/
native bool:DispatchSpawn(entity);
@ -178,8 +178,8 @@ native bool:DispatchSpawn(entity);
* @param entity Destination entity index.
* @param keyName Name of the key.
* @param value String value.
* @return True on success, false otherwise.
* @error Invalid entity index, or no mod support.
* @return True on success, false otherwise.
* @error Invalid entity index, or no mod support.
*/
native bool:DispatchKeyValue(entity, const String:keyName[], const String:value[]);
@ -189,8 +189,8 @@ native bool:DispatchKeyValue(entity, const String:keyName[], const String:value[
* @param entity Destination entity index.
* @param keyName Name of the key.
* @param value Floating point value.
* @return True on success, false otherwise.
* @error Invalid entity index, or no mod support.
* @return True on success, false otherwise.
* @error Invalid entity index, or no mod support.
*/
native bool:DispatchKeyValueFloat(entity, const String:keyName[], Float:value);
@ -200,11 +200,23 @@ native bool:DispatchKeyValueFloat(entity, const String:keyName[], Float:value);
* @param entity Destination entity index.
* @param keyName Name of the key.
* @param vec Vector value.
* @return True on success, false otherwise.
* @error Invalid entity index, or no mod support.
* @return True on success, false otherwise.
* @error Invalid entity index, or no mod support.
*/
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
*/