mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2024-12-29 03:19:44 +00:00
Use fixed size ints for Region and use an array for weather odds
This commit is contained in:
parent
1c47062083
commit
514723a4e6
@ -1201,16 +1201,10 @@ namespace EsmTool
|
||||
std::cout << " Name: " << mData.mName << std::endl;
|
||||
|
||||
std::cout << " Weather:" << std::endl;
|
||||
std::cout << " Clear: " << (int)mData.mData.mClear << std::endl;
|
||||
std::cout << " Cloudy: " << (int)mData.mData.mCloudy << std::endl;
|
||||
std::cout << " Foggy: " << (int)mData.mData.mFoggy << std::endl;
|
||||
std::cout << " Overcast: " << (int)mData.mData.mOvercast << std::endl;
|
||||
std::cout << " Rain: " << (int)mData.mData.mOvercast << std::endl;
|
||||
std::cout << " Thunder: " << (int)mData.mData.mThunder << std::endl;
|
||||
std::cout << " Ash: " << (int)mData.mData.mAsh << std::endl;
|
||||
std::cout << " Blight: " << (int)mData.mData.mBlight << std::endl;
|
||||
std::cout << " Snow: " << (int)mData.mData.mSnow << std::endl;
|
||||
std::cout << " Blizzard: " << (int)mData.mData.mBlizzard << std::endl;
|
||||
std::array<std::string_view, 10> weathers
|
||||
= { "Clear", "Cloudy", "Fog", "Overcast", "Rain", "Thunder", "Ash", "Blight", "Snow", "Blizzard" };
|
||||
for (size_t i = 0; i < weathers.size(); ++i)
|
||||
std::cout << " " << weathers[i] << ": " << mData.mData.mProbabilities[i] << std::endl;
|
||||
std::cout << " Map Color: " << mData.mMapColor << std::endl;
|
||||
if (!mData.mSleepList.empty())
|
||||
std::cout << " Sleep List: " << mData.mSleepList << std::endl;
|
||||
|
@ -47,9 +47,7 @@ void CSMTools::RegionCheckStage::perform(int stage, CSMDoc::Messages& messages)
|
||||
/// \todo test that the ID in mSleeplist exists
|
||||
|
||||
// test that chances add up to 100
|
||||
int chances = 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.mSnow
|
||||
+ region.mData.mBlizzard;
|
||||
auto chances = std::accumulate(region.mData.mProbabilities.begin(), region.mData.mProbabilities.end(), 0u);
|
||||
if (chances != 100)
|
||||
messages.add(id, "Weather chances do not add up to 100", "", CSMDoc::Message::Severity_Error);
|
||||
|
||||
|
@ -1076,31 +1076,8 @@ namespace CSMWorld
|
||||
}
|
||||
else if (subColIndex == 1)
|
||||
{
|
||||
switch (subRowIndex)
|
||||
{
|
||||
case 0:
|
||||
return region.mData.mClear;
|
||||
case 1:
|
||||
return region.mData.mCloudy;
|
||||
case 2:
|
||||
return region.mData.mFoggy;
|
||||
case 3:
|
||||
return region.mData.mOvercast;
|
||||
case 4:
|
||||
return region.mData.mRain;
|
||||
case 5:
|
||||
return region.mData.mThunder;
|
||||
case 6:
|
||||
return region.mData.mAsh;
|
||||
case 7:
|
||||
return region.mData.mBlight;
|
||||
case 8:
|
||||
return region.mData.mSnow;
|
||||
case 9:
|
||||
return region.mData.mBlizzard;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (subRowIndex >= 0 && subRowIndex < region.mData.mProbabilities.size())
|
||||
return region.mData.mProbabilities[subRowIndex];
|
||||
}
|
||||
|
||||
throw std::runtime_error("index out of range");
|
||||
@ -1110,45 +1087,11 @@ namespace CSMWorld
|
||||
Record<ESM::Region>& record, const QVariant& value, int subRowIndex, int subColIndex) const
|
||||
{
|
||||
ESM::Region region = record.get();
|
||||
unsigned char chance = static_cast<unsigned char>(value.toInt());
|
||||
uint8_t chance = static_cast<uint8_t>(value.toInt());
|
||||
|
||||
if (subColIndex == 1)
|
||||
{
|
||||
switch (subRowIndex)
|
||||
{
|
||||
case 0:
|
||||
region.mData.mClear = chance;
|
||||
break;
|
||||
case 1:
|
||||
region.mData.mCloudy = chance;
|
||||
break;
|
||||
case 2:
|
||||
region.mData.mFoggy = chance;
|
||||
break;
|
||||
case 3:
|
||||
region.mData.mOvercast = chance;
|
||||
break;
|
||||
case 4:
|
||||
region.mData.mRain = chance;
|
||||
break;
|
||||
case 5:
|
||||
region.mData.mThunder = chance;
|
||||
break;
|
||||
case 6:
|
||||
region.mData.mAsh = chance;
|
||||
break;
|
||||
case 7:
|
||||
region.mData.mBlight = chance;
|
||||
break;
|
||||
case 8:
|
||||
region.mData.mSnow = chance;
|
||||
break;
|
||||
case 9:
|
||||
region.mData.mBlizzard = chance;
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("index out of range");
|
||||
}
|
||||
region.mData.mProbabilities.at(subRowIndex) = chance;
|
||||
|
||||
record.setModified(region);
|
||||
}
|
||||
|
@ -232,7 +232,7 @@ namespace MWBase
|
||||
|
||||
virtual void setMoonColour(bool red) = 0;
|
||||
|
||||
virtual void modRegion(const ESM::RefId& regionid, const std::vector<char>& chances) = 0;
|
||||
virtual void modRegion(const ESM::RefId& regionid, const std::vector<uint8_t>& chances) = 0;
|
||||
|
||||
virtual void changeToInteriorCell(
|
||||
std::string_view cellName, const ESM::Position& position, bool adjustPlayerPos, bool changeEvent = true)
|
||||
|
@ -102,11 +102,11 @@ namespace MWScript
|
||||
std::string_view region{ runtime.getStringLiteral(runtime[0].mInteger) };
|
||||
runtime.pop();
|
||||
|
||||
std::vector<char> chances;
|
||||
std::vector<uint8_t> chances;
|
||||
chances.reserve(10);
|
||||
while (arg0 > 0)
|
||||
{
|
||||
chances.push_back(std::clamp(runtime[0].mInteger, 0, 127));
|
||||
chances.push_back(std::clamp(runtime[0].mInteger, 0, 100));
|
||||
runtime.pop();
|
||||
arg0--;
|
||||
}
|
||||
|
@ -285,19 +285,8 @@ namespace MWWorld
|
||||
|
||||
RegionWeather::RegionWeather(const ESM::Region& region)
|
||||
: mWeather(invalidWeatherID)
|
||||
, mChances()
|
||||
, mChances(region.mData.mProbabilities.begin(), region.mData.mProbabilities.end())
|
||||
{
|
||||
mChances.reserve(10);
|
||||
mChances.push_back(region.mData.mClear);
|
||||
mChances.push_back(region.mData.mCloudy);
|
||||
mChances.push_back(region.mData.mFoggy);
|
||||
mChances.push_back(region.mData.mOvercast);
|
||||
mChances.push_back(region.mData.mRain);
|
||||
mChances.push_back(region.mData.mThunder);
|
||||
mChances.push_back(region.mData.mAsh);
|
||||
mChances.push_back(region.mData.mBlight);
|
||||
mChances.push_back(region.mData.mSnow);
|
||||
mChances.push_back(region.mData.mBlizzard);
|
||||
}
|
||||
|
||||
RegionWeather::RegionWeather(const ESM::RegionWeatherState& state)
|
||||
@ -313,19 +302,9 @@ namespace MWWorld
|
||||
return state;
|
||||
}
|
||||
|
||||
void RegionWeather::setChances(const std::vector<char>& chances)
|
||||
void RegionWeather::setChances(const std::vector<uint8_t>& chances)
|
||||
{
|
||||
if (mChances.size() < chances.size())
|
||||
{
|
||||
mChances.reserve(chances.size());
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
for (char chance : chances)
|
||||
{
|
||||
mChances[i] = chance;
|
||||
i++;
|
||||
}
|
||||
mChances = chances;
|
||||
|
||||
// Regional weather no longer supports the current type, select a new weather pattern.
|
||||
if ((static_cast<size_t>(mWeather) >= mChances.size()) || (mChances[mWeather] == 0))
|
||||
@ -357,15 +336,14 @@ namespace MWWorld
|
||||
// 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).
|
||||
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||
int chance = Misc::Rng::rollDice(100, prng) + 1; // 1..100
|
||||
int sum = 0;
|
||||
int i = 0;
|
||||
for (; static_cast<size_t>(i) < mChances.size(); ++i)
|
||||
unsigned int chance = static_cast<unsigned int>(Misc::Rng::rollDice(100, prng) + 1); // 1..100
|
||||
unsigned int sum = 0;
|
||||
for (size_t i = 0; i < mChances.size(); ++i)
|
||||
{
|
||||
sum += mChances[i];
|
||||
if (chance <= sum)
|
||||
{
|
||||
mWeather = i;
|
||||
mWeather = static_cast<int>(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -649,7 +627,7 @@ namespace MWWorld
|
||||
}
|
||||
}
|
||||
|
||||
void WeatherManager::modRegion(const ESM::RefId& regionID, const std::vector<char>& chances)
|
||||
void WeatherManager::modRegion(const ESM::RefId& regionID, const std::vector<uint8_t>& chances)
|
||||
{
|
||||
// Sets the region's probability for various weather patterns. Note that this appears to be saved permanently.
|
||||
// In Morrowind, this seems to have the following behavior when applied to the current region:
|
||||
|
@ -230,7 +230,7 @@ namespace MWWorld
|
||||
|
||||
operator ESM::RegionWeatherState() const;
|
||||
|
||||
void setChances(const std::vector<char>& chances);
|
||||
void setChances(const std::vector<uint8_t>& chances);
|
||||
|
||||
void setWeather(int weatherID);
|
||||
|
||||
@ -238,7 +238,7 @@ namespace MWWorld
|
||||
|
||||
private:
|
||||
int mWeather;
|
||||
std::vector<char> mChances;
|
||||
std::vector<uint8_t> mChances;
|
||||
|
||||
void chooseNewWeather();
|
||||
};
|
||||
@ -286,7 +286,7 @@ namespace MWWorld
|
||||
* @param ID of the weather setting to shift to
|
||||
*/
|
||||
void changeWeather(const ESM::RefId& regionID, const unsigned int weatherID);
|
||||
void modRegion(const ESM::RefId& regionID, const std::vector<char>& chances);
|
||||
void modRegion(const ESM::RefId& regionID, const std::vector<uint8_t>& chances);
|
||||
void playerTeleported(const ESM::RefId& playerRegion, bool isExterior);
|
||||
|
||||
/**
|
||||
|
@ -1879,7 +1879,7 @@ namespace MWWorld
|
||||
mWeatherManager->changeWeather(region, id);
|
||||
}
|
||||
|
||||
void World::modRegion(const ESM::RefId& regionid, const std::vector<char>& chances)
|
||||
void World::modRegion(const ESM::RefId& regionid, const std::vector<uint8_t>& chances)
|
||||
{
|
||||
mWeatherManager->modRegion(regionid, chances);
|
||||
}
|
||||
|
@ -329,7 +329,7 @@ namespace MWWorld
|
||||
|
||||
void setMoonColour(bool red) override;
|
||||
|
||||
void modRegion(const ESM::RefId& regionid, const std::vector<char>& chances) override;
|
||||
void modRegion(const ESM::RefId& regionid, const std::vector<uint8_t>& chances) override;
|
||||
|
||||
void changeToInteriorCell(const std::string_view cellName, const ESM::Position& position, bool adjustPlayerPos,
|
||||
bool changeEvent = true) override;
|
||||
|
@ -27,15 +27,14 @@ namespace ESM
|
||||
{
|
||||
esm.getSubHeader();
|
||||
// Cold weather not included before 1.3
|
||||
if (esm.getSubSize() == sizeof(mData))
|
||||
if (esm.getSubSize() == mData.mProbabilities.size())
|
||||
{
|
||||
esm.getTSized<10>(mData);
|
||||
esm.getT(mData.mProbabilities);
|
||||
}
|
||||
else if (esm.getSubSize() == sizeof(mData) - 2)
|
||||
else if (esm.getSubSize() == mData.mProbabilities.size() - 2)
|
||||
{
|
||||
mData.mSnow = 0;
|
||||
mData.mBlizzard = 0;
|
||||
esm.getExact(&mData, sizeof(mData) - 2);
|
||||
mData.mProbabilities.fill(0);
|
||||
esm.getExact(&mData.mProbabilities, esm.getSubSize());
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -85,9 +84,9 @@ namespace ESM
|
||||
esm.writeHNOCString("FNAM", mName);
|
||||
|
||||
if (esm.getVersion() == VER_12)
|
||||
esm.writeHNT("WEAT", mData, sizeof(mData) - 2);
|
||||
esm.writeHNT("WEAT", mData.mProbabilities, mData.mProbabilities.size() - 2);
|
||||
else
|
||||
esm.writeHNT("WEAT", mData);
|
||||
esm.writeHNT("WEAT", mData.mProbabilities);
|
||||
|
||||
esm.writeHNOCRefId("BNAM", mSleepList);
|
||||
|
||||
@ -104,8 +103,7 @@ namespace ESM
|
||||
void Region::blank()
|
||||
{
|
||||
mRecordFlags = 0;
|
||||
mData.mClear = mData.mCloudy = mData.mFoggy = mData.mOvercast = mData.mRain = mData.mThunder = mData.mAsh
|
||||
= mData.mBlight = mData.mSnow = mData.mBlizzard = 0;
|
||||
mData.mProbabilities.fill(0);
|
||||
|
||||
mMapColor = 0;
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
#ifndef OPENMW_ESM_REGN_H
|
||||
#define OPENMW_ESM_REGN_H
|
||||
|
||||
#include <array>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@ -24,26 +25,24 @@ namespace ESM
|
||||
/// Return a string descriptor for this record type. Currently used for debugging / error logs only.
|
||||
static std::string_view getRecordType() { return "Region"; }
|
||||
|
||||
#pragma pack(push)
|
||||
#pragma pack(1)
|
||||
struct WEATstruct
|
||||
{
|
||||
// These are probabilities that add up to 100
|
||||
unsigned char mClear, mCloudy, mFoggy, mOvercast, mRain, mThunder, mAsh, mBlight, mSnow, mBlizzard;
|
||||
// Clear, Cloudy, Foggy, Overcast, Rain, Thunder, Ash, Blight, Snow, Blizzard
|
||||
std::array<uint8_t, 10> mProbabilities;
|
||||
}; // 10 bytes
|
||||
#pragma pack(pop)
|
||||
|
||||
// Reference to a sound that is played randomly in this region
|
||||
struct SoundRef
|
||||
{
|
||||
ESM::RefId mSound;
|
||||
unsigned char mChance;
|
||||
uint8_t mChance;
|
||||
};
|
||||
|
||||
WEATstruct mData;
|
||||
int mMapColor; // RGBA
|
||||
int32_t mMapColor; // RGBA
|
||||
|
||||
unsigned int mRecordFlags;
|
||||
uint32_t mRecordFlags;
|
||||
// sleepList refers to a leveled list of creatures you can meet if
|
||||
// you sleep outside in this region.
|
||||
RefId mId, mSleepList;
|
||||
|
@ -41,7 +41,7 @@ namespace ESM
|
||||
esm.getHNT(region.mWeather, regionWeatherRecord);
|
||||
while (esm.isNextSub(regionChanceRecord))
|
||||
{
|
||||
char chance;
|
||||
uint8_t chance;
|
||||
esm.getHT(chance);
|
||||
region.mChances.push_back(chance);
|
||||
}
|
||||
@ -66,9 +66,9 @@ namespace ESM
|
||||
{
|
||||
esm.writeHNCRefId(regionNameRecord, it->first);
|
||||
esm.writeHNT(regionWeatherRecord, it->second.mWeather);
|
||||
for (size_t i = 0; i < it->second.mChances.size(); ++i)
|
||||
for (const uint8_t& chance : it->second.mChances)
|
||||
{
|
||||
esm.writeHNT(regionChanceRecord, it->second.mChances[i]);
|
||||
esm.writeHNT(regionChanceRecord, chance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,8 +13,8 @@ namespace ESM
|
||||
|
||||
struct RegionWeatherState
|
||||
{
|
||||
int mWeather;
|
||||
std::vector<char> mChances;
|
||||
int32_t mWeather;
|
||||
std::vector<uint8_t> mChances;
|
||||
};
|
||||
|
||||
struct WeatherState
|
||||
@ -24,9 +24,9 @@ namespace ESM
|
||||
bool mFastForward;
|
||||
float mWeatherUpdateTime;
|
||||
float mTransitionFactor;
|
||||
int mCurrentWeather;
|
||||
int mNextWeather;
|
||||
int mQueuedWeather;
|
||||
int32_t mCurrentWeather;
|
||||
int32_t mNextWeather;
|
||||
int32_t mQueuedWeather;
|
||||
std::map<ESM::RefId, RegionWeatherState> mRegions;
|
||||
|
||||
void load(ESMReader& esm);
|
||||
|
Loading…
Reference in New Issue
Block a user