From 37a08f66b07153baba974d0d7604e0c6a9df2e31 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Wed, 26 May 2004 05:15:40 +0000 Subject: [PATCH] New version of Engine. --- dlls/engine/amxxapi.cpp | 136 +++ dlls/engine/amxxmodule.cpp | 22 +- dlls/engine/amxxmodule.h | 62 +- dlls/engine/engine.cpp | 816 ++++++++++++++++ dlls/engine/engine.dsp | 36 + dlls/engine/engine.h | 998 ++------------------ dlls/engine/engine.vcproj | 170 ++-- dlls/engine/entity.cpp | 1788 ++++++++++++++++++++++++++++++++++++ dlls/engine/entity.h | 155 ++++ dlls/engine/forwards.cpp | 229 +++++ dlls/engine/globals.cpp | 177 ++++ dlls/engine/gpglobals.h | 53 ++ dlls/engine/messages.cpp | 477 ++++++++++ dlls/engine/messages.h | 45 + dlls/engine/meta_api.cpp | 16 +- dlls/engine/moduleconfig.h | 24 +- 16 files changed, 4129 insertions(+), 1075 deletions(-) create mode 100755 dlls/engine/amxxapi.cpp create mode 100755 dlls/engine/engine.cpp create mode 100755 dlls/engine/entity.cpp create mode 100755 dlls/engine/entity.h create mode 100755 dlls/engine/forwards.cpp create mode 100755 dlls/engine/globals.cpp create mode 100755 dlls/engine/gpglobals.h create mode 100755 dlls/engine/messages.cpp create mode 100755 dlls/engine/messages.h diff --git a/dlls/engine/amxxapi.cpp b/dlls/engine/amxxapi.cpp new file mode 100755 index 00000000..bb123fda --- /dev/null +++ b/dlls/engine/amxxapi.cpp @@ -0,0 +1,136 @@ +#include "engine.h" + +int AmxStringToEngine(AMX *amx, cell param, int &len) +{ + char *szString = MF_GetAmxString(amx, param, 0, &len); + char *szCopy = new char[len+1]; + + memset(szCopy, 0, len+1); + strcpy(szCopy, szString); + + return MAKE_STRING(szCopy); +} + +void OnAmxxAttach() +{ + pfnTouchForward = 0; + pfnThinkForward = 0; + PlayerPreThinkForward = 0; + PlayerPostThinkForward = 0; + ClientKillForward = 0; + CmdStartForward = 0; + StartFrameForward = 0; + MF_AddNatives(msg_Natives); + MF_AddNatives(ent_Natives); + MF_AddNatives(engine_Natives); + MF_AddNatives(global_Natives); + memset(glinfo.szLastLights, 0x0, 128); + memset(glinfo.szRealLights, 0x0, 128); + glinfo.bLights = false; + glinfo.fNextLights = 0; + glinfo.bCheckLights = false; +} + +void OnPluginsLoaded() +{ + pfnThinkForward = MF_RegisterForward("pfnThink", ET_STOP, FP_CELL, FP_DONE); + PlayerPreThinkForward = MF_RegisterForward("client_PreThink", ET_STOP, FP_CELL, FP_DONE); + PlayerPostThinkForward = MF_RegisterForward("client_PostThink", ET_STOP, FP_CELL, FP_DONE); + ClientKillForward = MF_RegisterForward("client_kill", ET_STOP, FP_CELL, FP_DONE); + CmdStartForward = MF_RegisterForward("client_impulse", ET_STOP, FP_CELL, FP_CELL, FP_DONE); + StartFrameForward = MF_RegisterForward("ServerFrame", ET_IGNORE, FP_DONE); + DispatchKeyForward = MF_RegisterForward("Dispatch_KeyVal", ET_STOP, FP_CELL, FP_DONE); + PlaybackForward = MF_RegisterForward("PlaybackEvent", ET_STOP, FP_CELL, FP_CELL, FP_CELL, FP_FLOAT, FP_ARRAY, FP_ARRAY, FP_FLOAT, FP_FLOAT, FP_CELL, FP_CELL, FP_CELL, FP_CELL, FP_DONE); + ChangelevelForward = MF_RegisterForward("server_changelevel", ET_STOP, FP_STRING, FP_DONE); + SpawnForward = MF_RegisterForward("pfnSpawn", ET_IGNORE, FP_CELL, FP_DONE); + DispatchUseForward = MF_RegisterForward("pfnUse", ET_STOP, FP_CELL, FP_CELL, FP_DONE); + pfnTouchForward = MF_RegisterForward("pfnTouch", ET_STOP, FP_CELL, FP_CELL, FP_DONE); + MF_Log("pfnTouch Forward: %d", pfnTouchForward); +} + +qboolean Voice_SetClientListening(int iReceiver, int iSender, qboolean bListen) +{ + if((plinfo[iSender].iSpeakFlags & SPEAK_MUTED) != 0) { + (g_engfuncs.pfnVoice_SetClientListening)(iReceiver, iSender, false); + RETURN_META_VALUE(MRES_SUPERCEDE, false); + } + + if((plinfo[iSender].iSpeakFlags & SPEAK_ALL) != 0) { + (g_engfuncs.pfnVoice_SetClientListening)(iReceiver, iSender, true); + RETURN_META_VALUE(MRES_SUPERCEDE, true); + } + + if((plinfo[iReceiver].iSpeakFlags & SPEAK_LISTENALL) != 0) { + (g_engfuncs.pfnVoice_SetClientListening)(iReceiver, iSender, true); + RETURN_META_VALUE(MRES_SUPERCEDE, true); + } + + RETURN_META_VALUE(MRES_IGNORED, bListen); +} + +int AddToFullPack(struct entity_state_s *state, int e, edict_t *ent, edict_t *host, int hostflags, int player, unsigned char *pSet) +{ + if(ent == host) { + if(FStrEq(STRING(ent->v.classname), "player")) { + if(plinfo[ENTINDEX(ent)].iViewType != CAMERA_NONE) { + ent->v.rendermode = kRenderTransTexture; + ent->v.renderamt = 100; + RETURN_META_VALUE(MRES_IGNORED, 0); + } + } + } + + if(FStrEq(STRING(ent->v.classname), "player")) { + if(plinfo[ENTINDEX(ent)].iViewType != CAMERA_NONE) { + ent->v.rendermode = plinfo[ENTINDEX(ent)].iRenderMode; + ent->v.renderamt = plinfo[ENTINDEX(ent)].fRenderAmt; + } + } + + RETURN_META_VALUE(MRES_IGNORED, 0); +} + +void ClientDisconnect(edict_t *pEntity) +{ + int id = ENTINDEX(pEntity); + + plinfo[id].iSpeakFlags = SPEAK_NORMAL; + plinfo[id].iViewType = CAMERA_NONE; + plinfo[id].iRenderMode = 0; + plinfo[id].fRenderAmt = 0; + + RETURN_META(MRES_IGNORED); +} + +BOOL ClientConnect(edict_t *pEntity, const char *pszName, const char *pszAddress, char szRejectReason[128]) +{ + int id = ENTINDEX(pEntity); + + plinfo[id].iSpeakFlags = SPEAK_NORMAL; + plinfo[id].iViewType = CAMERA_NONE; + plinfo[id].pViewEnt = NULL; + plinfo[id].iRenderMode = 0; + plinfo[id].fRenderAmt = 0; + + RETURN_META_VALUE(MRES_IGNORED, 0); +} + +void ServerDeactivate() +{ + memset(glinfo.szLastLights, 0x0, 128); + memset(glinfo.szRealLights, 0x0, 128); + glinfo.bLights = false; + glinfo.fNextLights = 0; + + RETURN_META(MRES_IGNORED); + +} + +void LightStyle(int style, char *val) { + if (!style) { + memset(glinfo.szRealLights, 0x0, 128); + memcpy(glinfo.szRealLights, val, strlen(val)); + } + + RETURN_META(MRES_IGNORED); +} diff --git a/dlls/engine/amxxmodule.cpp b/dlls/engine/amxxmodule.cpp index ee60da14..b021ab49 100755 --- a/dlls/engine/amxxmodule.cpp +++ b/dlls/engine/amxxmodule.cpp @@ -34,6 +34,9 @@ #include #include +#include +#include +#include #include "amxxmodule.h" /************* METAMOD SUPPORT *************/ @@ -2469,6 +2472,12 @@ PFN_AMX_ALLOT g_fn_AmxAllot; PFN_AMX_FINDPUBLIC g_fn_AmxFindPublic; PFN_LOAD_AMXSCRIPT g_fn_LoadAmxScript; PFN_UNLOAD_AMXSCRIPT g_fn_UnloadAmxScript; +PFN_REAL_TO_CELL g_fn_RealToCell; +PFN_CELL_TO_REAL g_fn_CellToReal; +PFN_REGISTER_SPFORWARD g_fn_RegisterSPForward; +PFN_REGISTER_SPFORWARD_BYNAME g_fn_RegisterSPForwardByName; +PFN_UNREGISTER_SPFORWARD g_fn_UnregisterSPForward; + // *** Exports *** C_DLLEXPORT int AMXX_Query(int *interfaceVersion, amxx_module_info_s *moduleInfo) { @@ -2536,6 +2545,9 @@ C_DLLEXPORT int AMXX_Attach(PFN_REQ_FNPTR reqFnptrFunc) REQFUNC("AddNatives", g_fn_AddNatives, PFN_ADD_NATIVES); REQFUNC("RaiseAmxError", g_fn_RaiseAmxError, PFN_RAISE_AMXERROR); REQFUNC("RegisterForward", g_fn_RegisterForward, PFN_REGISTER_FORWARD); + REQFUNC("RegisterSPForward", g_fn_RegisterSPForward, PFN_REGISTER_SPFORWARD); + REQFUNC("RegisterSPForwardByName", g_fn_RegisterSPForwardByName, PFN_REGISTER_SPFORWARD_BYNAME); + REQFUNC("UnregisterSPForward", g_fn_UnregisterSPForward, PFN_UNREGISTER_SPFORWARD); REQFUNC("ExecuteForward", g_fn_ExecuteForward, PFN_EXECUTE_FORWARD); REQFUNC("PrepareCellArray", g_fn_PrepareCellArray, PFN_PREPARE_CELLARRAY); REQFUNC("PrepareCharArray", g_fn_PrepareCharArray, PFN_PREPARE_CHARARRAY); @@ -2566,6 +2578,9 @@ C_DLLEXPORT int AMXX_Attach(PFN_REQ_FNPTR reqFnptrFunc) REQFUNC_OPT("Reallocator", g_fn_Reallocator, PFN_REALLOCATOR); REQFUNC_OPT("Deallocator", g_fn_Deallocator, PFN_DEALLOCATOR); + REQFUNC("CellToReal", g_fn_CellToReal, PFN_CELL_TO_REAL); + REQFUNC("RealToCell", g_fn_RealToCell, PFN_REAL_TO_CELL); + #ifdef FN_AMXX_ATTACH FN_AMXX_ATTACH(); #endif // FN_AMXX_ATACH @@ -2593,8 +2608,6 @@ C_DLLEXPORT int AMXX_PluginsLoaded() // Advanced MF functions void MF_Log(const char *fmt, ...) { - ASSERT(g_fn_Log); - // :TODO: Overflow possible here char msg[3072]; va_list arglst; @@ -2609,7 +2622,7 @@ void MF_Log(const char *fmt, ...) #ifdef _DEBUG // validate macros // Makes sure compiler reports errors when macros are invalid -void ValidateMacros() +void ValidateMacros_DontCallThis_Smiley() { MF_BuildPathname("str", "str", 0); MF_FormatAmxString(NULL, 0, 0, NULL); @@ -2655,6 +2668,9 @@ void ValidateMacros() MF_AmxAllot(0, 0, 0, 0); MF_LoadAmxScript(0, 0, 0, 0); MF_UnloadAmxScript(0, 0); + MF_RegisterSPForward(0, 0, 0, 0, 0, 0); + MF_RegisterSPForwardByName(0, 0, 0, 0, 0, 0); + MF_UnregisterSPForward(0); } #endif diff --git a/dlls/engine/amxxmodule.h b/dlls/engine/amxxmodule.h index a3ef12f2..b548edf1 100755 --- a/dlls/engine/amxxmodule.h +++ b/dlls/engine/amxxmodule.h @@ -106,21 +106,17 @@ struct amxx_module_info_s -#if defined BIT16 - #define SMALL_CELL_SIZE 16 /* for backward compatibility */ -#endif #if !defined SMALL_CELL_SIZE #define SMALL_CELL_SIZE 32 /* by default, use 32-bit cells */ #endif -#if SMALL_CELL_SIZE==16 - typedef uint16_t ucell; - typedef int16_t cell; -#elif SMALL_CELL_SIZE==32 +#if SMALL_CELL_SIZE==32 typedef uint32_t ucell; typedef int32_t cell; + typedef float REAL; #elif SMALL_CELL_SIZE==64 typedef uint64_t ucell; typedef int64_t cell; + typedef double REAL; #else #error Unsupported cell size (SMALL_CELL_SIZE) #endif @@ -244,32 +240,6 @@ enum { AMX_ERR_DOMAIN, /* domain error, expression result does not fit in range */ }; -/* for native functions that use floating point parameters, the following - * two macros are convenient for casting a "cell" into a "float" type _without_ - * changing the bit pattern - */ -#if SMALL_CELL_SIZE==32 - inline cell amx_ftoc(float f) - { - return *(cell*)&f; - } - inline float amx_ctof(cell c) - { - return *(float*)&c; - } -#elif SMALL_CELL_SIZE==64 - inline cell amx_ftoc(double f) - { - return *(cell*)&f; - } - inline double amx_ctof(cell c) - { - return *(double*)&c; - } -#else - #error Unsupported cell size -#endif - // ***** declare functions ***** @@ -1979,6 +1949,11 @@ typedef int (*PFN_AMX_ALLOT) (AMX* /*amx*/, int /*length*/, cell* /*amx_ad typedef int (*PFN_AMX_FINDPUBLIC) (AMX* /*amx*/, char* /*func name*/, int* /*index*/); typedef int (*PFN_LOAD_AMXSCRIPT) (AMX* /*amx*/, void** /*code*/, const char* /*path*/, char[64] /*error info*/); typedef int (*PFN_UNLOAD_AMXSCRIPT) (AMX* /*amx*/,void** /*code*/); +typedef cell (*PFN_REAL_TO_CELL) (REAL /*x*/); +typedef REAL (*PFN_CELL_TO_REAL) (cell /*x*/); +typedef int (*PFN_REGISTER_SPFORWARD) (AMX * /*amx*/, int /*func*/, ... /*params*/); +typedef int (*PFN_REGISTER_SPFORWARD_BYNAME) (AMX * /*amx*/, const char * /*funcName*/, ... /*params*/); +typedef void (*PFN_UNREGISTER_SPFORWARD) (int /*id*/); extern PFN_ADD_NATIVES g_fn_AddNatives; extern PFN_BUILD_PATHNAME g_fn_BuildPathname; @@ -2019,6 +1994,17 @@ extern PFN_IS_PLAYER_CONNECTING g_fn_IsPlayerConnecting; extern PFN_IS_PLAYER_HLTV g_fn_IsPlayerHLTV; extern PFN_GET_PLAYER_ARMOR g_fn_GetPlayerArmor; extern PFN_GET_PLAYER_HEALTH g_fn_GetPlayerHealth; +extern PFN_AMX_EXEC g_fn_AmxExec; +extern PFN_AMX_EXECV g_fn_AmxExecv; +extern PFN_AMX_ALLOT g_fn_AmxAllot; +extern PFN_AMX_FINDPUBLIC g_fn_AmxFindPublic; +extern PFN_LOAD_AMXSCRIPT g_fn_LoadAmxScript; +extern PFN_UNLOAD_AMXSCRIPT g_fn_UnloadAmxScript; +extern PFN_REAL_TO_CELL g_fn_RealToCell; +extern PFN_CELL_TO_REAL g_fn_CellToReal; +extern PFN_REGISTER_SPFORWARD g_fn_RegisterSPForward; +extern PFN_REGISTER_SPFORWARD_BYNAME g_fn_RegisterSPForwardByName; +extern PFN_UNREGISTER_SPFORWARD g_fn_UnregisterSPForward; #ifdef MAY_NEVER_BE_DEFINED // Function prototypes for intellisense and similar systems @@ -2062,6 +2048,11 @@ int MF_IsPlayerConnecting (int id) { } int MF_IsPlayerHLTV (int id) { } int MF_GetPlayerArmor (int id) { } int MF_GetPlayerHealth (int id) { } +REAL amx_ctof (cell x) { } +cell amx_ftoc (float x) { } +int MF_RegisterSPForwardByName (AMX * amx, const char *str, ...) { } +int MF_RegisterSPForward (AMX * amx, int func, ...) { } +void MF_UnregisterSPForward (int id) { } #endif // MAY_NEVER_BE_DEFINED #define MF_AddNatives g_fn_AddNatives @@ -2109,6 +2100,11 @@ void MF_Log(const char *fmt, ...); #define MF_AmxAllot g_fn_AmxAllot #define MF_LoadAmxScript g_fn_LoadAmxScript #define MF_UnloadAmxScript g_fn_UnloadAmxScript +#define amx_ctof g_fn_CellToReal +#define amx_ftoc g_fn_RealToCell +#define MF_RegisterSPForwardByName g_fn_RegisterSPForwardByName +#define MF_RegisterSPForward g_fn_RegisterSPForward +#define MF_UnregisterSPForward g_fn_UnregisterSPForward /*** Memory ***/ void *operator new(size_t reportedSize); diff --git a/dlls/engine/engine.cpp b/dlls/engine/engine.cpp new file mode 100755 index 00000000..d8603448 --- /dev/null +++ b/dlls/engine/engine.cpp @@ -0,0 +1,816 @@ +#include "engine.h" + +bool inKeyValue=false; +KeyValueData *g_pkvd; +struct usercmd_s *g_cmd; +struct PlayerInfo plinfo[33]; +struct GlobalInfo glinfo; + +void UTIL_SetSize(edict_t *pev, const Vector &vecMin, const Vector &vecMax) +{ + SET_SIZE(ENT(pev), vecMin, vecMax); +} + +edict_t *UTIL_FindEntityInSphere(edict_t *pStart, const Vector &vecCenter, float flRadius) { + if (!pStart) pStart = NULL; + + pStart = FIND_ENTITY_IN_SPHERE(pStart, vecCenter, flRadius); + + if (!FNullEnt(pStart)) return pStart; + return NULL; +} + +static cell AMX_NATIVE_CALL halflife_time(AMX *amx, cell *params) +{ + REAL fVal = gpGlobals->time; + + return amx_ftoc(fVal); +} + +static cell AMX_NATIVE_CALL VelocityByAim(AMX *amx, cell *params) +{ + int iEnt = params[1]; + int iVelocity = params[2]; + cell *vRet = MF_GetAmxAddr(amx, params[3]); + Vector vVector = Vector(0, 0, 0); + + if (!is_ent_valid(iEnt)) { + MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + return 0; + } + + edict_t *pEnt = INDEXENT(iEnt); + + MAKE_VECTORS(pEnt->v.v_angle); + vVector = gpGlobals->v_forward * iVelocity; + + vRet[0] = amx_ftoc(vVector.x); + vRet[1] = amx_ftoc(vVector.y); + vRet[2] = amx_ftoc(vVector.z); + + return 1; +} + +// RadiusDamage. Damages players within a certain radius. ToDo: add the +// damage messaging so players know where the damage is coming from +// (the red arrow-like things on the screen). +//(vexd) +static cell AMX_NATIVE_CALL RadiusDamage(AMX *amx, cell *params) { + cell *cAddr = MF_GetAmxAddr(amx,params[1]); + + REAL fCurrentX = amx_ctof(cAddr[0]); + REAL fCurrentY = amx_ctof(cAddr[1]); + REAL fCurrentZ = amx_ctof(cAddr[2]); + int iDamageMultiplier = params[2]; + int iRadiusMultiplier = params[3]; + + Vector vOrigin = Vector(fCurrentX, fCurrentY, fCurrentZ); + + edict_t *pSearchEnt = NULL; + while((pSearchEnt = UTIL_FindEntityInSphere(pSearchEnt, vOrigin, 5 * iRadiusMultiplier)) != NULL) { + if(FStrEq(STRING(pSearchEnt->v.classname), "player")) { + if(pSearchEnt->v.takedamage != DAMAGE_NO) { + pSearchEnt->v.health -= 10 + RANDOM_FLOAT(0,1 * iDamageMultiplier); + if(pSearchEnt->v.health < 1) { + pSearchEnt->v.health = 1; + MDLL_ClientKill(pSearchEnt); + } + } + } + } + + pSearchEnt = NULL; + + while((pSearchEnt = UTIL_FindEntityInSphere(pSearchEnt, vOrigin, 4 * iRadiusMultiplier)) != NULL) { + if(FStrEq(STRING(pSearchEnt->v.classname), "player")) { + if(pSearchEnt->v.takedamage != DAMAGE_NO) { + pSearchEnt->v.health -= 25 + RANDOM_FLOAT(0,2 * iDamageMultiplier); + if(pSearchEnt->v.health < 1) { + pSearchEnt->v.health = 1; + MDLL_ClientKill(pSearchEnt); + } + } + } + } + + pSearchEnt = NULL; + + while((pSearchEnt = UTIL_FindEntityInSphere(pSearchEnt, vOrigin, 3 * iRadiusMultiplier)) != NULL) { + if(FStrEq(STRING(pSearchEnt->v.classname), "player")) { + if(pSearchEnt->v.takedamage != DAMAGE_NO) { + pSearchEnt->v.health -= 50 + RANDOM_FLOAT(0,3 * iDamageMultiplier); + if(pSearchEnt->v.health < 1) { + pSearchEnt->v.health = 1; + MDLL_ClientKill(pSearchEnt); + } + } + } + } + + pSearchEnt = NULL; + + while((pSearchEnt = UTIL_FindEntityInSphere(pSearchEnt, vOrigin, 2 * iRadiusMultiplier)) != NULL) { + if(FStrEq(STRING(pSearchEnt->v.classname), "player")) { + if(pSearchEnt->v.takedamage != DAMAGE_NO) MDLL_ClientKill(pSearchEnt); + } + } + + return 1; +} + +static cell AMX_NATIVE_CALL PointContents(AMX *amx, cell *params) +{ + cell *cAddr = MF_GetAmxAddr(amx, params[1]); + + REAL fX = amx_ctof(cAddr[0]); + REAL fY = amx_ctof(cAddr[1]); + REAL fZ = amx_ctof(cAddr[2]); + + Vector vPoint = Vector(fX, fY, fZ); + + return POINT_CONTENTS(vPoint); +} + +static cell AMX_NATIVE_CALL vector_to_angle(AMX *amx, cell *params) +{ + cell *cAddr = MF_GetAmxAddr(amx, params[1]); + + REAL fX = amx_ctof(cAddr[0]); + REAL fY = amx_ctof(cAddr[1]); + REAL fZ = amx_ctof(cAddr[2]); + + Vector vVector = Vector(fX, fY, fZ); + Vector vAngle = Vector(0, 0, 0); + VEC_TO_ANGLES(vVector, vAngle); + + cell *vRet = MF_GetAmxAddr(amx, params[2]); + vRet[0] = amx_ftoc(vAngle.x); + vRet[1] = amx_ftoc(vAngle.y); + vRet[2] = amx_ftoc(vAngle.z); + + return 1; +} + +static cell AMX_NATIVE_CALL vector_length(AMX *amx, cell *params) +{ + cell *cAddr = MF_GetAmxAddr(amx, params[1]); + + REAL fX = amx_ctof(cAddr[0]); + REAL fY = amx_ctof(cAddr[1]); + REAL fZ = amx_ctof(cAddr[2]); + + Vector vVector = Vector(fX, fY, fZ); + + REAL fLength = vVector.Length(); + + return amx_ftoc(fLength); +} + +static cell AMX_NATIVE_CALL vector_distance(AMX *amx, cell *params) +{ + cell *cAddr = MF_GetAmxAddr(amx, params[1]); + cell *cAddr2 = MF_GetAmxAddr(amx, params[2]); + + REAL fX = amx_ctof(cAddr[0]); + REAL fY = amx_ctof(cAddr[1]); + REAL fZ = amx_ctof(cAddr[2]); + REAL fX2 = amx_ctof(cAddr2[0]); + REAL fY2 = amx_ctof(cAddr2[1]); + REAL fZ2 = amx_ctof(cAddr2[2]); + + Vector vVector = Vector(fX, fY, fZ); + Vector vVector2 = Vector(fX2, fY2, fZ2); + + REAL fLength = (vVector - vVector2).Length(); + + return amx_ftoc(fLength); +} + +static cell AMX_NATIVE_CALL trace_normal(AMX *amx, cell *params) +{ + int iEnt = params[1]; + + cell *cStart = MF_GetAmxAddr(amx, params[2]); + cell *cEnd = MF_GetAmxAddr(amx, params[3]); + REAL fStartX = amx_ctof(cStart[0]); + REAL fStartY = amx_ctof(cStart[1]); + REAL fStartZ = amx_ctof(cStart[2]); + REAL fEndX = amx_ctof(cEnd[0]); + REAL fEndY = amx_ctof(cEnd[1]); + REAL fEndZ = amx_ctof(cEnd[2]); + + cell *vRet = MF_GetAmxAddr(amx, params[4]); + + Vector vStart = Vector(fStartX, fStartY, fStartZ); + Vector vEnd = Vector(fEndX, fEndY, fEndZ); + + TraceResult tr; + TRACE_LINE(vStart, vEnd, dont_ignore_monsters, INDEXENT(iEnt), &tr); + + vRet[0] = amx_ftoc(tr.vecPlaneNormal.x); + vRet[1] = amx_ftoc(tr.vecPlaneNormal.y); + vRet[2] = amx_ftoc(tr.vecPlaneNormal.z); + + if (tr.flFraction >= 1.0) + return 0; + + return 1; +} + +static cell AMX_NATIVE_CALL trace_line(AMX *amx, cell *params) +{ + int iEnt = params[1]; + + cell *cStart = MF_GetAmxAddr(amx, params[2]); + cell *cEnd = MF_GetAmxAddr(amx, params[3]); + REAL fStartX = amx_ctof(cStart[0]); + REAL fStartY = amx_ctof(cStart[1]); + REAL fStartZ = amx_ctof(cStart[2]); + REAL fEndX = amx_ctof(cEnd[0]); + REAL fEndY = amx_ctof(cEnd[1]); + REAL fEndZ = amx_ctof(cEnd[2]); + + cell *vRet = MF_GetAmxAddr(amx, params[4]); + + Vector vStart = Vector(fStartX, fStartY, fStartZ); + Vector vEnd = Vector(fEndX, fEndY, fEndZ); + + TraceResult tr; + + if (iEnt == -1) + TRACE_LINE(vStart, vEnd, ignore_monsters, NULL, &tr); + else + TRACE_LINE(vStart, vEnd, dont_ignore_monsters, INDEXENT(iEnt), &tr); + + edict_t *pHit = tr.pHit; + + vRet[0] = amx_ftoc(tr.vecEndPos.x); + vRet[1] = amx_ftoc(tr.vecEndPos.y); + vRet[2] = amx_ftoc(tr.vecEndPos.z); + + if (FNullEnt(pHit)) + return 0; + + return ENTINDEX(pHit); +} + +static cell AMX_NATIVE_CALL set_speak(AMX *amx, cell *params) { + int iIndex = params[1]; + int iNewSpeakFlags = params[2]; + + if (iIndex> 32 || !is_ent_valid(iIndex)) { + MF_RaiseAmxError(amx,AMX_ERR_NATIVE); + return 0; + } + + plinfo[iIndex].iSpeakFlags = iNewSpeakFlags; + + return 1; +} + +static cell AMX_NATIVE_CALL get_speak(AMX *amx, cell *params) { + int iIndex = params[1]; + + if (!is_ent_valid(iIndex) || iIndex > 32) { + MF_RaiseAmxError(amx,AMX_ERR_NATIVE); + return 0; + } + + return plinfo[iIndex].iSpeakFlags; +} + +static cell AMX_NATIVE_CALL get_decal_index(AMX *amx, cell *params) +{ + int len; + char *szDecal = MF_GetAmxString(amx, params[1], 0, &len); + return DECAL_INDEX(szDecal); +} + +static cell AMX_NATIVE_CALL precache_event(AMX *amx, cell *params) +{ + int len; + char *szEvent = MF_FormatAmxString(amx, params, 2, &len); + PRECACHE_EVENT(params[1], (char *)STRING(ALLOC_STRING(szEvent))); + + return 1; +} + +static cell AMX_NATIVE_CALL get_info_keybuffer(AMX *amx, cell *params) +{ + int iEnt = params[1]; + + if (!is_ent_valid(iEnt)) { + MF_RaiseAmxError(amx,AMX_ERR_NATIVE); + return 0; + } + + edict_t *e = INDEXENT(iEnt); + + char *info = GETINFOKEYBUFFER(e); + + return MF_SetAmxString(amx, params[2], info, params[3]); +} + +//from jghg, who says it doesn't work +static cell AMX_NATIVE_CALL drop_to_floor(AMX *amx, cell *params) +{ + int iEnt = params[1]; + + if (!is_ent_valid(iEnt)) { + MF_RaiseAmxError(amx,AMX_ERR_NATIVE); + return 0; + } + + edict_t *e = INDEXENT(iEnt); + + return DROP_TO_FLOOR(e); +} + +static cell AMX_NATIVE_CALL precache_generic(AMX *amx, cell *params) +{ + int len; + char* szPreCache = MF_GetAmxString(amx,params[1],0,&len); + PRECACHE_GENERIC((char*)STRING(ALLOC_STRING(szPreCache))); + return 1; +} + +// Attachview, this allows you to attach a player's view to an entity. +// use AttachView(player, player) to reset view. +//(vexd) +static cell AMX_NATIVE_CALL attach_view(AMX *amx, cell *params) +{ + int iIndex = params[1]; + int iTargetIndex = params[2]; + + if (iIndex > 32 || !is_ent_valid(iIndex)) { + MF_RaiseAmxError(amx,AMX_ERR_NATIVE); + return 0; + } + + if (!is_ent_valid(iTargetIndex)) { + MF_RaiseAmxError(amx,AMX_ERR_NATIVE); + return 0; + } + + SET_VIEW(INDEXENT(iIndex), INDEXENT(iTargetIndex)); + + return 1; +} + +// SetView, this sets the view of a player. This is done by +// Creating a camera entity, which follows the player. +//(vexd) +static cell AMX_NATIVE_CALL set_view(AMX *amx, cell *params) { + int iIndex = params[1]; + int iCameraType = params[2]; + + if (iIndex > 32 || !is_ent_valid(iIndex)) { + MF_RaiseAmxError(amx,AMX_ERR_NATIVE); + return 0; + } + + edict_t *pPlayer = INDEXENT(iIndex); + edict_t *pNewCamera; + + switch(iCameraType) + { + case CAMERA_NONE: + SET_VIEW(pPlayer, pPlayer); + if(plinfo[ENTINDEX(pPlayer)].pViewEnt) { + REMOVE_ENTITY(plinfo[ENTINDEX(pPlayer)].pViewEnt); + } + plinfo[ENTINDEX(pPlayer)].iViewType = CAMERA_NONE; + plinfo[ENTINDEX(pPlayer)].pViewEnt = NULL; + + pPlayer->v.rendermode = plinfo[ENTINDEX(pPlayer)].iRenderMode; + pPlayer->v.renderamt = plinfo[ENTINDEX(pPlayer)].fRenderAmt; + + plinfo[ENTINDEX(pPlayer)].iRenderMode = 0; + plinfo[ENTINDEX(pPlayer)].fRenderAmt = 0; + + return 1; + break; + case CAMERA_3RDPERSON: + if(plinfo[ENTINDEX(pPlayer)].iViewType != CAMERA_NONE) { + plinfo[ENTINDEX(pPlayer)].iViewType = CAMERA_3RDPERSON; + return 1; + } + + plinfo[ENTINDEX(pPlayer)].iRenderMode = pPlayer->v.rendermode; + plinfo[ENTINDEX(pPlayer)].fRenderAmt = pPlayer->v.renderamt; + + plinfo[ENTINDEX(pPlayer)].iViewType = CAMERA_3RDPERSON; + pNewCamera = CREATE_NAMED_ENTITY(MAKE_STRING("info_target")); + pNewCamera->v.classname = MAKE_STRING("VexdCam"); + + SET_MODEL(pNewCamera, "models/rpgrocket.mdl"); + SET_SIZE(pNewCamera, Vector(0, 0, 0), Vector(0, 0, 0)); + + pNewCamera->v.movetype = MOVETYPE_NOCLIP; + pNewCamera->v.solid = SOLID_NOT; + pNewCamera->v.takedamage = DAMAGE_NO; + pNewCamera->v.gravity = 0; + pNewCamera->v.owner = pPlayer; + pNewCamera->v.rendermode = kRenderTransColor; + pNewCamera->v.renderamt = 0; + pNewCamera->v.renderfx = kRenderFxNone; + + SET_VIEW(pPlayer, pNewCamera); + + plinfo[ENTINDEX(pPlayer)].pViewEnt = pNewCamera; + break; + case CAMERA_UPLEFT: + if(plinfo[ENTINDEX(pPlayer)].iViewType != CAMERA_NONE) { + plinfo[ENTINDEX(pPlayer)].iViewType = CAMERA_UPLEFT; + return 1; + } + + plinfo[ENTINDEX(pPlayer)].iRenderMode = pPlayer->v.rendermode; + plinfo[ENTINDEX(pPlayer)].fRenderAmt = pPlayer->v.renderamt; + + plinfo[ENTINDEX(pPlayer)].iViewType = CAMERA_3RDPERSON; + pNewCamera = CREATE_NAMED_ENTITY(MAKE_STRING("info_target")); + pNewCamera->v.classname = MAKE_STRING("VexdCam"); + + SET_MODEL(pNewCamera, "models/rpgrocket.mdl"); + SET_SIZE(pNewCamera, Vector(0, 0, 0), Vector(0, 0, 0)); + + pNewCamera->v.movetype = MOVETYPE_NOCLIP; + pNewCamera->v.solid = SOLID_NOT; + pNewCamera->v.takedamage = DAMAGE_NO; + pNewCamera->v.gravity = 0; + pNewCamera->v.owner = pPlayer; + pNewCamera->v.rendermode = kRenderTransColor; + pNewCamera->v.renderamt = 0; + pNewCamera->v.renderfx = kRenderFxNone; + + SET_VIEW(pPlayer, pNewCamera); + + plinfo[ENTINDEX(pPlayer)].pViewEnt = pNewCamera; + break; + case CAMERA_TOPDOWN: + if(plinfo[ENTINDEX(pPlayer)].iViewType != CAMERA_NONE) { + plinfo[ENTINDEX(pPlayer)].iViewType = CAMERA_TOPDOWN; + return 1; + } + + plinfo[ENTINDEX(pPlayer)].iRenderMode = pPlayer->v.rendermode; + plinfo[ENTINDEX(pPlayer)].fRenderAmt = pPlayer->v.renderamt; + + plinfo[ENTINDEX(pPlayer)].iViewType = CAMERA_TOPDOWN; + pNewCamera = CREATE_NAMED_ENTITY(MAKE_STRING("info_target")); + pNewCamera->v.classname = MAKE_STRING("VexdCam"); + + SET_MODEL(pNewCamera, "models/rpgrocket.mdl"); + SET_SIZE(pNewCamera, Vector(0, 0, 0), Vector(0, 0, 0)); + + pNewCamera->v.movetype = MOVETYPE_NOCLIP; + pNewCamera->v.solid = SOLID_NOT; + pNewCamera->v.takedamage = DAMAGE_NO; + pNewCamera->v.gravity = 0; + pNewCamera->v.owner = pPlayer; + pNewCamera->v.rendermode = kRenderTransColor; + pNewCamera->v.renderamt = 0; + pNewCamera->v.renderfx = kRenderFxNone; + + SET_VIEW(pPlayer, pNewCamera); + + plinfo[ENTINDEX(pPlayer)].pViewEnt = pNewCamera; + break; + default: + break; + } + + return 1; +} + +// SetLights, this sets the lights for the map. +//(vexd) +static cell AMX_NATIVE_CALL set_lights(AMX *amx, cell *params) { + int iLength; + char *szLights = MF_GetAmxString(amx, params[1], 0, &iLength); + + if (FStrEq(szLights, "#OFF")) { + glinfo.bLights = false; + memset(glinfo.szLastLights, 0x0, 128); + (g_engfuncs.pfnLightStyle)(0, (char *)glinfo.szRealLights); + return 1; + } + + glinfo.bLights = true; + glinfo.bCheckLights = true; + + //Reset LastLights + memset(glinfo.szLastLights, 0x0, 128); + //Store the previous lighting. + memcpy(glinfo.szLastLights, szLights, strlen(szLights)); + + (g_engfuncs.pfnLightStyle)(0, szLights); + + // These make it so that players/weaponmodels look like whatever the lighting is + // at. otherwise it would color players under the skybox to these values. + SERVER_COMMAND("sv_skycolor_r 0\n"); + SERVER_COMMAND("sv_skycolor_g 0\n"); + SERVER_COMMAND("sv_skycolor_b 0\n"); + + return 1; +} + +//(mahnsawce) +static cell AMX_NATIVE_CALL trace_hull(AMX *amx,cell *params) +{ + int iResult=0; + TraceResult tr; + Vector vPos; + cell *vCell; + + vCell = MF_GetAmxAddr(amx, params[1]); + + vPos.x = amx_ctof(vCell[0]); + vPos.y = amx_ctof(vCell[1]); + vPos.z = amx_ctof(vCell[2]); + + TRACE_HULL(vPos,vPos, params[4], params[2], params[3] > 0 ? INDEXENT(params[3]) : 0 , &tr); + + if (tr.fStartSolid) { + iResult += 1; + } + if (tr.fAllSolid) { + iResult += 2; + } + if (!tr.fInOpen) { + iResult += 4; + } + return iResult; +} + +//(mahnsawce) +static cell AMX_NATIVE_CALL playback_event(AMX *amx, cell *params) +{ + /* Params: + * native playback_event(flags,invoker,eventindex,Float:delay,Float:origin[3],Float:angles[3],Float:fparam1,Float:fparam2,iparam1,iparam2,bparam1,bparam2) + * 1 2 3 4 5 6 7 8 9 10 11 12 + */ + int flags; + edict_t *pInvoker; + unsigned short eventindex; + REAL delay; + vec3_t origin; + vec3_t angles; + REAL fparam1; + REAL fparam2; + int iparam1; + int iparam2; + int bparam1; + int bparam2; + flags = params[1]; + pInvoker=INDEXENT(params[2]); + eventindex=params[3]; + delay=amx_ctof(params[4]); + cell *cOrigin=MF_GetAmxAddr(amx, params[5]); + cell *cAngles=MF_GetAmxAddr(amx, params[6]); + origin.x=amx_ctof(cOrigin[0]); + origin.y=amx_ctof(cOrigin[1]); + origin.z=amx_ctof(cOrigin[2]); + angles.x=amx_ctof(cAngles[0]); + angles.y=amx_ctof(cAngles[1]); + angles.z=amx_ctof(cAngles[2]); + fparam1=amx_ctof(params[7]); + fparam2=amx_ctof(params[8]); + iparam1=params[9]; + iparam2=params[10]; + bparam1=params[11]; + bparam2=params[12]; + PLAYBACK_EVENT_FULL(flags, pInvoker,eventindex, delay, origin, angles, fparam1, fparam2, iparam1, iparam2, bparam1, bparam2); + return 1; +} + +//(mahnsawce) +static cell AMX_NATIVE_CALL ns2amx_anglevector(AMX *amx, cell *params) +{ + Vector v_angles,v_forward,v_right,v_up,v_return; + cell *vCell = MF_GetAmxAddr(amx, params[1]); + v_angles.x = amx_ctof(vCell[0]); + v_angles.y = amx_ctof(vCell[1]); + v_angles.z = amx_ctof(vCell[2]); + g_engfuncs.pfnAngleVectors(v_angles,v_forward,v_right,v_up); + if (params[2] == ANGLEVECTORS_FORWARD) + v_return = v_forward; + if (params[2] == ANGLEVECTORS_RIGHT) + v_return = v_right; + if (params[2] == ANGLEVECTORS_UP) + v_return = v_up; + vCell = MF_GetAmxAddr(amx,params[3]); + vCell[0] = amx_ftoc(v_return.x); + vCell[1] = amx_ftoc(v_return.y); + vCell[2] = amx_ftoc(v_return.z); + return 1; +} + +//(mahnsawce) +static cell AMX_NATIVE_CALL get_usercmd(AMX *amx, cell *params) +{ + if (!incmd) + return 0; + int type = params[1]; + if (type > usercmd_int_start && type < usercmd_int_end) + { + // Requesting an integer value... + switch(type) + { + case usercmd_lerp_msec: + return g_cmd->lerp_msec; + case usercmd_msec: + return g_cmd->msec; + case usercmd_lightlevel: + return g_cmd->lightlevel; + case usercmd_buttons: + return g_cmd->buttons; + case usercmd_weaponselect: + return g_cmd->weaponselect; + case usercmd_impact_index: + return g_cmd->impact_index; + default: + return 0; + } + } + else if (type > usercmd_float_start && type < usercmd_float_end) + { + // Requesting a single float value + // The second parameter needs to be the float variable. + + cell *cRet = MF_GetAmxAddr(amx, params[2]); + switch(type) + { + case usercmd_forwardmove: + *cRet = *(cell*)&g_cmd->forwardmove; + return 1; + case usercmd_sidemove: + *cRet = *(cell*)&g_cmd->sidemove; + return 1; + case usercmd_upmove: + *cRet = *(cell*)&g_cmd->upmove; + return 1; + default: + return 0; + } + } + else if (type > usercmd_vec_start && type < usercmd_vec_end) + { + // Requesting a Vector value. + cell *cRet = MF_GetAmxAddr(amx,params[2]); + switch (type) + { + case usercmd_viewangles: + cRet[0] = *(cell*)&g_cmd->viewangles.x; + cRet[1] = *(cell*)&g_cmd->viewangles.y; + cRet[2] = *(cell*)&g_cmd->viewangles.z; + return 1; + case usercmd_impact_position: + cRet[0] = *(cell*)&g_cmd->impact_position.x; + cRet[1] = *(cell*)&g_cmd->impact_position.y; + cRet[2] = *(cell*)&g_cmd->impact_position.z; + return 1; + default: + return 0; + } + } + return 1; +} + +static cell AMX_NATIVE_CALL set_usercmd(AMX *amx, cell *params) +{ + if (!incmd) + return 0; + int type = params[1]; + if (type > usercmd_int_start && type < usercmd_int_end) + { + // Setting an integer value... + cell *blah = MF_GetAmxAddr(amx,params[2]); + int iValue = blah[0]; + switch(type) + { + case usercmd_lerp_msec: + g_cmd->lerp_msec = iValue; + return 1; + case usercmd_msec: + g_cmd->msec = iValue; + return 1; + case usercmd_lightlevel: + g_cmd->lightlevel = iValue; + return 1; + case usercmd_buttons: + g_cmd->buttons = iValue; + return 1; + case usercmd_weaponselect: + g_cmd->weaponselect = iValue; + return 1; + case usercmd_impact_index: + g_cmd->impact_index = iValue; + return 1; + default: + return 0; + } + } + else if (type > usercmd_float_start && type < usercmd_float_end) + { + // Requesting a single float value + // The second parameter needs to be the float variable. + + cell *blah = MF_GetAmxAddr(amx,params[2]); + REAL fValue = amx_ctof(blah[0]); + switch(type) + { + case usercmd_forwardmove: + g_cmd->forwardmove = fValue; + return 1; + case usercmd_sidemove: + g_cmd->sidemove = fValue; + return 1; + case usercmd_upmove: + g_cmd->upmove = fValue; + return 1; + default: + return 0; + } + } + else if (type > usercmd_vec_start && type < usercmd_vec_end) + { + // Requesting a Vector value. + Vector vValue; + cell *blah = MF_GetAmxAddr(amx,params[2]); + vValue.x = amx_ctof(blah[0]); + vValue.y = amx_ctof(blah[1]); + vValue.z = amx_ctof(blah[2]); + switch (type) + { + case usercmd_viewangles: + g_cmd->viewangles = vValue; + return 1; + case usercmd_impact_position: + g_cmd->impact_position = vValue; + return 1; + default: + return 0; + } + } + return 1; +} + +//(mahnsawce) +static cell AMX_NATIVE_CALL take_damage(AMX *amx, cell *params) +{ + int indexa = params[1]; + int indexb = params[2]; + int indexc = params[3]; + if (!is_ent_valid(indexa) || !is_ent_valid(indexb) || !is_ent_valid(indexc)) { + MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + return 0; + } + REAL fnDamage = amx_ctof(params[4]); + int inType = params[5]; + edict_t* pEntitya = INDEXENT(indexa); + edict_t* pEntityb = INDEXENT(indexb); + edict_t* pEntityc = INDEXENT(indexc); + CBaseEntity *pCEntity = NULL; + pCEntity = CBaseEntity::Instance(INDEXENT(indexa)); + pCEntity->TakeDamage(VARS(pEntityb),VARS(pEntityc),fnDamage,inType); + return 1; +} + +AMX_NATIVE_INFO engine_Natives[] = { + {"halflife_time", halflife_time}, + + //These are mostly from original VexD + {"VelocityByAim", VelocityByAim}, + {"RadiusDamage", RadiusDamage}, + {"PointContents", PointContents}, + {"vector_to_angle", vector_to_angle}, + {"vector_length", vector_length}, + {"vector_distance", vector_distance}, + {"trace_normal", trace_normal}, + {"trace_line", trace_line}, + {"trace_hull", trace_hull}, + {"take_damage", take_damage}, + + {"set_speak", set_speak}, + {"get_speak", get_speak}, + + {"precache_event", precache_event}, + {"precache_generic", precache_generic}, + {"playback_event", playback_event}, + + {"set_view", set_view}, + {"attach_view", attach_view}, + + {"get_decal_index", get_decal_index}, + {"get_info_keybuffer", get_info_keybuffer}, + {"set_lights", set_lights}, + {"drop_to_floor", drop_to_floor}, + + {"get_usercmd", get_usercmd}, + {"set_usercmd", set_usercmd}, + + {NULL, NULL}, + /////////////////// +}; \ No newline at end of file diff --git a/dlls/engine/engine.dsp b/dlls/engine/engine.dsp index 26e049b4..ce1ff572 100755 --- a/dlls/engine/engine.dsp +++ b/dlls/engine/engine.dsp @@ -90,10 +90,34 @@ LINK32=link.exe # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File +SOURCE=.\amxxapi.cpp +# End Source File +# Begin Source File + SOURCE=.\amxxmodule.cpp # End Source File # Begin Source File +SOURCE=.\engine.cpp +# End Source File +# Begin Source File + +SOURCE=.\entity.cpp +# End Source File +# Begin Source File + +SOURCE=.\forwards.cpp +# End Source File +# Begin Source File + +SOURCE=.\globals.cpp +# End Source File +# Begin Source File + +SOURCE=.\messages.cpp +# End Source File +# Begin Source File + SOURCE=.\meta_api.cpp # End Source File # End Group @@ -110,6 +134,18 @@ SOURCE=.\engine.h # End Source File # Begin Source File +SOURCE=.\entity.h +# End Source File +# Begin Source File + +SOURCE=.\gpglobals.h +# End Source File +# Begin Source File + +SOURCE=.\messages.h +# End Source File +# Begin Source File + SOURCE=.\moduleconfig.h # End Source File # End Group diff --git a/dlls/engine/engine.h b/dlls/engine/engine.h index 188be68d..c577928c 100755 --- a/dlls/engine/engine.h +++ b/dlls/engine/engine.h @@ -1,88 +1,41 @@ -/* AMX Mod X -* Engine Module -* -* by the AMX Mod X Development Team -* thanks to Vexd -* -* This file is part of AMX Mod X. -* -* -* This program is free software; you can redistribute it and/or modify it -* under the terms of the GNU General Public License as published by the -* Free Software Foundation; either version 2 of the License, or (at -* your option) any later version. -* -* This program is distributed in the hope that it will be useful, but -* WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -* General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software Foundation, -* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -* -* In addition, as a special exception, the author gives permission to -* link the code of this program with the Half-Life Game Engine ("HL -* Engine") and Modified Game Libraries ("MODs") developed by Valve, -* L.L.C ("Valve"). You must obey the GNU General Public License in all -* respects for all of the code used other than the HL Engine and MODs -* from Valve. If you modify this file, you may extend this exception -* to your version of the file, but you are not obligated to do so. If -* you do not wish to do so, delete this exception statement from your -* version. -*/ +#ifndef _ENGINE_INCLUDE_H +#define _ENGINE_INCLUDE_H -#define VERSION "0.16" - -class AmxCallList { - public: -struct AmxCall { - AMX *amx; - int iFunctionIdx; - AmxCall* next; - AmxCall( AMX *a , int i, AmxCall* n ) : amx(a), iFunctionIdx(i), next(n) {} -} *head; - - AmxCallList() { head = 0; } - - ~AmxCallList() { clear(); } - - void clear() { - while ( head ) { - AmxCall* a = head->next; - delete head; - head = a; - } - } - - void put( AMX *a , int i ) - { - head = new AmxCall( a, i , head ); - } - -}; - -AmxCallList pfnTouch; -AmxCallList serverFrame; -AmxCallList preThink; -AmxCallList postThink; -AmxCallList clientKill; -AmxCallList Msgs; -AmxCallList clientImpulse; - -extern AMX_NATIVE_INFO Engine_Natives[]; - -void (*function)(void*); - -void (*endfunction)(void*); - -#ifdef __linux__ -int thread_fork(void *arg); +#include +#include +#include +#include +#include +#include +#ifndef CBASEPLAYER_H +#define CBASEPLAYER_H +#include +#include #endif +#include "amxxmodule.h" +#include +#include "messages.h" +#include "entity.h" +#include "gpglobals.h" + +extern int SpawnForward; +extern int ChangelevelForward; +extern int PlaybackForward; +extern int DispatchKeyForward; +extern int pfnTouchForward; +extern int pfnThinkForward; +extern int PlayerPreThinkForward; +extern int PlayerPostThinkForward; +extern int ClientKillForward; +extern int CmdStartForward; +extern int StartFrameForward; +extern int DispatchUseForward; #define AMS_OFFSET 0.01 #define GETINFOKEYBUFFER (*g_engfuncs.pfnGetInfoKeyBuffer) +#define INFO_KEY_BUFFER (*g_engfuncs.pfnGetInfoKeyBuffer) +#define INFO_KEY_VALUE (*g_engfuncs.pfnInfoKeyValue) #define SPEAK_NORMAL 0 #define SPEAK_MUTED 1 @@ -94,876 +47,61 @@ int thread_fork(void *arg); #define CAMERA_UPLEFT 2 #define CAMERA_TOPDOWN 3 -#define MAX_MESSAGES 255 +#define ANGLEVECTORS_FORWARD 1 +#define ANGLEVECTORS_RIGHT 2 +#define ANGLEVECTORS_UP 3 -#define BLOCK_NOT 0 -#define BLOCK_ONCE 1 -#define BLOCK_SET 2 +enum +{ + usercmd_float_start, + usercmd_forwardmove, // Float + usercmd_sidemove, // Float + usercmd_upmove, // Float + usercmd_float_end, + usercmd_int_start, + usercmd_lerp_msec, // short + usercmd_msec, // byte + usercmd_lightlevel, // byte + usercmd_buttons, // unsigned short + usercmd_impulse, // byte + usercmd_weaponselect, // byte -//jghg -enum globals { - // Edict - GL_trace_ent = 0, + usercmd_impact_index, // in + usercmd_int_end, + usercmd_vec_start, + usercmd_viewangles, // Vector + usercmd_impact_position, // vec + usercmd_vec_end - // Float - GL_coop, - GL_deathmatch, - GL_force_retouch, - GL_found_secrets, - GL_frametime, - GL_serverflags, - GL_teamplay, - GL_time, - GL_trace_allsolid, - GL_trace_fraction, - GL_trace_inopen, - GL_trace_inwater, - GL_trace_plane_dist, - GL_trace_startsolid, - - // Int - GL_cdAudioTrack, - GL_maxClients, - GL_maxEntities, - GL_msg_entity, - GL_trace_flags, - GL_trace_hitgroup, - - // String - GL_pStringBase, - GL_mapname, - GL_startspot, - - // Vector - GL_trace_endpos, - GL_trace_plane_normal, - GL_v_forward, - GL_v_right, - GL_v_up, - GL_vecLandmarkOffset, - - // Void (not supported) - GL_pSaveData -}; - -enum { - gamestate, - oldbuttons, - groupinfo, - iuser1, - iuser2, - iuser3, - iuser4, - weaponanim, - pushmsec, - bInDuck, - flTimeStepSound, - flSwimTime, - flDuckTime, - iStepLeft, - movetype, - solid, - skin, - body, - effects, - light_level, - sequence, - gaitsequence, - modelindex, - playerclass, - waterlevel, - watertype, - spawnflags, - flags, - colormap, - team, - fixangle, - weapons, - rendermode, - renderfx, - button, - impulse, - deadflag, -}; - -enum { - impacttime, - starttime, - idealpitch, - pitch_speed, - ideal_yaw, - yaw_speed, - ltime, - nextthink, - gravity, - friction, - frame, - animtime, - framerate, - health, - frags, - takedamage, - max_health, - teleport_time, - armortype, - armorvalue, - dmg_take, - dmg_save, - dmg, - dmgtime, - speed, - air_finished, - pain_finished, - radsuit_finished, - scale, - renderamt, - maxspeed, - fov, - flFallVelocity, - fuser1, - fuser2, - fuser3, - fuser4, -}; - -enum { - origin, - oldorigin, - velocity, - basevelocity, - clbasevelocity, - movedir, - angles, - avelocity, - punchangle, - v_angle, - endpos, - startpos, - absmin, - absmax, - mins, - maxs, - size, - rendercolor, - view_ofs, - vuser1, - vuser2, - vuser3, - vuser4, -}; - -enum { - chain, - dmg_inflictor, - enemy, - aiment, - owner, - groundentity, - pContainingEntity, - euser1, - euser2, - euser3, - euser4, -}; - -enum { - classname, - globalname, - model, - target, - targetname, - netname, - message, - noise, - noise1, - noise2, - noise3, - viewmodel, - weaponmodel, -}; - -enum { - controller1, - controller2, - controller3, - controller4, - blending1, - blending2, }; +//These two structs are relics from VexD struct PlayerInfo { - bool bModeled; - char szModel[32]; - float fModelSet; - int iSpeakFlags; - edict_t *pViewEnt; int iViewType; int iRenderMode; float fRenderAmt; }; -PlayerInfo PlInfo[33]; - struct GlobalInfo { bool bLights; float fNextLights; char *szLastLights[128]; char *szRealLights[128]; - - int iMessageBlock[MAX_MESSAGES]; - bool bBlocking; + bool bCheckLights; }; -enum { - arg_byte = 1, - arg_char, - arg_short, - arg_long, - arg_angle, - arg_coord, - arg_string, - arg_entity, -}; +int is_ent_valid(int iEnt); +int AmxStringToEngine(AMX *amx, cell param, int &len); +edict_t *UTIL_FindEntityInSphere(edict_t *pStart, const Vector &vecCenter, float flRadius); -//by BAILOPAN -class argStack { -public: - argStack(argStack *p=NULL) //initialize with link to previous - { - next = p; - init(); - } +extern bool inKeyValue; +extern KeyValueData *g_pkvd; +extern bool incmd; +extern struct usercmd_s *g_cmd; +extern struct PlayerInfo plinfo[33]; +extern struct GlobalInfo glinfo; +extern AMX_NATIVE_INFO engine_Natives[]; - void init() - { - writebyte = 0; - writechar = '\0'; - writeshort = 0; - writelong = (long)0; - writeangle = 0.0; - writecoord = 0.0; - writeentity = 0; - writestring = NULL; - } - - argStack* arg() - { - argStack *p; - p = new argStack(); //get the new pointer - next = p; //link this to the next pointer - return p; - } - - argStack* link() //return link - { - return next; - } - - ~argStack() - { - if (writestring != NULL) { - delete [] writestring; - } - } - - void put(int arg_type, int i) - { - argtype = arg_type; - switch (argtype) - { - case arg_byte: - writebyte = i; - break; - case arg_char: - writechar = i; - break; - case arg_entity: - writeentity = i; - break; - case arg_short: - writeshort = i; - break; - case arg_long: - writelong = i; - break; - } - } - - void put(int arg_type, float f) - { - argtype = arg_type; - switch (argtype) - { - case arg_angle: - writeangle = f; - break; - case arg_coord: - writecoord = f; - break; - } - } - - void put_string(int arg_type, const char *sz) - { - argtype = arg_type; - switch (argtype) - { - case arg_string: - delete [] writestring; - writestring = new char[strlen(sz)+1]; - strcpy(writestring, sz); - break; - } - } - - void write_arg() - { - switch (argtype) - { - case arg_byte: - WRITE_BYTE(writebyte); - break; - case arg_char: - WRITE_CHAR(writechar); - break; - case arg_short: - WRITE_SHORT(writeshort); - break; - case arg_long: - WRITE_LONG(writelong); - break; - case arg_angle: - WRITE_ANGLE(writeangle); - break; - case arg_coord: - WRITE_COORD(writecoord); - break; - case arg_string: - WRITE_STRING(writestring); - break; - case arg_entity: - WRITE_ENTITY(writeentity); - break; - } - } - - int getarg_int(int arg_type) - { - switch (argtype) - { - case arg_byte: - return writebyte; - break; - case arg_char: - return writechar; - break; - case arg_short: - return writeshort; - break; - case arg_long: - return writelong; - break; - case arg_entity: - return writeentity; - break; - } - - return 0; - } - - float getarg_float(int arg_type) - { - switch (argtype) - { - case arg_angle: - return writeangle; - break; - case arg_coord: - return writecoord; - break; - } - return 0.0; - } - - int getarg_strlen(int arg_type) - { - switch (argtype) - { - case arg_string: - return strlen(writestring); - break; - } - return 0; - } - - const char *getarg_string(int arg_type) - { - switch (argtype) - { - case arg_string: - return (const char*)writestring; - break; - } - - return '\0'; - } - - int get_argtype() - { - return argtype; - } - - bool is_arg(int arg_type) - { - switch (argtype) - { - case arg_byte: - { - switch (arg_type) - { - case arg_byte: - return true; - break; - case arg_char: - return true; - break; - case arg_short: - return true; - break; - case arg_long: - return true; - break; - case arg_entity: - return true; - break; - default: - return false; - break; - } - break; - } - case arg_char: - { - switch (arg_type) - { - case arg_byte: - return true; - break; - case arg_char: - return true; - break; - case arg_short: - return true; - break; - case arg_long: - return true; - break; - case arg_entity: - return true; - break; - default: - return false; - break; - } - break; - } - case arg_short: - { - switch (arg_type) - { - case arg_byte: - return true; - break; - case arg_char: - return true; - break; - case arg_short: - return true; - break; - case arg_long: - return true; - break; - case arg_entity: - return true; - break; - default: - return false; - break; - } - break; - } - case arg_long: - { - switch (arg_type) - { - case arg_byte: - return true; - break; - case arg_char: - return true; - break; - case arg_short: - return true; - break; - case arg_long: - return true; - break; - case arg_entity: - return true; - break; - default: - return false; - break; - } - break; - } - case arg_entity: - { - switch (arg_type) - { - case arg_byte: - return true; - break; - case arg_char: - return true; - break; - case arg_short: - return true; - break; - case arg_long: - return true; - break; - case arg_entity: - return true; - break; - default: - return false; - break; - } - break; - } - case arg_angle: - { - switch (arg_type) - { - case arg_angle: - return true; - break; - case arg_coord: - return true; - break; - default: - return false; - break; - } - break; - } - case arg_coord: - { - switch (arg_type) - { - case arg_angle: - return true; - break; - case arg_coord: - return true; - break; - default: - return false; - break; - } - break; - } - case arg_string: - { - switch (arg_type) - { - case arg_string: - return true; - break; - default: - return false; - break; - } - break; - } - default: - { - return false; - break; - } - } - } - - void destroy() - { - argStack *p; - while (next != NULL) { - p = next->link(); - delete next; - next = p; - } - if (p != NULL) { - delete p; - p = NULL; - } - } - -private: - int argtype; - int writebyte; - int writechar; - int writeshort; - int writelong; - float writeangle; - float writecoord; - char *writestring; - int writeentity; - argStack *next; -}; - -class MessageInfo -{ -public: - MessageInfo(int msgdest, int msg_id, const float *Origin, edict_t* ed) - { - msgID = msg_id; - msg_dest = msgdest; - pOrigin = Origin; - v = ed; - CHeadArg = new argStack(); - CTailArg = NULL; - argcount = 0; - } - - ~MessageInfo() - { - Destroy(); - } - - void SendMsg() - { - //we are going to build a message =D yay! gather 'round and watch. - argStack *p; - MESSAGE_BEGIN(msg_dest, msgID, pOrigin, v); - for (p=CHeadArg->link(); p!=NULL; p=p->link()) { - p->write_arg(); - } - MESSAGE_END(); - Destroy(); //clean up old arguments - } - - void AddArg(int i, int j) - { - argStack *p; - if (CTailArg == NULL) { - p = CHeadArg->arg(); - CTailArg = p; - } else { - p = CTailArg->arg(); - CTailArg = p; - } - CTailArg->put(i,j); - argcount++; - } - - void AddArg(int i, float f) - { - argStack *p; - if (CTailArg == NULL) { - p = CHeadArg->arg(); - CTailArg = p; - } else { - p = CTailArg->arg(); - CTailArg = p; - } - CTailArg->put(i,f); - argcount++; - } - - void AddArgString(int i, const char *sz) - { - argStack *p; - if (CTailArg == NULL) { - p = CHeadArg->arg(); - CTailArg = p; - } else { - p = CTailArg->arg(); - CTailArg = p; - } - CTailArg->put_string(i,sz); - argcount++; - } - - void Destroy() - { - CHeadArg->destroy(); - delete CHeadArg; - CHeadArg = NULL; - } - - bool Set(int n, int arg_type, int data) - { - argStack *p; - int i=0; - if (n>argcount) { - return false; - } else { - for (p=CHeadArg->link(); p!=NULL; p=p->link()) { - i++; - if (i==n) { - p->put(arg_type, data); - return true; - } - } - } - - return false; - } - - bool Set(int n, int arg_type, float data) - { - argStack *p; - int i=0; - if (n>argcount) { - return false; - } else { - for (p=CHeadArg->link(); p!=NULL; p=p->link()) { - i++; - if (i==n) { - p->put(arg_type, data); - return true; - } - } - } - - return false; - } - - bool Set(int n, int arg_type, char* data) - { - argStack *p; - int i=0; - if (n>argcount) { - return false; - } else { - for (p=CHeadArg->link(); p!=NULL; p=p->link()) { - i++; - if (i==n) { - p->put_string(arg_type, (const char*)data); - return true; - } - } - } - - return false; - } - - int RetArg_Int(int n) - { - argStack *p; - int i=0; - if (n>argcount) { - return -1; - } else { - for (p=CHeadArg->link(); p!=NULL; p=p->link()) { - i++; - if (i==n) { - return p->getarg_int(arg_short); - } - } - } - - return 0; - } - - float RetArg_Float(int n) - { - argStack *p; - int i=0; - if (n>argcount) { - return -1; - } else { - for (p=CHeadArg->link(); p!=NULL; p=p->link()) { - i++; - if (i==n) { - return p->getarg_float(arg_coord); - } - } - } - - return 0.0; - } - - int RetArg_Strlen(int n) - { - argStack *p; - int i=0; - if (n>argcount) { - return 0; - } else { - for (p=CHeadArg->link(); p!=NULL; p=p->link()) { - i++; - if (i==n) { - return p->getarg_strlen(arg_string); - } - } - } - - return 0; - } - - const char* RetArg_String(int n) - { - argStack *p; - int i=0; - if (n>argcount) { - return '\0'; - } else { - for (p=CHeadArg->link(); p!=NULL; p=p->link()) { - i++; - if (i==n) { - return p->getarg_string(arg_string); - } - } - } - - return '\0'; - } - - int ArgType(int n) - { - argStack *p; - int i=0; - if (n>argcount) { - return -1; - } else { - for (p=CHeadArg->link(); p!=NULL; p=p->link()) { - i++; - if (i==n) { - return p->get_argtype(); - } - } - } - - return 0; - } - - int args() - { - return argcount; - } - - int msg_dest; - int target; - -private: - int argcount; - int msgID; - const float *pOrigin; - edict_t *v; - argStack *CHeadArg; - argStack *CTailArg; -}; +#endif //_ENGINE_INCLUDE_H \ No newline at end of file diff --git a/dlls/engine/engine.vcproj b/dlls/engine/engine.vcproj index 91253259..6380e278 100755 --- a/dlls/engine/engine.vcproj +++ b/dlls/engine/engine.vcproj @@ -3,57 +3,43 @@ ProjectType="Visual C++" Version="7.10" Name="engine" - ProjectGUID="{7CAE7BDF-52CB-49D0-B82E-568259869811}" - SccProjectName="" - SccLocalPath=""> + ProjectGUID="{B3F4467B-6148-4EBF-B897-168D81CF8D9B}" + Keyword="Win32Proj"> + Detect64BitPortabilityProblems="FALSE" + DebugInformationFormat="4"/> + Name="VCMIDLTool"/> + Name="VCResourceCompilerTool"/> + Detect64BitPortabilityProblems="FALSE" + DebugInformationFormat="3"/> + Name="VCMIDLTool"/> + Name="VCResourceCompilerTool"/> + + + + + + + + + + + + + + + Filter="h;hpp;hxx;hm;inl;inc;xsd" + UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"> + RelativePath=".\engine.h"> + RelativePath=".\entity.h"> - - - - - - + RelativePath=".\gpglobals.h"> + RelativePath=".\messages.h"> - - + Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx" + UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"> + Name="amxx" + Filter=""> + + + + diff --git a/dlls/engine/entity.cpp b/dlls/engine/entity.cpp new file mode 100755 index 00000000..c5ceb572 --- /dev/null +++ b/dlls/engine/entity.cpp @@ -0,0 +1,1788 @@ +#include "entity.h" + +int is_ent_valid(int iEnt) +{ + if (iEnt < 1 || iEnt > gpGlobals->maxEntities) + return 0; + + if (iEnt >= 1 || iEnt <= 32) + if (!MF_IsPlayerIngame(iEnt)) + return 0; + + edict_t *pEnt = INDEXENT(iEnt); + + if (FNullEnt(pEnt)) + return 0; + + return 1; +} + +/*********** + Basic stuff + ***********/ + +static cell AMX_NATIVE_CALL entity_range(AMX *amx, cell *params) +{ + int idxa = params[1]; + int idxb = params[2]; + + if (!is_ent_valid(idxa) || !is_ent_valid(idxb)) { + MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + return 0; + } + + edict_t *pEntA = INDEXENT(idxa); + edict_t *pEntB = INDEXENT(idxb); + + REAL fRet = (pEntA->v.origin - pEntB->v.origin).Length(); + + return amx_ftoc(fRet); +} + +/********************* + Entity control stuff + ********************/ + +static cell AMX_NATIVE_CALL call_think(AMX *amx, cell *params) +{ + int iEnt = params[1]; + + if (is_ent_valid(iEnt)) { + MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + return 0; + } + + edict_t *pEnt = INDEXENT(iEnt); + + MDLL_Think(pEnt); + + return 1; +} + + +static cell AMX_NATIVE_CALL fake_touch(AMX *amx, cell *params) +{ + int iPtr = params[1]; + int iPtd = params[2]; + + if (!is_ent_valid(iPtr) || !is_ent_valid(iPtd)) { + MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + return 0; + } + + edict_t *pToucher = INDEXENT(iPtr); + edict_t *pTouched = INDEXENT(iPtd); + + MDLL_Touch(pToucher, pTouched); + + return 1; +} + +static cell AMX_NATIVE_CALL force_use(AMX *amx, cell *params) +{ + int iPtr = params[1]; + int iPtd = params[2]; + + if (!is_ent_valid(iPtr) || !is_ent_valid(iPtd)) { + MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + return 0; + } + + edict_t *pUser = INDEXENT(iPtr); + edict_t *pUsed = INDEXENT(iPtd); + + MDLL_Touch(pUsed, pUser); + + return 1; +} + +static cell AMX_NATIVE_CALL create_entity(AMX *amx, cell *params) +{ + int len; + int iszClass = AmxStringToEngine(amx, params[1], len); + + edict_t *pEnt = CREATE_NAMED_ENTITY(iszClass); + + if (FNullEnt(pEnt)) + return 0; + + return ENTINDEX(pEnt); +} + +static cell AMX_NATIVE_CALL remove_entity(AMX *amx, cell *params) +{ + int id = params[1]; + edict_t *pEnt = INDEXENT(id); + + if (FNullEnt(pEnt)) + return 0; + + REMOVE_ENTITY(pEnt); + + return 1; +} + +static cell AMX_NATIVE_CALL entity_count(AMX *amx, cell *params) +{ + return NUMBER_OF_ENTITIES(); +} + +static cell AMX_NATIVE_CALL is_valid_ent(AMX *amx, cell *params) +{ + return is_ent_valid(params[1]); +} + +//uses mahnsawce's version now +static cell AMX_NATIVE_CALL DispatchKeyValue(AMX *amx, cell *params) +{ + int count = *params/sizeof(cell); + if (count == 3) { + int iValue = params[1]; + if (!is_ent_valid(iValue)) { + MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + return 0; + } + edict_t *pEntity = INDEXENT(iValue); + KeyValueData kvd; + int iLength=0; + char *char1 = MF_GetAmxString(amx, params[2], 0, &iLength); + char *char2 = MF_GetAmxString(amx, params[3], 1, &iLength); + kvd.szClassName = (char*)STRING(pEntity->v.classname); + kvd.szKeyName = char1; + kvd.szValue = char2; + kvd.fHandled = 0; + MDLL_KeyValue(pEntity, &kvd); + } + else + { + int iLength; + char *char1 = MF_GetAmxString(amx, params[1], 0, &iLength); + char *char2 = MF_GetAmxString(amx, params[2], 1, &iLength); + char *charA = new char[strlen(char1)+1]; + char *charB = new char[strlen(char2)+1]; + strcpy(charA, char1); + strcpy(charB, char2); + g_pkvd->szKeyName = charA; + g_pkvd->szValue = charB; + } + return 1; +} + +static cell AMX_NATIVE_CALL get_keyvalue(AMX *amx, cell *params) +{ + int idx = params[1]; + if (!is_ent_valid(idx)) { + MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + return 0; + } + edict_t *pEntity = INDEXENT(idx); + char *test = INFO_KEY_BUFFER(pEntity); + int iLength=0; + char *char1 = MF_GetAmxString(amx, params[2], 1, &iLength); + return MF_SetAmxString(amx, params[3], INFO_KEY_VALUE(INFO_KEY_BUFFER(pEntity),char1), params[4]); +} + +static cell AMX_NATIVE_CALL DispatchSpawn(AMX *amx, cell *params) +{ + int iEnt = params[1]; + + if (!is_ent_valid(iEnt)) { + MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + return 0; + } + + edict_t *pEnt = INDEXENT(iEnt); + + MDLL_Spawn(pEnt); + + return 1; +} + +/*************************** + Entity modification stuff + ***************************/ + +static cell AMX_NATIVE_CALL entity_get_float(AMX *amx, cell *params) +{ + int iEnt = params[1]; + int idx = params[2]; + REAL fVal = 0; + + if (!is_ent_valid(iEnt)) { + MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + return 0; + } + + edict_t *pEnt = INDEXENT(iEnt); + + switch (idx) + { + case impacttime: + fVal = pEnt->v.impacttime; + break; + case starttime: + fVal = pEnt->v.starttime; + break; + case idealpitch: + fVal = pEnt->v.idealpitch; + break; + case pitch_speed: + fVal = pEnt->v.pitch_speed; + break; + case ideal_yaw: + fVal = pEnt->v.ideal_yaw; + break; + case yaw_speed: + fVal = pEnt->v.yaw_speed; + break; + case ltime: + fVal = pEnt->v.ltime; + break; + case nextthink: + fVal = pEnt->v.nextthink; + break; + case gravity: + fVal = pEnt->v.gravity; + break; + case friction: + fVal = pEnt->v.friction; + break; + case frame: + fVal = pEnt->v.frame; + break; + case animtime: + fVal = pEnt->v.animtime; + break; + case framerate: + fVal = pEnt->v.framerate; + break; + case health: + fVal = pEnt->v.health; + break; + case frags: + fVal = pEnt->v.frags; + break; + case takedamage: + fVal = pEnt->v.takedamage; + break; + case max_health: + fVal = pEnt->v.max_health; + break; + case teleport_time: + fVal = pEnt->v.teleport_time; + break; + case armortype: + fVal = pEnt->v.armortype; + break; + case armorvalue: + fVal = pEnt->v.armorvalue; + break; + case dmg_take: + fVal = pEnt->v.dmg_take; + break; + case dmg_save: + fVal = pEnt->v.dmg_save; + break; + case dmg: + fVal = pEnt->v.dmg; + break; + case dmgtime: + fVal = pEnt->v.dmgtime; + break; + case speed: + fVal = pEnt->v.speed; + break; + case air_finished: + fVal = pEnt->v.air_finished; + break; + case pain_finished: + fVal = pEnt->v.pain_finished; + break; + case radsuit_finished: + fVal = pEnt->v.radsuit_finished; + break; + case scale: + fVal = pEnt->v.scale; + break; + case renderamt: + fVal = pEnt->v.renderamt; + break; + case maxspeed: + fVal = pEnt->v.maxspeed; + break; + case fov: + fVal = pEnt->v.fov; + break; + case flFallVelocity: + fVal = pEnt->v.flFallVelocity; + break; + case fuser1: + fVal = pEnt->v.fuser1; + break; + case fuser2: + fVal = pEnt->v.fuser2; + break; + case fuser3: + fVal = pEnt->v.fuser3; + break; + case fuser4: + fVal = pEnt->v.fuser4; + break; + default: + return 0; + break; + } + + return amx_ftoc(fVal); +} + +static cell AMX_NATIVE_CALL entity_set_float(AMX *amx, cell *params) +{ + int iEnt = params[1]; + int idx = params[2]; + REAL fVal = amx_ctof(params[3]); + + if (!is_ent_valid(iEnt)) { + MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + return 0; + } + + edict_t *pEnt = INDEXENT(iEnt); + + switch (idx) + { + case impacttime: + pEnt->v.impacttime = fVal; + break; + case starttime: + pEnt->v.starttime = fVal; + break; + case idealpitch: + pEnt->v.idealpitch = fVal; + break; + case pitch_speed: + pEnt->v.pitch_speed = fVal; + break; + case ideal_yaw: + pEnt->v.ideal_yaw = fVal; + break; + case yaw_speed: + pEnt->v.yaw_speed = fVal; + break; + case ltime: + pEnt->v.ltime = fVal; + break; + case nextthink: + pEnt->v.nextthink = fVal; + break; + case gravity: + pEnt->v.gravity = fVal; + break; + case friction: + pEnt->v.friction = fVal; + break; + case frame: + pEnt->v.frame = fVal; + break; + case animtime: + pEnt->v.animtime = fVal; + break; + case framerate: + pEnt->v.framerate = fVal; + break; + case health: + pEnt->v.health = fVal; + break; + case frags: + pEnt->v.frags = fVal; + break; + case takedamage: + pEnt->v.takedamage = fVal; + break; + case max_health: + pEnt->v.max_health = fVal; + break; + case teleport_time: + pEnt->v.teleport_time = fVal; + break; + case armortype: + pEnt->v.armortype = fVal; + break; + case armorvalue: + pEnt->v.armorvalue = fVal; + break; + case dmg_take: + pEnt->v.dmg_take = fVal; + break; + case dmg_save: + pEnt->v.dmg_save = fVal; + break; + case dmg: + pEnt->v.dmg = fVal; + break; + case dmgtime: + pEnt->v.dmgtime = fVal; + break; + case speed: + pEnt->v.speed = fVal; + break; + case air_finished: + pEnt->v.air_finished = fVal; + break; + case pain_finished: + pEnt->v.pain_finished = fVal; + break; + case radsuit_finished: + pEnt->v.radsuit_finished = fVal; + break; + case scale: + pEnt->v.scale = fVal; + break; + case renderamt: + pEnt->v.renderamt = fVal; + break; + case maxspeed: + pEnt->v.maxspeed = fVal; + break; + case fov: + pEnt->v.fov = fVal; + break; + case flFallVelocity: + pEnt->v.flFallVelocity = fVal; + break; + case fuser1: + pEnt->v.fuser1 = fVal; + break; + case fuser2: + pEnt->v.fuser2 = fVal; + break; + case fuser3: + pEnt->v.fuser3 = fVal; + break; + case fuser4: + pEnt->v.fuser4 = fVal; + break; + default: + return 0; + break; + } + + return 1; +} + +static cell AMX_NATIVE_CALL entity_get_int(AMX *amx, cell *params) +{ + int iEnt = params[1]; + int idx = params[2]; + int iRetValue = 0; + + if (!is_ent_valid(iEnt)) { + MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + return 0; + } + + edict_t *pEnt = INDEXENT(iEnt); + + switch (idx) + { + case gamestate: + iRetValue = pEnt->v.gamestate; + break; + case oldbuttons: + iRetValue = pEnt->v.oldbuttons; + break; + case groupinfo: + iRetValue = pEnt->v.groupinfo; + break; + case iuser1: + iRetValue = pEnt->v.iuser1; + break; + case iuser2: + iRetValue = pEnt->v.iuser2; + break; + case iuser3: + iRetValue = pEnt->v.iuser3; + break; + case iuser4: + iRetValue = pEnt->v.iuser4; + break; + case weaponanim: + iRetValue = pEnt->v.weaponanim; + break; + case pushmsec: + iRetValue = pEnt->v.pushmsec; + break; + case bInDuck: + iRetValue = pEnt->v.bInDuck; + break; + case flTimeStepSound: + iRetValue = pEnt->v.flTimeStepSound; + break; + case flSwimTime: + iRetValue = pEnt->v.flSwimTime; + break; + case flDuckTime: + iRetValue = pEnt->v.flDuckTime; + break; + case iStepLeft: + iRetValue = pEnt->v.iStepLeft; + break; + case movetype: + iRetValue = pEnt->v.movetype; + break; + case solid: + iRetValue = pEnt->v.solid; + break; + case skin: + iRetValue = pEnt->v.skin; + break; + case body: + iRetValue = pEnt->v.body; + break; + case effects: + iRetValue = pEnt->v.effects; + break; + case light_level: + iRetValue = pEnt->v.light_level; + break; + case sequence: + iRetValue = pEnt->v.sequence; + break; + case gaitsequence: + iRetValue = pEnt->v.gaitsequence; + break; + case modelindex: + iRetValue = pEnt->v.modelindex; + break; + case playerclass: + iRetValue = pEnt->v.playerclass; + break; + case waterlevel: + iRetValue = pEnt->v.waterlevel; + break; + case watertype: + iRetValue = pEnt->v.watertype; + break; + case spawnflags: + iRetValue = pEnt->v.spawnflags; + break; + case flags: + iRetValue = pEnt->v.flags; + break; + case colormap: + iRetValue = pEnt->v.colormap; + break; + case team: + iRetValue = pEnt->v.team; + break; + case fixangle: + iRetValue = pEnt->v.fixangle; + break; + case weapons: + iRetValue = pEnt->v.weapons; + break; + case rendermode: + iRetValue = pEnt->v.rendermode; + break; + case renderfx: + iRetValue = pEnt->v.renderfx; + break; + case button: + iRetValue = pEnt->v.button; + break; + case impulse: + iRetValue = pEnt->v.impulse; + break; + case deadflag: + iRetValue = pEnt->v.deadflag; + break; + default: + MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + return 0; + break; + } + + return iRetValue; +} + +static cell AMX_NATIVE_CALL entity_set_int(AMX *amx, cell *params) +{ + int iEnt = params[1]; + int idx = params[2]; + int iNewValue = params[3]; + + if (!is_ent_valid(iEnt)) { + MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + return 0; + } + + edict_t *pEnt = INDEXENT(iEnt); + + switch (idx) + { + case gamestate: + pEnt->v.gamestate = iNewValue; + break; + case oldbuttons: + pEnt->v.oldbuttons = iNewValue; + break; + case groupinfo: + pEnt->v.groupinfo = iNewValue; + break; + case iuser1: + pEnt->v.iuser1 = iNewValue; + break; + case iuser2: + pEnt->v.iuser2 = iNewValue; + break; + case iuser3: + pEnt->v.iuser3 = iNewValue; + break; + case iuser4: + pEnt->v.iuser4 = iNewValue; + break; + case weaponanim: + pEnt->v.weaponanim = iNewValue; + break; + case pushmsec: + pEnt->v.pushmsec = iNewValue; + break; + case bInDuck: + pEnt->v.bInDuck = iNewValue; + break; + case flTimeStepSound: + pEnt->v.flTimeStepSound = iNewValue; + break; + case flSwimTime: + pEnt->v.flSwimTime = iNewValue; + break; + case flDuckTime: + pEnt->v.flDuckTime = iNewValue; + break; + case iStepLeft: + pEnt->v.iStepLeft = iNewValue; + break; + case movetype: + pEnt->v.movetype = iNewValue; + break; + case solid: + pEnt->v.solid = iNewValue; + break; + case skin: + pEnt->v.skin = iNewValue; + break; + case body: + pEnt->v.body = iNewValue; + break; + case effects: + pEnt->v.effects = iNewValue; + break; + case light_level: + pEnt->v.light_level = iNewValue; + break; + case sequence: + pEnt->v.sequence = iNewValue; + break; + case gaitsequence: + pEnt->v.gaitsequence = iNewValue; + break; + case modelindex: + pEnt->v.modelindex = iNewValue; + break; + case playerclass: + pEnt->v.playerclass = iNewValue; + break; + case waterlevel: + pEnt->v.waterlevel = iNewValue; + break; + case watertype: + pEnt->v.watertype = iNewValue; + break; + case spawnflags: + pEnt->v.spawnflags = iNewValue; + break; + case flags: + pEnt->v.flags = iNewValue; + break; + case colormap: + pEnt->v.colormap = iNewValue; + break; + case team: + pEnt->v.team = iNewValue; + break; + case fixangle: + pEnt->v.fixangle = iNewValue; + break; + case weapons: + pEnt->v.weapons = iNewValue; + break; + case rendermode: + pEnt->v.rendermode = iNewValue; + break; + case renderfx: + pEnt->v.renderfx = iNewValue; + break; + case button: + pEnt->v.button = iNewValue; + break; + case impulse: + pEnt->v.impulse = iNewValue; + break; + case deadflag: + pEnt->v.deadflag = iNewValue; + break; + default: + return 0; + break; + } + + return 1; +} + +static cell AMX_NATIVE_CALL entity_get_vector(AMX *amx, cell *params) +{ + int iEnt = params[1]; + int idx = params[2]; + cell *vRet = MF_GetAmxAddr(amx, params[3]); + Vector vRetValue = Vector(0, 0, 0); + + if (!is_ent_valid(iEnt)) { + MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + return 0; + } + + edict_t *pEnt = INDEXENT(iEnt); + + switch (idx) + { + case origin: + vRetValue = pEnt->v.origin; + break; + case oldorigin: + vRetValue = pEnt->v.oldorigin; + break; + case velocity: + vRetValue = pEnt->v.velocity; + break; + case basevelocity: + vRetValue = pEnt->v.basevelocity; + break; + case clbasevelocity: + vRetValue = pEnt->v.clbasevelocity; + break; + case movedir: + vRetValue = pEnt->v.movedir; + break; + case angles: + vRetValue = pEnt->v.angles; + break; + case avelocity: + vRetValue = pEnt->v.avelocity; + break; + case punchangle: + vRetValue = pEnt->v.punchangle; + break; + case v_angle: + vRetValue = pEnt->v.v_angle; + break; + case endpos: + vRetValue = pEnt->v.endpos; + break; + case startpos: + vRetValue = pEnt->v.startpos; + break; + case absmin: + vRetValue = pEnt->v.absmin; + break; + case absmax: + vRetValue = pEnt->v.absmax; + break; + case mins: + vRetValue = pEnt->v.mins; + break; + case maxs: + vRetValue = pEnt->v.maxs; + break; + case size: + vRetValue = pEnt->v.size; + break; + case rendercolor: + vRetValue = pEnt->v.rendercolor; + break; + case view_ofs: + vRetValue = pEnt->v.view_ofs; + break; + case vuser1: + vRetValue = pEnt->v.vuser1; + break; + case vuser2: + vRetValue = pEnt->v.vuser2; + break; + case vuser3: + vRetValue = pEnt->v.vuser3; + break; + case vuser4: + vRetValue = pEnt->v.vuser4; + break; + default: + return 0; + break; + } + + vRet[0] = amx_ftoc(vRetValue.x); + vRet[1] = amx_ftoc(vRetValue.y); + vRet[2] = amx_ftoc(vRetValue.z); + + return 1; +} + +static cell AMX_NATIVE_CALL entity_set_vector(AMX *amx, cell *params) +{ + int iEnt = params[1]; + int idx = params[2]; + cell *vAmx = MF_GetAmxAddr(amx, params[3]); + + if (!is_ent_valid(iEnt)) { + MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + return 0; + } + + REAL fX = amx_ctof(vAmx[0]); + REAL fY = amx_ctof(vAmx[1]); + REAL fZ = amx_ctof(vAmx[2]); + Vector vSet = Vector(fX, fY, fZ); + edict_t *pEnt = INDEXENT(iEnt); + + switch (idx) + { + case origin: + pEnt->v.origin = vSet; + break; + case oldorigin: + pEnt->v.oldorigin = vSet; + break; + case velocity: + pEnt->v.velocity = vSet; + break; + case basevelocity: + pEnt->v.basevelocity = vSet; + break; + case clbasevelocity: + pEnt->v.clbasevelocity = vSet; + break; + case movedir: + pEnt->v.movedir = vSet; + break; + case angles: + pEnt->v.angles = vSet; + break; + case avelocity: + pEnt->v.avelocity = vSet; + break; + case punchangle: + pEnt->v.punchangle = vSet; + break; + case v_angle: + pEnt->v.v_angle = vSet; + break; + case endpos: + pEnt->v.endpos = vSet; + break; + case startpos: + pEnt->v.startpos = vSet; + break; + case absmin: + pEnt->v.absmin = vSet; + break; + case absmax: + pEnt->v.absmax = vSet; + break; + case mins: + pEnt->v.mins = vSet; + break; + case maxs: + pEnt->v.maxs = vSet; + break; + case size: + pEnt->v.size = vSet; + break; + case rendercolor: + pEnt->v.rendercolor = vSet; + break; + case view_ofs: + pEnt->v.view_ofs = vSet; + break; + case vuser1: + pEnt->v.vuser1 = vSet; + break; + case vuser2: + pEnt->v.vuser2 = vSet; + break; + case vuser3: + pEnt->v.vuser3 = vSet; + break; + case vuser4: + pEnt->v.vuser4 = vSet; + break; + default: + return 0; + break; + } + + return 1; +} + +static cell AMX_NATIVE_CALL entity_get_string(AMX *amx, cell *params) +{ + int iEnt = params[1]; + int idx = params[2]; + int iszString = 0; + const char *szRet = NULL; + + if (!is_ent_valid(iEnt)) { + MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + return 0; + } + + edict_t *pEnt = INDEXENT(iEnt); + + switch (idx) + { + case classname: + iszString = pEnt->v.classname; + break; + case globalname: + iszString = pEnt->v.globalname; + break; + case model: + iszString = pEnt->v.model; + break; + case target: + iszString = pEnt->v.target; + break; + case targetname: + iszString = pEnt->v.targetname; + break; + case netname: + iszString = pEnt->v.netname; + break; + case message: + iszString = pEnt->v.message; + break; + case noise: + iszString = pEnt->v.noise; + break; + case noise1: + iszString = pEnt->v.noise1; + break; + case noise2: + iszString = pEnt->v.noise2; + break; + case noise3: + iszString = pEnt->v.noise3; + break; + case viewmodel: + iszString = pEnt->v.viewmodel; + break; + case weaponmodel: + iszString = pEnt->v.weaponmodel; + break; + default: + return 0; + break; + } + + szRet = STRING(iszString); + + return MF_SetAmxString(amx, params[3], szRet, params[4]); +} + +static cell AMX_NATIVE_CALL entity_set_string(AMX *amx, cell *params) +{ + int iEnt = params[1]; + int idx = params[2]; + int iLen; + int iszString = AmxStringToEngine(amx, params[3], iLen); + + if (!is_ent_valid(iEnt)) { + MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + return 0; + } + + edict_t *pEnt = INDEXENT(iEnt); + + switch (idx) + { + case classname: + pEnt->v.classname = iszString; + break; + case globalname: + pEnt->v.globalname = iszString; + break; + case model: + pEnt->v.model = iszString; + break; + case target: + pEnt->v.target = iszString; + break; + case targetname: + pEnt->v.targetname = iszString; + break; + case netname: + pEnt->v.netname = iszString; + break; + case message: + pEnt->v.message = iszString; + break; + case noise: + pEnt->v.noise = iszString; + break; + case noise1: + pEnt->v.noise1 = iszString; + break; + case noise2: + pEnt->v.noise2 = iszString; + break; + case noise3: + pEnt->v.noise3 = iszString; + break; + case viewmodel: + pEnt->v.viewmodel = iszString; + break; + case weaponmodel: + pEnt->v.weaponmodel = iszString; + break; + default: + return 0; + break; + } + + return 1; +} + +static cell AMX_NATIVE_CALL entity_get_edict(AMX *amx, cell *params) +{ + int iEnt = params[1]; + int idx = params[2]; + edict_t *pRet; + + if (!is_ent_valid(iEnt)) { + MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + return 0; + } + + edict_t *pEnt = INDEXENT(iEnt); + + switch (idx) + { + case chain: + pRet = pEnt->v.chain; + break; + case dmg_inflictor: + pRet = pEnt->v.dmg_inflictor; + break; + case enemy: + pRet = pEnt->v.enemy; + break; + case aiment: + pRet = pEnt->v.aiment; + break; + case owner: + pRet = pEnt->v.owner; + break; + case groundentity: + pRet = pEnt->v.groundentity; + break; + case pContainingEntity: + pRet = pEnt->v.pContainingEntity; + break; + case euser1: + pRet = pEnt->v.euser1; + break; + case euser2: + pRet = pEnt->v.euser2; + break; + case euser3: + pRet = pEnt->v.euser3; + break; + case euser4: + pRet = pEnt->v.euser4; + break; + default: + return 0; + break; + } + + if (FNullEnt(pRet)) + return 0; + + return ENTINDEX(pRet); +} + +static cell AMX_NATIVE_CALL entity_set_edict(AMX *amx, cell *params) +{ + int iEnt = params[1]; + int idx = params[2]; + int iSetEnt = params[3]; + + if (!is_ent_valid(iEnt) || !is_ent_valid(iSetEnt)) { + MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + return 0; + } + + edict_t *pEnt = INDEXENT(iEnt); + edict_t *pSetEnt = INDEXENT(iSetEnt); + + switch (idx) + { + case chain: + pEnt->v.chain = pSetEnt; + break; + case dmg_inflictor: + pEnt->v.dmg_inflictor = pSetEnt; + break; + case enemy: + pEnt->v.enemy = pSetEnt; + break; + case aiment: + pEnt->v.aiment = pSetEnt; + break; + case owner: + pEnt->v.owner = pSetEnt; + break; + case groundentity: + pEnt->v.groundentity = pSetEnt; + break; + case pContainingEntity: + pEnt->v.pContainingEntity = pSetEnt; + break; + case euser1: + pEnt->v.euser1 = pSetEnt; + break; + case euser2: + pEnt->v.euser2 = pSetEnt; + break; + case euser3: + pEnt->v.euser3 = pSetEnt; + break; + case euser4: + pEnt->v.euser4 = pSetEnt; + break; + default: + return 0; + break; + } + + return 1; +} + +static cell AMX_NATIVE_CALL entity_get_byte(AMX *amx, cell *params) +{ + int iEnt = params[1]; + int idx = params[2]; + int iRetValue = 0; + + if (!is_ent_valid(iEnt)) { + MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + return 0; + } + + edict_t *pEnt = INDEXENT(iEnt); + + switch (idx) + { + case controller1: + iRetValue = pEnt->v.controller[0]; + break; + case controller2: + iRetValue = pEnt->v.controller[1]; + break; + case controller3: + iRetValue = pEnt->v.controller[2]; + break; + case controller4: + iRetValue = pEnt->v.controller[3]; + break; + case blending1: + iRetValue = pEnt->v.blending[0]; + break; + case blending2: + iRetValue = pEnt->v.blending[1]; + break; + default: + return 0; + break; + } + + return iRetValue; +} + +static cell AMX_NATIVE_CALL entity_set_byte(AMX *amx, cell *params) +{ + int iEnt = params[1]; + int idx = params[2]; + int iNewValue = params[3]; + + if (!is_ent_valid(iEnt)) { + MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + return 0; + } + + if(iNewValue > 255) + iNewValue = 255; + if(iNewValue < 0) + iNewValue = 0; + + edict_t *pEnt = INDEXENT(iEnt); + + switch (idx) + { + case controller1: + pEnt->v.controller[1] = iNewValue; + break; + case controller2: + pEnt->v.controller[2] = iNewValue; + break; + case controller3: + pEnt->v.controller[3] = iNewValue; + break; + case controller4: + pEnt->v.controller[4] = iNewValue; + break; + case blending1: + pEnt->v.blending[1] = iNewValue; + break; + case blending2: + pEnt->v.blending[2] = iNewValue; + break; + default: + return 0; + break; + } + + return 1; +} + +static cell AMX_NATIVE_CALL entity_set_origin(AMX *amx, cell *params) +{ + int iEnt = params[1]; + + if (!is_ent_valid(iEnt)) { + MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + return 0; + } + + edict_t *pEnt = INDEXENT(iEnt); + cell *vVector = MF_GetAmxAddr(amx, params[2]); + REAL fX = amx_ctof(vVector[0]); + REAL fY = amx_ctof(vVector[1]); + REAL fZ = amx_ctof(vVector[2]); + Vector vOrigin = Vector(fX, fY, fZ); + + SET_SIZE(pEnt, pEnt->v.mins, pEnt->v.maxs); + SET_ORIGIN(pEnt, vOrigin); + + return 1; +} + +static cell AMX_NATIVE_CALL entity_set_model(AMX *amx, cell *params) +{ + int iEnt = params[1]; + + if (!is_ent_valid(iEnt)) { + MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + return 0; + } + + edict_t *pEnt = INDEXENT(iEnt); + int iLen; + char *szModel = MF_GetAmxString(amx, params[2], 0, &iLen); + char *szStatic = new char[iLen+1]; + + memset(szStatic, 0, iLen+1); + strcpy(szStatic, szModel); + + SET_MODEL(pEnt, szStatic); + + return 1; +} + +static cell AMX_NATIVE_CALL entity_set_size(AMX *amx, cell *params) +{ + int iEnt = params[1]; + + if (!is_ent_valid(iEnt)) { + MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + return 0; + } + + edict_t *pEnt = INDEXENT(iEnt); + + cell *cMin = MF_GetAmxAddr(amx, params[2]); + REAL x1 = amx_ftoc(cMin[0]); + REAL y1 = amx_ftoc(cMin[1]); + REAL z1 = amx_ftoc(cMin[2]); + Vector vMin = Vector(x1, y1, z1); + + cell *cMax = MF_GetAmxAddr(amx, params[3]); + REAL x2 = amx_ftoc(cMax[0]); + REAL y2 = amx_ftoc(cMax[1]); + REAL z2 = amx_ftoc(cMax[2]); + Vector vMax = Vector(x2, y2, z2); + + UTIL_SetSize(pEnt, vMin, vMax); + + return 1; +} + +/*********************** + Offset control natives + ***********************/ + +static cell AMX_NATIVE_CALL get_offset_short(AMX *amx, cell *params) +{ + int idx = params[1]; + int off = params[2]; + + if (!is_ent_valid(idx)) { + MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + return 0; + } + + edict_t *pEnt = INDEXENT(idx); +#ifndef __linux__ + off -= 5; +#endif + + return *((short *)pEnt->pvPrivateData + off); +} + +static cell AMX_NATIVE_CALL set_offset_short(AMX *amx, cell *params) +{ + int idx = params[1]; + int off = params[2]; + + if (!is_ent_valid(idx)) { + MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + return 0; + } + + edict_t *pEnt = INDEXENT(idx); +#ifndef __linux__ + off -= 5; +#endif + + *((short *)pEnt->pvPrivateData + off) = (short)params[3]; + + return 1; +} + +static cell AMX_NATIVE_CALL get_offset_char(AMX *amx, cell *params) +{ + int idx = params[1]; + int off = params[2]; + + if (!is_ent_valid(idx)) { + MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + return 0; + } + + edict_t *pEnt = INDEXENT(idx); +#ifndef __linux__ + off -= 5; +#endif + + char r = *((char *)pEnt->pvPrivateData + off); + return r; +} + +static cell AMX_NATIVE_CALL set_offset_char(AMX *amx, cell *params) +{ + int idx = params[1]; + int off = params[2]; + + if (!is_ent_valid(idx)) { + MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + return 0; + } + + edict_t *pEnt = INDEXENT(idx); +#ifndef __linux__ + off -= 5; +#endif + + char data = params[3]; + *((char *)pEnt->pvPrivateData + off) = data; + + return 1; +} + +static cell AMX_NATIVE_CALL get_offset_int(AMX *amx, cell *params) +{ + int idx = params[1]; + int off = params[2]; + + if (!is_ent_valid(idx)) { + MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + return 0; + } + + edict_t *pEnt = INDEXENT(idx); +#ifndef __linux__ + off -= 5; +#endif + + return *((int *)pEnt->pvPrivateData + off); +} + +static cell AMX_NATIVE_CALL set_offset_int(AMX *amx, cell *params) +{ + int idx = params[1]; + int off = params[2]; + + if (!is_ent_valid(idx)) { + MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + return 0; + } + + edict_t *pEnt = INDEXENT(idx); +#ifndef __linux__ + off -= 5; +#endif + + *((int *)pEnt->pvPrivateData + off) = params[3]; + + return 1; +} + +static cell AMX_NATIVE_CALL get_offset_float(AMX *amx, cell *params) +{ + int idx = params[1]; + int off = params[2]; + + if (!is_ent_valid(idx)) { + MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + return 0; + } + + edict_t *pEnt = INDEXENT(idx); +#ifndef __linux__ + off -= 5; +#endif + + REAL fRet = (REAL)(*((REAL*)pEnt->pvPrivateData + off)); + + return amx_ftoc(fRet); +} + +static cell AMX_NATIVE_CALL set_offset_float(AMX *amx, cell *params) +{ + int idx = params[1]; + int off = params[2]; + + if (!is_ent_valid(idx)) { + MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + return 0; + } + + edict_t *pEnt = INDEXENT(idx); +#ifndef __linux__ + off -= 5; +#endif + + REAL fVal = amx_ctof(params[3]); + *((float *)pEnt->pvPrivateData + off) = fVal; + + return 1; +} + +static cell AMX_NATIVE_CALL get_entity_pointer(AMX *amx, cell *params) // get_entity_pointer(index, pointer[], len); = 3 params +{ + return 0; +} + +/************************ + Entity finding functions + ************************/ + +static cell AMX_NATIVE_CALL find_ent_in_sphere(AMX *amx, cell *params) +{ + int idx = params[1]; + + if (!is_ent_valid(idx)) { + MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + return 0; + } + + edict_t *pEnt = INDEXENT(idx); + cell *cAddr = MF_GetAmxAddr(amx, params[2]); + REAL origin[3] = { + amx_ctof(cAddr[0]), + amx_ctof(cAddr[1]), + amx_ctof(cAddr[2]) + }; + REAL radius = amx_ctof(params[3]); + + int returnEnt = ENTINDEX(FIND_ENTITY_IN_SPHERE(pEnt, origin, radius)); + + if (FNullEnt(returnEnt)) + return 0; + + return returnEnt; +} + +static cell AMX_NATIVE_CALL find_ent_by_class(AMX *amx, cell *params) /* 3 param */ +{ + edict_t *pEnt = INDEXENT(params[1]); + + int len; + char* sValue = MF_GetAmxString(amx, params[2], 0, &len); + + pEnt = FIND_ENTITY_BY_STRING(pEnt, "classname", sValue); + + if (FNullEnt(pEnt)) + return 0; + + return ENTINDEX(pEnt); +} + +static cell AMX_NATIVE_CALL find_sphere_class(AMX *amx, cell *params) // find_sphere_class(aroundent, _lookforclassname[], Float:radius, entlist[], maxents, Float:origin[3] = {0.0, 0.0, 0.0}); // 6 params +{ + // params[1] = index to find around, if this is less than 1 then use around origin in last parameter. + // params[2] = classname to find + int len; + char* classToFind = MF_GetAmxString(amx, params[2], 0, &len); + // params[3] = radius, float... + REAL radius =amx_ctof(params[3]); + // params[4] = store ents in this list + cell *entList = MF_GetAmxAddr(amx, params[4]); + // params[5] = maximum ents to store in entlist[] in params[4] + // params[6] = origin, use this if params[1] is less than 1 + + vec3_t vecOrigin; + if (params[1] > 0) { + if (!is_ent_valid(params[1])) { + MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + return 0; + } + + edict_t* pEntity = INDEXENT(params[1]); + vecOrigin = pEntity->v.origin; + } else { + cell *cAddr = MF_GetAmxAddr(amx, params[6]); + vecOrigin = Vector(amx_ctof(cAddr[0]), amx_ctof(cAddr[1]), amx_ctof(cAddr[2])); + } + + int entsFound = 0; + edict_t* pSearchEnt = INDEXENT(0); + + while (entsFound < params[5]) { + pSearchEnt = FIND_ENTITY_IN_SPHERE(pSearchEnt, vecOrigin, radius); // takes const float origin + if (FNullEnt(pSearchEnt)) + break; + else { + if (strcmp(STRING(pSearchEnt->v.classname), classToFind) == 0) { + // Add to entlist (params[4]) + entList[entsFound++] = ENTINDEX(pSearchEnt); // raise entsFound + } + } + } + + return entsFound; +} + +static cell AMX_NATIVE_CALL find_ent_by_target(AMX *amx, cell *params) +{ + int iStart = params[1]; + int iLength; + char *szValue = MF_GetAmxString(amx, params[2], 0, &iLength); + + edict_t *pStart; + + if (iStart == -1) { + pStart = NULL; + } else { + if (!is_ent_valid(iStart)) + pStart = NULL; + else + pStart = INDEXENT(iStart); + } + + int iReturnEnt = ENTINDEX(FIND_ENTITY_BY_TARGET(pStart, szValue)); + + return iReturnEnt; +} + +static cell AMX_NATIVE_CALL find_ent_by_model(AMX *amx, cell *params) { + int iStart = params[1]; + int iLength, iLength2; + char *szClass = MF_GetAmxString(amx, params[2], 0, &iLength); + char *szModel = MF_GetAmxString(amx, params[3], 1, &iLength2); + + edict_t *pStart; + + if (iStart == -1) { + pStart = NULL; + } else { + if (!is_ent_valid(iStart)) + pStart = NULL; + else + pStart = INDEXENT(iStart); + } + + int checkEnt = ENTINDEX(FIND_ENTITY_BY_STRING(pStart, "classname", szClass)); + const char *CheckModel = ""; + + while (!FNullEnt(checkEnt)) { + CheckModel = STRING(pStart->v.model); + if (strcmp(CheckModel, szModel)==0) { + return checkEnt; + } else { + pStart = INDEXENT(checkEnt); + checkEnt = ENTINDEX(FIND_ENTITY_BY_STRING(pStart, "classname", szClass)); + } + } + + return checkEnt; +} + +static cell AMX_NATIVE_CALL find_ent_by_tname(AMX *amx, cell *params) { + int iStart = params[1]; + int iLength; + char *szValue = MF_GetAmxString(amx, params[2], 0, &iLength); + + edict_t *pStart; + + if (iStart == -1) { + pStart = NULL; + } else { + if (!is_ent_valid(iStart)) + pStart = NULL; + else + pStart = INDEXENT(iStart); + } + + int iReturnEnt = ENTINDEX(FIND_ENTITY_BY_TARGETNAME(pStart, szValue)); + + return iReturnEnt; +} + +static cell AMX_NATIVE_CALL find_ent_by_owner(AMX *amx, cell *params) // native find_ent_by_owner(start_from_ent, classname[], owner_index); = 3 params +{ + int iEnt = params[1]; + int oEnt = params[3]; + // Check index to start searching at, 0 must be possible. + if (!is_ent_valid(iEnt) || !is_ent_valid(oEnt)) { + MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + return 0; + } + + edict_t *pEnt = INDEXENT(iEnt); + edict_t *entOwner = INDEXENT(oEnt); + + //optional fourth parameter is for jghg2 compatibility + char* sCategory = NULL; + switch(params[4]){ + case 1: sCategory = "target"; break; + case 2: sCategory = "targetname"; break; + default: sCategory = "classname"; + } + + // No need to check if there is a real ent where entOwner points at since we don't access it anyway. + + int len; + char* classname = MF_GetAmxString(amx, params[2], 0, &len); + + while (true) { + pEnt = FIND_ENTITY_BY_STRING(pEnt, sCategory, classname); + if (FNullEnt(pEnt)) // break and return 0 if bad + break; + else if (pEnt->v.owner == entOwner) // compare pointers + return ENTINDEX(pEnt); + } + + // If it comes here, the while loop ended because an ent failed (FNullEnt() == true) + return 0; +} + +static cell AMX_NATIVE_CALL get_grenade_id(AMX *amx, cell *params) /* 4 param */ +{ + int index = params[1]; + char* szModel; + + if (!is_ent_valid(index)) { + MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + return 0; + } + + edict_t* pentFind = INDEXENT(params[4]); + edict_t* pentOwner = INDEXENT(index); + + pentFind = FIND_ENTITY_BY_CLASSNAME( pentFind, "grenade" ); + while (!FNullEnt(pentFind)) { + if (pentFind->v.owner == pentOwner) { + if (params[3]>0) { + szModel = new char[params[3]]; + szModel = (char*)STRING(pentFind->v.model); + MF_SetAmxString(amx, params[2], szModel, params[3]); + delete [] szModel; + return ENTINDEX(pentFind); + } + } + pentFind = FIND_ENTITY_BY_CLASSNAME( pentFind, "grenade" ); + } + return 0; +} + +AMX_NATIVE_INFO ent_Natives[] = { + {"create_entity", create_entity}, + {"remove_entity", remove_entity}, + {"entity_count", entity_count}, + {"is_valid_ent", is_valid_ent}, + + {"entity_range", entity_range}, + + {"entity_get_float", entity_get_float}, + {"entity_set_float", entity_set_float}, + {"entity_set_int", entity_set_int}, + {"entity_get_int", entity_get_int}, + {"entity_get_vector", entity_get_vector}, + {"entity_set_vector", entity_set_vector}, + {"entity_get_string", entity_get_string}, + {"entity_set_string", entity_set_string}, + {"entity_get_edict", entity_get_edict}, + {"entity_set_edict", entity_set_edict}, + {"entity_get_byte", entity_get_byte}, + {"entity_set_byte", entity_set_byte}, + {"entity_set_origin", entity_set_origin}, + {"entity_set_model", entity_set_model}, + {"entity_set_size", entity_set_size}, + {"DispatchKeyValue", DispatchKeyValue}, + {"DispatchSpawn", DispatchSpawn}, + + {"call_think", call_think}, + {"fake_touch", fake_touch}, + {"force_use", force_use}, + + {"get_offset_short", get_offset_short}, + {"set_offset_short", set_offset_short}, + {"get_offset_char", get_offset_char}, + {"set_offset_char", set_offset_char}, + {"get_offset", get_offset_int}, + {"set_offset", set_offset_int}, + {"get_offset_float", get_offset_float}, + {"set_offset_float", set_offset_float}, + {"get_entity_pointer", get_entity_pointer}, + + {"find_ent_in_sphere", find_ent_in_sphere}, + {"find_ent_by_class", find_ent_by_class}, + {"find_sphere_class", find_sphere_class}, + {"find_ent_by_model", find_ent_by_model}, + {"find_ent_by_target", find_ent_by_target}, + {"find_ent_by_tname", find_ent_by_tname}, + {"find_ent_by_owner", find_ent_by_owner}, + {"get_grenade_id", get_grenade_id}, + + {NULL, NULL}, + /////////////////// +}; \ No newline at end of file diff --git a/dlls/engine/entity.h b/dlls/engine/entity.h new file mode 100755 index 00000000..114045ec --- /dev/null +++ b/dlls/engine/entity.h @@ -0,0 +1,155 @@ +#ifndef _INCLUDE_ENGINE_ENTSTUFF +#define _INCLUDE_ENGINE_ENTSTUFF + +#include "engine.h" + +enum { + gamestate, + oldbuttons, + groupinfo, + iuser1, + iuser2, + iuser3, + iuser4, + weaponanim, + pushmsec, + bInDuck, + flTimeStepSound, + flSwimTime, + flDuckTime, + iStepLeft, + movetype, + solid, + skin, + body, + effects, + light_level, + sequence, + gaitsequence, + modelindex, + playerclass, + waterlevel, + watertype, + spawnflags, + flags, + colormap, + team, + fixangle, + weapons, + rendermode, + renderfx, + button, + impulse, + deadflag, +}; + +enum { + impacttime, + starttime, + idealpitch, + pitch_speed, + ideal_yaw, + yaw_speed, + ltime, + nextthink, + gravity, + friction, + frame, + animtime, + framerate, + health, + frags, + takedamage, + max_health, + teleport_time, + armortype, + armorvalue, + dmg_take, + dmg_save, + dmg, + dmgtime, + speed, + air_finished, + pain_finished, + radsuit_finished, + scale, + renderamt, + maxspeed, + fov, + flFallVelocity, + fuser1, + fuser2, + fuser3, + fuser4, +}; + +enum { + origin, + oldorigin, + velocity, + basevelocity, + clbasevelocity, + movedir, + angles, + avelocity, + punchangle, + v_angle, + endpos, + startpos, + absmin, + absmax, + mins, + maxs, + size, + rendercolor, + view_ofs, + vuser1, + vuser2, + vuser3, + vuser4, +}; + +enum { + chain, + dmg_inflictor, + enemy, + aiment, + owner, + groundentity, + pContainingEntity, + euser1, + euser2, + euser3, + euser4, +}; + +enum { + classname, + globalname, + model, + target, + targetname, + netname, + message, + noise, + noise1, + noise2, + noise3, + viewmodel, + weaponmodel, +}; + +enum { + controller1, + controller2, + controller3, + controller4, + blending1, + blending2, +}; + +void UTIL_SetSize(edict_t *pev, const Vector &vecMin, const Vector &vecMax); + +extern AMX_NATIVE_INFO ent_Natives[]; + +#endif //_INCLUDE_ENGINE_ENTSTUFF \ No newline at end of file diff --git a/dlls/engine/forwards.cpp b/dlls/engine/forwards.cpp new file mode 100755 index 00000000..48c1917a --- /dev/null +++ b/dlls/engine/forwards.cpp @@ -0,0 +1,229 @@ +#include "engine.h" + +bool incmd = false; +int DispatchUseForward = 0; +int SpawnForward = 0; +int ChangelevelForward = 0; +int PlaybackForward = 0; +int DispatchKeyForward = 0; +int pfnTouchForward = 0; +int pfnThinkForward = 0; +int PlayerPreThinkForward = 0; +int PlayerPostThinkForward = 0; +int ClientKillForward = 0; +int CmdStartForward = 0; +int StartFrameForward = 0; + +void DispatchUse(edict_t *pentUsed, edict_t *pentOther) +{ + if (DispatchUseForward) { + int retVal = 0; + int used = ENTINDEX(pentUsed); + int user = ENTINDEX(pentOther); + retVal = MF_ExecuteForward(DispatchUseForward, user, used); + if (retVal) + RETURN_META(MRES_SUPERCEDE); + } + RETURN_META(MRES_IGNORED); +} + +int DispatchSpawn(edict_t *pEntity) { + if (SpawnForward) { + int retVal = 0; + int id = ENTINDEX(pEntity); + retVal = MF_ExecuteForward(SpawnForward, id); + if (retVal) + RETURN_META_VALUE(MRES_SUPERCEDE, 0); + } + RETURN_META_VALUE(MRES_IGNORED, 0); +} + +void ChangeLevel(char* s1, char* s2) +{ + if (ChangelevelForward) { + int retVal = 0; + char *map = s1; + cell amxMap = MF_PrepareCharArray(map, strlen(map)); + retVal = MF_ExecuteForward(ChangelevelForward, amxMap); + if (retVal) + RETURN_META(MRES_SUPERCEDE); + } + RETURN_META(MRES_IGNORED); +} + +void PlaybackEvent(int flags, const edict_t *pInvoker, unsigned short eventindex, float delay, float *origin, float *angles, float fparam1, float fparam2, int iparam1, int iparam2, int bparam1, int bparam2) +{ + if (PlaybackForward) { + edict_t *e = (edict_t *)pInvoker; + int retVal = 0; + static cell cOrigin[3]; + static cell cAngles[3]; + Vector vOrigin = (Vector)origin; + Vector vAngles = (Vector)angles; + cOrigin[0] = amx_ftoc(vOrigin.x); + cOrigin[1] = amx_ftoc(vOrigin.y); + cOrigin[2] = amx_ftoc(vOrigin.z); + cAngles[0] = amx_ftoc(vAngles.x); + cAngles[1] = amx_ftoc(vAngles.y); + cAngles[2] = amx_ftoc(vAngles.z); + cell CellOrigin = MF_PrepareCellArray(cOrigin, 3); + cell CellAngles = MF_PrepareCellArray(cAngles, 3); + retVal = MF_ExecuteForward(PlaybackForward, flags, ENTINDEX(e), eventindex, amx_ftoc(delay), CellOrigin, CellAngles, amx_ftoc(fparam1), amx_ftoc(fparam2), iparam1, iparam2, bparam2); + if (retVal) + RETURN_META(MRES_SUPERCEDE); + } + RETURN_META(MRES_IGNORED); + +} + +#if 0 +void KeyValue(edict_t *pEntity, KeyValueData *pkvd) +{ + if (DispatchKeyForward) { + inKeyValue=true; + int retVal = 0; + g_pkvd=pkvd; + int index = ENTINDEX(pEntity); + retVal = MF_ExecuteForward(DispatchKeyForward, index); + inKeyValue=false; + if (retVal) + RETURN_META(MRES_SUPERCEDE); + } + RETURN_META(MRES_HANDLED); +} +#endif + +void StartFrame() +{ + if (glinfo.bCheckLights) { + if (!FStrEq((const char*)glinfo.szLastLights, "")) { + (g_engfuncs.pfnLightStyle)(0, (char *)glinfo.szLastLights); + glinfo.fNextLights = gpGlobals->time + 1; + } + } + + if (StartFrameForward) + MF_ExecuteForward(StartFrameForward); + + RETURN_META(MRES_IGNORED); +} + +void CmdStart(const edict_t *player, const struct usercmd_s *_cmd, unsigned int random_seed) +{ + int retVal = 0; + edict_t *pEntity = (edict_t *)player; + struct usercmd_s *g_cmd = (struct usercmd_s *)_cmd; + if (CmdStartForward) { + incmd = true; + retVal = MF_ExecuteForward(CmdStartForward, ENTINDEX(pEntity), g_cmd->impulse); + incmd = false; + if (retVal) { + g_cmd->impulse = 0; + RETURN_META(MRES_SUPERCEDE); + } + } + + RETURN_META(MRES_IGNORED); +} + +void ClientKill(edict_t *pEntity) +{ + int retVal = 0; + + if (ClientKillForward) { + retVal = MF_ExecuteForward(ClientKillForward, ENTINDEX(pEntity)); + if (retVal) + RETURN_META(MRES_SUPERCEDE); + } + + RETURN_META(MRES_IGNORED); +} + +void PlayerPreThink(edict_t *pEntity) +{ + int retVal = 0; + + if (pfnTouchForward) { + retVal = MF_ExecuteForward(PlayerPreThinkForward, ENTINDEX(pEntity)); + if (retVal) + RETURN_META(MRES_SUPERCEDE); + } + + RETURN_META(MRES_IGNORED); +} + +void PlayerPostThink(edict_t *pEntity) +{ + int retVal = 0; + + if(plinfo[ENTINDEX(pEntity)].pViewEnt) { + edict_t *pCamEnt = plinfo[ENTINDEX(pEntity)].pViewEnt; + + MAKE_VECTORS(pEntity->v.v_angle + pEntity->v.punchangle); + Vector vecSrc = pEntity->v.origin + pEntity->v.view_ofs; + Vector vecAiming = gpGlobals->v_forward; + TraceResult tr; + + switch(plinfo[ENTINDEX(pEntity)].iViewType) { + case CAMERA_3RDPERSON: + TRACE_LINE(vecSrc, vecSrc - (vecAiming * 128), ignore_monsters, ENT(pEntity), &tr); + SET_VIEW(pEntity, pCamEnt); + pCamEnt->v.origin = tr.vecEndPos; + pCamEnt->v.angles = pEntity->v.v_angle; + break; + case CAMERA_UPLEFT: + TRACE_LINE(vecSrc, vecSrc - ((vecAiming * 32) - ((gpGlobals->v_right * 15) + (gpGlobals->v_up * 15))), ignore_monsters, ENT(pEntity), &tr); + SET_VIEW(pEntity, pCamEnt); + pCamEnt->v.origin = tr.vecEndPos; + pCamEnt->v.angles = pEntity->v.v_angle; + break; + case CAMERA_TOPDOWN: + TRACE_LINE(vecSrc, vecSrc + Vector(0,0,2048), dont_ignore_monsters, ENT(pEntity), &tr); + SET_VIEW(pEntity, pCamEnt); + pCamEnt->v.origin = tr.vecEndPos; + pCamEnt->v.origin.z -= 40; + pCamEnt->v.angles = Vector(90,pEntity->v.v_angle.y,0); + break; + default: + SET_VIEW(pEntity, pEntity); + REMOVE_ENTITY(plinfo[ENTINDEX(pEntity)].pViewEnt); + plinfo[ENTINDEX(pEntity)].iViewType = CAMERA_NONE; + plinfo[ENTINDEX(pEntity)].pViewEnt = NULL; + break; + } + } + + if (pfnTouchForward) { + retVal = MF_ExecuteForward(PlayerPostThinkForward, ENTINDEX(pEntity)); + if (retVal) + RETURN_META(MRES_SUPERCEDE); + } + + RETURN_META(MRES_IGNORED); +} + +void DispatchTouch(edict_t *pToucher, edict_t *pTouched) +{ + int retVal = 0; + /* Execute pfnTouch forwards */ + if (pfnTouchForward) { + retVal = MF_ExecuteForward(pfnTouchForward, ENTINDEX(pToucher), ENTINDEX(pTouched)); + if (retVal) + RETURN_META(MRES_SUPERCEDE); + } + + RETURN_META(MRES_IGNORED); +} + +void DispatchThink(edict_t *pent) +{ + int retVal = 0; + + if (pfnThinkForward) { + retVal = MF_ExecuteForward(pfnThinkForward, ENTINDEX(pent)); + if (retVal) + RETURN_META(MRES_SUPERCEDE); + } + + RETURN_META(MRES_IGNORED); +} \ No newline at end of file diff --git a/dlls/engine/globals.cpp b/dlls/engine/globals.cpp new file mode 100755 index 00000000..ef50d826 --- /dev/null +++ b/dlls/engine/globals.cpp @@ -0,0 +1,177 @@ +#include "gpglobals.h" + +static cell AMX_NATIVE_CALL get_global_float(AMX *amx, cell *params) +{ + int global = params[1]; + + REAL returnValue; + + switch (params[1]) { + case GL_coop: + returnValue = gpGlobals->coop; + break; + case GL_deathmatch: + returnValue = gpGlobals->deathmatch; + break; + case GL_force_retouch: + returnValue = gpGlobals->force_retouch; + break; + case GL_found_secrets: + returnValue = gpGlobals->found_secrets; + break; + case GL_frametime: + returnValue = gpGlobals->frametime; + break; + case GL_serverflags: + returnValue = gpGlobals->serverflags; + break; + case GL_teamplay: + returnValue = gpGlobals->teamplay; + break; + case GL_time: + returnValue = gpGlobals->time; + break; + case GL_trace_allsolid: + returnValue = gpGlobals->trace_allsolid; + break; + case GL_trace_fraction: + returnValue = gpGlobals->trace_fraction; + break; + case GL_trace_inopen: + returnValue = gpGlobals->trace_inopen; + break; + case GL_trace_inwater: + returnValue = gpGlobals->trace_inwater; + break; + case GL_trace_plane_dist: + returnValue = gpGlobals->trace_plane_dist; + break; + case GL_trace_startsolid: + returnValue = gpGlobals->trace_startsolid; + break; + default: + MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + return 0; + } + + return amx_ftoc(returnValue); +} + +static cell AMX_NATIVE_CALL get_global_int(AMX *amx, cell *params) +{ + int returnValue = 0; + + switch (params[1]) { + case GL_cdAudioTrack: + returnValue = gpGlobals->cdAudioTrack; + break; + case GL_maxClients: + returnValue = gpGlobals->maxClients; + break; + case GL_maxEntities: + returnValue = gpGlobals->maxEntities; + break; + case GL_msg_entity: + returnValue = gpGlobals->msg_entity; + break; + case GL_trace_flags: + returnValue = gpGlobals->trace_flags; + break; + case GL_trace_hitgroup: + returnValue = gpGlobals->trace_hitgroup; + break; + default: + MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + return 0; + } + + return returnValue; +} + +static cell AMX_NATIVE_CALL get_global_string(AMX *amx, cell *params) +{ + string_t* returnValue; + + switch(params[1]) { + case GL_pStringBase: // const char *, so no string_t + return MF_SetAmxString(amx, params[2], gpGlobals->pStringBase, params[3]); + // The rest are string_t:s... + case GL_mapname: + returnValue = &(gpGlobals->mapname); + break; + case GL_startspot: + returnValue = &(gpGlobals->startspot); + break; + default: + MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + return 0; + } + + return MF_SetAmxString(amx, params[2], STRING(*returnValue), params[3]); +} + +static cell AMX_NATIVE_CALL get_global_vector(AMX *amx, cell *params) // globals_get_vector(variable, Float:vector[3]); = 2 params +{ + cell *cRet = MF_GetAmxAddr(amx, params[2]); + vec3_t fetchedVector; + + switch (params[1]) { + case GL_trace_endpos: + fetchedVector = gpGlobals->trace_endpos; + break; + case GL_trace_plane_normal: + fetchedVector = gpGlobals->trace_plane_normal; + break; + case GL_v_forward: + fetchedVector = gpGlobals->v_forward; + break; + case GL_v_right: + fetchedVector = gpGlobals->v_right; + break; + case GL_v_up: + fetchedVector = gpGlobals->v_up; + break; + case GL_vecLandmarkOffset: + fetchedVector = gpGlobals->vecLandmarkOffset; + break; + default: + MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + return 0; + } + + cRet[0] = amx_ftoc(fetchedVector.x); + cRet[1] = amx_ftoc(fetchedVector.y); + cRet[2] = amx_ftoc(fetchedVector.z); + + return 1; +} + +static cell AMX_NATIVE_CALL get_global_edict(AMX *amx, cell *params) // globals_get_edict(variable); = 1 param +{ + edict_t* pReturnEntity; + + switch (params[1]) { + case GL_trace_ent: + pReturnEntity = gpGlobals->trace_ent; + break; + default: + MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + return 0; + } + + // Will crash if ENTINDEX() is called on bad pointer? + if(!FNullEnt(pReturnEntity)) + return ENTINDEX(pReturnEntity); + + return 0; +} + +AMX_NATIVE_INFO global_Natives[] = { + {"get_global_float", get_global_float}, + {"get_global_int", get_global_int}, + {"get_global_string", get_global_string}, + {"get_global_edict", get_global_edict}, + {"get_global_vector", get_global_vector}, + {NULL, NULL}, + /////////////////// +}; \ No newline at end of file diff --git a/dlls/engine/gpglobals.h b/dlls/engine/gpglobals.h new file mode 100755 index 00000000..d65b304c --- /dev/null +++ b/dlls/engine/gpglobals.h @@ -0,0 +1,53 @@ +#ifndef _INCLUDE_ENGINE_GLOBAL +#define _INCLUDE_ENGINE_GLOBAL + +#include "engine.h" + +enum globals { + // Edict + GL_trace_ent = 0, + + // Float + GL_coop, + GL_deathmatch, + GL_force_retouch, + GL_found_secrets, + GL_frametime, + GL_serverflags, + GL_teamplay, + GL_time, + GL_trace_allsolid, + GL_trace_fraction, + GL_trace_inopen, + GL_trace_inwater, + GL_trace_plane_dist, + GL_trace_startsolid, + + // Int + GL_cdAudioTrack, + GL_maxClients, + GL_maxEntities, + GL_msg_entity, + GL_trace_flags, + GL_trace_hitgroup, + + // String + GL_pStringBase, + GL_mapname, + GL_startspot, + + // Vector + GL_trace_endpos, + GL_trace_plane_normal, + GL_v_forward, + GL_v_right, + GL_v_up, + GL_vecLandmarkOffset, + + // Void (not supported) + GL_pSaveData +}; + +extern AMX_NATIVE_INFO global_Natives[]; + +#endif //_INCLUDE_ENGINE_GLOBAL \ No newline at end of file diff --git a/dlls/engine/messages.cpp b/dlls/engine/messages.cpp new file mode 100755 index 00000000..9e0151df --- /dev/null +++ b/dlls/engine/messages.cpp @@ -0,0 +1,477 @@ +#include "messages.h" + +using namespace std; + +std::vector Msg; +int msgDest; +int msgType; +float *msgOrigin; +edict_t *msgpEntity; +int msgHooks[256] = {0}; +int msgBlocks[256] = {0}; +bool inhook = false; +bool inblock = false; +unsigned int msgCount = 0; + +argMsg::argMsg() +{ + Reset(); +} + +void argMsg::Reset() +{ + iData = 0; + fData = 0.0; + cData.clear(); + type = 0; +} + +void argMsg::Send() +{ + switch (type) + { + case arg_byte: + WRITE_BYTE(iData); + break; + case arg_char: + WRITE_CHAR(iData); + break; + case arg_short: + WRITE_SHORT(iData); + break; + case arg_long: + WRITE_LONG(iData); + break; + case arg_angle: + WRITE_ANGLE(fData); + break; + case arg_coord: + WRITE_COORD(fData); + break; + case arg_string: + WRITE_STRING(cData.c_str()); + break; + case arg_entity: + WRITE_ENTITY(iData); + break; + } + Reset(); +} + +int argMsg::Type() +{ + switch (type) + { + case arg_byte: + return type_int; + break; + case arg_char: + return type_int; + break; + case arg_short: + return type_int; + break; + case arg_long: + return type_int; + break; + case arg_angle: + return type_float; + break; + case arg_coord: + return type_float; + break; + case arg_string: + return type_string; + break; + case arg_entity: + return type_int; + break; + } + + return 0; +} + +void MessageBegin(int msg_dest, int msg_type, const float *pOrigin, edict_t *ed) +{ + if (msgBlocks[msg_type]) { + inblock = true; + RETURN_META(MRES_SUPERCEDE); + } else if (msgHooks[msg_type]) { + inhook = true; + msgCount = 0; + msgDest = msg_dest; + msgType = msg_type; + msgOrigin = (float *)pOrigin; + msgpEntity = ed; + RETURN_META(MRES_SUPERCEDE); + } + + RETURN_META(MRES_IGNORED); +} + +void WriteByte(int iValue) +{ + if (inblock) { + RETURN_META(MRES_SUPERCEDE); + } else if (inhook) { + if (++msgCount > Msg.size()) { + argMsg *p = new argMsg(); + p->iData = iValue; + p->type = arg_byte; + Msg.push_back(p); + } else { + Msg.at(msgCount-1)->iData = iValue; + Msg.at(msgCount-1)->type = arg_byte; + } + RETURN_META(MRES_SUPERCEDE); + } + + RETURN_META(MRES_IGNORED); +} + +void WriteChar(int iValue) +{ + if (inblock) { + RETURN_META(MRES_SUPERCEDE); + } else if (inhook) { + if (++msgCount > Msg.size()) { + argMsg *p = new argMsg(); + p->iData = iValue; + p->type = arg_char; + Msg.push_back(p); + } else { + Msg.at(msgCount-1)->iData = iValue; + Msg.at(msgCount-1)->type = arg_char; + } + RETURN_META(MRES_SUPERCEDE); + } + + RETURN_META(MRES_IGNORED); +} + +void WriteShort(int iValue) +{ + if (inblock) { + RETURN_META(MRES_SUPERCEDE); + } else if (inhook) { + if (++msgCount > Msg.size()) { + argMsg *p = new argMsg(); + p->iData = iValue; + p->type = arg_short; + Msg.push_back(p); + } else { + Msg.at(msgCount-1)->iData = iValue; + Msg.at(msgCount-1)->type = arg_short; + } + RETURN_META(MRES_SUPERCEDE); + } + + RETURN_META(MRES_IGNORED); +} + +void WriteLong(int iValue) +{ + if (inblock) { + RETURN_META(MRES_SUPERCEDE); + } else if (inhook) { + if (++msgCount > Msg.size()) { + argMsg *p = new argMsg(); + p->iData = iValue; + p->type = arg_long; + Msg.push_back(p); + } else { + Msg.at(msgCount-1)->iData = iValue; + Msg.at(msgCount-1)->type = arg_long; + } + RETURN_META(MRES_SUPERCEDE); + } + + RETURN_META(MRES_IGNORED); +} + +void WriteAngle(float flValue) +{ + if (inblock) { + RETURN_META(MRES_SUPERCEDE); + } else if (inhook) { + if (++msgCount > Msg.size()) { + argMsg *p = new argMsg(); + p->fData = flValue; + p->type = arg_angle; + Msg.push_back(p); + } else { + Msg.at(msgCount-1)->fData = flValue; + Msg.at(msgCount-1)->type = arg_angle; + } + RETURN_META(MRES_SUPERCEDE); + } + + RETURN_META(MRES_IGNORED); +} + +void WriteCoord(float flValue) +{ + if (inblock) { + RETURN_META(MRES_SUPERCEDE); + } else if (inhook) { + if (++msgCount > Msg.size()) { + argMsg *p = new argMsg(); + p->fData = flValue; + p->type = arg_coord; + Msg.push_back(p); + } else { + Msg.at(msgCount-1)->fData = flValue; + Msg.at(msgCount-1)->type = arg_coord; + } + RETURN_META(MRES_SUPERCEDE); + } + + RETURN_META(MRES_IGNORED); +} + +void WriteString(const char *sz) +{ + if (inblock) { + RETURN_META(MRES_SUPERCEDE); + } else if (inhook) { + if (++msgCount > Msg.size()) { + argMsg *p = new argMsg(); + p->cData.assign(sz); + p->type = arg_string; + Msg.push_back(p); + } else { + Msg.at(msgCount-1)->cData.assign(sz); + Msg.at(msgCount-1)->type = arg_string; + } + RETURN_META(MRES_SUPERCEDE); + } + + RETURN_META(MRES_IGNORED); +} + +void WriteEntity(int iValue) +{ + if (inblock) { + RETURN_META(MRES_SUPERCEDE); + } else if (inhook) { + if (++msgCount > Msg.size()) { + argMsg *p = new argMsg(); + p->iData = iValue; + p->type = arg_entity; + Msg.push_back(p); + } else { + Msg.at(msgCount-1)->iData = iValue; + Msg.at(msgCount-1)->type = arg_entity; + } + RETURN_META(MRES_SUPERCEDE); + } + + RETURN_META(MRES_IGNORED); +} + +void MessageEnd(void) +{ + int mres = 0; + int mct = msgCount; + unsigned int i = 0; + if (inblock) { + if (msgBlocks[msgType] == BLOCK_ONCE) + msgBlocks[msgType] = BLOCK_NOT; + RETURN_META(MRES_SUPERCEDE); + } else if (inhook) { + inhook = false; + mres = MF_ExecuteForward(msgHooks[msgType], msgType, msgDest, ENTINDEX(msgpEntity)); + MF_Log("Executing forward: %d with retval %d", msgHooks[msgType], mres); + if (mres & 1) + RETURN_META(MRES_SUPERCEDE); + MESSAGE_BEGIN(msgDest, msgType, msgOrigin, msgpEntity); + for (i=0; iSend(); + Msg.at(i)->Reset(); + } + MESSAGE_END(); + RETURN_META(MRES_SUPERCEDE); + } + + RETURN_META(MRES_IGNORED); +} + +static cell AMX_NATIVE_CALL register_message(AMX *amx, cell *params) +{ + int len; + if (params[1]>0 && params[1] < 256) { + int id = MF_RegisterSPForwardByName(amx, MF_GetAmxString(amx, params[2], 0, &len), FP_CELL, FP_CELL, FP_CELL, FP_DONE); + MF_Log("Registering message %d with result %d", params[1], id); + msgHooks[params[1]] = id; + return id; + } + + return 0; +} + +static cell AMX_NATIVE_CALL set_msg_block(AMX *amx, cell *params) +{ + int msgid = params[1]; + int block = params[2]; + + if (msgid < 1 || msgid > 255) { + MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + return 0; + } + + msgBlocks[msgid] = block; + + return 1; +} + +static cell AMX_NATIVE_CALL get_msg_block(AMX *amx, cell *params) +{ + int msgid = params[1]; + int block = params[2]; + + if (msgid < 1 || msgid > 255) { + MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + return 0; + } + + return msgBlocks[msgid]; +} + +static cell AMX_NATIVE_CALL get_msg_args(AMX *amx, cell *params) +{ + return msgCount; +} + +static cell AMX_NATIVE_CALL get_msg_argtype(AMX *amx, cell *params) +{ + unsigned int argn = params[1]; + + if (!inhook || argn >= Msg.size()) { + MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + return 0; + } + + return Msg.at(argn-1)->Type(); +} + +static cell AMX_NATIVE_CALL get_msg_arg_int(AMX *amx, cell *params) +{ + unsigned int argn = params[1]; + + if (!inhook || argn >= Msg.size()) { + MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + return 0; + } + + int iVal = Msg.at(argn-1)->iData; + + return iVal; +} + +static cell AMX_NATIVE_CALL set_msg_arg_int(AMX *amx, cell *params) +{ + unsigned int argn = params[1]; + + if (!inhook || argn >= Msg.size()) { + MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + return 0; + } + + Msg.at(argn-1)->iData = params[2]; + + return 1; +} + +static cell AMX_NATIVE_CALL get_msg_arg_float(AMX *amx, cell *params) +{ + unsigned int argn = params[1]; + + if (!inhook || argn >= Msg.size()) { + MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + return 0; + } + + return amx_ftoc(Msg.at(argn-1)->fData); +} + +static cell AMX_NATIVE_CALL set_msg_arg_float(AMX *amx, cell *params) +{ + unsigned int argn = params[1]; + + if (!inhook || argn >= Msg.size()) { + MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + return 0; + } + + REAL fVal = amx_ctof(params[2]); + + Msg.at(argn-1)->fData = fVal; + + return 1; +} + +static cell AMX_NATIVE_CALL get_msg_arg_string(AMX *amx, cell *params) +{ + unsigned int argn = params[1]; + + if (!inhook || argn >= Msg.size()) { + MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + return 0; + } + + const char *szVal = Msg.at(argn-1)->cData.c_str(); + + return MF_SetAmxString(amx, params[2], szVal, params[3]); +} + +static cell AMX_NATIVE_CALL set_msg_arg_string(AMX *amx, cell *params) +{ + unsigned int argn = params[1]; + int iLen; + + if (!inhook || argn >= Msg.size()) { + MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + return 0; + } + + char *szVal = MF_GetAmxString(amx, params[2], 0, &iLen); + + Msg.at(argn-1)->cData.assign(szVal); + + return 1; +} + +static cell AMX_NATIVE_CALL get_msg_origin(AMX *amx, cell *params) +{ + if (!inhook) { + MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + return 0; + } + vec3_t vRet = (Vector)msgOrigin; + cell *cAddr = MF_GetAmxAddr(amx, params[1]); + + cAddr[0] = amx_ftoc(vRet.x); + cAddr[1] = amx_ftoc(vRet.y); + cAddr[2] = amx_ftoc(vRet.z); + + return 1; +} + +AMX_NATIVE_INFO msg_Natives[] = { + {"register_message", register_message}, + + {"set_msg_block", set_msg_block}, + {"get_msg_block", get_msg_block}, + + {"get_msg_args", get_msg_args}, + {"get_msg_argtype", get_msg_argtype}, + {"get_msg_arg_int", get_msg_arg_int}, + {"set_msg_arg_int", set_msg_arg_int}, + {"get_msg_arg_float", get_msg_arg_float}, + {"set_msg_arg_float", set_msg_arg_float}, + {"get_msg_arg_string", get_msg_arg_string}, + {"set_msg_arg_string", set_msg_arg_string}, + {"get_msg_origin", get_msg_origin}, + + {NULL, NULL}, +}; \ No newline at end of file diff --git a/dlls/engine/messages.h b/dlls/engine/messages.h new file mode 100755 index 00000000..1231dca5 --- /dev/null +++ b/dlls/engine/messages.h @@ -0,0 +1,45 @@ +#ifndef _MSGS_INCLUDE_H +#define _MSGS_INCLUDE_H + +#include "engine.h" + +#define MAX_MESSAGES 255 + +#define BLOCK_NOT 0 +#define BLOCK_ONCE 1 +#define BLOCK_SET 2 + +enum { + arg_byte = 1, + arg_char, + arg_short, + arg_long, + arg_angle, + arg_coord, + arg_string, + arg_entity, +}; + +enum { + type_int = 1, + type_float, + type_string, +}; + +class argMsg +{ +public: + argMsg(); + void Reset(); + void Send(); + int Type(); + + int type; + REAL fData; + std::string cData; + int iData; +}; + +extern AMX_NATIVE_INFO msg_Natives[]; + +#endif //_MSGS_INCLUDE_H \ No newline at end of file diff --git a/dlls/engine/meta_api.cpp b/dlls/engine/meta_api.cpp index fed8bf64..096b743d 100755 --- a/dlls/engine/meta_api.cpp +++ b/dlls/engine/meta_api.cpp @@ -2901,8 +2901,19 @@ static cell AMX_NATIVE_CALL get_speak(AMX *amx, cell *params) { return PlInfo[iIndex].iSpeakFlags; } -/******************************************** - METAMOD HOOKED FUNCTIONS +static cell AMX_NATIVE_CALL trace_hull(AMX *amx, cell *params) +{ + int res = 0; + TraceResult v; +} + +/* ***************************************** + ***************************************** + ***************************************** + METAMOD HOOKED FUNCTIONS + ***************************************** + ***************************************** + ***************************************** *****************************************/ // This checks who can hear who through voice comm. this reads flags set, @@ -3423,6 +3434,7 @@ AMX_NATIVE_INFO Engine_Natives[] = { {"halflife_time", halflife_time}, {"fake_touch", fake_touch}, {"get_grenade_id", get_grenade_id}, + {"trace_hull", trace_hull}, {"create_entity", create_entity}, {"remove_entity", remove_entity}, diff --git a/dlls/engine/moduleconfig.h b/dlls/engine/moduleconfig.h index 77ccc49d..e0198cfc 100755 --- a/dlls/engine/moduleconfig.h +++ b/dlls/engine/moduleconfig.h @@ -4,7 +4,7 @@ #define __MODULECONFIG_H__ // Module info -#define MODULE_NAME "Engine" +#define MODULE_NAME "ENGINE" #define MODULE_VERSION "0.20" #define MODULE_AUTHOR "AMX Mod X Dev Team" #define MODULE_URL "www.amxmodx.org" @@ -32,7 +32,7 @@ //#define FN_AMXX_DETTACH OnAmxxDettach // All plugins loaded // Do forward functions init here (MF_RegisterForward) -//#define FN_AMXX_PLUGINSLOADED OnPluginsLoaded +#define FN_AMXX_PLUGINSLOADED OnPluginsLoaded /**** METAMOD ****/ // If your module doesn't use metamod, you may close the file now :) @@ -53,13 +53,13 @@ // (wd) are Will Day's notes // - GetEntityAPI2 functions -//#define FN_GameDLLInit GameDLLInit /* pfnGameInit() */ -// #define FN_DispatchSpawn DispatchSpawn /* pfnSpawn() */ -// #define FN_DispatchThink DispatchThink /* pfnThink() */ -// #define FN_DispatchUse DispatchUse /* pfnUse() */ +// #define FN_GameDLLInit GameDLLInit /* pfnGameInit() */ +#define FN_DispatchSpawn DispatchSpawn /* pfnSpawn() */ +#define FN_DispatchThink DispatchThink /* pfnThink() */ +#define FN_DispatchUse DispatchUse /* pfnUse() */ #define FN_DispatchTouch DispatchTouch /* pfnTouch() */ // #define FN_DispatchBlocked DispatchBlocked /* pfnBlocked() */ -// #define FN_DispatchKeyValue DispatchKeyValue /* pfnKeyValue() */ +//#define FN_DispatchKeyValue KeyValue /* pfnKeyValue() */ // #define FN_DispatchSave DispatchSave /* pfnSave() */ // #define FN_DispatchRestore DispatchRestore /* pfnRestore() */ // #define FN_DispatchObjectCollsionBox DispatchObjectCollsionBox /* pfnSetAbsBox() */ @@ -73,8 +73,8 @@ #define FN_ClientKill ClientKill /* pfnClientKill() (wd) Player has typed "kill" */ // #define FN_ClientPutInServer ClientPutInServer /* pfnClientPutInServer() (wd) Client is entering the game */ // #define FN_ClientCommand ClientCommand /* pfnClientCommand() (wd) Player has sent a command (typed or from a bind) */ -#define FN_ClientUserInfoChanged ClientUserInfoChanged /* pfnClientUserInfoChanged() (wd) Client has updated their setinfo structure */ -#define FN_ServerActivate ServerActivate /* pfnServerActivate() (wd) Server is starting a new map */ +// #define FN_ClientUserInfoChanged ClientUserInfoChanged /* pfnClientUserInfoChanged() (wd) Client has updated their setinfo structure */ +// #define FN_ServerActivate ServerActivate /* pfnServerActivate() (wd) Server is starting a new map */ #define FN_ServerDeactivate ServerDeactivate /* pfnServerDeactivate() (wd) Server is leaving the map (shutdown or changelevel); SDK2 */ #define FN_PlayerPreThink PlayerPreThink /* pfnPlayerPreThink() */ #define FN_PlayerPostThink PlayerPostThink /* pfnPlayerPostThink() */ @@ -123,7 +123,7 @@ // #define FN_ClientConnect_Post ClientConnect_Post // #define FN_ClientDisconnect_Post ClientDisconnect_Post // #define FN_ClientKill_Post ClientKill_Post -#define FN_ClientPutInServer_Post ClientPutInServer_Post +// #define FN_ClientPutInServer_Post ClientPutInServer_Post // #define FN_ClientCommand_Post ClientCommand_Post // #define FN_ClientUserInfoChanged_Post ClientUserInfoChanged_Post // #define FN_ServerActivate_Post ServerActivate_Post @@ -163,7 +163,7 @@ // #define FN_ModelIndex ModelIndex // #define FN_ModelFrames ModelFrames // #define FN_SetSize SetSize -// #define FN_ChangeLevel ChangeLevel +#define FN_ChangeLevel ChangeLevel // #define FN_GetSpawnParms GetSpawnParms // #define FN_SaveSpawnParms SaveSpawnParms // #define FN_VecToYaw VecToYaw @@ -280,7 +280,7 @@ // #define FN_SetPhysicsKeyValue SetPhysicsKeyValue // #define FN_GetPhysicsInfoString GetPhysicsInfoString // #define FN_PrecacheEvent PrecacheEvent -// #define FN_PlaybackEvent PlaybackEvent +#define FN_PlaybackEvent PlaybackEvent // #define FN_SetFatPVS SetFatPVS // #define FN_SetFatPAS SetFatPAS // #define FN_CheckVisibility CheckVisibility