From 528cff5a593412f4f221c54543c0bd110d7b2d3e Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 26 Feb 2012 11:51:02 +0100 Subject: [PATCH] implemented ChangeWeather script function --- apps/openmw/mwscript/docs/vmformat.txt | 3 +- apps/openmw/mwscript/skyextensions.cpp | 22 +++++ apps/openmw/mwworld/weather.cpp | 115 ++++++++++++++++--------- apps/openmw/mwworld/weather.hpp | 24 +++--- apps/openmw/mwworld/world.cpp | 5 ++ apps/openmw/mwworld/world.hpp | 2 + 6 files changed, 120 insertions(+), 51 deletions(-) diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index cf9b00f006..09b0c04825 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -120,4 +120,5 @@ op 0x200013c: FadeIn op 0x200013d: FadeOut op 0x200013e: FadeTo op 0x200013f: GetCurrentWeather -opcodes 0x2000140-0x3ffffff unused +op 0x2000140: ChangeWeather +opcodes 0x2000141-0x3ffffff unused diff --git a/apps/openmw/mwscript/skyextensions.cpp b/apps/openmw/mwscript/skyextensions.cpp index 2c05d00111..a5cc9e2138 100644 --- a/apps/openmw/mwscript/skyextensions.cpp +++ b/apps/openmw/mwscript/skyextensions.cpp @@ -92,6 +92,25 @@ namespace MWScript runtime.push (context.getWorld().getCurrentWeather()); } }; + + class OpChangeWeather : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + InterpreterContext& context = + static_cast (runtime.getContext()); + + std::string region = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + Interpreter::Type_Integer id = runtime[0].mInteger; + runtime.pop(); + + context.getWorld().changeWeather(region, id); + } + }; const int opcodeToggleSky = 0x2000021; const int opcodeTurnMoonWhite = 0x2000022; @@ -99,6 +118,7 @@ namespace MWScript const int opcodeGetMasserPhase = 0x2000024; const int opcodeGetSecundaPhase = 0x2000025; const int opcodeGetCurrentWeather = 0x200013f; + const int opcodeChangeWeather = 0x2000140; void registerExtensions (Compiler::Extensions& extensions) { @@ -106,6 +126,7 @@ namespace MWScript extensions.registerInstruction ("ts", "", opcodeToggleSky); extensions.registerInstruction ("turnmoonwhite", "", opcodeTurnMoonWhite); extensions.registerInstruction ("turnmoonred", "", opcodeTurnMoonRed); + extensions.registerInstruction ("changeweather", "Sl", opcodeChangeWeather); extensions.registerFunction ("getmasserphase", 'l', "", opcodeGetMasserPhase); extensions.registerFunction ("getsecundaphase", 'l', "", opcodeGetSecundaPhase); extensions.registerFunction ("getcurrentweather", 'l', "", opcodeGetCurrentWeather); @@ -119,6 +140,7 @@ namespace MWScript interpreter.installSegment5 (opcodeGetMasserPhase, new OpGetMasserPhase); interpreter.installSegment5 (opcodeGetSecundaPhase, new OpGetSecundaPhase); interpreter.installSegment5 (opcodeGetCurrentWeather, new OpGetCurrentWeather); + interpreter.installSegment5 (opcodeChangeWeather, new OpChangeWeather); } } } diff --git a/apps/openmw/mwworld/weather.cpp b/apps/openmw/mwworld/weather.cpp index 6ba9103888..2ffc0886c6 100644 --- a/apps/openmw/mwworld/weather.cpp +++ b/apps/openmw/mwworld/weather.cpp @@ -9,6 +9,8 @@ #include #include +#include + using namespace Ogre; using namespace MWWorld; using namespace MWSound; @@ -483,54 +485,60 @@ void WeatherManager::update(float duration) if (mEnvironment->mWorld->isCellExterior() || mEnvironment->mWorld->isCellQuasiExterior()) { std::string regionstr = mEnvironment->mWorld->getPlayer().getPlayer().getCell()->cell->region; + boost::algorithm::to_lower(regionstr); if (mWeatherUpdateTime <= 0 || regionstr != mCurrentRegion) { mCurrentRegion = regionstr; mWeatherUpdateTime = WeatherGlobals::mWeatherUpdateTime*60.f; - // get weather probabilities for the current region - const ESM::Region *region = mEnvironment->mWorld->getStore().regions.find (regionstr); - - float clear = region->data.clear/255.f; - float cloudy = region->data.cloudy/255.f; - float foggy = region->data.foggy/255.f; - float overcast = region->data.overcast/255.f; - float rain = region->data.rain/255.f; - float thunder = region->data.thunder/255.f; - float ash = region->data.ash/255.f; - float blight = region->data.blight/255.f; - float snow = region->data.a/255.f; - float blizzard = region->data.b/255.f; - - // re-scale to 100 percent - const float total = clear+cloudy+foggy+overcast+rain+thunder+ash+blight+snow+blizzard; - - srand(time(NULL)); - float random = ((rand()%100)/100.f) * total; - std::string weather; - if (random >= snow+blight+ash+thunder+rain+overcast+foggy+cloudy+clear) - weather = "blizzard"; - else if (random >= blight+ash+thunder+rain+overcast+foggy+cloudy+clear) - weather = "snow"; - else if (random >= ash+thunder+rain+overcast+foggy+cloudy+clear) - weather = "blight"; - else if (random >= thunder+rain+overcast+foggy+cloudy+clear) - weather = "ashstorm"; - else if (random >= rain+overcast+foggy+cloudy+clear) - weather = "thunderstorm"; - else if (random >= overcast+foggy+cloudy+clear) - weather = "rain"; - else if (random >= foggy+cloudy+clear) - weather = "overcast"; - else if (random >= cloudy+clear) - weather = "foggy"; - else if (random >= clear) - weather = "cloudy"; + if (mRegionOverrides.find(regionstr) != mRegionOverrides.end()) + weather = mRegionOverrides[regionstr]; else - weather = "clear"; + { + // get weather probabilities for the current region + const ESM::Region *region = mEnvironment->mWorld->getStore().regions.find (regionstr); + + float clear = region->data.clear/255.f; + float cloudy = region->data.cloudy/255.f; + float foggy = region->data.foggy/255.f; + float overcast = region->data.overcast/255.f; + float rain = region->data.rain/255.f; + float thunder = region->data.thunder/255.f; + float ash = region->data.ash/255.f; + float blight = region->data.blight/255.f; + float snow = region->data.a/255.f; + float blizzard = region->data.b/255.f; + + // re-scale to 100 percent + const float total = clear+cloudy+foggy+overcast+rain+thunder+ash+blight+snow+blizzard; + + srand(time(NULL)); + float random = ((rand()%100)/100.f) * total; + + if (random >= snow+blight+ash+thunder+rain+overcast+foggy+cloudy+clear) + weather = "blizzard"; + else if (random >= blight+ash+thunder+rain+overcast+foggy+cloudy+clear) + weather = "snow"; + else if (random >= ash+thunder+rain+overcast+foggy+cloudy+clear) + weather = "blight"; + else if (random >= thunder+rain+overcast+foggy+cloudy+clear) + weather = "ashstorm"; + else if (random >= rain+overcast+foggy+cloudy+clear) + weather = "thunderstorm"; + else if (random >= overcast+foggy+cloudy+clear) + weather = "rain"; + else if (random >= foggy+cloudy+clear) + weather = "overcast"; + else if (random >= cloudy+clear) + weather = "foggy"; + else if (random >= clear) + weather = "cloudy"; + else + weather = "clear"; + } setWeather(weather, false); /* @@ -756,3 +764,32 @@ unsigned int WeatherManager::getWeatherID() const else return 0; } + +void WeatherManager::changeWeather(const std::string& region, const unsigned int id) +{ + std::string weather; + if (id==0) + weather = "clear"; + else if (id==1) + weather = "cloudy"; + else if (id==2) + weather = "foggy"; + else if (id==3) + weather = "overcast"; + else if (id==4) + weather = "rain"; + else if (id==5) + weather = "thunder"; + else if (id==6) + weather = "ashstorm"; + else if (id==7) + weather = "blight"; + else if (id==8) + weather = "snow"; + else if (id==9) + weather = "blizzard"; + else + weather = "clear"; + + mRegionOverrides[region] = weather; +} diff --git a/apps/openmw/mwworld/weather.hpp b/apps/openmw/mwworld/weather.hpp index 23a48c5cea..7a719252b0 100644 --- a/apps/openmw/mwworld/weather.hpp +++ b/apps/openmw/mwworld/weather.hpp @@ -112,14 +112,14 @@ namespace MWWorld static const std::string mThunderSoundID2; static const std::string mThunderSoundID3; }; - + /// 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; float mCloudBlendFactor; - + Ogre::ColourValue mFogColor; Ogre::ColourValue mAmbientColor; @@ -217,13 +217,11 @@ namespace MWWorld WeatherManager(MWRender::RenderingManager*, MWWorld::Environment*); /** - * Change the weather setting - * @param weather - * new weather setting to use - * @param instant - * if true, the weather changes instantly. if false, it slowly starts transitioning. + * Change the weather in the specified region + * @param region that should be changed + * @param ID of the weather setting to shift to */ - void setWeather(const Ogre::String& weather, bool instant=false); + void changeWeather(const std::string& region, const unsigned int id); /** * Per-frame update @@ -240,12 +238,14 @@ namespace MWWorld private: float mHour; int mDay, mMonth; - + MWRender::RenderingManager* mRendering; MWWorld::Environment* mEnvironment; std::map mWeatherSettings; - + + std::map mRegionOverrides; + Ogre::String mCurrentWeather; Ogre::String mNextWeather; @@ -256,7 +256,7 @@ namespace MWWorld float mWeatherUpdateTime; float mRemainingTransitionTime; - + float mThunderFlash; float mThunderChance; float mThunderChanceNeeded; @@ -264,6 +264,8 @@ namespace MWWorld WeatherResult transition(const float factor); WeatherResult getResult(const Ogre::String& weather); + + void setWeather(const Ogre::String& weather, bool instant=false); }; } diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index a1e2a253dc..ead8847cf5 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -741,6 +741,11 @@ namespace MWWorld return mWeatherManager->getWeatherID(); } + void World::changeWeather(const std::string& region, const unsigned int id) + { + mWeatherManager->changeWeather(region, id); + } + OEngine::Render::Fader* World::getFader() { return mRendering->getFader(); diff --git a/apps/openmw/mwworld/world.hpp b/apps/openmw/mwworld/world.hpp index 46e55484cd..71cca3545d 100644 --- a/apps/openmw/mwworld/world.hpp +++ b/apps/openmw/mwworld/world.hpp @@ -164,6 +164,8 @@ namespace MWWorld bool toggleSky(); ///< \return Resulting mode + void changeWeather(const std::string& region, const unsigned int id); + int getCurrentWeather() const; int getMasserPhase() const;