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