3 * =============================================================================
4 * SourceMod SDKTools Extension
5 * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
6 * =============================================================================
8 * This program is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License, version 3.0, as published by the
10 * Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
17 * You should have received a copy of the GNU General Public License along with
18 * this program. If not, see <http://www.gnu.org/licenses/>.
20 * As a special exception, AlliedModders LLC gives you permission to link the
21 * code of this program (as well as its derivative works) to "Half-Life 2," the
22 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
23 * by the Valve Corporation. You must obey the GNU General Public License in
24 * all respects for all other code used. Additionally, AlliedModders LLC grants
25 * this exception to all derivative works. AlliedModders LLC defines further
26 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
27 * or <http://www.sourcemod.net/license.php>.
32 #include "extension.h"
33 #include <worldsize.h>
35 class CSMTraceFilter : public CTraceFilter
38 bool ShouldHitEntity(IHandleEntity *pEntity, int contentsMask)
41 edict_t *pEdict = gameents->BaseEntityToEdict(reinterpret_cast<CBaseEntity *>(pEntity));
42 m_pFunc->PushCell(IndexOfEdict(pEdict));
43 m_pFunc->PushCell(contentsMask);
44 m_pFunc->PushCell(m_Data);
45 m_pFunc->Execute(&res);
47 return (res) ? true : false;
49 void SetFunctionPtr(IPluginFunction *pFunc, cell_t data)
55 IPluginFunction *m_pFunc;
59 /* Used for the global trace version */
67 CTraceFilterHitAll g_HitAllFilter;
68 CSMTraceFilter g_SMTraceFilter;
76 static cell_t smn_TRTraceRay(IPluginContext *pContext, const cell_t *params)
78 cell_t *startaddr, *endaddr;
79 pContext->LocalToPhysAddr(params[1], &startaddr);
80 pContext->LocalToPhysAddr(params[2], &endaddr);
82 g_StartVec.Init(sp_ctof(startaddr[0]), sp_ctof(startaddr[1]), sp_ctof(startaddr[2]));
86 case RayType_EndPoint:
88 g_EndVec.Init(sp_ctof(endaddr[0]), sp_ctof(endaddr[1]), sp_ctof(endaddr[2]));
91 case RayType_Infinite:
93 g_DirAngles.Init(sp_ctof(endaddr[0]), sp_ctof(endaddr[1]), sp_ctof(endaddr[2]));
94 AngleVectors(g_DirAngles, &g_EndVec);
96 /* Make it unitary and get the ending point */
97 g_EndVec.NormalizeInPlace();
98 g_EndVec = g_StartVec + g_EndVec * MAX_TRACE_LENGTH;
103 g_Ray.Init(g_StartVec, g_EndVec);
104 enginetrace->TraceRay(g_Ray, params[3], &g_HitAllFilter, &g_Trace);
109 static cell_t smn_TRTraceHull(IPluginContext *pContext, const cell_t *params)
111 cell_t *startaddr, *endaddr, *mins, *maxs;
112 pContext->LocalToPhysAddr(params[1], &startaddr);
113 pContext->LocalToPhysAddr(params[2], &endaddr);
114 pContext->LocalToPhysAddr(params[3], &mins);
115 pContext->LocalToPhysAddr(params[4], &maxs);
117 g_StartVec.Init(sp_ctof(startaddr[0]), sp_ctof(startaddr[1]), sp_ctof(startaddr[2]));
118 g_HullMins.Init(sp_ctof(mins[0]), sp_ctof(mins[1]), sp_ctof(mins[2]));
119 g_HullMaxs.Init(sp_ctof(maxs[0]), sp_ctof(maxs[1]), sp_ctof(maxs[2]));
120 g_EndVec.Init(sp_ctof(endaddr[0]), sp_ctof(endaddr[1]), sp_ctof(endaddr[2]));
122 g_Ray.Init(g_StartVec, g_EndVec, g_HullMins, g_HullMaxs);
123 enginetrace->TraceRay(g_Ray, params[5], &g_HitAllFilter, &g_Trace);
128 static cell_t smn_TRTraceRayFilter(IPluginContext *pContext, const cell_t *params)
130 cell_t *startaddr, *endaddr;
131 IPluginFunction *pFunc;
134 pFunc = pContext->GetFunctionById(params[5]);
137 return pContext->ThrowNativeError("Invalid function id (%X)", params[5]);
149 g_SMTraceFilter.SetFunctionPtr(pFunc, data);
150 pContext->LocalToPhysAddr(params[1], &startaddr);
151 pContext->LocalToPhysAddr(params[2], &endaddr);
153 g_StartVec.Init(sp_ctof(startaddr[0]), sp_ctof(startaddr[1]), sp_ctof(startaddr[2]));
157 case RayType_EndPoint:
159 g_EndVec.Init(sp_ctof(endaddr[0]), sp_ctof(endaddr[1]), sp_ctof(endaddr[2]));
162 case RayType_Infinite:
164 g_DirAngles.Init(sp_ctof(endaddr[0]), sp_ctof(endaddr[1]), sp_ctof(endaddr[2]));
165 AngleVectors(g_DirAngles, &g_EndVec);
167 /* Make it unitary and get the ending point */
168 g_EndVec.NormalizeInPlace();
169 g_EndVec = g_StartVec + g_EndVec * MAX_TRACE_LENGTH;
174 g_Ray.Init(g_StartVec, g_EndVec);
175 enginetrace->TraceRay(g_Ray, params[3], &g_SMTraceFilter, &g_Trace);
180 static cell_t smn_TRTraceHullFilter(IPluginContext *pContext, const cell_t *params)
183 IPluginFunction *pFunc;
184 cell_t *startaddr, *endaddr, *mins, *maxs;
186 pFunc = pContext->GetFunctionById(params[6]);
189 return pContext->ThrowNativeError("Invalid function id (%X)", params[5]);
194 g_SMTraceFilter.SetFunctionPtr(pFunc, data);
195 pContext->LocalToPhysAddr(params[1], &startaddr);
196 pContext->LocalToPhysAddr(params[2], &endaddr);
197 pContext->LocalToPhysAddr(params[3], &mins);
198 pContext->LocalToPhysAddr(params[4], &maxs);
200 g_StartVec.Init(sp_ctof(startaddr[0]), sp_ctof(startaddr[1]), sp_ctof(startaddr[2]));
201 g_HullMins.Init(sp_ctof(mins[0]), sp_ctof(mins[1]), sp_ctof(mins[2]));
202 g_HullMaxs.Init(sp_ctof(maxs[0]), sp_ctof(maxs[1]), sp_ctof(maxs[2]));
203 g_EndVec.Init(sp_ctof(endaddr[0]), sp_ctof(endaddr[1]), sp_ctof(endaddr[2]));
205 g_Ray.Init(g_StartVec, g_EndVec, g_HullMins, g_HullMaxs);
206 enginetrace->TraceRay(g_Ray, params[5], &g_SMTraceFilter, &g_Trace);
212 static cell_t smn_TRTraceRayEx(IPluginContext *pContext, const cell_t *params)
214 cell_t *startaddr, *endaddr;
215 pContext->LocalToPhysAddr(params[1], &startaddr);
216 pContext->LocalToPhysAddr(params[2], &endaddr);
218 Vector StartVec, EndVec;
221 StartVec.Init(sp_ctof(startaddr[0]), sp_ctof(startaddr[1]), sp_ctof(startaddr[2]));
225 case RayType_EndPoint:
227 EndVec.Init(sp_ctof(endaddr[0]), sp_ctof(endaddr[1]), sp_ctof(endaddr[2]));
230 case RayType_Infinite:
233 DirAngles.Init(sp_ctof(endaddr[0]), sp_ctof(endaddr[1]), sp_ctof(endaddr[2]));
234 AngleVectors(DirAngles, &EndVec);
236 /* Make it unitary and get the ending point */
237 EndVec.NormalizeInPlace();
238 EndVec = StartVec + EndVec * MAX_TRACE_LENGTH;
243 trace_t *tr = new trace_t;
244 ray.Init(StartVec, EndVec);
245 enginetrace->TraceRay(ray, params[3], &g_HitAllFilter, tr);
249 if (!(hndl=handlesys->CreateHandle(g_TraceHandle, tr, pContext->GetIdentity(), myself->GetIdentity(), &herr)))
252 return pContext->ThrowNativeError("Unable to create a new trace handle (error %d)", herr);
258 static cell_t smn_TRTraceHullEx(IPluginContext *pContext, const cell_t *params)
260 cell_t *startaddr, *endaddr, *mins, *maxs;
261 pContext->LocalToPhysAddr(params[1], &startaddr);
262 pContext->LocalToPhysAddr(params[2], &endaddr);
263 pContext->LocalToPhysAddr(params[3], &mins);
264 pContext->LocalToPhysAddr(params[4], &maxs);
267 Vector StartVec, EndVec, vmins, vmaxs;
269 StartVec.Init(sp_ctof(startaddr[0]), sp_ctof(startaddr[1]), sp_ctof(startaddr[2]));
270 vmins.Init(sp_ctof(mins[0]), sp_ctof(mins[1]), sp_ctof(mins[2]));
271 vmaxs.Init(sp_ctof(maxs[0]), sp_ctof(maxs[1]), sp_ctof(maxs[2]));
272 EndVec.Init(sp_ctof(endaddr[0]), sp_ctof(endaddr[1]), sp_ctof(endaddr[2]));
274 ray.Init(StartVec, EndVec, vmins, vmaxs);
276 trace_t *tr = new trace_t;
277 enginetrace->TraceRay(ray, params[5], &g_HitAllFilter, tr);
281 if (!(hndl=handlesys->CreateHandle(g_TraceHandle, tr, pContext->GetIdentity(), myself->GetIdentity(), &herr)))
284 return pContext->ThrowNativeError("Unable to create a new trace handle (error %d)", herr);
290 static cell_t smn_TRTraceRayFilterEx(IPluginContext *pContext, const cell_t *params)
292 IPluginFunction *pFunc;
293 cell_t *startaddr, *endaddr;
296 pFunc = pContext->GetFunctionById(params[5]);
299 return pContext->ThrowNativeError("Invalid function id (%X)", params[5]);
301 pContext->LocalToPhysAddr(params[1], &startaddr);
302 pContext->LocalToPhysAddr(params[2], &endaddr);
304 Vector StartVec, EndVec;
305 CSMTraceFilter smfilter;
317 smfilter.SetFunctionPtr(pFunc, data);
318 StartVec.Init(sp_ctof(startaddr[0]), sp_ctof(startaddr[1]), sp_ctof(startaddr[2]));
322 case RayType_EndPoint:
324 EndVec.Init(sp_ctof(endaddr[0]), sp_ctof(endaddr[1]), sp_ctof(endaddr[2]));
327 case RayType_Infinite:
330 DirAngles.Init(sp_ctof(endaddr[0]), sp_ctof(endaddr[1]), sp_ctof(endaddr[2]));
331 AngleVectors(DirAngles, &EndVec);
333 /* Make it unitary and get the ending point */
334 EndVec.NormalizeInPlace();
335 EndVec = StartVec + EndVec * MAX_TRACE_LENGTH;
340 trace_t *tr = new trace_t;
341 ray.Init(StartVec, EndVec);
342 enginetrace->TraceRay(ray, params[3], &smfilter, tr);
346 if (!(hndl=handlesys->CreateHandle(g_TraceHandle, tr, pContext->GetIdentity(), myself->GetIdentity(), &herr)))
349 return pContext->ThrowNativeError("Unable to create a new trace handle (error %d)", herr);
355 static cell_t smn_TRTraceHullFilterEx(IPluginContext *pContext, const cell_t *params)
357 IPluginFunction *pFunc;
358 cell_t *startaddr, *endaddr, *mins, *maxs;
361 pFunc = pContext->GetFunctionById(params[6]);
364 return pContext->ThrowNativeError("Invalid function id (%X)", params[5]);
366 pContext->LocalToPhysAddr(params[1], &startaddr);
367 pContext->LocalToPhysAddr(params[2], &endaddr);
368 pContext->LocalToPhysAddr(params[3], &mins);
369 pContext->LocalToPhysAddr(params[4], &maxs);
371 Vector StartVec, EndVec, vmins, vmaxs;
372 CSMTraceFilter smfilter;
377 smfilter.SetFunctionPtr(pFunc, data);
378 StartVec.Init(sp_ctof(startaddr[0]), sp_ctof(startaddr[1]), sp_ctof(startaddr[2]));
379 vmins.Init(sp_ctof(mins[0]), sp_ctof(mins[1]), sp_ctof(mins[2]));
380 vmaxs.Init(sp_ctof(maxs[0]), sp_ctof(maxs[1]), sp_ctof(maxs[2]));
381 EndVec.Init(sp_ctof(endaddr[0]), sp_ctof(endaddr[1]), sp_ctof(endaddr[2]));
383 ray.Init(StartVec, EndVec, vmins, vmaxs);
385 trace_t *tr = new trace_t;
386 enginetrace->TraceRay(ray, params[5], &smfilter, tr);
390 if (!(hndl=handlesys->CreateHandle(g_TraceHandle, tr, pContext->GetIdentity(), myself->GetIdentity(), &herr)))
393 return pContext->ThrowNativeError("Unable to create a new trace handle (error %d)", herr);
399 static cell_t smn_TRGetFraction(IPluginContext *pContext, const cell_t *params)
403 HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
405 if (params[1] == BAD_HANDLE)
408 } else if ((err = handlesys->ReadHandle(params[1], g_TraceHandle, &sec, (void **)&tr)) != HandleError_None) {
409 return pContext->ThrowNativeError("Invalid Handle %x (error %d)", params[1], err);
412 return sp_ftoc(tr->fraction);
415 static cell_t smn_TRGetPlaneNormal(IPluginContext *pContext, const cell_t *params)
419 HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
421 if (params[1] == BAD_HANDLE)
424 } else if ((err = handlesys->ReadHandle(params[1], g_TraceHandle, &sec, (void **)&tr)) != HandleError_None) {
425 return pContext->ThrowNativeError("Invalid Handle %x (error %d)", params[1], err);
428 Vector *normal = &tr->plane.normal;
431 pContext->LocalToPhysAddr(params[2], &r);
432 r[0] = sp_ftoc(normal->x);
433 r[1] = sp_ftoc(normal->y);
434 r[2] = sp_ftoc(normal->z);
440 static cell_t smn_TRGetEndPosition(IPluginContext *pContext, const cell_t *params)
444 HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
446 if (params[2] == BAD_HANDLE)
449 } else if ((err = handlesys->ReadHandle(params[2], g_TraceHandle, &sec, (void **)&tr)) != HandleError_None) {
450 return pContext->ThrowNativeError("Invalid Handle %x (error %d)", params[2], err);
454 pContext->LocalToPhysAddr(params[1], &addr);
456 addr[0] = sp_ftoc(tr->endpos.x);
457 addr[1] = sp_ftoc(tr->endpos.y);
458 addr[2] = sp_ftoc(tr->endpos.z);
463 static cell_t smn_TRDidHit(IPluginContext *pContext, const cell_t *params)
467 HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
469 if (params[1] == BAD_HANDLE)
472 } else if ((err = handlesys->ReadHandle(params[1], g_TraceHandle, &sec, (void **)&tr)) != HandleError_None) {
473 return pContext->ThrowNativeError("Invalid Handle %x (error %d)", params[1], err);
476 return tr->DidHit() ? 1 : 0;
479 static cell_t smn_TRGetHitGroup(IPluginContext *pContext, const cell_t *params)
483 HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
485 if (params[1] == BAD_HANDLE)
488 } else if ((err = handlesys->ReadHandle(params[1], g_TraceHandle, &sec, (void **)&tr)) != HandleError_None) {
489 return pContext->ThrowNativeError("Invalid Handle %x (error %d)", params[1], err);
495 static cell_t smn_TRGetEntityIndex(IPluginContext *pContext, const cell_t *params)
499 HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
501 if (params[1] == BAD_HANDLE)
504 } else if ((err = handlesys->ReadHandle(params[1], g_TraceHandle, &sec, (void **)&tr)) != HandleError_None) {
505 return pContext->ThrowNativeError("Invalid Handle %x (error %d)", params[1], err);
508 edict_t *pEdict = gameents->BaseEntityToEdict(tr->m_pEnt);
509 return IndexOfEdict(pEdict);
512 static cell_t smn_TRGetPointContents(IPluginContext *pContext, const cell_t *params)
515 IHandleEntity *hentity;
519 pContext->LocalToPhysAddr(params[1], &vec);
520 pContext->LocalToPhysAddr(params[2], &ent);
522 pos.x = sp_ctof(vec[0]);
523 pos.y = sp_ctof(vec[1]);
524 pos.z = sp_ctof(vec[2]);
528 mask = enginetrace->GetPointContents(pos);
530 #if SOURCE_ENGINE == SE_LEFT4DEAD
531 mask = enginetrace->GetPointContents(pos, 0, &hentity);
533 mask = enginetrace->GetPointContents(pos, &hentity);
535 edict_t *pEdict = gameents->BaseEntityToEdict(reinterpret_cast<CBaseEntity *>(hentity));
536 *ent = IndexOfEdict(pEdict);
542 static cell_t smn_TRGetPointContentsEnt(IPluginContext *pContext, const cell_t *params)
544 edict_t *pEdict = PEntityOfEntIndex(params[1]);
545 if (!pEdict || pEdict->IsFree())
547 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
553 pContext->LocalToPhysAddr(params[2], &addr);
555 pos.x = sp_ctof(addr[0]);
556 pos.y = sp_ctof(addr[1]);
557 pos.z = sp_ctof(addr[2]);
559 return enginetrace->GetPointContents_Collideable(pEdict->GetCollideable(), pos);
562 sp_nativeinfo_t g_TRNatives[] =
564 {"TR_TraceRay", smn_TRTraceRay},
565 {"TR_TraceHull", smn_TRTraceHull},
566 {"TR_TraceRayEx", smn_TRTraceRayEx},
567 {"TR_TraceHullEx", smn_TRTraceHullEx},
568 {"TR_GetFraction", smn_TRGetFraction},
569 {"TR_GetEndPosition", smn_TRGetEndPosition},
570 {"TR_GetEntityIndex", smn_TRGetEntityIndex},
571 {"TR_DidHit", smn_TRDidHit},
572 {"TR_GetHitGroup", smn_TRGetHitGroup},
573 {"TR_GetPointContents", smn_TRGetPointContents},
574 {"TR_GetPointContentsEnt", smn_TRGetPointContentsEnt},
575 {"TR_TraceRayFilter", smn_TRTraceRayFilter},
576 {"TR_TraceRayFilterEx", smn_TRTraceRayFilterEx},
577 {"TR_TraceHullFilter", smn_TRTraceHullFilter},
578 {"TR_TraceHullFilterEx", smn_TRTraceHullFilterEx},
579 {"TR_GetPlaneNormal", smn_TRGetPlaneNormal},