3 * =============================================================================
5 * Copyright (C) 2004-2007 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 "server_class.h"
36 #include "PlayerManager.h"
37 #include "HalfLife2.h"
38 #include "GameConfigs.h"
39 #include "sm_stringutil.h"
49 PropField_Unsupported, /**< The type is unsupported. */
50 PropField_Integer, /**< Valid for SendProp and Data fields */
51 PropField_Float, /**< Valid for SendProp and Data fields */
52 PropField_Entity, /**< Valid for Data fields only (SendProp shows as int) */
53 PropField_Vector, /**< Valid for SendProp and Data fields */
54 PropField_String, /**< Valid for SendProp and Data fields */
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;
801 *pType = PropField_Float;
807 *pType = PropField_Entity;
813 *pType = PropField_Unsupported;
819 return td->fieldOffset[TD_OFFSET_NORMAL];
822 static cell_t GetEntDataString(IPluginContext *pContext, const cell_t *params)
824 CBaseEntity *pEntity;
825 edict_t *pEdict = GetEntity(params[1], &pEntity);
827 if (!pEdict || !pEntity)
829 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
832 int offset = params[2];
833 if (offset < 0 || offset > 32768)
835 return pContext->ThrowNativeError("Offset %d is invalid", offset);
839 char *src = (char *)((uint8_t *)pEntity + offset);
840 pContext->StringToLocalUTF8(params[3], params[4], src, &len);
845 static cell_t SetEntDataString(IPluginContext *pContext, const cell_t *params)
847 CBaseEntity *pEntity;
848 edict_t *pEdict = GetEntity(params[1], &pEntity);
850 if (!pEdict || !pEntity)
852 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
855 int offset = params[2];
856 if (offset < 0 || offset > 32768)
858 return pContext->ThrowNativeError("Offset %d is invalid", offset);
862 char *dest = (char *)((uint8_t *)pEntity + offset);
864 pContext->LocalToString(params[3], &src);
865 size_t len = strncopy(dest, src, params[4]);
869 g_HL2.SetEdictStateChanged(pEdict, offset);
875 #define FIND_PROP_DATA(td) \
877 if ((pMap = CBaseEntity_GetDataDescMap(pEntity)) == NULL) \
879 return pContext->ThrowNativeError("Could not retrieve datamap"); \
881 if ((td = g_HL2.FindInDataMap(pMap, prop)) == NULL) \
883 return pContext->ThrowNativeError("Property \"%s\" not found (entity %d/%s)", \
889 #define FIND_PROP_SEND(pProp) \
890 IServerNetworkable *pNet = pEdict->GetNetworkable(); \
893 return pContext->ThrowNativeError("Edict %d is not networkable", params[1]); \
895 if (!g_HL2.FindSendPropInfo(pNet->GetServerClass()->GetName(), prop, pProp)) \
897 return pContext->ThrowNativeError("Property \"%s\" not found (entity %d/%s)", \
903 inline int MatchFieldAsInteger(int field_type)
908 case FIELD_MODELINDEX:
909 case FIELD_MATERIALINDEX:
915 case FIELD_CHARACTER:
926 static cell_t GetEntProp(IPluginContext *pContext, const cell_t *params)
928 CBaseEntity *pEntity;
931 const char *class_name;
935 pEdict = GetEntity(params[1], &pEntity);
937 if (!pEdict || !pEntity)
939 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
942 if ((class_name = pEdict->GetClassName()) == NULL)
947 pContext->LocalToString(params[3], &prop);
953 typedescription_t *td;
957 if ((bit_count = MatchFieldAsInteger(td->fieldType)) == 0)
959 return pContext->ThrowNativeError("Data field %s is not an integer (%d)",
964 offset = td->fieldOffset[TD_OFFSET_NORMAL];
969 sm_sendprop_info_t info;
971 FIND_PROP_SEND(&info);
973 if (info.prop->GetType() != DPT_Int)
975 return pContext->ThrowNativeError("SendProp %s is not an integer ([%d,%d] != %d)",
977 info.prop->GetType(),
982 bit_count = info.prop->m_nBits;
983 offset = info.actual_offset;
988 return pContext->ThrowNativeError("Invalid Property type %d", params[2]);
994 bit_count = params[4] * 8;
999 return *(int32_t *)((uint8_t *)pEntity + offset);
1001 else if (bit_count >= 9)
1003 return *(int16_t *)((uint8_t *)pEntity + offset);
1005 else if (bit_count >= 2)
1007 return *(int8_t *)((uint8_t *)pEntity + offset);
1011 return *(bool *)((uint8_t *)pEntity + offset) ? 1 : 0;
1017 static cell_t SetEntProp(IPluginContext *pContext, const cell_t *params)
1019 CBaseEntity *pEntity;
1022 const char *class_name;
1026 pEdict = GetEntity(params[1], &pEntity);
1028 if (!pEdict || !pEntity)
1030 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
1033 if ((class_name = pEdict->GetClassName()) == NULL)
1038 pContext->LocalToString(params[3], &prop);
1044 typedescription_t *td;
1048 if ((bit_count = MatchFieldAsInteger(td->fieldType)) == 0)
1050 return pContext->ThrowNativeError("Data field %s is not an integer (%d)",
1055 offset = td->fieldOffset[TD_OFFSET_NORMAL];
1060 sm_sendprop_info_t info;
1062 FIND_PROP_SEND(&info);
1064 if (info.prop->GetType() != DPT_Int)
1066 return pContext->ThrowNativeError("SendProp %s is not an integer ([%d,%d] != %d)",
1068 info.prop->GetType(),
1073 bit_count = info.prop->m_nBits;
1074 offset = info.actual_offset;
1079 return pContext->ThrowNativeError("Invalid Property type %d", params[2]);
1085 bit_count = params[5] * 8;
1088 if (bit_count >= 17)
1090 *(int32_t *)((uint8_t *)pEntity + offset) = params[4];
1092 else if (bit_count >= 9)
1094 *(int16_t *)((uint8_t *)pEntity + offset) = (int16_t)params[4];
1096 else if (bit_count >= 2)
1098 *(int8_t *)((uint8_t *)pEntity + offset) = (int8_t)params[4];
1102 *(bool *)((uint8_t *)pEntity + offset) = params[4] ? true : false;
1108 static cell_t GetEntPropFloat(IPluginContext *pContext, const cell_t *params)
1110 CBaseEntity *pEntity;
1113 const char *class_name;
1116 pEdict = GetEntity(params[1], &pEntity);
1118 if (!pEdict || !pEntity)
1120 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
1123 if ((class_name = pEdict->GetClassName()) == NULL)
1128 pContext->LocalToString(params[3], &prop);
1134 typedescription_t *td;
1138 if (td->fieldType != FIELD_FLOAT
1139 && td->fieldType != FIELD_TIME)
1141 return pContext->ThrowNativeError("Data field %s is not a float (%d != [%d,%d])",
1148 offset = td->fieldOffset[TD_OFFSET_NORMAL];
1153 sm_sendprop_info_t info;
1155 FIND_PROP_SEND(&info);
1157 if (info.prop->GetType() != DPT_Float)
1159 return pContext->ThrowNativeError("SendProp %s is not a float (%d != %d)",
1161 info.prop->GetType(),
1165 offset = info.actual_offset;
1170 return pContext->ThrowNativeError("Invalid Property type %d", params[2]);
1174 float val = *(float *)((uint8_t *)pEntity + offset);
1176 return sp_ftoc(val);
1179 static cell_t SetEntPropFloat(IPluginContext *pContext, const cell_t *params)
1181 CBaseEntity *pEntity;
1184 const char *class_name;
1187 pEdict = GetEntity(params[1], &pEntity);
1189 if (!pEdict || !pEntity)
1191 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
1194 if ((class_name = pEdict->GetClassName()) == NULL)
1199 pContext->LocalToString(params[3], &prop);
1205 typedescription_t *td;
1209 if (td->fieldType != FIELD_FLOAT
1210 && td->fieldType != FIELD_TIME)
1212 return pContext->ThrowNativeError("Data field %s is not a float (%d != [%d,%d])",
1219 offset = td->fieldOffset[TD_OFFSET_NORMAL];
1224 sm_sendprop_info_t info;
1226 FIND_PROP_SEND(&info);
1228 if (info.prop->GetType() != DPT_Float)
1230 return pContext->ThrowNativeError("SendProp %s is not a float (%d != %d)",
1232 info.prop->GetType(),
1236 offset = info.actual_offset;
1241 return pContext->ThrowNativeError("Invalid Property type %d", params[2]);
1245 *(float *)((uint8_t *)pEntity + offset) = sp_ctof(params[4]);
1247 if (params[2] == Prop_Send)
1249 g_HL2.SetEdictStateChanged(pEdict, offset);
1255 static cell_t GetEntPropEnt(IPluginContext *pContext, const cell_t *params)
1257 CBaseEntity *pEntity;
1260 const char *class_name;
1263 pEdict = GetEntity(params[1], &pEntity);
1265 if (!pEdict || !pEntity)
1267 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
1270 if ((class_name = pEdict->GetClassName()) == NULL)
1275 pContext->LocalToString(params[3], &prop);
1281 typedescription_t *td;
1285 if (td->fieldType != FIELD_EHANDLE)
1287 return pContext->ThrowNativeError("Data field %s is not an entity (%d != %d)",
1293 offset = td->fieldOffset[TD_OFFSET_NORMAL];
1298 sm_sendprop_info_t info;
1300 FIND_PROP_SEND(&info);
1302 if (info.prop->GetType() != DPT_Int)
1304 return pContext->ThrowNativeError("SendProp %s is not an integer (%d != %d)",
1306 info.prop->GetType(),
1310 offset = info.actual_offset;
1315 return pContext->ThrowNativeError("Invalid Property type %d", params[2]);
1319 CBaseHandle &hndl = *(CBaseHandle *)((uint8_t *)pEntity + offset);
1321 return CheckBaseHandle(hndl);
1324 static cell_t SetEntPropEnt(IPluginContext *pContext, const cell_t *params)
1326 CBaseEntity *pEntity;
1329 const char *class_name;
1332 pEdict = GetEntity(params[1], &pEntity);
1334 if (!pEdict || !pEntity)
1336 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
1339 if ((class_name = pEdict->GetClassName()) == NULL)
1344 pContext->LocalToString(params[3], &prop);
1350 typedescription_t *td;
1354 if (td->fieldType != FIELD_EHANDLE)
1356 return pContext->ThrowNativeError("Data field %s is not an entity (%d != %d)",
1362 offset = td->fieldOffset[TD_OFFSET_NORMAL];
1367 sm_sendprop_info_t info;
1369 FIND_PROP_SEND(&info);
1371 if (info.prop->GetType() != DPT_Int)
1373 return pContext->ThrowNativeError("SendProp %s is not an integer (%d != %d)",
1375 info.prop->GetType(),
1379 offset = info.actual_offset;
1384 return pContext->ThrowNativeError("Invalid Property type %d", params[2]);
1388 CBaseHandle &hndl = *(CBaseHandle *)((uint8_t *)pEntity + offset);
1390 if (params[4] == -1)
1397 CBaseEntity *pOtherEnt;
1399 if ((pOther = GetEntity(params[4], &pOtherEnt)) == NULL)
1401 return pContext->ThrowNativeError("Invalid entity %d", params[4]);
1404 hndl.Set(pOther->GetIServerEntity());
1407 if (params[2] == Prop_Send)
1409 g_HL2.SetEdictStateChanged(pEdict, offset);
1415 static cell_t GetEntPropVector(IPluginContext *pContext, const cell_t *params)
1417 CBaseEntity *pEntity;
1420 const char *class_name;
1423 pEdict = GetEntity(params[1], &pEntity);
1425 if (!pEdict || !pEntity)
1427 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
1430 if ((class_name = pEdict->GetClassName()) == NULL)
1435 pContext->LocalToString(params[3], &prop);
1441 typedescription_t *td;
1445 if (td->fieldType != FIELD_VECTOR
1446 && td->fieldType != FIELD_POSITION_VECTOR)
1448 return pContext->ThrowNativeError("Data field %s is not a vector (%d != [%d,%d])",
1452 FIELD_POSITION_VECTOR);
1455 offset = td->fieldOffset[TD_OFFSET_NORMAL];
1460 sm_sendprop_info_t info;
1462 FIND_PROP_SEND(&info);
1464 if (info.prop->GetType() != DPT_Vector)
1466 return pContext->ThrowNativeError("SendProp %s is not a vector (%d != %d)",
1468 info.prop->GetType(),
1472 offset = info.actual_offset;
1477 return pContext->ThrowNativeError("Invalid Property type %d", params[2]);
1481 Vector *v = (Vector *)((uint8_t *)pEntity + offset);
1484 pContext->LocalToPhysAddr(params[4], &vec);
1486 vec[0] = sp_ftoc(v->x);
1487 vec[1] = sp_ftoc(v->y);
1488 vec[2] = sp_ftoc(v->z);
1493 static cell_t SetEntPropVector(IPluginContext *pContext, const cell_t *params)
1495 CBaseEntity *pEntity;
1498 const char *class_name;
1501 pEdict = GetEntity(params[1], &pEntity);
1503 if (!pEdict || !pEntity)
1505 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
1508 if ((class_name = pEdict->GetClassName()) == NULL)
1513 pContext->LocalToString(params[3], &prop);
1519 typedescription_t *td;
1523 if (td->fieldType != FIELD_VECTOR
1524 && td->fieldType != FIELD_POSITION_VECTOR)
1526 return pContext->ThrowNativeError("Data field %s is not a vector (%d != [%d,%d])",
1530 FIELD_POSITION_VECTOR);
1533 offset = td->fieldOffset[TD_OFFSET_NORMAL];
1538 sm_sendprop_info_t info;
1540 FIND_PROP_SEND(&info);
1542 if (info.prop->GetType() != DPT_Vector)
1544 return pContext->ThrowNativeError("SendProp %s is not a vector (%d != %d)",
1546 info.prop->GetType(),
1550 offset = info.actual_offset;
1555 return pContext->ThrowNativeError("Invalid Property type %d", params[2]);
1559 Vector *v = (Vector *)((uint8_t *)pEntity + offset);
1562 pContext->LocalToPhysAddr(params[4], &vec);
1564 v->x = sp_ctof(vec[0]);
1565 v->y = sp_ctof(vec[1]);
1566 v->z = sp_ctof(vec[2]);
1568 if (params[2] == Prop_Send)
1570 g_HL2.SetEdictStateChanged(pEdict, offset);
1576 static cell_t GetEntPropString(IPluginContext *pContext, const cell_t *params)
1578 CBaseEntity *pEntity;
1581 const char *class_name;
1584 pEdict = GetEntity(params[1], &pEntity);
1586 if (!pEdict || !pEntity)
1588 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
1591 if ((class_name = pEdict->GetClassName()) == NULL)
1596 pContext->LocalToString(params[3], &prop);
1602 typedescription_t *td;
1606 if (td->fieldType != FIELD_CHARACTER)
1608 return pContext->ThrowNativeError("Data field %s is not a string (%d != %d)",
1614 offset = td->fieldOffset[TD_OFFSET_NORMAL];
1619 sm_sendprop_info_t info;
1621 FIND_PROP_SEND(&info);
1623 if (info.prop->GetType() != DPT_String)
1625 return pContext->ThrowNativeError("SendProp %s is not a string (%d != %d)",
1627 info.prop->GetType(),
1631 offset = info.actual_offset;
1637 return pContext->ThrowNativeError("Invalid Property type %d", params[2]);
1642 char *src = (char *)((uint8_t *)pEntity + offset);
1643 pContext->StringToLocalUTF8(params[4], params[5], src, &len);
1648 static cell_t SetEntPropString(IPluginContext *pContext, const cell_t *params)
1650 CBaseEntity *pEntity;
1654 edict_t *pEdict = GetEntity(params[1], &pEntity);
1656 if (!pEdict || !pEntity)
1658 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
1666 typedescription_t *td;
1667 if ((pMap=CBaseEntity_GetDataDescMap(pEntity)) == NULL)
1669 return pContext->ThrowNativeError("Unable to retrieve GetDataDescMap offset");
1671 pContext->LocalToString(params[3], &prop);
1672 if ((td=g_HL2.FindInDataMap(pMap, prop)) == NULL)
1674 return pContext->ThrowNativeError("Property \"%s\" not found for entity %d", prop, params[1]);
1676 if (td->fieldType != FIELD_CHARACTER)
1678 return pContext->ThrowNativeError("Property \"%s\" is not a valid string", prop);
1680 offset = td->fieldOffset[TD_OFFSET_NORMAL];
1681 maxlen = td->fieldSize;
1687 IServerNetworkable *pNet = pEdict->GetNetworkable();
1690 return pContext->ThrowNativeError("The edict is not networkable");
1692 pContext->LocalToString(params[3], &prop);
1693 SendProp *pSend = g_HL2.FindInSendTable(pNet->GetServerClass()->GetName(), prop);
1696 return pContext->ThrowNativeError("Property \"%s\" not found for entity %d", prop, params[1]);
1698 if (pSend->GetType() != DPT_String)
1700 return pContext->ThrowNativeError("Property \"%s\" is not a valid string", prop);
1702 offset = pSend->GetOffset();
1703 maxlen = DT_MAX_STRING_BUFFERSIZE;
1708 return pContext->ThrowNativeError("Invalid Property type %d", params[2]);
1713 char *dest = (char *)((uint8_t *)pEntity + offset);
1715 pContext->LocalToString(params[4], &src);
1716 size_t len = strncopy(dest, src, maxlen);
1718 if (params[2] == Prop_Send)
1720 g_HL2.SetEdictStateChanged(pEdict, offset);
1726 REGISTER_NATIVES(entityNatives)
1728 {"ChangeEdictState", ChangeEdictState},
1729 {"CreateEdict", CreateEdict},
1730 {"FindDataMapOffs", FindDataMapOffs},
1731 {"FindSendPropInfo", FindSendPropInfo},
1732 {"FindSendPropOffs", FindSendPropOffs},
1733 {"GetEdictClassname", GetEdictClassname},
1734 {"GetEdictFlags", GetEdictFlags},
1735 {"GetEntData", GetEntData},
1736 {"GetEntDataEnt", GetEntDataEnt}, /** DEPRECATED */
1737 {"GetEntDataEnt2", GetEntDataEnt2},
1738 {"GetEntDataFloat", GetEntDataFloat},
1739 {"GetEntDataString", GetEntDataString},
1740 {"GetEntDataVector", GetEntDataVector},
1741 {"GetEntProp", GetEntProp},
1742 {"GetEntPropEnt", GetEntPropEnt},
1743 {"GetEntPropFloat", GetEntPropFloat},
1744 {"GetEntPropString", GetEntPropString},
1745 {"GetEntPropVector", GetEntPropVector},
1746 {"GetEntityCount", GetEntityCount},
1747 {"GetEntityNetClass", GetEntityNetClass},
1748 {"GetMaxEntities", GetMaxEntities},
1749 {"IsEntNetworkable", IsEntNetworkable},
1750 {"IsValidEdict", IsValidEdict},
1751 {"IsValidEntity", IsValidEntity},
1752 {"RemoveEdict", RemoveEdict},
1753 {"SetEdictFlags", SetEdictFlags},
1754 {"SetEntData", SetEntData},
1755 {"SetEntDataEnt", SetEntDataEnt}, /** DEPRECATED */
1756 {"SetEntDataEnt2", SetEntDataEnt2},
1757 {"SetEntDataFloat", SetEntDataFloat},
1758 {"SetEntDataVector", SetEntDataVector},
1759 {"SetEntDataString", SetEntDataString},
1760 {"SetEntProp", SetEntProp},
1761 {"SetEntPropEnt", SetEntPropEnt},
1762 {"SetEntPropFloat", SetEntPropFloat},
1763 {"SetEntPropString", SetEntPropString},
1764 {"SetEntPropVector", SetEntPropVector},