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