diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index be85feb5d8..7da3cd78fe 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -65,6 +65,7 @@ #include "mwsound/soundmanagerimp.hpp" #include "mwworld/class.hpp" +#include "mwworld/datetimemanager.hpp" #include "mwworld/worldimp.hpp" #include "mwrender/vismask.hpp" @@ -239,7 +240,7 @@ bool OMW::Engine::frame(float frametime) if (!guiActive) { - double hours = (frametime * mWorld->getTimeScaleFactor()) / 3600.0; + double hours = (frametime * mWorld->getTimeManager()->getGameTimeScale()) / 3600.0; mWorld->advanceTime(hours, true); mWorld->rechargeItems(frametime, true); } @@ -935,7 +936,7 @@ void OMW::Engine::go() const double dt = std::chrono::duration_cast>( std::min(frameRateLimiter.getLastFrameDuration(), maxSimulationInterval)) .count() - * mEnvironment.getWorld()->getSimulationTimeScale(); + * mWorld->getTimeManager()->getSimulationTimeScale(); mViewer->advance(simulationTime); diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 6f40ff7031..40d57cbb6e 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -92,6 +92,7 @@ namespace MWWorld class ESMStore; class RefData; class Cell; + class DateTimeManager; typedef std::vector> PtrMovementList; } @@ -209,15 +210,9 @@ namespace MWBase virtual void advanceTime(double hours, bool incremental = false) = 0; ///< Advance in-game time. - virtual std::string_view getMonthName(int month = -1) const = 0; - ///< Return name of month (-1: current month) - virtual MWWorld::TimeStamp getTimeStamp() const = 0; ///< Return current in-game time and number of day since new game start. - virtual ESM::EpochTimeStamp getEpochTimeStamp() const = 0; - ///< Return current in-game date and time. - virtual bool toggleSky() = 0; ///< \return Resulting mode @@ -239,12 +234,6 @@ namespace MWBase virtual void modRegion(const ESM::RefId& regionid, const std::vector& chances) = 0; - virtual float getTimeScaleFactor() const = 0; - - virtual float getSimulationTimeScale() const = 0; - - virtual void setSimulationTimeScale(float scale) = 0; - virtual void changeToInteriorCell( std::string_view cellName, const ESM::Position& position, bool adjustPlayerPos, bool changeEvent = true) = 0; @@ -612,6 +601,8 @@ namespace MWBase virtual MWRender::PostProcessor* getPostProcessor() = 0; + virtual MWWorld::DateTimeManager* getTimeManager() = 0; + virtual void setActorActive(const MWWorld::Ptr& ptr, bool value) = 0; }; } diff --git a/apps/openmw/mwgui/journalviewmodel.cpp b/apps/openmw/mwgui/journalviewmodel.cpp index 57c768aeac..46f77f6dc4 100644 --- a/apps/openmw/mwgui/journalviewmodel.cpp +++ b/apps/openmw/mwgui/journalviewmodel.cpp @@ -13,6 +13,7 @@ #include "../mwbase/world.hpp" #include "../mwdialogue/keywordsearch.hpp" +#include "../mwworld/datetimemanager.hpp" namespace MWGui { @@ -253,8 +254,9 @@ namespace MWGui std::ostringstream os; - os << itr->mDayOfMonth << ' ' << MWBase::Environment::get().getWorld()->getMonthName(itr->mMonth) - << " (" << dayStr << " " << (itr->mDay) << ')'; + os << itr->mDayOfMonth << ' ' + << MWBase::Environment::get().getWorld()->getTimeManager()->getMonthName(itr->mMonth) << " (" + << dayStr << " " << (itr->mDay) << ')'; timestamp_buffer = os.str(); } diff --git a/apps/openmw/mwgui/savegamedialog.cpp b/apps/openmw/mwgui/savegamedialog.cpp index 53136743d9..71b39328f6 100644 --- a/apps/openmw/mwgui/savegamedialog.cpp +++ b/apps/openmw/mwgui/savegamedialog.cpp @@ -29,6 +29,7 @@ #include "../mwbase/statemanager.hpp" #include "../mwbase/windowmanager.hpp" #include "../mwbase/world.hpp" +#include "../mwworld/datetimemanager.hpp" #include "../mwworld/esmstore.hpp" #include "../mwstate/character.hpp" @@ -422,8 +423,9 @@ namespace MWGui hour = 12; text << mCurrentSlot->mProfile.mInGameTime.mDay << " " - << MWBase::Environment::get().getWorld()->getMonthName(mCurrentSlot->mProfile.mInGameTime.mMonth) << " " - << hour << " " << (pm ? "#{Calendar:pm}" : "#{Calendar:am}"); + << MWBase::Environment::get().getWorld()->getTimeManager()->getMonthName( + mCurrentSlot->mProfile.mInGameTime.mMonth) + << " " << hour << " " << (pm ? "#{Calendar:pm}" : "#{Calendar:am}"); if (Settings::Manager::getBool("timeplayed", "Saves")) { diff --git a/apps/openmw/mwgui/waitdialog.cpp b/apps/openmw/mwgui/waitdialog.cpp index 0c93773278..ab17031168 100644 --- a/apps/openmw/mwgui/waitdialog.cpp +++ b/apps/openmw/mwgui/waitdialog.cpp @@ -19,6 +19,7 @@ #include "../mwworld/cellstore.hpp" #include "../mwworld/class.hpp" +#include "../mwworld/datetimemanager.hpp" #include "../mwworld/esmstore.hpp" #include "../mwmechanics/actorutil.hpp" @@ -154,17 +155,17 @@ namespace MWGui onHourSliderChangedPosition(mHourSlider, 0); mHourSlider->setScrollPosition(0); - std::string_view month = MWBase::Environment::get().getWorld()->getMonthName(); - int hour = static_cast(MWBase::Environment::get().getWorld()->getTimeStamp().getHour()); + const MWWorld::DateTimeManager& timeManager = *MWBase::Environment::get().getWorld()->getTimeManager(); + std::string_view month = timeManager.getMonthName(); + int hour = static_cast(timeManager.getTimeStamp().getHour()); bool pm = hour >= 12; if (hour >= 13) hour -= 12; if (hour == 0) hour = 12; - ESM::EpochTimeStamp currentDate = MWBase::Environment::get().getWorld()->getEpochTimeStamp(); - std::string daysPassed = Misc::StringUtils::format( - "(#{Calendar:day} %i)", MWBase::Environment::get().getWorld()->getTimeStamp().getDay()); + ESM::EpochTimeStamp currentDate = timeManager.getEpochTimeStamp(); + std::string daysPassed = Misc::StringUtils::format("(#{Calendar:day} %i)", timeManager.getTimeStamp().getDay()); std::string_view formattedHour(pm ? "#{Calendar:pm}" : "#{Calendar:am}"); std::string dateTimeText = Misc::StringUtils::format("%i %s %s %i %s", currentDate.mDay, month, daysPassed, hour, formattedHour); diff --git a/apps/openmw/mwlua/luabindings.cpp b/apps/openmw/mwlua/luabindings.cpp index 2a4368810c..5e9da7e6b9 100644 --- a/apps/openmw/mwlua/luabindings.cpp +++ b/apps/openmw/mwlua/luabindings.cpp @@ -20,6 +20,7 @@ #include "../mwbase/statemanager.hpp" #include "../mwworld/action.hpp" #include "../mwworld/class.hpp" +#include "../mwworld/datetimemanager.hpp" #include "../mwworld/esmstore.hpp" #include "../mwworld/manualref.hpp" #include "../mwworld/store.hpp" @@ -61,12 +62,12 @@ namespace MWLua static void addTimeBindings(sol::table& api, const Context& context, bool global) { - MWBase::World* world = MWBase::Environment::get().getWorld(); + MWWorld::DateTimeManager* timeManager = MWBase::Environment::get().getWorld()->getTimeManager(); - api["getSimulationTime"] = [world = context.mWorldView]() { return world->getSimulationTime(); }; - api["getSimulationTimeScale"] = [world]() { return world->getSimulationTimeScale(); }; - api["getGameTime"] = [world = context.mWorldView]() { return world->getGameTime(); }; - api["getGameTimeScale"] = [world = context.mWorldView]() { return world->getGameTimeScale(); }; + api["getSimulationTime"] = [timeManager]() { return timeManager->getSimulationTime(); }; + api["getSimulationTimeScale"] = [timeManager]() { return timeManager->getSimulationTimeScale(); }; + api["getGameTime"] = [timeManager]() { return timeManager->getGameTime(); }; + api["getGameTimeScale"] = [timeManager]() { return timeManager->getGameTimeScale(); }; api["isWorldPaused"] = [world = context.mWorldView]() { return world->isPaused(); }; api["getRealTime"] = []() { return std::chrono::duration(std::chrono::steady_clock::now().time_since_epoch()).count(); @@ -75,10 +76,9 @@ namespace MWLua if (!global) return; - api["setGameTimeScale"] = [world = context.mWorldView](double scale) { world->setGameTimeScale(scale); }; - - api["setSimulationTimeScale"] = [context, world](float scale) { - context.mLuaManager->addAction([scale, world] { world->setSimulationTimeScale(scale); }); + api["setGameTimeScale"] = [timeManager](double scale) { timeManager->setGameTimeScale(scale); }; + api["setSimulationTimeScale"] = [context, timeManager](float scale) { + context.mLuaManager->addAction([scale, timeManager] { timeManager->setSimulationTimeScale(scale); }); }; // TODO: Ability to pause/resume world from Lua (needed for UI dehardcoding) @@ -291,11 +291,11 @@ namespace MWLua std::map initCommonPackages(const Context& context) { sol::state_view lua = context.mLua->sol(); - WorldView* w = context.mWorldView; + MWWorld::DateTimeManager* tm = MWBase::Environment::get().getWorld()->getTimeManager(); return { { "openmw.async", LuaUtil::getAsyncPackageInitializer( - lua, [w] { return w->getSimulationTime(); }, [w] { return w->getGameTime(); }) }, + lua, [tm] { return tm->getSimulationTime(); }, [tm] { return tm->getGameTime(); }) }, { "openmw.core", initCorePackage(context) }, { "openmw.types", initTypesPackage(context) }, { "openmw.util", LuaUtil::initUtilPackage(lua) }, diff --git a/apps/openmw/mwlua/luamanagerimp.cpp b/apps/openmw/mwlua/luamanagerimp.cpp index fee4aa962d..34900f39a8 100644 --- a/apps/openmw/mwlua/luamanagerimp.cpp +++ b/apps/openmw/mwlua/luamanagerimp.cpp @@ -23,6 +23,7 @@ #include "../mwrender/postprocessor.hpp" +#include "../mwworld/datetimemanager.hpp" #include "../mwworld/esmstore.hpp" #include "../mwworld/ptr.hpp" #include "../mwworld/scene.hpp" @@ -152,9 +153,10 @@ namespace MWLua if (!mWorldView.isPaused()) { // Update time and process timers - double simulationTime = mWorldView.getSimulationTime() + frameDuration; - mWorldView.setSimulationTime(simulationTime); - double gameTime = mWorldView.getGameTime(); + MWWorld::DateTimeManager& timeManager = *MWBase::Environment::get().getWorld()->getTimeManager(); + double simulationTime = timeManager.getSimulationTime() + frameDuration; + timeManager.setSimulationTime(simulationTime); + double gameTime = timeManager.getGameTime(); mGlobalScripts.processTimers(simulationTime, gameTime); for (LocalScripts* scripts : mActiveLocalScripts) @@ -400,7 +402,8 @@ namespace MWLua { writer.startRecord(ESM::REC_LUAM); - mWorldView.save(writer); + writer.writeHNT("LUAW", MWBase::Environment::get().getWorld()->getTimeManager()->getSimulationTime()); + writer.writeFormId(MWBase::Environment::get().getWorldModel()->getLastGeneratedRefNum(), true); ESM::LuaScripts globalScripts; mGlobalScripts.save(globalScripts); globalScripts.save(writer); @@ -414,7 +417,14 @@ namespace MWLua if (type != ESM::REC_LUAM) throw std::runtime_error("ESM::REC_LUAM is expected"); - mWorldView.load(reader); + double simulationTime; + reader.getHNT(simulationTime, "LUAW"); + MWBase::Environment::get().getWorld()->getTimeManager()->setSimulationTime(simulationTime); + ESM::FormId lastGenerated = reader.getFormId(true); + if (lastGenerated.hasContentFile()) + throw std::runtime_error("Last generated RefNum is invalid"); + MWBase::Environment::get().getWorldModel()->setLastGeneratedRefNum(lastGenerated); + ESM::LuaScripts globalScripts; globalScripts.load(reader); mLuaEvents.load(mLua.sol(), reader, mContentFileMapping, mGlobalLoader.get()); diff --git a/apps/openmw/mwlua/luamanagerimp.hpp b/apps/openmw/mwlua/luamanagerimp.hpp index e9311fc854..7ddb31d253 100644 --- a/apps/openmw/mwlua/luamanagerimp.hpp +++ b/apps/openmw/mwlua/luamanagerimp.hpp @@ -3,6 +3,7 @@ #include #include +#include #include #include diff --git a/apps/openmw/mwlua/postprocessingbindings.cpp b/apps/openmw/mwlua/postprocessingbindings.cpp index f63ba5e70c..5ce37d13da 100644 --- a/apps/openmw/mwlua/postprocessingbindings.cpp +++ b/apps/openmw/mwlua/postprocessingbindings.cpp @@ -1,6 +1,7 @@ #include "postprocessingbindings.hpp" #include "../mwbase/environment.hpp" +#include "../mwbase/world.hpp" #include "../mwrender/postprocessor.hpp" #include "luamanagerimp.hpp" diff --git a/apps/openmw/mwlua/stats.cpp b/apps/openmw/mwlua/stats.cpp index 1eb96ebad0..bbac88e6e2 100644 --- a/apps/openmw/mwlua/stats.cpp +++ b/apps/openmw/mwlua/stats.cpp @@ -13,6 +13,7 @@ #include "localscripts.hpp" #include "luamanagerimp.hpp" +#include "../mwbase/environment.hpp" #include "../mwmechanics/creaturestats.hpp" #include "../mwmechanics/npcstats.hpp" #include "../mwworld/class.hpp" diff --git a/apps/openmw/mwlua/uibindings.cpp b/apps/openmw/mwlua/uibindings.cpp index b5212c566e..fca46fd7e6 100644 --- a/apps/openmw/mwlua/uibindings.cpp +++ b/apps/openmw/mwlua/uibindings.cpp @@ -14,6 +14,7 @@ #include "context.hpp" #include "luamanagerimp.hpp" +#include "../mwbase/environment.hpp" #include "../mwbase/windowmanager.hpp" namespace MWLua diff --git a/apps/openmw/mwlua/worldview.cpp b/apps/openmw/mwlua/worldview.cpp index 097a418869..f80f6a159f 100644 --- a/apps/openmw/mwlua/worldview.cpp +++ b/apps/openmw/mwlua/worldview.cpp @@ -6,12 +6,12 @@ #include +#include "../mwbase/environment.hpp" #include "../mwbase/windowmanager.hpp" #include "../mwclass/container.hpp" #include "../mwworld/class.hpp" -#include "../mwworld/timestamp.hpp" #include "../mwworld/worldmodel.hpp" namespace MWLua @@ -71,28 +71,6 @@ namespace MWLua removeFromGroup(*group, ptr); } - double WorldView::getGameTime() const - { - MWBase::World* world = MWBase::Environment::get().getWorld(); - MWWorld::TimeStamp timeStamp = world->getTimeStamp(); - return (static_cast(timeStamp.getDay()) * 24 + timeStamp.getHour()) * 3600.0; - } - - void WorldView::load(ESM::ESMReader& esm) - { - esm.getHNT(mSimulationTime, "LUAW"); - ESM::FormId lastGenerated = esm.getFormId(true); - if (lastGenerated.hasContentFile()) - throw std::runtime_error("Last generated RefNum is invalid"); - MWBase::Environment::get().getWorldModel()->setLastGeneratedRefNum(lastGenerated); - } - - void WorldView::save(ESM::ESMWriter& esm) const - { - esm.writeHNT("LUAW", mSimulationTime); - esm.writeFormId(MWBase::Environment::get().getWorldModel()->getLastGeneratedRefNum(), true); - } - void WorldView::ObjectGroup::updateList() { if (mChanged) diff --git a/apps/openmw/mwlua/worldview.hpp b/apps/openmw/mwlua/worldview.hpp index 7efb7c0f01..b00abadc60 100644 --- a/apps/openmw/mwlua/worldview.hpp +++ b/apps/openmw/mwlua/worldview.hpp @@ -1,20 +1,9 @@ #ifndef MWLUA_WORLDVIEW_H #define MWLUA_WORLDVIEW_H -#include "object.hpp" - -#include "../mwbase/environment.hpp" -#include "../mwbase/world.hpp" - -#include "../mwworld/globals.hpp" - #include -namespace ESM -{ - class ESMWriter; - class ESMReader; -} +#include "object.hpp" namespace MWLua { @@ -22,7 +11,6 @@ namespace MWLua // WorldView is a kind of an extension to mwworld. It was created on initial stage of // OpenMW Lua development in order to minimize the risk of merge conflicts. // TODO: Move get*InScene functions to mwworld/scene - // TODO: Move time-related stuff to mwworld; maybe create a new class TimeManager. // TODO: Remove WorldView. class WorldView { @@ -33,19 +21,6 @@ namespace MWLua // Whether the world is paused (i.e. game time is not changing and actors don't move). bool isPaused() const { return mPaused; } - // The number of seconds passed from the beginning of the game. - double getSimulationTime() const { return mSimulationTime; } - void setSimulationTime(double t) { mSimulationTime = t; } - - // The game time (in game seconds) passed from the beginning of the game. - // Note that game time generally goes faster than the simulation time. - double getGameTime() const; - double getGameTimeScale() const { return MWBase::Environment::get().getWorld()->getTimeScaleFactor(); } - void setGameTimeScale(double s) - { - MWBase::Environment::get().getWorld()->setGlobalFloat(MWWorld::Globals::sTimeScale, s); - } - ObjectIdList getActivatorsInScene() const { return mActivatorsInScene.mList; } ObjectIdList getActorsInScene() const { return mActorsInScene.mList; } ObjectIdList getContainersInScene() const { return mContainersInScene.mList; } @@ -58,9 +33,6 @@ namespace MWLua void setPlayer(const MWWorld::Ptr& player) { *mPlayers = { getId(player) }; } - void load(ESM::ESMReader& esm); - void save(ESM::ESMWriter& esm) const; - private: struct ObjectGroup { @@ -83,7 +55,6 @@ namespace MWLua ObjectGroup mItemsInScene; ObjectIdList mPlayers = std::make_shared>(); - double mSimulationTime = 0; bool mPaused = false; }; diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 8c749190f0..ec53bdec71 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -20,6 +20,7 @@ #include "../mwworld/cellstore.hpp" #include "../mwworld/class.hpp" +#include "../mwworld/datetimemanager.hpp" #include "../mwworld/esmstore.hpp" #include "../mwworld/inventorystore.hpp" #include "../mwworld/player.hpp" @@ -837,7 +838,7 @@ namespace MWMechanics // Take a maximum remaining duration of Stunted Magicka effects (-1 is a constant one) in game hours. if (remainingTime > 0) { - double timeScale = MWBase::Environment::get().getWorld()->getTimeScaleFactor(); + double timeScale = MWBase::Environment::get().getWorld()->getTimeManager()->getGameTimeScale(); if (timeScale == 0.0) timeScale = 1; @@ -1864,7 +1865,7 @@ namespace MWMechanics void Actors::rest(double hours, bool sleep) const { float duration = hours * 3600.f; - const float timeScale = MWBase::Environment::get().getWorld()->getTimeScaleFactor(); + const float timeScale = MWBase::Environment::get().getWorld()->getTimeManager()->getGameTimeScale(); if (timeScale != 0.f) duration /= timeScale; diff --git a/apps/openmw/mwmechanics/aiescort.cpp b/apps/openmw/mwmechanics/aiescort.cpp index e020e4a717..e1d657a207 100644 --- a/apps/openmw/mwmechanics/aiescort.cpp +++ b/apps/openmw/mwmechanics/aiescort.cpp @@ -10,6 +10,7 @@ #include "../mwworld/cellstore.hpp" #include "../mwworld/class.hpp" +#include "../mwworld/datetimemanager.hpp" #include "character.hpp" #include "creaturestats.hpp" @@ -72,7 +73,8 @@ namespace MWMechanics // and the duration is not infinite, the package is complete. if (mDuration > 0) { - mRemainingDuration -= ((duration * MWBase::Environment::get().getWorld()->getTimeScaleFactor()) / 3600); + mRemainingDuration + -= ((duration * MWBase::Environment::get().getWorld()->getTimeManager()->getGameTimeScale()) / 3600); if (mRemainingDuration <= 0) { mRemainingDuration = mDuration; diff --git a/apps/openmw/mwmechanics/aifollow.cpp b/apps/openmw/mwmechanics/aifollow.cpp index 3f0e4e287c..b78c1fd6ee 100644 --- a/apps/openmw/mwmechanics/aifollow.cpp +++ b/apps/openmw/mwmechanics/aifollow.cpp @@ -10,6 +10,7 @@ #include "../mwworld/cellstore.hpp" #include "../mwworld/class.hpp" +#include "../mwworld/datetimemanager.hpp" #include "character.hpp" #include "creaturestats.hpp" @@ -156,7 +157,9 @@ namespace MWMechanics // Check if we've run out of time if (mDuration > 0) { - mRemainingDuration -= ((duration * MWBase::Environment::get().getWorld()->getTimeScaleFactor()) / 3600); + mRemainingDuration + -= ((duration * MWBase::Environment::get().getWorld()->getTimeManager()->getGameTimeScale()) + / 3600); if (mRemainingDuration <= 0) { mRemainingDuration = mDuration; diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index 4e3e29c4fb..2392d5cd07 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -16,6 +16,7 @@ #include "../mwworld/cellstore.hpp" #include "../mwworld/class.hpp" +#include "../mwworld/datetimemanager.hpp" #include "../mwworld/esmstore.hpp" #include "../mwphysics/raycasting.hpp" @@ -200,7 +201,8 @@ namespace MWMechanics // get or create temporary storage AiWanderStorage& storage = state.get(); - mRemainingDuration -= ((duration * MWBase::Environment::get().getWorld()->getTimeScaleFactor()) / 3600); + mRemainingDuration + -= ((duration * MWBase::Environment::get().getWorld()->getTimeManager()->getGameTimeScale()) / 3600); cStats.setDrawState(DrawState::Nothing); cStats.setMovementFlag(CreatureStats::Flag_Run, false); diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index 5b8a25da17..d2f725c4b8 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -27,6 +27,7 @@ #include +#include "../mwworld/datetimemanager.hpp" #include "../mwworld/weather.hpp" #include "../mwbase/environment.hpp" @@ -559,7 +560,7 @@ namespace MWRender } // rotate the stars by 360 degrees every 4 days - mAtmosphereNightRoll += MWBase::Environment::get().getWorld()->getTimeScaleFactor() * duration + mAtmosphereNightRoll += MWBase::Environment::get().getWorld()->getTimeManager()->getGameTimeScale() * duration * osg::DegreesToRadians(360.f) / (3600 * 96.f); if (mAtmosphereNightNode->getNodeMask() != 0) mAtmosphereNightNode->setAttitude(osg::Quat(mAtmosphereNightRoll, osg::Vec3f(0, 0, 1))); diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index 603cec9d77..50fd123b4f 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -33,6 +33,7 @@ #include "../mwworld/cellstore.hpp" #include "../mwworld/class.hpp" +#include "../mwworld/datetimemanager.hpp" #include "../mwworld/esmstore.hpp" #include "../mwworld/globals.hpp" #include "../mwworld/scene.hpp" @@ -227,7 +228,7 @@ void MWState::StateManager::saveGame(std::string_view description, const Slot* s profile.mPlayerClassId = classId; profile.mPlayerCellName = world.getCellName(); - profile.mInGameTime = world.getEpochTimeStamp(); + profile.mInGameTime = world.getTimeManager()->getEpochTimeStamp(); profile.mTimePlayed = mTimePlayed; profile.mDescription = description; diff --git a/apps/openmw/mwworld/datetimemanager.cpp b/apps/openmw/mwworld/datetimemanager.cpp index 941f41d9e5..f97d1960ca 100644 --- a/apps/openmw/mwworld/datetimemanager.cpp +++ b/apps/openmw/mwworld/datetimemanager.cpp @@ -3,6 +3,8 @@ #include #include "../mwbase/environment.hpp" +#include "../mwbase/soundmanager.hpp" +#include "../mwbase/world.hpp" #include "duration.hpp" #include "globals.hpp" @@ -53,7 +55,8 @@ namespace MWWorld mDay = globalVariables[Globals::sDay].getInteger(); mMonth = globalVariables[Globals::sMonth].getInteger(); mYear = globalVariables[Globals::sYear].getInteger(); - mTimeScale = globalVariables[Globals::sTimeScale].getFloat(); + mGameTimeScale = globalVariables[Globals::sTimeScale].getFloat(); + setSimulationTimeScale(1.0); } void DateTimeManager::setHour(double hour) @@ -103,9 +106,9 @@ namespace MWWorld return TimeStamp(mGameHour, mDaysPassed); } - float DateTimeManager::getTimeScaleFactor() const + void DateTimeManager::setGameTimeScale(float scale) { - return mTimeScale; + MWBase::Environment::get().getWorld()->setGlobalFloat(MWWorld::Globals::sTimeScale, scale); } ESM::EpochTimeStamp DateTimeManager::getEpochTimeStamp() const @@ -199,7 +202,7 @@ namespace MWWorld } else if (name == Globals::sTimeScale) { - mTimeScale = value; + mGameTimeScale = value; } else if (name == Globals::sDaysPassed) { @@ -232,7 +235,7 @@ namespace MWWorld } else if (name == Globals::sTimeScale) { - mTimeScale = static_cast(value); + mGameTimeScale = static_cast(value); } else if (name == Globals::sDaysPassed) { @@ -241,4 +244,10 @@ namespace MWWorld return false; } + + void DateTimeManager::setSimulationTimeScale(float scale) + { + mSimulationTimeScale = std::max(0.f, scale); + MWBase::Environment::get().getSoundManager()->setSimulationTimeScale(mSimulationTimeScale); + } } diff --git a/apps/openmw/mwworld/datetimemanager.hpp b/apps/openmw/mwworld/datetimemanager.hpp index 0ceaae9584..47609efc26 100644 --- a/apps/openmw/mwworld/datetimemanager.hpp +++ b/apps/openmw/mwworld/datetimemanager.hpp @@ -14,31 +14,45 @@ namespace MWWorld { class Globals; class TimeStamp; + class World; class DateTimeManager { - int mDaysPassed = 0; - int mDay = 0; - int mMonth = 0; - int mYear = 0; - float mGameHour = 0.f; - float mTimeScale = 0.f; - - void setHour(double hour); - void setDay(int day); - void setMonth(int month); - public: - std::string_view getMonthName(int month) const; + // Game time. + // Note that game time generally goes faster than the simulation time. + std::string_view getMonthName(int month = -1) const; // -1: current month TimeStamp getTimeStamp() const; ESM::EpochTimeStamp getEpochTimeStamp() const; - float getTimeScaleFactor() const; - - void advanceTime(double hours, Globals& globalVariables); - + double getGameTime() const { return (static_cast(mDaysPassed) * 24 + mGameHour) * 3600.0; } + float getGameTimeScale() const { return mGameTimeScale; } + void setGameTimeScale(float scale); // game time to simulation time ratio + + // Simulation time (the number of seconds passed from the beginning of the game). + double getSimulationTime() const { return mSimulationTime; } + void setSimulationTime(double t) { mSimulationTime = t; } + float getSimulationTimeScale() const { return mSimulationTimeScale; } + void setSimulationTimeScale(float scale); // simulation time to real time ratio + + private: + friend class World; void setup(Globals& globalVariables); bool updateGlobalInt(GlobalVariableName name, int value); bool updateGlobalFloat(GlobalVariableName name, float value); + void advanceTime(double hours, Globals& globalVariables); + + void setHour(double hour); + void setDay(int day); + void setMonth(int month); + + int mDaysPassed = 0; + int mDay = 0; + int mMonth = 0; + int mYear = 0; + float mGameHour = 0.f; + float mGameTimeScale = 0.f; + float mSimulationTimeScale = 1.0; + double mSimulationTime = 0.0; }; } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 7f2260f1a5..2044e8905c 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -249,7 +249,7 @@ namespace MWWorld : mResourceSystem(resourceSystem) , mLocalScripts(mStore) , mWorldModel(mStore, mReaders) - , mCurrentDate(std::make_unique()) + , mTimeManager(std::make_unique()) , mSky(true) , mGodMode(false) , mScriptsEnabled(true) @@ -319,7 +319,7 @@ namespace MWWorld void World::fillGlobalVariables() { mGlobalVariables.fill(mStore); - mCurrentDate->setup(mGlobalVariables); + mTimeManager->setup(mGlobalVariables); } void World::startNewGame(bool bypass) @@ -399,7 +399,7 @@ namespace MWWorld mPhysics->toggleCollisionMode(); MWBase::Environment::get().getWindowManager()->updatePlayer(); - mCurrentDate->setup(mGlobalVariables); + mTimeManager->setup(mGlobalVariables); // Initial seed. mPrng.seed(mRandomSeed); @@ -614,7 +614,7 @@ namespace MWWorld void World::setGlobalInt(GlobalVariableName name, int value) { - bool dateUpdated = mCurrentDate->updateGlobalInt(name, value); + bool dateUpdated = mTimeManager->updateGlobalInt(name, value); if (dateUpdated) updateSkyDate(); @@ -623,7 +623,7 @@ namespace MWWorld void World::setGlobalFloat(GlobalVariableName name, float value) { - bool dateUpdated = mCurrentDate->updateGlobalFloat(name, value); + bool dateUpdated = mTimeManager->updateGlobalFloat(name, value); if (dateUpdated) updateSkyDate(); @@ -645,11 +645,6 @@ namespace MWWorld return mGlobalVariables.getType(name); } - std::string_view World::getMonthName(int month) const - { - return mCurrentDate->getMonthName(month); - } - std::string_view World::getCellName(const MWWorld::CellStore* cell) const { if (!cell) @@ -892,7 +887,7 @@ namespace MWWorld // When we fast-forward time, we should recharge magic items // in all loaded cells, using game world time float duration = hours * 3600; - const float timeScaleFactor = getTimeScaleFactor(); + const float timeScaleFactor = mTimeManager->getGameTimeScale(); if (timeScaleFactor != 0.0f) duration /= timeScaleFactor; @@ -900,7 +895,7 @@ namespace MWWorld } mWeatherManager->advanceTime(hours, incremental); - mCurrentDate->advanceTime(hours, mGlobalVariables); + mTimeManager->advanceTime(hours, mGlobalVariables); updateSkyDate(); if (!incremental) @@ -911,25 +906,9 @@ namespace MWWorld } } - float World::getTimeScaleFactor() const - { - return mCurrentDate->getTimeScaleFactor(); - } - - void World::setSimulationTimeScale(float scale) - { - mSimulationTimeScale = std::max(0.f, scale); - MWBase::Environment::get().getSoundManager()->setSimulationTimeScale(mSimulationTimeScale); - } - TimeStamp World::getTimeStamp() const { - return mCurrentDate->getTimeStamp(); - } - - ESM::EpochTimeStamp World::getEpochTimeStamp() const - { - return mCurrentDate->getEpochTimeStamp(); + return mTimeManager->getTimeStamp(); } bool World::toggleSky() @@ -2313,7 +2292,7 @@ namespace MWWorld { mStore.rebuildIdsIndex(); mStore.validateDynamic(); - mCurrentDate->setup(mGlobalVariables); + mTimeManager->setup(mGlobalVariables); } void World::setupPlayer() @@ -3863,7 +3842,7 @@ namespace MWWorld void World::updateSkyDate() { - ESM::EpochTimeStamp currentDate = mCurrentDate->getEpochTimeStamp(); + ESM::EpochTimeStamp currentDate = mTimeManager->getEpochTimeStamp(); mRendering->skySetDate(currentDate.mDay, currentDate.mMonth); } diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 510c25f2d9..64bc3666de 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -102,7 +102,7 @@ namespace MWWorld std::unique_ptr mRendering; std::unique_ptr mWorldScene; std::unique_ptr mWeatherManager; - std::unique_ptr mCurrentDate; + std::unique_ptr mTimeManager; std::unique_ptr mProjectileManager; bool mSky; @@ -135,8 +135,6 @@ namespace MWWorld uint32_t mRandomSeed{}; - float mSimulationTimeScale = 1.0; - // not implemented World(const World&); World& operator=(const World&); @@ -309,15 +307,9 @@ namespace MWWorld void advanceTime(double hours, bool incremental = false) override; ///< Advance in-game time. - std::string_view getMonthName(int month = -1) const override; - ///< Return name of month (-1: current month) - TimeStamp getTimeStamp() const override; ///< Return current in-game time and number of day since new game start. - ESM::EpochTimeStamp getEpochTimeStamp() const override; - ///< Return current in-game date and time. - bool toggleSky() override; ///< \return Resulting mode @@ -339,12 +331,6 @@ namespace MWWorld void modRegion(const ESM::RefId& regionid, const std::vector& chances) override; - float getTimeScaleFactor() const override; - - float getSimulationTimeScale() const override { return mSimulationTimeScale; } - - void setSimulationTimeScale(float scale) override; - void changeToInteriorCell(const std::string_view cellName, const ESM::Position& position, bool adjustPlayerPos, bool changeEvent = true) override; ///< Move to interior cell. @@ -690,6 +676,8 @@ namespace MWWorld MWRender::PostProcessor* getPostProcessor() override; + DateTimeManager* getTimeManager() override { return mTimeManager.get(); } + void setActorActive(const MWWorld::Ptr& ptr, bool value) override; }; }