diff --git a/Client/game_sa/CGameSA.cpp b/Client/game_sa/CGameSA.cpp index 4a90d6a5756..b8c713c1e18 100644 --- a/Client/game_sa/CGameSA.cpp +++ b/Client/game_sa/CGameSA.cpp @@ -836,6 +836,11 @@ void CGameSA::ResetModelLodDistances() CModelInfoSA::StaticResetLodDistances(); } +void CGameSA::ResetModelTimes() +{ + CModelInfoSA::StaticResetModelTimes(); +} + void CGameSA::ResetAlphaTransparencies() { CModelInfoSA::StaticResetAlphaTransparencies(); diff --git a/Client/game_sa/CGameSA.h b/Client/game_sa/CGameSA.h index 972e672004c..e715d726ef2 100644 --- a/Client/game_sa/CGameSA.h +++ b/Client/game_sa/CGameSA.h @@ -417,6 +417,7 @@ class CGameSA : public CGame void ResetModelLodDistances(); void ResetAlphaTransparencies(); void DisableVSync(); + void ResetModelTimes(); void OnPedContextChange(CPed* pPedContext); CPed* GetPedContext(); diff --git a/Client/game_sa/CModelInfoSA.cpp b/Client/game_sa/CModelInfoSA.cpp index ad03cc8b524..841786d7241 100644 --- a/Client/game_sa/CModelInfoSA.cpp +++ b/Client/game_sa/CModelInfoSA.cpp @@ -20,6 +20,7 @@ std::map std::map CModelInfoSA::ms_ModelDefaultLodDistanceMap; std::map CModelInfoSA::ms_ModelDefaultAlphaTransparencyMap; std::unordered_map> CModelInfoSA::ms_ModelDefaultDummiesPosition; +std::map CModelInfoSA::ms_ModelDefaultModelTimeInfo; std::unordered_map CModelInfoSA::ms_OriginalObjectPropertiesGroups; CModelInfoSA::CModelInfoSA() @@ -562,6 +563,51 @@ float CModelInfoSA::GetLODDistance() return 0.0f; } +bool CModelInfoSA::SetTime(char cHourOn, char cHourOff) +{ + m_pInterface = ppModelInfo[m_dwModelID]; + if (!m_pInterface) + return false; + + TimeInfo* pTime = ((TimeInfo*(*)(void))m_pInterface->VFTBL->GetTimeInfo)(); + if (!pTime) + return false; + + if (!MapContains(ms_ModelDefaultModelTimeInfo, pTime)) + MapSet(ms_ModelDefaultModelTimeInfo, pTime, new TimeInfo(pTime->m_nTimeOn, pTime->m_nTimeOff, pTime->m_wOtherTimeModel)); + + pTime->m_nTimeOn = cHourOn; + pTime->m_nTimeOff = cHourOff; + return true; +} + +bool CModelInfoSA::GetTime(char& cHourOn, char& cHourOff) +{ + m_pInterface = ppModelInfo[m_dwModelID]; + if (!m_pInterface) + return false; + + TimeInfo* time = ((TimeInfo*(*)(void))m_pInterface->VFTBL->GetTimeInfo)(); + if (!time) + return false; + + cHourOn = time->m_nTimeOn; + cHourOff = time->m_nTimeOff; + return true; +} + +void CModelInfoSA::StaticResetModelTimes() +{ + // Restore default values + for (std::map::const_iterator iter = ms_ModelDefaultModelTimeInfo.begin(); iter != ms_ModelDefaultModelTimeInfo.end(); ++iter) + { + iter->first->m_nTimeOn = iter->second->m_nTimeOn; + iter->first->m_nTimeOff = iter->second->m_nTimeOff; + } + + ms_ModelDefaultModelTimeInfo.clear(); +} + float CModelInfoSA::GetOriginalLODDistance() { // Return default LOD distance value (if doesn't exist, LOD distance hasn't been changed) @@ -1440,7 +1486,7 @@ bool CModelInfoSA::IsTowableBy(CModelInfo* towingModel) const bool isTowTruck = towingModel->GetModel() == 525; const bool isTractor = towingModel->GetModel() == 531; - + if (IsTrain() || towingModel->IsTrain()) { // A train is never towing other vehicles. Trains are linked by other means diff --git a/Client/game_sa/CModelInfoSA.h b/Client/game_sa/CModelInfoSA.h index c046a71e863..f60613d1567 100644 --- a/Client/game_sa/CModelInfoSA.h +++ b/Client/game_sa/CModelInfoSA.h @@ -268,6 +268,7 @@ class CModelInfoSA : public CModelInfo static std::map ms_ModelDefaultLodDistanceMap; static std::map ms_ModelDefaultAlphaTransparencyMap; static std::unordered_map> ms_ModelDefaultDummiesPosition; + static std::map ms_ModelDefaultModelTimeInfo; static std::unordered_map ms_OriginalObjectPropertiesGroups; bool m_bAddedRefForCollision; SVehicleSupportedUpgrades m_ModelSupportedUpgrades; @@ -319,6 +320,9 @@ class CModelInfoSA : public CModelInfo void RestreamIPL(); static void StaticFlushPendingRestreamIPL(); static void StaticSetHooks(); + bool GetTime(char& cHourOn, char& cHourOff); + bool SetTime(char cHourOn, char cHourOff); + static void StaticResetModelTimes(); void SetAlphaTransparencyEnabled(BOOL bEnabled); bool IsAlphaTransparencyEnabled(); diff --git a/Client/mods/deathmatch/logic/CClientGame.cpp b/Client/mods/deathmatch/logic/CClientGame.cpp index 7428ad334a9..e38df4739e9 100644 --- a/Client/mods/deathmatch/logic/CClientGame.cpp +++ b/Client/mods/deathmatch/logic/CClientGame.cpp @@ -3554,6 +3554,7 @@ void CClientGame::Event_OnIngame() g_pGame->ResetModelLodDistances(); g_pGame->ResetAlphaTransparencies(); + g_pGame->ResetModelTimes(); // Make sure we can access all areas g_pGame->GetStats()->ModifyStat(CITIES_PASSED, 2.0); diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.cpp index 78ef1831be8..016af4eb1a7 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.cpp @@ -37,6 +37,8 @@ void CLuaEngineDefs::LoadFunctions() {"engineGetModelIDFromName", EngineGetModelIDFromName}, {"engineGetModelTextureNames", EngineGetModelTextureNames}, {"engineGetVisibleTextureNames", EngineGetVisibleTextureNames}, + {"engineSetModelVisibleTime", EngineSetModelVisibleTime}, + {"engineGetModelVisibleTime", EngineGetModelVisibleTime}, {"engineGetModelTextures", EngineGetModelTextures}, {"engineGetSurfaceProperties", EngineGetSurfaceProperties}, {"engineSetSurfaceProperties", EngineSetSurfaceProperties}, @@ -72,6 +74,7 @@ void CLuaEngineDefs::AddClass(lua_State* luaVM) lua_classfunction(luaVM, "setAsynchronousLoading", "engineSetAsynchronousLoading"); lua_classfunction(luaVM, "setModelLODDistance", "engineSetModelLODDistance"); lua_classfunction(luaVM, "resetModelLODDistance", "engineResetModelLODDistance"); + lua_classfunction(luaVM, "setModelVisibleTime", "engineSetModelVisibleTime"); lua_classfunction(luaVM, "getVisibleTextureNames", "engineGetVisibleTextureNames"); lua_classfunction(luaVM, "getModelLODDistance", "engineGetModelLODDistance"); @@ -79,6 +82,7 @@ void CLuaEngineDefs::AddClass(lua_State* luaVM) lua_classfunction(luaVM, "getModelTextures", "engineGetModelTextures"); lua_classfunction(luaVM, "getModelIDFromName", "engineGetModelIDFromName"); lua_classfunction(luaVM, "getModelNameFromID", "engineGetModelNameFromID"); + lua_classfunction(luaVM, "getModelVisibleTime", "engineGetModelVisibleTime"); lua_classfunction(luaVM, "getModelPhysicalPropertiesGroup", "engineGetModelPhysicalPropertiesGroup"); lua_classfunction(luaVM, "setModelPhysicalPropertiesGroup", "engineSetModelPhysicalPropertiesGroup"); lua_classfunction(luaVM, "restoreModelPhysicalPropertiesGroup", "engineRestoreModelPhysicalPropertiesGroup"); @@ -231,7 +235,7 @@ int CLuaEngineDefs::EngineLoadDFF(lua_State* luaVM) } SString filePath; - + if (bIsRawData || CResourceManager::ParseResourcePathInput(input, pResource, &filePath)) { // Grab the resource root entity @@ -1100,6 +1104,77 @@ int CLuaEngineDefs::EngineGetVisibleTextureNames(lua_State* luaVM) return 1; } +int CLuaEngineDefs::EngineSetModelVisibleTime(lua_State* luaVM) +{ + // bool engineSetModelVisibleTime ( int/string modelID, int hourOn, int hourOff ) + SString strModelId; + char cHourOn,cHourOff; + CScriptArgReader argStream(luaVM); + argStream.ReadString(strModelId); + argStream.ReadNumber(cHourOn); + argStream.ReadNumber(cHourOff); + + if (!argStream.HasErrors()) + { + ushort usModelID = CModelNames::ResolveModelID(strModelId); + CModelInfo* pModelInfo = g_pGame->GetModelInfo(usModelID); + if (pModelInfo) + { + if (cHourOn > cHourOff) + std::swap(cHourOn, cHourOff); + + if (cHourOn >= 0 && cHourOn <= 24 && cHourOff >= 0 && cHourOff <= 24) + { + lua_pushboolean(luaVM, pModelInfo->SetTime(cHourOn, cHourOff)); + return 1; + } + } + } + else + luaL_error(luaVM, argStream.GetFullErrorMessage()); + + // Failed + lua_pushboolean(luaVM, false); + return 1; +} + +int CLuaEngineDefs::EngineGetModelVisibleTime(lua_State* luaVM) +{ + // int, int engineGetModelVisibleTime ( int/string modelID ) + SString strModelId; + + CScriptArgReader argStream(luaVM); + argStream.ReadString(strModelId); + + if (!argStream.HasErrors()) + { + ushort usModelID = CModelNames::ResolveModelID(strModelId); + CModelInfo* pModelInfo = g_pGame->GetModelInfo(usModelID); + if (pModelInfo) + { + char cHourOn, cHourOff; + if (pModelInfo->GetTime(cHourOn, cHourOff)) + { + lua_pushnumber(luaVM, cHourOn); + lua_pushnumber(luaVM, cHourOff); + return 2; + } + else // Model is incompatible, don't let confuse user. + { + lua_pushnumber(luaVM, 0); + lua_pushnumber(luaVM, 24); + return 2; + } + } + } + else + luaL_error(luaVM, argStream.GetFullErrorMessage()); + + // Failed + lua_pushboolean(luaVM, false); + return 1; +} + int CLuaEngineDefs::EngineGetModelTextures(lua_State* luaVM) { // table engineGetModelTextures ( string/int modelName/modelID, string/table textureNames ) @@ -1568,7 +1643,7 @@ int CLuaEngineDefs::EngineGetModelPhysicalPropertiesGroup(lua_State* luaVM) } argStream.SetCustomError("Expected valid model ID at argument 1"); } - + return luaL_error(luaVM, argStream.GetFullErrorMessage()); } @@ -1605,7 +1680,7 @@ int CLuaEngineDefs::EngineSetModelPhysicalPropertiesGroup(lua_State* luaVM) } argStream.SetCustomError("Expected valid model ID at argument 1"); } - + return luaL_error(luaVM, argStream.GetFullErrorMessage()); } @@ -1634,7 +1709,7 @@ int CLuaEngineDefs::EngineRestoreModelPhysicalPropertiesGroup(lua_State* luaVM) } argStream.SetCustomError("Expected valid model ID at argument 1"); } - + return luaL_error(luaVM, argStream.GetFullErrorMessage()); } @@ -1818,7 +1893,7 @@ int CLuaEngineDefs::EngineSetObjectGroupPhysicalProperty(lua_State* luaVM) } } } - + return luaL_error(luaVM, argStream.GetFullErrorMessage()); } diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.h b/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.h index 1999e72d5de..9214535f0c7 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.h +++ b/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.h @@ -47,6 +47,8 @@ class CLuaEngineDefs : public CLuaDefs LUA_DECLARE(EngineGetModelIDFromName); LUA_DECLARE(EngineGetModelTextureNames); LUA_DECLARE(EngineGetVisibleTextureNames); + LUA_DECLARE(EngineSetModelVisibleTime); + LUA_DECLARE(EngineGetModelVisibleTime); LUA_DECLARE(EngineGetModelTextures); LUA_DECLARE(EngineSetSurfaceProperties); LUA_DECLARE(EngineGetSurfaceProperties); diff --git a/Client/sdk/game/CGame.h b/Client/sdk/game/CGame.h index 1ab81fdd37c..662753c810f 100644 --- a/Client/sdk/game/CGame.h +++ b/Client/sdk/game/CGame.h @@ -239,6 +239,7 @@ class __declspec(novtable) CGame virtual void ResetModelLodDistances() = 0; virtual void ResetAlphaTransparencies() = 0; virtual void DisableVSync() = 0; + virtual void ResetModelTimes() = 0; virtual void OnPedContextChange(CPed* pPedContext) = 0; virtual CPed* GetPedContext() = 0; diff --git a/Client/sdk/game/CModelInfo.h b/Client/sdk/game/CModelInfo.h index 93568f949ba..06d14799636 100644 --- a/Client/sdk/game/CModelInfo.h +++ b/Client/sdk/game/CModelInfo.h @@ -129,6 +129,8 @@ class CModelInfo virtual float GetOriginalLODDistance() = 0; virtual void SetLODDistance(float fDistance, bool bOverrideMaxDistance = false) = 0; virtual void RestreamIPL() = 0; + virtual bool GetTime(char& hourOn, char& hourOff) = 0; + virtual bool SetTime(char hourOn, char hourOff) = 0; virtual void ModelAddRef(EModelRequestType requestType, const char* szTag /* = NULL*/) = 0; virtual void RemoveRef(bool bRemoveExtraGTARef = false) = 0; diff --git a/Client/sdk/game/RenderWare.h b/Client/sdk/game/RenderWare.h index 8a0e73e3910..9e13e817711 100644 --- a/Client/sdk/game/RenderWare.h +++ b/Client/sdk/game/RenderWare.h @@ -424,3 +424,10 @@ struct RwError { int err1, err2; }; + +struct TimeInfo { + TimeInfo(char timeOn, char timeOff, short OtherTimeModel) : m_nTimeOn(timeOn), m_nTimeOff(timeOff), m_wOtherTimeModel(OtherTimeModel) {}; + char m_nTimeOn; + char m_nTimeOff; + short m_wOtherTimeModel; +};