core/smn_entities.cpp
author Nicholas Hastings <skamonkey@gmail.com>
Mon Feb 08 19:57:20 2010 -0800 (2010-02-08)
changeset 2914 bf5f9aa53abe
parent 2913 141ce1313e4a
child 3010 8ea042c00c80
permissions -rw-r--r--
Fixed FindEntityByClassname crash in Synergy (bug 4235, r=dvander).
dvander@555
     1
/**
ds@653
     2
 * vim: set ts=4 :
ds@1330
     3
 * =============================================================================
dvander@1231
     4
 * SourceMod
ds@1947
     5
 * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
ds@1330
     6
 * =============================================================================
dvander@555
     7
 *
ds@1330
     8
 * This program is free software; you can redistribute it and/or modify it under
ds@1330
     9
 * the terms of the GNU General Public License, version 3.0, as published by the
ds@1330
    10
 * Free Software Foundation.
dvander@1231
    11
 * 
ds@1330
    12
 * This program is distributed in the hope that it will be useful, but WITHOUT
ds@1330
    13
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
ds@1330
    14
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
ds@1330
    15
 * details.
dvander@1231
    16
 *
ds@1330
    17
 * You should have received a copy of the GNU General Public License along with
ds@1330
    18
 * this program.  If not, see <http://www.gnu.org/licenses/>.
dvander@1231
    19
 *
ds@1330
    20
 * As a special exception, AlliedModders LLC gives you permission to link the
ds@1330
    21
 * code of this program (as well as its derivative works) to "Half-Life 2," the
ds@1330
    22
 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
ds@1330
    23
 * by the Valve Corporation.  You must obey the GNU General Public License in
ds@1330
    24
 * all respects for all other code used.  Additionally, AlliedModders LLC grants
ds@1330
    25
 * this exception to all derivative works.  AlliedModders LLC defines further
ds@1330
    26
 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
ds@1330
    27
 * or <http://www.sourcemod.net/license.php>.
dvander@555
    28
 *
dvander@555
    29
 * Version: $Id$
dvander@555
    30
 */
dvander@555
    31
dvander@555
    32
#include "sm_globals.h"
dvander@555
    33
#include "sourcemod.h"
dvander@555
    34
#include "sourcemm_api.h"
dvander@591
    35
#include "PlayerManager.h"
dvander@592
    36
#include "HalfLife2.h"
faluco@682
    37
#include "GameConfigs.h"
faluco@694
    38
#include "sm_stringutil.h"
faluco@694
    39
faluco@694
    40
enum PropType
faluco@694
    41
{
faluco@694
    42
	Prop_Send = 0,
faluco@694
    43
	Prop_Data
faluco@694
    44
};
dvander@555
    45
dvander@1847
    46
enum PropFieldType
dvander@1847
    47
{
dvander@1847
    48
	PropField_Unsupported,		/**< The type is unsupported. */
dvander@1847
    49
	PropField_Integer,			/**< Valid for SendProp and Data fields */
dvander@1847
    50
	PropField_Float,			/**< Valid for SendProp and Data fields */
dvander@1847
    51
	PropField_Entity,			/**< Valid for Data fields only (SendProp shows as int) */
dvander@1847
    52
	PropField_Vector,			/**< Valid for SendProp and Data fields */
dvander@1847
    53
	PropField_String,			/**< Valid for SendProp and Data fields */
dvander@1884
    54
	PropField_String_T,			/**< Valid for Data fields.  Read only! */
dvander@1847
    55
};
dvander@1847
    56
pred@2746
    57
inline edict_t *BaseEntityToEdict(CBaseEntity *pEntity)
pred@2746
    58
{
pred@2746
    59
	IServerUnknown *pUnk = (IServerUnknown *)pEntity;
pred@2746
    60
	IServerNetworkable *pNet = pUnk->GetNetworkable();
pred@2746
    61
pred@2746
    62
	if (!pNet)
pred@2746
    63
	{
pred@2746
    64
		return NULL;
pred@2746
    65
	}
pred@2746
    66
pred@2746
    67
	return pNet->GetEdict();
pred@2746
    68
}
pred@2746
    69
dvander@555
    70
inline edict_t *GetEdict(cell_t num)
dvander@555
    71
{
fyrenmoo@2879
    72
	edict_t *pEdict;
fyrenmoo@2879
    73
	if (!IndexToAThings(num, NULL, &pEdict))
fyrenmoo@2879
    74
	{
fyrenmoo@2879
    75
		return NULL;
fyrenmoo@2879
    76
	}
fyrenmoo@2879
    77
	
fyrenmoo@2879
    78
	return pEdict;
fyrenmoo@2879
    79
}
fyrenmoo@2879
    80
fyrenmoo@2879
    81
inline CBaseEntity *GetEntity(cell_t num)
fyrenmoo@2879
    82
{
fyrenmoo@2879
    83
	CBaseEntity *pEntity;
fyrenmoo@2879
    84
	if (!IndexToAThings(num, &pEntity, NULL))
fyrenmoo@2879
    85
	{
fyrenmoo@2879
    86
		return NULL;
fyrenmoo@2879
    87
	}
fyrenmoo@2879
    88
fyrenmoo@2879
    89
	return pEntity;
fyrenmoo@2879
    90
}
fyrenmoo@2879
    91
fyrenmoo@2879
    92
/* Given an entity reference or index, fill out a CBaseEntity and/or edict.
fyrenmoo@2879
    93
   If lookup is successful, returns true and writes back the two parameters.
fyrenmoo@2879
    94
   If lookup fails, returns false and doesn't touch the params.  */
fyrenmoo@2879
    95
bool IndexToAThings(cell_t num, CBaseEntity **pEntData, edict_t **pEdictData)
fyrenmoo@2879
    96
{
pred@2746
    97
	CBaseEntity *pEntity = g_HL2.ReferenceToEntity(num);
pred@2746
    98
pred@2746
    99
	if (!pEntity)
pred@2746
   100
	{
fyrenmoo@2879
   101
		return false;
dvander@555
   102
	}
pred@2746
   103
pred@2746
   104
	int index = g_HL2.ReferenceToIndex(num);
pred@2746
   105
	if (index > 0 && index <= g_Players.GetMaxClients())
dvander@556
   106
	{
pred@2746
   107
		CPlayer *pPlayer = g_Players.GetPlayerByIndex(index);
dvander@556
   108
		if (!pPlayer || !pPlayer->IsConnected())
dvander@556
   109
		{
fyrenmoo@2879
   110
			return false;
dvander@556
   111
		}
dvander@556
   112
	}
pred@2746
   113
fyrenmoo@2879
   114
	if (pEntData)
dvander@557
   115
	{
fyrenmoo@2879
   116
		*pEntData = pEntity;
dvander@557
   117
	}
pred@2746
   118
fyrenmoo@2879
   119
	if (pEdictData)
dvander@557
   120
	{
fyrenmoo@2879
   121
		edict_t *pEdict = ::BaseEntityToEdict(pEntity);
fyrenmoo@2913
   122
		if (!pEdict || pEdict->IsFree())
dvander@557
   123
		{
fyrenmoo@2879
   124
			pEdict = NULL;
dvander@557
   125
		}
fyrenmoo@2879
   126
fyrenmoo@2879
   127
		*pEdictData = pEdict;
dvander@557
   128
	}
pred@2746
   129
fyrenmoo@2879
   130
	return true;
dvander@557
   131
}
fyrenmoo@2879
   132
/*
fyrenmoo@2879
   133
  <predcrab> AThings is like guaranteed r+ by dvander though
fyrenmoo@2879
   134
  <predcrab> he wont even read the rest of the patch to nit stuff
fyrenmoo@2879
   135
  <Fyren> Like I wasn't going to r? you anyway!
fyrenmoo@2879
   136
  <predcrab> he still sees!
fyrenmoo@2879
   137
  <predcrab> he's everywhere
fyrenmoo@2879
   138
*/
dvander@557
   139
faluco@682
   140
class VEmptyClass {};
faluco@682
   141
datamap_t *VGetDataDescMap(CBaseEntity *pThisPtr, int offset)
faluco@682
   142
{
faluco@682
   143
	void **this_ptr = *reinterpret_cast<void ***>(&pThisPtr);
faluco@682
   144
	void **vtable = *reinterpret_cast<void ***>(pThisPtr);
faluco@682
   145
	void *vfunc = vtable[offset];
faluco@682
   146
faluco@682
   147
	union
faluco@682
   148
	{
faluco@682
   149
		datamap_t *(VEmptyClass::*mfpnew)();
faluco@682
   150
#ifndef PLATFORM_POSIX
faluco@682
   151
		void *addr;
faluco@682
   152
	} u;
faluco@682
   153
	u.addr = vfunc;
faluco@682
   154
#else
faluco@682
   155
		struct  
faluco@682
   156
		{
faluco@682
   157
			void *addr;
faluco@682
   158
			intptr_t adjustor;
faluco@682
   159
		} s;
faluco@682
   160
	} u;
faluco@682
   161
	u.s.addr = vfunc;
faluco@682
   162
	u.s.adjustor = 0;
faluco@682
   163
#endif
faluco@682
   164
faluco@682
   165
	return (datamap_t *)(reinterpret_cast<VEmptyClass *>(this_ptr)->*u.mfpnew)();
faluco@682
   166
}
faluco@682
   167
faluco@682
   168
inline datamap_t *CBaseEntity_GetDataDescMap(CBaseEntity *pEntity)
faluco@682
   169
{
faluco@682
   170
	int offset;
faluco@682
   171
faluco@682
   172
	if (!g_pGameConf->GetOffset("GetDataDescMap", &offset) || !offset)
faluco@682
   173
	{
faluco@682
   174
		return NULL;
faluco@682
   175
	}
faluco@682
   176
faluco@682
   177
	return VGetDataDescMap(pEntity, offset);
faluco@682
   178
}
faluco@682
   179
dvander@965
   180
/* :TODO: Move this! */
dvander@965
   181
datamap_t *CHalfLife2::GetDataMap(CBaseEntity *pEntity)
dvander@965
   182
{
dvander@965
   183
	return CBaseEntity_GetDataDescMap(pEntity);
dvander@965
   184
}
dvander@965
   185
dvander@555
   186
static cell_t GetMaxEntities(IPluginContext *pContext, const cell_t *params)
dvander@555
   187
{
dvander@555
   188
	return gpGlobals->maxEntities;
dvander@555
   189
}
dvander@555
   190
dvander@555
   191
static cell_t CreateEdict(IPluginContext *pContext, const cell_t *params)
dvander@555
   192
{
dvander@555
   193
	edict_t *pEdict = engine->CreateEdict();
dvander@555
   194
dvander@555
   195
	if (!pEdict)
dvander@555
   196
	{
dvander@555
   197
		return 0;
dvander@555
   198
	}
dvander@555
   199
ds@2400
   200
	return IndexOfEdict(pEdict);
dvander@555
   201
}
dvander@555
   202
dvander@555
   203
static cell_t RemoveEdict(IPluginContext *pContext, const cell_t *params)
dvander@555
   204
{
pred@2746
   205
	edict_t *pEdict = GetEdict(params[1]);
dvander@555
   206
dvander@555
   207
	if (!pEdict)
dvander@555
   208
	{
pred@2746
   209
		return pContext->ThrowNativeError("Edict %d (%d) is not a valid edict", g_HL2.ReferenceToIndex(params[1]), params[1]);
dvander@555
   210
	}
dvander@555
   211
dvander@555
   212
	engine->RemoveEdict(pEdict);
dvander@555
   213
dvander@555
   214
	return 1;
dvander@555
   215
}
dvander@555
   216
dvander@555
   217
static cell_t IsValidEdict(IPluginContext *pContext, const cell_t *params)
dvander@555
   218
{
dvander@556
   219
	edict_t *pEdict = GetEdict(params[1]);
dvander@555
   220
dvander@555
   221
	if (!pEdict)
dvander@555
   222
	{
dvander@555
   223
		return 0;
dvander@555
   224
	}
dvander@555
   225
dvander@555
   226
	/* Shouldn't be necessary... not sure though */
dvander@555
   227
	return pEdict->IsFree() ? 0 : 1;
dvander@555
   228
}
dvander@555
   229
dvander@555
   230
static cell_t IsValidEntity(IPluginContext *pContext, const cell_t *params)
dvander@555
   231
{
pred@2746
   232
	CBaseEntity *pEntity = g_HL2.ReferenceToEntity(params[1]);
dvander@555
   233
dvander@555
   234
	return (pEntity != NULL) ? 1 : 0;
dvander@555
   235
}
dvander@555
   236
dvander@555
   237
static cell_t IsEntNetworkable(IPluginContext *pContext, const cell_t *params)
dvander@555
   238
{
dvander@556
   239
	edict_t *pEdict = GetEdict(params[1]);
dvander@555
   240
dvander@556
   241
	if (!pEdict)
dvander@555
   242
	{
dvander@555
   243
		return 0;
dvander@555
   244
	}
dvander@555
   245
dvander@555
   246
	return (pEdict->GetNetworkable() != NULL) ? 1 : 0;
dvander@555
   247
}
dvander@555
   248
dvander@555
   249
static cell_t GetEntityCount(IPluginContext *pContext, const cell_t *params)
dvander@555
   250
{
dvander@555
   251
	return engine->GetEntityCount();
dvander@555
   252
}
dvander@555
   253
dvander@555
   254
static cell_t GetEdictFlags(IPluginContext *pContext, const cell_t *params)
dvander@555
   255
{
dvander@555
   256
	edict_t *pEdict = GetEdict(params[1]);
dvander@555
   257
dvander@555
   258
	if (!pEdict)
dvander@555
   259
	{
pred@2746
   260
		return pContext->ThrowNativeError("Invalid edict (%d - %d)", g_HL2.ReferenceToIndex(params[1]), params[1]);
dvander@555
   261
	}
dvander@555
   262
dvander@555
   263
	return pEdict->m_fStateFlags;
dvander@555
   264
}
dvander@555
   265
dvander@555
   266
static cell_t SetEdictFlags(IPluginContext *pContext, const cell_t *params)
dvander@555
   267
{
dvander@555
   268
	edict_t *pEdict = GetEdict(params[1]);
dvander@555
   269
dvander@555
   270
	if (!pEdict)
dvander@555
   271
	{
pred@2746
   272
		return pContext->ThrowNativeError("Invalid edict (%d - %d)", g_HL2.ReferenceToIndex(params[1]), params[1]);
dvander@555
   273
	}
dvander@555
   274
dvander@555
   275
	pEdict->m_fStateFlags = params[2];
dvander@555
   276
dvander@555
   277
	return 1;
dvander@555
   278
}
dvander@555
   279
dvander@556
   280
static cell_t GetEdictClassname(IPluginContext *pContext, const cell_t *params)
dvander@556
   281
{
dvander@556
   282
	edict_t *pEdict = GetEdict(params[1]);
dvander@556
   283
dvander@556
   284
	if (!pEdict)
dvander@556
   285
	{
pred@2746
   286
		return pContext->ThrowNativeError("Invalid edict (%d - %d)", g_HL2.ReferenceToIndex(params[1]), params[1]);
dvander@556
   287
	}
dvander@556
   288
dvander@556
   289
	const char *cls = pEdict->GetClassName();
dvander@556
   290
dvander@556
   291
	if (!cls || cls[0] == '\0')
dvander@556
   292
	{
dvander@556
   293
		return 0;
dvander@556
   294
	}
dvander@556
   295
dvander@556
   296
	pContext->StringToLocal(params[2], params[3], cls);
dvander@556
   297
dvander@556
   298
	return 1;
dvander@556
   299
}
dvander@556
   300
dvander@556
   301
static cell_t GetEntityNetClass(IPluginContext *pContext, const cell_t *params)
dvander@556
   302
{
pred@2746
   303
	CBaseEntity *pEntity = g_HL2.ReferenceToEntity(params[1]);
pred@2746
   304
pred@2746
   305
	IServerUnknown *pUnk = (IServerUnknown *)pEntity;
dvander@556
   306
pred@2746
   307
	if (!pEntity)
dvander@556
   308
	{
pred@2746
   309
		return pContext->ThrowNativeError("Invalid entity (%d - %d)", g_HL2.ReferenceToIndex(params[1]), params[1]);
dvander@556
   310
	}
dvander@556
   311
pred@2746
   312
	IServerNetworkable *pNet = pUnk->GetNetworkable();
dvander@556
   313
	if (!pNet)
dvander@556
   314
	{
dvander@556
   315
		return 0;
dvander@556
   316
	}
dvander@556
   317
dvander@556
   318
	ServerClass *pClass = pNet->GetServerClass();
dvander@556
   319
dvander@556
   320
	pContext->StringToLocal(params[2], params[3], pClass->GetName());
dvander@556
   321
dvander@556
   322
	return 1;
dvander@556
   323
}
dvander@556
   324
dvander@557
   325
static cell_t GetEntData(IPluginContext *pContext, const cell_t *params)
dvander@557
   326
{
fyrenmoo@2879
   327
	CBaseEntity *pEntity = GetEntity(params[1]);
dvander@557
   328
pred@2746
   329
	if (!pEntity)
dvander@557
   330
	{
pred@2746
   331
		return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
dvander@557
   332
	}
dvander@557
   333
dvander@557
   334
	int offset = params[2];
dvander@1847
   335
	if (offset <= 0 || offset > 32768)
dvander@557
   336
	{
dvander@557
   337
		return pContext->ThrowNativeError("Offset %d is invalid", offset);
dvander@557
   338
	}
dvander@557
   339
dvander@557
   340
	switch (params[3])
dvander@557
   341
	{
dvander@557
   342
	case 4:
dvander@557
   343
		return *(int *)((uint8_t *)pEntity + offset);
dvander@557
   344
	case 2:
dvander@557
   345
		return *(short *)((uint8_t *)pEntity + offset);
dvander@557
   346
	case 1:
dvander@557
   347
		return *((uint8_t *)pEntity + offset);
dvander@557
   348
	default:
dvander@557
   349
		return pContext->ThrowNativeError("Integer size %d is invalid", params[3]);
dvander@557
   350
	}
dvander@557
   351
}
dvander@557
   352
dvander@557
   353
static cell_t SetEntData(IPluginContext *pContext, const cell_t *params)
dvander@557
   354
{
dvander@557
   355
	CBaseEntity *pEntity;
fyrenmoo@2879
   356
	edict_t *pEdict;
dvander@557
   357
fyrenmoo@2879
   358
	if (!IndexToAThings(params[1], &pEntity, &pEdict))
dvander@557
   359
	{
pred@2746
   360
		return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
dvander@557
   361
	}
dvander@557
   362
dvander@557
   363
	int offset = params[2];
dvander@1847
   364
	if (offset <= 0 || offset > 32768)
dvander@557
   365
	{
dvander@557
   366
		return pContext->ThrowNativeError("Offset %d is invalid", offset);
dvander@557
   367
	}
dvander@557
   368
pred@2746
   369
	if (params[5] && (pEdict != NULL))
dvander@561
   370
	{
dvander@685
   371
		g_HL2.SetEdictStateChanged(pEdict, offset);
dvander@561
   372
	}
dvander@561
   373
dvander@557
   374
	switch (params[4])
dvander@557
   375
	{
dvander@557
   376
	case 4:
dvander@557
   377
		{
dvander@557
   378
			*(int *)((uint8_t *)pEntity + offset) = params[3];
dvander@557
   379
			break;
dvander@557
   380
		}
dvander@557
   381
	case 2:
dvander@557
   382
		{
dvander@557
   383
			*(short *)((uint8_t *)pEntity + offset) = params[3];
dvander@557
   384
			break;
dvander@557
   385
		}
dvander@557
   386
	case 1:
dvander@557
   387
		{
dvander@557
   388
			*((uint8_t *)pEntity + offset) = params[3];
dvander@557
   389
			break;
dvander@557
   390
		}
dvander@557
   391
	default:
dvander@557
   392
		return pContext->ThrowNativeError("Integer size %d is invalid", params[4]);
dvander@557
   393
	}
dvander@557
   394
dvander@557
   395
	return 1;
dvander@557
   396
}
dvander@557
   397
dvander@557
   398
static cell_t GetEntDataFloat(IPluginContext *pContext, const cell_t *params)
dvander@557
   399
{
fyrenmoo@2879
   400
	CBaseEntity *pEntity = GetEntity(params[1]);
dvander@557
   401
pred@2746
   402
	if (!pEntity)
dvander@557
   403
	{
pred@2746
   404
		return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
dvander@557
   405
	}
dvander@557
   406
dvander@557
   407
	int offset = params[2];
dvander@1847
   408
	if (offset <= 0 || offset > 32768)
dvander@557
   409
	{
dvander@557
   410
		return pContext->ThrowNativeError("Offset %d is invalid", offset);
dvander@557
   411
	}
dvander@557
   412
dvander@557
   413
	float f = *(float *)((uint8_t *)pEntity + offset);
dvander@557
   414
dvander@557
   415
	return sp_ftoc(f);
dvander@557
   416
}
dvander@557
   417
dvander@557
   418
static cell_t SetEntDataFloat(IPluginContext *pContext, const cell_t *params)
dvander@557
   419
{
dvander@557
   420
	CBaseEntity *pEntity;
fyrenmoo@2879
   421
	edict_t *pEdict;
dvander@557
   422
fyrenmoo@2879
   423
	if (!IndexToAThings(params[1], &pEntity, &pEdict))
dvander@557
   424
	{
pred@2746
   425
		return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
dvander@557
   426
	}
dvander@557
   427
dvander@557
   428
	int offset = params[2];
dvander@1847
   429
	if (offset <= 0 || offset > 32768)
dvander@557
   430
	{
dvander@557
   431
		return pContext->ThrowNativeError("Offset %d is invalid", offset);
dvander@557
   432
	}
dvander@557
   433
dvander@557
   434
	*(float *)((uint8_t *)pEntity + offset) = sp_ctof(params[3]);
dvander@557
   435
pred@2746
   436
	if (params[4] && (pEdict != NULL))
dvander@561
   437
	{
dvander@685
   438
		g_HL2.SetEdictStateChanged(pEdict, offset);
dvander@561
   439
	}
dvander@561
   440
dvander@557
   441
	return 1;
dvander@557
   442
}
dvander@557
   443
dvander@557
   444
static cell_t GetEntDataVector(IPluginContext *pContext, const cell_t *params)
dvander@557
   445
{
fyrenmoo@2879
   446
	CBaseEntity *pEntity = GetEntity(params[1]);
dvander@557
   447
pred@2746
   448
	if (!pEntity)
dvander@557
   449
	{
pred@2746
   450
		return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
dvander@557
   451
	}
dvander@557
   452
dvander@557
   453
	int offset = params[2];
dvander@1847
   454
	if (offset <= 0 || offset > 32768)
dvander@557
   455
	{
dvander@557
   456
		return pContext->ThrowNativeError("Offset %d is invalid", offset);
dvander@557
   457
	}
dvander@557
   458
dvander@557
   459
	Vector *v = (Vector *)((uint8_t *)pEntity + offset);
dvander@557
   460
dvander@557
   461
	cell_t *vec;
dvander@557
   462
	pContext->LocalToPhysAddr(params[3], &vec);
dvander@557
   463
faluco@597
   464
	vec[0] = sp_ftoc(v->x);
faluco@597
   465
	vec[1] = sp_ftoc(v->y);
faluco@597
   466
	vec[2] = sp_ftoc(v->z);
dvander@557
   467
dvander@557
   468
	return 1;
dvander@557
   469
}
dvander@557
   470
dvander@557
   471
static cell_t SetEntDataVector(IPluginContext *pContext, const cell_t *params)
dvander@557
   472
{
dvander@557
   473
	CBaseEntity *pEntity;
fyrenmoo@2879
   474
	edict_t *pEdict;
dvander@557
   475
fyrenmoo@2879
   476
	if (!IndexToAThings(params[1], &pEntity, &pEdict))
dvander@557
   477
	{
pred@2746
   478
		return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
dvander@557
   479
	}
dvander@557
   480
dvander@557
   481
	int offset = params[2];
dvander@1847
   482
	if (offset <= 0 || offset > 32768)
dvander@557
   483
	{
dvander@557
   484
		return pContext->ThrowNativeError("Offset %d is invalid", offset);
dvander@557
   485
	}
dvander@557
   486
dvander@557
   487
	Vector *v = (Vector *)((uint8_t *)pEntity + offset);
dvander@557
   488
dvander@557
   489
	cell_t *vec;
dvander@557
   490
	pContext->LocalToPhysAddr(params[3], &vec);
dvander@557
   491
faluco@597
   492
	v->x = sp_ctof(vec[0]);
faluco@597
   493
	v->y = sp_ctof(vec[1]);
faluco@597
   494
	v->z = sp_ctof(vec[2]);
dvander@557
   495
pred@2746
   496
	if (params[4] && (pEdict != NULL))
dvander@561
   497
	{
dvander@685
   498
		g_HL2.SetEdictStateChanged(pEdict, offset);
dvander@561
   499
	}
dvander@561
   500
dvander@557
   501
	return 1;
dvander@557
   502
}
dvander@557
   503
dvander@1847
   504
/* THIS GUY IS DEPRECATED. */
dvander@557
   505
static cell_t GetEntDataEnt(IPluginContext *pContext, const cell_t *params)
dvander@557
   506
{
fyrenmoo@2879
   507
	CBaseEntity *pEntity = GetEntity(params[1]);
dvander@557
   508
pred@2746
   509
	if (!pEntity)
dvander@557
   510
	{
pred@2746
   511
		return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
dvander@557
   512
	}
dvander@557
   513
dvander@557
   514
	int offset = params[2];
dvander@1847
   515
	if (offset <= 0 || offset > 32768)
dvander@557
   516
	{
dvander@557
   517
		return pContext->ThrowNativeError("Offset %d is invalid", offset);
dvander@557
   518
	}
dvander@557
   519
dvander@557
   520
	CBaseHandle &hndl = *(CBaseHandle *)((uint8_t *)pEntity + offset);
dvander@557
   521
dvander@557
   522
	if (!hndl.IsValid())
dvander@557
   523
	{
dvander@557
   524
		return 0;
dvander@557
   525
	}
dvander@557
   526
pred@2746
   527
	int ref = g_HL2.IndexToReference(hndl.GetEntryIndex());
pred@2746
   528
	return g_HL2.ReferenceToBCompatRef(ref);
dvander@557
   529
}
dvander@557
   530
dvander@1847
   531
int CheckBaseHandle(CBaseHandle &hndl)
dvander@1847
   532
{
dvander@1847
   533
	if (!hndl.IsValid())
dvander@1847
   534
	{
dvander@1847
   535
		return -1;
dvander@1847
   536
	}
dvander@1847
   537
dvander@1847
   538
	int index = hndl.GetEntryIndex();
dvander@1847
   539
dvander@1847
   540
	edict_t *pStoredEdict;
dvander@1847
   541
	CBaseEntity *pStoredEntity;
dvander@1847
   542
fyrenmoo@2879
   543
	if (!IndexToAThings(index, &pStoredEntity, &pStoredEdict))
fyrenmoo@2879
   544
	{
fyrenmoo@2879
   545
		return -1;
fyrenmoo@2879
   546
	}
dvander@1847
   547
dvander@1847
   548
	if (pStoredEdict == NULL || pStoredEntity == NULL)
dvander@1847
   549
	{
dvander@1847
   550
		return -1;
dvander@1847
   551
	}
dvander@1847
   552
dvander@1847
   553
	IServerEntity *pSE = pStoredEdict->GetIServerEntity();
dvander@1847
   554
dvander@1847
   555
	if (pSE == NULL)
dvander@1847
   556
	{
dvander@1847
   557
		return -1;
dvander@1847
   558
	}
dvander@1847
   559
dvander@1847
   560
	if (pSE->GetRefEHandle() != hndl)
dvander@1847
   561
	{
dvander@1847
   562
		return -1;
dvander@1847
   563
	}
dvander@1847
   564
dvander@1847
   565
	return index;
dvander@1847
   566
}
dvander@1847
   567
dvander@1847
   568
static cell_t GetEntDataEnt2(IPluginContext *pContext, const cell_t *params)
dvander@1847
   569
{
fyrenmoo@2879
   570
	CBaseEntity *pEntity = GetEntity(params[1]);
dvander@1847
   571
pred@2746
   572
	if (pEntity == NULL)
dvander@1847
   573
	{
pred@2746
   574
		return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
dvander@1847
   575
	}
dvander@1847
   576
dvander@1847
   577
	int offset = params[2];
dvander@1847
   578
	if (offset <= 0 || offset > 32768)
dvander@1847
   579
	{
dvander@1847
   580
		return pContext->ThrowNativeError("Offset %d is invalid", offset);
dvander@1847
   581
	}
dvander@1847
   582
dvander@1847
   583
	CBaseHandle &hndl = *(CBaseHandle *)((uint8_t *)pEntity + offset);
dvander@1847
   584
pred@2746
   585
	int ref = g_HL2.IndexToReference(hndl.GetEntryIndex());
pred@2746
   586
	return g_HL2.ReferenceToBCompatRef(ref);
dvander@1847
   587
}
dvander@1847
   588
dvander@1847
   589
/* THIS GUY IS DEPRECATED. */
dvander@557
   590
static cell_t SetEntDataEnt(IPluginContext *pContext, const cell_t *params)
dvander@557
   591
{
dvander@557
   592
	CBaseEntity *pEntity;
fyrenmoo@2879
   593
	edict_t *pEdict;
dvander@557
   594
fyrenmoo@2879
   595
	if (!IndexToAThings(params[1], &pEntity, &pEdict))
dvander@557
   596
	{
pred@2746
   597
		return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
dvander@557
   598
	}
dvander@557
   599
dvander@557
   600
	int offset = params[2];
dvander@1847
   601
	if (offset <= 0 || offset > 32768)
dvander@557
   602
	{
dvander@557
   603
		return pContext->ThrowNativeError("Offset %d is invalid", offset);
dvander@557
   604
	}
dvander@557
   605
dvander@557
   606
	CBaseHandle &hndl = *(CBaseHandle *)((uint8_t *)pEntity + offset);
dvander@557
   607
pred@2748
   608
	if (params[3] == 0 || (unsigned)params[3] == INVALID_EHANDLE_INDEX)
dvander@557
   609
	{
dvander@557
   610
		hndl.Set(NULL);
dvander@557
   611
	} else {
fyrenmoo@2879
   612
		CBaseEntity *pOther = GetEntity(params[3]);
pred@2746
   613
pred@2746
   614
		if (!pOther)
dvander@557
   615
		{
pred@2746
   616
			return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[3]), params[3]);
dvander@557
   617
		}
pred@2746
   618
pred@2746
   619
		IHandleEntity *pHandleEnt = (IHandleEntity *)pOther;
pred@2746
   620
		hndl.Set(pHandleEnt);
dvander@557
   621
	}
dvander@557
   622
pred@2746
   623
	if (params[4] && (pEdict != NULL))
dvander@561
   624
	{
dvander@685
   625
		g_HL2.SetEdictStateChanged(pEdict, offset);
dvander@561
   626
	}
dvander@561
   627
dvander@557
   628
	return 1;
dvander@557
   629
}
dvander@557
   630
dvander@1847
   631
static cell_t SetEntDataEnt2(IPluginContext *pContext, const cell_t *params)
dvander@1847
   632
{
dvander@1847
   633
	CBaseEntity *pEntity;
fyrenmoo@2879
   634
	edict_t *pEdict;
dvander@1847
   635
fyrenmoo@2879
   636
	if (!IndexToAThings(params[1], &pEntity, &pEdict))
dvander@1847
   637
	{
pred@2746
   638
		return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
dvander@1847
   639
	}
dvander@1847
   640
dvander@1847
   641
	int offset = params[2];
dvander@1847
   642
	if (offset <= 0 || offset > 32768)
dvander@1847
   643
	{
dvander@1847
   644
		return pContext->ThrowNativeError("Offset %d is invalid", offset);
dvander@1847
   645
	}
dvander@1847
   646
dvander@1847
   647
	CBaseHandle &hndl = *(CBaseHandle *)((uint8_t *)pEntity + offset);
dvander@1847
   648
pred@2748
   649
	if ((unsigned)params[3] == INVALID_EHANDLE_INDEX)
dvander@1847
   650
	{
dvander@1847
   651
		hndl.Set(NULL);
dvander@1847
   652
	}
dvander@1847
   653
	else
dvander@1847
   654
	{
fyrenmoo@2879
   655
		CBaseEntity *pOther = GetEntity(params[3]);
pred@2746
   656
pred@2746
   657
		if (!pOther)
dvander@1847
   658
		{
pred@2746
   659
			return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[3]), params[3]);
dvander@1847
   660
		}
pred@2746
   661
pred@2746
   662
		IHandleEntity *pHandleEnt = (IHandleEntity *)pOther;
pred@2746
   663
		hndl.Set(pHandleEnt);
dvander@1847
   664
	}
dvander@1847
   665
pred@2746
   666
	if (params[4] && (pEdict != NULL))
dvander@1847
   667
	{
dvander@1847
   668
		g_HL2.SetEdictStateChanged(pEdict, offset);
dvander@1847
   669
	}
dvander@1847
   670
dvander@1847
   671
	return 1;
dvander@1847
   672
}
dvander@1847
   673
dvander@558
   674
static cell_t ChangeEdictState(IPluginContext *pContext, const cell_t *params)
dvander@558
   675
{
dvander@558
   676
	edict_t *pEdict = GetEdict(params[1]);
dvander@558
   677
dvander@558
   678
	if (!pEdict)
dvander@558
   679
	{
pred@2746
   680
		return pContext->ThrowNativeError("Edict %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
dvander@558
   681
	}
dvander@558
   682
dvander@685
   683
	g_HL2.SetEdictStateChanged(pEdict, params[2]);
dvander@558
   684
dvander@558
   685
	return 1;
dvander@558
   686
}
dvander@558
   687
dvander@561
   688
static cell_t FindSendPropOffs(IPluginContext *pContext, const cell_t *params)
dvander@561
   689
{
dvander@561
   690
	char *cls, *prop;
dvander@561
   691
	pContext->LocalToString(params[1], &cls);
dvander@561
   692
	pContext->LocalToString(params[2], &prop);
dvander@561
   693
dvander@561
   694
	SendProp *pSend = g_HL2.FindInSendTable(cls, prop);
dvander@561
   695
dvander@561
   696
	if (!pSend)
dvander@561
   697
	{
dvander@561
   698
		return -1;
dvander@561
   699
	}
dvander@561
   700
dvander@561
   701
	return pSend->GetOffset();
dvander@561
   702
}
dvander@561
   703
dvander@1847
   704
static cell_t FindSendPropInfo(IPluginContext *pContext, const cell_t *params)
dvander@1847
   705
{
dvander@1847
   706
	char *cls, *prop;
dvander@1847
   707
	sm_sendprop_info_t info;
dvander@1847
   708
	cell_t *pType, *pBits, *pLocal;
dvander@1847
   709
dvander@1847
   710
	pContext->LocalToString(params[1], &cls);
dvander@1847
   711
	pContext->LocalToString(params[2], &prop);
dvander@1847
   712
dvander@1847
   713
	if (!g_HL2.FindSendPropInfo(cls, prop, &info))
dvander@1847
   714
	{
dvander@1847
   715
		return -1;
dvander@1847
   716
	}
dvander@1847
   717
dvander@1847
   718
	pContext->LocalToPhysAddr(params[3], &pType);
dvander@1847
   719
	pContext->LocalToPhysAddr(params[4], &pBits);
dvander@1847
   720
	pContext->LocalToPhysAddr(params[5], &pLocal);
dvander@1847
   721
dvander@1847
   722
	switch (info.prop->GetType())
dvander@1847
   723
	{
dvander@1847
   724
	case DPT_Int:
dvander@1847
   725
		{
dvander@1847
   726
			*pType = PropField_Integer;
dvander@1847
   727
			break;
dvander@1847
   728
		}
dvander@1847
   729
	case DPT_Float:
dvander@1847
   730
		{
dvander@1847
   731
			*pType = PropField_Float;
dvander@1847
   732
			break;
dvander@1847
   733
		}
dvander@1847
   734
	case DPT_String:
dvander@1847
   735
		{
dvander@1847
   736
			*pType = PropField_String;
dvander@1847
   737
			break;
dvander@1847
   738
		}
dvander@1847
   739
	case DPT_Vector:
dvander@1847
   740
		{
dvander@1847
   741
			*pType = PropField_Vector;
dvander@1847
   742
			break;
dvander@1847
   743
		}
dvander@1847
   744
	default:
dvander@1847
   745
		{
dvander@1847
   746
			*pType = PropField_Unsupported;
dvander@1847
   747
			break;
dvander@1847
   748
		}
dvander@1847
   749
	}
dvander@1847
   750
dvander@1847
   751
	*pBits = info.prop->m_nBits;
dvander@1847
   752
	*pLocal = info.prop->GetOffset();
dvander@1847
   753
dvander@1847
   754
	return info.actual_offset;
dvander@1847
   755
}
dvander@1847
   756
faluco@682
   757
static cell_t FindDataMapOffs(IPluginContext *pContext, const cell_t *params)
faluco@682
   758
{
faluco@682
   759
	CBaseEntity *pEntity;
faluco@682
   760
	datamap_t *pMap;
faluco@682
   761
	typedescription_t *td;
faluco@682
   762
	char *offset;
fyrenmoo@2879
   763
	pEntity = GetEntity(params[1]);
faluco@682
   764
pred@2746
   765
	if (!pEntity)
faluco@682
   766
	{
pred@2746
   767
		return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
faluco@682
   768
	}
faluco@682
   769
faluco@682
   770
	if ((pMap=CBaseEntity_GetDataDescMap(pEntity)) == NULL)
faluco@682
   771
	{
faluco@682
   772
		return pContext->ThrowNativeError("Unable to retrieve GetDataDescMap offset");
faluco@682
   773
	}
faluco@682
   774
faluco@682
   775
	pContext->LocalToString(params[2], &offset);
faluco@682
   776
	if ((td=g_HL2.FindInDataMap(pMap, offset)) == NULL)
faluco@682
   777
	{
faluco@682
   778
		return -1;
faluco@682
   779
	}
faluco@682
   780
dvander@1847
   781
	if (params[0] == 4)
dvander@1847
   782
	{
dvander@1847
   783
		cell_t *pType, *pSize;
dvander@1847
   784
dvander@1847
   785
		pContext->LocalToPhysAddr(params[3], &pType);
dvander@1847
   786
		pContext->LocalToPhysAddr(params[4], &pSize);
dvander@1847
   787
dvander@1847
   788
		switch (td->fieldType)
dvander@1847
   789
		{
dvander@1847
   790
		case FIELD_TICK:
dvander@1847
   791
		case FIELD_MODELINDEX:
dvander@1847
   792
		case FIELD_MATERIALINDEX:
dvander@1847
   793
		case FIELD_INTEGER:
dvander@1847
   794
		case FIELD_COLOR32:
dvander@1847
   795
			{
dvander@1847
   796
				*pType = PropField_Integer;
dvander@1847
   797
				*pSize = 32;
dvander@1847
   798
				break;
dvander@1847
   799
			}
dvander@1847
   800
		case FIELD_VECTOR:
dvander@1847
   801
		case FIELD_POSITION_VECTOR:
dvander@1847
   802
			{
dvander@1847
   803
				*pType = PropField_Vector;
dvander@1847
   804
				*pSize = 12;
dvander@1847
   805
				break;
dvander@1847
   806
			}
dvander@1847
   807
		case FIELD_SHORT:
dvander@1847
   808
			{
dvander@1847
   809
				*pType = PropField_Integer;
dvander@1847
   810
				*pSize = 16;
dvander@1847
   811
				break;
dvander@1847
   812
			}
dvander@1847
   813
		case FIELD_BOOLEAN:
dvander@1847
   814
			{
dvander@1847
   815
				*pType = PropField_Integer;
dvander@1847
   816
				*pSize = 1;
dvander@1847
   817
				break;
dvander@1847
   818
			}
dvander@1847
   819
		case FIELD_CHARACTER:
dvander@1847
   820
			{
dvander@1847
   821
				if (td->fieldSize == 1)
dvander@1847
   822
				{
dvander@1847
   823
					*pType = PropField_Integer;
dvander@1847
   824
					*pSize = 8;
dvander@1847
   825
				}
dvander@1847
   826
				else
dvander@1847
   827
				{
dvander@1847
   828
					*pType = PropField_String;
dvander@1847
   829
					*pSize = 8 * td->fieldSize;
dvander@1847
   830
				}
dvander@1847
   831
				break;
dvander@1847
   832
			}
dvander@1900
   833
		case FIELD_MODELNAME:
dvander@1900
   834
		case FIELD_SOUNDNAME:
dvander@1884
   835
		case FIELD_STRING:
dvander@1884
   836
			{
dvander@1884
   837
				*pSize = sizeof(string_t);
dvander@1884
   838
				*pType = PropField_String_T;
dvander@1884
   839
				break;
dvander@1884
   840
			}
dvander@1847
   841
		case FIELD_FLOAT:
dvander@1847
   842
		case FIELD_TIME:
dvander@1847
   843
			{
dvander@1847
   844
				*pType = PropField_Float;
dvander@1847
   845
				*pSize = 32;
dvander@1847
   846
				break;
dvander@1847
   847
			}
dvander@1847
   848
		case FIELD_EHANDLE:
dvander@1847
   849
			{
dvander@1847
   850
				*pType = PropField_Entity;
dvander@1847
   851
				*pSize = 32;
dvander@1847
   852
				break;
dvander@1847
   853
			}
dvander@1847
   854
		default:
dvander@1847
   855
			{
dvander@1847
   856
				*pType = PropField_Unsupported;
dvander@1847
   857
				*pSize = 0;
dvander@1847
   858
			}
dvander@1847
   859
		}
dvander@1847
   860
	}
dvander@1847
   861
faluco@682
   862
	return td->fieldOffset[TD_OFFSET_NORMAL];
faluco@682
   863
}
faluco@682
   864
faluco@694
   865
static cell_t GetEntDataString(IPluginContext *pContext, const cell_t *params)
faluco@694
   866
{
fyrenmoo@2879
   867
	CBaseEntity *pEntity = GetEntity(params[1]);
faluco@694
   868
pred@2746
   869
	if (!pEntity)
faluco@694
   870
	{
pred@2746
   871
		return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
faluco@694
   872
	}
faluco@694
   873
faluco@694
   874
	int offset = params[2];
faluco@694
   875
	if (offset < 0 || offset > 32768)
faluco@694
   876
	{
faluco@694
   877
		return pContext->ThrowNativeError("Offset %d is invalid", offset);
faluco@694
   878
	}
faluco@694
   879
faluco@694
   880
	size_t len;
faluco@694
   881
	char *src = (char *)((uint8_t *)pEntity + offset);
faluco@694
   882
	pContext->StringToLocalUTF8(params[3], params[4], src, &len);
faluco@694
   883
faluco@694
   884
	return len;
faluco@694
   885
}
faluco@694
   886
faluco@694
   887
static cell_t SetEntDataString(IPluginContext *pContext, const cell_t *params)
faluco@694
   888
{
faluco@694
   889
	CBaseEntity *pEntity;
fyrenmoo@2879
   890
	edict_t *pEdict;
faluco@694
   891
fyrenmoo@2879
   892
	if (!IndexToAThings(params[1], &pEntity, &pEdict))
faluco@694
   893
	{
pred@2746
   894
		return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
faluco@694
   895
	}
faluco@694
   896
faluco@694
   897
	int offset = params[2];
faluco@694
   898
	if (offset < 0 || offset > 32768)
faluco@694
   899
	{
faluco@694
   900
		return pContext->ThrowNativeError("Offset %d is invalid", offset);
faluco@694
   901
	}
faluco@694
   902
faluco@694
   903
	char *src;
faluco@694
   904
	char *dest = (char *)((uint8_t *)pEntity + offset);
faluco@694
   905
faluco@694
   906
	pContext->LocalToString(params[3], &src);
faluco@694
   907
	size_t len = strncopy(dest, src, params[4]);
faluco@694
   908
pred@2746
   909
	if (params[5] && (pEdict != NULL))
faluco@694
   910
	{
faluco@694
   911
		g_HL2.SetEdictStateChanged(pEdict, offset);
faluco@694
   912
	}
faluco@694
   913
faluco@694
   914
	return len;
faluco@694
   915
}
faluco@694
   916
dvander@1847
   917
#define FIND_PROP_DATA(td) \
dvander@1847
   918
	datamap_t *pMap; \
dvander@1847
   919
	if ((pMap = CBaseEntity_GetDataDescMap(pEntity)) == NULL) \
dvander@1847
   920
	{ \
dvander@1847
   921
		return pContext->ThrowNativeError("Could not retrieve datamap"); \
dvander@1847
   922
	} \
dvander@1847
   923
	if ((td = g_HL2.FindInDataMap(pMap, prop)) == NULL) \
dvander@1847
   924
	{ \
dvander@1847
   925
		return pContext->ThrowNativeError("Property \"%s\" not found (entity %d/%s)", \
dvander@1847
   926
			prop, \
dvander@1847
   927
			params[1], \
dvander@1847
   928
			class_name); \
dvander@1847
   929
	}
dvander@1847
   930
dvander@1847
   931
#define FIND_PROP_SEND(pProp) \
pred@2746
   932
	IServerUnknown *pUnk = (IServerUnknown *)pEntity; \
pred@2746
   933
	IServerNetworkable *pNet = pUnk->GetNetworkable(); \
dvander@1847
   934
	if (!pNet) \
dvander@1847
   935
	{ \
pred@2746
   936
		return pContext->ThrowNativeError("Edict %d (%d) is not networkable", g_HL2.ReferenceToIndex(params[1]), params[1]); \
dvander@1847
   937
	} \
dvander@1847
   938
	if (!g_HL2.FindSendPropInfo(pNet->GetServerClass()->GetName(), prop, pProp)) \
dvander@1847
   939
	{ \
dvander@1847
   940
		return pContext->ThrowNativeError("Property \"%s\" not found (entity %d/%s)", \
dvander@1847
   941
			prop, \
dvander@1847
   942
			params[1], \
dvander@1847
   943
			class_name); \
dvander@1847
   944
	}
dvander@1847
   945
dvander@1847
   946
inline int MatchFieldAsInteger(int field_type)
dvander@1847
   947
{
dvander@1847
   948
	switch (field_type)
dvander@1847
   949
	{
dvander@1847
   950
	case FIELD_TICK:
dvander@1847
   951
	case FIELD_MODELINDEX:
dvander@1847
   952
	case FIELD_MATERIALINDEX:
dvander@1847
   953
	case FIELD_INTEGER:
dvander@1847
   954
	case FIELD_COLOR32:
dvander@1847
   955
		return 32;
dvander@1847
   956
	case FIELD_SHORT:
dvander@1847
   957
		return 16;
dvander@1847
   958
	case FIELD_CHARACTER:
dvander@1847
   959
		return 8;
dvander@1847
   960
	case FIELD_BOOLEAN:
dvander@1847
   961
		return 1;
dvander@1847
   962
	default:
dvander@1847
   963
		return 0;
dvander@1847
   964
	}
dvander@1847
   965
dvander@1847
   966
	return 0;
dvander@1847
   967
}
dvander@1847
   968
dvander@1847
   969
static cell_t GetEntProp(IPluginContext *pContext, const cell_t *params)
dvander@1847
   970
{
dvander@1847
   971
	CBaseEntity *pEntity;
dvander@1847
   972
	char *prop;
dvander@1847
   973
	int offset;
dvander@1847
   974
	const char *class_name;
dvander@1847
   975
	edict_t *pEdict;
dvander@1847
   976
	int bit_count;
dvander@1847
   977
fyrenmoo@2879
   978
	if (!IndexToAThings(params[1], &pEntity, &pEdict))
dvander@1847
   979
	{
pred@2746
   980
		return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
dvander@1847
   981
	}
dvander@1847
   982
pred@2746
   983
	/* TODO: Find a way to lookup classname without having an edict - Is this a guaranteed prop? */
pred@2746
   984
	if (!pEdict || (class_name = pEdict->GetClassName()) == NULL)
dvander@1847
   985
	{
dvander@1847
   986
		class_name = "";
dvander@1847
   987
	}
dvander@1847
   988
dvander@1847
   989
	pContext->LocalToString(params[3], &prop);
dvander@1847
   990
dvander@1847
   991
	switch (params[2])
dvander@1847
   992
	{
dvander@1847
   993
	case Prop_Data:
dvander@1847
   994
		{
dvander@1847
   995
			typedescription_t *td;
dvander@1847
   996
dvander@1847
   997
			FIND_PROP_DATA(td);
dvander@1847
   998
dvander@1847
   999
			if ((bit_count = MatchFieldAsInteger(td->fieldType)) == 0)
dvander@1847
  1000
			{
dvander@1847
  1001
				return pContext->ThrowNativeError("Data field %s is not an integer (%d)", 
dvander@1847
  1002
					prop,
dvander@1847
  1003
					td->fieldType);
dvander@1847
  1004
			}
dvander@1847
  1005
dvander@1847
  1006
			offset = td->fieldOffset[TD_OFFSET_NORMAL];
dvander@1847
  1007
			break;
dvander@1847
  1008
		}
dvander@1847
  1009
	case Prop_Send:
dvander@1847
  1010
		{
dvander@1847
  1011
			sm_sendprop_info_t info;
dvander@1847
  1012
dvander@1847
  1013
			FIND_PROP_SEND(&info);
dvander@1847
  1014
dvander@1847
  1015
			if (info.prop->GetType() != DPT_Int)
dvander@1847
  1016
			{
dvander@1847
  1017
				return pContext->ThrowNativeError("SendProp %s is not an integer ([%d,%d] != %d)",
dvander@1847
  1018
					prop,
dvander@1847
  1019
					info.prop->GetType(),
dvander@1847
  1020
					info.prop->m_nBits,
dvander@1847
  1021
					DPT_Int);
dvander@1847
  1022
			}
dvander@1847
  1023
dvander@1847
  1024
			bit_count = info.prop->m_nBits;
dvander@1847
  1025
			offset = info.actual_offset;
dvander@1847
  1026
			break;
dvander@1847
  1027
		}
dvander@1847
  1028
	default:
dvander@1847
  1029
		{
dvander@1847
  1030
			return pContext->ThrowNativeError("Invalid Property type %d", params[2]);
dvander@1847
  1031
		}
dvander@1847
  1032
	}
dvander@1847
  1033
dvander@1847
  1034
	if (bit_count < 1)
dvander@1847
  1035
	{
dvander@1847
  1036
		bit_count = params[4] * 8;
dvander@1847
  1037
	}
dvander@1847
  1038
dvander@1847
  1039
	if (bit_count >= 17)
dvander@1847
  1040
	{
dvander@1847
  1041
		return *(int32_t *)((uint8_t *)pEntity + offset);
dvander@1847
  1042
	}
dvander@1847
  1043
	else if (bit_count >= 9)
dvander@1847
  1044
	{
dvander@1847
  1045
		return *(int16_t *)((uint8_t *)pEntity + offset);
dvander@1847
  1046
	}
dvander@1847
  1047
	else if (bit_count >= 2)
dvander@1847
  1048
	{
dvander@1847
  1049
		return *(int8_t *)((uint8_t *)pEntity + offset);
dvander@1847
  1050
	}
dvander@1847
  1051
	else
dvander@1847
  1052
	{
dvander@1847
  1053
		return *(bool *)((uint8_t *)pEntity + offset) ? 1 : 0;
dvander@1847
  1054
	}
dvander@1847
  1055
dvander@1847
  1056
	return 0;
dvander@1847
  1057
}
dvander@1847
  1058
dvander@1847
  1059
static cell_t SetEntProp(IPluginContext *pContext, const cell_t *params)
faluco@694
  1060
{
faluco@694
  1061
	CBaseEntity *pEntity;
faluco@694
  1062
	char *prop;
faluco@694
  1063
	int offset;
dvander@1847
  1064
	const char *class_name;
dvander@1847
  1065
	edict_t *pEdict;
dvander@1847
  1066
	int bit_count;
dvander@1847
  1067
fyrenmoo@2879
  1068
	if (!IndexToAThings(params[1], &pEntity, &pEdict))
dvander@1847
  1069
	{
pred@2746
  1070
		return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
dvander@1847
  1071
	}
dvander@1847
  1072
pred@2746
  1073
	if (!pEdict || (class_name = pEdict->GetClassName()) == NULL)
dvander@1847
  1074
	{
dvander@1847
  1075
		class_name = "";
dvander@1847
  1076
	}
dvander@1847
  1077
dvander@1847
  1078
	pContext->LocalToString(params[3], &prop);
dvander@1847
  1079
dvander@1847
  1080
	switch (params[2])
dvander@1847
  1081
	{
dvander@1847
  1082
	case Prop_Data:
dvander@1847
  1083
		{
dvander@1847
  1084
			typedescription_t *td;
dvander@1847
  1085
dvander@1847
  1086
			FIND_PROP_DATA(td);
dvander@1847
  1087
dvander@1847
  1088
			if ((bit_count = MatchFieldAsInteger(td->fieldType)) == 0)
dvander@1847
  1089
			{
dvander@1847
  1090
				return pContext->ThrowNativeError("Data field %s is not an integer (%d)", 
dvander@1847
  1091
					prop,
dvander@1847
  1092
					td->fieldType);
dvander@1847
  1093
			}
dvander@1847
  1094
dvander@1847
  1095
			offset = td->fieldOffset[TD_OFFSET_NORMAL];
dvander@1847
  1096
			break;
dvander@1847
  1097
		}
dvander@1847
  1098
	case Prop_Send:
dvander@1847
  1099
		{
dvander@1847
  1100
			sm_sendprop_info_t info;
dvander@1847
  1101
dvander@1847
  1102
			FIND_PROP_SEND(&info);
dvander@1847
  1103
dvander@1847
  1104
			if (info.prop->GetType() != DPT_Int)
dvander@1847
  1105
			{
dvander@1847
  1106
				return pContext->ThrowNativeError("SendProp %s is not an integer ([%d,%d] != %d)",
dvander@1847
  1107
					prop,
dvander@1847
  1108
					info.prop->GetType(),
dvander@1847
  1109
					info.prop->m_nBits,
dvander@1847
  1110
					DPT_Int);
dvander@1847
  1111
			}
dvander@1847
  1112
dvander@1847
  1113
			bit_count = info.prop->m_nBits;
dvander@1847
  1114
			offset = info.actual_offset;
dvander@1847
  1115
			break;
dvander@1847
  1116
		}
dvander@1847
  1117
	default:
dvander@1847
  1118
		{
dvander@1847
  1119
			return pContext->ThrowNativeError("Invalid Property type %d", params[2]);
dvander@1847
  1120
		}
dvander@1847
  1121
	}
dvander@1847
  1122
dvander@1847
  1123
	if (bit_count < 1)
dvander@1847
  1124
	{
dvander@1847
  1125
		bit_count = params[5] * 8;
dvander@1847
  1126
	}
dvander@1847
  1127
dvander@1847
  1128
	if (bit_count >= 17)
dvander@1847
  1129
	{
dvander@1847
  1130
		*(int32_t *)((uint8_t *)pEntity + offset) = params[4];
dvander@1847
  1131
	}
dvander@1847
  1132
	else if (bit_count >= 9)
dvander@1847
  1133
	{
dvander@1847
  1134
		*(int16_t *)((uint8_t *)pEntity + offset) = (int16_t)params[4];
dvander@1847
  1135
	}
dvander@1847
  1136
	else if (bit_count >= 2)
dvander@1847
  1137
	{
dvander@1847
  1138
		*(int8_t *)((uint8_t *)pEntity + offset) = (int8_t)params[4];
dvander@1847
  1139
	}
dvander@1847
  1140
	else
dvander@1847
  1141
	{
dvander@1847
  1142
		*(bool *)((uint8_t *)pEntity + offset) = params[4] ? true : false;
dvander@1847
  1143
	}
dvander@1847
  1144
dvander@1847
  1145
	return 0;
dvander@1847
  1146
}
dvander@1847
  1147
dvander@1847
  1148
static cell_t GetEntPropFloat(IPluginContext *pContext, const cell_t *params)
dvander@1847
  1149
{
dvander@1847
  1150
	CBaseEntity *pEntity;
dvander@1847
  1151
	char *prop;
dvander@1847
  1152
	int offset;
dvander@1847
  1153
	const char *class_name;
dvander@1847
  1154
	edict_t *pEdict;
dvander@1847
  1155
fyrenmoo@2879
  1156
	if (!IndexToAThings(params[1], &pEntity, &pEdict))
dvander@1847
  1157
	{
pred@2746
  1158
		return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
dvander@1847
  1159
	}
dvander@1847
  1160
pred@2746
  1161
	if (!pEdict || (class_name = pEdict->GetClassName()) == NULL)
dvander@1847
  1162
	{
dvander@1847
  1163
		class_name = "";
dvander@1847
  1164
	}
dvander@1847
  1165
dvander@1847
  1166
	pContext->LocalToString(params[3], &prop);
dvander@1847
  1167
dvander@1847
  1168
	switch (params[2])
dvander@1847
  1169
	{
dvander@1847
  1170
	case Prop_Data:
dvander@1847
  1171
		{
dvander@1847
  1172
			typedescription_t *td;
dvander@1847
  1173
dvander@1847
  1174
			FIND_PROP_DATA(td);
dvander@1847
  1175
dvander@1847
  1176
			if (td->fieldType != FIELD_FLOAT
dvander@1847
  1177
				&& td->fieldType != FIELD_TIME)
dvander@1847
  1178
			{
dvander@1847
  1179
				return pContext->ThrowNativeError("Data field %s is not a float (%d != [%d,%d])", 
dvander@1847
  1180
					prop,
dvander@1847
  1181
					td->fieldType,
dvander@1847
  1182
					FIELD_FLOAT,
dvander@1847
  1183
					FIELD_TIME);
dvander@1847
  1184
			}
dvander@1847
  1185
dvander@1847
  1186
			offset = td->fieldOffset[TD_OFFSET_NORMAL];
dvander@1847
  1187
			break;
dvander@1847
  1188
		}
dvander@1847
  1189
	case Prop_Send:
dvander@1847
  1190
		{
dvander@1847
  1191
			sm_sendprop_info_t info;
dvander@1847
  1192
dvander@1847
  1193
			FIND_PROP_SEND(&info);
dvander@1847
  1194
dvander@1847
  1195
			if (info.prop->GetType() != DPT_Float)
dvander@1847
  1196
			{
dvander@1847
  1197
				return pContext->ThrowNativeError("SendProp %s is not a float (%d != %d)",
dvander@1847
  1198
					prop,
dvander@1847
  1199
					info.prop->GetType(),
dvander@1847
  1200
					DPT_Float);
dvander@1847
  1201
			}
dvander@1847
  1202
dvander@1847
  1203
			offset = info.actual_offset;
dvander@1847
  1204
			break;
dvander@1847
  1205
		}
dvander@1847
  1206
	default:
dvander@1847
  1207
		{
dvander@1847
  1208
			return pContext->ThrowNativeError("Invalid Property type %d", params[2]);
dvander@1847
  1209
		}
dvander@1847
  1210
	}
dvander@1847
  1211
dvander@1847
  1212
	float val = *(float *)((uint8_t *)pEntity + offset);
dvander@1847
  1213
dvander@1847
  1214
	return sp_ftoc(val);
dvander@1847
  1215
}
dvander@1847
  1216
dvander@1847
  1217
static cell_t SetEntPropFloat(IPluginContext *pContext, const cell_t *params)
dvander@1847
  1218
{
dvander@1847
  1219
	CBaseEntity *pEntity;
dvander@1847
  1220
	char *prop;
dvander@1847
  1221
	int offset;
dvander@1847
  1222
	const char *class_name;
dvander@1847
  1223
	edict_t *pEdict;
dvander@1847
  1224
fyrenmoo@2879
  1225
	if (!IndexToAThings(params[1], &pEntity, &pEdict))
faluco@694
  1226
	{
pred@2746
  1227
		return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
faluco@694
  1228
	}
faluco@694
  1229
pred@2746
  1230
	if (!pEdict || (class_name = pEdict->GetClassName()) == NULL)
dvander@1847
  1231
	{
dvander@1847
  1232
		class_name = "";
dvander@1847
  1233
	}
dvander@1847
  1234
dvander@1847
  1235
	pContext->LocalToString(params[3], &prop);
dvander@1847
  1236
faluco@694
  1237
	switch (params[2])
faluco@694
  1238
	{
faluco@694
  1239
	case Prop_Data:
faluco@694
  1240
		{
faluco@694
  1241
			typedescription_t *td;
dvander@1847
  1242
dvander@1847
  1243
			FIND_PROP_DATA(td);
dvander@1847
  1244
dvander@1847
  1245
			if (td->fieldType != FIELD_FLOAT
dvander@1847
  1246
				&& td->fieldType != FIELD_TIME)
faluco@694
  1247
			{
dvander@1847
  1248
				return pContext->ThrowNativeError("Data field %s is not a float (%d != [%d,%d])", 
dvander@1847
  1249
					prop,
dvander@1847
  1250
					td->fieldType,
dvander@1847
  1251
					FIELD_FLOAT,
dvander@1847
  1252
					FIELD_TIME);
dvander@1847
  1253
			}
dvander@1847
  1254
dvander@1847
  1255
			offset = td->fieldOffset[TD_OFFSET_NORMAL];
dvander@1847
  1256
			break;
dvander@1847
  1257
		}
dvander@1847
  1258
	case Prop_Send:
dvander@1847
  1259
		{
dvander@1847
  1260
			sm_sendprop_info_t info;
dvander@1847
  1261
dvander@1847
  1262
			FIND_PROP_SEND(&info);
dvander@1847
  1263
dvander@1847
  1264
			if (info.prop->GetType() != DPT_Float)
dvander@1847
  1265
			{
dvander@1847
  1266
				return pContext->ThrowNativeError("SendProp %s is not a float (%d != %d)",
dvander@1847
  1267
					prop,
dvander@1847
  1268
					info.prop->GetType(),
dvander@1847
  1269
					DPT_Float);
faluco@694
  1270
			}
dvander@1847
  1271
dvander@1847
  1272
			offset = info.actual_offset;
dvander@1847
  1273
			break;
dvander@1847
  1274
		}
dvander@1847
  1275
	default:
dvander@1847
  1276
		{
dvander@1847
  1277
			return pContext->ThrowNativeError("Invalid Property type %d", params[2]);
dvander@1847
  1278
		}
dvander@1847
  1279
	}
dvander@1847
  1280
dvander@1847
  1281
	*(float *)((uint8_t *)pEntity + offset) = sp_ctof(params[4]);
dvander@1847
  1282
pred@2746
  1283
	if (params[2] == Prop_Send && (pEdict != NULL))
dvander@1847
  1284
	{
dvander@1847
  1285
		g_HL2.SetEdictStateChanged(pEdict, offset);
dvander@1847
  1286
	}
dvander@1847
  1287
dvander@1847
  1288
	return 1;
dvander@1847
  1289
}
dvander@1847
  1290
dvander@1847
  1291
static cell_t GetEntPropEnt(IPluginContext *pContext, const cell_t *params)
dvander@1847
  1292
{
dvander@1847
  1293
	CBaseEntity *pEntity;
dvander@1847
  1294
	char *prop;
dvander@1847
  1295
	int offset;
dvander@1847
  1296
	const char *class_name;
dvander@1847
  1297
	edict_t *pEdict;
dvander@1847
  1298
fyrenmoo@2879
  1299
	if (!IndexToAThings(params[1], &pEntity, &pEdict))
dvander@1847
  1300
	{
pred@2746
  1301
		return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
dvander@1847
  1302
	}
dvander@1847
  1303
pred@2746
  1304
	if (!pEdict || (class_name = pEdict->GetClassName()) == NULL)
dvander@1847
  1305
	{
dvander@1847
  1306
		class_name = "";
dvander@1847
  1307
	}
dvander@1847
  1308
dvander@1847
  1309
	pContext->LocalToString(params[3], &prop);
dvander@1847
  1310
dvander@1847
  1311
	switch (params[2])
dvander@1847
  1312
	{
dvander@1847
  1313
	case Prop_Data:
dvander@1847
  1314
		{
dvander@1847
  1315
			typedescription_t *td;
dvander@1847
  1316
dvander@1847
  1317
			FIND_PROP_DATA(td);
dvander@1847
  1318
dvander@1847
  1319
			if (td->fieldType != FIELD_EHANDLE)
faluco@694
  1320
			{
dvander@1847
  1321
				return pContext->ThrowNativeError("Data field %s is not an entity (%d != %d)", 
dvander@1847
  1322
					prop,
dvander@1847
  1323
					td->fieldType,
dvander@1847
  1324
					FIELD_EHANDLE);
faluco@694
  1325
			}
dvander@1847
  1326
dvander@1847
  1327
			offset = td->fieldOffset[TD_OFFSET_NORMAL];
dvander@1847
  1328
			break;
dvander@1847
  1329
		}
dvander@1847
  1330
	case Prop_Send:
dvander@1847
  1331
		{
dvander@1847
  1332
			sm_sendprop_info_t info;
dvander@1847
  1333
dvander@1847
  1334
			FIND_PROP_SEND(&info);
dvander@1847
  1335
dvander@1847
  1336
			if (info.prop->GetType() != DPT_Int)
faluco@694
  1337
			{
dvander@1847
  1338
				return pContext->ThrowNativeError("SendProp %s is not an integer (%d != %d)",
dvander@1847
  1339
					prop,
dvander@1847
  1340
					info.prop->GetType(),
dvander@1847
  1341
					DPT_Int);
faluco@694
  1342
			}
dvander@1847
  1343
dvander@1847
  1344
			offset = info.actual_offset;
dvander@1847
  1345
			break;
dvander@1847
  1346
		}
dvander@1847
  1347
	default:
dvander@1847
  1348
		{
dvander@1847
  1349
			return pContext->ThrowNativeError("Invalid Property type %d", params[2]);
dvander@1847
  1350
		}
dvander@1847
  1351
	}
dvander@1847
  1352
dvander@1847
  1353
	CBaseHandle &hndl = *(CBaseHandle *)((uint8_t *)pEntity + offset);
dvander@1847
  1354
pred@2746
  1355
	int ref = g_HL2.IndexToReference(hndl.GetEntryIndex());
pred@2746
  1356
	return g_HL2.ReferenceToBCompatRef(ref);
dvander@1847
  1357
}
dvander@1847
  1358
dvander@1847
  1359
static cell_t SetEntPropEnt(IPluginContext *pContext, const cell_t *params)
dvander@1847
  1360
{
dvander@1847
  1361
	CBaseEntity *pEntity;
dvander@1847
  1362
	char *prop;
dvander@1847
  1363
	int offset;
dvander@1847
  1364
	const char *class_name;
dvander@1847
  1365
	edict_t *pEdict;
dvander@1847
  1366
fyrenmoo@2879
  1367
	if (!IndexToAThings(params[1], &pEntity, &pEdict))
dvander@1847
  1368
	{
pred@2746
  1369
		return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
dvander@1847
  1370
	}
dvander@1847
  1371
pred@2746
  1372
	if (!pEdict || (class_name = pEdict->GetClassName()) == NULL)
dvander@1847
  1373
	{
dvander@1847
  1374
		class_name = "";
dvander@1847
  1375
	}
dvander@1847
  1376
dvander@1847
  1377
	pContext->LocalToString(params[3], &prop);
dvander@1847
  1378
dvander@1847
  1379
	switch (params[2])
dvander@1847
  1380
	{
dvander@1847
  1381
	case Prop_Data:
dvander@1847
  1382
		{
dvander@1847
  1383
			typedescription_t *td;
dvander@1847
  1384
dvander@1847
  1385
			FIND_PROP_DATA(td);
dvander@1847
  1386
dvander@1847
  1387
			if (td->fieldType != FIELD_EHANDLE)
dvander@1847
  1388
			{
dvander@1847
  1389
				return pContext->ThrowNativeError("Data field %s is not an entity (%d != %d)", 
dvander@1847
  1390
					prop,
dvander@1847
  1391
					td->fieldType,
dvander@1847
  1392
					FIELD_EHANDLE);
dvander@1847
  1393
			}
dvander@1847
  1394
faluco@694
  1395
			offset = td->fieldOffset[TD_OFFSET_NORMAL];
faluco@694
  1396
			break;
faluco@694
  1397
		}
faluco@694
  1398
	case Prop_Send:
faluco@694
  1399
		{
dvander@1847
  1400
			sm_sendprop_info_t info;
dvander@1847
  1401
dvander@1847
  1402
			FIND_PROP_SEND(&info);
dvander@1847
  1403
dvander@1847
  1404
			if (info.prop->GetType() != DPT_Int)
faluco@694
  1405
			{
dvander@1847
  1406
				return pContext->ThrowNativeError("SendProp %s is not an integer (%d != %d)",
dvander@1847
  1407
					prop,
dvander@1847
  1408
					info.prop->GetType(),
dvander@1847
  1409
					DPT_Int);
dvander@1847
  1410
			}
dvander@1847
  1411
dvander@1847
  1412
			offset = info.actual_offset;
dvander@1847
  1413
			break;
dvander@1847
  1414
		}
dvander@1847
  1415
	default:
dvander@1847
  1416
		{
dvander@1847
  1417
			return pContext->ThrowNativeError("Invalid Property type %d", params[2]);
dvander@1847
  1418
		}
dvander@1847
  1419
	}
dvander@1847
  1420
dvander@1847
  1421
	CBaseHandle &hndl = *(CBaseHandle *)((uint8_t *)pEntity + offset);
dvander@1847
  1422
dvander@1847
  1423
	if (params[4] == -1)
dvander@1847
  1424
	{
dvander@1847
  1425
		hndl.Set(NULL);
dvander@1847
  1426
	}
dvander@1847
  1427
	else
dvander@1847
  1428
	{
fyrenmoo@2879
  1429
		CBaseEntity *pOther = GetEntity(params[4]);
dvander@1847
  1430
pred@2746
  1431
		if (!pOther)
dvander@1847
  1432
		{
pred@2746
  1433
			return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[4]), params[4]);
dvander@1847
  1434
		}
dvander@1847
  1435
pred@2746
  1436
		IHandleEntity *pHandleEnt = (IHandleEntity *)pOther;
pred@2746
  1437
		hndl.Set(pHandleEnt);
dvander@1847
  1438
	}
dvander@1847
  1439
pred@2746
  1440
	if (params[2] == Prop_Send && (pEdict != NULL))
dvander@1847
  1441
	{
dvander@1847
  1442
		g_HL2.SetEdictStateChanged(pEdict, offset);
dvander@1847
  1443
	}
dvander@1847
  1444
dvander@1847
  1445
	return 1;
dvander@1847
  1446
}
dvander@1847
  1447
dvander@1847
  1448
static cell_t GetEntPropVector(IPluginContext *pContext, const cell_t *params)
dvander@1847
  1449
{
dvander@1847
  1450
	CBaseEntity *pEntity;
dvander@1847
  1451
	char *prop;
dvander@1847
  1452
	int offset;
dvander@1847
  1453
	const char *class_name;
dvander@1847
  1454
	edict_t *pEdict;
dvander@1847
  1455
	
fyrenmoo@2879
  1456
	if (!IndexToAThings(params[1], &pEntity, &pEdict))
dvander@1847
  1457
	{
pred@2746
  1458
		return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
dvander@1847
  1459
	}
dvander@1847
  1460
pred@2746
  1461
	if (!pEdict || (class_name = pEdict->GetClassName()) == NULL)
dvander@1847
  1462
	{
dvander@1847
  1463
		class_name = "";
dvander@1847
  1464
	}
dvander@1847
  1465
dvander@1847
  1466
	pContext->LocalToString(params[3], &prop);
dvander@1847
  1467
dvander@1847
  1468
	switch (params[2])
dvander@1847
  1469
	{
dvander@1847
  1470
	case Prop_Data:
dvander@1847
  1471
		{
dvander@1847
  1472
			typedescription_t *td;
dvander@1847
  1473
			
dvander@1847
  1474
			FIND_PROP_DATA(td);
dvander@1847
  1475
dvander@1847
  1476
			if (td->fieldType != FIELD_VECTOR
dvander@1847
  1477
				&& td->fieldType != FIELD_POSITION_VECTOR)
dvander@1847
  1478
			{
dvander@1847
  1479
				return pContext->ThrowNativeError("Data field %s is not a vector (%d != [%d,%d])", 
dvander@1847
  1480
					prop,
dvander@1847
  1481
					td->fieldType,
dvander@1847
  1482
					FIELD_VECTOR,
dvander@1847
  1483
					FIELD_POSITION_VECTOR);
dvander@1847
  1484
			}
dvander@1847
  1485
dvander@1847
  1486
			offset = td->fieldOffset[TD_OFFSET_NORMAL];
dvander@1847
  1487
			break;
dvander@1847
  1488
		}
dvander@1847
  1489
	case Prop_Send:
dvander@1847
  1490
		{
dvander@1847
  1491
			sm_sendprop_info_t info;
dvander@1847
  1492
dvander@1847
  1493
			FIND_PROP_SEND(&info);
dvander@1847
  1494
dvander@1847
  1495
			if (info.prop->GetType() != DPT_Vector)
dvander@1847
  1496
			{
dvander@1847
  1497
				return pContext->ThrowNativeError("SendProp %s is not a vector (%d != %d)",
dvander@1847
  1498
					prop,
dvander@1847
  1499
					info.prop->GetType(),
dvander@1847
  1500
					DPT_Vector);
faluco@694
  1501
			}
dvander@1847
  1502
dvander@1847
  1503
			offset = info.actual_offset;
dvander@1847
  1504
			break;
dvander@1847
  1505
		}
dvander@1847
  1506
	default:
dvander@1847
  1507
		{
dvander@1847
  1508
			return pContext->ThrowNativeError("Invalid Property type %d", params[2]);
dvander@1847
  1509
		}
dvander@1847
  1510
	}
dvander@1847
  1511
dvander@1847
  1512
	Vector *v = (Vector *)((uint8_t *)pEntity + offset);
dvander@1847
  1513
dvander@1847
  1514
	cell_t *vec;
dvander@1847
  1515
	pContext->LocalToPhysAddr(params[4], &vec);
dvander@1847
  1516
dvander@1847
  1517
	vec[0] = sp_ftoc(v->x);
dvander@1847
  1518
	vec[1] = sp_ftoc(v->y);
dvander@1847
  1519
	vec[2] = sp_ftoc(v->z);
dvander@1847
  1520
dvander@1847
  1521
	return 1;
dvander@1847
  1522
}
dvander@1847
  1523
dvander@1847
  1524
static cell_t SetEntPropVector(IPluginContext *pContext, const cell_t *params)
dvander@1847
  1525
{
dvander@1847
  1526
	CBaseEntity *pEntity;
dvander@1847
  1527
	char *prop;
dvander@1847
  1528
	int offset;
dvander@1847
  1529
	const char *class_name;
dvander@1847
  1530
	edict_t *pEdict;
dvander@1847
  1531
	
fyrenmoo@2879
  1532
	if (!IndexToAThings(params[1], &pEntity, &pEdict))
dvander@1847
  1533
	{
pred@2746
  1534
		return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
dvander@1847
  1535
	}
dvander@1847
  1536
pred@2746
  1537
	if (!pEdict || (class_name = pEdict->GetClassName()) == NULL)
dvander@1847
  1538
	{
dvander@1847
  1539
		class_name = "";
dvander@1847
  1540
	}
dvander@1847
  1541
dvander@1847
  1542
	pContext->LocalToString(params[3], &prop);
dvander@1847
  1543
dvander@1847
  1544
	switch (params[2])
dvander@1847
  1545
	{
dvander@1847
  1546
	case Prop_Data:
dvander@1847
  1547
		{
dvander@1847
  1548
			typedescription_t *td;
dvander@1847
  1549
			
dvander@1847
  1550
			FIND_PROP_DATA(td);
dvander@1847
  1551
dvander@1847
  1552
			if (td->fieldType != FIELD_VECTOR
dvander@1847
  1553
				&& td->fieldType != FIELD_POSITION_VECTOR)
faluco@694
  1554
			{
dvander@1847
  1555
				return pContext->ThrowNativeError("Data field %s is not a vector (%d != [%d,%d])", 
dvander@1847
  1556
					prop,
dvander@1847
  1557
					td->fieldType,
dvander@1847
  1558
					FIELD_VECTOR,
dvander@1847
  1559
					FIELD_POSITION_VECTOR);
dvander@1847
  1560
			}
dvander@1847
  1561
dvander@1847
  1562
			offset = td->fieldOffset[TD_OFFSET_NORMAL];
dvander@1847
  1563
			break;
dvander@1847
  1564
		}
dvander@1847
  1565
	case Prop_Send:
dvander@1847
  1566
		{
dvander@1847
  1567
			sm_sendprop_info_t info;
dvander@1847
  1568
dvander@1847
  1569
			FIND_PROP_SEND(&info);
dvander@1847
  1570
dvander@1847
  1571
			if (info.prop->GetType() != DPT_Vector)
dvander@1847
  1572
			{
dvander@1847
  1573
				return pContext->ThrowNativeError("SendProp %s is not a vector (%d != %d)",
dvander@1847
  1574
					prop,
dvander@1847
  1575
					info.prop->GetType(),
dvander@1847
  1576
					DPT_Vector);
faluco@694
  1577
			}
dvander@1847
  1578
dvander@1847
  1579
			offset = info.actual_offset;
dvander@1847
  1580
			break;
dvander@1847
  1581
		}
dvander@1847
  1582
	default:
dvander@1847
  1583
		{
dvander@1847
  1584
			return pContext->ThrowNativeError("Invalid Property type %d", params[2]);
dvander@1847
  1585
		}
dvander@1847
  1586
	}
dvander@1847
  1587
dvander@1847
  1588
	Vector *v = (Vector *)((uint8_t *)pEntity + offset);
dvander@1847
  1589
dvander@1847
  1590
	cell_t *vec;
dvander@1847
  1591
	pContext->LocalToPhysAddr(params[4], &vec);
dvander@1847
  1592
dvander@1847
  1593
	v->x = sp_ctof(vec[0]);
dvander@1847
  1594
	v->y = sp_ctof(vec[1]);
dvander@1847
  1595
	v->z = sp_ctof(vec[2]);
dvander@1847
  1596
pred@2746
  1597
	if (params[2] == Prop_Send && (pEdict != NULL))
dvander@1847
  1598
	{
dvander@1847
  1599
		g_HL2.SetEdictStateChanged(pEdict, offset);
dvander@1847
  1600
	}
dvander@1847
  1601
dvander@1847
  1602
	return 1;
dvander@1847
  1603
}
dvander@1847
  1604
dvander@1847
  1605
static cell_t GetEntPropString(IPluginContext *pContext, const cell_t *params)
dvander@1847
  1606
{
dvander@1847
  1607
	CBaseEntity *pEntity;
dvander@1847
  1608
	char *prop;
dvander@1847
  1609
	int offset;
dvander@1847
  1610
	const char *class_name;
dvander@1847
  1611
	edict_t *pEdict;
dvander@1884
  1612
	bool bIsStringIndex;
dvander@1847
  1613
	
fyrenmoo@2879
  1614
	if (!IndexToAThings(params[1], &pEntity, &pEdict))
dvander@1847
  1615
	{
pred@2746
  1616
		return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
dvander@1847
  1617
	}
dvander@1847
  1618
pred@2746
  1619
	if (!pEdict || (class_name = pEdict->GetClassName()) == NULL)
dvander@1847
  1620
	{
dvander@1847
  1621
		class_name = "";
dvander@1847
  1622
	}
dvander@1847
  1623
dvander@1847
  1624
	pContext->LocalToString(params[3], &prop);
dvander@1847
  1625
dvander@1884
  1626
	bIsStringIndex = false;
dvander@1884
  1627
dvander@1847
  1628
	switch (params[2])
dvander@1847
  1629
	{
dvander@1847
  1630
	case Prop_Data:
dvander@1847
  1631
		{
dvander@1847
  1632
			typedescription_t *td;
dvander@1847
  1633
			
dvander@1847
  1634
			FIND_PROP_DATA(td);
dvander@1847
  1635
dvander@1884
  1636
			if (td->fieldType != FIELD_CHARACTER
dvander@1900
  1637
				&& td->fieldType != FIELD_STRING
dvander@1900
  1638
				&& td->fieldType != FIELD_MODELNAME 
dvander@1900
  1639
				&& td->fieldType != FIELD_SOUNDNAME)
faluco@694
  1640
			{
dvander@1847
  1641
				return pContext->ThrowNativeError("Data field %s is not a string (%d != %d)", 
dvander@1847
  1642
					prop,
dvander@1847
  1643
					td->fieldType,
dvander@1847
  1644
					FIELD_CHARACTER);
faluco@694
  1645
			}
dvander@1847
  1646
dvander@1900
  1647
			bIsStringIndex = (td->fieldType != FIELD_CHARACTER);
dvander@1884
  1648
dvander@1847
  1649
			offset = td->fieldOffset[TD_OFFSET_NORMAL];
dvander@1847
  1650
			break;
dvander@1847
  1651
		}
dvander@1847
  1652
	case Prop_Send:
dvander@1847
  1653
		{
dvander@1847
  1654
			sm_sendprop_info_t info;
dvander@1847
  1655
dvander@1847
  1656
			FIND_PROP_SEND(&info);
dvander@1847
  1657
dvander@1847
  1658
			if (info.prop->GetType() != DPT_String)
dvander@1847
  1659
			{
dvander@1847
  1660
				return pContext->ThrowNativeError("SendProp %s is not a string (%d != %d)",
dvander@1847
  1661
					prop,
dvander@1847
  1662
					info.prop->GetType(),
dvander@1847
  1663
					DPT_String);
dvander@1847
  1664
			}
dvander@1847
  1665
dvander@1847
  1666
			offset = info.actual_offset;
dvander@1847
  1667
			break;
faluco@694
  1668
			break;
faluco@694
  1669
		}
faluco@694
  1670
	default:
faluco@694
  1671
		{
faluco@694
  1672
			return pContext->ThrowNativeError("Invalid Property type %d", params[2]);
faluco@694
  1673
		}
faluco@694
  1674
	}
faluco@694
  1675
faluco@694
  1676
	size_t len;
dvander@1884
  1677
	const char *src; 
dvander@1884
  1678
	
dvander@1884
  1679
	if (!bIsStringIndex)
dvander@1884
  1680
	{
dvander@1884
  1681
		src = (char *)((uint8_t *)pEntity + offset);
dvander@1884
  1682
	}
dvander@1884
  1683
	else
dvander@1884
  1684
	{
dvander@1884
  1685
		string_t idx;
dvander@1884
  1686
dvander@1884
  1687
		idx = *(string_t *)((uint8_t *)pEntity + offset);
dvander@1884
  1688
		src = (idx == NULL_STRING) ? "" : STRING(idx);
dvander@1884
  1689
	}
dvander@1884
  1690
faluco@694
  1691
	pContext->StringToLocalUTF8(params[4], params[5], src, &len);
faluco@694
  1692
faluco@694
  1693
	return len;
faluco@694
  1694
}
faluco@694
  1695
faluco@694
  1696
static cell_t SetEntPropString(IPluginContext *pContext, const cell_t *params)
faluco@694
  1697
{
faluco@694
  1698
	CBaseEntity *pEntity;
faluco@694
  1699
	char *prop;
faluco@694
  1700
	int offset;
faluco@694
  1701
	int maxlen;
fyrenmoo@2879
  1702
	edict_t *pEdict;
faluco@694
  1703
fyrenmoo@2879
  1704
	if (!IndexToAThings(params[1], &pEntity, &pEdict))
faluco@694
  1705
	{
pred@2746
  1706
		return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
faluco@694
  1707
	}
faluco@694
  1708
faluco@694
  1709
	switch (params[2])
faluco@694
  1710
	{
faluco@694
  1711
	case Prop_Data:
faluco@694
  1712
		{
faluco@694
  1713
			datamap_t *pMap;
faluco@694
  1714
			typedescription_t *td;
faluco@694
  1715
			if ((pMap=CBaseEntity_GetDataDescMap(pEntity)) == NULL)
faluco@694
  1716
			{
faluco@694
  1717
				return pContext->ThrowNativeError("Unable to retrieve GetDataDescMap offset");
faluco@694
  1718
			}
faluco@694
  1719
			pContext->LocalToString(params[3], &prop);
faluco@694
  1720
			if ((td=g_HL2.FindInDataMap(pMap, prop)) == NULL)
faluco@694
  1721
			{
faluco@694
  1722
				return pContext->ThrowNativeError("Property \"%s\" not found for entity %d", prop, params[1]);
faluco@694
  1723
			}
faluco@694
  1724
			if (td->fieldType != FIELD_CHARACTER)
faluco@694
  1725
			{
faluco@694
  1726
				return pContext->ThrowNativeError("Property \"%s\" is not a valid string", prop);
faluco@694
  1727
			}
faluco@694
  1728
			offset = td->fieldOffset[TD_OFFSET_NORMAL];
faluco@694
  1729
			maxlen = td->fieldSize;
faluco@694
  1730
			break;
faluco@694
  1731
		}
faluco@694
  1732
	case Prop_Send:
faluco@694
  1733
		{
faluco@694
  1734
			char *prop;
pred@2746
  1735
			IServerUnknown *pUnk = (IServerUnknown *)pEntity;
pred@2746
  1736
			IServerNetworkable *pNet = pUnk->GetNetworkable();
faluco@694
  1737
			if (!pNet)
faluco@694
  1738
			{
faluco@694
  1739
				return pContext->ThrowNativeError("The edict is not networkable");
faluco@694
  1740
			}
faluco@694
  1741
			pContext->LocalToString(params[3], &prop);
faluco@694
  1742
			SendProp *pSend = g_HL2.FindInSendTable(pNet->GetServerClass()->GetName(), prop);
faluco@694
  1743
			if (!pSend)
faluco@694
  1744
			{
faluco@694
  1745
				return pContext->ThrowNativeError("Property \"%s\" not found for entity %d", prop, params[1]);
faluco@694
  1746
			}
faluco@694
  1747
			if (pSend->GetType() != DPT_String)
faluco@694
  1748
			{
faluco@694
  1749
				return pContext->ThrowNativeError("Property \"%s\" is not a valid string", prop);
faluco@694
  1750
			}
faluco@694
  1751
			offset = pSend->GetOffset();
faluco@694
  1752
			maxlen = DT_MAX_STRING_BUFFERSIZE;
faluco@694
  1753
			break;
faluco@694
  1754
		}
faluco@694
  1755
	default:
faluco@694
  1756
		{
faluco@694
  1757
			return pContext->ThrowNativeError("Invalid Property type %d", params[2]);
faluco@694
  1758
		}
faluco@694
  1759
	}
faluco@694
  1760
faluco@694
  1761
	char *src;
faluco@694
  1762
	char *dest = (char *)((uint8_t *)pEntity + offset);
faluco@694
  1763
faluco@694
  1764
	pContext->LocalToString(params[4], &src);
faluco@694
  1765
	size_t len = strncopy(dest, src, maxlen);
faluco@694
  1766
pred@2746
  1767
	if (params[2] == Prop_Send && (pEdict != NULL))
faluco@694
  1768
	{
faluco@694
  1769
		g_HL2.SetEdictStateChanged(pEdict, offset);
faluco@694
  1770
	}
faluco@694
  1771
faluco@694
  1772
	return len;
faluco@694
  1773
}
faluco@694
  1774
dvander@555
  1775
REGISTER_NATIVES(entityNatives)
dvander@555
  1776
{
dvander@558
  1777
	{"ChangeEdictState",		ChangeEdictState},
dvander@555
  1778
	{"CreateEdict",				CreateEdict},
dvander@1847
  1779
	{"FindDataMapOffs",			FindDataMapOffs},
dvander@1847
  1780
	{"FindSendPropInfo",		FindSendPropInfo},
dvander@561
  1781
	{"FindSendPropOffs",		FindSendPropOffs},
dvander@556
  1782
	{"GetEdictClassname",		GetEdictClassname},
dvander@555
  1783
	{"GetEdictFlags",			GetEdictFlags},
dvander@557
  1784
	{"GetEntData",				GetEntData},
dvander@1847
  1785
	{"GetEntDataEnt",			GetEntDataEnt},		/** DEPRECATED */
dvander@1847
  1786
	{"GetEntDataEnt2",			GetEntDataEnt2},
dvander@557
  1787
	{"GetEntDataFloat",			GetEntDataFloat},
dvander@1847
  1788
	{"GetEntDataString",		GetEntDataString},
dvander@557
  1789
	{"GetEntDataVector",		GetEntDataVector},
dvander@1847
  1790
	{"GetEntProp",				GetEntProp},
dvander@1847
  1791
	{"GetEntPropEnt",			GetEntPropEnt},
dvander@1847
  1792
	{"GetEntPropFloat",			GetEntPropFloat},
dvander@1847
  1793
	{"GetEntPropString",		GetEntPropString},
dvander@1847
  1794
	{"GetEntPropVector",		GetEntPropVector},
dvander@603
  1795
	{"GetEntityCount",			GetEntityCount},
dvander@556
  1796
	{"GetEntityNetClass",		GetEntityNetClass},
dvander@555
  1797
	{"GetMaxEntities",			GetMaxEntities},
dvander@555
  1798
	{"IsEntNetworkable",		IsEntNetworkable},
dvander@555
  1799
	{"IsValidEdict",			IsValidEdict},
dvander@555
  1800
	{"IsValidEntity",			IsValidEntity},
dvander@555
  1801
	{"RemoveEdict",				RemoveEdict},
dvander@555
  1802
	{"SetEdictFlags",			SetEdictFlags},
dvander@557
  1803
	{"SetEntData",				SetEntData},
dvander@1847
  1804
	{"SetEntDataEnt",			SetEntDataEnt},		/** DEPRECATED */
dvander@1847
  1805
	{"SetEntDataEnt2",			SetEntDataEnt2},
dvander@557
  1806
	{"SetEntDataFloat",			SetEntDataFloat},
dvander@557
  1807
	{"SetEntDataVector",		SetEntDataVector},
faluco@694
  1808
	{"SetEntDataString",		SetEntDataString},
dvander@1847
  1809
	{"SetEntProp",				SetEntProp},
dvander@1847
  1810
	{"SetEntPropEnt",			SetEntPropEnt},
dvander@1847
  1811
	{"SetEntPropFloat",			SetEntPropFloat},
faluco@694
  1812
	{"SetEntPropString",		SetEntPropString},
dvander@1847
  1813
	{"SetEntPropVector",		SetEntPropVector},
faluco@588
  1814
	{NULL,						NULL}
dvander@555
  1815
};