From 1acd1bd913c8dc68483c8ce82c0a55678fd13219 Mon Sep 17 00:00:00 2001 From: slothlife Date: Thu, 20 Mar 2014 01:25:52 -0500 Subject: [PATCH] Feature #1173: Saved Game: include weather state Removed some unused state in and changed Ogre::String to std::string in WeatherManager. --- apps/openmw/mwstate/statemanagerimp.cpp | 1 + apps/openmw/mwworld/weather.cpp | 77 ++++++++++++++++++++++--- apps/openmw/mwworld/weather.hpp | 37 +++++++----- apps/openmw/mwworld/worldimp.cpp | 4 +- components/esm/defs.hpp | 1 + 5 files changed, 93 insertions(+), 27 deletions(-) diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index d6309c1c9..c0860b784 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -266,6 +266,7 @@ void MWState::StateManager::loadGame (const Character *character, const Slot *sl case ESM::REC_GLOB: case ESM::REC_PLAY: case ESM::REC_CSTA: + case ESM::REC_WTHR: MWBase::Environment::get().getWorld()->readRecord (reader, n.val, contentFileMap); break; diff --git a/apps/openmw/mwworld/weather.cpp b/apps/openmw/mwworld/weather.cpp index 5f38ee286..b74ca6393 100644 --- a/apps/openmw/mwworld/weather.cpp +++ b/apps/openmw/mwworld/weather.cpp @@ -1,5 +1,8 @@ #include "weather.hpp" +#include +#include + #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" #include "../mwbase/soundmanager.hpp" @@ -15,6 +18,15 @@ using namespace Ogre; using namespace MWWorld; using namespace MWSound; +#define HOUR "HOUR" +#define WINDSPEED "WNSP" +#define CURRENTWEATHER "CWTH" +#define NEXTWEATHER "NWTH" +#define CURRENTREGION "CREG" +#define FIRSTUPDATE "FUPD" +#define REMAININGTRANSITIONTIME "RTTM" +#define TIMEPASSED "TMPS" + namespace { float lerp (float x, float y, float factor) @@ -91,8 +103,7 @@ WeatherManager::WeatherManager(MWRender::RenderingManager* rendering,MWWorld::Fa mHour(14), mCurrentWeather("clear"), mNextWeather(""), mFirstUpdate(true), mWeatherUpdateTime(0), mThunderFlash(0), mThunderChance(0), mThunderChanceNeeded(50), mThunderSoundDelay(0), mRemainingTransitionTime(0), - mMonth(0), mDay(0), mTimePassed(0), mFallback(fallback), mWindSpeed(0.f), - mRendering(rendering) + mTimePassed(0), mFallback(fallback), mWindSpeed(0.f), mRendering(rendering) { //Globals mThunderSoundID0 = mFallback->getFallbackString("Weather_Thunderstorm_Thunder_Sound_ID_0"); @@ -530,7 +541,7 @@ void WeatherManager::stopSounds(bool stopAll) } } -Ogre::String WeatherManager::nextWeather(const ESM::Region* region) const +std::string WeatherManager::nextWeather(const ESM::Region* region) const { std::vector probability; @@ -599,12 +610,6 @@ void WeatherManager::setHour(const float hour) mHour = hour; } -void WeatherManager::setDate(const int day, const int month) -{ - mDay = day; - mMonth = month; -} - unsigned int WeatherManager::getWeatherID() const { // Source: http://www.uesp.net/wiki/Tes3Mod:GetCurrentWeather @@ -691,6 +696,60 @@ bool WeatherManager::isDark() const return exterior && (mHour < mSunriseTime || mHour > mNightStart - 1); } +void WeatherManager::write(ESM::ESMWriter& writer) +{ + writer.startRecord(ESM::REC_WTHR); + writer.writeHNT(HOUR, mHour); + writer.writeHNT(WINDSPEED, mWindSpeed); + writer.writeHNCString(CURRENTWEATHER, mCurrentWeather.c_str()); + writer.writeHNCString(NEXTWEATHER, mNextWeather.c_str()); + writer.writeHNCString(CURRENTREGION, mCurrentRegion.c_str()); + writer.writeHNT(FIRSTUPDATE, mFirstUpdate); + writer.writeHNT(REMAININGTRANSITIONTIME, mRemainingTransitionTime); + writer.writeHNT(TIMEPASSED, mTimePassed); + writer.endRecord(ESM::REC_WTHR); +} + +bool WeatherManager::readRecord(ESM::ESMReader& reader, int32_t type) +{ + if(ESM::REC_WTHR == type) + { + // store state in locals so that if we fail to load, we don't leave the manager in a half-way state + float newHour = 0.0; + reader.getHNT(newHour, HOUR); + float newWindSpeed = 0.0; + reader.getHNT(newWindSpeed, WINDSPEED); + std::string newCurrentWeather = reader.getHNString(CURRENTWEATHER); + std::string newNextWeather = reader.getHNString(NEXTWEATHER); + std::string newCurrentRegion = reader.getHNString(CURRENTREGION); + bool newFirstUpdate = false; + reader.getHNT(newFirstUpdate, FIRSTUPDATE); + float newRemainingTransitionTime = 0.0; + reader.getHNT(newRemainingTransitionTime, REMAININGTRANSITIONTIME); + double newTimePassed = 0.0; + reader.getHNT(newTimePassed, TIMEPASSED); + + // reset other temporary state + mRegionOverrides.clear(); + stopSounds(true); // TODO: inconsistent state if this throws... + mRegionMods.clear(); + + // swap in new values, now that we can't fail + mHour = newHour; + mWindSpeed = newWindSpeed; + mCurrentWeather.swap(newCurrentWeather); + mNextWeather.swap(newNextWeather); + mCurrentRegion.swap(newCurrentRegion); + mFirstUpdate = newFirstUpdate; + mRemainingTransitionTime = newRemainingTransitionTime; + mTimePassed = newTimePassed; + + return true; + } + + return false; +} + void WeatherManager::switchToNextWeather(bool instantly) { MWBase::World* world = MWBase::Environment::get().getWorld(); diff --git a/apps/openmw/mwworld/weather.hpp b/apps/openmw/mwworld/weather.hpp index fa2d9bd8e..3167a64c2 100644 --- a/apps/openmw/mwworld/weather.hpp +++ b/apps/openmw/mwworld/weather.hpp @@ -1,12 +1,16 @@ #ifndef GAME_MWWORLD_WEATHER_H #define GAME_MWWORLD_WEATHER_H -#include +#include +#include + #include namespace ESM { struct Region; + class ESMWriter; + class ESMReader; } namespace MWRender @@ -21,8 +25,8 @@ namespace MWWorld /// Defines the actual weather that results from weather setting (see below), time of day and weather transition struct WeatherResult { - Ogre::String mCloudTexture; - Ogre::String mNextCloudTexture; + std::string mCloudTexture; + std::string mNextCloudTexture; float mCloudBlendFactor; Ogre::ColourValue mFogColor; @@ -48,14 +52,14 @@ namespace MWWorld bool mNight; // use night skybox float mNightFade; // fading factor for night skybox - Ogre::String mAmbientLoopSoundID; + std::string mAmbientLoopSoundID; }; /// Defines a single weather setting (according to INI) struct Weather { - Ogre::String mCloudTexture; + std::string mCloudTexture; // Sky (atmosphere) colors Ogre::ColourValue mSkySunriseColor, @@ -105,10 +109,10 @@ namespace MWWorld // Sound effect // This is used for Blight, Ashstorm and Blizzard (Bloodmoon) - Ogre::String mAmbientLoopSoundID; + std::string mAmbientLoopSoundID; // Rain sound effect - Ogre::String mRainLoopSoundID; + std::string mRainLoopSoundID; /// \todo disease chance }; @@ -142,8 +146,6 @@ namespace MWWorld float getWindSpeed() const; - void setDate(const int day, const int month); - void advanceTime(double hours) { mTimePassed += hours*3600; @@ -156,22 +158,25 @@ namespace MWWorld /// @see World::isDark bool isDark() const; + void write(ESM::ESMWriter& writer); + + bool readRecord(ESM::ESMReader& reader, int32_t type); + private: float mHour; - int mDay, mMonth; float mWindSpeed; MWWorld::Fallback* mFallback; void setFallbackWeather(Weather& weather,const std::string& name); MWRender::RenderingManager* mRendering; - std::map mWeatherSettings; + std::map mWeatherSettings; std::map mRegionOverrides; std::vector mSoundsPlaying; - Ogre::String mCurrentWeather; - Ogre::String mNextWeather; + std::string mCurrentWeather; + std::string mNextWeather; std::string mCurrentRegion; @@ -186,13 +191,13 @@ namespace MWWorld double mTimePassed; // time passed since last update void transition(const float factor); - void setResult(const Ogre::String& weatherType); + void setResult(const std::string& weatherType); float calculateHourFade (const std::string& moonName) const; float calculateAngleFade (const std::string& moonName, float angle) const; - void setWeather(const Ogre::String& weatherType, bool instant=false); - Ogre::String nextWeather(const ESM::Region* region) const; + void setWeather(const std::string& weatherType, bool instant=false); + std::string nextWeather(const ESM::Region* region) const; WeatherResult mResult; typedef std::map > RegionModMap; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 62bdd38ea..81afc394a 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -279,6 +279,7 @@ namespace MWWorld mGlobalVariables.write (writer); mCells.write (writer); mPlayer->write (writer); + mWeatherManager->write (writer); } void World::readRecord (ESM::ESMReader& reader, int32_t type, @@ -287,6 +288,7 @@ namespace MWWorld if (!mStore.readRecord (reader, type) && !mGlobalVariables.readRecord (reader, type) && !mPlayer->readRecord (reader, type) && + !mWeatherManager->readRecord (reader, type) && !mCells.readRecord (reader, type, contentFileMap)) { throw std::runtime_error ("unknown record in saved game"); @@ -680,8 +682,6 @@ namespace MWWorld mGlobalVariables["month"].setInteger (month); mRendering->skySetDate (day, month); - - mWeatherManager->setDate (day, month); } void World::setMonth (int month) diff --git a/components/esm/defs.hpp b/components/esm/defs.hpp index 57842796f..4d5b36c74 100644 --- a/components/esm/defs.hpp +++ b/components/esm/defs.hpp @@ -92,6 +92,7 @@ enum RecNameInts REC_CSTA = 0x41545343, REC_GMAP = 0x50414d47, REC_DIAS = 0x53414944, + REC_WTHR = 0x52485457, // format 1 REC_FILT = 0x544C4946