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