3 * =============================================================================
5 * Copyright (C) 2004-2010 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 <IGameConfigs.h>
38 #include "sm_stringutil.h"
39 #include "logic_bridge.h"
41 // These values need to mirror the values in entity_prop_stocks
42 #define ENTFLAG_ONGROUND (1 << 0)
43 #define ENTFLAG_DUCKING (1 << 1)
44 #define ENTFLAG_WATERJUMP (1 << 2)
45 #define ENTFLAG_ONTRAIN (1 << 3)
46 #define ENTFLAG_INRAIN (1 << 4)
47 #define ENTFLAG_FROZEN (1 << 5)
48 #define ENTFLAG_ATCONTROLS (1 << 6)
49 #define ENTFLAG_CLIENT (1 << 7)
50 #define ENTFLAG_FAKECLIENT (1 << 8)
51 #define ENTFLAG_INWATER (1 << 9)
52 #define ENTFLAG_FLY (1 << 10)
53 #define ENTFLAG_SWIM (1 << 11)
54 #define ENTFLAG_CONVEYOR (1 << 12)
55 #define ENTFLAG_NPC (1 << 13)
56 #define ENTFLAG_GODMODE (1 << 14)
57 #define ENTFLAG_NOTARGET (1 << 15)
58 #define ENTFLAG_AIMTARGET (1 << 16)
59 #define ENTFLAG_PARTIALGROUND (1 << 17)
60 #define ENTFLAG_STATICPROP (1 << 18)
61 #define ENTFLAG_GRAPHED (1 << 19)
62 #define ENTFLAG_GRENADE (1 << 20)
63 #define ENTFLAG_STEPMOVEMENT (1 << 21)
64 #define ENTFLAG_DONTTOUCH (1 << 22)
65 #define ENTFLAG_BASEVELOCITY (1 << 23)
66 #define ENTFLAG_WORLDBRUSH (1 << 24)
67 #define ENTFLAG_OBJECT (1 << 25)
68 #define ENTFLAG_KILLME (1 << 26)
69 #define ENTFLAG_ONFIRE (1 << 27)
70 #define ENTFLAG_DISSOLVING (1 << 28)
71 #define ENTFLAG_TRANSRAGDOLL (1 << 29)
72 #define ENTFLAG_UNBLOCKABLE_BY_PLAYER (1 << 30)
73 #define ENTFLAG_FREEZING (1 << 31)
74 #define ENTFLAG_EP2V_UNKNOWN1 (1 << 31)
76 // Not defined in the sdk as we have no clue what it is
77 #define FL_EP2V_UNKNOWN (1 << 2)
87 PropField_Unsupported, /**< The type is unsupported. */
88 PropField_Integer, /**< Valid for SendProp and Data fields */
89 PropField_Float, /**< Valid for SendProp and Data fields */
90 PropField_Entity, /**< Valid for Data fields only (SendProp shows as int) */
91 PropField_Vector, /**< Valid for SendProp and Data fields */
92 PropField_String, /**< Valid for SendProp and Data fields */
93 PropField_String_T, /**< Valid for Data fields. Read only! */
96 inline edict_t *BaseEntityToEdict(CBaseEntity *pEntity)
98 IServerUnknown *pUnk = (IServerUnknown *)pEntity;
99 IServerNetworkable *pNet = pUnk->GetNetworkable();
106 return pNet->GetEdict();
109 inline edict_t *GetEdict(cell_t num)
112 if (!IndexToAThings(num, NULL, &pEdict))
120 inline CBaseEntity *GetEntity(cell_t num)
122 CBaseEntity *pEntity;
123 if (!IndexToAThings(num, &pEntity, NULL))
131 /* Given an entity reference or index, fill out a CBaseEntity and/or edict.
132 If lookup is successful, returns true and writes back the two parameters.
133 If lookup fails, returns false and doesn't touch the params. */
134 bool IndexToAThings(cell_t num, CBaseEntity **pEntData, edict_t **pEdictData)
136 CBaseEntity *pEntity = g_HL2.ReferenceToEntity(num);
143 int index = g_HL2.ReferenceToIndex(num);
144 if (index > 0 && index <= g_Players.GetMaxClients())
146 CPlayer *pPlayer = g_Players.GetPlayerByIndex(index);
147 if (!pPlayer || !pPlayer->IsConnected())
160 edict_t *pEdict = ::BaseEntityToEdict(pEntity);
161 if (!pEdict || pEdict->IsFree())
166 *pEdictData = pEdict;
172 <predcrab> AThings is like guaranteed r+ by dvander though
173 <predcrab> he wont even read the rest of the patch to nit stuff
174 <Fyren> Like I wasn't going to r? you anyway!
175 <predcrab> he still sees!
176 <predcrab> he's everywhere
179 class VEmptyClass {};
180 datamap_t *VGetDataDescMap(CBaseEntity *pThisPtr, int offset)
182 void **this_ptr = *reinterpret_cast<void ***>(&pThisPtr);
183 void **vtable = *reinterpret_cast<void ***>(pThisPtr);
184 void *vfunc = vtable[offset];
188 datamap_t *(VEmptyClass::*mfpnew)();
189 #ifndef PLATFORM_POSIX
204 return (datamap_t *)(reinterpret_cast<VEmptyClass *>(this_ptr)->*u.mfpnew)();
207 inline datamap_t *CBaseEntity_GetDataDescMap(CBaseEntity *pEntity)
211 if (!g_pGameConf->GetOffset("GetDataDescMap", &offset) || !offset)
216 return VGetDataDescMap(pEntity, offset);
219 /* :TODO: Move this! */
220 datamap_t *CHalfLife2::GetDataMap(CBaseEntity *pEntity)
222 return CBaseEntity_GetDataDescMap(pEntity);
225 static cell_t GetMaxEntities(IPluginContext *pContext, const cell_t *params)
227 return gpGlobals->maxEntities;
230 static cell_t CreateEdict(IPluginContext *pContext, const cell_t *params)
232 edict_t *pEdict = engine->CreateEdict();
239 return IndexOfEdict(pEdict);
242 static cell_t RemoveEdict(IPluginContext *pContext, const cell_t *params)
244 edict_t *pEdict = GetEdict(params[1]);
248 return pContext->ThrowNativeError("Edict %d (%d) is not a valid edict", g_HL2.ReferenceToIndex(params[1]), params[1]);
251 engine->RemoveEdict(pEdict);
256 static cell_t IsValidEdict(IPluginContext *pContext, const cell_t *params)
258 edict_t *pEdict = GetEdict(params[1]);
265 /* Shouldn't be necessary... not sure though */
266 return pEdict->IsFree() ? 0 : 1;
269 static cell_t IsValidEntity(IPluginContext *pContext, const cell_t *params)
271 CBaseEntity *pEntity = g_HL2.ReferenceToEntity(params[1]);
273 return (pEntity != NULL) ? 1 : 0;
276 static cell_t IsEntNetworkable(IPluginContext *pContext, const cell_t *params)
278 edict_t *pEdict = GetEdict(params[1]);
285 return (pEdict->GetNetworkable() != NULL) ? 1 : 0;
288 static cell_t GetEntityCount(IPluginContext *pContext, const cell_t *params)
290 return engine->GetEntityCount();
293 static cell_t GetEdictFlags(IPluginContext *pContext, const cell_t *params)
295 edict_t *pEdict = GetEdict(params[1]);
299 return pContext->ThrowNativeError("Invalid edict (%d - %d)", g_HL2.ReferenceToIndex(params[1]), params[1]);
302 return pEdict->m_fStateFlags;
305 static cell_t SetEdictFlags(IPluginContext *pContext, const cell_t *params)
307 edict_t *pEdict = GetEdict(params[1]);
311 return pContext->ThrowNativeError("Invalid edict (%d - %d)", g_HL2.ReferenceToIndex(params[1]), params[1]);
314 pEdict->m_fStateFlags = params[2];
319 static cell_t GetEdictClassname(IPluginContext *pContext, const cell_t *params)
321 edict_t *pEdict = GetEdict(params[1]);
325 return pContext->ThrowNativeError("Invalid edict (%d - %d)", g_HL2.ReferenceToIndex(params[1]), params[1]);
328 const char *cls = g_HL2.GetEntityClassname(pEdict);
330 if (!cls || cls[0] == '\0')
335 pContext->StringToLocal(params[2], params[3], cls);
340 static cell_t GetEntityNetClass(IPluginContext *pContext, const cell_t *params)
342 CBaseEntity *pEntity = g_HL2.ReferenceToEntity(params[1]);
344 IServerUnknown *pUnk = (IServerUnknown *)pEntity;
348 return pContext->ThrowNativeError("Invalid entity (%d - %d)", g_HL2.ReferenceToIndex(params[1]), params[1]);
351 IServerNetworkable *pNet = pUnk->GetNetworkable();
357 ServerClass *pClass = pNet->GetServerClass();
359 pContext->StringToLocal(params[2], params[3], pClass->GetName());
364 static cell_t GetEntData(IPluginContext *pContext, const cell_t *params)
366 CBaseEntity *pEntity = GetEntity(params[1]);
370 return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
373 int offset = params[2];
374 if (offset <= 0 || offset > 32768)
376 return pContext->ThrowNativeError("Offset %d is invalid", offset);
382 return *(int *)((uint8_t *)pEntity + offset);
384 return *(short *)((uint8_t *)pEntity + offset);
386 return *((uint8_t *)pEntity + offset);
388 return pContext->ThrowNativeError("Integer size %d is invalid", params[3]);
392 static cell_t SetEntData(IPluginContext *pContext, const cell_t *params)
394 CBaseEntity *pEntity;
397 if (!IndexToAThings(params[1], &pEntity, &pEdict))
399 return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
402 int offset = params[2];
403 if (offset <= 0 || offset > 32768)
405 return pContext->ThrowNativeError("Offset %d is invalid", offset);
408 if (params[5] && (pEdict != NULL))
410 g_HL2.SetEdictStateChanged(pEdict, offset);
417 *(int *)((uint8_t *)pEntity + offset) = params[3];
422 *(short *)((uint8_t *)pEntity + offset) = params[3];
427 *((uint8_t *)pEntity + offset) = params[3];
431 return pContext->ThrowNativeError("Integer size %d is invalid", params[4]);
437 static cell_t GetEntDataFloat(IPluginContext *pContext, const cell_t *params)
439 CBaseEntity *pEntity = GetEntity(params[1]);
443 return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
446 int offset = params[2];
447 if (offset <= 0 || offset > 32768)
449 return pContext->ThrowNativeError("Offset %d is invalid", offset);
452 float f = *(float *)((uint8_t *)pEntity + offset);
457 static cell_t SetEntDataFloat(IPluginContext *pContext, const cell_t *params)
459 CBaseEntity *pEntity;
462 if (!IndexToAThings(params[1], &pEntity, &pEdict))
464 return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
467 int offset = params[2];
468 if (offset <= 0 || offset > 32768)
470 return pContext->ThrowNativeError("Offset %d is invalid", offset);
473 *(float *)((uint8_t *)pEntity + offset) = sp_ctof(params[3]);
475 if (params[4] && (pEdict != NULL))
477 g_HL2.SetEdictStateChanged(pEdict, offset);
483 static cell_t GetEntDataVector(IPluginContext *pContext, const cell_t *params)
485 CBaseEntity *pEntity = GetEntity(params[1]);
489 return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
492 int offset = params[2];
493 if (offset <= 0 || offset > 32768)
495 return pContext->ThrowNativeError("Offset %d is invalid", offset);
498 Vector *v = (Vector *)((uint8_t *)pEntity + offset);
501 pContext->LocalToPhysAddr(params[3], &vec);
503 vec[0] = sp_ftoc(v->x);
504 vec[1] = sp_ftoc(v->y);
505 vec[2] = sp_ftoc(v->z);
510 static cell_t SetEntDataVector(IPluginContext *pContext, const cell_t *params)
512 CBaseEntity *pEntity;
515 if (!IndexToAThings(params[1], &pEntity, &pEdict))
517 return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
520 int offset = params[2];
521 if (offset <= 0 || offset > 32768)
523 return pContext->ThrowNativeError("Offset %d is invalid", offset);
526 Vector *v = (Vector *)((uint8_t *)pEntity + offset);
529 pContext->LocalToPhysAddr(params[3], &vec);
531 v->x = sp_ctof(vec[0]);
532 v->y = sp_ctof(vec[1]);
533 v->z = sp_ctof(vec[2]);
535 if (params[4] && (pEdict != NULL))
537 g_HL2.SetEdictStateChanged(pEdict, offset);
543 /* THIS GUY IS DEPRECATED. */
544 static cell_t GetEntDataEnt(IPluginContext *pContext, const cell_t *params)
546 CBaseEntity *pEntity = GetEntity(params[1]);
550 return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
553 int offset = params[2];
554 if (offset <= 0 || offset > 32768)
556 return pContext->ThrowNativeError("Offset %d is invalid", offset);
559 CBaseHandle &hndl = *(CBaseHandle *)((uint8_t *)pEntity + offset);
566 int ref = g_HL2.IndexToReference(hndl.GetEntryIndex());
567 return g_HL2.ReferenceToBCompatRef(ref);
570 int CheckBaseHandle(CBaseHandle &hndl)
577 int index = hndl.GetEntryIndex();
579 edict_t *pStoredEdict;
580 CBaseEntity *pStoredEntity;
582 if (!IndexToAThings(index, &pStoredEntity, &pStoredEdict))
587 if (pStoredEdict == NULL || pStoredEntity == NULL)
592 IServerEntity *pSE = pStoredEdict->GetIServerEntity();
599 if (pSE->GetRefEHandle() != hndl)
607 static cell_t GetEntDataEnt2(IPluginContext *pContext, const cell_t *params)
609 CBaseEntity *pEntity = GetEntity(params[1]);
613 return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
616 int offset = params[2];
617 if (offset <= 0 || offset > 32768)
619 return pContext->ThrowNativeError("Offset %d is invalid", offset);
622 CBaseHandle &hndl = *(CBaseHandle *)((uint8_t *)pEntity + offset);
623 CBaseEntity *pHandleEntity = g_HL2.ReferenceToEntity(hndl.GetEntryIndex());
625 if (!pHandleEntity || hndl != reinterpret_cast<IHandleEntity *>(pHandleEntity)->GetRefEHandle())
628 return g_HL2.EntityToBCompatRef(pHandleEntity);
631 /* THIS GUY IS DEPRECATED. */
632 static cell_t SetEntDataEnt(IPluginContext *pContext, const cell_t *params)
634 CBaseEntity *pEntity;
637 if (!IndexToAThings(params[1], &pEntity, &pEdict))
639 return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
642 int offset = params[2];
643 if (offset <= 0 || offset > 32768)
645 return pContext->ThrowNativeError("Offset %d is invalid", offset);
648 CBaseHandle &hndl = *(CBaseHandle *)((uint8_t *)pEntity + offset);
650 if (params[3] == 0 || (unsigned)params[3] == INVALID_EHANDLE_INDEX)
654 CBaseEntity *pOther = GetEntity(params[3]);
658 return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[3]), params[3]);
661 IHandleEntity *pHandleEnt = (IHandleEntity *)pOther;
662 hndl.Set(pHandleEnt);
665 if (params[4] && (pEdict != NULL))
667 g_HL2.SetEdictStateChanged(pEdict, offset);
673 static cell_t SetEntDataEnt2(IPluginContext *pContext, const cell_t *params)
675 CBaseEntity *pEntity;
678 if (!IndexToAThings(params[1], &pEntity, &pEdict))
680 return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
683 int offset = params[2];
684 if (offset <= 0 || offset > 32768)
686 return pContext->ThrowNativeError("Offset %d is invalid", offset);
689 CBaseHandle &hndl = *(CBaseHandle *)((uint8_t *)pEntity + offset);
691 if ((unsigned)params[3] == INVALID_EHANDLE_INDEX)
697 CBaseEntity *pOther = GetEntity(params[3]);
701 return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[3]), params[3]);
704 IHandleEntity *pHandleEnt = (IHandleEntity *)pOther;
705 hndl.Set(pHandleEnt);
708 if (params[4] && (pEdict != NULL))
710 g_HL2.SetEdictStateChanged(pEdict, offset);
716 static cell_t ChangeEdictState(IPluginContext *pContext, const cell_t *params)
718 edict_t *pEdict = GetEdict(params[1]);
722 return pContext->ThrowNativeError("Edict %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
725 g_HL2.SetEdictStateChanged(pEdict, params[2]);
730 static cell_t FindSendPropOffs(IPluginContext *pContext, const cell_t *params)
733 pContext->LocalToString(params[1], &cls);
734 pContext->LocalToString(params[2], &prop);
736 SendProp *pSend = g_HL2.FindInSendTable(cls, prop);
743 return pSend->GetOffset();
746 static cell_t FindSendPropInfo(IPluginContext *pContext, const cell_t *params)
749 sm_sendprop_info_t info;
750 cell_t *pType, *pBits, *pLocal;
752 pContext->LocalToString(params[1], &cls);
753 pContext->LocalToString(params[2], &prop);
755 if (!g_HL2.FindSendPropInfo(cls, prop, &info))
760 pContext->LocalToPhysAddr(params[3], &pType);
761 pContext->LocalToPhysAddr(params[4], &pBits);
762 pContext->LocalToPhysAddr(params[5], &pLocal);
764 switch (info.prop->GetType())
768 *pType = PropField_Integer;
773 *pType = PropField_Float;
778 *pType = PropField_String;
783 *pType = PropField_Vector;
788 *pType = PropField_Unsupported;
793 *pBits = info.prop->m_nBits;
794 *pLocal = info.prop->GetOffset();
796 return info.actual_offset;
799 static void GuessDataPropTypes(typedescription_t *td, cell_t * pSize, cell_t * pType)
801 switch (td->fieldType)
804 case FIELD_MODELINDEX:
805 case FIELD_MATERIALINDEX:
809 *pType = PropField_Integer;
814 case FIELD_POSITION_VECTOR:
816 *pType = PropField_Vector;
822 *pType = PropField_Integer;
828 *pType = PropField_Integer;
832 case FIELD_CHARACTER:
834 if (td->fieldSize == 1)
836 *pType = PropField_Integer;
841 *pType = PropField_String;
842 *pSize = 8 * td->fieldSize;
846 case FIELD_MODELNAME:
847 case FIELD_SOUNDNAME:
850 *pSize = sizeof(string_t);
851 *pType = PropField_String_T;
857 *pType = PropField_Float;
863 *pType = PropField_Entity;
869 *pType = PropField_Unsupported;
875 static cell_t FindDataMapOffs(IPluginContext *pContext, const cell_t *params)
877 CBaseEntity *pEntity;
879 typedescription_t *td;
881 pEntity = GetEntity(params[1]);
885 return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
888 if ((pMap=CBaseEntity_GetDataDescMap(pEntity)) == NULL)
890 return pContext->ThrowNativeError("Unable to retrieve GetDataDescMap offset");
893 pContext->LocalToString(params[2], &offset);
894 sm_datatable_info_t info;
895 if (!g_HL2.FindDataMapInfo(pMap, offset, &info))
904 cell_t *pType, *pSize;
906 pContext->LocalToPhysAddr(params[3], &pType);
907 pContext->LocalToPhysAddr(params[4], &pSize);
909 GuessDataPropTypes(td, pSize, pType);
912 return GetTypeDescOffs(td);
915 static cell_t FindDataMapInfo(IPluginContext *pContext, const cell_t *params)
917 CBaseEntity *pEntity;
919 typedescription_t *td;
921 pEntity = GetEntity(params[1]);
925 return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
928 if ((pMap=CBaseEntity_GetDataDescMap(pEntity)) == NULL)
930 return pContext->ThrowNativeError("Unable to retrieve GetDataDescMap offset");
933 pContext->LocalToString(params[2], &offset);
934 sm_datatable_info_t info;
935 if (!g_HL2.FindDataMapInfo(pMap, offset, &info))
944 cell_t *pType, *pSize;
946 pContext->LocalToPhysAddr(params[3], &pType);
947 pContext->LocalToPhysAddr(params[4], &pSize);
949 GuessDataPropTypes(td, pSize, pType);
955 pContext->LocalToPhysAddr(params[5], &pLocalOffs);
957 *pLocalOffs = GetTypeDescOffs(info.prop);
961 return info.actual_offset;
964 static cell_t GetEntDataString(IPluginContext *pContext, const cell_t *params)
966 CBaseEntity *pEntity = GetEntity(params[1]);
970 return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
973 int offset = params[2];
974 if (offset < 0 || offset > 32768)
976 return pContext->ThrowNativeError("Offset %d is invalid", offset);
980 char *src = (char *)((uint8_t *)pEntity + offset);
981 pContext->StringToLocalUTF8(params[3], params[4], src, &len);
986 static cell_t SetEntDataString(IPluginContext *pContext, const cell_t *params)
988 CBaseEntity *pEntity;
991 if (!IndexToAThings(params[1], &pEntity, &pEdict))
993 return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
996 int offset = params[2];
997 if (offset < 0 || offset > 32768)
999 return pContext->ThrowNativeError("Offset %d is invalid", offset);
1003 char *dest = (char *)((uint8_t *)pEntity + offset);
1005 pContext->LocalToString(params[3], &src);
1006 size_t len = strncopy(dest, src, params[4]);
1008 if (params[5] && (pEdict != NULL))
1010 g_HL2.SetEdictStateChanged(pEdict, offset);
1016 #define FIND_PROP_DATA(td) \
1018 if ((pMap = CBaseEntity_GetDataDescMap(pEntity)) == NULL) \
1020 return pContext->ThrowNativeError("Could not retrieve datamap"); \
1022 sm_datatable_info_t info; \
1023 if (!g_HL2.FindDataMapInfo(pMap, prop, &info)) \
1025 const char *class_name = g_HL2.GetEntityClassname(pEntity); \
1026 return pContext->ThrowNativeError("Property \"%s\" not found (entity %d/%s)", \
1029 ((class_name) ? class_name : "")); \
1033 #define CHECK_SET_PROP_DATA_OFFSET() \
1034 if (element < 0 || element >= td->fieldSize) \
1036 return pContext->ThrowNativeError("Element %d is out of bounds (Prop %s has %d elements).", \
1042 offset = info.actual_offset + (element * (td->fieldSizeInBytes / td->fieldSize));
1044 #define FIND_PROP_SEND(type, type_name) \
1045 sm_sendprop_info_t info;\
1047 IServerUnknown *pUnk = (IServerUnknown *)pEntity; \
1048 IServerNetworkable *pNet = pUnk->GetNetworkable(); \
1051 return pContext->ThrowNativeError("Edict %d (%d) is not networkable", g_HL2.ReferenceToIndex(params[1]), params[1]); \
1053 if (!g_HL2.FindSendPropInfo(pNet->GetServerClass()->GetName(), prop, &info)) \
1055 const char *class_name = g_HL2.GetEntityClassname(pEntity); \
1056 return pContext->ThrowNativeError("Property \"%s\" not found (entity %d/%s)", \
1059 ((class_name) ? class_name : "")); \
1062 offset = info.actual_offset; \
1063 pProp = info.prop; \
1064 bit_count = pProp->m_nBits; \
1066 switch (pProp->GetType()) \
1072 return pContext->ThrowNativeError("SendProp %s is not an array. Element %d is invalid.", \
1078 case DPT_DataTable: \
1080 FIND_PROP_SEND_IN_SENDTABLE(info, pProp, element, type, type_name); \
1082 offset += pProp->GetOffset(); \
1083 bit_count = pProp->m_nBits; \
1088 return pContext->ThrowNativeError("SendProp %s type is not " type_name " (%d != %d)", \
1095 #define FIND_PROP_SEND_IN_SENDTABLE(info, pProp, element, type, type_name) \
1096 SendTable *pTable = pProp->GetDataTable(); \
1099 return pContext->ThrowNativeError("Error looking up DataTable for prop %s", \
1103 int elementCount = pTable->GetNumProps(); \
1104 if (element < 0 || element >= elementCount) \
1106 return pContext->ThrowNativeError("Element %d is out of bounds (Prop %s has %d elements).", \
1112 pProp = pTable->GetProp(element); \
1113 if (pProp->GetType() != type) \
1115 return pContext->ThrowNativeError("SendProp %s type is not " type_name " ([%d,%d] != %d)", \
1123 inline int MatchFieldAsInteger(int field_type)
1128 case FIELD_MODELINDEX:
1129 case FIELD_MATERIALINDEX:
1135 case FIELD_CHARACTER:
1146 static cell_t GetEntPropArraySize(IPluginContext *pContext, const cell_t *params)
1148 CBaseEntity *pEntity;
1152 if (!IndexToAThings(params[1], &pEntity, &pEdict))
1154 return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
1157 pContext->LocalToString(params[3], &prop);
1163 typedescription_t *td;
1167 return td->fieldSize;
1171 sm_sendprop_info_t info;
1173 IServerUnknown *pUnk = (IServerUnknown *)pEntity;
1174 IServerNetworkable *pNet = pUnk->GetNetworkable();
1177 return pContext->ThrowNativeError("Edict %d (%d) is not networkable", g_HL2.ReferenceToIndex(params[1]), params[1]);
1179 if (!g_HL2.FindSendPropInfo(pNet->GetServerClass()->GetName(), prop, &info))
1181 const char *class_name = g_HL2.GetEntityClassname(pEntity);
1182 return pContext->ThrowNativeError("Property \"%s\" not found (entity %d/%s)",
1185 ((class_name) ? class_name : ""));
1188 if (info.prop->GetType() != DPT_DataTable)
1193 SendTable *pTable = info.prop->GetDataTable();
1196 return pContext->ThrowNativeError("Error looking up DataTable for prop %s", prop);
1199 return pTable->GetNumProps();
1203 return pContext->ThrowNativeError("Invalid Property type %d", params[2]);
1210 static cell_t GetEntProp(IPluginContext *pContext, const cell_t *params)
1212 CBaseEntity *pEntity;
1217 bool is_unsigned = false;
1222 element = params[5];
1225 if (!IndexToAThings(params[1], &pEntity, &pEdict))
1227 return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
1230 pContext->LocalToString(params[3], &prop);
1236 typedescription_t *td;
1240 if ((bit_count = MatchFieldAsInteger(td->fieldType)) == 0)
1242 return pContext->ThrowNativeError("Data field %s is not an integer (%d)",
1247 CHECK_SET_PROP_DATA_OFFSET();
1253 FIND_PROP_SEND(DPT_Int, "integer");
1254 is_unsigned = ((pProp->GetFlags() & SPROP_UNSIGNED) == SPROP_UNSIGNED);
1256 // This isn't in CS:S yet, but will be, doesn't hurt to add now, and will save us a build later
1257 #if SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_TF2
1258 if (pProp->GetFlags() & SPROP_VARINT)
1260 bit_count = sizeof(int) * 8;
1267 return pContext->ThrowNativeError("Invalid Property type %d", params[2]);
1273 bit_count = params[4] * 8;
1276 if (bit_count >= 17)
1278 return *(int32_t *)((uint8_t *)pEntity + offset);
1280 else if (bit_count >= 9)
1284 return *(uint16_t *)((uint8_t *)pEntity + offset);
1288 return *(int16_t *)((uint8_t *)pEntity + offset);
1291 else if (bit_count >= 2)
1295 return *(uint8_t *)((uint8_t *)pEntity + offset);
1299 return *(int8_t *)((uint8_t *)pEntity + offset);
1304 return *(bool *)((uint8_t *)pEntity + offset) ? 1 : 0;
1310 static cell_t SetEntProp(IPluginContext *pContext, const cell_t *params)
1312 CBaseEntity *pEntity;
1321 element = params[6];
1324 if (!IndexToAThings(params[1], &pEntity, &pEdict))
1326 return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
1329 pContext->LocalToString(params[3], &prop);
1335 typedescription_t *td;
1339 if ((bit_count = MatchFieldAsInteger(td->fieldType)) == 0)
1341 return pContext->ThrowNativeError("Data field %s is not an integer (%d)",
1346 CHECK_SET_PROP_DATA_OFFSET();
1352 FIND_PROP_SEND(DPT_Int, "integer");
1354 // This isn't in CS:S yet, but will be, doesn't hurt to add now, and will save us a build later
1355 #if SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_TF2
1356 if (pProp->GetFlags() & SPROP_VARINT)
1358 bit_count = sizeof(int) * 8;
1365 return pContext->ThrowNativeError("Invalid Property type %d", params[2]);
1371 bit_count = params[5] * 8;
1374 if (bit_count >= 17)
1376 *(int32_t *)((uint8_t *)pEntity + offset) = params[4];
1378 else if (bit_count >= 9)
1380 *(int16_t *)((uint8_t *)pEntity + offset) = (int16_t)params[4];
1382 else if (bit_count >= 2)
1384 *(int8_t *)((uint8_t *)pEntity + offset) = (int8_t)params[4];
1388 *(bool *)((uint8_t *)pEntity + offset) = params[4] ? true : false;
1391 if (params[2] == Prop_Send && (pEdict != NULL))
1393 g_HL2.SetEdictStateChanged(pEdict, offset);
1399 static cell_t GetEntPropFloat(IPluginContext *pContext, const cell_t *params)
1401 CBaseEntity *pEntity;
1410 element = params[4];
1413 if (!IndexToAThings(params[1], &pEntity, &pEdict))
1415 return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
1418 pContext->LocalToString(params[3], &prop);
1424 typedescription_t *td;
1428 if (td->fieldType != FIELD_FLOAT
1429 && td->fieldType != FIELD_TIME)
1431 return pContext->ThrowNativeError("Data field %s is not a float (%d != [%d,%d])",
1438 CHECK_SET_PROP_DATA_OFFSET();
1444 FIND_PROP_SEND(DPT_Float, "float");
1449 return pContext->ThrowNativeError("Invalid Property type %d", params[2]);
1453 float val = *(float *)((uint8_t *)pEntity + offset);
1455 return sp_ftoc(val);
1458 static cell_t SetEntPropFloat(IPluginContext *pContext, const cell_t *params)
1460 CBaseEntity *pEntity;
1469 element = params[5];
1472 if (!IndexToAThings(params[1], &pEntity, &pEdict))
1474 return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
1477 pContext->LocalToString(params[3], &prop);
1483 typedescription_t *td;
1487 if (td->fieldType != FIELD_FLOAT
1488 && td->fieldType != FIELD_TIME)
1490 return pContext->ThrowNativeError("Data field %s is not a float (%d != [%d,%d])",
1497 CHECK_SET_PROP_DATA_OFFSET();
1503 FIND_PROP_SEND(DPT_Float, "float");
1508 return pContext->ThrowNativeError("Invalid Property type %d", params[2]);
1512 *(float *)((uint8_t *)pEntity + offset) = sp_ctof(params[4]);
1514 if (params[2] == Prop_Send && (pEdict != NULL))
1516 g_HL2.SetEdictStateChanged(pEdict, offset);
1522 static cell_t GetEntPropEnt(IPluginContext *pContext, const cell_t *params)
1524 CBaseEntity *pEntity;
1533 element = params[4];
1536 if (!IndexToAThings(params[1], &pEntity, &pEdict))
1538 return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
1541 pContext->LocalToString(params[3], &prop);
1547 typedescription_t *td;
1551 if (td->fieldType != FIELD_EHANDLE)
1553 return pContext->ThrowNativeError("Data field %s is not an entity (%d != %d)",
1559 CHECK_SET_PROP_DATA_OFFSET();
1565 FIND_PROP_SEND(DPT_Int, "integer");
1570 return pContext->ThrowNativeError("Invalid Property type %d", params[2]);
1574 CBaseHandle &hndl = *(CBaseHandle *)((uint8_t *)pEntity + offset);
1575 CBaseEntity *pHandleEntity = g_HL2.ReferenceToEntity(hndl.GetEntryIndex());
1577 if (!pHandleEntity || hndl != reinterpret_cast<IHandleEntity *>(pHandleEntity)->GetRefEHandle())
1580 return g_HL2.EntityToBCompatRef(pHandleEntity);
1583 static cell_t SetEntPropEnt(IPluginContext *pContext, const cell_t *params)
1585 CBaseEntity *pEntity;
1594 element = params[5];
1597 if (!IndexToAThings(params[1], &pEntity, &pEdict))
1599 return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
1602 pContext->LocalToString(params[3], &prop);
1608 typedescription_t *td;
1612 if (td->fieldType != FIELD_EHANDLE)
1614 return pContext->ThrowNativeError("Data field %s is not an entity (%d != %d)",
1620 CHECK_SET_PROP_DATA_OFFSET();
1626 FIND_PROP_SEND(DPT_Int, "integer");
1631 return pContext->ThrowNativeError("Invalid Property type %d", params[2]);
1635 CBaseHandle &hndl = *(CBaseHandle *)((uint8_t *)pEntity + offset);
1637 if (params[4] == -1)
1643 CBaseEntity *pOther = GetEntity(params[4]);
1647 return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[4]), params[4]);
1650 IHandleEntity *pHandleEnt = (IHandleEntity *)pOther;
1651 hndl.Set(pHandleEnt);
1654 if (params[2] == Prop_Send && (pEdict != NULL))
1656 g_HL2.SetEdictStateChanged(pEdict, offset);
1662 static cell_t GetEntPropVector(IPluginContext *pContext, const cell_t *params)
1664 CBaseEntity *pEntity;
1673 element = params[5];
1676 if (!IndexToAThings(params[1], &pEntity, &pEdict))
1678 return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
1681 pContext->LocalToString(params[3], &prop);
1687 typedescription_t *td;
1691 if (td->fieldType != FIELD_VECTOR
1692 && td->fieldType != FIELD_POSITION_VECTOR)
1694 return pContext->ThrowNativeError("Data field %s is not a vector (%d != [%d,%d])",
1698 FIELD_POSITION_VECTOR);
1701 CHECK_SET_PROP_DATA_OFFSET();
1707 FIND_PROP_SEND(DPT_Vector, "vector");
1712 return pContext->ThrowNativeError("Invalid Property type %d", params[2]);
1716 Vector *v = (Vector *)((uint8_t *)pEntity + offset);
1719 pContext->LocalToPhysAddr(params[4], &vec);
1721 vec[0] = sp_ftoc(v->x);
1722 vec[1] = sp_ftoc(v->y);
1723 vec[2] = sp_ftoc(v->z);
1728 static cell_t SetEntPropVector(IPluginContext *pContext, const cell_t *params)
1730 CBaseEntity *pEntity;
1739 element = params[5];
1742 if (!IndexToAThings(params[1], &pEntity, &pEdict))
1744 return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
1747 pContext->LocalToString(params[3], &prop);
1753 typedescription_t *td;
1757 if (td->fieldType != FIELD_VECTOR
1758 && td->fieldType != FIELD_POSITION_VECTOR)
1760 return pContext->ThrowNativeError("Data field %s is not a vector (%d != [%d,%d])",
1764 FIELD_POSITION_VECTOR);
1767 CHECK_SET_PROP_DATA_OFFSET();
1773 FIND_PROP_SEND(DPT_Vector, "vector");
1778 return pContext->ThrowNativeError("Invalid Property type %d", params[2]);
1782 Vector *v = (Vector *)((uint8_t *)pEntity + offset);
1785 pContext->LocalToPhysAddr(params[4], &vec);
1787 v->x = sp_ctof(vec[0]);
1788 v->y = sp_ctof(vec[1]);
1789 v->z = sp_ctof(vec[2]);
1791 if (params[2] == Prop_Send && (pEdict != NULL))
1793 g_HL2.SetEdictStateChanged(pEdict, offset);
1799 static cell_t GetEntPropString(IPluginContext *pContext, const cell_t *params)
1801 CBaseEntity *pEntity;
1805 bool bIsStringIndex;
1810 element = params[6];
1813 if (!IndexToAThings(params[1], &pEntity, &pEdict))
1815 return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
1818 pContext->LocalToString(params[3], &prop);
1820 bIsStringIndex = false;
1826 typedescription_t *td;
1830 if (td->fieldType != FIELD_CHARACTER
1831 && td->fieldType != FIELD_STRING
1832 && td->fieldType != FIELD_MODELNAME
1833 && td->fieldType != FIELD_SOUNDNAME)
1835 return pContext->ThrowNativeError("Data field %s is not a string (%d != %d)",
1841 bIsStringIndex = (td->fieldType != FIELD_CHARACTER);
1843 if (bIsStringIndex && (element < 0 || element >= td->fieldSize))
1845 return pContext->ThrowNativeError("Element %d is out of bounds (Prop %s has %d elements).",
1850 else if (element != 0)
1852 return pContext->ThrowNativeError("Prop %s is not an array. Element %d is invalid.",
1857 offset = info.actual_offset;
1860 offset += (element * (td->fieldSizeInBytes / td->fieldSize));
1866 sm_sendprop_info_t info;
1868 IServerUnknown *pUnk = (IServerUnknown *)pEntity;
1869 IServerNetworkable *pNet = pUnk->GetNetworkable();
1872 return pContext->ThrowNativeError("Edict %d (%d) is not networkable", g_HL2.ReferenceToIndex(params[1]), params[1]);
1874 if (!g_HL2.FindSendPropInfo(pNet->GetServerClass()->GetName(), prop, &info))
1876 const char *class_name = g_HL2.GetEntityClassname(pEntity);
1877 return pContext->ThrowNativeError("Property \"%s\" not found (entity %d/%s)",
1880 ((class_name) ? class_name : ""));
1883 offset = info.actual_offset;
1885 if (info.prop->GetType() != DPT_String)
1887 return pContext->ThrowNativeError("SendProp %s is not a string (%d != %d)",
1889 info.prop->GetType(),
1892 else if (element != 0)
1894 return pContext->ThrowNativeError("SendProp %s is not an array. Element %d is invalid.",
1903 return pContext->ThrowNativeError("Invalid Property type %d", params[2]);
1910 if (!bIsStringIndex)
1912 src = (char *)((uint8_t *)pEntity + offset);
1918 idx = *(string_t *)((uint8_t *)pEntity + offset);
1919 src = (idx == NULL_STRING) ? "" : STRING(idx);
1922 pContext->StringToLocalUTF8(params[4], params[5], src, &len);
1927 static cell_t SetEntPropString(IPluginContext *pContext, const cell_t *params)
1929 CBaseEntity *pEntity;
1935 if (!IndexToAThings(params[1], &pEntity, &pEdict))
1937 return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
1945 if ((pMap=CBaseEntity_GetDataDescMap(pEntity)) == NULL)
1947 return pContext->ThrowNativeError("Unable to retrieve GetDataDescMap offset");
1949 pContext->LocalToString(params[3], &prop);
1950 sm_datatable_info_t info;
1951 if (!g_HL2.FindDataMapInfo(pMap, prop, &info))
1953 return pContext->ThrowNativeError("Property \"%s\" not found for entity %d", prop, params[1]);
1956 typedescription_t *td = info.prop;
1957 if (td->fieldType != FIELD_CHARACTER)
1959 return pContext->ThrowNativeError("Property \"%s\" is not a valid string", prop);
1961 offset = info.actual_offset;
1962 maxlen = td->fieldSize;
1968 IServerUnknown *pUnk = (IServerUnknown *)pEntity;
1969 IServerNetworkable *pNet = pUnk->GetNetworkable();
1972 return pContext->ThrowNativeError("The edict is not networkable");
1974 pContext->LocalToString(params[3], &prop);
1975 SendProp *pSend = g_HL2.FindInSendTable(pNet->GetServerClass()->GetName(), prop);
1978 return pContext->ThrowNativeError("Property \"%s\" not found for entity %d", prop, params[1]);
1980 if (pSend->GetType() != DPT_String)
1982 return pContext->ThrowNativeError("Property \"%s\" is not a valid string", prop);
1984 offset = pSend->GetOffset();
1985 maxlen = DT_MAX_STRING_BUFFERSIZE;
1990 return pContext->ThrowNativeError("Invalid Property type %d", params[2]);
1995 char *dest = (char *)((uint8_t *)pEntity + offset);
1997 pContext->LocalToString(params[4], &src);
1998 size_t len = strncopy(dest, src, maxlen);
2000 if (params[2] == Prop_Send && (pEdict != NULL))
2002 g_HL2.SetEdictStateChanged(pEdict, offset);
2008 static int32_t SDKEntFlagToSMEntFlag(int flag)
2013 return ENTFLAG_ONGROUND;
2015 return ENTFLAG_DUCKING;
2017 return ENTFLAG_WATERJUMP;
2019 return ENTFLAG_ONTRAIN;
2021 return ENTFLAG_INRAIN;
2023 return ENTFLAG_FROZEN;
2025 return ENTFLAG_ATCONTROLS;
2027 return ENTFLAG_CLIENT;
2029 return ENTFLAG_FAKECLIENT;
2031 return ENTFLAG_INWATER;
2035 return ENTFLAG_SWIM;
2037 return ENTFLAG_CONVEYOR;
2041 return ENTFLAG_GODMODE;
2043 return ENTFLAG_NOTARGET;
2045 return ENTFLAG_AIMTARGET;
2046 case FL_PARTIALGROUND:
2047 return ENTFLAG_PARTIALGROUND;
2049 return ENTFLAG_STATICPROP;
2051 return ENTFLAG_GRAPHED;
2053 return ENTFLAG_GRENADE;
2054 case FL_STEPMOVEMENT:
2055 return ENTFLAG_STEPMOVEMENT;
2057 return ENTFLAG_DONTTOUCH;
2058 case FL_BASEVELOCITY:
2059 return ENTFLAG_BASEVELOCITY;
2061 return ENTFLAG_WORLDBRUSH;
2063 return ENTFLAG_OBJECT;
2065 return ENTFLAG_KILLME;
2067 return ENTFLAG_ONFIRE;
2069 return ENTFLAG_DISSOLVING;
2070 case FL_TRANSRAGDOLL:
2071 return ENTFLAG_TRANSRAGDOLL;
2072 case FL_UNBLOCKABLE_BY_PLAYER:
2073 return ENTFLAG_UNBLOCKABLE_BY_PLAYER;
2074 #if SOURCE_ENGINE == SE_ALIENSWARM
2076 return ENTFLAG_FREEZING;
2077 #elif SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_TF2
2078 case FL_EP2V_UNKNOWN:
2079 return ENTFLAG_EP2V_UNKNOWN1;
2086 static int32_t SMEntFlagToSDKEntFlag(int32_t flag)
2090 case ENTFLAG_ONGROUND:
2092 case ENTFLAG_DUCKING:
2094 case ENTFLAG_WATERJUMP:
2095 return FL_WATERJUMP;
2096 case ENTFLAG_ONTRAIN:
2098 case ENTFLAG_INRAIN:
2100 case ENTFLAG_FROZEN:
2102 case ENTFLAG_ATCONTROLS:
2103 return FL_ATCONTROLS;
2104 case ENTFLAG_CLIENT:
2106 case ENTFLAG_FAKECLIENT:
2107 return FL_FAKECLIENT;
2108 case ENTFLAG_INWATER:
2114 case ENTFLAG_CONVEYOR:
2118 case ENTFLAG_GODMODE:
2120 case ENTFLAG_NOTARGET:
2122 case ENTFLAG_AIMTARGET:
2123 return FL_AIMTARGET;
2124 case ENTFLAG_PARTIALGROUND:
2125 return FL_PARTIALGROUND;
2126 case ENTFLAG_STATICPROP:
2127 return FL_STATICPROP;
2128 case ENTFLAG_GRAPHED:
2130 case ENTFLAG_GRENADE:
2132 case ENTFLAG_STEPMOVEMENT:
2133 return FL_STEPMOVEMENT;
2134 case ENTFLAG_DONTTOUCH:
2135 return FL_DONTTOUCH;
2136 case ENTFLAG_BASEVELOCITY:
2137 return FL_BASEVELOCITY;
2138 case ENTFLAG_WORLDBRUSH:
2139 return FL_WORLDBRUSH;
2140 case ENTFLAG_OBJECT:
2142 case ENTFLAG_KILLME:
2144 case ENTFLAG_ONFIRE:
2146 case ENTFLAG_DISSOLVING:
2147 return FL_DISSOLVING;
2148 case ENTFLAG_TRANSRAGDOLL:
2149 return FL_TRANSRAGDOLL;
2150 case ENTFLAG_UNBLOCKABLE_BY_PLAYER:
2151 return FL_UNBLOCKABLE_BY_PLAYER;
2152 #if SOURCE_ENGINE == SE_ALIENSWARM
2153 case ENTFLAG_FREEZING:
2155 #elif SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_TF2
2156 case ENTFLAG_EP2V_UNKNOWN1:
2157 return FL_EP2V_UNKNOWN;
2164 static cell_t GetEntityFlags(IPluginContext *pContext, const cell_t *params)
2166 CBaseEntity *pEntity = g_HL2.ReferenceToEntity(params[1]);
2169 return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
2172 const char *prop = g_pGameConf->GetKeyValue("m_fFlags");
2175 return pContext->ThrowNativeError("Could not find m_fFlags prop in gamedata");
2178 typedescription_t *td;
2181 if ((pMap = CBaseEntity_GetDataDescMap(pEntity)) == NULL)
2183 return pContext->ThrowNativeError("Could not retrieve datamap");
2186 sm_datatable_info_t info;
2187 if (!g_HL2.FindDataMapInfo(pMap, prop, &info))
2189 return pContext->ThrowNativeError("Property \"%s\" not found (entity %d)",
2194 int offset = info.actual_offset;
2196 int32_t actual_flags = *(int32_t *)((uint8_t *)pEntity + offset);
2197 int32_t sm_flags = 0;
2199 for (int32_t i = 0; i < 32; i++)
2201 int32_t flag = (1<<i);
2202 if ((actual_flags & flag) == flag)
2204 sm_flags |= SDKEntFlagToSMEntFlag(flag);
2211 static cell_t SetEntityFlags(IPluginContext *pContext, const cell_t *params)
2213 CBaseEntity *pEntity = g_HL2.ReferenceToEntity(params[1]);
2216 return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
2219 const char *prop = g_pGameConf->GetKeyValue("m_fFlags");
2222 return pContext->ThrowNativeError("Could not find m_fFlags prop in gamedata");
2227 if ((pMap = CBaseEntity_GetDataDescMap(pEntity)) == NULL)
2229 return pContext->ThrowNativeError("Could not retrieve datamap");
2232 sm_datatable_info_t info;
2233 if (!g_HL2.FindDataMapInfo(pMap, prop, &info))
2235 return pContext->ThrowNativeError("Property \"%s\" not found (entity %d)",
2240 int offset = info.actual_offset;
2242 int32_t sm_flags = params[2];
2243 int32_t actual_flags = 0;
2245 for (int32_t i = 0; i < 32; i++)
2247 int32_t flag = (1<<i);
2248 if ((sm_flags & flag) == flag)
2250 actual_flags |= SMEntFlagToSDKEntFlag(flag);
2254 *(int32_t *)((uint8_t *)pEntity + offset) = actual_flags;
2259 static cell_t GetEntityAddress(IPluginContext *pContext, const cell_t *params)
2261 CBaseEntity * pEntity = GetEntity(params[1]);
2264 return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
2266 return reinterpret_cast<cell_t>(pEntity);
2269 REGISTER_NATIVES(entityNatives)
2271 {"ChangeEdictState", ChangeEdictState},
2272 {"CreateEdict", CreateEdict},
2273 {"FindDataMapOffs", FindDataMapOffs},
2274 {"FindSendPropInfo", FindSendPropInfo},
2275 {"FindSendPropOffs", FindSendPropOffs},
2276 {"GetEdictClassname", GetEdictClassname},
2277 {"GetEdictFlags", GetEdictFlags},
2278 {"GetEntData", GetEntData},
2279 {"GetEntDataEnt", GetEntDataEnt}, /** DEPRECATED */
2280 {"GetEntDataEnt2", GetEntDataEnt2},
2281 {"GetEntDataFloat", GetEntDataFloat},
2282 {"GetEntDataString", GetEntDataString},
2283 {"GetEntDataVector", GetEntDataVector},
2284 {"GetEntProp", GetEntProp},
2285 {"GetEntPropArraySize", GetEntPropArraySize},
2286 {"GetEntPropEnt", GetEntPropEnt},
2287 {"GetEntPropFloat", GetEntPropFloat},
2288 {"GetEntPropString", GetEntPropString},
2289 {"GetEntPropVector", GetEntPropVector},
2290 {"GetEntityCount", GetEntityCount},
2291 {"GetEntityFlags", GetEntityFlags},
2292 {"GetEntityNetClass", GetEntityNetClass},
2293 {"GetMaxEntities", GetMaxEntities},
2294 {"IsEntNetworkable", IsEntNetworkable},
2295 {"IsValidEdict", IsValidEdict},
2296 {"IsValidEntity", IsValidEntity},
2297 {"RemoveEdict", RemoveEdict},
2298 {"SetEdictFlags", SetEdictFlags},
2299 {"SetEntData", SetEntData},
2300 {"SetEntDataEnt", SetEntDataEnt}, /** DEPRECATED */
2301 {"SetEntDataEnt2", SetEntDataEnt2},
2302 {"SetEntDataFloat", SetEntDataFloat},
2303 {"SetEntDataVector", SetEntDataVector},
2304 {"SetEntDataString", SetEntDataString},
2305 {"SetEntityFlags", SetEntityFlags},
2306 {"SetEntProp", SetEntProp},
2307 {"SetEntPropEnt", SetEntPropEnt},
2308 {"SetEntPropFloat", SetEntPropFloat},
2309 {"SetEntPropString", SetEntPropString},
2310 {"SetEntPropVector", SetEntPropVector},
2311 {"GetEntityAddress", GetEntityAddress},
2312 {"FindDataMapInfo", FindDataMapInfo},