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