forked from teamnwah/openmw-tes3coop
Refactor weather transitions to act more like MW
Fixed several issues: * Waiting/jail time/training all now properly skip remaining transitions * ChangeWeather no longer permanently sets the region's weather * ChangeWeather being called during a transition now correctly queues up another transition * Corrected transition delta and factor calculations * ModRegion settings are now saved
This commit is contained in:
parent
e76401d5ea
commit
54fa5273dc
9 changed files with 890 additions and 719 deletions
|
@ -507,60 +507,40 @@ class ConvertGAME : public Converter
|
||||||
public:
|
public:
|
||||||
ConvertGAME() : mHasGame(false) {}
|
ConvertGAME() : mHasGame(false) {}
|
||||||
|
|
||||||
std::string toString(int weatherId)
|
|
||||||
{
|
|
||||||
switch (weatherId)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
return "clear";
|
|
||||||
case 1:
|
|
||||||
return "cloudy";
|
|
||||||
case 2:
|
|
||||||
return "foggy";
|
|
||||||
case 3:
|
|
||||||
return "overcast";
|
|
||||||
case 4:
|
|
||||||
return "rain";
|
|
||||||
case 5:
|
|
||||||
return "thunderstorm";
|
|
||||||
case 6:
|
|
||||||
return "ashstorm";
|
|
||||||
case 7:
|
|
||||||
return "blight";
|
|
||||||
case 8:
|
|
||||||
return "snow";
|
|
||||||
case 9:
|
|
||||||
return "blizzard";
|
|
||||||
case -1:
|
|
||||||
return "";
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
std::stringstream error;
|
|
||||||
error << "unknown weather id: " << weatherId;
|
|
||||||
throw std::runtime_error(error.str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void read(ESM::ESMReader &esm)
|
virtual void read(ESM::ESMReader &esm)
|
||||||
{
|
{
|
||||||
mGame.load(esm);
|
mGame.load(esm);
|
||||||
mHasGame = true;
|
mHasGame = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int validateWeatherID(int weatherID)
|
||||||
|
{
|
||||||
|
if(weatherID >= -1 && weatherID < 10)
|
||||||
|
{
|
||||||
|
return weatherID;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::stringstream error;
|
||||||
|
error << "Invalid weather ID:" << weatherID << std::endl;
|
||||||
|
throw std::runtime_error(error.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
virtual void write(ESM::ESMWriter &esm)
|
virtual void write(ESM::ESMWriter &esm)
|
||||||
{
|
{
|
||||||
if (!mHasGame)
|
if (!mHasGame)
|
||||||
return;
|
return;
|
||||||
esm.startRecord(ESM::REC_WTHR);
|
esm.startRecord(ESM::REC_WTHR);
|
||||||
ESM::WeatherState weather;
|
ESM::WeatherState weather;
|
||||||
weather.mCurrentWeather = toString(mGame.mGMDT.mCurrentWeather);
|
weather.mTimePassed = 0.0f;
|
||||||
weather.mNextWeather = toString(mGame.mGMDT.mNextWeather);
|
weather.mFastForward = false;
|
||||||
weather.mRemainingTransitionTime = mGame.mGMDT.mWeatherTransition/100.f*(0.015f*24*3600);
|
weather.mWeatherUpdateTime = mGame.mGMDT.mTimeOfNextTransition - mContext->mHour;
|
||||||
weather.mHour = mContext->mHour;
|
weather.mTransitionFactor = 1 - (mGame.mGMDT.mWeatherTransition / 100.0f);
|
||||||
weather.mWindSpeed = 0.f;
|
weather.mCurrentWeather = validateWeatherID(mGame.mGMDT.mCurrentWeather);
|
||||||
weather.mTimePassed = 0.0;
|
weather.mNextWeather = validateWeatherID(mGame.mGMDT.mNextWeather);
|
||||||
weather.mFirstUpdate = false;
|
weather.mQueuedWeather = -1;
|
||||||
|
// TODO: Determine how ModRegion modifiers are saved in Morrowind.
|
||||||
weather.save(esm);
|
weather.save(esm);
|
||||||
esm.endRecord(ESM::REC_WTHR);
|
esm.endRecord(ESM::REC_WTHR);
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,8 +128,7 @@ void OMW::Engine::frame(float frametime)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!guiActive)
|
if (!guiActive)
|
||||||
mEnvironment.getWorld()->advanceTime(
|
mEnvironment.getWorld()->advanceTimeByFrame(frametime);
|
||||||
frametime*mEnvironment.getWorld()->getTimeScaleFactor()/3600);
|
|
||||||
}
|
}
|
||||||
osg::Timer_t afterScriptTick = osg::Timer::instance()->tick();
|
osg::Timer_t afterScriptTick = osg::Timer::instance()->tick();
|
||||||
|
|
||||||
|
|
|
@ -188,6 +188,9 @@ namespace MWBase
|
||||||
virtual void advanceTime (double hours) = 0;
|
virtual void advanceTime (double hours) = 0;
|
||||||
///< Advance in-game time.
|
///< Advance in-game time.
|
||||||
|
|
||||||
|
virtual void advanceTimeByFrame (double frametime) = 0;
|
||||||
|
///< Advance in-game time by the duration of a frame.
|
||||||
|
|
||||||
virtual void setHour (double hour) = 0;
|
virtual void setHour (double hour) = 0;
|
||||||
///< Set in-game time hour.
|
///< Set in-game time hour.
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -14,6 +14,7 @@
|
||||||
namespace ESM
|
namespace ESM
|
||||||
{
|
{
|
||||||
struct Region;
|
struct Region;
|
||||||
|
struct RegionWeatherState;
|
||||||
class ESMWriter;
|
class ESMWriter;
|
||||||
class ESMReader;
|
class ESMReader;
|
||||||
}
|
}
|
||||||
|
@ -31,6 +32,7 @@ namespace Loading
|
||||||
namespace MWWorld
|
namespace MWWorld
|
||||||
{
|
{
|
||||||
class Fallback;
|
class Fallback;
|
||||||
|
class TimeStamp;
|
||||||
|
|
||||||
/// Defines a single weather setting (according to INI)
|
/// Defines a single weather setting (according to INI)
|
||||||
class Weather
|
class Weather
|
||||||
|
@ -110,7 +112,7 @@ namespace MWWorld
|
||||||
// Note: For Weather Blight, there is a "Disease Chance" (=0.1) setting. But according to MWSFD this feature
|
// Note: For Weather Blight, there is a "Disease Chance" (=0.1) setting. But according to MWSFD this feature
|
||||||
// is broken in the vanilla game and was disabled.
|
// is broken in the vanilla game and was disabled.
|
||||||
|
|
||||||
float transitionSeconds() const;
|
float transitionDelta() const;
|
||||||
float cloudBlendFactor(float transitionRatio) const;
|
float cloudBlendFactor(float transitionRatio) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -118,12 +120,35 @@ namespace MWWorld
|
||||||
float mCloudsMaximumPercent;
|
float mCloudsMaximumPercent;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// A class for storing a region's weather.
|
||||||
|
class RegionWeather
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit RegionWeather(const ESM::Region& region);
|
||||||
|
explicit RegionWeather(const ESM::RegionWeatherState& state);
|
||||||
|
|
||||||
|
explicit operator ESM::RegionWeatherState() const;
|
||||||
|
|
||||||
|
void setChances(const std::vector<char>& chances);
|
||||||
|
|
||||||
|
void setWeather(int weatherID);
|
||||||
|
|
||||||
|
int getWeather();
|
||||||
|
|
||||||
|
private:
|
||||||
|
int mWeather;
|
||||||
|
std::vector<char> mChances;
|
||||||
|
|
||||||
|
void chooseNewWeather();
|
||||||
|
};
|
||||||
|
|
||||||
|
/// A class that acts as a model for the moons.
|
||||||
class MoonModel
|
class MoonModel
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MoonModel(const std::string& name, const MWWorld::Fallback& fallback);
|
MoonModel(const std::string& name, const MWWorld::Fallback& fallback);
|
||||||
|
|
||||||
MWRender::MoonState calculateState(unsigned int daysPassed, float gameHour) const;
|
MWRender::MoonState calculateState(const TimeStamp& gameTime) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float mFadeInStart;
|
float mFadeInStart;
|
||||||
|
@ -137,23 +162,23 @@ namespace MWWorld
|
||||||
float mFadeEndAngle;
|
float mFadeEndAngle;
|
||||||
float mMoonShadowEarlyFadeAngle;
|
float mMoonShadowEarlyFadeAngle;
|
||||||
|
|
||||||
float angle(unsigned int daysPassed, float gameHour) const;
|
float angle(const TimeStamp& gameTime) const;
|
||||||
float moonRiseHour(unsigned int daysPassed) const;
|
float moonRiseHour(unsigned int daysPassed) const;
|
||||||
float rotation(float hours) const;
|
float rotation(float hours) const;
|
||||||
unsigned int phase(unsigned int daysPassed, float gameHour) const;
|
unsigned int phase(const TimeStamp& gameTime) const;
|
||||||
float shadowBlend(float angle) const;
|
float shadowBlend(float angle) const;
|
||||||
float hourlyAlpha(float gameHour) const;
|
float hourlyAlpha(float gameHour) const;
|
||||||
float earlyMoonShadowAlpha(float angle) const;
|
float earlyMoonShadowAlpha(float angle) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
///
|
|
||||||
/// Interface for weather settings
|
/// Interface for weather settings
|
||||||
///
|
|
||||||
class WeatherManager
|
class WeatherManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// Have to pass fallback and Store, can't use singleton since World isn't fully constructed yet at the time
|
// Have to pass fallback and Store, can't use singleton since World isn't fully constructed yet at the time
|
||||||
WeatherManager(MWRender::RenderingManager*, MWWorld::Fallback* fallback, MWWorld::ESMStore* store);
|
WeatherManager(MWRender::RenderingManager& rendering,
|
||||||
|
const MWWorld::Fallback& fallback,
|
||||||
|
MWWorld::ESMStore& store);
|
||||||
~WeatherManager();
|
~WeatherManager();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -161,8 +186,9 @@ namespace MWWorld
|
||||||
* @param region that should be changed
|
* @param region that should be changed
|
||||||
* @param ID of the weather setting to shift to
|
* @param ID of the weather setting to shift to
|
||||||
*/
|
*/
|
||||||
void changeWeather(const std::string& region, const unsigned int id);
|
void changeWeather(const std::string& regionID, const unsigned int weatherID);
|
||||||
void switchToNextWeather(bool instantly = true);
|
void modRegion(const std::string& regionID, const std::vector<char>& chances);
|
||||||
|
void playerTeleported();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Per-frame update
|
* Per-frame update
|
||||||
|
@ -173,8 +199,6 @@ namespace MWWorld
|
||||||
|
|
||||||
void stopSounds();
|
void stopSounds();
|
||||||
|
|
||||||
void setHour(const float hour);
|
|
||||||
|
|
||||||
float getWindSpeed() const;
|
float getWindSpeed() const;
|
||||||
|
|
||||||
/// Are we in an ash or blight storm?
|
/// Are we in an ash or blight storm?
|
||||||
|
@ -183,11 +207,10 @@ namespace MWWorld
|
||||||
osg::Vec3f getStormDirection() const;
|
osg::Vec3f getStormDirection() const;
|
||||||
|
|
||||||
void advanceTime(double hours);
|
void advanceTime(double hours);
|
||||||
|
void advanceTimeByFrame(double hours);
|
||||||
|
|
||||||
unsigned int getWeatherID() const;
|
unsigned int getWeatherID() const;
|
||||||
|
|
||||||
void modRegion(const std::string ®ionid, const std::vector<char> &chances);
|
|
||||||
|
|
||||||
/// @see World::isDark
|
/// @see World::isDark
|
||||||
bool isDark() const;
|
bool isDark() const;
|
||||||
|
|
||||||
|
@ -198,73 +221,77 @@ namespace MWWorld
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float mHour;
|
MWWorld::ESMStore& mStore;
|
||||||
float mWindSpeed;
|
MWRender::RenderingManager& mRendering;
|
||||||
bool mIsStorm;
|
|
||||||
osg::Vec3f mStormDirection;
|
|
||||||
|
|
||||||
MWBase::SoundPtr mAmbientSound;
|
|
||||||
std::string mPlayingSoundID;
|
|
||||||
|
|
||||||
MWWorld::ESMStore* mStore;
|
|
||||||
MWRender::RenderingManager* mRendering;
|
|
||||||
|
|
||||||
std::map<std::string, Weather> mWeatherSettings;
|
|
||||||
|
|
||||||
std::map<std::string, std::string> mRegionOverrides;
|
|
||||||
|
|
||||||
std::string mCurrentWeather;
|
|
||||||
std::string mNextWeather;
|
|
||||||
|
|
||||||
std::string mCurrentRegion;
|
|
||||||
|
|
||||||
bool mFirstUpdate;
|
|
||||||
|
|
||||||
float mRemainingTransitionTime;
|
|
||||||
|
|
||||||
float mThunderFlash;
|
|
||||||
float mThunderChance;
|
|
||||||
float mThunderChanceNeeded;
|
|
||||||
|
|
||||||
double mTimePassed; // time passed since last update
|
|
||||||
|
|
||||||
void transition(const float factor);
|
|
||||||
void setResult(const std::string& weatherType);
|
|
||||||
|
|
||||||
void setWeather(const std::string& weatherType, bool instant=false);
|
|
||||||
std::string nextWeather(const ESM::Region* region) const;
|
|
||||||
MWRender::WeatherResult mResult;
|
|
||||||
|
|
||||||
typedef std::map<std::string,std::vector<char> > RegionModMap;
|
|
||||||
RegionModMap mRegionMods;
|
|
||||||
|
|
||||||
float mRainSpeed;
|
|
||||||
float mSunriseTime;
|
float mSunriseTime;
|
||||||
float mSunsetTime;
|
float mSunsetTime;
|
||||||
float mSunriseDuration;
|
float mSunriseDuration;
|
||||||
float mSunsetDuration;
|
float mSunsetDuration;
|
||||||
float mWeatherUpdateTime;
|
// Some useful values
|
||||||
float mHoursBetweenWeatherChanges;
|
/* TODO: Use pre-sunrise_time, pre-sunset_time,
|
||||||
float mThunderFrequency;
|
* post-sunrise_time, and post-sunset_time to better
|
||||||
float mThunderThreshold;
|
* describe sunrise/sunset time.
|
||||||
float mThunderSoundDelay;
|
* These values are fallbacks attached to weather.
|
||||||
|
*/
|
||||||
float mNightStart;
|
float mNightStart;
|
||||||
float mNightEnd;
|
float mNightEnd;
|
||||||
float mDayStart;
|
float mDayStart;
|
||||||
float mDayEnd;
|
float mDayEnd;
|
||||||
|
float mHoursBetweenWeatherChanges;
|
||||||
|
float mRainSpeed;
|
||||||
|
std::vector<Weather> mWeatherSettings;
|
||||||
|
MoonModel mMasser;
|
||||||
|
MoonModel mSecunda;
|
||||||
|
|
||||||
|
float mThunderFrequency;
|
||||||
|
float mThunderThreshold;
|
||||||
std::string mThunderSoundID0;
|
std::string mThunderSoundID0;
|
||||||
std::string mThunderSoundID1;
|
std::string mThunderSoundID1;
|
||||||
std::string mThunderSoundID2;
|
std::string mThunderSoundID2;
|
||||||
std::string mThunderSoundID3;
|
std::string mThunderSoundID3;
|
||||||
MoonModel mMasser;
|
|
||||||
MoonModel mSecunda;
|
float mWindSpeed;
|
||||||
|
bool mIsStorm;
|
||||||
|
osg::Vec3f mStormDirection;
|
||||||
|
|
||||||
|
float mThunderSoundDelay;
|
||||||
|
float mThunderFlash;
|
||||||
|
float mThunderChance;
|
||||||
|
float mThunderChanceNeeded;
|
||||||
|
|
||||||
|
std::string mCurrentRegion;
|
||||||
|
float mTimePassed;
|
||||||
|
bool mFastForward;
|
||||||
|
float mWeatherUpdateTime;
|
||||||
|
float mTransitionFactor;
|
||||||
|
int mCurrentWeather;
|
||||||
|
int mNextWeather;
|
||||||
|
int mQueuedWeather;
|
||||||
|
std::map<std::string, RegionWeather> mRegions;
|
||||||
|
MWRender::WeatherResult mResult;
|
||||||
|
|
||||||
|
MWBase::SoundPtr mAmbientSound;
|
||||||
|
std::string mPlayingSoundID;
|
||||||
|
|
||||||
void addWeather(const std::string& name,
|
void addWeather(const std::string& name,
|
||||||
const MWWorld::Fallback& fallback,
|
const MWWorld::Fallback& fallback,
|
||||||
const std::string& ambientLoopSoundID = "",
|
const std::string& ambientLoopSoundID = "",
|
||||||
const std::string& particleEffect = "");
|
const std::string& particleEffect = "");
|
||||||
|
|
||||||
Weather& findWeather(const std::string& name);
|
void importRegions();
|
||||||
|
|
||||||
|
void regionalWeatherChanged(const std::string& regionID, RegionWeather& region);
|
||||||
|
bool updateWeatherTime();
|
||||||
|
bool updateWeatherRegion(const std::string& playerRegion);
|
||||||
|
void updateWeatherTransitions(const float elapsedRealSeconds);
|
||||||
|
void forceWeather(const int weatherID);
|
||||||
|
|
||||||
|
bool inTransition();
|
||||||
|
void addWeatherTransition(const int weatherID);
|
||||||
|
|
||||||
|
void calculateWeatherResult(const float gameHour);
|
||||||
|
void calculateResult(const int weatherID, const float gameHour);
|
||||||
|
void calculateTransitionResult(const float factor, const float gameHour);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -193,7 +193,7 @@ namespace MWWorld
|
||||||
|
|
||||||
mGlobalVariables.fill (mStore);
|
mGlobalVariables.fill (mStore);
|
||||||
|
|
||||||
mWeatherManager = new MWWorld::WeatherManager(mRendering,&mFallback,&mStore);
|
mWeatherManager = new MWWorld::WeatherManager(*mRendering, mFallback, mStore);
|
||||||
|
|
||||||
mWorldScene = new Scene(*mRendering, mPhysics);
|
mWorldScene = new Scene(*mRendering, mPhysics);
|
||||||
}
|
}
|
||||||
|
@ -212,6 +212,11 @@ namespace MWWorld
|
||||||
|
|
||||||
MWBase::Environment::get().getWindowManager()->updatePlayer();
|
MWBase::Environment::get().getWindowManager()->updatePlayer();
|
||||||
|
|
||||||
|
// we don't want old weather to persist on a new game
|
||||||
|
// Note that if reset later, the initial ChangeWeather that the chargen script calls will be lost.
|
||||||
|
delete mWeatherManager;
|
||||||
|
mWeatherManager = new MWWorld::WeatherManager(*mRendering, mFallback, mStore);
|
||||||
|
|
||||||
if (!bypass)
|
if (!bypass)
|
||||||
{
|
{
|
||||||
// set new game mark
|
// set new game mark
|
||||||
|
@ -265,11 +270,6 @@ namespace MWWorld
|
||||||
if (!mPhysics->toggleCollisionMode())
|
if (!mPhysics->toggleCollisionMode())
|
||||||
mPhysics->toggleCollisionMode();
|
mPhysics->toggleCollisionMode();
|
||||||
|
|
||||||
// we don't want old weather to persist on a new game
|
|
||||||
delete mWeatherManager;
|
|
||||||
mWeatherManager = 0;
|
|
||||||
mWeatherManager = new MWWorld::WeatherManager(mRendering,&mFallback,&mStore);
|
|
||||||
|
|
||||||
if (!mStartupScript.empty())
|
if (!mStartupScript.empty())
|
||||||
MWBase::Environment::get().getWindowManager()->executeInConsole(mStartupScript);
|
MWBase::Environment::get().getWindowManager()->executeInConsole(mStartupScript);
|
||||||
}
|
}
|
||||||
|
@ -804,6 +804,25 @@ namespace MWWorld
|
||||||
days + mGlobalVariables["dayspassed"].getInteger());
|
days + mGlobalVariables["dayspassed"].getInteger());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void World::advanceTimeByFrame (double frametime)
|
||||||
|
{
|
||||||
|
double hours = (frametime * getTimeScaleFactor()) / 3600.0;
|
||||||
|
|
||||||
|
MWBase::Environment::get().getMechanicsManager()->advanceTime(static_cast<float>(hours * 3600));
|
||||||
|
|
||||||
|
mWeatherManager->advanceTimeByFrame (hours);
|
||||||
|
|
||||||
|
hours += mGlobalVariables["gamehour"].getFloat();
|
||||||
|
|
||||||
|
setHour (hours);
|
||||||
|
|
||||||
|
int days = static_cast<int>(hours / 24);
|
||||||
|
|
||||||
|
if (days>0)
|
||||||
|
mGlobalVariables["dayspassed"].setInteger (
|
||||||
|
days + mGlobalVariables["dayspassed"].getInteger());
|
||||||
|
}
|
||||||
|
|
||||||
void World::setHour (double hour)
|
void World::setHour (double hour)
|
||||||
{
|
{
|
||||||
if (hour<0)
|
if (hour<0)
|
||||||
|
@ -815,8 +834,6 @@ namespace MWWorld
|
||||||
|
|
||||||
mGlobalVariables["gamehour"].setFloat(static_cast<float>(hour));
|
mGlobalVariables["gamehour"].setFloat(static_cast<float>(hour));
|
||||||
|
|
||||||
mWeatherManager->setHour(static_cast<float>(hour));
|
|
||||||
|
|
||||||
if (days>0)
|
if (days>0)
|
||||||
setDay (days + mGlobalVariables["day"].getInteger());
|
setDay (days + mGlobalVariables["day"].getInteger());
|
||||||
}
|
}
|
||||||
|
@ -2894,7 +2911,7 @@ namespace MWWorld
|
||||||
if (mPlayer->wasTeleported())
|
if (mPlayer->wasTeleported())
|
||||||
{
|
{
|
||||||
mPlayer->setTeleported(false);
|
mPlayer->setTeleported(false);
|
||||||
mWeatherManager->switchToNextWeather(true);
|
mWeatherManager->playerTeleported();
|
||||||
}
|
}
|
||||||
|
|
||||||
mWeatherManager->update(duration, paused);
|
mWeatherManager->update(duration, paused);
|
||||||
|
|
|
@ -277,6 +277,9 @@ namespace MWWorld
|
||||||
virtual void advanceTime (double hours);
|
virtual void advanceTime (double hours);
|
||||||
///< Advance in-game time.
|
///< Advance in-game time.
|
||||||
|
|
||||||
|
virtual void advanceTimeByFrame (double frametime);
|
||||||
|
///< Advance in-game time by the duration of a frame.
|
||||||
|
|
||||||
virtual void setHour (double hour);
|
virtual void setHour (double hour);
|
||||||
///< Set in-game time hour.
|
///< Set in-game time hour.
|
||||||
|
|
||||||
|
|
|
@ -5,55 +5,68 @@
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
const char* hourRecord = "HOUR";
|
const char* currentRegionRecord = "CREG";
|
||||||
const char* windSpeedRecord = "WNSP";
|
const char* timePassedRecord = "TMPS";
|
||||||
|
const char* fastForwardRecord = "FAST";
|
||||||
|
const char* weatherUpdateTimeRecord = "WUPD";
|
||||||
|
const char* transitionFactorRecord = "TRFC";
|
||||||
const char* currentWeatherRecord = "CWTH";
|
const char* currentWeatherRecord = "CWTH";
|
||||||
const char* nextWeatherRecord = "NWTH";
|
const char* nextWeatherRecord = "NWTH";
|
||||||
const char* currentRegionRecord = "CREG";
|
const char* queuedWeatherRecord = "QWTH";
|
||||||
const char* firstUpdateRecord = "FUPD";
|
const char* regionNameRecord = "RGNN";
|
||||||
const char* remainingTransitionTimeRecord = "RTTM";
|
const char* regionWeatherRecord = "RGNW";
|
||||||
const char* timePassedRecord = "TMPS";
|
const char* regionChanceRecord = "RGNC";
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace ESM
|
namespace ESM
|
||||||
{
|
{
|
||||||
void WeatherState::load(ESMReader& esm)
|
void WeatherState::load(ESMReader& esm)
|
||||||
{
|
{
|
||||||
// store values locally so that a failed load can't leave the state half set
|
mCurrentRegion = esm.getHNString(currentRegionRecord);
|
||||||
float newHour = 0.0;
|
esm.getHNT(mTimePassed, timePassedRecord);
|
||||||
esm.getHNT(newHour, hourRecord);
|
esm.getHNT(mFastForward, fastForwardRecord);
|
||||||
float newWindSpeed = 0.0;
|
esm.getHNT(mWeatherUpdateTime, weatherUpdateTimeRecord);
|
||||||
esm.getHNT(newWindSpeed, windSpeedRecord);
|
esm.getHNT(mTransitionFactor, transitionFactorRecord);
|
||||||
std::string newCurrentWeather = esm.getHNString(currentWeatherRecord);
|
esm.getHNT(mCurrentWeather, currentWeatherRecord);
|
||||||
std::string newNextWeather = esm.getHNString(nextWeatherRecord);
|
esm.getHNT(mNextWeather, nextWeatherRecord);
|
||||||
std::string newCurrentRegion = esm.getHNString(currentRegionRecord);
|
esm.getHNT(mQueuedWeather, queuedWeatherRecord);
|
||||||
bool newFirstUpdate = false;
|
|
||||||
esm.getHNT(newFirstUpdate, firstUpdateRecord);
|
|
||||||
float newRemainingTransitionTime = 0.0;
|
|
||||||
esm.getHNT(newRemainingTransitionTime, remainingTransitionTimeRecord);
|
|
||||||
double newTimePassed = 0.0;
|
|
||||||
esm.getHNT(newTimePassed, timePassedRecord);
|
|
||||||
|
|
||||||
// swap values now that it is safe to do so
|
while(esm.peekNextSub(regionNameRecord))
|
||||||
mHour = newHour;
|
{
|
||||||
mWindSpeed = newWindSpeed;
|
std::string regionID = esm.getHNString(regionNameRecord);
|
||||||
mCurrentWeather.swap(newCurrentWeather);
|
RegionWeatherState region;
|
||||||
mNextWeather.swap(newNextWeather);
|
esm.getHNT(region.mWeather, regionWeatherRecord);
|
||||||
mCurrentRegion.swap(newCurrentRegion);
|
while(esm.peekNextSub(regionChanceRecord))
|
||||||
mFirstUpdate = newFirstUpdate;
|
{
|
||||||
mRemainingTransitionTime = newRemainingTransitionTime;
|
char chance;
|
||||||
mTimePassed = newTimePassed;
|
esm.getHNT(chance, regionChanceRecord);
|
||||||
|
region.mChances.push_back(chance);
|
||||||
|
}
|
||||||
|
|
||||||
|
mRegions.insert(std::make_pair(regionID, region));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WeatherState::save(ESMWriter& esm) const
|
void WeatherState::save(ESMWriter& esm) const
|
||||||
{
|
{
|
||||||
esm.writeHNT(hourRecord, mHour);
|
|
||||||
esm.writeHNT(windSpeedRecord, mWindSpeed);
|
|
||||||
esm.writeHNCString(currentWeatherRecord, mCurrentWeather.c_str());
|
|
||||||
esm.writeHNCString(nextWeatherRecord, mNextWeather.c_str());
|
|
||||||
esm.writeHNCString(currentRegionRecord, mCurrentRegion.c_str());
|
esm.writeHNCString(currentRegionRecord, mCurrentRegion.c_str());
|
||||||
esm.writeHNT(firstUpdateRecord, mFirstUpdate);
|
|
||||||
esm.writeHNT(remainingTransitionTimeRecord, mRemainingTransitionTime);
|
|
||||||
esm.writeHNT(timePassedRecord, mTimePassed);
|
esm.writeHNT(timePassedRecord, mTimePassed);
|
||||||
|
esm.writeHNT(fastForwardRecord, mFastForward);
|
||||||
|
esm.writeHNT(weatherUpdateTimeRecord, mWeatherUpdateTime);
|
||||||
|
esm.writeHNT(transitionFactorRecord, mTransitionFactor);
|
||||||
|
esm.writeHNT(currentWeatherRecord, mCurrentWeather);
|
||||||
|
esm.writeHNT(nextWeatherRecord, mNextWeather);
|
||||||
|
esm.writeHNT(queuedWeatherRecord, mQueuedWeather);
|
||||||
|
|
||||||
|
std::map<std::string, RegionWeatherState>::const_iterator it = mRegions.begin();
|
||||||
|
for(; it != mRegions.end(); ++it)
|
||||||
|
{
|
||||||
|
esm.writeHNCString(regionNameRecord, it->first.c_str());
|
||||||
|
esm.writeHNT(regionWeatherRecord, it->second.mWeather);
|
||||||
|
for(size_t i = 0; i < it->second.mChances.size(); ++i)
|
||||||
|
{
|
||||||
|
esm.writeHNT(regionChanceRecord, it->second.mChances[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +1,32 @@
|
||||||
#ifndef OPENMW_ESM_WEATHERSTATE_H
|
#ifndef OPENMW_ESM_WEATHERSTATE_H
|
||||||
#define OPENMW_ESM_WEATHERSTATE_H
|
#define OPENMW_ESM_WEATHERSTATE_H
|
||||||
|
|
||||||
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace ESM
|
namespace ESM
|
||||||
{
|
{
|
||||||
class ESMReader;
|
class ESMReader;
|
||||||
class ESMWriter;
|
class ESMWriter;
|
||||||
|
|
||||||
|
struct RegionWeatherState
|
||||||
|
{
|
||||||
|
int mWeather;
|
||||||
|
std::vector<char> mChances;
|
||||||
|
};
|
||||||
|
|
||||||
struct WeatherState
|
struct WeatherState
|
||||||
{
|
{
|
||||||
float mHour;
|
|
||||||
float mWindSpeed;
|
|
||||||
std::string mCurrentWeather;
|
|
||||||
std::string mNextWeather;
|
|
||||||
std::string mCurrentRegion;
|
std::string mCurrentRegion;
|
||||||
bool mFirstUpdate;
|
float mTimePassed;
|
||||||
float mRemainingTransitionTime;
|
bool mFastForward;
|
||||||
double mTimePassed;
|
float mWeatherUpdateTime;
|
||||||
|
float mTransitionFactor;
|
||||||
|
int mCurrentWeather;
|
||||||
|
int mNextWeather;
|
||||||
|
int mQueuedWeather;
|
||||||
|
std::map<std::string, RegionWeatherState> mRegions;
|
||||||
|
|
||||||
void load(ESMReader& esm);
|
void load(ESMReader& esm);
|
||||||
void save(ESMWriter& esm) const;
|
void save(ESMWriter& esm) const;
|
||||||
|
|
Loading…
Reference in a new issue