Implement the ModRegion script function

actorid
Chris Robinson 12 years ago
parent 1174b85ac8
commit c94653dc49

@ -201,6 +201,8 @@ namespace MWBase
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 void changeToInteriorCell (const std::string& cellName,

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

@ -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 opcodeTurnMoonWhite = 0x2000022;
const int opcodeTurnMoonRed = 0x2000023;
@ -103,6 +125,7 @@ namespace MWScript
const int opcodeGetSecundaPhase = 0x2000025;
const int opcodeGetCurrentWeather = 0x200013f;
const int opcodeChangeWeather = 0x2000140;
const int opcodeModRegion = 0x20026;
void registerExtensions (Compiler::Extensions& extensions)
{
@ -114,6 +137,7 @@ namespace MWScript
extensions.registerFunction ("getmasserphase", 'l', "", opcodeGetMasserPhase);
extensions.registerFunction ("getsecundaphase", 'l', "", opcodeGetSecundaPhase);
extensions.registerFunction ("getcurrentweather", 'l', "", opcodeGetCurrentWeather);
extensions.registerInstruction ("modregion", "S/llllllllll", opcodeModRegion);
}
void installOpcodes (Interpreter::Interpreter& interpreter)
@ -125,6 +149,7 @@ namespace MWScript
interpreter.installSegment5 (opcodeGetSecundaPhase, new OpGetSecundaPhase);
interpreter.installSegment5 (opcodeGetCurrentWeather, new OpGetCurrentWeather);
interpreter.installSegment5 (opcodeChangeWeather, new OpChangeWeather);
interpreter.installSegment3 (opcodeModRegion, new OpModRegion);
}
}
}

@ -537,8 +537,8 @@ void WeatherManager::stopSounds(bool stopAll)
std::vector<std::string>::iterator it = mSoundsPlaying.begin();
while (it!=mSoundsPlaying.end())
{
if (stopAll || \
!((*it == mWeatherSettings[mCurrentWeather].mAmbientLoopSoundID) || \
if (stopAll ||
!((*it == mWeatherSettings[mCurrentWeather].mAmbientLoopSoundID) ||
(*it == mWeatherSettings[mCurrentWeather].mRainLoopSoundID)))
{
MWBase::Environment::get().getSoundManager()->stopSound(*it);
@ -551,29 +551,38 @@ void WeatherManager::stopSounds(bool stopAll)
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).
* 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
* 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 sum = 0;
int i = 0;
for (; i < 10; ++i)
for (; i < probability.size(); ++i)
{
sum += probability[i];
if (chance < sum)
@ -681,6 +690,15 @@ void WeatherManager::changeWeather(const std::string& region, const unsigned int
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
{
return mWindSpeed;

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

@ -1374,6 +1374,11 @@ namespace MWWorld
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()
{
return mRendering->getFader();

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

Loading…
Cancel
Save