mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-03-30 07:21:12 +00:00
Merge branch 'time' into 'master'
Pause/resume the game in Lua scripts See merge request OpenMW/openmw!3317
This commit is contained in:
commit
e21e3a0d46
@ -59,7 +59,7 @@ add_openmw_dir (mwscript
|
|||||||
)
|
)
|
||||||
|
|
||||||
add_openmw_dir (mwlua
|
add_openmw_dir (mwlua
|
||||||
luamanagerimp object worldview userdataserializer luaevents engineevents objectvariant
|
luamanagerimp object objectlists userdataserializer luaevents engineevents objectvariant
|
||||||
context globalscripts localscripts playerscripts luabindings objectbindings cellbindings mwscriptbindings
|
context globalscripts localscripts playerscripts luabindings objectbindings cellbindings mwscriptbindings
|
||||||
camerabindings uibindings inputbindings nearbybindings postprocessingbindings stats debugbindings
|
camerabindings uibindings inputbindings nearbybindings postprocessingbindings stats debugbindings
|
||||||
types/types types/door types/item types/actor types/container types/lockable types/weapon types/npc types/creature types/player types/activator types/book types/lockpick types/probe types/apparatus types/potion types/ingredient types/misc types/repair types/armor types/light types/static types/clothing types/levelledlist types/terminal
|
types/types types/door types/item types/actor types/container types/lockable types/weapon types/npc types/creature types/player types/activator types/book types/lockpick types/probe types/apparatus types/potion types/ingredient types/misc types/repair types/armor types/light types/static types/clothing types/levelledlist types/terminal
|
||||||
|
@ -65,6 +65,7 @@
|
|||||||
#include "mwsound/soundmanagerimp.hpp"
|
#include "mwsound/soundmanagerimp.hpp"
|
||||||
|
|
||||||
#include "mwworld/class.hpp"
|
#include "mwworld/class.hpp"
|
||||||
|
#include "mwworld/datetimemanager.hpp"
|
||||||
#include "mwworld/worldimp.hpp"
|
#include "mwworld/worldimp.hpp"
|
||||||
|
|
||||||
#include "mwrender/vismask.hpp"
|
#include "mwrender/vismask.hpp"
|
||||||
@ -200,9 +201,6 @@ bool OMW::Engine::frame(float frametime)
|
|||||||
mSoundManager->update(frametime);
|
mSoundManager->update(frametime);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Main menu opened? Then scripts are also paused.
|
|
||||||
bool paused = mWindowManager->containsMode(MWGui::GM_MainMenu);
|
|
||||||
|
|
||||||
{
|
{
|
||||||
ScopedProfile<UserStatsType::LuaSyncUpdate> profile(frameStart, frameNumber, *timer, *stats);
|
ScopedProfile<UserStatsType::LuaSyncUpdate> profile(frameStart, frameNumber, *timer, *stats);
|
||||||
// Should be called after input manager update and before any change to the game world.
|
// Should be called after input manager update and before any change to the game world.
|
||||||
@ -216,14 +214,14 @@ bool OMW::Engine::frame(float frametime)
|
|||||||
mStateManager->update(frametime);
|
mStateManager->update(frametime);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool guiActive = mWindowManager->isGuiMode();
|
bool paused = mWorld->getTimeManager()->isPaused();
|
||||||
|
|
||||||
{
|
{
|
||||||
ScopedProfile<UserStatsType::Script> profile(frameStart, frameNumber, *timer, *stats);
|
ScopedProfile<UserStatsType::Script> profile(frameStart, frameNumber, *timer, *stats);
|
||||||
|
|
||||||
if (mStateManager->getState() != MWBase::StateManager::State_NoGame)
|
if (mStateManager->getState() != MWBase::StateManager::State_NoGame)
|
||||||
{
|
{
|
||||||
if (!paused)
|
if (!mWindowManager->containsMode(MWGui::GM_MainMenu))
|
||||||
{
|
{
|
||||||
if (mWorld->getScriptsEnabled())
|
if (mWorld->getScriptsEnabled())
|
||||||
{
|
{
|
||||||
@ -237,9 +235,9 @@ bool OMW::Engine::frame(float frametime)
|
|||||||
mWorld->getWorldScene().markCellAsUnchanged();
|
mWorld->getWorldScene().markCellAsUnchanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!guiActive)
|
if (!paused)
|
||||||
{
|
{
|
||||||
double hours = (frametime * mWorld->getTimeScaleFactor()) / 3600.0;
|
double hours = (frametime * mWorld->getTimeManager()->getGameTimeScale()) / 3600.0;
|
||||||
mWorld->advanceTime(hours, true);
|
mWorld->advanceTime(hours, true);
|
||||||
mWorld->rechargeItems(frametime, true);
|
mWorld->rechargeItems(frametime, true);
|
||||||
}
|
}
|
||||||
@ -252,13 +250,13 @@ bool OMW::Engine::frame(float frametime)
|
|||||||
|
|
||||||
if (mStateManager->getState() != MWBase::StateManager::State_NoGame)
|
if (mStateManager->getState() != MWBase::StateManager::State_NoGame)
|
||||||
{
|
{
|
||||||
mMechanicsManager->update(frametime, guiActive);
|
mMechanicsManager->update(frametime, paused);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mStateManager->getState() == MWBase::StateManager::State_Running)
|
if (mStateManager->getState() == MWBase::StateManager::State_Running)
|
||||||
{
|
{
|
||||||
MWWorld::Ptr player = mWorld->getPlayerPtr();
|
MWWorld::Ptr player = mWorld->getPlayerPtr();
|
||||||
if (!guiActive && player.getClass().getCreatureStats(player).isDead())
|
if (!paused && player.getClass().getCreatureStats(player).isDead())
|
||||||
mStateManager->endGame();
|
mStateManager->endGame();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -269,7 +267,7 @@ bool OMW::Engine::frame(float frametime)
|
|||||||
|
|
||||||
if (mStateManager->getState() != MWBase::StateManager::State_NoGame)
|
if (mStateManager->getState() != MWBase::StateManager::State_NoGame)
|
||||||
{
|
{
|
||||||
mWorld->updatePhysics(frametime, guiActive, frameStart, frameNumber, *stats);
|
mWorld->updatePhysics(frametime, paused, frameStart, frameNumber, *stats);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -279,7 +277,7 @@ bool OMW::Engine::frame(float frametime)
|
|||||||
|
|
||||||
if (mStateManager->getState() != MWBase::StateManager::State_NoGame)
|
if (mStateManager->getState() != MWBase::StateManager::State_NoGame)
|
||||||
{
|
{
|
||||||
mWorld->update(frametime, guiActive);
|
mWorld->update(frametime, paused);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -928,7 +926,7 @@ void OMW::Engine::go()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Start the main rendering loop
|
// Start the main rendering loop
|
||||||
double simulationTime = 0.0;
|
MWWorld::DateTimeManager& timeManager = *mWorld->getTimeManager();
|
||||||
Misc::FrameRateLimiter frameRateLimiter = Misc::makeFrameRateLimiter(mEnvironment.getFrameRateLimit());
|
Misc::FrameRateLimiter frameRateLimiter = Misc::makeFrameRateLimiter(mEnvironment.getFrameRateLimit());
|
||||||
const std::chrono::steady_clock::duration maxSimulationInterval(std::chrono::milliseconds(200));
|
const std::chrono::steady_clock::duration maxSimulationInterval(std::chrono::milliseconds(200));
|
||||||
while (!mViewer->done() && !mStateManager->hasQuitRequest())
|
while (!mViewer->done() && !mStateManager->hasQuitRequest())
|
||||||
@ -936,21 +934,18 @@ void OMW::Engine::go()
|
|||||||
const double dt = std::chrono::duration_cast<std::chrono::duration<double>>(
|
const double dt = std::chrono::duration_cast<std::chrono::duration<double>>(
|
||||||
std::min(frameRateLimiter.getLastFrameDuration(), maxSimulationInterval))
|
std::min(frameRateLimiter.getLastFrameDuration(), maxSimulationInterval))
|
||||||
.count()
|
.count()
|
||||||
* mEnvironment.getWorld()->getSimulationTimeScale();
|
* timeManager.getSimulationTimeScale();
|
||||||
|
|
||||||
mViewer->advance(simulationTime);
|
mViewer->advance(timeManager.getSimulationTime());
|
||||||
|
|
||||||
if (!frame(dt))
|
if (!frame(dt))
|
||||||
{
|
{
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(5));
|
std::this_thread::sleep_for(std::chrono::milliseconds(5));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else
|
timeManager.updateIsPaused();
|
||||||
{
|
if (!timeManager.isPaused())
|
||||||
bool guiActive = mWindowManager->isGuiMode();
|
timeManager.setSimulationTime(timeManager.getSimulationTime() + dt);
|
||||||
if (!guiActive)
|
|
||||||
simulationTime += dt;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stats)
|
if (stats)
|
||||||
{
|
{
|
||||||
|
@ -92,6 +92,7 @@ namespace MWWorld
|
|||||||
class ESMStore;
|
class ESMStore;
|
||||||
class RefData;
|
class RefData;
|
||||||
class Cell;
|
class Cell;
|
||||||
|
class DateTimeManager;
|
||||||
|
|
||||||
typedef std::vector<std::pair<MWWorld::Ptr, MWMechanics::Movement>> PtrMovementList;
|
typedef std::vector<std::pair<MWWorld::Ptr, MWMechanics::Movement>> PtrMovementList;
|
||||||
}
|
}
|
||||||
@ -209,15 +210,9 @@ namespace MWBase
|
|||||||
virtual void advanceTime(double hours, bool incremental = false) = 0;
|
virtual void advanceTime(double hours, bool incremental = false) = 0;
|
||||||
///< Advance in-game time.
|
///< 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;
|
virtual MWWorld::TimeStamp getTimeStamp() const = 0;
|
||||||
///< Return current in-game time and number of day since new game start.
|
///< 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;
|
virtual bool toggleSky() = 0;
|
||||||
///< \return Resulting mode
|
///< \return Resulting mode
|
||||||
|
|
||||||
@ -239,12 +234,6 @@ namespace MWBase
|
|||||||
|
|
||||||
virtual void modRegion(const ESM::RefId& regionid, const std::vector<char>& chances) = 0;
|
virtual void modRegion(const ESM::RefId& regionid, const std::vector<char>& chances) = 0;
|
||||||
|
|
||||||
virtual float getTimeScaleFactor() const = 0;
|
|
||||||
|
|
||||||
virtual float getSimulationTimeScale() const = 0;
|
|
||||||
|
|
||||||
virtual void setSimulationTimeScale(float scale) = 0;
|
|
||||||
|
|
||||||
virtual void changeToInteriorCell(
|
virtual void changeToInteriorCell(
|
||||||
std::string_view cellName, const ESM::Position& position, bool adjustPlayerPos, bool changeEvent = true)
|
std::string_view cellName, const ESM::Position& position, bool adjustPlayerPos, bool changeEvent = true)
|
||||||
= 0;
|
= 0;
|
||||||
@ -612,6 +601,8 @@ namespace MWBase
|
|||||||
|
|
||||||
virtual MWRender::PostProcessor* getPostProcessor() = 0;
|
virtual MWRender::PostProcessor* getPostProcessor() = 0;
|
||||||
|
|
||||||
|
virtual MWWorld::DateTimeManager* getTimeManager() = 0;
|
||||||
|
|
||||||
virtual void setActorActive(const MWWorld::Ptr& ptr, bool value) = 0;
|
virtual void setActorActive(const MWWorld::Ptr& ptr, bool value) = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
|
|
||||||
#include "../mwdialogue/keywordsearch.hpp"
|
#include "../mwdialogue/keywordsearch.hpp"
|
||||||
|
#include "../mwworld/datetimemanager.hpp"
|
||||||
|
|
||||||
namespace MWGui
|
namespace MWGui
|
||||||
{
|
{
|
||||||
@ -253,8 +254,9 @@ namespace MWGui
|
|||||||
|
|
||||||
std::ostringstream os;
|
std::ostringstream os;
|
||||||
|
|
||||||
os << itr->mDayOfMonth << ' ' << MWBase::Environment::get().getWorld()->getMonthName(itr->mMonth)
|
os << itr->mDayOfMonth << ' '
|
||||||
<< " (" << dayStr << " " << (itr->mDay) << ')';
|
<< MWBase::Environment::get().getWorld()->getTimeManager()->getMonthName(itr->mMonth) << " ("
|
||||||
|
<< dayStr << " " << (itr->mDay) << ')';
|
||||||
|
|
||||||
timestamp_buffer = os.str();
|
timestamp_buffer = os.str();
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
#include "../mwbase/statemanager.hpp"
|
#include "../mwbase/statemanager.hpp"
|
||||||
#include "../mwbase/windowmanager.hpp"
|
#include "../mwbase/windowmanager.hpp"
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
|
#include "../mwworld/datetimemanager.hpp"
|
||||||
#include "../mwworld/esmstore.hpp"
|
#include "../mwworld/esmstore.hpp"
|
||||||
|
|
||||||
#include "../mwstate/character.hpp"
|
#include "../mwstate/character.hpp"
|
||||||
@ -422,8 +423,9 @@ namespace MWGui
|
|||||||
hour = 12;
|
hour = 12;
|
||||||
|
|
||||||
text << mCurrentSlot->mProfile.mInGameTime.mDay << " "
|
text << mCurrentSlot->mProfile.mInGameTime.mDay << " "
|
||||||
<< MWBase::Environment::get().getWorld()->getMonthName(mCurrentSlot->mProfile.mInGameTime.mMonth) << " "
|
<< MWBase::Environment::get().getWorld()->getTimeManager()->getMonthName(
|
||||||
<< hour << " " << (pm ? "#{Calendar:pm}" : "#{Calendar:am}");
|
mCurrentSlot->mProfile.mInGameTime.mMonth)
|
||||||
|
<< " " << hour << " " << (pm ? "#{Calendar:pm}" : "#{Calendar:am}");
|
||||||
|
|
||||||
if (Settings::Manager::getBool("timeplayed", "Saves"))
|
if (Settings::Manager::getBool("timeplayed", "Saves"))
|
||||||
{
|
{
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#include "../mwworld/cellstore.hpp"
|
#include "../mwworld/cellstore.hpp"
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
#include "../mwworld/datetimemanager.hpp"
|
||||||
#include "../mwworld/esmstore.hpp"
|
#include "../mwworld/esmstore.hpp"
|
||||||
|
|
||||||
#include "../mwmechanics/actorutil.hpp"
|
#include "../mwmechanics/actorutil.hpp"
|
||||||
@ -154,17 +155,17 @@ namespace MWGui
|
|||||||
onHourSliderChangedPosition(mHourSlider, 0);
|
onHourSliderChangedPosition(mHourSlider, 0);
|
||||||
mHourSlider->setScrollPosition(0);
|
mHourSlider->setScrollPosition(0);
|
||||||
|
|
||||||
std::string_view month = MWBase::Environment::get().getWorld()->getMonthName();
|
const MWWorld::DateTimeManager& timeManager = *MWBase::Environment::get().getWorld()->getTimeManager();
|
||||||
int hour = static_cast<int>(MWBase::Environment::get().getWorld()->getTimeStamp().getHour());
|
std::string_view month = timeManager.getMonthName();
|
||||||
|
int hour = static_cast<int>(timeManager.getTimeStamp().getHour());
|
||||||
bool pm = hour >= 12;
|
bool pm = hour >= 12;
|
||||||
if (hour >= 13)
|
if (hour >= 13)
|
||||||
hour -= 12;
|
hour -= 12;
|
||||||
if (hour == 0)
|
if (hour == 0)
|
||||||
hour = 12;
|
hour = 12;
|
||||||
|
|
||||||
ESM::EpochTimeStamp currentDate = MWBase::Environment::get().getWorld()->getEpochTimeStamp();
|
ESM::EpochTimeStamp currentDate = timeManager.getEpochTimeStamp();
|
||||||
std::string daysPassed = Misc::StringUtils::format(
|
std::string daysPassed = Misc::StringUtils::format("(#{Calendar:day} %i)", timeManager.getTimeStamp().getDay());
|
||||||
"(#{Calendar:day} %i)", MWBase::Environment::get().getWorld()->getTimeStamp().getDay());
|
|
||||||
std::string_view formattedHour(pm ? "#{Calendar:pm}" : "#{Calendar:am}");
|
std::string_view formattedHour(pm ? "#{Calendar:pm}" : "#{Calendar:am}");
|
||||||
std::string dateTimeText
|
std::string dateTimeText
|
||||||
= Misc::StringUtils::format("%i %s %s %i %s", currentDate.mDay, month, daysPassed, hour, formattedHour);
|
= Misc::StringUtils::format("%i %s %s %i %s", currentDate.mDay, month, daysPassed, hour, formattedHour);
|
||||||
|
@ -11,7 +11,7 @@ namespace MWLua
|
|||||||
{
|
{
|
||||||
class LuaEvents;
|
class LuaEvents;
|
||||||
class LuaManager;
|
class LuaManager;
|
||||||
class WorldView;
|
class ObjectLists;
|
||||||
|
|
||||||
struct Context
|
struct Context
|
||||||
{
|
{
|
||||||
@ -19,7 +19,7 @@ namespace MWLua
|
|||||||
LuaManager* mLuaManager;
|
LuaManager* mLuaManager;
|
||||||
LuaUtil::LuaState* mLua;
|
LuaUtil::LuaState* mLua;
|
||||||
LuaUtil::UserdataSerializer* mSerializer;
|
LuaUtil::UserdataSerializer* mSerializer;
|
||||||
WorldView* mWorldView;
|
ObjectLists* mObjectLists;
|
||||||
LuaEvents* mLuaEvents;
|
LuaEvents* mLuaEvents;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include "../mwbase/statemanager.hpp"
|
#include "../mwbase/statemanager.hpp"
|
||||||
#include "../mwworld/action.hpp"
|
#include "../mwworld/action.hpp"
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
#include "../mwworld/datetimemanager.hpp"
|
||||||
#include "../mwworld/esmstore.hpp"
|
#include "../mwworld/esmstore.hpp"
|
||||||
#include "../mwworld/manualref.hpp"
|
#include "../mwworld/manualref.hpp"
|
||||||
#include "../mwworld/store.hpp"
|
#include "../mwworld/store.hpp"
|
||||||
@ -28,7 +29,7 @@
|
|||||||
#include "luaevents.hpp"
|
#include "luaevents.hpp"
|
||||||
#include "luamanagerimp.hpp"
|
#include "luamanagerimp.hpp"
|
||||||
#include "mwscriptbindings.hpp"
|
#include "mwscriptbindings.hpp"
|
||||||
#include "worldview.hpp"
|
#include "objectlists.hpp"
|
||||||
|
|
||||||
#include "camerabindings.hpp"
|
#include "camerabindings.hpp"
|
||||||
#include "cellbindings.hpp"
|
#include "cellbindings.hpp"
|
||||||
@ -61,13 +62,13 @@ namespace MWLua
|
|||||||
|
|
||||||
static void addTimeBindings(sol::table& api, const Context& context, bool global)
|
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["getSimulationTime"] = [timeManager]() { return timeManager->getSimulationTime(); };
|
||||||
api["getSimulationTimeScale"] = [world]() { return world->getSimulationTimeScale(); };
|
api["getSimulationTimeScale"] = [timeManager]() { return timeManager->getSimulationTimeScale(); };
|
||||||
api["getGameTime"] = [world = context.mWorldView]() { return world->getGameTime(); };
|
api["getGameTime"] = [timeManager]() { return timeManager->getGameTime(); };
|
||||||
api["getGameTimeScale"] = [world = context.mWorldView]() { return world->getGameTimeScale(); };
|
api["getGameTimeScale"] = [timeManager]() { return timeManager->getGameTimeScale(); };
|
||||||
api["isWorldPaused"] = [world = context.mWorldView]() { return world->isPaused(); };
|
api["isWorldPaused"] = [timeManager]() { return timeManager->isPaused(); };
|
||||||
api["getRealTime"] = []() {
|
api["getRealTime"] = []() {
|
||||||
return std::chrono::duration<double>(std::chrono::steady_clock::now().time_since_epoch()).count();
|
return std::chrono::duration<double>(std::chrono::steady_clock::now().time_since_epoch()).count();
|
||||||
};
|
};
|
||||||
@ -75,15 +76,21 @@ namespace MWLua
|
|||||||
if (!global)
|
if (!global)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
api["setGameTimeScale"] = [world = context.mWorldView](double scale) { world->setGameTimeScale(scale); };
|
api["setGameTimeScale"] = [timeManager](double scale) { timeManager->setGameTimeScale(scale); };
|
||||||
|
api["setSimulationTimeScale"] = [context, timeManager](float scale) {
|
||||||
api["setSimulationTimeScale"] = [context, world](float scale) {
|
context.mLuaManager->addAction([scale, timeManager] { timeManager->setSimulationTimeScale(scale); });
|
||||||
context.mLuaManager->addAction([scale, world] { world->setSimulationTimeScale(scale); });
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: Ability to pause/resume world from Lua (needed for UI dehardcoding)
|
api["pause"]
|
||||||
// api["pause"] = []() {};
|
= [timeManager](sol::optional<std::string_view> tag) { timeManager->pause(tag.value_or("paused")); };
|
||||||
// api["resume"] = []() {};
|
api["unpause"]
|
||||||
|
= [timeManager](sol::optional<std::string_view> tag) { timeManager->unpause(tag.value_or("paused")); };
|
||||||
|
api["getPausedTags"] = [timeManager](sol::this_state lua) {
|
||||||
|
sol::table res(lua, sol::create);
|
||||||
|
for (const std::string& tag : timeManager->getPausedTags())
|
||||||
|
res[tag] = tag;
|
||||||
|
return res;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static sol::table initContentFilesBindings(sol::state_view& lua)
|
static sol::table initContentFilesBindings(sol::state_view& lua)
|
||||||
@ -228,12 +235,12 @@ namespace MWLua
|
|||||||
static sol::table initWorldPackage(const Context& context)
|
static sol::table initWorldPackage(const Context& context)
|
||||||
{
|
{
|
||||||
sol::table api(context.mLua->sol(), sol::create);
|
sol::table api(context.mLua->sol(), sol::create);
|
||||||
WorldView* worldView = context.mWorldView;
|
ObjectLists* objectLists = context.mObjectLists;
|
||||||
addTimeBindings(api, context, true);
|
addTimeBindings(api, context, true);
|
||||||
addCellGetters(api, context);
|
addCellGetters(api, context);
|
||||||
api["mwscript"] = initMWScriptBindings(context);
|
api["mwscript"] = initMWScriptBindings(context);
|
||||||
api["activeActors"] = GObjectList{ worldView->getActorsInScene() };
|
api["activeActors"] = GObjectList{ objectLists->getActorsInScene() };
|
||||||
api["players"] = GObjectList{ worldView->getPlayers() };
|
api["players"] = GObjectList{ objectLists->getPlayers() };
|
||||||
api["createObject"] = [](std::string_view recordId, sol::optional<int> count) -> GObject {
|
api["createObject"] = [](std::string_view recordId, sol::optional<int> count) -> GObject {
|
||||||
MWWorld::ManualRef mref(*MWBase::Environment::get().getESMStore(), ESM::RefId::deserializeText(recordId));
|
MWWorld::ManualRef mref(*MWBase::Environment::get().getESMStore(), ESM::RefId::deserializeText(recordId));
|
||||||
const MWWorld::Ptr& ptr = mref.getPtr();
|
const MWWorld::Ptr& ptr = mref.getPtr();
|
||||||
@ -291,11 +298,11 @@ namespace MWLua
|
|||||||
std::map<std::string, sol::object> initCommonPackages(const Context& context)
|
std::map<std::string, sol::object> initCommonPackages(const Context& context)
|
||||||
{
|
{
|
||||||
sol::state_view lua = context.mLua->sol();
|
sol::state_view lua = context.mLua->sol();
|
||||||
WorldView* w = context.mWorldView;
|
MWWorld::DateTimeManager* tm = MWBase::Environment::get().getWorld()->getTimeManager();
|
||||||
return {
|
return {
|
||||||
{ "openmw.async",
|
{ "openmw.async",
|
||||||
LuaUtil::getAsyncPackageInitializer(
|
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.core", initCorePackage(context) },
|
||||||
{ "openmw.types", initTypesPackage(context) },
|
{ "openmw.types", initTypesPackage(context) },
|
||||||
{ "openmw.util", LuaUtil::initUtilPackage(lua) },
|
{ "openmw.util", LuaUtil::initUtilPackage(lua) },
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
|
|
||||||
#include "../mwrender/postprocessor.hpp"
|
#include "../mwrender/postprocessor.hpp"
|
||||||
|
|
||||||
|
#include "../mwworld/datetimemanager.hpp"
|
||||||
#include "../mwworld/esmstore.hpp"
|
#include "../mwworld/esmstore.hpp"
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
#include "../mwworld/scene.hpp"
|
#include "../mwworld/scene.hpp"
|
||||||
@ -75,7 +76,7 @@ namespace MWLua
|
|||||||
context.mIsGlobal = true;
|
context.mIsGlobal = true;
|
||||||
context.mLuaManager = this;
|
context.mLuaManager = this;
|
||||||
context.mLua = &mLua;
|
context.mLua = &mLua;
|
||||||
context.mWorldView = &mWorldView;
|
context.mObjectLists = &mObjectLists;
|
||||||
context.mLuaEvents = &mLuaEvents;
|
context.mLuaEvents = &mLuaEvents;
|
||||||
context.mSerializer = mGlobalSerializer.get();
|
context.mSerializer = mGlobalSerializer.get();
|
||||||
|
|
||||||
@ -127,8 +128,6 @@ namespace MWLua
|
|||||||
if (mPlayer.isEmpty())
|
if (mPlayer.isEmpty())
|
||||||
return; // The game is not started yet.
|
return; // The game is not started yet.
|
||||||
|
|
||||||
float frameDuration = MWBase::Environment::get().getFrameDuration();
|
|
||||||
|
|
||||||
MWWorld::Ptr newPlayerPtr = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
MWWorld::Ptr newPlayerPtr = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
||||||
if (!(getId(mPlayer) == getId(newPlayerPtr)))
|
if (!(getId(mPlayer) == getId(newPlayerPtr)))
|
||||||
throw std::logic_error("Player RefNum was changed unexpectedly");
|
throw std::logic_error("Player RefNum was changed unexpectedly");
|
||||||
@ -138,7 +137,7 @@ namespace MWLua
|
|||||||
MWBase::Environment::get().getWorldModel()->registerPtr(mPlayer);
|
MWBase::Environment::get().getWorldModel()->registerPtr(mPlayer);
|
||||||
}
|
}
|
||||||
|
|
||||||
mWorldView.update();
|
mObjectLists.update();
|
||||||
|
|
||||||
std::erase_if(mActiveLocalScripts, [](const LocalScripts* l) {
|
std::erase_if(mActiveLocalScripts, [](const LocalScripts* l) {
|
||||||
return l->getPtrOrEmpty().isEmpty() || l->getPtrOrEmpty().getRefData().isDeleted();
|
return l->getPtrOrEmpty().isEmpty() || l->getPtrOrEmpty().getRefData().isDeleted();
|
||||||
@ -150,15 +149,12 @@ namespace MWLua
|
|||||||
|
|
||||||
mLuaEvents.finalizeEventBatch();
|
mLuaEvents.finalizeEventBatch();
|
||||||
|
|
||||||
if (!mWorldView.isPaused())
|
MWWorld::DateTimeManager& timeManager = *MWBase::Environment::get().getWorld()->getTimeManager();
|
||||||
{ // Update time and process timers
|
if (!timeManager.isPaused())
|
||||||
double simulationTime = mWorldView.getSimulationTime() + frameDuration;
|
{
|
||||||
mWorldView.setSimulationTime(simulationTime);
|
mGlobalScripts.processTimers(timeManager.getSimulationTime(), timeManager.getGameTime());
|
||||||
double gameTime = mWorldView.getGameTime();
|
|
||||||
|
|
||||||
mGlobalScripts.processTimers(simulationTime, gameTime);
|
|
||||||
for (LocalScripts* scripts : mActiveLocalScripts)
|
for (LocalScripts* scripts : mActiveLocalScripts)
|
||||||
scripts->processTimers(simulationTime, gameTime);
|
scripts->processTimers(timeManager.getSimulationTime(), timeManager.getGameTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run event handlers for events that were sent before `finalizeEventBatch`.
|
// Run event handlers for events that were sent before `finalizeEventBatch`.
|
||||||
@ -171,8 +167,9 @@ namespace MWLua
|
|||||||
|
|
||||||
// Run engine handlers
|
// Run engine handlers
|
||||||
mEngineEvents.callEngineHandlers();
|
mEngineEvents.callEngineHandlers();
|
||||||
if (!mWorldView.isPaused())
|
if (!timeManager.isPaused())
|
||||||
{
|
{
|
||||||
|
float frameDuration = MWBase::Environment::get().getFrameDuration();
|
||||||
for (LocalScripts* scripts : mActiveLocalScripts)
|
for (LocalScripts* scripts : mActiveLocalScripts)
|
||||||
scripts->update(frameDuration);
|
scripts->update(frameDuration);
|
||||||
mGlobalScripts.update(frameDuration);
|
mGlobalScripts.update(frameDuration);
|
||||||
@ -220,17 +217,19 @@ namespace MWLua
|
|||||||
// We apply input events in `synchronizedUpdate` rather than in `update` in order to reduce input latency.
|
// We apply input events in `synchronizedUpdate` rather than in `update` in order to reduce input latency.
|
||||||
mProcessingInputEvents = true;
|
mProcessingInputEvents = true;
|
||||||
PlayerScripts* playerScripts = dynamic_cast<PlayerScripts*>(mPlayer.getRefData().getLuaScripts());
|
PlayerScripts* playerScripts = dynamic_cast<PlayerScripts*>(mPlayer.getRefData().getLuaScripts());
|
||||||
if (playerScripts && !MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_MainMenu))
|
MWBase::WindowManager* windowManager = MWBase::Environment::get().getWindowManager();
|
||||||
|
if (playerScripts && !windowManager->containsMode(MWGui::GM_MainMenu))
|
||||||
{
|
{
|
||||||
for (const auto& event : mInputEvents)
|
for (const auto& event : mInputEvents)
|
||||||
playerScripts->processInputEvent(event);
|
playerScripts->processInputEvent(event);
|
||||||
}
|
}
|
||||||
mInputEvents.clear();
|
mInputEvents.clear();
|
||||||
if (playerScripts)
|
if (playerScripts)
|
||||||
playerScripts->onFrame(mWorldView.isPaused() ? 0.0 : MWBase::Environment::get().getFrameDuration());
|
playerScripts->onFrame(MWBase::Environment::get().getWorld()->getTimeManager()->isPaused()
|
||||||
|
? 0.0
|
||||||
|
: MWBase::Environment::get().getFrameDuration());
|
||||||
mProcessingInputEvents = false;
|
mProcessingInputEvents = false;
|
||||||
|
|
||||||
MWBase::WindowManager* windowManager = MWBase::Environment::get().getWindowManager();
|
|
||||||
for (const std::string& message : mUIMessages)
|
for (const std::string& message : mUIMessages)
|
||||||
windowManager->messageBox(message);
|
windowManager->messageBox(message);
|
||||||
mUIMessages.clear();
|
mUIMessages.clear();
|
||||||
@ -262,7 +261,7 @@ namespace MWLua
|
|||||||
mLuaEvents.clear();
|
mLuaEvents.clear();
|
||||||
mEngineEvents.clear();
|
mEngineEvents.clear();
|
||||||
mInputEvents.clear();
|
mInputEvents.clear();
|
||||||
mWorldView.clear();
|
mObjectLists.clear();
|
||||||
mGlobalScripts.removeAllScripts();
|
mGlobalScripts.removeAllScripts();
|
||||||
mGlobalScriptsStarted = false;
|
mGlobalScriptsStarted = false;
|
||||||
mNewGameStarted = false;
|
mNewGameStarted = false;
|
||||||
@ -284,8 +283,8 @@ namespace MWLua
|
|||||||
return;
|
return;
|
||||||
if (!mPlayer.isEmpty())
|
if (!mPlayer.isEmpty())
|
||||||
throw std::logic_error("Player is initialized twice");
|
throw std::logic_error("Player is initialized twice");
|
||||||
mWorldView.objectAddedToScene(ptr);
|
mObjectLists.objectAddedToScene(ptr);
|
||||||
mWorldView.setPlayer(ptr);
|
mObjectLists.setPlayer(ptr);
|
||||||
mPlayer = ptr;
|
mPlayer = ptr;
|
||||||
LocalScripts* localScripts = ptr.getRefData().getLuaScripts();
|
LocalScripts* localScripts = ptr.getRefData().getLuaScripts();
|
||||||
if (!localScripts)
|
if (!localScripts)
|
||||||
@ -314,7 +313,7 @@ namespace MWLua
|
|||||||
|
|
||||||
void LuaManager::objectAddedToScene(const MWWorld::Ptr& ptr)
|
void LuaManager::objectAddedToScene(const MWWorld::Ptr& ptr)
|
||||||
{
|
{
|
||||||
mWorldView.objectAddedToScene(ptr); // assigns generated RefNum if it is not set yet.
|
mObjectLists.objectAddedToScene(ptr); // assigns generated RefNum if it is not set yet.
|
||||||
mEngineEvents.addToQueue(EngineEvents::OnActive{ getId(ptr) });
|
mEngineEvents.addToQueue(EngineEvents::OnActive{ getId(ptr) });
|
||||||
|
|
||||||
LocalScripts* localScripts = ptr.getRefData().getLuaScripts();
|
LocalScripts* localScripts = ptr.getRefData().getLuaScripts();
|
||||||
@ -334,7 +333,7 @@ namespace MWLua
|
|||||||
|
|
||||||
void LuaManager::objectRemovedFromScene(const MWWorld::Ptr& ptr)
|
void LuaManager::objectRemovedFromScene(const MWWorld::Ptr& ptr)
|
||||||
{
|
{
|
||||||
mWorldView.objectRemovedFromScene(ptr);
|
mObjectLists.objectRemovedFromScene(ptr);
|
||||||
LocalScripts* localScripts = ptr.getRefData().getLuaScripts();
|
LocalScripts* localScripts = ptr.getRefData().getLuaScripts();
|
||||||
if (localScripts)
|
if (localScripts)
|
||||||
{
|
{
|
||||||
@ -400,7 +399,8 @@ namespace MWLua
|
|||||||
{
|
{
|
||||||
writer.startRecord(ESM::REC_LUAM);
|
writer.startRecord(ESM::REC_LUAM);
|
||||||
|
|
||||||
mWorldView.save(writer);
|
writer.writeHNT<double>("LUAW", MWBase::Environment::get().getWorld()->getTimeManager()->getSimulationTime());
|
||||||
|
writer.writeFormId(MWBase::Environment::get().getWorldModel()->getLastGeneratedRefNum(), true);
|
||||||
ESM::LuaScripts globalScripts;
|
ESM::LuaScripts globalScripts;
|
||||||
mGlobalScripts.save(globalScripts);
|
mGlobalScripts.save(globalScripts);
|
||||||
globalScripts.save(writer);
|
globalScripts.save(writer);
|
||||||
@ -414,7 +414,14 @@ namespace MWLua
|
|||||||
if (type != ESM::REC_LUAM)
|
if (type != ESM::REC_LUAM)
|
||||||
throw std::runtime_error("ESM::REC_LUAM is expected");
|
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;
|
ESM::LuaScripts globalScripts;
|
||||||
globalScripts.load(reader);
|
globalScripts.load(reader);
|
||||||
mLuaEvents.load(mLua.sol(), reader, mContentFileMapping, mGlobalLoader.get());
|
mLuaEvents.load(mLua.sol(), reader, mContentFileMapping, mGlobalLoader.get());
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <osg/Stats>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
#include <components/lua/luastate.hpp>
|
#include <components/lua/luastate.hpp>
|
||||||
@ -17,7 +18,7 @@
|
|||||||
#include "localscripts.hpp"
|
#include "localscripts.hpp"
|
||||||
#include "luaevents.hpp"
|
#include "luaevents.hpp"
|
||||||
#include "object.hpp"
|
#include "object.hpp"
|
||||||
#include "worldview.hpp"
|
#include "objectlists.hpp"
|
||||||
|
|
||||||
namespace MWLua
|
namespace MWLua
|
||||||
{
|
{
|
||||||
@ -156,7 +157,7 @@ namespace MWLua
|
|||||||
|
|
||||||
GlobalScripts mGlobalScripts{ &mLua };
|
GlobalScripts mGlobalScripts{ &mLua };
|
||||||
std::set<LocalScripts*> mActiveLocalScripts;
|
std::set<LocalScripts*> mActiveLocalScripts;
|
||||||
WorldView mWorldView;
|
ObjectLists mObjectLists;
|
||||||
|
|
||||||
MWWorld::Ptr mPlayer;
|
MWWorld::Ptr mPlayer;
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
#include "../mwphysics/raycasting.hpp"
|
#include "../mwphysics/raycasting.hpp"
|
||||||
|
|
||||||
#include "luamanagerimp.hpp"
|
#include "luamanagerimp.hpp"
|
||||||
#include "worldview.hpp"
|
#include "objectlists.hpp"
|
||||||
|
|
||||||
namespace sol
|
namespace sol
|
||||||
{
|
{
|
||||||
@ -25,7 +25,7 @@ namespace MWLua
|
|||||||
sol::table initNearbyPackage(const Context& context)
|
sol::table initNearbyPackage(const Context& context)
|
||||||
{
|
{
|
||||||
sol::table api(context.mLua->sol(), sol::create);
|
sol::table api(context.mLua->sol(), sol::create);
|
||||||
WorldView* worldView = context.mWorldView;
|
ObjectLists* objectLists = context.mObjectLists;
|
||||||
|
|
||||||
sol::usertype<MWPhysics::RayCastingResult> rayResult
|
sol::usertype<MWPhysics::RayCastingResult> rayResult
|
||||||
= context.mLua->sol().new_usertype<MWPhysics::RayCastingResult>("RayCastingResult");
|
= context.mLua->sol().new_usertype<MWPhysics::RayCastingResult>("RayCastingResult");
|
||||||
@ -131,12 +131,12 @@ namespace MWLua
|
|||||||
return LObject(refId.getIf<ESM::FormIdRefId>()->getValue());
|
return LObject(refId.getIf<ESM::FormIdRefId>()->getValue());
|
||||||
};
|
};
|
||||||
|
|
||||||
api["activators"] = LObjectList{ worldView->getActivatorsInScene() };
|
api["activators"] = LObjectList{ objectLists->getActivatorsInScene() };
|
||||||
api["actors"] = LObjectList{ worldView->getActorsInScene() };
|
api["actors"] = LObjectList{ objectLists->getActorsInScene() };
|
||||||
api["containers"] = LObjectList{ worldView->getContainersInScene() };
|
api["containers"] = LObjectList{ objectLists->getContainersInScene() };
|
||||||
api["doors"] = LObjectList{ worldView->getDoorsInScene() };
|
api["doors"] = LObjectList{ objectLists->getDoorsInScene() };
|
||||||
api["items"] = LObjectList{ worldView->getItemsInScene() };
|
api["items"] = LObjectList{ objectLists->getItemsInScene() };
|
||||||
api["players"] = LObjectList{ worldView->getPlayers() };
|
api["players"] = LObjectList{ objectLists->getPlayers() };
|
||||||
|
|
||||||
api["NAVIGATOR_FLAGS"]
|
api["NAVIGATOR_FLAGS"]
|
||||||
= LuaUtil::makeStrictReadOnly(context.mLua->tableFromPairs<std::string_view, DetourNavigator::Flag>({
|
= LuaUtil::makeStrictReadOnly(context.mLua->tableFromPairs<std::string_view, DetourNavigator::Flag>({
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#include "worldview.hpp"
|
#include "objectlists.hpp"
|
||||||
|
|
||||||
#include <components/esm3/esmreader.hpp>
|
#include <components/esm3/esmreader.hpp>
|
||||||
#include <components/esm3/esmwriter.hpp>
|
#include <components/esm3/esmwriter.hpp>
|
||||||
@ -6,28 +6,27 @@
|
|||||||
|
|
||||||
#include <components/misc/resourcehelpers.hpp>
|
#include <components/misc/resourcehelpers.hpp>
|
||||||
|
|
||||||
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/windowmanager.hpp"
|
#include "../mwbase/windowmanager.hpp"
|
||||||
|
|
||||||
#include "../mwclass/container.hpp"
|
#include "../mwclass/container.hpp"
|
||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
#include "../mwworld/timestamp.hpp"
|
|
||||||
#include "../mwworld/worldmodel.hpp"
|
#include "../mwworld/worldmodel.hpp"
|
||||||
|
|
||||||
namespace MWLua
|
namespace MWLua
|
||||||
{
|
{
|
||||||
|
|
||||||
void WorldView::update()
|
void ObjectLists::update()
|
||||||
{
|
{
|
||||||
mActivatorsInScene.updateList();
|
mActivatorsInScene.updateList();
|
||||||
mActorsInScene.updateList();
|
mActorsInScene.updateList();
|
||||||
mContainersInScene.updateList();
|
mContainersInScene.updateList();
|
||||||
mDoorsInScene.updateList();
|
mDoorsInScene.updateList();
|
||||||
mItemsInScene.updateList();
|
mItemsInScene.updateList();
|
||||||
mPaused = MWBase::Environment::get().getWindowManager()->isGuiMode();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldView::clear()
|
void ObjectLists::clear()
|
||||||
{
|
{
|
||||||
mActivatorsInScene.clear();
|
mActivatorsInScene.clear();
|
||||||
mActorsInScene.clear();
|
mActorsInScene.clear();
|
||||||
@ -36,7 +35,7 @@ namespace MWLua
|
|||||||
mItemsInScene.clear();
|
mItemsInScene.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
WorldView::ObjectGroup* WorldView::chooseGroup(const MWWorld::Ptr& ptr)
|
ObjectLists::ObjectGroup* ObjectLists::chooseGroup(const MWWorld::Ptr& ptr)
|
||||||
{
|
{
|
||||||
// It is important to check `isMarker` first.
|
// It is important to check `isMarker` first.
|
||||||
// For example "prisonmarker" has class "Door" despite that it is only an invisible marker.
|
// For example "prisonmarker" has class "Door" despite that it is only an invisible marker.
|
||||||
@ -56,7 +55,7 @@ namespace MWLua
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldView::objectAddedToScene(const MWWorld::Ptr& ptr)
|
void ObjectLists::objectAddedToScene(const MWWorld::Ptr& ptr)
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getWorldModel()->registerPtr(ptr);
|
MWBase::Environment::get().getWorldModel()->registerPtr(ptr);
|
||||||
ObjectGroup* group = chooseGroup(ptr);
|
ObjectGroup* group = chooseGroup(ptr);
|
||||||
@ -64,36 +63,14 @@ namespace MWLua
|
|||||||
addToGroup(*group, ptr);
|
addToGroup(*group, ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldView::objectRemovedFromScene(const MWWorld::Ptr& ptr)
|
void ObjectLists::objectRemovedFromScene(const MWWorld::Ptr& ptr)
|
||||||
{
|
{
|
||||||
ObjectGroup* group = chooseGroup(ptr);
|
ObjectGroup* group = chooseGroup(ptr);
|
||||||
if (group)
|
if (group)
|
||||||
removeFromGroup(*group, ptr);
|
removeFromGroup(*group, ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
double WorldView::getGameTime() const
|
void ObjectLists::ObjectGroup::updateList()
|
||||||
{
|
|
||||||
MWBase::World* world = MWBase::Environment::get().getWorld();
|
|
||||||
MWWorld::TimeStamp timeStamp = world->getTimeStamp();
|
|
||||||
return (static_cast<double>(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)
|
if (mChanged)
|
||||||
{
|
{
|
||||||
@ -104,20 +81,20 @@ namespace MWLua
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldView::ObjectGroup::clear()
|
void ObjectLists::ObjectGroup::clear()
|
||||||
{
|
{
|
||||||
mChanged = false;
|
mChanged = false;
|
||||||
mList->clear();
|
mList->clear();
|
||||||
mSet.clear();
|
mSet.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldView::addToGroup(ObjectGroup& group, const MWWorld::Ptr& ptr)
|
void ObjectLists::addToGroup(ObjectGroup& group, const MWWorld::Ptr& ptr)
|
||||||
{
|
{
|
||||||
group.mSet.insert(getId(ptr));
|
group.mSet.insert(getId(ptr));
|
||||||
group.mChanged = true;
|
group.mChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldView::removeFromGroup(ObjectGroup& group, const MWWorld::Ptr& ptr)
|
void ObjectLists::removeFromGroup(ObjectGroup& group, const MWWorld::Ptr& ptr)
|
||||||
{
|
{
|
||||||
group.mSet.erase(getId(ptr));
|
group.mSet.erase(getId(ptr));
|
||||||
group.mChanged = true;
|
group.mChanged = true;
|
@ -1,51 +1,20 @@
|
|||||||
#ifndef MWLUA_WORLDVIEW_H
|
#ifndef MWLUA_OBJECTLISTS_H
|
||||||
#define MWLUA_WORLDVIEW_H
|
#define MWLUA_OBJECTLISTS_H
|
||||||
|
|
||||||
#include "object.hpp"
|
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
|
||||||
#include "../mwbase/world.hpp"
|
|
||||||
|
|
||||||
#include "../mwworld/globals.hpp"
|
|
||||||
|
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
namespace ESM
|
#include "object.hpp"
|
||||||
{
|
|
||||||
class ESMWriter;
|
|
||||||
class ESMReader;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace MWLua
|
namespace MWLua
|
||||||
{
|
{
|
||||||
|
|
||||||
// WorldView is a kind of an extension to mwworld. It was created on initial stage of
|
// ObjectLists is used to track lists of game objects like nearby.items, nearby.actors, etc.
|
||||||
// OpenMW Lua development in order to minimize the risk of merge conflicts.
|
class ObjectLists
|
||||||
// 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
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void update(); // Should be called every frame.
|
void update(); // Should be called every frame.
|
||||||
void clear(); // Should be called every time before starting or loading a new game.
|
void clear(); // Should be called every time before starting or loading a new game.
|
||||||
|
|
||||||
// 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 getActivatorsInScene() const { return mActivatorsInScene.mList; }
|
||||||
ObjectIdList getActorsInScene() const { return mActorsInScene.mList; }
|
ObjectIdList getActorsInScene() const { return mActorsInScene.mList; }
|
||||||
ObjectIdList getContainersInScene() const { return mContainersInScene.mList; }
|
ObjectIdList getContainersInScene() const { return mContainersInScene.mList; }
|
||||||
@ -58,9 +27,6 @@ namespace MWLua
|
|||||||
|
|
||||||
void setPlayer(const MWWorld::Ptr& player) { *mPlayers = { getId(player) }; }
|
void setPlayer(const MWWorld::Ptr& player) { *mPlayers = { getId(player) }; }
|
||||||
|
|
||||||
void load(ESM::ESMReader& esm);
|
|
||||||
void save(ESM::ESMWriter& esm) const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct ObjectGroup
|
struct ObjectGroup
|
||||||
{
|
{
|
||||||
@ -82,11 +48,8 @@ namespace MWLua
|
|||||||
ObjectGroup mDoorsInScene;
|
ObjectGroup mDoorsInScene;
|
||||||
ObjectGroup mItemsInScene;
|
ObjectGroup mItemsInScene;
|
||||||
ObjectIdList mPlayers = std::make_shared<std::vector<ObjectId>>();
|
ObjectIdList mPlayers = std::make_shared<std::vector<ObjectId>>();
|
||||||
|
|
||||||
double mSimulationTime = 0;
|
|
||||||
bool mPaused = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // MWLUA_WORLDVIEW_H
|
#endif // MWLUA_OBJECTLISTS_H
|
@ -1,6 +1,7 @@
|
|||||||
#include "postprocessingbindings.hpp"
|
#include "postprocessingbindings.hpp"
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
|
#include "../mwbase/world.hpp"
|
||||||
#include "../mwrender/postprocessor.hpp"
|
#include "../mwrender/postprocessor.hpp"
|
||||||
|
|
||||||
#include "luamanagerimp.hpp"
|
#include "luamanagerimp.hpp"
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "localscripts.hpp"
|
#include "localscripts.hpp"
|
||||||
#include "luamanagerimp.hpp"
|
#include "luamanagerimp.hpp"
|
||||||
|
|
||||||
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwmechanics/creaturestats.hpp"
|
#include "../mwmechanics/creaturestats.hpp"
|
||||||
#include "../mwmechanics/npcstats.hpp"
|
#include "../mwmechanics/npcstats.hpp"
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include "context.hpp"
|
#include "context.hpp"
|
||||||
#include "luamanagerimp.hpp"
|
#include "luamanagerimp.hpp"
|
||||||
|
|
||||||
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/windowmanager.hpp"
|
#include "../mwbase/windowmanager.hpp"
|
||||||
|
|
||||||
namespace MWLua
|
namespace MWLua
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#include "../mwworld/cellstore.hpp"
|
#include "../mwworld/cellstore.hpp"
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
#include "../mwworld/datetimemanager.hpp"
|
||||||
#include "../mwworld/esmstore.hpp"
|
#include "../mwworld/esmstore.hpp"
|
||||||
#include "../mwworld/inventorystore.hpp"
|
#include "../mwworld/inventorystore.hpp"
|
||||||
#include "../mwworld/player.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.
|
// Take a maximum remaining duration of Stunted Magicka effects (-1 is a constant one) in game hours.
|
||||||
if (remainingTime > 0)
|
if (remainingTime > 0)
|
||||||
{
|
{
|
||||||
double timeScale = MWBase::Environment::get().getWorld()->getTimeScaleFactor();
|
double timeScale = MWBase::Environment::get().getWorld()->getTimeManager()->getGameTimeScale();
|
||||||
if (timeScale == 0.0)
|
if (timeScale == 0.0)
|
||||||
timeScale = 1;
|
timeScale = 1;
|
||||||
|
|
||||||
@ -1864,7 +1865,7 @@ namespace MWMechanics
|
|||||||
void Actors::rest(double hours, bool sleep) const
|
void Actors::rest(double hours, bool sleep) const
|
||||||
{
|
{
|
||||||
float duration = hours * 3600.f;
|
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)
|
if (timeScale != 0.f)
|
||||||
duration /= timeScale;
|
duration /= timeScale;
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
#include "../mwworld/cellstore.hpp"
|
#include "../mwworld/cellstore.hpp"
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
#include "../mwworld/datetimemanager.hpp"
|
||||||
|
|
||||||
#include "character.hpp"
|
#include "character.hpp"
|
||||||
#include "creaturestats.hpp"
|
#include "creaturestats.hpp"
|
||||||
@ -72,7 +73,8 @@ namespace MWMechanics
|
|||||||
// and the duration is not infinite, the package is complete.
|
// and the duration is not infinite, the package is complete.
|
||||||
if (mDuration > 0)
|
if (mDuration > 0)
|
||||||
{
|
{
|
||||||
mRemainingDuration -= ((duration * MWBase::Environment::get().getWorld()->getTimeScaleFactor()) / 3600);
|
mRemainingDuration
|
||||||
|
-= ((duration * MWBase::Environment::get().getWorld()->getTimeManager()->getGameTimeScale()) / 3600);
|
||||||
if (mRemainingDuration <= 0)
|
if (mRemainingDuration <= 0)
|
||||||
{
|
{
|
||||||
mRemainingDuration = mDuration;
|
mRemainingDuration = mDuration;
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
#include "../mwworld/cellstore.hpp"
|
#include "../mwworld/cellstore.hpp"
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
#include "../mwworld/datetimemanager.hpp"
|
||||||
|
|
||||||
#include "character.hpp"
|
#include "character.hpp"
|
||||||
#include "creaturestats.hpp"
|
#include "creaturestats.hpp"
|
||||||
@ -156,7 +157,9 @@ namespace MWMechanics
|
|||||||
// Check if we've run out of time
|
// Check if we've run out of time
|
||||||
if (mDuration > 0)
|
if (mDuration > 0)
|
||||||
{
|
{
|
||||||
mRemainingDuration -= ((duration * MWBase::Environment::get().getWorld()->getTimeScaleFactor()) / 3600);
|
mRemainingDuration
|
||||||
|
-= ((duration * MWBase::Environment::get().getWorld()->getTimeManager()->getGameTimeScale())
|
||||||
|
/ 3600);
|
||||||
if (mRemainingDuration <= 0)
|
if (mRemainingDuration <= 0)
|
||||||
{
|
{
|
||||||
mRemainingDuration = mDuration;
|
mRemainingDuration = mDuration;
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
#include "../mwworld/cellstore.hpp"
|
#include "../mwworld/cellstore.hpp"
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
#include "../mwworld/datetimemanager.hpp"
|
||||||
#include "../mwworld/esmstore.hpp"
|
#include "../mwworld/esmstore.hpp"
|
||||||
|
|
||||||
#include "../mwphysics/raycasting.hpp"
|
#include "../mwphysics/raycasting.hpp"
|
||||||
@ -200,7 +201,8 @@ namespace MWMechanics
|
|||||||
// get or create temporary storage
|
// get or create temporary storage
|
||||||
AiWanderStorage& storage = state.get<AiWanderStorage>();
|
AiWanderStorage& storage = state.get<AiWanderStorage>();
|
||||||
|
|
||||||
mRemainingDuration -= ((duration * MWBase::Environment::get().getWorld()->getTimeScaleFactor()) / 3600);
|
mRemainingDuration
|
||||||
|
-= ((duration * MWBase::Environment::get().getWorld()->getTimeManager()->getGameTimeScale()) / 3600);
|
||||||
|
|
||||||
cStats.setDrawState(DrawState::Nothing);
|
cStats.setDrawState(DrawState::Nothing);
|
||||||
cStats.setMovementFlag(CreatureStats::Flag_Run, false);
|
cStats.setMovementFlag(CreatureStats::Flag_Run, false);
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
#include <components/nifosg/particle.hpp>
|
#include <components/nifosg/particle.hpp>
|
||||||
|
|
||||||
|
#include "../mwworld/datetimemanager.hpp"
|
||||||
#include "../mwworld/weather.hpp"
|
#include "../mwworld/weather.hpp"
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
@ -559,7 +560,7 @@ namespace MWRender
|
|||||||
}
|
}
|
||||||
|
|
||||||
// rotate the stars by 360 degrees every 4 days
|
// 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);
|
* osg::DegreesToRadians(360.f) / (3600 * 96.f);
|
||||||
if (mAtmosphereNightNode->getNodeMask() != 0)
|
if (mAtmosphereNightNode->getNodeMask() != 0)
|
||||||
mAtmosphereNightNode->setAttitude(osg::Quat(mAtmosphereNightRoll, osg::Vec3f(0, 0, 1)));
|
mAtmosphereNightNode->setAttitude(osg::Quat(mAtmosphereNightRoll, osg::Vec3f(0, 0, 1)));
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
|
|
||||||
#include "../mwworld/cellstore.hpp"
|
#include "../mwworld/cellstore.hpp"
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
#include "../mwworld/datetimemanager.hpp"
|
||||||
#include "../mwworld/esmstore.hpp"
|
#include "../mwworld/esmstore.hpp"
|
||||||
#include "../mwworld/globals.hpp"
|
#include "../mwworld/globals.hpp"
|
||||||
#include "../mwworld/scene.hpp"
|
#include "../mwworld/scene.hpp"
|
||||||
@ -227,7 +228,7 @@ void MWState::StateManager::saveGame(std::string_view description, const Slot* s
|
|||||||
profile.mPlayerClassId = classId;
|
profile.mPlayerClassId = classId;
|
||||||
|
|
||||||
profile.mPlayerCellName = world.getCellName();
|
profile.mPlayerCellName = world.getCellName();
|
||||||
profile.mInGameTime = world.getEpochTimeStamp();
|
profile.mInGameTime = world.getTimeManager()->getEpochTimeStamp();
|
||||||
profile.mTimePlayed = mTimePlayed;
|
profile.mTimePlayed = mTimePlayed;
|
||||||
profile.mDescription = description;
|
profile.mDescription = description;
|
||||||
|
|
||||||
|
@ -3,6 +3,9 @@
|
|||||||
#include <components/l10n/manager.hpp>
|
#include <components/l10n/manager.hpp>
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
|
#include "../mwbase/soundmanager.hpp"
|
||||||
|
#include "../mwbase/windowmanager.hpp"
|
||||||
|
#include "../mwbase/world.hpp"
|
||||||
|
|
||||||
#include "duration.hpp"
|
#include "duration.hpp"
|
||||||
#include "globals.hpp"
|
#include "globals.hpp"
|
||||||
@ -53,7 +56,10 @@ namespace MWWorld
|
|||||||
mDay = globalVariables[Globals::sDay].getInteger();
|
mDay = globalVariables[Globals::sDay].getInteger();
|
||||||
mMonth = globalVariables[Globals::sMonth].getInteger();
|
mMonth = globalVariables[Globals::sMonth].getInteger();
|
||||||
mYear = globalVariables[Globals::sYear].getInteger();
|
mYear = globalVariables[Globals::sYear].getInteger();
|
||||||
mTimeScale = globalVariables[Globals::sTimeScale].getFloat();
|
mGameTimeScale = globalVariables[Globals::sTimeScale].getFloat();
|
||||||
|
setSimulationTimeScale(1.0);
|
||||||
|
mPaused = false;
|
||||||
|
mPausedTags.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DateTimeManager::setHour(double hour)
|
void DateTimeManager::setHour(double hour)
|
||||||
@ -103,9 +109,9 @@ namespace MWWorld
|
|||||||
return TimeStamp(mGameHour, mDaysPassed);
|
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
|
ESM::EpochTimeStamp DateTimeManager::getEpochTimeStamp() const
|
||||||
@ -199,7 +205,7 @@ namespace MWWorld
|
|||||||
}
|
}
|
||||||
else if (name == Globals::sTimeScale)
|
else if (name == Globals::sTimeScale)
|
||||||
{
|
{
|
||||||
mTimeScale = value;
|
mGameTimeScale = value;
|
||||||
}
|
}
|
||||||
else if (name == Globals::sDaysPassed)
|
else if (name == Globals::sDaysPassed)
|
||||||
{
|
{
|
||||||
@ -232,7 +238,7 @@ namespace MWWorld
|
|||||||
}
|
}
|
||||||
else if (name == Globals::sTimeScale)
|
else if (name == Globals::sTimeScale)
|
||||||
{
|
{
|
||||||
mTimeScale = static_cast<float>(value);
|
mGameTimeScale = static_cast<float>(value);
|
||||||
}
|
}
|
||||||
else if (name == Globals::sDaysPassed)
|
else if (name == Globals::sDaysPassed)
|
||||||
{
|
{
|
||||||
@ -241,4 +247,22 @@ namespace MWWorld
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DateTimeManager::setSimulationTimeScale(float scale)
|
||||||
|
{
|
||||||
|
mSimulationTimeScale = std::max(0.f, scale);
|
||||||
|
MWBase::Environment::get().getSoundManager()->setSimulationTimeScale(mSimulationTimeScale);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DateTimeManager::unpause(std::string_view tag)
|
||||||
|
{
|
||||||
|
auto it = mPausedTags.find(tag);
|
||||||
|
if (it != mPausedTags.end())
|
||||||
|
mPausedTags.erase(it);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DateTimeManager::updateIsPaused()
|
||||||
|
{
|
||||||
|
mPaused = !mPausedTags.empty() || MWBase::Environment::get().getWindowManager()->isGuiMode();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#ifndef GAME_MWWORLD_DATETIMEMANAGER_H
|
#ifndef GAME_MWWORLD_DATETIMEMANAGER_H
|
||||||
#define GAME_MWWORLD_DATETIMEMANAGER_H
|
#define GAME_MWWORLD_DATETIMEMANAGER_H
|
||||||
|
|
||||||
|
#include <set>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
|
||||||
#include "globalvariablename.hpp"
|
#include "globalvariablename.hpp"
|
||||||
@ -14,31 +15,58 @@ namespace MWWorld
|
|||||||
{
|
{
|
||||||
class Globals;
|
class Globals;
|
||||||
class TimeStamp;
|
class TimeStamp;
|
||||||
|
class World;
|
||||||
|
|
||||||
class DateTimeManager
|
class DateTimeManager
|
||||||
{
|
{
|
||||||
int mDaysPassed = 0;
|
public:
|
||||||
int mDay = 0;
|
// Game time.
|
||||||
int mMonth = 0;
|
// Note that game time generally goes faster than the simulation time.
|
||||||
int mYear = 0;
|
std::string_view getMonthName(int month = -1) const; // -1: current month
|
||||||
float mGameHour = 0.f;
|
TimeStamp getTimeStamp() const;
|
||||||
float mTimeScale = 0.f;
|
ESM::EpochTimeStamp getEpochTimeStamp() const;
|
||||||
|
double getGameTime() const { return (static_cast<double>(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
|
||||||
|
|
||||||
|
// Whether the game is paused in the current frame.
|
||||||
|
bool isPaused() const { return mPaused; }
|
||||||
|
|
||||||
|
// Pauses the game starting from the next frame until `unpause` is called with the same tag.
|
||||||
|
void pause(std::string_view tag) { mPausedTags.emplace(tag); }
|
||||||
|
void unpause(std::string_view tag);
|
||||||
|
const std::set<std::string, std::less<>>& getPausedTags() const { return mPausedTags; }
|
||||||
|
|
||||||
|
// Updates mPaused; should be called once a frame.
|
||||||
|
void updateIsPaused();
|
||||||
|
|
||||||
|
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 setHour(double hour);
|
||||||
void setDay(int day);
|
void setDay(int day);
|
||||||
void setMonth(int month);
|
void setMonth(int month);
|
||||||
|
|
||||||
public:
|
int mDaysPassed = 0;
|
||||||
std::string_view getMonthName(int month) const;
|
int mDay = 0;
|
||||||
TimeStamp getTimeStamp() const;
|
int mMonth = 0;
|
||||||
ESM::EpochTimeStamp getEpochTimeStamp() const;
|
int mYear = 0;
|
||||||
float getTimeScaleFactor() const;
|
float mGameHour = 0.f;
|
||||||
|
float mGameTimeScale = 0.f;
|
||||||
void advanceTime(double hours, Globals& globalVariables);
|
float mSimulationTimeScale = 1.0;
|
||||||
|
double mSimulationTime = 0.0;
|
||||||
void setup(Globals& globalVariables);
|
bool mPaused = false;
|
||||||
bool updateGlobalInt(GlobalVariableName name, int value);
|
std::set<std::string, std::less<>> mPausedTags;
|
||||||
bool updateGlobalFloat(GlobalVariableName name, float value);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,7 +249,7 @@ namespace MWWorld
|
|||||||
: mResourceSystem(resourceSystem)
|
: mResourceSystem(resourceSystem)
|
||||||
, mLocalScripts(mStore)
|
, mLocalScripts(mStore)
|
||||||
, mWorldModel(mStore, mReaders)
|
, mWorldModel(mStore, mReaders)
|
||||||
, mCurrentDate(std::make_unique<DateTimeManager>())
|
, mTimeManager(std::make_unique<DateTimeManager>())
|
||||||
, mSky(true)
|
, mSky(true)
|
||||||
, mGodMode(false)
|
, mGodMode(false)
|
||||||
, mScriptsEnabled(true)
|
, mScriptsEnabled(true)
|
||||||
@ -319,7 +319,7 @@ namespace MWWorld
|
|||||||
void World::fillGlobalVariables()
|
void World::fillGlobalVariables()
|
||||||
{
|
{
|
||||||
mGlobalVariables.fill(mStore);
|
mGlobalVariables.fill(mStore);
|
||||||
mCurrentDate->setup(mGlobalVariables);
|
mTimeManager->setup(mGlobalVariables);
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::startNewGame(bool bypass)
|
void World::startNewGame(bool bypass)
|
||||||
@ -399,7 +399,7 @@ namespace MWWorld
|
|||||||
mPhysics->toggleCollisionMode();
|
mPhysics->toggleCollisionMode();
|
||||||
|
|
||||||
MWBase::Environment::get().getWindowManager()->updatePlayer();
|
MWBase::Environment::get().getWindowManager()->updatePlayer();
|
||||||
mCurrentDate->setup(mGlobalVariables);
|
mTimeManager->setup(mGlobalVariables);
|
||||||
|
|
||||||
// Initial seed.
|
// Initial seed.
|
||||||
mPrng.seed(mRandomSeed);
|
mPrng.seed(mRandomSeed);
|
||||||
@ -615,7 +615,7 @@ namespace MWWorld
|
|||||||
|
|
||||||
void World::setGlobalInt(GlobalVariableName name, int value)
|
void World::setGlobalInt(GlobalVariableName name, int value)
|
||||||
{
|
{
|
||||||
bool dateUpdated = mCurrentDate->updateGlobalInt(name, value);
|
bool dateUpdated = mTimeManager->updateGlobalInt(name, value);
|
||||||
if (dateUpdated)
|
if (dateUpdated)
|
||||||
updateSkyDate();
|
updateSkyDate();
|
||||||
|
|
||||||
@ -624,7 +624,7 @@ namespace MWWorld
|
|||||||
|
|
||||||
void World::setGlobalFloat(GlobalVariableName name, float value)
|
void World::setGlobalFloat(GlobalVariableName name, float value)
|
||||||
{
|
{
|
||||||
bool dateUpdated = mCurrentDate->updateGlobalFloat(name, value);
|
bool dateUpdated = mTimeManager->updateGlobalFloat(name, value);
|
||||||
if (dateUpdated)
|
if (dateUpdated)
|
||||||
updateSkyDate();
|
updateSkyDate();
|
||||||
|
|
||||||
@ -646,11 +646,6 @@ namespace MWWorld
|
|||||||
return mGlobalVariables.getType(name);
|
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
|
std::string_view World::getCellName(const MWWorld::CellStore* cell) const
|
||||||
{
|
{
|
||||||
if (!cell)
|
if (!cell)
|
||||||
@ -893,7 +888,7 @@ namespace MWWorld
|
|||||||
// When we fast-forward time, we should recharge magic items
|
// When we fast-forward time, we should recharge magic items
|
||||||
// in all loaded cells, using game world time
|
// in all loaded cells, using game world time
|
||||||
float duration = hours * 3600;
|
float duration = hours * 3600;
|
||||||
const float timeScaleFactor = getTimeScaleFactor();
|
const float timeScaleFactor = mTimeManager->getGameTimeScale();
|
||||||
if (timeScaleFactor != 0.0f)
|
if (timeScaleFactor != 0.0f)
|
||||||
duration /= timeScaleFactor;
|
duration /= timeScaleFactor;
|
||||||
|
|
||||||
@ -901,7 +896,7 @@ namespace MWWorld
|
|||||||
}
|
}
|
||||||
|
|
||||||
mWeatherManager->advanceTime(hours, incremental);
|
mWeatherManager->advanceTime(hours, incremental);
|
||||||
mCurrentDate->advanceTime(hours, mGlobalVariables);
|
mTimeManager->advanceTime(hours, mGlobalVariables);
|
||||||
updateSkyDate();
|
updateSkyDate();
|
||||||
|
|
||||||
if (!incremental)
|
if (!incremental)
|
||||||
@ -912,25 +907,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
|
TimeStamp World::getTimeStamp() const
|
||||||
{
|
{
|
||||||
return mCurrentDate->getTimeStamp();
|
return mTimeManager->getTimeStamp();
|
||||||
}
|
|
||||||
|
|
||||||
ESM::EpochTimeStamp World::getEpochTimeStamp() const
|
|
||||||
{
|
|
||||||
return mCurrentDate->getEpochTimeStamp();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool World::toggleSky()
|
bool World::toggleSky()
|
||||||
@ -2314,7 +2293,7 @@ namespace MWWorld
|
|||||||
{
|
{
|
||||||
mStore.rebuildIdsIndex();
|
mStore.rebuildIdsIndex();
|
||||||
mStore.validateDynamic();
|
mStore.validateDynamic();
|
||||||
mCurrentDate->setup(mGlobalVariables);
|
mTimeManager->setup(mGlobalVariables);
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::setupPlayer()
|
void World::setupPlayer()
|
||||||
@ -3864,7 +3843,7 @@ namespace MWWorld
|
|||||||
|
|
||||||
void World::updateSkyDate()
|
void World::updateSkyDate()
|
||||||
{
|
{
|
||||||
ESM::EpochTimeStamp currentDate = mCurrentDate->getEpochTimeStamp();
|
ESM::EpochTimeStamp currentDate = mTimeManager->getEpochTimeStamp();
|
||||||
mRendering->skySetDate(currentDate.mDay, currentDate.mMonth);
|
mRendering->skySetDate(currentDate.mDay, currentDate.mMonth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,7 +102,7 @@ namespace MWWorld
|
|||||||
std::unique_ptr<MWRender::RenderingManager> mRendering;
|
std::unique_ptr<MWRender::RenderingManager> mRendering;
|
||||||
std::unique_ptr<MWWorld::Scene> mWorldScene;
|
std::unique_ptr<MWWorld::Scene> mWorldScene;
|
||||||
std::unique_ptr<MWWorld::WeatherManager> mWeatherManager;
|
std::unique_ptr<MWWorld::WeatherManager> mWeatherManager;
|
||||||
std::unique_ptr<MWWorld::DateTimeManager> mCurrentDate;
|
std::unique_ptr<MWWorld::DateTimeManager> mTimeManager;
|
||||||
std::unique_ptr<ProjectileManager> mProjectileManager;
|
std::unique_ptr<ProjectileManager> mProjectileManager;
|
||||||
|
|
||||||
bool mSky;
|
bool mSky;
|
||||||
@ -135,8 +135,6 @@ namespace MWWorld
|
|||||||
|
|
||||||
uint32_t mRandomSeed{};
|
uint32_t mRandomSeed{};
|
||||||
|
|
||||||
float mSimulationTimeScale = 1.0;
|
|
||||||
|
|
||||||
// not implemented
|
// not implemented
|
||||||
World(const World&);
|
World(const World&);
|
||||||
World& operator=(const World&);
|
World& operator=(const World&);
|
||||||
@ -309,15 +307,9 @@ namespace MWWorld
|
|||||||
void advanceTime(double hours, bool incremental = false) override;
|
void advanceTime(double hours, bool incremental = false) override;
|
||||||
///< Advance in-game time.
|
///< Advance in-game time.
|
||||||
|
|
||||||
std::string_view getMonthName(int month = -1) const override;
|
|
||||||
///< Return name of month (-1: current month)
|
|
||||||
|
|
||||||
TimeStamp getTimeStamp() const override;
|
TimeStamp getTimeStamp() const override;
|
||||||
///< Return current in-game time and number of day since new game start.
|
///< 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;
|
bool toggleSky() override;
|
||||||
///< \return Resulting mode
|
///< \return Resulting mode
|
||||||
|
|
||||||
@ -339,12 +331,6 @@ namespace MWWorld
|
|||||||
|
|
||||||
void modRegion(const ESM::RefId& regionid, const std::vector<char>& chances) override;
|
void modRegion(const ESM::RefId& regionid, const std::vector<char>& 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,
|
void changeToInteriorCell(const std::string_view cellName, const ESM::Position& position, bool adjustPlayerPos,
|
||||||
bool changeEvent = true) override;
|
bool changeEvent = true) override;
|
||||||
///< Move to interior cell.
|
///< Move to interior cell.
|
||||||
@ -690,6 +676,8 @@ namespace MWWorld
|
|||||||
|
|
||||||
MWRender::PostProcessor* getPostProcessor() override;
|
MWRender::PostProcessor* getPostProcessor() override;
|
||||||
|
|
||||||
|
DateTimeManager* getTimeManager() override { return mTimeManager.get(); }
|
||||||
|
|
||||||
void setActorActive(const MWWorld::Ptr& ptr, bool value) override;
|
void setActorActive(const MWWorld::Ptr& ptr, bool value) override;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
//
|
//
|
||||||
// Subrecords:
|
// Subrecords:
|
||||||
// LUAF - LuaScriptCfg::mFlags and ESM::RecNameInts list
|
// LUAF - LuaScriptCfg::mFlags and ESM::RecNameInts list
|
||||||
// LUAW - Start of MWLua::WorldView data
|
// LUAW - Simulation time and last generated RefNum
|
||||||
// LUAE - Start of MWLua::LocalEvent or MWLua::GlobalEvent (eventName)
|
// LUAE - Start of MWLua::LocalEvent or MWLua::GlobalEvent (eventName)
|
||||||
// LUAS - VFS path to a Lua script
|
// LUAS - VFS path to a Lua script
|
||||||
// LUAD - Serialized Lua variable
|
// LUAD - Serialized Lua variable
|
||||||
|
@ -106,6 +106,21 @@
|
|||||||
-- @function [parent=#world] isWorldPaused
|
-- @function [parent=#world] isWorldPaused
|
||||||
-- @return #boolean
|
-- @return #boolean
|
||||||
|
|
||||||
|
---
|
||||||
|
-- Pause the game starting from the next frame.
|
||||||
|
-- @function [parent=#world] pause
|
||||||
|
-- @param #string tag (optional) The game will be paused until `unpause` is called with the same tag.
|
||||||
|
|
||||||
|
---
|
||||||
|
-- Remove given tag from the list of pause tags. Resume the game starting from the next frame if the list became empty.
|
||||||
|
-- @function [parent=#world] unpause
|
||||||
|
-- @param #string tag (optional) Needed to undo `pause` called with this tag.
|
||||||
|
|
||||||
|
---
|
||||||
|
-- The tags that are currently pausing the game.
|
||||||
|
-- @function [parent=#world] getPausedTags
|
||||||
|
-- @return #table
|
||||||
|
|
||||||
---
|
---
|
||||||
-- Return an object by RefNum/FormId.
|
-- Return an object by RefNum/FormId.
|
||||||
-- Note: the function always returns @{openmw.core#GameObject} and doesn't validate that
|
-- Note: the function always returns @{openmw.core#GameObject} and doesn't validate that
|
||||||
|
Loading…
x
Reference in New Issue
Block a user