- added GetClientAimTarget()
authorDavid Anderson <dvander@alliedmods.net>
Fri Oct 19 08:51:05 2007 +0000 (2007-10-19)
changeset 16111bd18b7530eb
parent 1610 c962ed7d35de
child 1612 6a4c932c1cf6
- added GetClientAimTarget()
- fixed a bug where GetClientEyeAngles() was basically bogus
extensions/sdktools/extension.cpp
extensions/sdktools/vhelpers.cpp
extensions/sdktools/vhelpers.h
extensions/sdktools/vnatives.cpp
plugins/include/sdktools_functions.inc
     1.1 --- a/extensions/sdktools/extension.cpp	Fri Oct 19 06:51:44 2007 +0000
     1.2 +++ b/extensions/sdktools/extension.cpp	Fri Oct 19 08:51:05 2007 +0000
     1.3 @@ -104,6 +104,8 @@
     1.4  
     1.5  	SH_ADD_HOOK_MEMFUNC(IServerGameDLL, LevelInit, gamedll, this, &SDKTools::LevelInit, true);
     1.6  
     1.7 +	MathLib_Init(2.2f, 2.2f, 0.0f, 2);
     1.8 +
     1.9  	return true;
    1.10  }
    1.11  
     2.1 --- a/extensions/sdktools/vhelpers.cpp	Fri Oct 19 06:51:44 2007 +0000
     2.2 +++ b/extensions/sdktools/vhelpers.cpp	Fri Oct 19 08:51:05 2007 +0000
     2.3 @@ -34,6 +34,7 @@
     2.4  
     2.5  CallHelper s_Teleport;
     2.6  CallHelper s_GetVelocity;
     2.7 +CallHelper s_EyeAngles;
     2.8  
     2.9  bool SetupTeleport()
    2.10  {
    2.11 @@ -53,7 +54,7 @@
    2.12  
    2.13  		s_Teleport.call = g_pBinTools->CreateVCall(offset, 0, 0, NULL, info, 3);
    2.14  
    2.15 -		if (s_Teleport.call)
    2.16 +		if (s_Teleport.call != NULL)
    2.17  		{
    2.18  			s_Teleport.supported = true;
    2.19  		}
    2.20 @@ -101,7 +102,7 @@
    2.21  
    2.22  		s_GetVelocity.call = g_pBinTools->CreateVCall(offset, 0, 0, NULL, info, 2);
    2.23  
    2.24 -		if (s_GetVelocity.call)
    2.25 +		if (s_GetVelocity.call != NULL)
    2.26  		{
    2.27  			s_GetVelocity.supported = true;
    2.28  		}
    2.29 @@ -130,6 +131,65 @@
    2.30  	return SetupGetVelocity();
    2.31  }
    2.32  
    2.33 +bool SetupGetEyeAngles()
    2.34 +{
    2.35 +	if (s_EyeAngles.setup)
    2.36 +	{
    2.37 +		return s_EyeAngles.supported;
    2.38 +	}
    2.39 +
    2.40 +	int offset;
    2.41 +	if (g_pGameConf->GetOffset("EyeAngles", &offset))
    2.42 +	{
    2.43 +		PassInfo info[2];
    2.44 +		info[0].flags = info[1].flags = PASSFLAG_BYVAL;
    2.45 +		info[0].size = info[1].size = sizeof(void *);
    2.46 +		info[0].type = info[1].type = PassType_Basic;
    2.47 +
    2.48 +		s_EyeAngles.call = g_pBinTools->CreateVCall(offset, 0, 0, &info[0], &info[1], 1);
    2.49 +
    2.50 +		if (s_EyeAngles.call != NULL)
    2.51 +		{
    2.52 +			s_EyeAngles.supported = true;
    2.53 +		}
    2.54 +	}
    2.55 +
    2.56 +	s_EyeAngles.setup = true;
    2.57 +
    2.58 +	return s_EyeAngles.supported;
    2.59 +}
    2.60 +
    2.61 +bool GetEyeAngles(CBaseEntity *pEntity, QAngle *pAngles)
    2.62 +{
    2.63 +	if (!IsEyeAnglesSupported())
    2.64 +	{
    2.65 +		return false;
    2.66 +	}
    2.67 +
    2.68 +	QAngle *pRetAngle = NULL;
    2.69 +	unsigned char params[sizeof(void *)];
    2.70 +	unsigned char *vptr = params;
    2.71 +
    2.72 +	*(CBaseEntity **)vptr = pEntity;
    2.73 +	vptr += sizeof(CBaseEntity *);
    2.74 +
    2.75 +	s_EyeAngles.call->Execute(params, &pRetAngle);
    2.76 +
    2.77 +	if (pRetAngle == NULL)
    2.78 +	{
    2.79 +		return false;
    2.80 +	}
    2.81 +
    2.82 +	*pAngles = *pRetAngle;
    2.83 +
    2.84 +	return true;
    2.85 +}
    2.86 +
    2.87 +bool IsEyeAnglesSupported()
    2.88 +{
    2.89 +	return SetupGetEyeAngles();
    2.90 +}
    2.91 +
    2.92  void ShutdownHelpers()
    2.93  {
    2.94  	s_Teleport.Shutdown();
     3.1 --- a/extensions/sdktools/vhelpers.h	Fri Oct 19 06:51:44 2007 +0000
     3.2 +++ b/extensions/sdktools/vhelpers.h	Fri Oct 19 08:51:05 2007 +0000
     3.3 @@ -63,6 +63,9 @@
     3.4  void GetVelocity(CBaseEntity *pEntity, Vector *velocity, AngularImpulse *angvelocity);
     3.5  bool IsGetVelocitySupported();
     3.6  
     3.7 +bool GetEyeAngles(CBaseEntity *pEntity, QAngle *pAngles);
     3.8 +bool IsEyeAnglesSupported();
     3.9 +
    3.10  void ShutdownHelpers();
    3.11  
    3.12  #endif //_INCLUDE_SDKTOOLS_VHELPERS_H_
     4.1 --- a/extensions/sdktools/vnatives.cpp	Fri Oct 19 06:51:44 2007 +0000
     4.2 +++ b/extensions/sdktools/vnatives.cpp	Fri Oct 19 08:51:05 2007 +0000
     4.3 @@ -113,6 +113,23 @@
     4.4  	return false;
     4.5  }
     4.6  
     4.7 +class CTraceFilterSimple : public CTraceFilterEntitiesOnly
     4.8 +{
     4.9 +public:
    4.10 +	CTraceFilterSimple(const IHandleEntity *passentity): m_pPassEnt(passentity)
    4.11 +	{
    4.12 +	}
    4.13 +	virtual bool ShouldHitEntity(IHandleEntity *pServerEntity, int contentsMask)
    4.14 +	{
    4.15 +		if (pServerEntity == m_pPassEnt)
    4.16 +		{
    4.17 +			return false;
    4.18 +		}
    4.19 +		return true;
    4.20 +	}
    4.21 +private:
    4.22 +	const IHandleEntity *m_pPassEnt;
    4.23 +};
    4.24  
    4.25  static cell_t RemovePlayerItem(IPluginContext *pContext, const cell_t *params)
    4.26  {
    4.27 @@ -567,31 +584,39 @@
    4.28  
    4.29  static cell_t GetClientEyeAngles(IPluginContext *pContext, const cell_t *params)
    4.30  {
    4.31 -	static ValveCall *pCall = NULL;
    4.32 -	if (!pCall)
    4.33 +	int client = params[1];
    4.34 +	IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(client);
    4.35 +
    4.36 +	if (!pPlayer)
    4.37  	{
    4.38 -		ValvePassInfo retinfo[1];
    4.39 -		InitPass(retinfo[0], Valve_POD, PassType_Basic, PASSFLAG_BYVAL);
    4.40 -		if (!CreateBaseCall("EyeAngles", ValveCall_Player, retinfo, NULL, 0, &pCall))
    4.41 -		{
    4.42 -			return pContext->ThrowNativeError("\"EyeAngles\" not supported by this mod");
    4.43 -		} else if (!pCall) {
    4.44 -			return pContext->ThrowNativeError("\"EyeAngles\" wrapper failed to initialized");
    4.45 -		}
    4.46 +		return pContext->ThrowNativeError("Invalid client index %d", client);
    4.47 +	}
    4.48 +	else if (!pPlayer->IsInGame())
    4.49 +	{
    4.50 +		return pContext->ThrowNativeError("Client %d is not in game", client);
    4.51  	}
    4.52  
    4.53 -	QAngle *ang;
    4.54 -	START_CALL();
    4.55 -	DECODE_VALVE_PARAM(1, thisinfo, 0);
    4.56 -	FINISH_CALL_SIMPLE(&ang);
    4.57 +	edict_t *pEdict = pPlayer->GetEdict();
    4.58 +	CBaseEntity *pEntity = pEdict->GetUnknown() ? pEdict->GetUnknown()->GetBaseEntity() : NULL;
    4.59 +
    4.60 +	/* We always set the angles for backwards compatibility -- 
    4.61 +	 * The original function had no return value.
    4.62 +	 */
    4.63 +	QAngle angles;
    4.64 +	bool got_angles = false;
    4.65 +
    4.66 +	if (pEntity == NULL)
    4.67 +	{
    4.68 +		got_angles = GetEyeAngles(pEntity, &angles);
    4.69 +	}
    4.70  	
    4.71  	cell_t *addr;
    4.72  	pContext->LocalToPhysAddr(params[2], &addr);
    4.73 -	addr[0] = sp_ftoc(ang->x);
    4.74 -	addr[1] = sp_ftoc(ang->y);
    4.75 -	addr[2] = sp_ftoc(ang->z);
    4.76 +	addr[0] = sp_ftoc(angles.x);
    4.77 +	addr[1] = sp_ftoc(angles.y);
    4.78 +	addr[2] = sp_ftoc(angles.z);
    4.79  
    4.80 -	return 1;
    4.81 +	return got_angles ? 1 : 0;
    4.82  }
    4.83  
    4.84  static cell_t FindEntityByClassname(IPluginContext *pContext, const cell_t *params)
    4.85 @@ -638,7 +663,8 @@
    4.86  	if (player == NULL)
    4.87  	{
    4.88  		return pContext->ThrowNativeError("Invalid client index %d", params[1]);
    4.89 -	} else if (!player->IsInGame())
    4.90 +	}
    4.91 +	else if (!player->IsInGame())
    4.92  	{
    4.93  		return pContext->ThrowNativeError("Client %d is not in game", params[1]);
    4.94  	}
    4.95 @@ -814,6 +840,78 @@
    4.96  	return (ret) ? 1 : 0;
    4.97  }
    4.98  
    4.99 +static cell_t GetClientAimTarget(IPluginContext *pContext, const cell_t *params)
   4.100 +{
   4.101 +	int client = params[1];
   4.102 +	IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(client);
   4.103 +
   4.104 +	if (!pPlayer)
   4.105 +	{
   4.106 +		return pContext->ThrowNativeError("Invalid client index %d", client);
   4.107 +	}
   4.108 +	else if (!pPlayer->IsInGame())
   4.109 +	{
   4.110 +		return pContext->ThrowNativeError("Client %d is not in game", client);
   4.111 +	}
   4.112 +
   4.113 +	edict_t *pEdict = pPlayer->GetEdict();
   4.114 +	CBaseEntity *pEntity = pEdict->GetUnknown() ? pEdict->GetUnknown()->GetBaseEntity() : NULL;
   4.115 +
   4.116 +	if (pEntity == NULL)
   4.117 +	{
   4.118 +		return -1;
   4.119 +	}
   4.120 +
   4.121 +	Vector eye_position;
   4.122 +	QAngle eye_angles;
   4.123 +	
   4.124 +	/* Get the private information we need */
   4.125 +	serverClients->ClientEarPosition(pEdict, &eye_position);
   4.126 +	if (!GetEyeAngles(pEntity, &eye_angles))
   4.127 +	{
   4.128 +		return -2;
   4.129 +	}
   4.130 +
   4.131 +	Vector aim_dir;
   4.132 +	AngleVectors(eye_angles, &aim_dir);
   4.133 +	VectorNormalize(aim_dir);
   4.134 +
   4.135 +	Vector vec_end = eye_position + aim_dir * 8000;
   4.136 +
   4.137 +	Ray_t ray;
   4.138 +	ray.Init(eye_position, vec_end);
   4.139 +
   4.140 +	trace_t tr;
   4.141 +	CTraceFilterSimple simple(pEdict->GetIServerEntity());
   4.142 +
   4.143 +	enginetrace->TraceRay(ray, MASK_SOLID|CONTENTS_DEBRIS|CONTENTS_HITBOX, &simple, &tr);
   4.144 +
   4.145 +	if (tr.fraction == 1.0f || tr.m_pEnt == NULL)
   4.146 +	{
   4.147 +		return -1;
   4.148 +	}
   4.149 +
   4.150 +	edict_t *pTarget = gameents->BaseEntityToEdict(tr.m_pEnt);
   4.151 +	if (pTarget == NULL)
   4.152 +	{
   4.153 +		return -1;
   4.154 +	}
   4.155 +
   4.156 +	int ent_index = engine->IndexOfEdict(pTarget);
   4.157 +
   4.158 +	IGamePlayer *pTargetPlayer = playerhelpers->GetGamePlayer(ent_index);
   4.159 +	if (pTargetPlayer != NULL && !pTargetPlayer->IsInGame())
   4.160 +	{
   4.161 +		return -1;
   4.162 +	}
   4.163 +	else if (params[2] && pTargetPlayer == NULL)
   4.164 +	{
   4.165 +		return -1;
   4.166 +	}
   4.167 +
   4.168 +	return ent_index;
   4.169 +}
   4.170 +
   4.171  sp_nativeinfo_t g_Natives[] = 
   4.172  {
   4.173  	{"ExtinguishPlayer",		ExtinguishEntity},
   4.174 @@ -838,5 +936,6 @@
   4.175  	{"DispatchKeyValue",		DispatchKeyValue},
   4.176  	{"DispatchKeyValueFloat",	DispatchKeyValueFloat},
   4.177  	{"DispatchKeyValueVector",	DispatchKeyValueVector},
   4.178 +	{"GetClientAimTarget",		GetClientAimTarget},
   4.179  	{NULL,						NULL},
   4.180  };
     5.1 --- a/plugins/include/sdktools_functions.inc	Fri Oct 19 06:51:44 2007 +0000
     5.2 +++ b/plugins/include/sdktools_functions.inc	Fri Oct 19 08:51:05 2007 +0000
     5.3 @@ -137,16 +137,16 @@
     5.4   *
     5.5   * @param client		Player's index.
     5.6   * @param ang			Destination vector to store the client's eye angles.
     5.7 - * @noreturn
     5.8 + * @return				True on success, false on failure.
     5.9   * @error				Invalid client index, client not in game, or no mod support.
    5.10   */
    5.11 -native GetClientEyeAngles(client, Float:ang[3]);
    5.12 +native bool:GetClientEyeAngles(client, Float:ang[3]);
    5.13  
    5.14  /**
    5.15   * Returns if the client is alive or dead.
    5.16   *
    5.17   * @param client		Player's index.
    5.18 - * @return			True if the client is alive, false otherwise.
    5.19 + * @return				True if the client is alive, false otherwise.
    5.20   * @error				Invalid client index, client not in game, or no mod support.
    5.21   */
    5.22  native bool:IsPlayerAlive(client);
    5.23 @@ -156,10 +156,10 @@
    5.24   * If ForceEdictIndex is not -1, then it will use the edict by that index. If the index is 
    5.25   *  invalid or there is already an edict using that index, it will error out.
    5.26   *
    5.27 - * @param classname		Entity classname.
    5.28 + * @param classname			Entity classname.
    5.29   * @param ForceEdictIndex	Edict index used by the created entity.
    5.30 - * @return			Entity index on success, or -1 on failure.
    5.31 - * @error			Invalid edict index, or no mod support.
    5.32 + * @return					Entity index on success, or -1 on failure.
    5.33 + * @error					Invalid edict index, or no mod support.
    5.34   */
    5.35  native CreateEntityByName(const String:classname[], ForceEdictIndex=-1);
    5.36  
    5.37 @@ -167,8 +167,8 @@
    5.38   * Spawns an entity into the game.
    5.39   *
    5.40   * @param entity		Entity index of the created entity.
    5.41 - * @return			True on success, false otherwise.
    5.42 - * @error			Invalid entity index, or no mod support.
    5.43 + * @return				True on success, false otherwise.
    5.44 + * @error				Invalid entity index, or no mod support.
    5.45   */
    5.46  native bool:DispatchSpawn(entity);
    5.47  
    5.48 @@ -178,8 +178,8 @@
    5.49   * @param entity		Destination entity index.
    5.50   * @param keyName		Name of the key.
    5.51   * @param value			String value.
    5.52 - * @return			True on success, false otherwise.
    5.53 - * @error			Invalid entity index, or no mod support.
    5.54 + * @return				True on success, false otherwise.
    5.55 + * @error				Invalid entity index, or no mod support.
    5.56   */
    5.57  native bool:DispatchKeyValue(entity, const String:keyName[], const String:value[]);
    5.58  
    5.59 @@ -189,8 +189,8 @@
    5.60   * @param entity		Destination entity index.
    5.61   * @param keyName		Name of the key.
    5.62   * @param value			Floating point value.
    5.63 - * @return			True on success, false otherwise.
    5.64 - * @error			Invalid entity index, or no mod support.
    5.65 + * @return				True on success, false otherwise.
    5.66 + * @error				Invalid entity index, or no mod support.
    5.67   */
    5.68  native bool:DispatchKeyValueFloat(entity, const String:keyName[], Float:value);
    5.69  
    5.70 @@ -200,12 +200,24 @@
    5.71   * @param entity		Destination entity index.
    5.72   * @param keyName		Name of the key.
    5.73   * @param vec			Vector value.
    5.74 - * @return			True on success, false otherwise.
    5.75 - * @error			Invalid entity index, or no mod support.
    5.76 + * @return				True on success, false otherwise.
    5.77 + * @error				Invalid entity index, or no mod support.
    5.78   */
    5.79  native bool:DispatchKeyValueVector(entity, const String:keyName[], const Float:vector[3]);
    5.80  
    5.81  /**
    5.82 + * Returns the entity a client is aiming at.
    5.83 + *
    5.84 + * @param client		Client performing the aiming.
    5.85 + * @param only_clients	True to exclude all entities but clients.
    5.86 + * @return				Entity index being aimed at.
    5.87 + *						-1 if no entity is being aimed at.
    5.88 + * 						-2 if the function is not supported.
    5.89 + * @error				Invalid client index.
    5.90 + */
    5.91 +native GetClientAimTarget(client, bool:only_clients=true);
    5.92 +
    5.93 +/**
    5.94   * @deprecated
    5.95   */
    5.96  #pragma deprecated Use IgniteEntity() instead