3 * =============================================================================
5 * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
6 * =============================================================================
8 * This program is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License, version 3.0, as published by the
10 * Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
17 * You should have received a copy of the GNU General Public License along with
18 * this program. If not, see <http://www.gnu.org/licenses/>.
20 * As a special exception, AlliedModders LLC gives you permission to link the
21 * code of this program (as well as its derivative works) to "Half-Life 2," the
22 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
23 * by the Valve Corporation. You must obey the GNU General Public License in
24 * all respects for all other code used. Additionally, AlliedModders LLC grants
25 * this exception to all derivative works. AlliedModders LLC defines further
26 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
27 * or <http://www.sourcemod.net/license.php>.
32 #include "sm_globals.h"
33 #include "sourcemod.h"
34 #include "sourcemm_api.h"
35 #include "PlayerManager.h"
36 #include "HalfLife2.h"
37 #include "GameConfigs.h"
38 #include "sm_stringutil.h"
48 PropField_Unsupported, /**< The type is unsupported. */
49 PropField_Integer, /**< Valid for SendProp and Data fields */
50 PropField_Float, /**< Valid for SendProp and Data fields */
51 PropField_Entity, /**< Valid for Data fields only (SendProp shows as int) */
52 PropField_Vector, /**< Valid for SendProp and Data fields */
53 PropField_String, /**< Valid for SendProp and Data fields */
54 PropField_String_T, /**< Valid for Data fields. Read only! */
57 inline edict_t *GetEdict(cell_t num)
59 edict_t *pEdict = engine->PEntityOfEntIndex(num);
60 if (!pEdict || pEdict->IsFree())
64 if (num > 0 && num <= g_Players.GetMaxClients())
66 CPlayer *pPlayer = g_Players.GetPlayerByIndex(num);
67 if (!pPlayer || !pPlayer->IsConnected())
75 inline edict_t *GetEntity(cell_t num, CBaseEntity **pData)
77 edict_t *pEdict = engine->PEntityOfEntIndex(num);
78 if (!pEdict || pEdict->IsFree())
82 if (num > 0 && num <= g_Players.GetMaxClients())
84 CPlayer *pPlayer = g_Players.GetPlayerByIndex(num);
85 if (!pPlayer || !pPlayer->IsConnected())
91 if ((pUnk=pEdict->GetUnknown()) == NULL)
95 *pData = pUnk->GetBaseEntity();
100 datamap_t *VGetDataDescMap(CBaseEntity *pThisPtr, int offset)
102 void **this_ptr = *reinterpret_cast<void ***>(&pThisPtr);
103 void **vtable = *reinterpret_cast<void ***>(pThisPtr);
104 void *vfunc = vtable[offset];
108 datamap_t *(VEmptyClass::*mfpnew)();
109 #ifndef PLATFORM_POSIX
124 return (datamap_t *)(reinterpret_cast<VEmptyClass *>(this_ptr)->*u.mfpnew)();
127 inline datamap_t *CBaseEntity_GetDataDescMap(CBaseEntity *pEntity)
131 if (!g_pGameConf->GetOffset("GetDataDescMap", &offset) || !offset)
136 return VGetDataDescMap(pEntity, offset);
139 /* :TODO: Move this! */
140 datamap_t *CHalfLife2::GetDataMap(CBaseEntity *pEntity)
142 return CBaseEntity_GetDataDescMap(pEntity);
145 static cell_t GetMaxEntities(IPluginContext *pContext, const cell_t *params)
147 return gpGlobals->maxEntities;
150 static cell_t CreateEdict(IPluginContext *pContext, const cell_t *params)
152 edict_t *pEdict = engine->CreateEdict();
159 return engine->IndexOfEdict(pEdict);
162 static cell_t RemoveEdict(IPluginContext *pContext, const cell_t *params)
164 edict_t *pEdict = engine->PEntityOfEntIndex(params[1]);
168 return pContext->ThrowNativeError("Edict %d is not a valid edict", params[1]);
171 engine->RemoveEdict(pEdict);
176 static cell_t IsValidEdict(IPluginContext *pContext, const cell_t *params)
178 edict_t *pEdict = GetEdict(params[1]);
185 /* Shouldn't be necessary... not sure though */
186 return pEdict->IsFree() ? 0 : 1;
189 static cell_t IsValidEntity(IPluginContext *pContext, const cell_t *params)
191 edict_t *pEdict = GetEdict(params[1]);
198 IServerUnknown *pUnknown = pEdict->GetUnknown();
204 CBaseEntity *pEntity = pUnknown->GetBaseEntity();
205 return (pEntity != NULL) ? 1 : 0;
208 static cell_t IsEntNetworkable(IPluginContext *pContext, const cell_t *params)
210 edict_t *pEdict = GetEdict(params[1]);
217 return (pEdict->GetNetworkable() != NULL) ? 1 : 0;
220 static cell_t GetEntityCount(IPluginContext *pContext, const cell_t *params)
222 return engine->GetEntityCount();
225 static cell_t GetEdictFlags(IPluginContext *pContext, const cell_t *params)
227 edict_t *pEdict = GetEdict(params[1]);
231 return pContext->ThrowNativeError("Invalid edict (%d)", params[1]);
234 return pEdict->m_fStateFlags;
237 static cell_t SetEdictFlags(IPluginContext *pContext, const cell_t *params)
239 edict_t *pEdict = GetEdict(params[1]);
243 return pContext->ThrowNativeError("Invalid edict (%d)", params[1]);
246 pEdict->m_fStateFlags = params[2];
251 static cell_t GetEdictClassname(IPluginContext *pContext, const cell_t *params)
253 edict_t *pEdict = GetEdict(params[1]);
257 return pContext->ThrowNativeError("Invalid edict (%d)", params[1]);
260 const char *cls = pEdict->GetClassName();
262 if (!cls || cls[0] == '\0')
267 pContext->StringToLocal(params[2], params[3], cls);
272 static cell_t GetEntityNetClass(IPluginContext *pContext, const cell_t *params)
274 edict_t *pEdict = GetEdict(params[1]);
278 return pContext->ThrowNativeError("Invalid edict (%d)", params[1]);
281 IServerNetworkable *pNet = pEdict->GetNetworkable();
287 ServerClass *pClass = pNet->GetServerClass();
289 pContext->StringToLocal(params[2], params[3], pClass->GetName());
294 static cell_t GetEntData(IPluginContext *pContext, const cell_t *params)
296 CBaseEntity *pEntity;
297 edict_t *pEdict = GetEntity(params[1], &pEntity);
299 if (!pEdict || !pEntity)
301 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
304 int offset = params[2];
305 if (offset <= 0 || offset > 32768)
307 return pContext->ThrowNativeError("Offset %d is invalid", offset);
313 return *(int *)((uint8_t *)pEntity + offset);
315 return *(short *)((uint8_t *)pEntity + offset);
317 return *((uint8_t *)pEntity + offset);
319 return pContext->ThrowNativeError("Integer size %d is invalid", params[3]);
323 static cell_t SetEntData(IPluginContext *pContext, const cell_t *params)
325 CBaseEntity *pEntity;
326 edict_t *pEdict = GetEntity(params[1], &pEntity);
328 if (!pEdict || !pEntity)
330 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
333 int offset = params[2];
334 if (offset <= 0 || offset > 32768)
336 return pContext->ThrowNativeError("Offset %d is invalid", offset);
341 g_HL2.SetEdictStateChanged(pEdict, offset);
348 *(int *)((uint8_t *)pEntity + offset) = params[3];
353 *(short *)((uint8_t *)pEntity + offset) = params[3];
358 *((uint8_t *)pEntity + offset) = params[3];
362 return pContext->ThrowNativeError("Integer size %d is invalid", params[4]);
368 static cell_t GetEntDataFloat(IPluginContext *pContext, const cell_t *params)
370 CBaseEntity *pEntity;
371 edict_t *pEdict = GetEntity(params[1], &pEntity);
373 if (!pEdict || !pEntity)
375 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
378 int offset = params[2];
379 if (offset <= 0 || offset > 32768)
381 return pContext->ThrowNativeError("Offset %d is invalid", offset);
384 float f = *(float *)((uint8_t *)pEntity + offset);
389 static cell_t SetEntDataFloat(IPluginContext *pContext, const cell_t *params)
391 CBaseEntity *pEntity;
392 edict_t *pEdict = GetEntity(params[1], &pEntity);
394 if (!pEdict || !pEntity)
396 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
399 int offset = params[2];
400 if (offset <= 0 || offset > 32768)
402 return pContext->ThrowNativeError("Offset %d is invalid", offset);
405 *(float *)((uint8_t *)pEntity + offset) = sp_ctof(params[3]);
409 g_HL2.SetEdictStateChanged(pEdict, offset);
415 static cell_t GetEntDataVector(IPluginContext *pContext, const cell_t *params)
417 CBaseEntity *pEntity;
418 edict_t *pEdict = GetEntity(params[1], &pEntity);
420 if (!pEdict || !pEntity)
422 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
425 int offset = params[2];
426 if (offset <= 0 || offset > 32768)
428 return pContext->ThrowNativeError("Offset %d is invalid", offset);
431 Vector *v = (Vector *)((uint8_t *)pEntity + offset);
434 pContext->LocalToPhysAddr(params[3], &vec);
436 vec[0] = sp_ftoc(v->x);
437 vec[1] = sp_ftoc(v->y);
438 vec[2] = sp_ftoc(v->z);
443 static cell_t SetEntDataVector(IPluginContext *pContext, const cell_t *params)
445 CBaseEntity *pEntity;
446 edict_t *pEdict = GetEntity(params[1], &pEntity);
448 if (!pEdict || !pEntity)
450 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
453 int offset = params[2];
454 if (offset <= 0 || offset > 32768)
456 return pContext->ThrowNativeError("Offset %d is invalid", offset);
459 Vector *v = (Vector *)((uint8_t *)pEntity + offset);
462 pContext->LocalToPhysAddr(params[3], &vec);
464 v->x = sp_ctof(vec[0]);
465 v->y = sp_ctof(vec[1]);
466 v->z = sp_ctof(vec[2]);
470 g_HL2.SetEdictStateChanged(pEdict, offset);
476 /* THIS GUY IS DEPRECATED. */
477 static cell_t GetEntDataEnt(IPluginContext *pContext, const cell_t *params)
479 CBaseEntity *pEntity;
480 edict_t *pEdict = GetEntity(params[1], &pEntity);
482 if (!pEdict || !pEntity)
484 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
487 int offset = params[2];
488 if (offset <= 0 || offset > 32768)
490 return pContext->ThrowNativeError("Offset %d is invalid", offset);
493 CBaseHandle &hndl = *(CBaseHandle *)((uint8_t *)pEntity + offset);
500 return hndl.GetEntryIndex();
503 int CheckBaseHandle(CBaseHandle &hndl)
510 int index = hndl.GetEntryIndex();
512 edict_t *pStoredEdict;
513 CBaseEntity *pStoredEntity;
515 pStoredEdict = GetEntity(index, &pStoredEntity);
517 if (pStoredEdict == NULL || pStoredEntity == NULL)
522 IServerEntity *pSE = pStoredEdict->GetIServerEntity();
529 if (pSE->GetRefEHandle() != hndl)
537 static cell_t GetEntDataEnt2(IPluginContext *pContext, const cell_t *params)
539 CBaseEntity *pEntity;
540 edict_t *pEdict = GetEntity(params[1], &pEntity);
542 if (pEdict == NULL || pEntity == NULL)
544 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
547 int offset = params[2];
548 if (offset <= 0 || offset > 32768)
550 return pContext->ThrowNativeError("Offset %d is invalid", offset);
553 CBaseHandle &hndl = *(CBaseHandle *)((uint8_t *)pEntity + offset);
555 return CheckBaseHandle(hndl);
558 /* THIS GUY IS DEPRECATED. */
559 static cell_t SetEntDataEnt(IPluginContext *pContext, const cell_t *params)
561 CBaseEntity *pEntity;
562 edict_t *pEdict = GetEntity(params[1], &pEntity);
564 if (!pEdict || !pEntity)
566 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
569 int offset = params[2];
570 if (offset <= 0 || offset > 32768)
572 return pContext->ThrowNativeError("Offset %d is invalid", offset);
575 CBaseHandle &hndl = *(CBaseHandle *)((uint8_t *)pEntity + offset);
581 edict_t *pEdict = GetEdict(params[3]);
584 return pContext->ThrowNativeError("Entity %d is invalid", params[3]);
586 IServerEntity *pEntOther = pEdict->GetIServerEntity();
592 g_HL2.SetEdictStateChanged(pEdict, offset);
598 static cell_t SetEntDataEnt2(IPluginContext *pContext, const cell_t *params)
600 CBaseEntity *pEntity;
601 edict_t *pEdict = GetEntity(params[1], &pEntity);
603 if (!pEdict || !pEntity)
605 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
608 int offset = params[2];
609 if (offset <= 0 || offset > 32768)
611 return pContext->ThrowNativeError("Offset %d is invalid", offset);
614 CBaseHandle &hndl = *(CBaseHandle *)((uint8_t *)pEntity + offset);
622 edict_t *pEdict = GetEdict(params[3]);
625 return pContext->ThrowNativeError("Entity %d is invalid", params[3]);
627 IServerEntity *pEntOther = pEdict->GetIServerEntity();
633 g_HL2.SetEdictStateChanged(pEdict, offset);
639 static cell_t ChangeEdictState(IPluginContext *pContext, const cell_t *params)
641 edict_t *pEdict = GetEdict(params[1]);
645 return pContext->ThrowNativeError("Edict %d is invalid", params[1]);
648 g_HL2.SetEdictStateChanged(pEdict, params[2]);
653 static cell_t FindSendPropOffs(IPluginContext *pContext, const cell_t *params)
656 pContext->LocalToString(params[1], &cls);
657 pContext->LocalToString(params[2], &prop);
659 SendProp *pSend = g_HL2.FindInSendTable(cls, prop);
666 return pSend->GetOffset();
669 static cell_t FindSendPropInfo(IPluginContext *pContext, const cell_t *params)
672 sm_sendprop_info_t info;
673 cell_t *pType, *pBits, *pLocal;
675 pContext->LocalToString(params[1], &cls);
676 pContext->LocalToString(params[2], &prop);
678 if (!g_HL2.FindSendPropInfo(cls, prop, &info))
683 pContext->LocalToPhysAddr(params[3], &pType);
684 pContext->LocalToPhysAddr(params[4], &pBits);
685 pContext->LocalToPhysAddr(params[5], &pLocal);
687 switch (info.prop->GetType())
691 *pType = PropField_Integer;
696 *pType = PropField_Float;
701 *pType = PropField_String;
706 *pType = PropField_Vector;
711 *pType = PropField_Unsupported;
716 *pBits = info.prop->m_nBits;
717 *pLocal = info.prop->GetOffset();
719 return info.actual_offset;
722 static cell_t FindDataMapOffs(IPluginContext *pContext, const cell_t *params)
724 CBaseEntity *pEntity;
726 typedescription_t *td;
728 edict_t *pEdict = GetEntity(params[1], &pEntity);
730 if (!pEdict || !pEntity)
732 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
735 if ((pMap=CBaseEntity_GetDataDescMap(pEntity)) == NULL)
737 return pContext->ThrowNativeError("Unable to retrieve GetDataDescMap offset");
740 pContext->LocalToString(params[2], &offset);
741 if ((td=g_HL2.FindInDataMap(pMap, offset)) == NULL)
748 cell_t *pType, *pSize;
750 pContext->LocalToPhysAddr(params[3], &pType);
751 pContext->LocalToPhysAddr(params[4], &pSize);
753 switch (td->fieldType)
756 case FIELD_MODELINDEX:
757 case FIELD_MATERIALINDEX:
761 *pType = PropField_Integer;
766 case FIELD_POSITION_VECTOR:
768 *pType = PropField_Vector;
774 *pType = PropField_Integer;
780 *pType = PropField_Integer;
784 case FIELD_CHARACTER:
786 if (td->fieldSize == 1)
788 *pType = PropField_Integer;
793 *pType = PropField_String;
794 *pSize = 8 * td->fieldSize;
798 case FIELD_MODELNAME:
799 case FIELD_SOUNDNAME:
802 *pSize = sizeof(string_t);
803 *pType = PropField_String_T;
809 *pType = PropField_Float;
815 *pType = PropField_Entity;
821 *pType = PropField_Unsupported;
827 return td->fieldOffset[TD_OFFSET_NORMAL];
830 static cell_t GetEntDataString(IPluginContext *pContext, const cell_t *params)
832 CBaseEntity *pEntity;
833 edict_t *pEdict = GetEntity(params[1], &pEntity);
835 if (!pEdict || !pEntity)
837 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
840 int offset = params[2];
841 if (offset < 0 || offset > 32768)
843 return pContext->ThrowNativeError("Offset %d is invalid", offset);
847 char *src = (char *)((uint8_t *)pEntity + offset);
848 pContext->StringToLocalUTF8(params[3], params[4], src, &len);
853 static cell_t SetEntDataString(IPluginContext *pContext, const cell_t *params)
855 CBaseEntity *pEntity;
856 edict_t *pEdict = GetEntity(params[1], &pEntity);
858 if (!pEdict || !pEntity)
860 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
863 int offset = params[2];
864 if (offset < 0 || offset > 32768)
866 return pContext->ThrowNativeError("Offset %d is invalid", offset);
870 char *dest = (char *)((uint8_t *)pEntity + offset);
872 pContext->LocalToString(params[3], &src);
873 size_t len = strncopy(dest, src, params[4]);
877 g_HL2.SetEdictStateChanged(pEdict, offset);
883 #define FIND_PROP_DATA(td) \
885 if ((pMap = CBaseEntity_GetDataDescMap(pEntity)) == NULL) \
887 return pContext->ThrowNativeError("Could not retrieve datamap"); \
889 if ((td = g_HL2.FindInDataMap(pMap, prop)) == NULL) \
891 return pContext->ThrowNativeError("Property \"%s\" not found (entity %d/%s)", \
897 #define FIND_PROP_SEND(pProp) \
898 IServerNetworkable *pNet = pEdict->GetNetworkable(); \
901 return pContext->ThrowNativeError("Edict %d is not networkable", params[1]); \
903 if (!g_HL2.FindSendPropInfo(pNet->GetServerClass()->GetName(), prop, pProp)) \
905 return pContext->ThrowNativeError("Property \"%s\" not found (entity %d/%s)", \
911 inline int MatchFieldAsInteger(int field_type)
916 case FIELD_MODELINDEX:
917 case FIELD_MATERIALINDEX:
923 case FIELD_CHARACTER:
934 static cell_t GetEntProp(IPluginContext *pContext, const cell_t *params)
936 CBaseEntity *pEntity;
939 const char *class_name;
943 pEdict = GetEntity(params[1], &pEntity);
945 if (!pEdict || !pEntity)
947 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
950 if ((class_name = pEdict->GetClassName()) == NULL)
955 pContext->LocalToString(params[3], &prop);
961 typedescription_t *td;
965 if ((bit_count = MatchFieldAsInteger(td->fieldType)) == 0)
967 return pContext->ThrowNativeError("Data field %s is not an integer (%d)",
972 offset = td->fieldOffset[TD_OFFSET_NORMAL];
977 sm_sendprop_info_t info;
979 FIND_PROP_SEND(&info);
981 if (info.prop->GetType() != DPT_Int)
983 return pContext->ThrowNativeError("SendProp %s is not an integer ([%d,%d] != %d)",
985 info.prop->GetType(),
990 bit_count = info.prop->m_nBits;
991 offset = info.actual_offset;
996 return pContext->ThrowNativeError("Invalid Property type %d", params[2]);
1002 bit_count = params[4] * 8;
1005 if (bit_count >= 17)
1007 return *(int32_t *)((uint8_t *)pEntity + offset);
1009 else if (bit_count >= 9)
1011 return *(int16_t *)((uint8_t *)pEntity + offset);
1013 else if (bit_count >= 2)
1015 return *(int8_t *)((uint8_t *)pEntity + offset);
1019 return *(bool *)((uint8_t *)pEntity + offset) ? 1 : 0;
1025 static cell_t SetEntProp(IPluginContext *pContext, const cell_t *params)
1027 CBaseEntity *pEntity;
1030 const char *class_name;
1034 pEdict = GetEntity(params[1], &pEntity);
1036 if (!pEdict || !pEntity)
1038 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
1041 if ((class_name = pEdict->GetClassName()) == NULL)
1046 pContext->LocalToString(params[3], &prop);
1052 typedescription_t *td;
1056 if ((bit_count = MatchFieldAsInteger(td->fieldType)) == 0)
1058 return pContext->ThrowNativeError("Data field %s is not an integer (%d)",
1063 offset = td->fieldOffset[TD_OFFSET_NORMAL];
1068 sm_sendprop_info_t info;
1070 FIND_PROP_SEND(&info);
1072 if (info.prop->GetType() != DPT_Int)
1074 return pContext->ThrowNativeError("SendProp %s is not an integer ([%d,%d] != %d)",
1076 info.prop->GetType(),
1081 bit_count = info.prop->m_nBits;
1082 offset = info.actual_offset;
1087 return pContext->ThrowNativeError("Invalid Property type %d", params[2]);
1093 bit_count = params[5] * 8;
1096 if (bit_count >= 17)
1098 *(int32_t *)((uint8_t *)pEntity + offset) = params[4];
1100 else if (bit_count >= 9)
1102 *(int16_t *)((uint8_t *)pEntity + offset) = (int16_t)params[4];
1104 else if (bit_count >= 2)
1106 *(int8_t *)((uint8_t *)pEntity + offset) = (int8_t)params[4];
1110 *(bool *)((uint8_t *)pEntity + offset) = params[4] ? true : false;
1116 static cell_t GetEntPropFloat(IPluginContext *pContext, const cell_t *params)
1118 CBaseEntity *pEntity;
1121 const char *class_name;
1124 pEdict = GetEntity(params[1], &pEntity);
1126 if (!pEdict || !pEntity)
1128 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
1131 if ((class_name = pEdict->GetClassName()) == NULL)
1136 pContext->LocalToString(params[3], &prop);
1142 typedescription_t *td;
1146 if (td->fieldType != FIELD_FLOAT
1147 && td->fieldType != FIELD_TIME)
1149 return pContext->ThrowNativeError("Data field %s is not a float (%d != [%d,%d])",
1156 offset = td->fieldOffset[TD_OFFSET_NORMAL];
1161 sm_sendprop_info_t info;
1163 FIND_PROP_SEND(&info);
1165 if (info.prop->GetType() != DPT_Float)
1167 return pContext->ThrowNativeError("SendProp %s is not a float (%d != %d)",
1169 info.prop->GetType(),
1173 offset = info.actual_offset;
1178 return pContext->ThrowNativeError("Invalid Property type %d", params[2]);
1182 float val = *(float *)((uint8_t *)pEntity + offset);
1184 return sp_ftoc(val);
1187 static cell_t SetEntPropFloat(IPluginContext *pContext, const cell_t *params)
1189 CBaseEntity *pEntity;
1192 const char *class_name;
1195 pEdict = GetEntity(params[1], &pEntity);
1197 if (!pEdict || !pEntity)
1199 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
1202 if ((class_name = pEdict->GetClassName()) == NULL)
1207 pContext->LocalToString(params[3], &prop);
1213 typedescription_t *td;
1217 if (td->fieldType != FIELD_FLOAT
1218 && td->fieldType != FIELD_TIME)
1220 return pContext->ThrowNativeError("Data field %s is not a float (%d != [%d,%d])",
1227 offset = td->fieldOffset[TD_OFFSET_NORMAL];
1232 sm_sendprop_info_t info;
1234 FIND_PROP_SEND(&info);
1236 if (info.prop->GetType() != DPT_Float)
1238 return pContext->ThrowNativeError("SendProp %s is not a float (%d != %d)",
1240 info.prop->GetType(),
1244 offset = info.actual_offset;
1249 return pContext->ThrowNativeError("Invalid Property type %d", params[2]);
1253 *(float *)((uint8_t *)pEntity + offset) = sp_ctof(params[4]);
1255 if (params[2] == Prop_Send)
1257 g_HL2.SetEdictStateChanged(pEdict, offset);
1263 static cell_t GetEntPropEnt(IPluginContext *pContext, const cell_t *params)
1265 CBaseEntity *pEntity;
1268 const char *class_name;
1271 pEdict = GetEntity(params[1], &pEntity);
1273 if (!pEdict || !pEntity)
1275 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
1278 if ((class_name = pEdict->GetClassName()) == NULL)
1283 pContext->LocalToString(params[3], &prop);
1289 typedescription_t *td;
1293 if (td->fieldType != FIELD_EHANDLE)
1295 return pContext->ThrowNativeError("Data field %s is not an entity (%d != %d)",
1301 offset = td->fieldOffset[TD_OFFSET_NORMAL];
1306 sm_sendprop_info_t info;
1308 FIND_PROP_SEND(&info);
1310 if (info.prop->GetType() != DPT_Int)
1312 return pContext->ThrowNativeError("SendProp %s is not an integer (%d != %d)",
1314 info.prop->GetType(),
1318 offset = info.actual_offset;
1323 return pContext->ThrowNativeError("Invalid Property type %d", params[2]);
1327 CBaseHandle &hndl = *(CBaseHandle *)((uint8_t *)pEntity + offset);
1329 return CheckBaseHandle(hndl);
1332 static cell_t SetEntPropEnt(IPluginContext *pContext, const cell_t *params)
1334 CBaseEntity *pEntity;
1337 const char *class_name;
1340 pEdict = GetEntity(params[1], &pEntity);
1342 if (!pEdict || !pEntity)
1344 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
1347 if ((class_name = pEdict->GetClassName()) == NULL)
1352 pContext->LocalToString(params[3], &prop);
1358 typedescription_t *td;
1362 if (td->fieldType != FIELD_EHANDLE)
1364 return pContext->ThrowNativeError("Data field %s is not an entity (%d != %d)",
1370 offset = td->fieldOffset[TD_OFFSET_NORMAL];
1375 sm_sendprop_info_t info;
1377 FIND_PROP_SEND(&info);
1379 if (info.prop->GetType() != DPT_Int)
1381 return pContext->ThrowNativeError("SendProp %s is not an integer (%d != %d)",
1383 info.prop->GetType(),
1387 offset = info.actual_offset;
1392 return pContext->ThrowNativeError("Invalid Property type %d", params[2]);
1396 CBaseHandle &hndl = *(CBaseHandle *)((uint8_t *)pEntity + offset);
1398 if (params[4] == -1)
1405 CBaseEntity *pOtherEnt;
1407 if ((pOther = GetEntity(params[4], &pOtherEnt)) == NULL)
1409 return pContext->ThrowNativeError("Invalid entity %d", params[4]);
1412 hndl.Set(pOther->GetIServerEntity());
1415 if (params[2] == Prop_Send)
1417 g_HL2.SetEdictStateChanged(pEdict, offset);
1423 static cell_t GetEntPropVector(IPluginContext *pContext, const cell_t *params)
1425 CBaseEntity *pEntity;
1428 const char *class_name;
1431 pEdict = GetEntity(params[1], &pEntity);
1433 if (!pEdict || !pEntity)
1435 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
1438 if ((class_name = pEdict->GetClassName()) == NULL)
1443 pContext->LocalToString(params[3], &prop);
1449 typedescription_t *td;
1453 if (td->fieldType != FIELD_VECTOR
1454 && td->fieldType != FIELD_POSITION_VECTOR)
1456 return pContext->ThrowNativeError("Data field %s is not a vector (%d != [%d,%d])",
1460 FIELD_POSITION_VECTOR);
1463 offset = td->fieldOffset[TD_OFFSET_NORMAL];
1468 sm_sendprop_info_t info;
1470 FIND_PROP_SEND(&info);
1472 if (info.prop->GetType() != DPT_Vector)
1474 return pContext->ThrowNativeError("SendProp %s is not a vector (%d != %d)",
1476 info.prop->GetType(),
1480 offset = info.actual_offset;
1485 return pContext->ThrowNativeError("Invalid Property type %d", params[2]);
1489 Vector *v = (Vector *)((uint8_t *)pEntity + offset);
1492 pContext->LocalToPhysAddr(params[4], &vec);
1494 vec[0] = sp_ftoc(v->x);
1495 vec[1] = sp_ftoc(v->y);
1496 vec[2] = sp_ftoc(v->z);
1501 static cell_t SetEntPropVector(IPluginContext *pContext, const cell_t *params)
1503 CBaseEntity *pEntity;
1506 const char *class_name;
1509 pEdict = GetEntity(params[1], &pEntity);
1511 if (!pEdict || !pEntity)
1513 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
1516 if ((class_name = pEdict->GetClassName()) == NULL)
1521 pContext->LocalToString(params[3], &prop);
1527 typedescription_t *td;
1531 if (td->fieldType != FIELD_VECTOR
1532 && td->fieldType != FIELD_POSITION_VECTOR)
1534 return pContext->ThrowNativeError("Data field %s is not a vector (%d != [%d,%d])",
1538 FIELD_POSITION_VECTOR);
1541 offset = td->fieldOffset[TD_OFFSET_NORMAL];
1546 sm_sendprop_info_t info;
1548 FIND_PROP_SEND(&info);
1550 if (info.prop->GetType() != DPT_Vector)
1552 return pContext->ThrowNativeError("SendProp %s is not a vector (%d != %d)",
1554 info.prop->GetType(),
1558 offset = info.actual_offset;
1563 return pContext->ThrowNativeError("Invalid Property type %d", params[2]);
1567 Vector *v = (Vector *)((uint8_t *)pEntity + offset);
1570 pContext->LocalToPhysAddr(params[4], &vec);
1572 v->x = sp_ctof(vec[0]);
1573 v->y = sp_ctof(vec[1]);
1574 v->z = sp_ctof(vec[2]);
1576 if (params[2] == Prop_Send)
1578 g_HL2.SetEdictStateChanged(pEdict, offset);
1584 static cell_t GetEntPropString(IPluginContext *pContext, const cell_t *params)
1586 CBaseEntity *pEntity;
1589 const char *class_name;
1591 bool bIsStringIndex;
1593 pEdict = GetEntity(params[1], &pEntity);
1595 if (!pEdict || !pEntity)
1597 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
1600 if ((class_name = pEdict->GetClassName()) == NULL)
1605 pContext->LocalToString(params[3], &prop);
1607 bIsStringIndex = false;
1613 typedescription_t *td;
1617 if (td->fieldType != FIELD_CHARACTER
1618 && td->fieldType != FIELD_STRING
1619 && td->fieldType != FIELD_MODELNAME
1620 && td->fieldType != FIELD_SOUNDNAME)
1622 return pContext->ThrowNativeError("Data field %s is not a string (%d != %d)",
1628 bIsStringIndex = (td->fieldType != FIELD_CHARACTER);
1630 offset = td->fieldOffset[TD_OFFSET_NORMAL];
1635 sm_sendprop_info_t info;
1637 FIND_PROP_SEND(&info);
1639 if (info.prop->GetType() != DPT_String)
1641 return pContext->ThrowNativeError("SendProp %s is not a string (%d != %d)",
1643 info.prop->GetType(),
1647 offset = info.actual_offset;
1653 return pContext->ThrowNativeError("Invalid Property type %d", params[2]);
1660 if (!bIsStringIndex)
1662 src = (char *)((uint8_t *)pEntity + offset);
1668 idx = *(string_t *)((uint8_t *)pEntity + offset);
1669 src = (idx == NULL_STRING) ? "" : STRING(idx);
1672 pContext->StringToLocalUTF8(params[4], params[5], src, &len);
1677 static cell_t SetEntPropString(IPluginContext *pContext, const cell_t *params)
1679 CBaseEntity *pEntity;
1683 edict_t *pEdict = GetEntity(params[1], &pEntity);
1685 if (!pEdict || !pEntity)
1687 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
1695 typedescription_t *td;
1696 if ((pMap=CBaseEntity_GetDataDescMap(pEntity)) == NULL)
1698 return pContext->ThrowNativeError("Unable to retrieve GetDataDescMap offset");
1700 pContext->LocalToString(params[3], &prop);
1701 if ((td=g_HL2.FindInDataMap(pMap, prop)) == NULL)
1703 return pContext->ThrowNativeError("Property \"%s\" not found for entity %d", prop, params[1]);
1705 if (td->fieldType != FIELD_CHARACTER)
1707 return pContext->ThrowNativeError("Property \"%s\" is not a valid string", prop);
1709 offset = td->fieldOffset[TD_OFFSET_NORMAL];
1710 maxlen = td->fieldSize;
1716 IServerNetworkable *pNet = pEdict->GetNetworkable();
1719 return pContext->ThrowNativeError("The edict is not networkable");
1721 pContext->LocalToString(params[3], &prop);
1722 SendProp *pSend = g_HL2.FindInSendTable(pNet->GetServerClass()->GetName(), prop);
1725 return pContext->ThrowNativeError("Property \"%s\" not found for entity %d", prop, params[1]);
1727 if (pSend->GetType() != DPT_String)
1729 return pContext->ThrowNativeError("Property \"%s\" is not a valid string", prop);
1731 offset = pSend->GetOffset();
1732 maxlen = DT_MAX_STRING_BUFFERSIZE;
1737 return pContext->ThrowNativeError("Invalid Property type %d", params[2]);
1742 char *dest = (char *)((uint8_t *)pEntity + offset);
1744 pContext->LocalToString(params[4], &src);
1745 size_t len = strncopy(dest, src, maxlen);
1747 if (params[2] == Prop_Send)
1749 g_HL2.SetEdictStateChanged(pEdict, offset);
1755 REGISTER_NATIVES(entityNatives)
1757 {"ChangeEdictState", ChangeEdictState},
1758 {"CreateEdict", CreateEdict},
1759 {"FindDataMapOffs", FindDataMapOffs},
1760 {"FindSendPropInfo", FindSendPropInfo},
1761 {"FindSendPropOffs", FindSendPropOffs},
1762 {"GetEdictClassname", GetEdictClassname},
1763 {"GetEdictFlags", GetEdictFlags},
1764 {"GetEntData", GetEntData},
1765 {"GetEntDataEnt", GetEntDataEnt}, /** DEPRECATED */
1766 {"GetEntDataEnt2", GetEntDataEnt2},
1767 {"GetEntDataFloat", GetEntDataFloat},
1768 {"GetEntDataString", GetEntDataString},
1769 {"GetEntDataVector", GetEntDataVector},
1770 {"GetEntProp", GetEntProp},
1771 {"GetEntPropEnt", GetEntPropEnt},
1772 {"GetEntPropFloat", GetEntPropFloat},
1773 {"GetEntPropString", GetEntPropString},
1774 {"GetEntPropVector", GetEntPropVector},
1775 {"GetEntityCount", GetEntityCount},
1776 {"GetEntityNetClass", GetEntityNetClass},
1777 {"GetMaxEntities", GetMaxEntities},
1778 {"IsEntNetworkable", IsEntNetworkable},
1779 {"IsValidEdict", IsValidEdict},
1780 {"IsValidEntity", IsValidEntity},
1781 {"RemoveEdict", RemoveEdict},
1782 {"SetEdictFlags", SetEdictFlags},
1783 {"SetEntData", SetEntData},
1784 {"SetEntDataEnt", SetEntDataEnt}, /** DEPRECATED */
1785 {"SetEntDataEnt2", SetEntDataEnt2},
1786 {"SetEntDataFloat", SetEntDataFloat},
1787 {"SetEntDataVector", SetEntDataVector},
1788 {"SetEntDataString", SetEntDataString},
1789 {"SetEntProp", SetEntProp},
1790 {"SetEntPropEnt", SetEntPropEnt},
1791 {"SetEntPropFloat", SetEntPropFloat},
1792 {"SetEntPropString", SetEntPropString},
1793 {"SetEntPropVector", SetEntPropVector},