extensions/sdktools/trnatives.cpp
author Fyren <fyrenmoo@gmail.com>
Mon May 11 18:46:19 2009 -0700 (2009-05-11)
changeset 2710 3bf47c5fa143
parent 2400 76b7b4575e21
child 2746 8d68569b9648
permissions -rw-r--r--
Some sdktools string and style changes (r=pred)
     1 /**
     2  * vim: set ts=4 :
     3  * =============================================================================
     4  * SourceMod SDKTools Extension
     5  * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
     6  * =============================================================================
     7  *
     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.
    11  * 
    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
    15  * details.
    16  *
    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/>.
    19  *
    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>.
    28  *
    29  * Version: $Id$
    30  */
    31 
    32 #include "extension.h"
    33 #include <worldsize.h>
    34 
    35 class CSMTraceFilter : public CTraceFilter
    36 {
    37 public:
    38 	bool ShouldHitEntity(IHandleEntity *pEntity, int contentsMask)
    39 	{
    40 		cell_t res = 1;
    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);
    46 
    47 		return (res) ? true : false;
    48 	}
    49 	void SetFunctionPtr(IPluginFunction *pFunc, cell_t data)
    50 	{
    51 		m_pFunc = pFunc;
    52 		m_Data = data;
    53 	}
    54 private:
    55 	IPluginFunction *m_pFunc;
    56 	cell_t m_Data;
    57 };
    58 
    59 /* Used for the global trace version */
    60 Ray_t g_Ray;
    61 trace_t g_Trace;
    62 Vector g_StartVec;
    63 Vector g_EndVec;
    64 Vector g_HullMins;
    65 Vector g_HullMaxs;
    66 QAngle g_DirAngles;
    67 CTraceFilterHitAll g_HitAllFilter;
    68 CSMTraceFilter g_SMTraceFilter;
    69 
    70 enum
    71 {
    72 	RayType_EndPoint,
    73 	RayType_Infinite
    74 };
    75 
    76 static cell_t smn_TRTraceRay(IPluginContext *pContext, const cell_t *params)
    77 {
    78 	cell_t *startaddr, *endaddr;
    79 	pContext->LocalToPhysAddr(params[1], &startaddr);
    80 	pContext->LocalToPhysAddr(params[2], &endaddr);
    81 
    82 	g_StartVec.Init(sp_ctof(startaddr[0]), sp_ctof(startaddr[1]), sp_ctof(startaddr[2]));
    83 
    84 	switch (params[4])
    85 	{
    86 	case RayType_EndPoint:
    87 		{
    88 			g_EndVec.Init(sp_ctof(endaddr[0]), sp_ctof(endaddr[1]), sp_ctof(endaddr[2]));
    89 			break;
    90 		}
    91 	case RayType_Infinite:
    92 		{
    93 			g_DirAngles.Init(sp_ctof(endaddr[0]), sp_ctof(endaddr[1]), sp_ctof(endaddr[2]));
    94 			AngleVectors(g_DirAngles, &g_EndVec);
    95 
    96 			/* Make it unitary and get the ending point */
    97 			g_EndVec.NormalizeInPlace();
    98 			g_EndVec = g_StartVec + g_EndVec * MAX_TRACE_LENGTH;
    99 			break;
   100 		}
   101 	}
   102 
   103 	g_Ray.Init(g_StartVec, g_EndVec);
   104 	enginetrace->TraceRay(g_Ray, params[3], &g_HitAllFilter, &g_Trace);
   105 
   106 	return 1;
   107 }
   108 
   109 static cell_t smn_TRTraceHull(IPluginContext *pContext, const cell_t *params)
   110 {
   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);
   116 
   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]));
   121 
   122 	g_Ray.Init(g_StartVec, g_EndVec, g_HullMins, g_HullMaxs);
   123 	enginetrace->TraceRay(g_Ray, params[5], &g_HitAllFilter, &g_Trace);
   124 
   125 	return 1;
   126 }
   127 
   128 static cell_t smn_TRTraceRayFilter(IPluginContext *pContext, const cell_t *params)
   129 {
   130 	cell_t *startaddr, *endaddr;
   131 	IPluginFunction *pFunc;
   132 	cell_t data;
   133 
   134 	pFunc = pContext->GetFunctionById(params[5]);
   135 	if (!pFunc)
   136 	{
   137 		return pContext->ThrowNativeError("Invalid function id (%X)", params[5]);
   138 	}
   139 
   140 	if (params[0] >= 6)
   141 	{
   142 		data = params[6];
   143 	}
   144 	else
   145 	{
   146 		data = 0;
   147 	}
   148 
   149 	g_SMTraceFilter.SetFunctionPtr(pFunc, data);
   150 	pContext->LocalToPhysAddr(params[1], &startaddr);
   151 	pContext->LocalToPhysAddr(params[2], &endaddr);
   152 
   153 	g_StartVec.Init(sp_ctof(startaddr[0]), sp_ctof(startaddr[1]), sp_ctof(startaddr[2]));
   154 
   155 	switch (params[4])
   156 	{
   157 	case RayType_EndPoint:
   158 		{
   159 			g_EndVec.Init(sp_ctof(endaddr[0]), sp_ctof(endaddr[1]), sp_ctof(endaddr[2]));
   160 			break;
   161 		}
   162 	case RayType_Infinite:
   163 		{
   164 			g_DirAngles.Init(sp_ctof(endaddr[0]), sp_ctof(endaddr[1]), sp_ctof(endaddr[2]));
   165 			AngleVectors(g_DirAngles, &g_EndVec);
   166 
   167 			/* Make it unitary and get the ending point */
   168 			g_EndVec.NormalizeInPlace();
   169 			g_EndVec = g_StartVec + g_EndVec * MAX_TRACE_LENGTH;
   170 			break;
   171 		}
   172 	}
   173 
   174 	g_Ray.Init(g_StartVec, g_EndVec);
   175 	enginetrace->TraceRay(g_Ray, params[3], &g_SMTraceFilter, &g_Trace);
   176 
   177 	return 1;
   178 }
   179 
   180 static cell_t smn_TRTraceHullFilter(IPluginContext *pContext, const cell_t *params)
   181 {
   182 	cell_t data;
   183 	IPluginFunction *pFunc;
   184 	cell_t *startaddr, *endaddr, *mins, *maxs;
   185 
   186 	pFunc = pContext->GetFunctionById(params[6]);
   187 	if (!pFunc)
   188 	{
   189 		return pContext->ThrowNativeError("Invalid function id (%X)", params[5]);
   190 	}
   191 
   192 	data = params[7];
   193 
   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);
   199 
   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]));
   204 
   205 	g_Ray.Init(g_StartVec, g_EndVec, g_HullMins, g_HullMaxs);
   206 	enginetrace->TraceRay(g_Ray, params[5], &g_SMTraceFilter, &g_Trace);
   207 
   208 	return 1;
   209 }
   210 
   211 
   212 static cell_t smn_TRTraceRayEx(IPluginContext *pContext, const cell_t *params)
   213 {
   214 	cell_t *startaddr, *endaddr;
   215 	pContext->LocalToPhysAddr(params[1], &startaddr);
   216 	pContext->LocalToPhysAddr(params[2], &endaddr);
   217 
   218 	Vector StartVec, EndVec;
   219 	Ray_t ray;
   220 
   221 	StartVec.Init(sp_ctof(startaddr[0]), sp_ctof(startaddr[1]), sp_ctof(startaddr[2]));
   222 
   223 	switch (params[4])
   224 	{
   225 	case RayType_EndPoint:
   226 		{
   227 			EndVec.Init(sp_ctof(endaddr[0]), sp_ctof(endaddr[1]), sp_ctof(endaddr[2]));
   228 			break;
   229 		}
   230 	case RayType_Infinite:
   231 		{
   232 			QAngle DirAngles;
   233 			DirAngles.Init(sp_ctof(endaddr[0]), sp_ctof(endaddr[1]), sp_ctof(endaddr[2]));
   234 			AngleVectors(DirAngles, &EndVec);
   235 
   236 			/* Make it unitary and get the ending point */
   237 			EndVec.NormalizeInPlace();
   238 			EndVec = StartVec + EndVec * MAX_TRACE_LENGTH;
   239 			break;
   240 		}
   241 	}
   242 
   243 	trace_t *tr = new trace_t;
   244 	ray.Init(StartVec, EndVec);
   245 	enginetrace->TraceRay(ray, params[3], &g_HitAllFilter, tr);
   246 
   247 	HandleError herr;
   248 	Handle_t hndl;
   249 	if (!(hndl=handlesys->CreateHandle(g_TraceHandle, tr, pContext->GetIdentity(), myself->GetIdentity(), &herr)))
   250 	{
   251 		delete tr;
   252 		return pContext->ThrowNativeError("Unable to create a new trace handle (error %d)", herr);
   253 	}
   254 
   255 	return hndl;
   256 }
   257 
   258 static cell_t smn_TRTraceHullEx(IPluginContext *pContext, const cell_t *params)
   259 {
   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);
   265 
   266 	Ray_t ray;
   267 	Vector StartVec, EndVec, vmins, vmaxs;
   268 
   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]));
   273 
   274 	ray.Init(StartVec, EndVec, vmins, vmaxs);
   275 
   276 	trace_t *tr = new trace_t;
   277 	enginetrace->TraceRay(ray, params[5], &g_HitAllFilter, tr);
   278 
   279 	HandleError herr;
   280 	Handle_t hndl;
   281 	if (!(hndl=handlesys->CreateHandle(g_TraceHandle, tr, pContext->GetIdentity(), myself->GetIdentity(), &herr)))
   282 	{
   283 		delete tr;
   284 		return pContext->ThrowNativeError("Unable to create a new trace handle (error %d)", herr);
   285 	}
   286 
   287 	return hndl;
   288 }
   289 
   290 static cell_t smn_TRTraceRayFilterEx(IPluginContext *pContext, const cell_t *params)
   291 {
   292 	IPluginFunction *pFunc;
   293 	cell_t *startaddr, *endaddr;
   294 	cell_t data;
   295 
   296 	pFunc = pContext->GetFunctionById(params[5]);
   297 	if (!pFunc)
   298 	{
   299 		return pContext->ThrowNativeError("Invalid function id (%X)", params[5]);
   300 	}
   301 	pContext->LocalToPhysAddr(params[1], &startaddr);
   302 	pContext->LocalToPhysAddr(params[2], &endaddr);
   303 
   304 	Vector StartVec, EndVec;
   305 	CSMTraceFilter smfilter;
   306 	Ray_t ray;
   307 
   308 	if (params[0] >= 6)
   309 	{
   310 		data = params[6];
   311 	}
   312 	else
   313 	{
   314 		data = 0;
   315 	}
   316 
   317 	smfilter.SetFunctionPtr(pFunc, data);
   318 	StartVec.Init(sp_ctof(startaddr[0]), sp_ctof(startaddr[1]), sp_ctof(startaddr[2]));
   319 
   320 	switch (params[4])
   321 	{
   322 	case RayType_EndPoint:
   323 		{
   324 			EndVec.Init(sp_ctof(endaddr[0]), sp_ctof(endaddr[1]), sp_ctof(endaddr[2]));
   325 			break;
   326 		}
   327 	case RayType_Infinite:
   328 		{
   329 			QAngle DirAngles;
   330 			DirAngles.Init(sp_ctof(endaddr[0]), sp_ctof(endaddr[1]), sp_ctof(endaddr[2]));
   331 			AngleVectors(DirAngles, &EndVec);
   332 
   333 			/* Make it unitary and get the ending point */
   334 			EndVec.NormalizeInPlace();
   335 			EndVec = StartVec + EndVec * MAX_TRACE_LENGTH;
   336 			break;
   337 		}
   338 	}
   339 
   340 	trace_t *tr = new trace_t;
   341 	ray.Init(StartVec, EndVec);
   342 	enginetrace->TraceRay(ray, params[3], &smfilter, tr);
   343 
   344 	HandleError herr;
   345 	Handle_t hndl;
   346 	if (!(hndl=handlesys->CreateHandle(g_TraceHandle, tr, pContext->GetIdentity(), myself->GetIdentity(), &herr)))
   347 	{
   348 		delete tr;
   349 		return pContext->ThrowNativeError("Unable to create a new trace handle (error %d)", herr);
   350 	}
   351 
   352 	return hndl;
   353 }
   354 
   355 static cell_t smn_TRTraceHullFilterEx(IPluginContext *pContext, const cell_t *params)
   356 {
   357 	IPluginFunction *pFunc;
   358 	cell_t *startaddr, *endaddr, *mins, *maxs;
   359 	cell_t data;
   360 
   361 	pFunc = pContext->GetFunctionById(params[6]);
   362 	if (!pFunc)
   363 	{
   364 		return pContext->ThrowNativeError("Invalid function id (%X)", params[5]);
   365 	}
   366 	pContext->LocalToPhysAddr(params[1], &startaddr);
   367 	pContext->LocalToPhysAddr(params[2], &endaddr);
   368 	pContext->LocalToPhysAddr(params[3], &mins);
   369 	pContext->LocalToPhysAddr(params[4], &maxs);
   370 
   371 	Vector StartVec, EndVec, vmins, vmaxs;
   372 	CSMTraceFilter smfilter;
   373 	Ray_t ray;
   374 
   375 	data = params[7];
   376 
   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]));
   382 
   383 	ray.Init(StartVec, EndVec, vmins, vmaxs);
   384 
   385 	trace_t *tr = new trace_t;
   386 	enginetrace->TraceRay(ray, params[5], &smfilter, tr);
   387 
   388 	HandleError herr;
   389 	Handle_t hndl;
   390 	if (!(hndl=handlesys->CreateHandle(g_TraceHandle, tr, pContext->GetIdentity(), myself->GetIdentity(), &herr)))
   391 	{
   392 		delete tr;
   393 		return pContext->ThrowNativeError("Unable to create a new trace handle (error %d)", herr);
   394 	}
   395 
   396 	return hndl;
   397 }
   398 
   399 static cell_t smn_TRGetFraction(IPluginContext *pContext, const cell_t *params)
   400 {
   401 	trace_t *tr;
   402 	HandleError err;
   403 	HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
   404 
   405 	if (params[1] == BAD_HANDLE)
   406 	{
   407 		tr = &g_Trace;
   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);
   410 	}
   411 
   412 	return sp_ftoc(tr->fraction);
   413 }
   414 
   415 static cell_t smn_TRGetPlaneNormal(IPluginContext *pContext, const cell_t *params)
   416 {
   417 	trace_t *tr;
   418 	HandleError err;
   419 	HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
   420 
   421 	if (params[1] == BAD_HANDLE)
   422 	{
   423 		tr = &g_Trace;
   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);
   426 	}
   427 
   428 	Vector *normal = &tr->plane.normal;
   429 
   430 	cell_t *r;
   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);
   435 
   436 	return 1;
   437 }
   438 
   439 
   440 static cell_t smn_TRGetEndPosition(IPluginContext *pContext, const cell_t *params)
   441 {
   442 	trace_t *tr;
   443 	HandleError err;
   444 	HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
   445 
   446 	if (params[2] == BAD_HANDLE)
   447 	{
   448 		tr = &g_Trace;
   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);
   451 	}
   452 
   453 	cell_t *addr;
   454 	pContext->LocalToPhysAddr(params[1], &addr);
   455 
   456 	addr[0] = sp_ftoc(tr->endpos.x);
   457 	addr[1] = sp_ftoc(tr->endpos.y);
   458 	addr[2] = sp_ftoc(tr->endpos.z);
   459 
   460 	return 1;
   461 }
   462 
   463 static cell_t smn_TRDidHit(IPluginContext *pContext, const cell_t *params)
   464 {
   465 	trace_t *tr;
   466 	HandleError err;
   467 	HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
   468 
   469 	if (params[1] == BAD_HANDLE)
   470 	{
   471 		tr = &g_Trace;
   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);
   474 	}
   475 
   476 	return tr->DidHit() ? 1 : 0;
   477 }
   478 
   479 static cell_t smn_TRGetHitGroup(IPluginContext *pContext, const cell_t *params)
   480 {
   481 	trace_t *tr;
   482 	HandleError err;
   483 	HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
   484 
   485 	if (params[1] == BAD_HANDLE)
   486 	{
   487 		tr = &g_Trace;
   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);
   490 	}
   491 
   492 	return tr->hitgroup;
   493 }
   494 
   495 static cell_t smn_TRGetEntityIndex(IPluginContext *pContext, const cell_t *params)
   496 {
   497 	trace_t *tr;
   498 	HandleError err;
   499 	HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
   500 
   501 	if (params[1] == BAD_HANDLE)
   502 	{
   503 		tr = &g_Trace;
   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);
   506 	}
   507 
   508 	edict_t *pEdict = gameents->BaseEntityToEdict(tr->m_pEnt);
   509 	return IndexOfEdict(pEdict);
   510 }
   511 
   512 static cell_t smn_TRGetPointContents(IPluginContext *pContext, const cell_t *params)
   513 {
   514 	cell_t *vec, *ent;
   515 	IHandleEntity *hentity;
   516 	Vector pos;
   517 	int mask;
   518 
   519 	pContext->LocalToPhysAddr(params[1], &vec);
   520 	pContext->LocalToPhysAddr(params[2], &ent);
   521 
   522 	pos.x = sp_ctof(vec[0]);
   523 	pos.y = sp_ctof(vec[1]);
   524 	pos.z = sp_ctof(vec[2]);
   525 
   526 	if (*ent == -1)
   527 	{
   528 		mask = enginetrace->GetPointContents(pos);
   529 	} else {
   530 #if SOURCE_ENGINE == SE_LEFT4DEAD
   531 		mask = enginetrace->GetPointContents(pos, 0, &hentity);
   532 #else
   533 		mask = enginetrace->GetPointContents(pos, &hentity);
   534 #endif
   535 		edict_t *pEdict = gameents->BaseEntityToEdict(reinterpret_cast<CBaseEntity *>(hentity));
   536 		*ent = IndexOfEdict(pEdict);
   537 	}
   538 
   539 	return mask;
   540 }
   541 
   542 static cell_t smn_TRGetPointContentsEnt(IPluginContext *pContext, const cell_t *params)
   543 {
   544 	edict_t *pEdict = PEntityOfEntIndex(params[1]);
   545 	if (!pEdict || pEdict->IsFree())
   546 	{
   547 		return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
   548 	}
   549 
   550 	cell_t *addr;
   551 	Vector pos;
   552 
   553 	pContext->LocalToPhysAddr(params[2], &addr);
   554 
   555 	pos.x = sp_ctof(addr[0]);
   556 	pos.y = sp_ctof(addr[1]);
   557 	pos.z = sp_ctof(addr[2]);
   558 
   559 	return enginetrace->GetPointContents_Collideable(pEdict->GetCollideable(), pos);
   560 }
   561 
   562 sp_nativeinfo_t g_TRNatives[] = 
   563 {
   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},
   580 	{NULL,						NULL}
   581 };