1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/extensions/sdktools/trnatives.cpp Sun Mar 30 07:00:22 2008 +0000
1.3 @@ -0,0 +1,444 @@
1.4 +/**
1.5 + * vim: set ts=4 :
1.6 + * =============================================================================
1.7 + * SourceMod SDKTools Extension
1.8 + * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
1.9 + * =============================================================================
1.10 + *
1.11 + * This program is free software; you can redistribute it and/or modify it under
1.12 + * the terms of the GNU General Public License, version 3.0, as published by the
1.13 + * Free Software Foundation.
1.14 + *
1.15 + * This program is distributed in the hope that it will be useful, but WITHOUT
1.16 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
1.18 + * details.
1.19 + *
1.20 + * You should have received a copy of the GNU General Public License along with
1.21 + * this program. If not, see <http://www.gnu.org/licenses/>.
1.22 + *
1.23 + * As a special exception, AlliedModders LLC gives you permission to link the
1.24 + * code of this program (as well as its derivative works) to "Half-Life 2," the
1.25 + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
1.26 + * by the Valve Corporation. You must obey the GNU General Public License in
1.27 + * all respects for all other code used. Additionally, AlliedModders LLC grants
1.28 + * this exception to all derivative works. AlliedModders LLC defines further
1.29 + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
1.30 + * or <http://www.sourcemod.net/license.php>.
1.31 + *
1.32 + * Version: $Id$
1.33 + */
1.34 +
1.35 +#include "extension.h"
1.36 +#include <worldsize.h>
1.37 +
1.38 +class CSMTraceFilter : public CTraceFilter
1.39 +{
1.40 +public:
1.41 + bool ShouldHitEntity(IHandleEntity *pEntity, int contentsMask)
1.42 + {
1.43 + cell_t res = 1;
1.44 + edict_t *pEdict = gameents->BaseEntityToEdict(reinterpret_cast<CBaseEntity *>(pEntity));
1.45 + m_pFunc->PushCell(engine->IndexOfEdict(pEdict));
1.46 + m_pFunc->PushCell(contentsMask);
1.47 + m_pFunc->PushCell(m_Data);
1.48 + m_pFunc->Execute(&res);
1.49 +
1.50 + return (res) ? true : false;
1.51 + }
1.52 + void SetFunctionPtr(IPluginFunction *pFunc, cell_t data)
1.53 + {
1.54 + m_pFunc = pFunc;
1.55 + m_Data = data;
1.56 + }
1.57 +private:
1.58 + IPluginFunction *m_pFunc;
1.59 + cell_t m_Data;
1.60 +};
1.61 +
1.62 +/* Used for the global trace version */
1.63 +Ray_t g_Ray;
1.64 +trace_t g_Trace;
1.65 +Vector g_StartVec;
1.66 +Vector g_EndVec;
1.67 +QAngle g_DirAngles;
1.68 +CTraceFilterHitAll g_HitAllFilter;
1.69 +CSMTraceFilter g_SMTraceFilter;
1.70 +
1.71 +enum
1.72 +{
1.73 + RayType_EndPoint,
1.74 + RayType_Infinite
1.75 +};
1.76 +
1.77 +static cell_t smn_TRTraceRay(IPluginContext *pContext, const cell_t *params)
1.78 +{
1.79 + cell_t *startaddr, *endaddr;
1.80 + pContext->LocalToPhysAddr(params[1], &startaddr);
1.81 + pContext->LocalToPhysAddr(params[2], &endaddr);
1.82 +
1.83 + g_StartVec.Init(sp_ctof(startaddr[0]), sp_ctof(startaddr[1]), sp_ctof(startaddr[2]));
1.84 +
1.85 + switch (params[4])
1.86 + {
1.87 + case RayType_EndPoint:
1.88 + {
1.89 + g_EndVec.Init(sp_ctof(endaddr[0]), sp_ctof(endaddr[1]), sp_ctof(endaddr[2]));
1.90 + break;
1.91 + }
1.92 + case RayType_Infinite:
1.93 + {
1.94 + g_DirAngles.Init(sp_ctof(endaddr[0]), sp_ctof(endaddr[1]), sp_ctof(endaddr[2]));
1.95 + AngleVectors(g_DirAngles, &g_EndVec);
1.96 +
1.97 + /* Make it unitary and get the ending point */
1.98 + g_EndVec.NormalizeInPlace();
1.99 + g_EndVec = g_StartVec + g_EndVec * MAX_TRACE_LENGTH;
1.100 + break;
1.101 + }
1.102 + }
1.103 +
1.104 + g_Ray.Init(g_StartVec, g_EndVec);
1.105 + enginetrace->TraceRay(g_Ray, params[3], &g_HitAllFilter, &g_Trace);
1.106 +
1.107 + return 1;
1.108 +}
1.109 +
1.110 +static cell_t smn_TRTraceRayFilter(IPluginContext *pContext, const cell_t *params)
1.111 +{
1.112 + cell_t *startaddr, *endaddr;
1.113 + IPluginFunction *pFunc;
1.114 + cell_t data;
1.115 +
1.116 + pFunc = pContext->GetFunctionById(params[5]);
1.117 + if (!pFunc)
1.118 + {
1.119 + return pContext->ThrowNativeError("Invalid function id (%X)", params[5]);
1.120 + }
1.121 +
1.122 + if (params[0] >= 6)
1.123 + {
1.124 + data = params[6];
1.125 + }
1.126 + else
1.127 + {
1.128 + data = 0;
1.129 + }
1.130 +
1.131 + g_SMTraceFilter.SetFunctionPtr(pFunc, data);
1.132 + pContext->LocalToPhysAddr(params[1], &startaddr);
1.133 + pContext->LocalToPhysAddr(params[2], &endaddr);
1.134 +
1.135 + g_StartVec.Init(sp_ctof(startaddr[0]), sp_ctof(startaddr[1]), sp_ctof(startaddr[2]));
1.136 +
1.137 + switch (params[4])
1.138 + {
1.139 + case RayType_EndPoint:
1.140 + {
1.141 + g_EndVec.Init(sp_ctof(endaddr[0]), sp_ctof(endaddr[1]), sp_ctof(endaddr[2]));
1.142 + break;
1.143 + }
1.144 + case RayType_Infinite:
1.145 + {
1.146 + g_DirAngles.Init(sp_ctof(endaddr[0]), sp_ctof(endaddr[1]), sp_ctof(endaddr[2]));
1.147 + AngleVectors(g_DirAngles, &g_EndVec);
1.148 +
1.149 + /* Make it unitary and get the ending point */
1.150 + g_EndVec.NormalizeInPlace();
1.151 + g_EndVec = g_StartVec + g_EndVec * MAX_TRACE_LENGTH;
1.152 + break;
1.153 + }
1.154 + }
1.155 +
1.156 + g_Ray.Init(g_StartVec, g_EndVec);
1.157 + enginetrace->TraceRay(g_Ray, params[3], &g_SMTraceFilter, &g_Trace);
1.158 +
1.159 + return 1;
1.160 +}
1.161 +
1.162 +static cell_t smn_TRTraceRayEx(IPluginContext *pContext, const cell_t *params)
1.163 +{
1.164 + cell_t *startaddr, *endaddr;
1.165 + pContext->LocalToPhysAddr(params[1], &startaddr);
1.166 + pContext->LocalToPhysAddr(params[2], &endaddr);
1.167 +
1.168 + Vector StartVec, EndVec;
1.169 + Ray_t ray;
1.170 +
1.171 + StartVec.Init(sp_ctof(startaddr[0]), sp_ctof(startaddr[1]), sp_ctof(startaddr[2]));
1.172 +
1.173 + switch (params[4])
1.174 + {
1.175 + case RayType_EndPoint:
1.176 + {
1.177 + EndVec.Init(sp_ctof(endaddr[0]), sp_ctof(endaddr[1]), sp_ctof(endaddr[2]));
1.178 + break;
1.179 + }
1.180 + case RayType_Infinite:
1.181 + {
1.182 + QAngle DirAngles;
1.183 + DirAngles.Init(sp_ctof(endaddr[0]), sp_ctof(endaddr[1]), sp_ctof(endaddr[2]));
1.184 + AngleVectors(DirAngles, &EndVec);
1.185 +
1.186 + /* Make it unitary and get the ending point */
1.187 + EndVec.NormalizeInPlace();
1.188 + EndVec = StartVec + EndVec * MAX_TRACE_LENGTH;
1.189 + break;
1.190 + }
1.191 + }
1.192 +
1.193 + trace_t *tr = new trace_t;
1.194 + ray.Init(StartVec, EndVec);
1.195 + enginetrace->TraceRay(ray, params[3], &g_HitAllFilter, tr);
1.196 +
1.197 + HandleError herr;
1.198 + Handle_t hndl;
1.199 + if (!(hndl=handlesys->CreateHandle(g_TraceHandle, tr, pContext->GetIdentity(), myself->GetIdentity(), &herr)))
1.200 + {
1.201 + delete tr;
1.202 + return pContext->ThrowNativeError("Unable to create a new trace handle (error %d)", herr);
1.203 + }
1.204 +
1.205 + return hndl;
1.206 +}
1.207 +
1.208 +static cell_t smn_TRTraceRayFilterEx(IPluginContext *pContext, const cell_t *params)
1.209 +{
1.210 + IPluginFunction *pFunc;
1.211 + cell_t *startaddr, *endaddr;
1.212 + cell_t data;
1.213 +
1.214 + pFunc = pContext->GetFunctionById(params[5]);
1.215 + if (!pFunc)
1.216 + {
1.217 + return pContext->ThrowNativeError("Invalid function id (%X)", params[5]);
1.218 + }
1.219 + pContext->LocalToPhysAddr(params[1], &startaddr);
1.220 + pContext->LocalToPhysAddr(params[2], &endaddr);
1.221 +
1.222 + Vector StartVec, EndVec;
1.223 + CSMTraceFilter smfilter;
1.224 + Ray_t ray;
1.225 +
1.226 + if (params[0] >= 6)
1.227 + {
1.228 + data = params[6];
1.229 + }
1.230 + else
1.231 + {
1.232 + data = 0;
1.233 + }
1.234 +
1.235 + smfilter.SetFunctionPtr(pFunc, data);
1.236 + StartVec.Init(sp_ctof(startaddr[0]), sp_ctof(startaddr[1]), sp_ctof(startaddr[2]));
1.237 +
1.238 + switch (params[4])
1.239 + {
1.240 + case RayType_EndPoint:
1.241 + {
1.242 + EndVec.Init(sp_ctof(endaddr[0]), sp_ctof(endaddr[1]), sp_ctof(endaddr[2]));
1.243 + break;
1.244 + }
1.245 + case RayType_Infinite:
1.246 + {
1.247 + QAngle DirAngles;
1.248 + DirAngles.Init(sp_ctof(endaddr[0]), sp_ctof(endaddr[1]), sp_ctof(endaddr[2]));
1.249 + AngleVectors(DirAngles, &EndVec);
1.250 +
1.251 + /* Make it unitary and get the ending point */
1.252 + EndVec.NormalizeInPlace();
1.253 + EndVec = StartVec + EndVec * MAX_TRACE_LENGTH;
1.254 + break;
1.255 + }
1.256 + }
1.257 +
1.258 + trace_t *tr = new trace_t;
1.259 + ray.Init(StartVec, EndVec);
1.260 + enginetrace->TraceRay(ray, params[3], &smfilter, tr);
1.261 +
1.262 + HandleError herr;
1.263 + Handle_t hndl;
1.264 + if (!(hndl=handlesys->CreateHandle(g_TraceHandle, tr, pContext->GetIdentity(), myself->GetIdentity(), &herr)))
1.265 + {
1.266 + delete tr;
1.267 + return pContext->ThrowNativeError("Unable to create a new trace handle (error %d)", herr);
1.268 + }
1.269 +
1.270 + return hndl;
1.271 +}
1.272 +
1.273 +static cell_t smn_TRGetFraction(IPluginContext *pContext, const cell_t *params)
1.274 +{
1.275 + trace_t *tr;
1.276 + HandleError err;
1.277 + HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
1.278 +
1.279 + if (params[1] == BAD_HANDLE)
1.280 + {
1.281 + tr = &g_Trace;
1.282 + } else if ((err = handlesys->ReadHandle(params[1], g_TraceHandle, &sec, (void **)&tr)) != HandleError_None) {
1.283 + return pContext->ThrowNativeError("Invalid Handle %x (error %d)", params[1], err);
1.284 + }
1.285 +
1.286 + return sp_ftoc(tr->fraction);
1.287 +}
1.288 +
1.289 +static cell_t smn_TRGetPlaneNormal(IPluginContext *pContext, const cell_t *params)
1.290 +{
1.291 + trace_t *tr;
1.292 + HandleError err;
1.293 + HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
1.294 +
1.295 + if (params[1] == BAD_HANDLE)
1.296 + {
1.297 + tr = &g_Trace;
1.298 + } else if ((err = handlesys->ReadHandle(params[1], g_TraceHandle, &sec, (void **)&tr)) != HandleError_None) {
1.299 + return pContext->ThrowNativeError("Invalid Handle %x (error %d)", params[1], err);
1.300 + }
1.301 +
1.302 + Vector *normal = &tr->plane.normal;
1.303 +
1.304 + cell_t *r;
1.305 + pContext->LocalToPhysAddr(params[2], &r);
1.306 + r[0] = sp_ftoc(normal->x);
1.307 + r[1] = sp_ftoc(normal->y);
1.308 + r[2] = sp_ftoc(normal->z);
1.309 +
1.310 + return 1;
1.311 +}
1.312 +
1.313 +
1.314 +static cell_t smn_TRGetEndPosition(IPluginContext *pContext, const cell_t *params)
1.315 +{
1.316 + trace_t *tr;
1.317 + HandleError err;
1.318 + HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
1.319 +
1.320 + if (params[2] == BAD_HANDLE)
1.321 + {
1.322 + tr = &g_Trace;
1.323 + } else if ((err = handlesys->ReadHandle(params[2], g_TraceHandle, &sec, (void **)&tr)) != HandleError_None) {
1.324 + return pContext->ThrowNativeError("Invalid Handle %x (error %d)", params[2], err);
1.325 + }
1.326 +
1.327 + cell_t *addr;
1.328 + pContext->LocalToPhysAddr(params[1], &addr);
1.329 +
1.330 + addr[0] = sp_ftoc(tr->endpos.x);
1.331 + addr[1] = sp_ftoc(tr->endpos.y);
1.332 + addr[2] = sp_ftoc(tr->endpos.z);
1.333 +
1.334 + return 1;
1.335 +}
1.336 +
1.337 +static cell_t smn_TRDidHit(IPluginContext *pContext, const cell_t *params)
1.338 +{
1.339 + trace_t *tr;
1.340 + HandleError err;
1.341 + HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
1.342 +
1.343 + if (params[1] == BAD_HANDLE)
1.344 + {
1.345 + tr = &g_Trace;
1.346 + } else if ((err = handlesys->ReadHandle(params[1], g_TraceHandle, &sec, (void **)&tr)) != HandleError_None) {
1.347 + return pContext->ThrowNativeError("Invalid Handle %x (error %d)", params[1], err);
1.348 + }
1.349 +
1.350 + return tr->DidHit() ? 1 : 0;
1.351 +}
1.352 +
1.353 +static cell_t smn_TRGetHitGroup(IPluginContext *pContext, const cell_t *params)
1.354 +{
1.355 + trace_t *tr;
1.356 + HandleError err;
1.357 + HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
1.358 +
1.359 + if (params[1] == BAD_HANDLE)
1.360 + {
1.361 + tr = &g_Trace;
1.362 + } else if ((err = handlesys->ReadHandle(params[1], g_TraceHandle, &sec, (void **)&tr)) != HandleError_None) {
1.363 + return pContext->ThrowNativeError("Invalid Handle %x (error %d)", params[1], err);
1.364 + }
1.365 +
1.366 + return tr->hitgroup;
1.367 +}
1.368 +
1.369 +static cell_t smn_TRGetEntityIndex(IPluginContext *pContext, const cell_t *params)
1.370 +{
1.371 + trace_t *tr;
1.372 + HandleError err;
1.373 + HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
1.374 +
1.375 + if (params[1] == BAD_HANDLE)
1.376 + {
1.377 + tr = &g_Trace;
1.378 + } else if ((err = handlesys->ReadHandle(params[1], g_TraceHandle, &sec, (void **)&tr)) != HandleError_None) {
1.379 + return pContext->ThrowNativeError("Invalid Handle %x (error %d)", params[1], err);
1.380 + }
1.381 +
1.382 + edict_t *pEdict = gameents->BaseEntityToEdict(tr->m_pEnt);
1.383 + return engine->IndexOfEdict(pEdict);
1.384 +}
1.385 +
1.386 +static cell_t smn_TRGetPointContents(IPluginContext *pContext, const cell_t *params)
1.387 +{
1.388 + cell_t *vec, *ent;
1.389 + IHandleEntity *hentity;
1.390 + Vector pos;
1.391 + int mask;
1.392 +
1.393 + pContext->LocalToPhysAddr(params[1], &vec);
1.394 + pContext->LocalToPhysAddr(params[2], &ent);
1.395 +
1.396 + pos.x = sp_ctof(vec[0]);
1.397 + pos.y = sp_ctof(vec[1]);
1.398 + pos.z = sp_ctof(vec[2]);
1.399 +
1.400 + if (*ent == -1)
1.401 + {
1.402 + mask = enginetrace->GetPointContents(pos);
1.403 + } else {
1.404 + mask = enginetrace->GetPointContents(pos, &hentity);
1.405 + edict_t *pEdict = gameents->BaseEntityToEdict(reinterpret_cast<CBaseEntity *>(hentity));
1.406 + *ent = engine->IndexOfEdict(pEdict);
1.407 + }
1.408 +
1.409 + return mask;
1.410 +}
1.411 +
1.412 +static cell_t smn_TRGetPointContentsEnt(IPluginContext *pContext, const cell_t *params)
1.413 +{
1.414 + edict_t *pEdict = engine->PEntityOfEntIndex(params[1]);
1.415 + if (!pEdict || pEdict->IsFree())
1.416 + {
1.417 + return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
1.418 + }
1.419 +
1.420 + cell_t *addr;
1.421 + Vector pos;
1.422 +
1.423 + pContext->LocalToPhysAddr(params[2], &addr);
1.424 +
1.425 + pos.x = sp_ctof(addr[0]);
1.426 + pos.y = sp_ctof(addr[1]);
1.427 + pos.z = sp_ctof(addr[2]);
1.428 +
1.429 + return enginetrace->GetPointContents_Collideable(pEdict->GetCollideable(), pos);
1.430 +}
1.431 +
1.432 +sp_nativeinfo_t g_TRNatives[] =
1.433 +{
1.434 + {"TR_TraceRay", smn_TRTraceRay},
1.435 + {"TR_TraceRayEx", smn_TRTraceRayEx},
1.436 + {"TR_GetFraction", smn_TRGetFraction},
1.437 + {"TR_GetEndPosition", smn_TRGetEndPosition},
1.438 + {"TR_GetEntityIndex", smn_TRGetEntityIndex},
1.439 + {"TR_DidHit", smn_TRDidHit},
1.440 + {"TR_GetHitGroup", smn_TRGetHitGroup},
1.441 + {"TR_GetPointContents", smn_TRGetPointContents},
1.442 + {"TR_GetPointContentsEnt", smn_TRGetPointContentsEnt},
1.443 + {"TR_TraceRayFilter", smn_TRTraceRayFilter},
1.444 + {"TR_TraceRayFilterEx", smn_TRTraceRayFilterEx},
1.445 + {"TR_GetPlaneNormal", smn_TRGetPlaneNormal},
1.446 + {NULL, NULL}
1.447 +};