Implement the ModRegion script function

This commit is contained in:
Chris Robinson 2013-07-27 07:10:18 -07:00
parent 1174b85ac8
commit c94653dc49
7 changed files with 74 additions and 16 deletions

View file

@ -201,6 +201,8 @@ namespace MWBase
virtual void setMoonColour (bool red) = 0; virtual void setMoonColour (bool red) = 0;
virtual void modRegion(const std::string &regionid, const std::vector<char> &chances) = 0;
virtual float getTimeScaleFactor() const = 0; virtual float getTimeScaleFactor() const = 0;
virtual void changeToInteriorCell (const std::string& cellName, virtual void changeToInteriorCell (const std::string& cellName,

View file

@ -51,7 +51,8 @@ op 0x20022: AiFollow
op 0x20023: AiFollow, explicit reference op 0x20023: AiFollow, explicit reference
op 0x20024: AiFollowCell op 0x20024: AiFollowCell
op 0x20025: AiFollowCell, explicit reference op 0x20025: AiFollowCell, explicit reference
op s 0x20026-0x3ffff unused op 0x20026: ModRegion
opcodes 0x20027-0x3ffff unused
Segment 4: Segment 4:
(not implemented yet) (not implemented yet)

View file

@ -96,6 +96,28 @@ namespace MWScript
} }
}; };
class OpModRegion : public Interpreter::Opcode1
{
public:
virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0)
{
std::string region = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop();
std::vector<char> chances;
chances.reserve(10);
while(arg0 > 0)
{
chances.push_back(std::max(0, std::min(127, runtime[0].mInteger)));
runtime.pop();
arg0--;
}
MWBase::Environment::get().getWorld()->modRegion(region, chances);
}
};
const int opcodeToggleSky = 0x2000021; const int opcodeToggleSky = 0x2000021;
const int opcodeTurnMoonWhite = 0x2000022; const int opcodeTurnMoonWhite = 0x2000022;
const int opcodeTurnMoonRed = 0x2000023; const int opcodeTurnMoonRed = 0x2000023;
@ -103,6 +125,7 @@ namespace MWScript
const int opcodeGetSecundaPhase = 0x2000025; const int opcodeGetSecundaPhase = 0x2000025;
const int opcodeGetCurrentWeather = 0x200013f; const int opcodeGetCurrentWeather = 0x200013f;
const int opcodeChangeWeather = 0x2000140; const int opcodeChangeWeather = 0x2000140;
const int opcodeModRegion = 0x20026;
void registerExtensions (Compiler::Extensions& extensions) void registerExtensions (Compiler::Extensions& extensions)
{ {
@ -114,6 +137,7 @@ namespace MWScript
extensions.registerFunction ("getmasserphase", 'l', "", opcodeGetMasserPhase); extensions.registerFunction ("getmasserphase", 'l', "", opcodeGetMasserPhase);
extensions.registerFunction ("getsecundaphase", 'l', "", opcodeGetSecundaPhase); extensions.registerFunction ("getsecundaphase", 'l', "", opcodeGetSecundaPhase);
extensions.registerFunction ("getcurrentweather", 'l', "", opcodeGetCurrentWeather); extensions.registerFunction ("getcurrentweather", 'l', "", opcodeGetCurrentWeather);
extensions.registerInstruction ("modregion", "S/llllllllll", opcodeModRegion);
} }
void installOpcodes (Interpreter::Interpreter& interpreter) void installOpcodes (Interpreter::Interpreter& interpreter)
@ -125,6 +149,7 @@ namespace MWScript
interpreter.installSegment5 (opcodeGetSecundaPhase, new OpGetSecundaPhase); interpreter.installSegment5 (opcodeGetSecundaPhase, new OpGetSecundaPhase);
interpreter.installSegment5 (opcodeGetCurrentWeather, new OpGetCurrentWeather); interpreter.installSegment5 (opcodeGetCurrentWeather, new OpGetCurrentWeather);
interpreter.installSegment5 (opcodeChangeWeather, new OpChangeWeather); interpreter.installSegment5 (opcodeChangeWeather, new OpChangeWeather);
interpreter.installSegment3 (opcodeModRegion, new OpModRegion);
} }
} }
} }

View file

@ -537,8 +537,8 @@ void WeatherManager::stopSounds(bool stopAll)
std::vector<std::string>::iterator it = mSoundsPlaying.begin(); std::vector<std::string>::iterator it = mSoundsPlaying.begin();
while (it!=mSoundsPlaying.end()) while (it!=mSoundsPlaying.end())
{ {
if (stopAll || \ if (stopAll ||
!((*it == mWeatherSettings[mCurrentWeather].mAmbientLoopSoundID) || \ !((*it == mWeatherSettings[mCurrentWeather].mAmbientLoopSoundID) ||
(*it == mWeatherSettings[mCurrentWeather].mRainLoopSoundID))) (*it == mWeatherSettings[mCurrentWeather].mRainLoopSoundID)))
{ {
MWBase::Environment::get().getSoundManager()->stopSound(*it); MWBase::Environment::get().getSoundManager()->stopSound(*it);
@ -551,29 +551,38 @@ void WeatherManager::stopSounds(bool stopAll)
Ogre::String WeatherManager::nextWeather(const ESM::Region* region) const Ogre::String WeatherManager::nextWeather(const ESM::Region* region) const
{ {
const MWBase::World *world = MWBase::Environment::get().getWorld();
std::vector<char> probability;
RegionModMap::const_iterator iter = mRegionMods.find(Misc::StringUtils::lowerCase(region->mId));
if(iter != mRegionMods.end())
probability = iter->second;
else
{
probability.reserve(10);
probability.push_back(region->mData.mClear);
probability.push_back(region->mData.mCloudy);
probability.push_back(region->mData.mFoggy);
probability.push_back(region->mData.mOvercast);
probability.push_back(region->mData.mRain);
probability.push_back(region->mData.mThunder);
probability.push_back(region->mData.mAsh);
probability.push_back(region->mData.mBlight);
probability.push_back(region->mData.mA);
probability.push_back(region->mData.mB);
}
/* /*
* All probabilities must add to 100 (responsibility of the user). * All probabilities must add to 100 (responsibility of the user).
* If chances A and B has values 30 and 70 then by generating * If chances A and B has values 30 and 70 then by generating
* 100 numbers 1..100, 30% will be lesser or equal 30 and * 100 numbers 1..100, 30% will be lesser or equal 30 and
* 70% will be greater than 30 (in theory). * 70% will be greater than 30 (in theory).
*/ */
const int probability[] = {
region->mData.mClear,
region->mData.mCloudy,
region->mData.mFoggy,
region->mData.mOvercast,
region->mData.mRain,
region->mData.mThunder,
region->mData.mAsh,
region->mData.mBlight,
region->mData.mA,
region->mData.mB
}; // 10 elements
int chance = (rand() % 100) + 1; // 1..100 int chance = (rand() % 100) + 1; // 1..100
int sum = 0; int sum = 0;
int i = 0; int i = 0;
for (; i < 10; ++i) for (; i < probability.size(); ++i)
{ {
sum += probability[i]; sum += probability[i];
if (chance < sum) if (chance < sum)
@ -681,6 +690,15 @@ void WeatherManager::changeWeather(const std::string& region, const unsigned int
setWeather(weather); setWeather(weather);
} }
void WeatherManager::modRegion(const std::string &regionid, const std::vector<char> &chances)
{
mRegionMods[Misc::StringUtils::lowerCase(regionid)] = chances;
// Start transitioning right away if the region no longer supports the current weather type
unsigned int current = getWeatherID();
if(current >= chances.size() || chances[current] == 0)
mWeatherUpdateTime = 0.0f;
}
float WeatherManager::getWindSpeed() const float WeatherManager::getWindSpeed() const
{ {
return mWindSpeed; return mWindSpeed;

View file

@ -149,6 +149,8 @@ namespace MWWorld
unsigned int getWeatherID() const; unsigned int getWeatherID() const;
void modRegion(const std::string &regionid, const std::vector<char> &chances);
private: private:
float mHour; float mHour;
int mDay, mMonth; int mDay, mMonth;
@ -188,6 +190,9 @@ namespace MWWorld
Ogre::String nextWeather(const ESM::Region* region) const; Ogre::String nextWeather(const ESM::Region* region) const;
WeatherResult mResult; WeatherResult mResult;
typedef std::map<std::string,std::vector<char> > RegionModMap;
RegionModMap mRegionMods;
float mSunriseTime; float mSunriseTime;
float mSunsetTime; float mSunsetTime;
float mSunriseDuration; float mSunriseDuration;

View file

@ -1374,6 +1374,11 @@ namespace MWWorld
mWeatherManager->changeWeather(region, id); mWeatherManager->changeWeather(region, id);
} }
void World::modRegion(const std::string &regionid, const std::vector<char> &chances)
{
mWeatherManager->modRegion(regionid, chances);
}
OEngine::Render::Fader* World::getFader() OEngine::Render::Fader* World::getFader()
{ {
return mRendering->getFader(); return mRendering->getFader();

View file

@ -237,6 +237,8 @@ namespace MWWorld
virtual void setMoonColour (bool red); virtual void setMoonColour (bool red);
virtual void modRegion(const std::string &regionid, const std::vector<char> &chances);
virtual float getTimeScaleFactor() const; virtual float getTimeScaleFactor() const;
virtual void changeToInteriorCell (const std::string& cellName, virtual void changeToInteriorCell (const std::string& cellName,