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