diff --git a/main/source/mod/AvHConstants.h b/main/source/mod/AvHConstants.h index e3ad442e..c1609ec8 100644 --- a/main/source/mod/AvHConstants.h +++ b/main/source/mod/AvHConstants.h @@ -189,7 +189,8 @@ typedef enum MAP_MODE_NS = 1, MAP_MODE_CS = 2, MAP_MODE_DM = 3, - MAP_MODE_CO = 4 + MAP_MODE_CO = 4, + MAP_MODE_NSC = 5 } AvHMapMode; diff --git a/main/source/mod/AvHGamerules.cpp b/main/source/mod/AvHGamerules.cpp index 302fab39..6767b774 100644 --- a/main/source/mod/AvHGamerules.cpp +++ b/main/source/mod/AvHGamerules.cpp @@ -264,6 +264,11 @@ int kProfileRunConfig = 0xFFFFFFFF; std::string GetLogStringForPlayer( edict_t *pEntity ); +// SCRIPTENGINE: +#include "scriptengine/AvHLUA.h" +extern AvHLUA *gLUA; +// :SCRIPTENGINE + const AvHMapExtents& GetMapExtents() { return GetGameRules()->GetMapExtents(); @@ -1338,6 +1343,11 @@ bool AvHGamerules::GetIsNSMode(void) const return (this->GetMapMode() == MAP_MODE_NS); } +bool AvHGamerules::GetIsScriptedMode(void) const +{ + return (this->GetMapMode() == MAP_MODE_NSC); +} + bool AvHGamerules::GetIsHamboneMode() const { return this->GetIsCombatMode() && (CVAR_GET_FLOAT(kvIronMan) == 2); @@ -2510,6 +2520,10 @@ void AvHGamerules::RecalculateMapMode( void ) { this->mMapMode = MAP_MODE_CO; } + else if(!strnicmp(theCStrLevelName, "nsc_", 4)) + { + this->mMapMode = MAP_MODE_NSC; + } } } // Check for CS entities @@ -3688,6 +3702,13 @@ void AvHGamerules::UpdateCheats() void AvHGamerules::UpdateCountdown(float inTime) { + if (this->GetIsScriptedMode()) + { + // this->SetGameStarted(true); + // TODO: SCRIPTENGINE START + return; + } + const float kTimeWontStartInterval = 8.0f; int kSecondsToCountdown = 5; @@ -3864,6 +3885,11 @@ void AvHGamerules::UpdateVictoryStatus(void) { bool theCheckVictoryWithCheats = !this->GetCheatsEnabled() || this->GetIsCheatEnabled(kcEndGame1) || this->GetIsCheatEnabled(kcEndGame2); + if (this->GetIsScriptedMode()) + { + // SCRIPTENGINE: Check for victory status + } + else if((this->mVictoryTeam == TEAM_IND) && this->mGameStarted && theCheckVictoryWithCheats && !this->GetIsTrainingMode()) { char* theVictoryMessage = NULL; diff --git a/main/source/mod/AvHGamerules.h b/main/source/mod/AvHGamerules.h index 996df319..ea086e09 100644 --- a/main/source/mod/AvHGamerules.h +++ b/main/source/mod/AvHGamerules.h @@ -263,6 +263,7 @@ public: virtual bool GetIsCombatMode(void) const; virtual AvHTeamNumber GetCombatAttackingTeamNumber() const; virtual bool GetIsNSMode(void) const; + virtual bool GetIsScriptedMode(void) const; virtual bool GetIsTrainingMode(void) const; int GetBaseHealthForMessageID(AvHMessageID inMessageID) const; diff --git a/main/source/mod/AvHHud.cpp b/main/source/mod/AvHHud.cpp index cae4950b..f771bdc9 100644 --- a/main/source/mod/AvHHud.cpp +++ b/main/source/mod/AvHHud.cpp @@ -190,6 +190,11 @@ #include #include "mod/AvHNetworkMessages.h" +// SCRIPTENGINE: +#include "scriptengine/AvHLUA.h" +#include "scriptengine/AvHLUAUtil.h" +// :SCRIPTENGINE + //#include "cl_dll/studio_util.h" //#include "cl_dll/r_studioint.h" @@ -2570,8 +2575,33 @@ void AvHHud::ResetGame(bool inMapChanged) this->mCenterText.clear(); this->mCenterTextTime = -1; // :tankefugl + + // SCRIPTENGINE: + if (inMapChanged) + { + gLUA->Init(); + gLUA->LoadLUAForMap(this->GetMapName().c_str()); + } + // :SCRIPTENGINE } +// SCRIPTENGINE: +BIND_MESSAGE(LUAmsg); +int AvHHud::LUAmsg(const char* pszName, int iSize, void* pbuf) +{ + int arguments; + lua_State *L = lua_newthread(gLUA->mGlobalContext); + + NetMsg_LUAMessage(pbuf, iSize, L, arguments); + + if (lua_resume(L, arguments)) + { + AvHLUA_OnError(lua_tostring(L, -1)); + } + return 1; +} +// :SCRIPTENGINE + BIND_MESSAGE(SetGmma); int AvHHud::SetGmma(const char* pszName, int iSize, void* pbuf) { @@ -4881,6 +4911,11 @@ bool AvHHud::GetIsNSMode() const return (this->mMapMode == MAP_MODE_NS); } +bool AvHHud::GetIsScriptedMode() const +{ + return (this->mMapMode == MAP_MODE_NSC); +} + bool AvHHud::GetIsMouseInRegion(int inX, int inY, int inWidth, int inHeight) { bool theMouseIsInRegion = false; diff --git a/main/source/mod/AvHHud.h b/main/source/mod/AvHHud.h index d9677fdd..b0f59757 100644 --- a/main/source/mod/AvHHud.h +++ b/main/source/mod/AvHHud.h @@ -336,6 +336,7 @@ public: bool SwitchUIMode(UIMode inNewMode); bool GetIsCombatMode() const; bool GetIsNSMode() const; + bool GetIsScriptedMode() const; void HideResearchProgressStatus(); void SetResearchProgressStatus(float inPercentage); @@ -397,9 +398,8 @@ public: int GameStatus(const char* pszName, int iSize, void* pbuf); int MiniMap(const char* pszName, int iSize, void* pbuf); - // tankefugl: 0000971 int IssueOrder(const char* pszName, int iSize, void* pbuf); - // :tankefugl + int LUAmsg(const char* pszName, int iSize, void* pbuf); int Progress(const char* pszName, int iSize, void* pbuf); int SetGmma(const char* pszName, int iSize, void* pbuf); int SetSelect(const char* pszName, int iSize, void* pbuf); diff --git a/main/source/mod/AvHNetworkMessages.cpp b/main/source/mod/AvHNetworkMessages.cpp index 9ea98900..c291c4c1 100644 --- a/main/source/mod/AvHNetworkMessages.cpp +++ b/main/source/mod/AvHNetworkMessages.cpp @@ -24,7 +24,7 @@ int g_msgAmmoPickup = 0, g_msgAmmoX, g_msgBattery, g_msgCurWeapon, g_msgDamage, g_msgServerVar, g_msgSetGammaRamp, g_msgSetOrder, g_msgSetParticleTemplates, g_msgSetSelect, g_msgSetRequest, g_msgSetSoundNames, g_msgSetTechNodes, g_msgSetTechSlots, g_msgSetTopDown, g_msgSetupMap, g_msgUpdateCountdown, g_msgUpdateEntityHierarchy, - g_msgProfileInfo, g_msgNexusBytes, g_msgIssueOrder; + g_msgProfileInfo, g_msgNexusBytes, g_msgIssueOrder, g_msgLUAMessage; void Net_InitializeMessages(void) { @@ -47,7 +47,6 @@ void Net_InitializeMessages(void) g_msgMOTD = REG_USER_MSG( "MOTD", -1 ); g_msgResetHUD = REG_USER_MSG( "ResetHUD", 0 ); g_msgSayText = REG_USER_MSG( "SayText", -1 ); - // puzl: 0001073 g_msgScoreInfo = REG_USER_MSG( "ScoreInfo", -1 ); g_msgServerName = REG_USER_MSG( "ServerName", -1 ); g_msgSetFOV = REG_USER_MSG( "SetFOV", 1 ); @@ -90,9 +89,8 @@ void Net_InitializeMessages(void) g_msgUpdateEntityHierarchy = REG_USER_MSG( "EntHier", -1 ); g_msgProfileInfo = REG_USER_MSG( "ProfileInfo", 8 ); g_msgNexusBytes = REG_USER_MSG( "NexusBytes", -1 ); - // tankefugl: 0000971 g_msgIssueOrder = REG_USER_MSG( "IssueOrder", 9); - // :tankefugl + g_msgLUAMessage = REG_USER_MSG( "LUAmsg", -1); } #endif @@ -2159,4 +2157,85 @@ const int kEntHierFlagDeletion = 0x02; MESSAGE_END(); } #endif -// :tankefugl \ No newline at end of file +// :tankefugl + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#ifndef AVH_SERVER + void NetMsg_LUAMessage( void* const buffer, const int size, lua_State *L, int &arguments) + { + BEGIN_READ( buffer, size ); + arguments = READ_BYTE(); + for (int i = arguments; i > 0; i--) + { + if (i == arguments) + { + std::string temp = READ_STRING(); + lua_getglobal(L, temp.c_str()); + continue; + } + + int theLuaType = READ_BYTE(); + switch (theLuaType) + { + case LUA_TBOOLEAN: + lua_pushboolean(L, READ_BYTE()); + break; + case LUA_TNUMBER: + lua_pushnumber(L, (float)(READ_LONG())); + break; + case LUA_TSTRING: + lua_pushstring(L, READ_STRING()); + break; + default: + ASSERT(false); + break; + } + } + END_READ(); + arguments--; + } +#else + void NetMsg_LUAMessage(entvars_t* const pev, lua_State *L) + { + luaL_checktype(L, 2, LUA_TSTRING); + int arguments = lua_gettop(L); + for (int i = 3; i <= arguments; i++) + { + int theLuaType = lua_type(L, i); + if (!(theLuaType == LUA_TBOOLEAN || + theLuaType == LUA_TNUMBER || + theLuaType == LUA_TSTRING)) + luaL_typerror(L, i, "boolean|number|string"); + } + + MESSAGE_BEGIN( MSG_ONE, g_msgLUAMessage, NULL, pev ); + WRITE_BYTE(arguments - 1); + WRITE_STRING(lua_tostring(L, 2)); + int top = lua_gettop(L); + int current = 3; + while (current <= top) + { + int theLuaType = lua_type(L, current); + WRITE_BYTE(theLuaType); + switch (theLuaType) + { + case LUA_TBOOLEAN: + WRITE_BYTE(lua_toboolean(L, current)); + break; + case LUA_TNUMBER: + WRITE_LONG((float)(lua_tonumber(L, current))); + break; + case LUA_TSTRING: + WRITE_STRING(lua_tostring(L, current)); + break; + default: + ASSERT(false); + break; + } + current++; + } + MESSAGE_END(); + + } +#endif diff --git a/main/source/mod/AvHNetworkMessages.h b/main/source/mod/AvHNetworkMessages.h index 77af6bd7..916b79b4 100644 --- a/main/source/mod/AvHNetworkMessages.h +++ b/main/source/mod/AvHNetworkMessages.h @@ -34,6 +34,11 @@ #include "AvHEntityHierarchy.h" #include "../engine/shake.h" #include "../common/weaponinfo.h" +extern "C" { +#include +#include +#include +} //FUNCTION PROTOTYPES #ifdef AVH_SERVER @@ -107,6 +112,7 @@ void NetMsg_SetupMap_Location( entvars_t* const pev, const string& name, const float* const min_extents, const float* const max_extents ); void NetMsg_UpdateEntityHierarchy( entvars_t* const pev, const MapEntityMap& NewItems, const EntityListType& OldItems ); void NetMsg_IssueOrder(entvars_t* const pev, const int ordertype, const int ordersource, const int ordertarget); + void NetMsg_LUAMessage(entvars_t* const pev, lua_State *L); //BROADCAST MESSAGE TRANSMISSION void NetMsg_DeathMsg( const int killer_index, const int victim_index, string& weapon_name ); @@ -197,6 +203,8 @@ void NetMsg_UpdateCountdown( void* const buffer, const int size, int& countdown ); void NetMsg_UpdateEntityHierarchy( void* const buffer, const int size, MapEntityMap& NewItems, EntityListType& OldItems ); void NetMsg_IssueOrder( void* const buffer, const int size, int& ordertype, int& ordersource, int& ordertarget ); + void NetMsg_LUAMessage( void* const buffer, const int size, lua_State *L, int &arguments); + // 60 #endif //AVH_SERVER diff --git a/main/source/scriptengine/AvHLUA.cpp b/main/source/scriptengine/AvHLUA.cpp new file mode 100644 index 00000000..05461c27 --- /dev/null +++ b/main/source/scriptengine/AvHLUA.cpp @@ -0,0 +1,161 @@ +extern "C" { +#include +#include +#include +} +#include "scriptengine/AvHLUA.h" +#include "scriptengine/AvHLUAUtil.h" +#include + +#ifdef AVH_CLIENT +extern double gClientTimeLastUpdate; +#endif + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +AvHLUA::AvHLUA() +{ + this->mGlobalContext = NULL; + this->mLoaded = false; +} + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +AvHLUA::~AvHLUA() +{ +} + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +void AvHLUA::Init() +{ + this->mTimetable.clear(); + bool isRestricted = false; + +#ifdef AVH_SERVER + this->mNextCallTime = gpGlobals->time + 99999; + isRestricted = GetGameRules()->GetIsCombatMode() || GetGameRules()->GetIsNSMode(); +#else + this->mNextCallTime = gClientTimeLastUpdate + 99999; + isRestricted = gHUD.GetIsCombatMode() || gHUD.GetIsNSMode(); +#endif + + if (this->mGlobalContext != NULL) + { + lua_close(this->mGlobalContext); + } + this->mGlobalContext = lua_open(); + + // load libs for context -- give full access to servers, limited to clients +#ifdef AVH_SERVER + luaopen_io(this->mGlobalContext); +#endif + luaopen_base(this->mGlobalContext); + luaopen_table(this->mGlobalContext); + luaopen_string(this->mGlobalContext); + luaopen_math(this->mGlobalContext); + + // SERVER and CLIENT replacements + lua_register(this->mGlobalContext, "print", AvHLUABase_Print); + + +#ifdef AVH_CLIENT + // CLIENT replacements + //lua_register(this->mGlobalContext, "assert", AvHLUABase_Blank); + //lua_register(this->mGlobalContext, "collectgarbage", AvHLUABase_Blank); + lua_register(this->mGlobalContext, "dofile", AvHLUABase_Blank); + //lua_register(this->mGlobalContext, "error", AvHLUABase_Blank); + //lua_register(this->mGlobalContext, "_G", AvHLUABase_Blank); + //lua_register(this->mGlobalContext, "getfenv", AvHLUABase_Blank); + //lua_register(this->mGlobalContext, "getmetatable", AvHLUABase_Blank); + //lua_register(this->mGlobalContext, "gcinfo", AvHLUABase_Blank); + //lua_register(this->mGlobalContext, "ipairs", AvHLUABase_Blank); + lua_register(this->mGlobalContext, "loadfile", AvHLUABase_Blank); + lua_register(this->mGlobalContext, "loadlib", AvHLUABase_Blank); + lua_register(this->mGlobalContext, "loadstring", AvHLUABase_Blank); + //lua_register(this->mGlobalContext, "next", AvHLUABase_Blank); + //lua_register(this->mGlobalContext, "pairs", AvHLUABase_Blank); + //lua_register(this->mGlobalContext, "pcall", AvHLUABase_Blank); + //lua_register(this->mGlobalContext, "rawequal", AvHLUABase_Blank); + //lua_register(this->mGlobalContext, "rawget", AvHLUABase_Blank); + //lua_register(this->mGlobalContext, "rawset", AvHLUABase_Blank); + lua_register(this->mGlobalContext, "require", AvHLUABase_Blank); + //lua_register(this->mGlobalContext, "setfenv", AvHLUABase_Blank); + //lua_register(this->mGlobalContext, "setmetatable", AvHLUABase_Blank); + //lua_register(this->mGlobalContext, "tonumber", AvHLUABase_Blank); + //lua_register(this->mGlobalContext, "tostring", AvHLUABase_Blank); + //lua_register(this->mGlobalContext, "type", AvHLUABase_Blank); + //lua_register(this->mGlobalContext, "unpack", AvHLUABase_Blank); + //lua_register(this->mGlobalContext, "_VERSION", AvHLUABase_Blank); + //lua_register(this->mGlobalContext, "xpcall", AvHLUABase_Blank); +#endif + + this->RegisterNamespace_Time(); + +#ifdef AVH_SERVER + // SERVER API: common + this->RegisterNamespace_Player(); + this->RegisterNamespace_Team(); + + lua_register(this->mGlobalContext, "client", AvHLUABase_Client); + + // SERVER API: non-restricted + if (!isRestricted) + { + + } +#endif + +#ifdef AVH_CLIENT + // CLIENT API: common + + lua_register(this->mGlobalContext, "client", AvHLUABase_Blank); + + // CLIENT API: non-restricted + if (!isRestricted) + { + + } +#endif + +} + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +bool AvHLUA::LoadLUAForMap(const char *inMapName) +{ + ASSERT(this->mGlobalContext != NULL); + std::string filename; + filename = getModDirectory(); + filename += "/maps/"; + filename += inMapName; + filename += ".lua"; + std::string msg; + bool result = false; + + if (luaL_loadfile(this->mGlobalContext, filename.c_str()) || lua_pcall(this->mGlobalContext, 0, 0, 0)) + { + AvHLUA_OnError(lua_tostring(this->mGlobalContext, -1)); + } + else + { + +#ifdef AVH_SERVER + msg = "[LUA] "; +#else + msg = "[LUA CLIENT] "; +#endif + msg += LUA_VERSION; + msg += "\n[LUA] "; + msg += filename; + msg += " is loaded\n"; + + this->mLoaded = true; + result = true; + } +#ifdef AVH_SERVER + ALERT(at_console, UTIL_VarArgs("%s", msg.c_str())); +#else + gEngfuncs.pfnConsolePrint(msg.c_str()); +#endif + return result; +} + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +AvHLUA *gLUA = new AvHLUA(); \ No newline at end of file diff --git a/main/source/scriptengine/AvHLUA.h b/main/source/scriptengine/AvHLUA.h new file mode 100644 index 00000000..04248a9c --- /dev/null +++ b/main/source/scriptengine/AvHLUA.h @@ -0,0 +1,113 @@ +#ifndef AVHLUA_H +#define AVHLUA_H + +extern "C" { +#include +#include +#include +} +#ifdef AVH_CLIENT +#include "cl_dll/wrect.h" +#include "cl_dll/cl_dll.h" +#include "engine/progdefs.h" +#include "mod/AvHHud.h" +#include "common/cl_entity.h" +extern cl_enginefunc_t gEngfuncs; +extern AvHHud gHUD; +#endif + +#ifdef AVH_SERVER +#include "util/nowarnings.h" +#include "mod/AvHPlayer.h" +#include "mod/AvHMessage.h" +#include "mod/AvHParticleTemplateServer.h" +#include "mod/AvHEntities.h" +#include "mod/AvHGamerules.h" +#include "mod/AvHServerVariables.h" +#include "mod/AvHConstants.h" +#include "mod/AvHMarineWeapons.h" +#include "dlls/client.h" +#include "dlls/util.h" +#include "mod/AvHSoundListManager.h" +#include "mod/AvHServerUtil.h" +#include "mod/AvHMarineEquipment.h" +#include "mod/AvHTitles.h" +#include "mod/AvHMarineEquipmentConstants.h" +#include "mod/AvHParticleTemplate.h" +#include "common/vector_util.h" +#include "dlls/roach.h" +#include "mod/AvHSelectionHelper.h" +#include "mod/AvHPlayerUpgrade.h" +#include "mod/AvHSharedUtil.h" +#include "mod/AvHDramaticPriority.h" +#include "mod/AvHHulls.h" +#include "mod/AvHMovementUtil.h" +#include "mod/AvHAlienWeaponConstants.h" +#include "mod/AvHParticleSystemEntity.h" +#include "mod/AvHAlienAbilities.h" +#include "mod/AvHAlienAbilityConstants.h" +#include "mod/AvHAlienEquipmentConstants.h" +#include "mod/AvHMarineTurret.h" +#include "mod/AvHSiegeTurret.h" +#include "mod/AvHBlipConstants.h" +#include "mod/AvHParticleConstants.h" +#include "util/MathUtil.h" +#include "types.h" +#include "mod/AvHNetworkMessages.h" +#include "mod/AvHNexusServer.h" +#include "dlls/cbase.h" +#endif + +#include "mod/AvHConstants.h" +#include "engine/edict.h" +#include "engine/eiface.h" +#include "common/const.h" +#include +#include + +#include "scriptengine/AvHLUABase.h" + +typedef pair LUATimetableCallbackType; +typedef multimap LUATimetableType; + +class AvHLUA +{ +public: + AvHLUA(); + ~AvHLUA(); + + void Init(); + bool LoadLUAForMap(const char *inMapName); + + void OnLoad(); + void OnStart(); + void OnStarted(); + void OnJointeam(int inEntindex, AvHTeamNumber inTeamToJoin); + + bool mLoaded; + + lua_State *mGlobalContext; + + bool ExecuteCallbacks(float time); + int Suspend(lua_State *L, float delay); + int DelayedExecute(lua_State *L, float time); + +private: + + void RegisterNamespace_Time(); +#ifdef AVH_SERVER + void RegisterNamespace_Player(); + void RegisterNamespace_Team(); +#else + +#endif + + int Resume(lua_State *L, int numargs); + float mNextCallTime; + LUATimetableType mTimetable; + +}; + +extern AvHLUA *gLUA; + +#endif \ No newline at end of file diff --git a/main/source/scriptengine/AvHLUABase.cpp b/main/source/scriptengine/AvHLUABase.cpp new file mode 100644 index 00000000..d628a832 --- /dev/null +++ b/main/source/scriptengine/AvHLUABase.cpp @@ -0,0 +1,59 @@ +extern "C" { +#include +#include +#include +} +#include "scriptengine/AvHLUA.h" +#include "scriptengine/AvHLUAUtil.h" + + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// replacement: blank +int AvHLUABase_Blank(lua_State *L) +{ + return 0; +} + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// replacement: print +int AvHLUABase_Print(lua_State *L) +{ + if (lua_gettop(L) > 0) + { + std::string theConsoleString; + +#ifdef AVH_CLIENT + theConsoleString = "[LUA CLIENT] "; + theConsoleString += lua_tostring(L, 1); + theConsoleString += "\n"; + gEngfuncs.pfnConsolePrint(theConsoleString.c_str()); +#else + theConsoleString = "[LUA] "; + theConsoleString += lua_tostring(L, 1); + theConsoleString += "\n"; + ALERT(at_console, UTIL_VarArgs("%s", theConsoleString.c_str())); +#endif + + } + return 0; +} + + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +int AvHLUABase_Client(lua_State *L) +{ +#ifdef AVH_SERVER + luaL_checktype(L, 1, LUA_TNUMBER); + CBaseEntity* theEntity = CBaseEntity::Instance(g_engfuncs.pfnPEntityOfEntIndex(lua_tonumber(L, 1))); + + if (theEntity && theEntity->IsPlayer()) + NetMsg_LUAMessage(theEntity->pev, L); + else + int a = 0; // TODO: ADD ERROR CHECK + + return 0; +#endif +#ifdef AVH_CLIENT + return 0; +#endif +} \ No newline at end of file diff --git a/main/source/scriptengine/AvHLUABase.h b/main/source/scriptengine/AvHLUABase.h new file mode 100644 index 00000000..76b2622e --- /dev/null +++ b/main/source/scriptengine/AvHLUABase.h @@ -0,0 +1,14 @@ +#ifndef AVHLUABASE_H +#define AVHLUABASE_H + +extern "C" { +#include +#include +#include +} + +int AvHLUABase_Blank(lua_State *L); +int AvHLUABase_Print(lua_State *L); +int AvHLUABase_Client(lua_State *L); + +#endif \ No newline at end of file diff --git a/main/source/scriptengine/AvHLUAServerEntity.cpp b/main/source/scriptengine/AvHLUAServerEntity.cpp new file mode 100644 index 00000000..d15bb778 --- /dev/null +++ b/main/source/scriptengine/AvHLUAServerEntity.cpp @@ -0,0 +1,66 @@ +// --------------------------------------------------------------------- +// SERVER ENTITY +extern "C" { +#include +#include +#include +} +#include "scriptengine/AvHLUA.h" +#include "scriptengine/AvHLUAUtil.h" + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +static int AvHLUAEntity_IsPlayer(lua_State *L) +{ + int entindex = luaL_checkint(L, 1); + CBaseEntity* theEntity = CBaseEntity::Instance(g_engfuncs.pfnPEntityOfEntIndex(entindex)); + // TODO: Errorcheck- and handling + if (theEntity) + lua_pushboolean(L, theEntity->IsPlayer()); + return 1; +} + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +static int AvHLUAEntity_GetPlayer(lua_State *L) +{ + int entindex = luaL_checkint(L, 1); + // TODO: Optimization based on entindex? + CBaseEntity* theEntity = CBaseEntity::Instance(g_engfuncs.pfnPEntityOfEntIndex(entindex)); + if (theEntity && theEntity->IsPlayer()) + lua_pushnumber(L, entindex); + else + // TODO: Error + lua_pushnumber(L, 0); + return 1; +} + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +static int AvHLUAEntity_Name(lua_State *L) +{ + int entindex = luaL_checkint(L, 1); + CBaseEntity* theEntity = CBaseEntity::Instance(g_engfuncs.pfnPEntityOfEntIndex(entindex)); + // TODO: Errorcheck and handling + if (theEntity && theEntity->pev->netname) + lua_pushstring(L, STRING(theEntity->pev->netname)); + else + lua_pushstring(L, "unnamed"); + return 1; +} + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +static const luaL_reg meta_methods [] = { + {0,0} +}; + +static const luaL_reg player_methods [] = { + {"IsPlayer", AvHLUAEntity_IsPlayer}, + {"GetPlayer", AvHLUAEntity_GetPlayer}, + {"Name", AvHLUAEntity_Name}, + {0,0} +}; + + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +void AvHLUA::RegisterNamespace_Player() +{ + UTIL_LUARegisterObject(this->mGlobalContext, player_methods, meta_methods, "Player"); +} \ No newline at end of file diff --git a/main/source/scriptengine/AvHLUAServerEvents.cpp b/main/source/scriptengine/AvHLUAServerEvents.cpp new file mode 100644 index 00000000..7aaf2344 --- /dev/null +++ b/main/source/scriptengine/AvHLUAServerEvents.cpp @@ -0,0 +1,60 @@ +// --------------------------------------------------------------------- +// SERVER EVENTS +extern "C" { +#include +#include +#include +} +#include "scriptengine/AvHLUA.h" +#include "scriptengine/AvHLUAUtil.h" + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +void AvHLUA::OnLoad() +{ + if (this->mLoaded) + { + lua_getglobal(this->mGlobalContext, "OnLoad"); + AvHLUA_Pcall(this->mGlobalContext, 0, 0); + } +} + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +void AvHLUA::OnStart() +{ + if (this->mLoaded) + { + lua_getglobal(this->mGlobalContext, "OnStart"); + AvHLUA_Pcall(this->mGlobalContext, 0, 0); + } +} + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +void AvHLUA::OnStarted() +{ + if (this->mLoaded) + { + lua_getglobal(this->mGlobalContext, "OnStarted"); + AvHLUA_Pcall(this->mGlobalContext, 0, 0); + } +} + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +void AvHLUA::OnJointeam(int inEntindex, AvHTeamNumber inTeamToJoin) +{ + if (this->mLoaded) + { + lua_State *threadState = lua_newthread(this->mGlobalContext); + lua_getglobal(threadState, "OnJointeam"); + lua_pushnumber(threadState, inEntindex); + lua_pushnumber(threadState, (int)(inTeamToJoin)); + if (int errorcode = lua_resume(threadState, 2)) + { + AvHLUA_OnError(lua_tostring(threadState, -1)); + } + else + { + // all values returned are on the stack + } + } +} +// --------------------------------------------------------------------- \ No newline at end of file diff --git a/main/source/scriptengine/AvHLUAServerTeam.cpp b/main/source/scriptengine/AvHLUAServerTeam.cpp new file mode 100644 index 00000000..af620512 --- /dev/null +++ b/main/source/scriptengine/AvHLUAServerTeam.cpp @@ -0,0 +1,15 @@ +// --------------------------------------------------------------------- +// SERVER TEAM +extern "C" { +#include +#include +#include +} +#include "scriptengine/AvHLUA.h" +#include "scriptengine/AvHLUAUtil.h" + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +void AvHLUA::RegisterNamespace_Team() +{ + +} diff --git a/main/source/scriptengine/AvHLUATime.cpp b/main/source/scriptengine/AvHLUATime.cpp new file mode 100644 index 00000000..7a5513e8 --- /dev/null +++ b/main/source/scriptengine/AvHLUATime.cpp @@ -0,0 +1,164 @@ +extern "C" { +#include +#include +#include +} +#include "scriptengine/AvHLUA.h" +#include "scriptengine/AvHLUAUtil.h" + +#ifdef AVH_CLIENT +extern double gClientTimeLastUpdate; +#endif + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +static int AvHLUATime_Now(lua_State *L) +{ +#ifdef AVH_SERVER + float now = gpGlobals->time; +#else + float now = gClientTimeLastUpdate; +#endif + + lua_pushnumber(L, (float)(now)); + return 1; +} + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +static int AvHLUATime_Sleep(lua_State *L) +{ + float sleeptime = (float)(luaL_checknumber(L, 1)); + if (sleeptime > 0) + { + return gLUA->Suspend(L, sleeptime); + } + else + { + return gLUA->Suspend(L, 0); + } +} + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +static int AvHLUATime_At(lua_State *L) +{ + float time = (float)(luaL_checknumber(L, 1)); + luaL_checktype(L, 2, LUA_TSTRING); + + gLUA->DelayedExecute(L, time); + return 0; +} + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +static const luaL_reg meta_methods [] = { + {0,0} +}; + +static const luaL_reg time_methods [] = { + {"Now", AvHLUATime_Now}, + {"Sleep", AvHLUATime_Sleep}, + {"At", AvHLUATime_At}, + {0,0} +}; + +void AvHLUA::RegisterNamespace_Time() +{ + UTIL_LUARegisterObject(this->mGlobalContext, time_methods, meta_methods, "Time"); +} + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +int AvHLUA::DelayedExecute(lua_State *L, float time) +{ + int args = lua_gettop(L) - 2; + lua_State *threadContext = lua_newthread(L); + lua_getglobal(threadContext, lua_tostring(L, 2)); + + if (args > 0) + { + lua_xmove(L, threadContext, args + 1); + lua_pop(threadContext, 1); + } + + this->mTimetable.insert(pair((float)(time), LUATimetableCallbackType(args, threadContext))); + + LUATimetableType::iterator firstCall = this->mTimetable.begin(); + this->mNextCallTime = (float)((*firstCall).first); + + return 0; +} + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +int AvHLUA::Suspend(lua_State *L, float delay) +{ +#ifdef AVH_SERVER + float now = gpGlobals->time; +#else + float now = gClientTimeLastUpdate; +#endif + this->mTimetable.insert(pair((float)(now + delay), LUATimetableCallbackType(0, L))); + + LUATimetableType::iterator firstCall = this->mTimetable.begin(); + this->mNextCallTime = (float)((*firstCall).first); + + return (lua_yield(L, 0)); +} + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +int AvHLUA::Resume(lua_State *L, int numargs) +{ + int errorcode = lua_resume(L, numargs); + if (errorcode) + { + AvHLUA_OnError(lua_tostring(L, -1)); + } + return errorcode; +} + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +bool AvHLUA::ExecuteCallbacks(float time) +{ + if (time < this->mNextCallTime) + return false; + + LUATimetableType::iterator TimetableStart = this->mTimetable.begin(); + LUATimetableType::iterator TimetableEnd = this->mTimetable.end(); + + list eraseList; + + LUATimetableType::iterator current = TimetableStart; + while (current != TimetableEnd) + { + float calltime = (float)((*current).first); + if (calltime < time) + { + LUATimetableCallbackType callbackfunc = (*current).second; + int numargs = callbackfunc.first; + lua_State *L = callbackfunc.second; + this->Resume(L, numargs); + + eraseList.push_back(current); + + current++; + } + else + { + this->mNextCallTime = calltime; + break; + } + } + if (current == TimetableEnd) + { +#ifdef AVH_SERVER + this->mNextCallTime = gpGlobals->time + 99999; +#else + this->mNextCallTime = gClientTimeLastUpdate + 99999; +#endif + } + + while (eraseList.size() > 0) + { + LUATimetableType::iterator toErase = eraseList.front(); + this->mTimetable.erase(toErase); + eraseList.pop_front(); + } + + return true; +} \ No newline at end of file diff --git a/main/source/scriptengine/AvHLUAUtil.cpp b/main/source/scriptengine/AvHLUAUtil.cpp new file mode 100644 index 00000000..537d6e57 --- /dev/null +++ b/main/source/scriptengine/AvHLUAUtil.cpp @@ -0,0 +1,73 @@ +extern "C" { +#include +#include +#include +} +#include "scriptengine/AvHLUAUtil.h" +#include "scriptengine/AvHLUA.h" +extern AvHLUA *gLUA; + +/* +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +void UTIL_LUATablePair(char *key, const char *value) +{ + lua_pushstring(gLUA->mGlobalContext, key); + lua_pushstring(gLUA->mGlobalContext, value); + lua_settable(gLUA->mGlobalContext, -3); +} + +void UTIL_LUATablePair(char *key, lua_Number value) +{ + lua_pushstring(gLUA->mGlobalContext, key); + lua_pushnumber(gLUA->mGlobalContext, value); + lua_settable(gLUA->mGlobalContext, -3); +} + +void UTIL_LUATablePair(char *key, bool value) +{ + lua_pushstring(gLUA->mGlobalContext, key); + lua_pushboolean(gLUA->mGlobalContext, value); + lua_settable(gLUA->mGlobalContext, -3); +} + +void UTIL_LUATablePair(char *key, lua_CFunction function) +{ + lua_pushstring(gLUA->mGlobalContext, key); + lua_pushcfunction(gLUA->mGlobalContext, function); + lua_settable(gLUA->mGlobalContext, -3); +} +*/ + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +void UTIL_LUARegisterObject(lua_State *L, const luaL_reg *mainmethods, const luaL_reg *metamethods, char *objName) +{ + lua_pushstring(L, objName); + int methods = newtable(L); + int metatable = newtable(L); + lua_pushliteral(L, "__index"); + lua_pushvalue(L, methods); + lua_settable(L, metatable); + lua_pushliteral(L, "__metatable"); + lua_pushvalue(L, methods); + lua_settable(L, metatable); + luaL_openlib(L, 0, metamethods, 0); + luaL_openlib(L, 0, mainmethods, 1); + lua_settable(L, LUA_GLOBALSINDEX); +} + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +void AvHLUA_OnError(const char *errorMsg) +{ + std::string msg; +#ifdef AVH_CLIENT + msg = "[LUA CLIENT] Error: "; + msg += errorMsg; + msg += "\n"; + gEngfuncs.pfnConsolePrint(msg.c_str()); +#else + msg += "[LUA] Error: "; + msg += errorMsg; + msg += "\n"; + ALERT(at_console, UTIL_VarArgs("%s", msg.c_str())); +#endif +} diff --git a/main/source/scriptengine/AvHLUAUtil.h b/main/source/scriptengine/AvHLUAUtil.h new file mode 100644 index 00000000..1cd8ee86 --- /dev/null +++ b/main/source/scriptengine/AvHLUAUtil.h @@ -0,0 +1,29 @@ +#ifndef AVHLUAUTIL_H +#define AVHLUAUTIL_H + +extern "C" { +#include +#include +#include +} + +#define newtable(L) (lua_newtable(L), lua_gettop(L)) + +/* +void UTIL_LUATablePair(char *key, const char *value); +void UTIL_LUATablePair(char *key, lua_Number value); +void UTIL_LUATablePair(char *key, bool value); +void UTIL_LUATablePair(char *key, lua_CFunction function); +*/ + +void UTIL_LUARegisterObject(lua_State *L, const luaL_reg *mainmethods, const luaL_reg *metamethods, char *objName); + +void AvHLUA_OnError(const char *errorMsg); +#define AvHLUA_Pcall(L, a, b) \ + if (lua_pcall(L, a, b, 0)) \ + { \ + AvHLUA_OnError(lua_tostring(L, -1)); \ + } + + +#endif \ No newline at end of file