2013-02-09 13:00:57 +01:00
|
|
|
#include "store.hpp"
|
|
|
|
|
2021-05-05 20:28:46 +02:00
|
|
|
#include <iterator>
|
2022-04-10 18:33:42 +02:00
|
|
|
#include <sstream>
|
2015-07-09 19:22:04 +02:00
|
|
|
#include <stdexcept>
|
|
|
|
|
2022-12-30 11:28:19 +01:00
|
|
|
#include <components/debug/debuglog.hpp>
|
|
|
|
#include <components/esm/records.hpp>
|
|
|
|
#include <components/esm3/esmreader.hpp>
|
|
|
|
#include <components/esm3/esmwriter.hpp>
|
2023-05-15 23:48:22 +02:00
|
|
|
#include <components/esm4/loadland.hpp>
|
2023-04-22 13:59:53 +02:00
|
|
|
#include <components/esm4/loadwrld.hpp>
|
2022-12-30 11:28:19 +01:00
|
|
|
#include <components/loadinglistener/loadinglistener.hpp>
|
|
|
|
#include <components/misc/rng.hpp>
|
2022-12-28 20:48:25 +01:00
|
|
|
|
2023-05-15 23:48:22 +02:00
|
|
|
#include "../mwbase/environment.hpp"
|
|
|
|
#include "../mwworld/cell.hpp"
|
|
|
|
#include "../mwworld/worldimp.hpp"
|
2023-02-04 18:45:53 +01:00
|
|
|
|
2022-06-13 18:21:29 +02:00
|
|
|
namespace
|
|
|
|
{
|
|
|
|
// TODO: Switch to C++23 to get a working version of std::unordered_map::erase
|
2023-04-20 00:25:42 +02:00
|
|
|
template <class T, class Id>
|
|
|
|
bool eraseFromMap(T& map, const Id& value)
|
2022-06-13 18:21:29 +02:00
|
|
|
{
|
|
|
|
auto it = map.find(value);
|
|
|
|
if (it != map.end())
|
|
|
|
{
|
|
|
|
map.erase(it);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2023-05-31 17:02:18 +02:00
|
|
|
|
|
|
|
std::string_view getGMSTString(const MWWorld::Store<ESM::GameSetting>& settings, std::string_view id)
|
|
|
|
{
|
|
|
|
const ESM::GameSetting* setting = settings.search(id);
|
|
|
|
if (setting && setting->mValue.getType() == ESM::VT_String)
|
|
|
|
return setting->mValue.getString();
|
|
|
|
return id;
|
|
|
|
}
|
|
|
|
|
|
|
|
float getGMSTFloat(const MWWorld::Store<ESM::GameSetting>& settings, std::string_view id)
|
|
|
|
{
|
|
|
|
const ESM::GameSetting* setting = settings.search(id);
|
|
|
|
if (setting && (setting->mValue.getType() == ESM::VT_Float || setting->mValue.getType() == ESM::VT_Int))
|
|
|
|
return setting->mValue.getFloat();
|
|
|
|
return {};
|
|
|
|
}
|
2022-06-13 18:21:29 +02:00
|
|
|
}
|
|
|
|
|
2015-07-09 19:22:04 +02:00
|
|
|
namespace MWWorld
|
2014-06-11 15:37:05 +02:00
|
|
|
{
|
Initial commit: In ESM structures, replace the string members that are RefIds to other records, to a new strong type
The strong type is actually just a string underneath, but this will help in the future to have a distinction so it's easier to search and replace when we use an integer ID
Slowly going through all the changes to make, still hundreds of errors
a lot of functions/structures use std::string or stringview to designate an ID. So it takes time
Continues slowly replacing ids. There are technically more and more compilation errors
I have good hope that there is a point where the amount of errors will dramatically go down as all the main functions use the ESM::RefId type
Continue moving forward, changes to the stores
slowly moving along
Starting to see the fruit of those changes.
still many many error, but more and more Irun into a situation where a function is sandwiched between two functions that use the RefId type.
More replacements. Things are starting to get easier
I can see more and more often the issue is that the function is awaiting a RefId, but is given a string
there is less need to go down functions and to fix a long list of them.
Still moving forward, and for the first time error count is going down!
Good pace, not sure about topics though, mId and mName are actually the same thing and are used interchangeably
Cells are back to using string for the name, haven't fixed everything yet. Many other changes
Under the bar of 400 compilation errors.
more good progress <100 compile errors!
More progress
Game settings store can use string for find, it was a bit absurd how every use of it required to create refId from string
some more progress on other fronts
Mostly game settings clean
one error opened a lot of other errors. Down to 18, but more will prbably appear
only link errors left??
Fixed link errors
OpenMW compiles, and launches, with some issues, but still!
2022-09-25 13:17:09 +02:00
|
|
|
RecordId::RecordId(const ESM::RefId& id, bool isDeleted)
|
2015-07-12 15:20:22 +03:00
|
|
|
: mId(id)
|
|
|
|
, mIsDeleted(isDeleted)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2021-06-30 15:34:40 +10:00
|
|
|
template <typename T>
|
2015-07-09 19:22:04 +02:00
|
|
|
IndexedStore<T>::IndexedStore()
|
|
|
|
{
|
|
|
|
}
|
2021-06-30 15:34:40 +10:00
|
|
|
template <typename T>
|
2015-07-09 19:22:04 +02:00
|
|
|
typename IndexedStore<T>::iterator IndexedStore<T>::begin() const
|
|
|
|
{
|
|
|
|
return mStatic.begin();
|
|
|
|
}
|
2021-06-30 15:34:40 +10:00
|
|
|
template <typename T>
|
2015-07-09 19:22:04 +02:00
|
|
|
typename IndexedStore<T>::iterator IndexedStore<T>::end() const
|
|
|
|
{
|
|
|
|
return mStatic.end();
|
|
|
|
}
|
|
|
|
template <typename T>
|
|
|
|
void IndexedStore<T>::load(ESM::ESMReader& esm)
|
|
|
|
{
|
|
|
|
T record;
|
2015-07-21 13:17:03 +03:00
|
|
|
bool isDeleted = false;
|
|
|
|
|
|
|
|
record.load(esm, isDeleted);
|
2021-10-30 17:27:57 +00:00
|
|
|
auto idx = record.mIndex;
|
|
|
|
mStatic.insert_or_assign(idx, std::move(record));
|
2015-07-09 19:22:04 +02:00
|
|
|
}
|
|
|
|
template <typename T>
|
|
|
|
int IndexedStore<T>::getSize() const
|
|
|
|
{
|
|
|
|
return mStatic.size();
|
|
|
|
}
|
|
|
|
template <typename T>
|
|
|
|
void IndexedStore<T>::setUp()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
template <typename T>
|
|
|
|
const T* IndexedStore<T>::search(int index) const
|
|
|
|
{
|
|
|
|
typename Static::const_iterator it = mStatic.find(index);
|
|
|
|
if (it != mStatic.end())
|
|
|
|
return &(it->second);
|
2018-10-09 10:21:12 +04:00
|
|
|
return nullptr;
|
2015-07-09 19:22:04 +02:00
|
|
|
}
|
|
|
|
template <typename T>
|
|
|
|
const T* IndexedStore<T>::find(int index) const
|
|
|
|
{
|
|
|
|
const T* ptr = search(index);
|
2020-11-13 11:39:47 +04:00
|
|
|
if (ptr == nullptr)
|
2019-01-07 17:47:39 +04:00
|
|
|
{
|
2021-10-12 00:18:23 +02:00
|
|
|
std::stringstream msg;
|
|
|
|
msg << T::getRecordType() << " with index " << index << " not found";
|
|
|
|
throw std::runtime_error(msg.str());
|
2015-07-09 19:22:04 +02:00
|
|
|
}
|
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Need to instantiate these before they're used
|
|
|
|
template class IndexedStore<ESM::MagicEffect>;
|
|
|
|
template class IndexedStore<ESM::Skill>;
|
|
|
|
|
2023-04-20 00:25:42 +02:00
|
|
|
template <class T, class Id>
|
|
|
|
TypedDynamicStore<T, Id>::TypedDynamicStore()
|
2015-07-09 19:22:04 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2023-04-20 00:25:42 +02:00
|
|
|
template <class T, class Id>
|
|
|
|
TypedDynamicStore<T, Id>::TypedDynamicStore(const TypedDynamicStore<T, Id>& orig)
|
2021-12-24 00:54:00 +03:00
|
|
|
: mStatic(orig.mStatic)
|
2015-07-09 19:22:04 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2023-04-20 00:25:42 +02:00
|
|
|
template <class T, class Id>
|
|
|
|
void TypedDynamicStore<T, Id>::clearDynamic()
|
2015-07-09 19:22:04 +02:00
|
|
|
{
|
|
|
|
// remove the dynamic part of mShared
|
|
|
|
assert(mShared.size() >= mStatic.size());
|
|
|
|
mShared.erase(mShared.begin() + mStatic.size(), mShared.end());
|
|
|
|
mDynamic.clear();
|
|
|
|
}
|
|
|
|
|
2023-04-20 00:25:42 +02:00
|
|
|
template <class T, class Id>
|
|
|
|
const T* TypedDynamicStore<T, Id>::search(const Id& id) const
|
2015-07-09 19:22:04 +02:00
|
|
|
{
|
2021-10-30 17:27:57 +00:00
|
|
|
typename Dynamic::const_iterator dit = mDynamic.find(id);
|
2020-05-16 13:37:00 +00:00
|
|
|
if (dit != mDynamic.end())
|
2015-07-09 19:22:04 +02:00
|
|
|
return &dit->second;
|
|
|
|
|
2021-10-30 17:27:57 +00:00
|
|
|
typename Static::const_iterator it = mStatic.find(id);
|
2020-05-16 13:37:00 +00:00
|
|
|
if (it != mStatic.end())
|
2015-07-09 19:22:04 +02:00
|
|
|
return &(it->second);
|
|
|
|
|
2020-11-13 11:39:47 +04:00
|
|
|
return nullptr;
|
2015-07-09 19:22:04 +02:00
|
|
|
}
|
2023-04-20 00:25:42 +02:00
|
|
|
template <class T, class Id>
|
|
|
|
const T* TypedDynamicStore<T, Id>::searchStatic(const Id& id) const
|
2019-06-13 13:37:00 +00:00
|
|
|
{
|
2021-10-30 17:27:57 +00:00
|
|
|
typename Static::const_iterator it = mStatic.find(id);
|
2020-05-16 13:37:00 +00:00
|
|
|
if (it != mStatic.end())
|
2019-06-13 13:37:00 +00:00
|
|
|
return &(it->second);
|
|
|
|
|
2020-11-13 11:39:47 +04:00
|
|
|
return nullptr;
|
2019-06-13 13:37:00 +00:00
|
|
|
}
|
|
|
|
|
2023-04-20 00:25:42 +02:00
|
|
|
template <class T, class Id>
|
|
|
|
bool TypedDynamicStore<T, Id>::isDynamic(const Id& id) const
|
2015-07-09 19:22:04 +02:00
|
|
|
{
|
|
|
|
typename Dynamic::const_iterator dit = mDynamic.find(id);
|
|
|
|
return (dit != mDynamic.end());
|
|
|
|
}
|
2023-04-20 00:25:42 +02:00
|
|
|
template <class T, class Id>
|
|
|
|
const T* TypedDynamicStore<T, Id>::searchRandom(const std::string_view prefix, Misc::Rng::Generator& prng) const
|
2015-07-09 19:22:04 +02:00
|
|
|
{
|
2023-04-20 00:25:42 +02:00
|
|
|
if constexpr (std::is_same_v<Id, ESM::RefId>)
|
|
|
|
{
|
|
|
|
std::vector<const T*> results;
|
|
|
|
std::copy_if(mShared.begin(), mShared.end(), std::back_inserter(results),
|
|
|
|
[prefix](const T* item) { return item->mId.startsWith(prefix); });
|
|
|
|
if (!results.empty())
|
|
|
|
return results[Misc::Rng::rollDice(results.size(), prng)];
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
throw std::runtime_error("Store<T>::searchRandom is supported only if Id is ESM::RefId");
|
2015-07-09 19:22:04 +02:00
|
|
|
}
|
2023-04-20 00:25:42 +02:00
|
|
|
template <class T, class Id>
|
|
|
|
const T* TypedDynamicStore<T, Id>::find(const Id& id) const
|
2015-07-09 19:22:04 +02:00
|
|
|
{
|
|
|
|
const T* ptr = search(id);
|
2020-11-13 11:39:47 +04:00
|
|
|
if (ptr == nullptr)
|
2019-01-07 17:47:39 +04:00
|
|
|
{
|
2021-10-12 00:18:23 +02:00
|
|
|
std::stringstream msg;
|
2022-12-28 20:48:25 +01:00
|
|
|
if constexpr (!ESM::isESM4Rec(T::sRecordId))
|
|
|
|
{
|
2023-01-02 19:20:03 +01:00
|
|
|
msg << T::getRecordType();
|
2022-12-28 20:48:25 +01:00
|
|
|
}
|
2023-01-04 14:07:47 +01:00
|
|
|
else
|
|
|
|
{
|
|
|
|
msg << "ESM::REC_" << getRecNameString(T::sRecordId).toStringView();
|
|
|
|
}
|
2023-01-02 19:20:03 +01:00
|
|
|
msg << " '" << id << "' not found";
|
2021-10-12 00:18:23 +02:00
|
|
|
throw std::runtime_error(msg.str());
|
2015-07-09 19:22:04 +02:00
|
|
|
}
|
|
|
|
return ptr;
|
|
|
|
}
|
2023-04-20 00:25:42 +02:00
|
|
|
template <class T, class Id>
|
|
|
|
RecordId TypedDynamicStore<T, Id>::load(ESM::ESMReader& esm)
|
2015-07-09 19:22:04 +02:00
|
|
|
{
|
2015-07-12 12:01:18 +03:00
|
|
|
T record;
|
2015-07-21 13:17:03 +03:00
|
|
|
bool isDeleted = false;
|
2022-12-28 20:48:25 +01:00
|
|
|
if constexpr (!ESM::isESM4Rec(T::sRecordId))
|
|
|
|
{
|
|
|
|
record.load(esm, isDeleted);
|
|
|
|
}
|
2015-07-09 19:22:04 +02:00
|
|
|
|
2021-05-14 23:38:39 +02:00
|
|
|
std::pair<typename Static::iterator, bool> inserted = mStatic.insert_or_assign(record.mId, record);
|
2015-07-09 19:22:04 +02:00
|
|
|
if (inserted.second)
|
|
|
|
mShared.push_back(&inserted.first->second);
|
|
|
|
|
2023-04-20 00:25:42 +02:00
|
|
|
if constexpr (std::is_same_v<Id, ESM::RefId>)
|
|
|
|
return RecordId(record.mId, isDeleted);
|
|
|
|
else
|
|
|
|
return RecordId();
|
2015-07-09 19:22:04 +02:00
|
|
|
}
|
2023-04-20 00:25:42 +02:00
|
|
|
|
|
|
|
template <class T, class Id>
|
|
|
|
void TypedDynamicStore<T, Id>::setUp()
|
2015-07-09 19:22:04 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2023-04-20 00:25:42 +02:00
|
|
|
template <class T, class Id>
|
|
|
|
typename TypedDynamicStore<T, Id>::iterator TypedDynamicStore<T, Id>::begin() const
|
2015-07-09 19:22:04 +02:00
|
|
|
{
|
2021-06-30 15:34:40 +10:00
|
|
|
return mShared.begin();
|
2015-07-09 19:22:04 +02:00
|
|
|
}
|
2023-04-20 00:25:42 +02:00
|
|
|
template <class T, class Id>
|
|
|
|
typename TypedDynamicStore<T, Id>::iterator TypedDynamicStore<T, Id>::end() const
|
2015-07-09 19:22:04 +02:00
|
|
|
{
|
|
|
|
return mShared.end();
|
|
|
|
}
|
|
|
|
|
2023-04-20 00:25:42 +02:00
|
|
|
template <class T, class Id>
|
|
|
|
size_t TypedDynamicStore<T, Id>::getSize() const
|
2015-07-09 19:22:04 +02:00
|
|
|
{
|
|
|
|
return mShared.size();
|
|
|
|
}
|
|
|
|
|
2023-04-20 00:25:42 +02:00
|
|
|
template <class T, class Id>
|
|
|
|
int TypedDynamicStore<T, Id>::getDynamicSize() const
|
2015-07-09 19:22:04 +02:00
|
|
|
{
|
|
|
|
return mDynamic.size();
|
|
|
|
}
|
2023-04-20 00:25:42 +02:00
|
|
|
template <class T, class Id>
|
|
|
|
void TypedDynamicStore<T, Id>::listIdentifier(std::vector<Id>& list) const
|
2015-07-09 19:22:04 +02:00
|
|
|
{
|
|
|
|
list.reserve(list.size() + getSize());
|
|
|
|
typename std::vector<T*>::const_iterator it = mShared.begin();
|
|
|
|
for (; it != mShared.end(); ++it)
|
|
|
|
{
|
|
|
|
list.push_back((*it)->mId);
|
|
|
|
}
|
|
|
|
}
|
2023-04-20 00:25:42 +02:00
|
|
|
template <class T, class Id>
|
|
|
|
T* TypedDynamicStore<T, Id>::insert(const T& item, bool overrideOnly)
|
2015-07-09 19:22:04 +02:00
|
|
|
{
|
2021-03-22 22:29:10 +01:00
|
|
|
if (overrideOnly)
|
|
|
|
{
|
2021-10-30 17:27:57 +00:00
|
|
|
auto it = mStatic.find(item.mId);
|
2021-03-22 22:29:10 +01:00
|
|
|
if (it == mStatic.end())
|
|
|
|
return nullptr;
|
|
|
|
}
|
2021-10-30 17:27:57 +00:00
|
|
|
std::pair<typename Dynamic::iterator, bool> result = mDynamic.insert_or_assign(item.mId, item);
|
2015-07-09 19:22:04 +02:00
|
|
|
T* ptr = &result.first->second;
|
2021-05-14 23:38:39 +02:00
|
|
|
if (result.second)
|
2015-07-09 19:22:04 +02:00
|
|
|
mShared.push_back(ptr);
|
|
|
|
return ptr;
|
|
|
|
}
|
2023-04-20 00:25:42 +02:00
|
|
|
template <class T, class Id>
|
|
|
|
T* TypedDynamicStore<T, Id>::insertStatic(const T& item)
|
2015-07-09 19:22:04 +02:00
|
|
|
{
|
2021-10-30 17:27:57 +00:00
|
|
|
std::pair<typename Static::iterator, bool> result = mStatic.insert_or_assign(item.mId, item);
|
2015-07-09 19:22:04 +02:00
|
|
|
T* ptr = &result.first->second;
|
2021-05-14 23:38:39 +02:00
|
|
|
if (result.second)
|
2015-07-09 19:22:04 +02:00
|
|
|
mShared.push_back(ptr);
|
|
|
|
return ptr;
|
|
|
|
}
|
2023-04-20 00:25:42 +02:00
|
|
|
template <class T, class Id>
|
|
|
|
bool TypedDynamicStore<T, Id>::eraseStatic(const Id& id)
|
2015-07-09 19:22:04 +02:00
|
|
|
{
|
2021-10-30 17:27:57 +00:00
|
|
|
typename Static::iterator it = mStatic.find(id);
|
2015-07-09 19:22:04 +02:00
|
|
|
|
2020-05-16 13:37:00 +00:00
|
|
|
if (it != mStatic.end())
|
|
|
|
{
|
2015-07-09 19:22:04 +02:00
|
|
|
// delete from the static part of mShared
|
|
|
|
typename std::vector<T*>::iterator sharedIter = mShared.begin();
|
|
|
|
typename std::vector<T*>::iterator end = sharedIter + mStatic.size();
|
|
|
|
|
|
|
|
while (sharedIter != mShared.end() && sharedIter != end)
|
|
|
|
{
|
2022-10-18 09:26:55 +02:00
|
|
|
if ((*sharedIter)->mId == id)
|
2021-10-30 17:27:57 +00:00
|
|
|
{
|
2015-07-09 19:22:04 +02:00
|
|
|
mShared.erase(sharedIter);
|
|
|
|
break;
|
2013-02-09 13:00:57 +01:00
|
|
|
}
|
2015-07-09 19:22:04 +02:00
|
|
|
++sharedIter;
|
|
|
|
}
|
|
|
|
mStatic.erase(it);
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2023-04-20 00:25:42 +02:00
|
|
|
template <class T, class Id>
|
|
|
|
bool TypedDynamicStore<T, Id>::erase(const Id& id)
|
2015-07-09 19:22:04 +02:00
|
|
|
{
|
2022-06-13 18:21:29 +02:00
|
|
|
if (!eraseFromMap(mDynamic, id))
|
2015-07-09 19:22:04 +02:00
|
|
|
return false;
|
|
|
|
|
|
|
|
// have to reinit the whole shared part
|
|
|
|
assert(mShared.size() >= mStatic.size());
|
|
|
|
mShared.erase(mShared.begin() + mStatic.size(), mShared.end());
|
2021-10-30 17:27:57 +00:00
|
|
|
for (auto it = mDynamic.begin(); it != mDynamic.end(); ++it)
|
|
|
|
{
|
2015-07-09 19:22:04 +02:00
|
|
|
mShared.push_back(&it->second);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
2023-04-20 00:25:42 +02:00
|
|
|
template <class T, class Id>
|
|
|
|
bool TypedDynamicStore<T, Id>::erase(const T& item)
|
2015-07-09 19:22:04 +02:00
|
|
|
{
|
|
|
|
return erase(item.mId);
|
|
|
|
}
|
2023-04-20 00:25:42 +02:00
|
|
|
template <class T, class Id>
|
|
|
|
void TypedDynamicStore<T, Id>::write(ESM::ESMWriter& writer, Loading::Listener& progress) const
|
2015-07-09 19:22:04 +02:00
|
|
|
{
|
|
|
|
for (typename Dynamic::const_iterator iter(mDynamic.begin()); iter != mDynamic.end(); ++iter)
|
|
|
|
{
|
2022-12-28 20:48:25 +01:00
|
|
|
if constexpr (!ESM::isESM4Rec(T::sRecordId))
|
|
|
|
{
|
2023-01-02 19:20:03 +01:00
|
|
|
writer.startRecord(T::sRecordId);
|
2022-12-28 20:48:25 +01:00
|
|
|
iter->second.save(writer);
|
2023-01-02 19:20:03 +01:00
|
|
|
writer.endRecord(T::sRecordId);
|
2022-12-28 20:48:25 +01:00
|
|
|
}
|
2015-07-09 19:22:04 +02:00
|
|
|
}
|
|
|
|
}
|
2023-04-20 00:25:42 +02:00
|
|
|
template <class T, class Id>
|
|
|
|
RecordId TypedDynamicStore<T, Id>::read(ESM::ESMReader& reader, bool overrideOnly)
|
2015-07-09 19:22:04 +02:00
|
|
|
{
|
|
|
|
T record;
|
2015-07-21 13:17:03 +03:00
|
|
|
bool isDeleted = false;
|
2022-12-28 20:48:25 +01:00
|
|
|
if constexpr (!ESM::isESM4Rec(T::sRecordId))
|
|
|
|
{
|
|
|
|
record.load(reader, isDeleted);
|
|
|
|
}
|
2021-03-22 22:29:10 +01:00
|
|
|
insert(record, overrideOnly);
|
2015-07-09 19:22:04 +02:00
|
|
|
|
2023-04-20 00:25:42 +02:00
|
|
|
if constexpr (std::is_same_v<Id, ESM::RefId>)
|
|
|
|
return RecordId(record.mId, isDeleted);
|
|
|
|
else
|
|
|
|
return RecordId();
|
2015-07-12 12:01:18 +03:00
|
|
|
}
|
2015-07-09 19:22:04 +02:00
|
|
|
|
|
|
|
// LandTexture
|
|
|
|
//=========================================================================
|
|
|
|
Store<ESM::LandTexture>::Store() {}
|
|
|
|
const ESM::LandTexture* Store<ESM::LandTexture>::search(size_t index, size_t plugin) const
|
|
|
|
{
|
|
|
|
assert(plugin < mStatic.size());
|
|
|
|
const LandTextureList& ltexl = mStatic[plugin];
|
|
|
|
|
2015-11-27 21:40:36 +01:00
|
|
|
if (index >= ltexl.size())
|
2018-10-09 10:21:12 +04:00
|
|
|
return nullptr;
|
2015-11-27 21:40:36 +01:00
|
|
|
return <exl[index];
|
2015-07-09 19:22:04 +02:00
|
|
|
}
|
|
|
|
const ESM::LandTexture* Store<ESM::LandTexture>::find(size_t index, size_t plugin) const
|
|
|
|
{
|
|
|
|
const ESM::LandTexture* ptr = search(index, plugin);
|
2020-11-13 11:39:47 +04:00
|
|
|
if (ptr == nullptr)
|
2019-01-07 17:47:39 +04:00
|
|
|
{
|
|
|
|
const std::string msg = "Land texture with index " + std::to_string(index) + " not found";
|
|
|
|
throw std::runtime_error(msg);
|
2015-07-09 19:22:04 +02:00
|
|
|
}
|
|
|
|
return ptr;
|
|
|
|
}
|
2022-08-16 22:44:13 +02:00
|
|
|
|
|
|
|
void Store<ESM::LandTexture>::resize(std::size_t num)
|
|
|
|
{
|
|
|
|
mStatic.resize(num);
|
|
|
|
}
|
|
|
|
|
2015-07-09 19:22:04 +02:00
|
|
|
size_t Store<ESM::LandTexture>::getSize() const
|
|
|
|
{
|
|
|
|
return mStatic.size();
|
|
|
|
}
|
|
|
|
size_t Store<ESM::LandTexture>::getSize(size_t plugin) const
|
|
|
|
{
|
|
|
|
assert(plugin < mStatic.size());
|
|
|
|
return mStatic[plugin].size();
|
|
|
|
}
|
2021-11-04 15:55:32 +00:00
|
|
|
RecordId Store<ESM::LandTexture>::load(ESM::ESMReader& esm)
|
2015-07-09 19:22:04 +02:00
|
|
|
{
|
|
|
|
ESM::LandTexture lt;
|
2015-07-21 13:17:03 +03:00
|
|
|
bool isDeleted = false;
|
|
|
|
|
|
|
|
lt.load(esm, isDeleted);
|
2015-07-09 19:22:04 +02:00
|
|
|
|
2019-03-11 15:05:43 +04:00
|
|
|
// Replace texture for records with given ID and index from all plugins.
|
|
|
|
for (unsigned int i = 0; i < mStatic.size(); i++)
|
|
|
|
{
|
|
|
|
ESM::LandTexture* tex = const_cast<ESM::LandTexture*>(search(lt.mIndex, i));
|
|
|
|
if (tex)
|
|
|
|
{
|
2022-10-18 09:26:55 +02:00
|
|
|
if (tex->mId == lt.mId)
|
2019-03-11 15:05:43 +04:00
|
|
|
tex->mTexture = lt.mTexture;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-04 15:55:32 +00:00
|
|
|
LandTextureList& ltexl = mStatic.back();
|
2015-07-09 19:22:04 +02:00
|
|
|
if (lt.mIndex + 1 > (int)ltexl.size())
|
|
|
|
ltexl.resize(lt.mIndex + 1);
|
|
|
|
|
|
|
|
// Store it
|
2021-10-30 17:27:57 +00:00
|
|
|
auto idx = lt.mIndex;
|
|
|
|
ltexl[idx] = std::move(lt);
|
2015-07-12 15:20:22 +03:00
|
|
|
|
2021-10-30 17:27:57 +00:00
|
|
|
return RecordId(ltexl[idx].mId, isDeleted);
|
2015-07-09 19:22:04 +02:00
|
|
|
}
|
|
|
|
Store<ESM::LandTexture>::iterator Store<ESM::LandTexture>::begin(size_t plugin) const
|
|
|
|
{
|
|
|
|
assert(plugin < mStatic.size());
|
|
|
|
return mStatic[plugin].begin();
|
|
|
|
}
|
|
|
|
Store<ESM::LandTexture>::iterator Store<ESM::LandTexture>::end(size_t plugin) const
|
|
|
|
{
|
|
|
|
assert(plugin < mStatic.size());
|
|
|
|
return mStatic[plugin].end();
|
|
|
|
}
|
2021-06-30 15:34:40 +10:00
|
|
|
|
2015-07-09 19:22:04 +02:00
|
|
|
// Land
|
|
|
|
//=========================================================================
|
|
|
|
Store<ESM::Land>::~Store() {}
|
|
|
|
size_t Store<ESM::Land>::getSize() const
|
|
|
|
{
|
|
|
|
return mStatic.size();
|
|
|
|
}
|
|
|
|
Store<ESM::Land>::iterator Store<ESM::Land>::begin() const
|
|
|
|
{
|
|
|
|
return iterator(mStatic.begin());
|
|
|
|
}
|
|
|
|
Store<ESM::Land>::iterator Store<ESM::Land>::end() const
|
|
|
|
{
|
|
|
|
return iterator(mStatic.end());
|
|
|
|
}
|
2017-02-13 01:29:22 +01:00
|
|
|
const ESM::Land* Store<ESM::Land>::search(int x, int y) const
|
2015-07-09 19:22:04 +02:00
|
|
|
{
|
2017-02-14 07:10:01 +01:00
|
|
|
std::pair<int, int> comp(x, y);
|
2021-07-26 18:30:06 +02:00
|
|
|
if (auto it = mStatic.find(comp); it != mStatic.end() && it->mX == x && it->mY == y)
|
|
|
|
return &*it;
|
2020-11-13 11:39:47 +04:00
|
|
|
return nullptr;
|
2015-07-09 19:22:04 +02:00
|
|
|
}
|
2017-02-13 01:29:22 +01:00
|
|
|
const ESM::Land* Store<ESM::Land>::find(int x, int y) const
|
2015-07-09 19:22:04 +02:00
|
|
|
{
|
2017-02-13 01:29:22 +01:00
|
|
|
const ESM::Land* ptr = search(x, y);
|
2020-11-13 11:39:47 +04:00
|
|
|
if (ptr == nullptr)
|
2019-01-07 17:47:39 +04:00
|
|
|
{
|
|
|
|
const std::string msg = "Land at (" + std::to_string(x) + ", " + std::to_string(y) + ") not found";
|
|
|
|
throw std::runtime_error(msg);
|
2015-07-09 19:22:04 +02:00
|
|
|
}
|
|
|
|
return ptr;
|
|
|
|
}
|
2015-07-12 15:20:22 +03:00
|
|
|
RecordId Store<ESM::Land>::load(ESM::ESMReader& esm)
|
2015-07-09 19:22:04 +02:00
|
|
|
{
|
2021-07-26 18:30:06 +02:00
|
|
|
ESM::Land land;
|
2015-07-21 13:17:03 +03:00
|
|
|
bool isDeleted = false;
|
|
|
|
|
2021-07-26 18:30:06 +02:00
|
|
|
land.load(esm, isDeleted);
|
2015-07-09 19:22:04 +02:00
|
|
|
|
|
|
|
// Same area defined in multiple plugins? -> last plugin wins
|
2022-06-26 21:39:05 +02:00
|
|
|
auto it = mStatic.lower_bound(land);
|
|
|
|
if (it != mStatic.end() && (std::tie(it->mX, it->mY) == std::tie(land.mX, land.mY)))
|
|
|
|
{
|
2021-07-28 10:29:16 +02:00
|
|
|
auto nh = mStatic.extract(it);
|
|
|
|
nh.value() = std::move(land);
|
|
|
|
mStatic.insert(std::move(nh));
|
|
|
|
}
|
2022-06-26 21:39:05 +02:00
|
|
|
else
|
|
|
|
mStatic.insert(it, std::move(land));
|
2015-07-12 15:20:22 +03:00
|
|
|
|
2023-02-17 19:20:29 +01:00
|
|
|
return RecordId(ESM::RefId(), isDeleted);
|
2015-07-09 19:22:04 +02:00
|
|
|
}
|
|
|
|
void Store<ESM::Land>::setUp()
|
|
|
|
{
|
2019-05-08 14:42:17 +04:00
|
|
|
// The land is static for given game session, there is no need to refresh it every load.
|
|
|
|
if (mBuilt)
|
2023-05-30 11:43:20 +02:00
|
|
|
throw std::logic_error("Store<ESM::Land>::setUp() is called twice");
|
2019-05-08 14:42:17 +04:00
|
|
|
|
|
|
|
mBuilt = true;
|
2015-07-09 19:22:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Cell
|
|
|
|
//=========================================================================
|
|
|
|
|
2023-02-18 22:32:27 +01:00
|
|
|
const ESM::Cell* Store<ESM::Cell>::search(const ESM::RefId& cellId) const
|
|
|
|
{
|
|
|
|
auto foundCellIt = mCells.find(cellId);
|
2023-02-19 17:42:37 +01:00
|
|
|
if (foundCellIt != mCells.end())
|
2023-02-18 22:32:27 +01:00
|
|
|
return &foundCellIt->second;
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2015-07-09 19:22:04 +02:00
|
|
|
const ESM::Cell* Store<ESM::Cell>::search(const ESM::Cell& cell) const
|
|
|
|
{
|
2023-02-18 22:32:27 +01:00
|
|
|
return search(cell.mId);
|
2015-07-09 19:22:04 +02:00
|
|
|
}
|
2021-06-30 15:34:40 +10:00
|
|
|
|
2022-01-22 15:58:41 +01:00
|
|
|
// this method *must* be called right after esm3.loadCell()
|
2015-07-09 19:22:04 +02:00
|
|
|
void Store<ESM::Cell>::handleMovedCellRefs(ESM::ESMReader& esm, ESM::Cell* cell)
|
|
|
|
{
|
2021-06-30 15:34:40 +10:00
|
|
|
ESM::CellRef ref;
|
|
|
|
ESM::MovedCellRef cMRef;
|
|
|
|
bool deleted = false;
|
2021-07-12 17:30:39 +02:00
|
|
|
bool moved = false;
|
2015-07-09 19:22:04 +02:00
|
|
|
|
2021-06-30 15:34:40 +10:00
|
|
|
ESM::ESM_Context ctx = esm.getContext();
|
|
|
|
|
|
|
|
// Handling MovedCellRefs, there is no way to do it inside loadcell
|
|
|
|
// TODO: verify above comment
|
|
|
|
//
|
|
|
|
// Get regular moved reference data. Adapted from CellStore::loadRefs. Maybe we can optimize the following
|
|
|
|
// implementation when the oher implementation works as well.
|
2022-04-08 17:08:18 +02:00
|
|
|
while (ESM::Cell::getNextRef(esm, ref, deleted, cMRef, moved, ESM::Cell::GetNextRefMode::LoadOnlyMoved))
|
2021-06-30 15:34:40 +10:00
|
|
|
{
|
2021-07-12 17:30:39 +02:00
|
|
|
if (!moved)
|
|
|
|
continue;
|
2015-07-09 19:22:04 +02:00
|
|
|
|
2021-06-30 15:34:40 +10:00
|
|
|
ESM::Cell* cellAlt = const_cast<ESM::Cell*>(searchOrCreate(cMRef.mTarget[0], cMRef.mTarget[1]));
|
2015-07-09 19:22:04 +02:00
|
|
|
|
2016-07-22 01:59:02 +02:00
|
|
|
// Add data required to make reference appear in the correct cell.
|
|
|
|
// We should not need to test for duplicates, as this part of the code is pre-cell merge.
|
|
|
|
cell->mMovedRefs.push_back(cMRef);
|
|
|
|
|
|
|
|
// But there may be duplicates here!
|
|
|
|
ESM::CellRefTracker::iterator iter = std::find_if(
|
|
|
|
cellAlt->mLeasedRefs.begin(), cellAlt->mLeasedRefs.end(), ESM::CellRefTrackerPredicate(ref.mRefNum));
|
|
|
|
if (iter == cellAlt->mLeasedRefs.end())
|
2021-05-15 02:29:50 +02:00
|
|
|
cellAlt->mLeasedRefs.emplace_back(std::move(ref), deleted);
|
2016-07-22 01:59:02 +02:00
|
|
|
else
|
2021-05-15 02:29:50 +02:00
|
|
|
*iter = std::make_pair(std::move(ref), deleted);
|
2021-06-30 15:34:40 +10:00
|
|
|
|
|
|
|
cMRef.mRefNum.mIndex = 0;
|
2015-07-09 19:22:04 +02:00
|
|
|
}
|
2021-06-30 15:34:40 +10:00
|
|
|
|
|
|
|
esm.restoreContext(ctx);
|
2015-07-09 19:22:04 +02:00
|
|
|
}
|
2023-01-19 17:31:45 +01:00
|
|
|
const ESM::Cell* Store<ESM::Cell>::search(std::string_view name) const
|
2015-07-09 19:22:04 +02:00
|
|
|
{
|
2023-01-21 17:45:23 +01:00
|
|
|
DynamicInt::const_iterator it = mInt.find(name);
|
2020-05-16 13:37:00 +00:00
|
|
|
if (it != mInt.end())
|
|
|
|
{
|
2023-02-18 22:32:27 +01:00
|
|
|
return it->second;
|
2015-07-09 19:22:04 +02:00
|
|
|
}
|
|
|
|
|
2023-01-21 17:45:23 +01:00
|
|
|
DynamicInt::const_iterator dit = mDynamicInt.find(name);
|
2015-07-09 19:22:04 +02:00
|
|
|
if (dit != mDynamicInt.end())
|
|
|
|
{
|
2023-02-18 22:32:27 +01:00
|
|
|
return dit->second;
|
2015-07-09 19:22:04 +02:00
|
|
|
}
|
|
|
|
|
2020-11-13 11:39:47 +04:00
|
|
|
return nullptr;
|
2015-07-09 19:22:04 +02:00
|
|
|
}
|
|
|
|
const ESM::Cell* Store<ESM::Cell>::search(int x, int y) const
|
|
|
|
{
|
|
|
|
std::pair<int, int> key(x, y);
|
|
|
|
DynamicExt::const_iterator it = mExt.find(key);
|
2021-10-30 17:27:57 +00:00
|
|
|
if (it != mExt.end())
|
2023-02-18 22:32:27 +01:00
|
|
|
return it->second;
|
2015-07-09 19:22:04 +02:00
|
|
|
|
|
|
|
DynamicExt::const_iterator dit = mDynamicExt.find(key);
|
2021-10-30 17:27:57 +00:00
|
|
|
if (dit != mDynamicExt.end())
|
2023-02-18 22:32:27 +01:00
|
|
|
return dit->second;
|
2015-07-09 19:22:04 +02:00
|
|
|
|
2020-11-13 11:39:47 +04:00
|
|
|
return nullptr;
|
2015-07-09 19:22:04 +02:00
|
|
|
}
|
2019-06-13 13:37:00 +00:00
|
|
|
const ESM::Cell* Store<ESM::Cell>::searchStatic(int x, int y) const
|
|
|
|
{
|
2021-10-30 17:27:57 +00:00
|
|
|
DynamicExt::const_iterator it = mExt.find(std::make_pair(x, y));
|
|
|
|
if (it != mExt.end())
|
2023-02-18 22:32:27 +01:00
|
|
|
return (it->second);
|
2020-11-13 11:39:47 +04:00
|
|
|
return nullptr;
|
2019-06-13 13:37:00 +00:00
|
|
|
}
|
2015-07-09 19:22:04 +02:00
|
|
|
const ESM::Cell* Store<ESM::Cell>::searchOrCreate(int x, int y)
|
|
|
|
{
|
|
|
|
std::pair<int, int> key(x, y);
|
|
|
|
DynamicExt::const_iterator it = mExt.find(key);
|
2021-10-30 17:27:57 +00:00
|
|
|
if (it != mExt.end())
|
2023-02-18 22:32:27 +01:00
|
|
|
return (it->second);
|
2015-07-09 19:22:04 +02:00
|
|
|
|
|
|
|
DynamicExt::const_iterator dit = mDynamicExt.find(key);
|
2021-10-30 17:27:57 +00:00
|
|
|
if (dit != mDynamicExt.end())
|
2023-02-18 22:32:27 +01:00
|
|
|
return dit->second;
|
2015-07-09 19:22:04 +02:00
|
|
|
|
|
|
|
ESM::Cell newCell;
|
|
|
|
newCell.mData.mX = x;
|
|
|
|
newCell.mData.mY = y;
|
|
|
|
newCell.mData.mFlags = ESM::Cell::HasWater;
|
|
|
|
newCell.mAmbi.mAmbient = 0;
|
|
|
|
newCell.mAmbi.mSunlight = 0;
|
|
|
|
newCell.mAmbi.mFog = 0;
|
|
|
|
newCell.mAmbi.mFogDensity = 0;
|
2023-02-18 22:32:27 +01:00
|
|
|
newCell.updateId();
|
|
|
|
|
|
|
|
ESM::Cell* newCellInserted = &mCells.insert(std::make_pair(newCell.mId, newCell)).first->second;
|
2022-07-05 17:19:47 +04:00
|
|
|
|
2023-02-18 22:32:27 +01:00
|
|
|
return mExt.insert(std::make_pair(key, newCellInserted)).first->second;
|
2015-07-09 19:22:04 +02:00
|
|
|
}
|
2023-04-06 12:52:52 +02:00
|
|
|
const ESM::Cell* Store<ESM::Cell>::find(const ESM::RefId& id) const
|
|
|
|
{
|
|
|
|
const ESM::Cell* ptr = search(id);
|
|
|
|
if (ptr == nullptr)
|
|
|
|
{
|
|
|
|
const std::string msg = "Cell " + id.toDebugString() + " not found";
|
|
|
|
throw std::runtime_error(msg);
|
|
|
|
}
|
|
|
|
return ptr;
|
|
|
|
}
|
2023-01-19 17:31:45 +01:00
|
|
|
const ESM::Cell* Store<ESM::Cell>::find(std::string_view id) const
|
2015-07-09 19:22:04 +02:00
|
|
|
{
|
|
|
|
const ESM::Cell* ptr = search(id);
|
2020-11-13 11:39:47 +04:00
|
|
|
if (ptr == nullptr)
|
2019-01-07 17:47:39 +04:00
|
|
|
{
|
2023-01-19 17:31:45 +01:00
|
|
|
const std::string msg = "Cell '" + std::string(id) + "' not found";
|
2019-01-07 17:47:39 +04:00
|
|
|
throw std::runtime_error(msg);
|
2015-07-09 19:22:04 +02:00
|
|
|
}
|
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
const ESM::Cell* Store<ESM::Cell>::find(int x, int y) const
|
|
|
|
{
|
|
|
|
const ESM::Cell* ptr = search(x, y);
|
2020-11-13 11:39:47 +04:00
|
|
|
if (ptr == nullptr)
|
2019-01-07 17:47:39 +04:00
|
|
|
{
|
|
|
|
const std::string msg = "Exterior at (" + std::to_string(x) + ", " + std::to_string(y) + ") not found";
|
|
|
|
throw std::runtime_error(msg);
|
2015-07-09 19:22:04 +02:00
|
|
|
}
|
|
|
|
return ptr;
|
|
|
|
}
|
2018-02-13 00:38:55 +00:00
|
|
|
void Store<ESM::Cell>::clearDynamic()
|
|
|
|
{
|
|
|
|
setUp();
|
|
|
|
}
|
|
|
|
|
2015-07-09 19:22:04 +02:00
|
|
|
void Store<ESM::Cell>::setUp()
|
|
|
|
{
|
|
|
|
mSharedInt.clear();
|
|
|
|
mSharedInt.reserve(mInt.size());
|
2021-05-16 09:40:41 +02:00
|
|
|
for (auto& [_, cell] : mInt)
|
2023-02-18 22:32:27 +01:00
|
|
|
mSharedInt.push_back(cell);
|
2015-07-09 19:22:04 +02:00
|
|
|
|
|
|
|
mSharedExt.clear();
|
|
|
|
mSharedExt.reserve(mExt.size());
|
2021-05-16 09:40:41 +02:00
|
|
|
for (auto& [_, cell] : mExt)
|
2023-02-18 22:32:27 +01:00
|
|
|
mSharedExt.push_back(cell);
|
2015-07-09 19:22:04 +02:00
|
|
|
}
|
2015-07-12 15:20:22 +03:00
|
|
|
RecordId Store<ESM::Cell>::load(ESM::ESMReader& esm)
|
2015-07-09 19:22:04 +02:00
|
|
|
{
|
|
|
|
// Don't automatically assume that a new cell must be spawned. Multiple plugins write to the same cell,
|
|
|
|
// and we merge all this data into one Cell object. However, we can't simply search for the cell id,
|
|
|
|
// as many exterior cells do not have a name. Instead, we need to search by (x,y) coordinates - and they
|
|
|
|
// are not available until both cells have been loaded at least partially!
|
|
|
|
|
|
|
|
// All cells have a name record, even nameless exterior cells.
|
2023-02-18 22:32:27 +01:00
|
|
|
ESM::Cell* emplacedCell = nullptr;
|
2015-07-21 13:17:03 +03:00
|
|
|
bool isDeleted = false;
|
2023-05-05 16:39:24 +02:00
|
|
|
bool newCell = false;
|
2015-07-09 19:22:04 +02:00
|
|
|
|
2023-02-18 22:32:27 +01:00
|
|
|
{
|
|
|
|
ESM::Cell cellToLoad;
|
|
|
|
cellToLoad.loadNameAndData(esm, isDeleted);
|
2023-05-05 16:39:24 +02:00
|
|
|
auto [it, inserted] = mCells.insert(std::make_pair(cellToLoad.mId, cellToLoad));
|
|
|
|
emplacedCell = &it->second;
|
|
|
|
if (!inserted)
|
|
|
|
{
|
|
|
|
emplacedCell->mData = cellToLoad.mData;
|
|
|
|
emplacedCell->mName = cellToLoad.mName;
|
|
|
|
}
|
|
|
|
newCell = inserted;
|
2023-02-18 22:32:27 +01:00
|
|
|
}
|
|
|
|
ESM::Cell& cell = *emplacedCell;
|
2021-06-30 15:34:40 +10:00
|
|
|
// Load the (x,y) coordinates of the cell, if it is an exterior cell,
|
2015-07-09 19:22:04 +02:00
|
|
|
// so we can find the cell we need to merge with
|
|
|
|
if (cell.mData.mFlags & ESM::Cell::Interior)
|
|
|
|
{
|
2023-05-05 16:39:24 +02:00
|
|
|
cell.loadCell(esm, true);
|
|
|
|
if (newCell)
|
2023-02-18 22:32:27 +01:00
|
|
|
mInt[cell.mName] = &cell;
|
2015-07-09 19:22:04 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2023-05-05 16:39:24 +02:00
|
|
|
cell.loadCell(esm, false);
|
|
|
|
// handle moved ref (MVRF) subrecords
|
|
|
|
ESM::MovedCellRefTracker newMovedRefs;
|
|
|
|
std::swap(newMovedRefs, cell.mMovedRefs);
|
|
|
|
handleMovedCellRefs(esm, &cell);
|
|
|
|
std::swap(newMovedRefs, cell.mMovedRefs);
|
|
|
|
// push the new references on the list of references to manage
|
|
|
|
cell.postLoad(esm);
|
|
|
|
if (newCell)
|
|
|
|
mExt[std::make_pair(cell.mData.mX, cell.mData.mY)] = &cell;
|
|
|
|
else
|
2015-07-09 19:22:04 +02:00
|
|
|
{
|
|
|
|
// merge lists of leased references, use newer data in case of conflict
|
2023-05-05 16:39:24 +02:00
|
|
|
for (const auto& movedRef : newMovedRefs)
|
2015-07-09 19:22:04 +02:00
|
|
|
{
|
|
|
|
// remove reference from current leased ref tracker and add it to new cell
|
2023-05-07 17:27:28 +02:00
|
|
|
auto itOld = std::find(cell.mMovedRefs.begin(), cell.mMovedRefs.end(), movedRef.mRefNum);
|
|
|
|
if (itOld != cell.mMovedRefs.end())
|
2016-07-22 02:12:03 +02:00
|
|
|
{
|
2023-05-07 17:27:28 +02:00
|
|
|
if (movedRef.mTarget[0] != itOld->mTarget[0] || movedRef.mTarget[1] != itOld->mTarget[1])
|
2016-07-22 02:12:03 +02:00
|
|
|
{
|
2023-05-07 17:27:28 +02:00
|
|
|
ESM::Cell* wipecell = const_cast<ESM::Cell*>(search(itOld->mTarget[0], itOld->mTarget[1]));
|
|
|
|
auto itLease = std::find_if(wipecell->mLeasedRefs.begin(), wipecell->mLeasedRefs.end(),
|
2023-05-05 16:39:24 +02:00
|
|
|
ESM::CellRefTrackerPredicate(movedRef.mRefNum));
|
2023-05-07 17:27:28 +02:00
|
|
|
if (itLease != wipecell->mLeasedRefs.end())
|
|
|
|
wipecell->mLeasedRefs.erase(itLease);
|
2016-07-22 02:12:03 +02:00
|
|
|
else
|
2023-05-05 16:39:24 +02:00
|
|
|
Log(Debug::Error) << "Error: can't find " << movedRef.mRefNum.mIndex << " "
|
|
|
|
<< movedRef.mRefNum.mContentFile << " in leasedRefs";
|
2016-07-22 02:12:03 +02:00
|
|
|
}
|
2023-05-07 17:27:28 +02:00
|
|
|
*itOld = movedRef;
|
2015-07-09 19:22:04 +02:00
|
|
|
}
|
|
|
|
else
|
2023-05-05 16:39:24 +02:00
|
|
|
cell.mMovedRefs.push_back(movedRef);
|
2015-07-09 19:22:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// We don't need to merge mLeasedRefs of cell / oldcell. This list is filled when another cell moves a
|
|
|
|
// reference to this cell, so the list for the new cell should be empty. The list for oldcell,
|
|
|
|
// however, could have leased refs in it and so should be kept.
|
|
|
|
}
|
|
|
|
}
|
2015-07-21 13:17:03 +03:00
|
|
|
|
2023-02-18 22:32:27 +01:00
|
|
|
return RecordId(cell.mId, isDeleted);
|
2015-07-09 19:22:04 +02:00
|
|
|
}
|
|
|
|
Store<ESM::Cell>::iterator Store<ESM::Cell>::intBegin() const
|
|
|
|
{
|
|
|
|
return iterator(mSharedInt.begin());
|
|
|
|
}
|
|
|
|
Store<ESM::Cell>::iterator Store<ESM::Cell>::intEnd() const
|
|
|
|
{
|
|
|
|
return iterator(mSharedInt.end());
|
|
|
|
}
|
|
|
|
Store<ESM::Cell>::iterator Store<ESM::Cell>::extBegin() const
|
|
|
|
{
|
|
|
|
return iterator(mSharedExt.begin());
|
|
|
|
}
|
|
|
|
Store<ESM::Cell>::iterator Store<ESM::Cell>::extEnd() const
|
|
|
|
{
|
|
|
|
return iterator(mSharedExt.end());
|
|
|
|
}
|
2023-01-19 17:31:45 +01:00
|
|
|
const ESM::Cell* Store<ESM::Cell>::searchExtByName(std::string_view name) const
|
2015-07-09 19:22:04 +02:00
|
|
|
{
|
2019-03-07 12:38:55 +04:00
|
|
|
const ESM::Cell* cell = nullptr;
|
|
|
|
for (const ESM::Cell* sharedCell : mSharedExt)
|
|
|
|
{
|
2023-01-23 22:49:01 +01:00
|
|
|
if (Misc::StringUtils::ciEqual(sharedCell->mName, name))
|
2019-03-07 12:38:55 +04:00
|
|
|
{
|
|
|
|
if (cell == nullptr || (sharedCell->mData.mX > cell->mData.mX)
|
|
|
|
|| (sharedCell->mData.mX == cell->mData.mX && sharedCell->mData.mY > cell->mData.mY))
|
2015-07-09 19:22:04 +02:00
|
|
|
{
|
2019-03-07 12:38:55 +04:00
|
|
|
cell = sharedCell;
|
2015-07-09 19:22:04 +02:00
|
|
|
}
|
2013-02-09 13:00:57 +01:00
|
|
|
}
|
2015-07-09 19:22:04 +02:00
|
|
|
}
|
|
|
|
return cell;
|
|
|
|
}
|
Initial commit: In ESM structures, replace the string members that are RefIds to other records, to a new strong type
The strong type is actually just a string underneath, but this will help in the future to have a distinction so it's easier to search and replace when we use an integer ID
Slowly going through all the changes to make, still hundreds of errors
a lot of functions/structures use std::string or stringview to designate an ID. So it takes time
Continues slowly replacing ids. There are technically more and more compilation errors
I have good hope that there is a point where the amount of errors will dramatically go down as all the main functions use the ESM::RefId type
Continue moving forward, changes to the stores
slowly moving along
Starting to see the fruit of those changes.
still many many error, but more and more Irun into a situation where a function is sandwiched between two functions that use the RefId type.
More replacements. Things are starting to get easier
I can see more and more often the issue is that the function is awaiting a RefId, but is given a string
there is less need to go down functions and to fix a long list of them.
Still moving forward, and for the first time error count is going down!
Good pace, not sure about topics though, mId and mName are actually the same thing and are used interchangeably
Cells are back to using string for the name, haven't fixed everything yet. Many other changes
Under the bar of 400 compilation errors.
more good progress <100 compile errors!
More progress
Game settings store can use string for find, it was a bit absurd how every use of it required to create refId from string
some more progress on other fronts
Mostly game settings clean
one error opened a lot of other errors. Down to 18, but more will prbably appear
only link errors left??
Fixed link errors
OpenMW compiles, and launches, with some issues, but still!
2022-09-25 13:17:09 +02:00
|
|
|
const ESM::Cell* Store<ESM::Cell>::searchExtByRegion(const ESM::RefId& id) const
|
2015-07-09 19:22:04 +02:00
|
|
|
{
|
2019-03-07 12:38:55 +04:00
|
|
|
const ESM::Cell* cell = nullptr;
|
|
|
|
for (const ESM::Cell* sharedCell : mSharedExt)
|
|
|
|
{
|
2022-10-18 09:26:55 +02:00
|
|
|
if (sharedCell->mRegion == id)
|
2019-03-07 12:38:55 +04:00
|
|
|
{
|
|
|
|
if (cell == nullptr || (sharedCell->mData.mX > cell->mData.mX)
|
|
|
|
|| (sharedCell->mData.mX == cell->mData.mX && sharedCell->mData.mY > cell->mData.mY))
|
2015-07-09 19:22:04 +02:00
|
|
|
{
|
2019-03-07 12:38:55 +04:00
|
|
|
cell = sharedCell;
|
2015-07-09 19:22:04 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return cell;
|
|
|
|
}
|
|
|
|
size_t Store<ESM::Cell>::getSize() const
|
|
|
|
{
|
|
|
|
return mSharedInt.size() + mSharedExt.size();
|
|
|
|
}
|
2019-11-24 17:40:19 +04:00
|
|
|
size_t Store<ESM::Cell>::getExtSize() const
|
|
|
|
{
|
|
|
|
return mSharedExt.size();
|
|
|
|
}
|
|
|
|
size_t Store<ESM::Cell>::getIntSize() const
|
|
|
|
{
|
|
|
|
return mSharedInt.size();
|
|
|
|
}
|
Initial commit: In ESM structures, replace the string members that are RefIds to other records, to a new strong type
The strong type is actually just a string underneath, but this will help in the future to have a distinction so it's easier to search and replace when we use an integer ID
Slowly going through all the changes to make, still hundreds of errors
a lot of functions/structures use std::string or stringview to designate an ID. So it takes time
Continues slowly replacing ids. There are technically more and more compilation errors
I have good hope that there is a point where the amount of errors will dramatically go down as all the main functions use the ESM::RefId type
Continue moving forward, changes to the stores
slowly moving along
Starting to see the fruit of those changes.
still many many error, but more and more Irun into a situation where a function is sandwiched between two functions that use the RefId type.
More replacements. Things are starting to get easier
I can see more and more often the issue is that the function is awaiting a RefId, but is given a string
there is less need to go down functions and to fix a long list of them.
Still moving forward, and for the first time error count is going down!
Good pace, not sure about topics though, mId and mName are actually the same thing and are used interchangeably
Cells are back to using string for the name, haven't fixed everything yet. Many other changes
Under the bar of 400 compilation errors.
more good progress <100 compile errors!
More progress
Game settings store can use string for find, it was a bit absurd how every use of it required to create refId from string
some more progress on other fronts
Mostly game settings clean
one error opened a lot of other errors. Down to 18, but more will prbably appear
only link errors left??
Fixed link errors
OpenMW compiles, and launches, with some issues, but still!
2022-09-25 13:17:09 +02:00
|
|
|
void Store<ESM::Cell>::listIdentifier(std::vector<ESM::RefId>& list) const
|
2015-07-09 19:22:04 +02:00
|
|
|
{
|
|
|
|
list.reserve(list.size() + mSharedInt.size());
|
|
|
|
|
2019-03-07 12:38:55 +04:00
|
|
|
for (const ESM::Cell* sharedCell : mSharedInt)
|
|
|
|
{
|
2023-01-19 17:31:45 +01:00
|
|
|
list.push_back(ESM::RefId::stringRefId(sharedCell->mName));
|
2015-07-09 19:22:04 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
ESM::Cell* Store<ESM::Cell>::insert(const ESM::Cell& cell)
|
|
|
|
{
|
2020-11-13 11:39:47 +04:00
|
|
|
if (search(cell) != nullptr)
|
2019-01-07 17:47:39 +04:00
|
|
|
{
|
|
|
|
const std::string cellType = (cell.isExterior()) ? "exterior" : "interior";
|
|
|
|
throw std::runtime_error("Failed to create " + cellType + " cell");
|
2015-07-09 19:22:04 +02:00
|
|
|
}
|
2023-03-01 17:27:35 +01:00
|
|
|
ESM::Cell* insertedCell = &mCells.emplace(cell.mId, cell).first->second;
|
2015-07-09 19:22:04 +02:00
|
|
|
if (cell.isExterior())
|
|
|
|
{
|
|
|
|
std::pair<int, int> key(cell.getGridX(), cell.getGridY());
|
|
|
|
|
|
|
|
// duplicate insertions are avoided by search(ESM::Cell &)
|
2023-02-18 22:32:27 +01:00
|
|
|
DynamicExt::iterator result = mDynamicExt.emplace(key, insertedCell).first;
|
|
|
|
mSharedExt.push_back(result->second);
|
|
|
|
return result->second;
|
2015-07-09 19:22:04 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// duplicate insertions are avoided by search(ESM::Cell &)
|
2023-02-18 22:32:27 +01:00
|
|
|
DynamicInt::iterator result = mDynamicInt.emplace(cell.mName, insertedCell).first;
|
|
|
|
mSharedInt.push_back(result->second);
|
|
|
|
return result->second;
|
2015-07-09 19:22:04 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Pathgrid
|
|
|
|
//=========================================================================
|
|
|
|
|
|
|
|
Store<ESM::Pathgrid>::Store()
|
2018-10-09 10:21:12 +04:00
|
|
|
: mCells(nullptr)
|
2015-07-09 19:22:04 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void Store<ESM::Pathgrid>::setCells(Store<ESM::Cell>& cells)
|
|
|
|
{
|
|
|
|
mCells = &cells;
|
|
|
|
}
|
2015-07-12 15:20:22 +03:00
|
|
|
RecordId Store<ESM::Pathgrid>::load(ESM::ESMReader& esm)
|
2015-07-09 19:22:04 +02:00
|
|
|
{
|
|
|
|
ESM::Pathgrid pathgrid;
|
2015-07-21 13:17:03 +03:00
|
|
|
bool isDeleted = false;
|
|
|
|
|
|
|
|
pathgrid.load(esm, isDeleted);
|
2015-07-09 19:22:04 +02:00
|
|
|
|
|
|
|
// Unfortunately the Pathgrid record model does not specify whether the pathgrid belongs to an interior or
|
|
|
|
// exterior cell. For interior cells, mCell is the cell name, but for exterior cells it is either the cell name
|
|
|
|
// or if that doesn't exist, the cell's region name. mX and mY will be (0,0) for interior cells, but there is
|
|
|
|
// also an exterior cell with the coordinates of (0,0), so that doesn't help. Check whether mCell is an interior
|
|
|
|
// cell. This isn't perfect, will break if a Region with the same name as an interior cell is created. A proper
|
|
|
|
// fix should be made for future versions of the file format.
|
2023-01-19 17:31:45 +01:00
|
|
|
bool interior = pathgrid.mData.mX == 0 && pathgrid.mData.mY == 0
|
|
|
|
&& mCells->search(pathgrid.mCell.getRefIdString()) != nullptr;
|
2015-07-09 19:22:04 +02:00
|
|
|
|
2023-04-18 20:18:11 +02:00
|
|
|
ESM::RefId cell
|
|
|
|
= interior ? pathgrid.mCell : ESM::RefId::esm3ExteriorCell(pathgrid.mData.mX, pathgrid.mData.mY);
|
2021-08-19 12:45:09 +10:00
|
|
|
// deal with mods that have empty pathgrid records (Issue #6209)
|
2021-08-10 19:39:46 +10:00
|
|
|
// we assume that these records are empty on purpose (i.e. to remove old pathgrid on an updated cell)
|
2021-08-21 07:20:10 +10:00
|
|
|
if (isDeleted || pathgrid.mPoints.empty() || pathgrid.mEdges.empty())
|
2021-08-10 19:39:46 +10:00
|
|
|
{
|
2023-04-19 02:31:40 +02:00
|
|
|
mStatic.erase(cell);
|
2021-08-10 19:39:46 +10:00
|
|
|
|
2023-02-17 19:20:29 +01:00
|
|
|
return RecordId(ESM::RefId(), isDeleted);
|
2021-08-10 19:39:46 +10:00
|
|
|
}
|
|
|
|
|
2015-07-09 19:22:04 +02:00
|
|
|
// Try to overwrite existing record
|
2023-04-18 20:18:11 +02:00
|
|
|
auto ret = mStatic.emplace(cell, pathgrid);
|
|
|
|
if (!ret.second)
|
|
|
|
ret.first->second = pathgrid;
|
2015-07-12 15:20:22 +03:00
|
|
|
|
2023-02-17 19:20:29 +01:00
|
|
|
return RecordId(ESM::RefId(), isDeleted);
|
2015-07-09 19:22:04 +02:00
|
|
|
}
|
|
|
|
size_t Store<ESM::Pathgrid>::getSize() const
|
|
|
|
{
|
2023-04-18 20:18:11 +02:00
|
|
|
return mStatic.size();
|
2015-07-09 19:22:04 +02:00
|
|
|
}
|
|
|
|
void Store<ESM::Pathgrid>::setUp() {}
|
Initial commit: In ESM structures, replace the string members that are RefIds to other records, to a new strong type
The strong type is actually just a string underneath, but this will help in the future to have a distinction so it's easier to search and replace when we use an integer ID
Slowly going through all the changes to make, still hundreds of errors
a lot of functions/structures use std::string or stringview to designate an ID. So it takes time
Continues slowly replacing ids. There are technically more and more compilation errors
I have good hope that there is a point where the amount of errors will dramatically go down as all the main functions use the ESM::RefId type
Continue moving forward, changes to the stores
slowly moving along
Starting to see the fruit of those changes.
still many many error, but more and more Irun into a situation where a function is sandwiched between two functions that use the RefId type.
More replacements. Things are starting to get easier
I can see more and more often the issue is that the function is awaiting a RefId, but is given a string
there is less need to go down functions and to fix a long list of them.
Still moving forward, and for the first time error count is going down!
Good pace, not sure about topics though, mId and mName are actually the same thing and are used interchangeably
Cells are back to using string for the name, haven't fixed everything yet. Many other changes
Under the bar of 400 compilation errors.
more good progress <100 compile errors!
More progress
Game settings store can use string for find, it was a bit absurd how every use of it required to create refId from string
some more progress on other fronts
Mostly game settings clean
one error opened a lot of other errors. Down to 18, but more will prbably appear
only link errors left??
Fixed link errors
OpenMW compiles, and launches, with some issues, but still!
2022-09-25 13:17:09 +02:00
|
|
|
const ESM::Pathgrid* Store<ESM::Pathgrid>::search(const ESM::RefId& name) const
|
2015-07-09 19:22:04 +02:00
|
|
|
{
|
2023-04-18 20:18:11 +02:00
|
|
|
auto it = mStatic.find(name);
|
|
|
|
if (it != mStatic.end())
|
2015-07-09 19:22:04 +02:00
|
|
|
return &(it->second);
|
2018-10-09 10:21:12 +04:00
|
|
|
return nullptr;
|
2015-07-09 19:22:04 +02:00
|
|
|
}
|
Initial commit: In ESM structures, replace the string members that are RefIds to other records, to a new strong type
The strong type is actually just a string underneath, but this will help in the future to have a distinction so it's easier to search and replace when we use an integer ID
Slowly going through all the changes to make, still hundreds of errors
a lot of functions/structures use std::string or stringview to designate an ID. So it takes time
Continues slowly replacing ids. There are technically more and more compilation errors
I have good hope that there is a point where the amount of errors will dramatically go down as all the main functions use the ESM::RefId type
Continue moving forward, changes to the stores
slowly moving along
Starting to see the fruit of those changes.
still many many error, but more and more Irun into a situation where a function is sandwiched between two functions that use the RefId type.
More replacements. Things are starting to get easier
I can see more and more often the issue is that the function is awaiting a RefId, but is given a string
there is less need to go down functions and to fix a long list of them.
Still moving forward, and for the first time error count is going down!
Good pace, not sure about topics though, mId and mName are actually the same thing and are used interchangeably
Cells are back to using string for the name, haven't fixed everything yet. Many other changes
Under the bar of 400 compilation errors.
more good progress <100 compile errors!
More progress
Game settings store can use string for find, it was a bit absurd how every use of it required to create refId from string
some more progress on other fronts
Mostly game settings clean
one error opened a lot of other errors. Down to 18, but more will prbably appear
only link errors left??
Fixed link errors
OpenMW compiles, and launches, with some issues, but still!
2022-09-25 13:17:09 +02:00
|
|
|
const ESM::Pathgrid* Store<ESM::Pathgrid>::find(const ESM::RefId& name) const
|
2015-07-09 19:22:04 +02:00
|
|
|
{
|
|
|
|
const ESM::Pathgrid* pathgrid = search(name);
|
2023-02-20 23:11:18 +01:00
|
|
|
if (pathgrid == nullptr)
|
|
|
|
throw std::runtime_error("Pathgrid in cell " + name.toDebugString() + " is not found");
|
2015-07-09 19:22:04 +02:00
|
|
|
return pathgrid;
|
|
|
|
}
|
|
|
|
const ESM::Pathgrid* Store<ESM::Pathgrid>::search(const ESM::Cell& cell) const
|
|
|
|
{
|
2023-04-18 20:18:11 +02:00
|
|
|
return search(cell.mId);
|
2015-07-09 19:22:04 +02:00
|
|
|
}
|
2023-02-04 18:45:53 +01:00
|
|
|
const ESM::Pathgrid* Store<ESM::Pathgrid>::search(const MWWorld::Cell& cellVariant) const
|
|
|
|
{
|
|
|
|
return ESM::visit(ESM::VisitOverload{
|
|
|
|
[&](const ESM::Cell& cell) { return search(cell); },
|
|
|
|
[&](const ESM4::Cell& cell) -> const ESM::Pathgrid* { return nullptr; },
|
|
|
|
},
|
|
|
|
cellVariant);
|
|
|
|
}
|
2015-07-09 19:22:04 +02:00
|
|
|
const ESM::Pathgrid* Store<ESM::Pathgrid>::find(const ESM::Cell& cell) const
|
|
|
|
{
|
2023-04-18 20:18:11 +02:00
|
|
|
return find(cell.mId);
|
2015-07-09 19:22:04 +02:00
|
|
|
}
|
2014-06-11 15:37:05 +02:00
|
|
|
|
2015-07-09 19:22:04 +02:00
|
|
|
// Skill
|
|
|
|
//=========================================================================
|
2021-06-30 15:34:40 +10:00
|
|
|
|
2015-07-09 19:22:04 +02:00
|
|
|
Store<ESM::Skill>::Store() {}
|
|
|
|
|
2023-05-31 17:02:18 +02:00
|
|
|
void Store<ESM::Skill>::setUp(const MWWorld::Store<ESM::GameSetting>& settings)
|
2023-05-29 17:56:14 +02:00
|
|
|
{
|
2023-05-31 17:45:20 +02:00
|
|
|
constexpr std::string_view skillValues[ESM::Skill::Length][3] = {
|
|
|
|
{ "sSkillBlock", "icons\\k\\combat_block.dds", "fWerewolfBlock" },
|
|
|
|
{ "sSkillArmorer", "icons\\k\\combat_armor.dds", "fWerewolfArmorer" },
|
|
|
|
{ "sSkillMediumarmor", "icons\\k\\combat_mediumarmor.dds", "fWerewolfMediumarmor" },
|
|
|
|
{ "sSkillHeavyarmor", "icons\\k\\combat_heavyarmor.dds", "fWerewolfHeavyarmor" },
|
|
|
|
{ "sSkillBluntweapon", "icons\\k\\combat_blunt.dds", "fWerewolfBluntweapon" },
|
|
|
|
{ "sSkillLongblade", "icons\\k\\combat_longblade.dds", "fWerewolfLongblade" },
|
|
|
|
{ "sSkillAxe", "icons\\k\\combat_axe.dds", "fWerewolfAxe" },
|
|
|
|
{ "sSkillSpear", "icons\\k\\combat_spear.dds", "fWerewolfSpear" },
|
|
|
|
{ "sSkillAthletics", "icons\\k\\combat_athletics.dds", "fWerewolfAthletics" },
|
|
|
|
{ "sSkillEnchant", "icons\\k\\magic_enchant.dds", "fWerewolfEnchant" },
|
|
|
|
{ "sSkillDestruction", "icons\\k\\magic_destruction.dds", "fWerewolfDestruction" },
|
|
|
|
{ "sSkillAlteration", "icons\\k\\magic_alteration.dds", "fWerewolfAlteration" },
|
|
|
|
{ "sSkillIllusion", "icons\\k\\magic_illusion.dds", "fWerewolfIllusion" },
|
|
|
|
{ "sSkillConjuration", "icons\\k\\magic_conjuration.dds", "fWerewolfConjuration" },
|
|
|
|
{ "sSkillMysticism", "icons\\k\\magic_mysticism.dds", "fWerewolfMysticism" },
|
|
|
|
{ "sSkillRestoration", "icons\\k\\magic_restoration.dds", "fWerewolfRestoration" },
|
|
|
|
{ "sSkillAlchemy", "icons\\k\\magic_alchemy.dds", "fWerewolfAlchemy" },
|
|
|
|
{ "sSkillUnarmored", "icons\\k\\magic_unarmored.dds", "fWerewolfUnarmored" },
|
|
|
|
{ "sSkillSecurity", "icons\\k\\stealth_security.dds", "fWerewolfSecurity" },
|
|
|
|
{ "sSkillSneak", "icons\\k\\stealth_sneak.dds", "fWerewolfSneak" },
|
|
|
|
{ "sSkillAcrobatics", "icons\\k\\stealth_acrobatics.dds", "fWerewolfAcrobatics" },
|
|
|
|
{ "sSkillLightarmor", "icons\\k\\stealth_lightarmor.dds", "fWerewolfLightarmor" },
|
|
|
|
{ "sSkillShortblade", "icons\\k\\stealth_shortblade.dds", "fWerewolfShortblade" },
|
|
|
|
{ "sSkillMarksman", "icons\\k\\stealth_marksman.dds", "fWerewolfMarksman" },
|
|
|
|
// "Mercantile"! >_<
|
|
|
|
{ "sSkillMercantile", "icons\\k\\stealth_mercantile.dds", "fWerewolfMerchantile" },
|
|
|
|
{ "sSkillSpeechcraft", "icons\\k\\stealth_speechcraft.dds", "fWerewolfSpeechcraft" },
|
|
|
|
{ "sSkillHandtohand", "icons\\k\\stealth_handtohand.dds", "fWerewolfHandtohand" },
|
2023-05-29 17:56:14 +02:00
|
|
|
};
|
|
|
|
for (int i = 0; i < ESM::Skill::Length; ++i)
|
|
|
|
{
|
|
|
|
auto found = mStatic.find(i);
|
|
|
|
if (found != mStatic.end())
|
|
|
|
{
|
|
|
|
ESM::Skill& skill = found->second;
|
2023-05-31 17:45:20 +02:00
|
|
|
skill.mName = getGMSTString(settings, skillValues[i][0]);
|
|
|
|
skill.mIcon = skillValues[i][1];
|
|
|
|
skill.mWerewolfValue = getGMSTFloat(settings, skillValues[i][2]);
|
2023-05-29 17:56:14 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-01 22:09:30 +01:00
|
|
|
// Game Settings
|
2015-07-09 19:22:04 +02:00
|
|
|
//=========================================================================
|
|
|
|
|
Initial commit: In ESM structures, replace the string members that are RefIds to other records, to a new strong type
The strong type is actually just a string underneath, but this will help in the future to have a distinction so it's easier to search and replace when we use an integer ID
Slowly going through all the changes to make, still hundreds of errors
a lot of functions/structures use std::string or stringview to designate an ID. So it takes time
Continues slowly replacing ids. There are technically more and more compilation errors
I have good hope that there is a point where the amount of errors will dramatically go down as all the main functions use the ESM::RefId type
Continue moving forward, changes to the stores
slowly moving along
Starting to see the fruit of those changes.
still many many error, but more and more Irun into a situation where a function is sandwiched between two functions that use the RefId type.
More replacements. Things are starting to get easier
I can see more and more often the issue is that the function is awaiting a RefId, but is given a string
there is less need to go down functions and to fix a long list of them.
Still moving forward, and for the first time error count is going down!
Good pace, not sure about topics though, mId and mName are actually the same thing and are used interchangeably
Cells are back to using string for the name, haven't fixed everything yet. Many other changes
Under the bar of 400 compilation errors.
more good progress <100 compile errors!
More progress
Game settings store can use string for find, it was a bit absurd how every use of it required to create refId from string
some more progress on other fronts
Mostly game settings clean
one error opened a lot of other errors. Down to 18, but more will prbably appear
only link errors left??
Fixed link errors
OpenMW compiles, and launches, with some issues, but still!
2022-09-25 13:17:09 +02:00
|
|
|
const ESM::GameSetting* Store<ESM::GameSetting>::search(const ESM::RefId& id) const
|
|
|
|
{
|
|
|
|
return TypedDynamicStore::search(id);
|
|
|
|
}
|
|
|
|
|
|
|
|
const ESM::GameSetting* Store<ESM::GameSetting>::find(std::string_view id) const
|
|
|
|
{
|
|
|
|
return TypedDynamicStore::find(ESM::RefId::stringRefId(id));
|
|
|
|
}
|
|
|
|
|
|
|
|
const ESM::GameSetting* Store<ESM::GameSetting>::search(std::string_view id) const
|
|
|
|
{
|
2022-10-18 09:26:55 +02:00
|
|
|
return TypedDynamicStore::search(ESM::RefId::stringRefId(id));
|
Initial commit: In ESM structures, replace the string members that are RefIds to other records, to a new strong type
The strong type is actually just a string underneath, but this will help in the future to have a distinction so it's easier to search and replace when we use an integer ID
Slowly going through all the changes to make, still hundreds of errors
a lot of functions/structures use std::string or stringview to designate an ID. So it takes time
Continues slowly replacing ids. There are technically more and more compilation errors
I have good hope that there is a point where the amount of errors will dramatically go down as all the main functions use the ESM::RefId type
Continue moving forward, changes to the stores
slowly moving along
Starting to see the fruit of those changes.
still many many error, but more and more Irun into a situation where a function is sandwiched between two functions that use the RefId type.
More replacements. Things are starting to get easier
I can see more and more often the issue is that the function is awaiting a RefId, but is given a string
there is less need to go down functions and to fix a long list of them.
Still moving forward, and for the first time error count is going down!
Good pace, not sure about topics though, mId and mName are actually the same thing and are used interchangeably
Cells are back to using string for the name, haven't fixed everything yet. Many other changes
Under the bar of 400 compilation errors.
more good progress <100 compile errors!
More progress
Game settings store can use string for find, it was a bit absurd how every use of it required to create refId from string
some more progress on other fronts
Mostly game settings clean
one error opened a lot of other errors. Down to 18, but more will prbably appear
only link errors left??
Fixed link errors
OpenMW compiles, and launches, with some issues, but still!
2022-09-25 13:17:09 +02:00
|
|
|
}
|
|
|
|
|
2022-12-01 22:09:30 +01:00
|
|
|
// Magic effect
|
|
|
|
//=========================================================================
|
2015-07-09 19:22:04 +02:00
|
|
|
Store<ESM::MagicEffect>::Store() {}
|
2014-06-11 21:56:10 +02:00
|
|
|
|
2015-07-09 19:22:04 +02:00
|
|
|
// Attribute
|
|
|
|
//=========================================================================
|
|
|
|
|
|
|
|
Store<ESM::Attribute>::Store()
|
|
|
|
{
|
|
|
|
mStatic.reserve(ESM::Attribute::Length);
|
|
|
|
}
|
|
|
|
const ESM::Attribute* Store<ESM::Attribute>::search(size_t index) const
|
|
|
|
{
|
|
|
|
if (index >= mStatic.size())
|
|
|
|
{
|
2020-11-13 11:39:47 +04:00
|
|
|
return nullptr;
|
2014-06-11 15:37:05 +02:00
|
|
|
}
|
2021-05-15 15:38:17 +02:00
|
|
|
return &mStatic[index];
|
2013-02-09 13:00:57 +01:00
|
|
|
}
|
|
|
|
|
2015-07-09 19:22:04 +02:00
|
|
|
const ESM::Attribute* Store<ESM::Attribute>::find(size_t index) const
|
|
|
|
{
|
|
|
|
const ESM::Attribute* ptr = search(index);
|
2020-11-13 11:39:47 +04:00
|
|
|
if (ptr == nullptr)
|
2019-01-07 17:47:39 +04:00
|
|
|
{
|
|
|
|
const std::string msg = "Attribute with index " + std::to_string(index) + " not found";
|
|
|
|
throw std::runtime_error(msg);
|
2015-07-09 19:22:04 +02:00
|
|
|
}
|
|
|
|
return ptr;
|
|
|
|
}
|
2023-05-31 17:02:18 +02:00
|
|
|
void Store<ESM::Attribute>::setUp(const MWWorld::Store<ESM::GameSetting>& settings)
|
2015-07-09 19:22:04 +02:00
|
|
|
{
|
2023-05-31 17:45:20 +02:00
|
|
|
// TODO remove after !3084 gets merged
|
|
|
|
mStatic.clear();
|
2023-05-28 15:10:53 +02:00
|
|
|
mStatic.push_back({ .mId = ESM::Attribute::Strength,
|
2023-05-31 17:02:18 +02:00
|
|
|
.mName = std::string{ getGMSTString(settings, "sAttributeStrength") },
|
|
|
|
.mDescription = std::string{ getGMSTString(settings, "sStrDesc") },
|
2023-05-28 15:28:34 +02:00
|
|
|
.mIcon = "icons\\k\\attribute_strength.dds",
|
2023-05-31 17:02:18 +02:00
|
|
|
.mWerewolfValue = getGMSTFloat(settings, "fWerewolfStrength") });
|
2023-05-28 15:10:53 +02:00
|
|
|
mStatic.push_back({ .mId = ESM::Attribute::Intelligence,
|
2023-05-31 17:02:18 +02:00
|
|
|
.mName = std::string{ getGMSTString(settings, "sAttributeIntelligence") },
|
|
|
|
.mDescription = std::string{ getGMSTString(settings, "sIntDesc") },
|
2023-05-28 15:28:34 +02:00
|
|
|
.mIcon = "icons\\k\\attribute_int.dds",
|
|
|
|
// Oh, Bethesda. It's "Intelligence".
|
2023-05-31 17:02:18 +02:00
|
|
|
.mWerewolfValue = getGMSTFloat(settings, "fWerewolfIntellegence") });
|
2023-05-28 15:10:53 +02:00
|
|
|
mStatic.push_back({ .mId = ESM::Attribute::Willpower,
|
2023-05-31 17:02:18 +02:00
|
|
|
.mName = std::string{ getGMSTString(settings, "sAttributeWillpower") },
|
|
|
|
.mDescription = std::string{ getGMSTString(settings, "sWilDesc") },
|
2023-05-28 15:28:34 +02:00
|
|
|
.mIcon = "icons\\k\\attribute_wilpower.dds",
|
2023-05-31 17:02:18 +02:00
|
|
|
.mWerewolfValue = getGMSTFloat(settings, "fWerewolfWillpower") });
|
2023-05-28 15:10:53 +02:00
|
|
|
mStatic.push_back({ .mId = ESM::Attribute::Agility,
|
2023-05-31 17:02:18 +02:00
|
|
|
.mName = std::string{ getGMSTString(settings, "sAttributeAgility") },
|
|
|
|
.mDescription = std::string{ getGMSTString(settings, "sAgiDesc") },
|
2023-05-28 15:28:34 +02:00
|
|
|
.mIcon = "icons\\k\\attribute_agility.dds",
|
2023-05-31 17:02:18 +02:00
|
|
|
.mWerewolfValue = getGMSTFloat(settings, "fWerewolfAgility") });
|
2023-05-28 15:10:53 +02:00
|
|
|
mStatic.push_back({ .mId = ESM::Attribute::Speed,
|
2023-05-31 17:02:18 +02:00
|
|
|
.mName = std::string{ getGMSTString(settings, "sAttributeSpeed") },
|
|
|
|
.mDescription = std::string{ getGMSTString(settings, "sSpdDesc") },
|
2023-05-28 15:28:34 +02:00
|
|
|
.mIcon = "icons\\k\\attribute_speed.dds",
|
2023-05-31 17:02:18 +02:00
|
|
|
.mWerewolfValue = getGMSTFloat(settings, "fWerewolfSpeed") });
|
2023-05-28 15:10:53 +02:00
|
|
|
mStatic.push_back({ .mId = ESM::Attribute::Endurance,
|
2023-05-31 17:02:18 +02:00
|
|
|
.mName = std::string{ getGMSTString(settings, "sAttributeEndurance") },
|
|
|
|
.mDescription = std::string{ getGMSTString(settings, "sEndDesc") },
|
2023-05-28 15:28:34 +02:00
|
|
|
.mIcon = "icons\\k\\attribute_endurance.dds",
|
2023-05-31 17:02:18 +02:00
|
|
|
.mWerewolfValue = getGMSTFloat(settings, "fWerewolfEndurance") });
|
2023-05-28 15:10:53 +02:00
|
|
|
mStatic.push_back({ .mId = ESM::Attribute::Personality,
|
2023-05-31 17:02:18 +02:00
|
|
|
.mName = std::string{ getGMSTString(settings, "sAttributePersonality") },
|
|
|
|
.mDescription = std::string{ getGMSTString(settings, "sPerDesc") },
|
2023-05-28 15:28:34 +02:00
|
|
|
.mIcon = "icons\\k\\attribute_personality.dds",
|
2023-05-31 17:02:18 +02:00
|
|
|
.mWerewolfValue = getGMSTFloat(settings, "fWerewolfPersonality") });
|
2023-05-28 15:10:53 +02:00
|
|
|
mStatic.push_back({ .mId = ESM::Attribute::Luck,
|
2023-05-31 17:02:18 +02:00
|
|
|
.mName = std::string{ getGMSTString(settings, "sAttributeLuck") },
|
|
|
|
.mDescription = std::string{ getGMSTString(settings, "sLucDesc") },
|
2023-05-28 15:28:34 +02:00
|
|
|
.mIcon = "icons\\k\\attribute_luck.dds",
|
2023-05-31 17:02:18 +02:00
|
|
|
.mWerewolfValue = getGMSTFloat(settings, "fWerewolfLuck") });
|
2015-07-09 19:22:04 +02:00
|
|
|
}
|
|
|
|
size_t Store<ESM::Attribute>::getSize() const
|
|
|
|
{
|
|
|
|
return mStatic.size();
|
|
|
|
}
|
|
|
|
Store<ESM::Attribute>::iterator Store<ESM::Attribute>::begin() const
|
|
|
|
{
|
|
|
|
return mStatic.begin();
|
|
|
|
}
|
|
|
|
Store<ESM::Attribute>::iterator Store<ESM::Attribute>::end() const
|
|
|
|
{
|
|
|
|
return mStatic.end();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Dialogue
|
|
|
|
//=========================================================================
|
|
|
|
|
2021-12-24 00:54:00 +03:00
|
|
|
Store<ESM::Dialogue>::Store()
|
|
|
|
: mKeywordSearchModFlag(true)
|
|
|
|
{
|
|
|
|
}
|
2015-07-09 19:22:04 +02:00
|
|
|
|
2015-09-24 15:21:42 +02:00
|
|
|
void Store<ESM::Dialogue>::setUp()
|
2015-07-09 19:22:04 +02:00
|
|
|
{
|
|
|
|
// DialInfos marked as deleted are kept during the loading phase, so that the linked list
|
|
|
|
// structure is kept intact for inserting further INFOs. Delete them now that loading is done.
|
2021-05-16 09:40:41 +02:00
|
|
|
for (auto& [_, dial] : mStatic)
|
2023-03-12 15:11:10 +01:00
|
|
|
dial.setUp();
|
2015-07-09 19:22:04 +02:00
|
|
|
|
|
|
|
mShared.clear();
|
|
|
|
mShared.reserve(mStatic.size());
|
2021-05-16 09:40:41 +02:00
|
|
|
for (auto& [_, dial] : mStatic)
|
|
|
|
mShared.push_back(&dial);
|
2021-11-02 20:13:41 +00:00
|
|
|
// TODO: verify and document this inconsistent behaviour
|
|
|
|
// TODO: if we require this behaviour, maybe we should move it to the place that requires it
|
|
|
|
std::sort(mShared.begin(), mShared.end(),
|
|
|
|
[](const ESM::Dialogue* l, const ESM::Dialogue* r) -> bool { return l->mId < r->mId; });
|
2021-12-19 14:00:49 +03:00
|
|
|
|
2021-12-24 00:54:00 +03:00
|
|
|
mKeywordSearchModFlag = true;
|
|
|
|
}
|
|
|
|
|
Initial commit: In ESM structures, replace the string members that are RefIds to other records, to a new strong type
The strong type is actually just a string underneath, but this will help in the future to have a distinction so it's easier to search and replace when we use an integer ID
Slowly going through all the changes to make, still hundreds of errors
a lot of functions/structures use std::string or stringview to designate an ID. So it takes time
Continues slowly replacing ids. There are technically more and more compilation errors
I have good hope that there is a point where the amount of errors will dramatically go down as all the main functions use the ESM::RefId type
Continue moving forward, changes to the stores
slowly moving along
Starting to see the fruit of those changes.
still many many error, but more and more Irun into a situation where a function is sandwiched between two functions that use the RefId type.
More replacements. Things are starting to get easier
I can see more and more often the issue is that the function is awaiting a RefId, but is given a string
there is less need to go down functions and to fix a long list of them.
Still moving forward, and for the first time error count is going down!
Good pace, not sure about topics though, mId and mName are actually the same thing and are used interchangeably
Cells are back to using string for the name, haven't fixed everything yet. Many other changes
Under the bar of 400 compilation errors.
more good progress <100 compile errors!
More progress
Game settings store can use string for find, it was a bit absurd how every use of it required to create refId from string
some more progress on other fronts
Mostly game settings clean
one error opened a lot of other errors. Down to 18, but more will prbably appear
only link errors left??
Fixed link errors
OpenMW compiles, and launches, with some issues, but still!
2022-09-25 13:17:09 +02:00
|
|
|
const ESM::Dialogue* Store<ESM::Dialogue>::search(const ESM::RefId& id) const
|
2021-12-24 00:54:00 +03:00
|
|
|
{
|
|
|
|
typename Static::const_iterator it = mStatic.find(id);
|
|
|
|
if (it != mStatic.end())
|
|
|
|
return &(it->second);
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
Initial commit: In ESM structures, replace the string members that are RefIds to other records, to a new strong type
The strong type is actually just a string underneath, but this will help in the future to have a distinction so it's easier to search and replace when we use an integer ID
Slowly going through all the changes to make, still hundreds of errors
a lot of functions/structures use std::string or stringview to designate an ID. So it takes time
Continues slowly replacing ids. There are technically more and more compilation errors
I have good hope that there is a point where the amount of errors will dramatically go down as all the main functions use the ESM::RefId type
Continue moving forward, changes to the stores
slowly moving along
Starting to see the fruit of those changes.
still many many error, but more and more Irun into a situation where a function is sandwiched between two functions that use the RefId type.
More replacements. Things are starting to get easier
I can see more and more often the issue is that the function is awaiting a RefId, but is given a string
there is less need to go down functions and to fix a long list of them.
Still moving forward, and for the first time error count is going down!
Good pace, not sure about topics though, mId and mName are actually the same thing and are used interchangeably
Cells are back to using string for the name, haven't fixed everything yet. Many other changes
Under the bar of 400 compilation errors.
more good progress <100 compile errors!
More progress
Game settings store can use string for find, it was a bit absurd how every use of it required to create refId from string
some more progress on other fronts
Mostly game settings clean
one error opened a lot of other errors. Down to 18, but more will prbably appear
only link errors left??
Fixed link errors
OpenMW compiles, and launches, with some issues, but still!
2022-09-25 13:17:09 +02:00
|
|
|
const ESM::Dialogue* Store<ESM::Dialogue>::find(const ESM::RefId& id) const
|
2021-12-24 00:54:00 +03:00
|
|
|
{
|
|
|
|
const ESM::Dialogue* ptr = search(id);
|
|
|
|
if (ptr == nullptr)
|
|
|
|
{
|
|
|
|
std::stringstream msg;
|
|
|
|
msg << ESM::Dialogue::getRecordType() << " '" << id << "' not found";
|
|
|
|
throw std::runtime_error(msg.str());
|
|
|
|
}
|
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
typename Store<ESM::Dialogue>::iterator Store<ESM::Dialogue>::begin() const
|
|
|
|
{
|
|
|
|
return mShared.begin();
|
|
|
|
}
|
|
|
|
|
|
|
|
typename Store<ESM::Dialogue>::iterator Store<ESM::Dialogue>::end() const
|
|
|
|
{
|
|
|
|
return mShared.end();
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t Store<ESM::Dialogue>::getSize() const
|
|
|
|
{
|
|
|
|
return mShared.size();
|
2015-07-09 19:22:04 +02:00
|
|
|
}
|
|
|
|
|
2015-07-12 15:20:22 +03:00
|
|
|
inline RecordId Store<ESM::Dialogue>::load(ESM::ESMReader& esm)
|
|
|
|
{
|
2015-07-12 12:01:18 +03:00
|
|
|
// The original letter case of a dialogue ID is saved, because it's printed
|
|
|
|
ESM::Dialogue dialogue;
|
2015-07-21 13:17:03 +03:00
|
|
|
bool isDeleted = false;
|
2015-01-25 01:53:20 +01:00
|
|
|
|
2015-07-13 10:53:31 +03:00
|
|
|
dialogue.loadId(esm);
|
2015-07-09 19:22:04 +02:00
|
|
|
|
2021-10-30 17:27:57 +00:00
|
|
|
Static::iterator found = mStatic.find(dialogue.mId);
|
2015-07-12 12:01:18 +03:00
|
|
|
if (found == mStatic.end())
|
|
|
|
{
|
2015-07-21 13:17:03 +03:00
|
|
|
dialogue.loadData(esm, isDeleted);
|
2021-10-30 17:27:57 +00:00
|
|
|
mStatic.emplace(dialogue.mId, dialogue);
|
2015-07-09 19:22:04 +02:00
|
|
|
}
|
|
|
|
else
|
2015-07-12 12:01:18 +03:00
|
|
|
{
|
2015-07-21 13:17:03 +03:00
|
|
|
found->second.loadData(esm, isDeleted);
|
2021-05-13 23:02:26 +02:00
|
|
|
dialogue.mId = found->second.mId;
|
2014-06-11 15:37:05 +02:00
|
|
|
}
|
2022-09-22 21:26:05 +03:00
|
|
|
|
2021-12-24 00:54:00 +03:00
|
|
|
mKeywordSearchModFlag = true;
|
2015-07-09 19:22:04 +02:00
|
|
|
|
2015-07-21 13:17:03 +03:00
|
|
|
return RecordId(dialogue.mId, isDeleted);
|
2015-07-09 19:22:04 +02:00
|
|
|
}
|
2015-11-13 01:34:36 +01:00
|
|
|
|
Initial commit: In ESM structures, replace the string members that are RefIds to other records, to a new strong type
The strong type is actually just a string underneath, but this will help in the future to have a distinction so it's easier to search and replace when we use an integer ID
Slowly going through all the changes to make, still hundreds of errors
a lot of functions/structures use std::string or stringview to designate an ID. So it takes time
Continues slowly replacing ids. There are technically more and more compilation errors
I have good hope that there is a point where the amount of errors will dramatically go down as all the main functions use the ESM::RefId type
Continue moving forward, changes to the stores
slowly moving along
Starting to see the fruit of those changes.
still many many error, but more and more Irun into a situation where a function is sandwiched between two functions that use the RefId type.
More replacements. Things are starting to get easier
I can see more and more often the issue is that the function is awaiting a RefId, but is given a string
there is less need to go down functions and to fix a long list of them.
Still moving forward, and for the first time error count is going down!
Good pace, not sure about topics though, mId and mName are actually the same thing and are used interchangeably
Cells are back to using string for the name, haven't fixed everything yet. Many other changes
Under the bar of 400 compilation errors.
more good progress <100 compile errors!
More progress
Game settings store can use string for find, it was a bit absurd how every use of it required to create refId from string
some more progress on other fronts
Mostly game settings clean
one error opened a lot of other errors. Down to 18, but more will prbably appear
only link errors left??
Fixed link errors
OpenMW compiles, and launches, with some issues, but still!
2022-09-25 13:17:09 +02:00
|
|
|
bool Store<ESM::Dialogue>::eraseStatic(const ESM::RefId& id)
|
2019-09-21 16:24:05 +02:00
|
|
|
{
|
2022-06-13 18:21:29 +02:00
|
|
|
if (eraseFromMap(mStatic, id))
|
2021-12-24 00:54:00 +03:00
|
|
|
mKeywordSearchModFlag = true;
|
2021-12-19 14:00:49 +03:00
|
|
|
|
2019-09-21 16:24:05 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
Initial commit: In ESM structures, replace the string members that are RefIds to other records, to a new strong type
The strong type is actually just a string underneath, but this will help in the future to have a distinction so it's easier to search and replace when we use an integer ID
Slowly going through all the changes to make, still hundreds of errors
a lot of functions/structures use std::string or stringview to designate an ID. So it takes time
Continues slowly replacing ids. There are technically more and more compilation errors
I have good hope that there is a point where the amount of errors will dramatically go down as all the main functions use the ESM::RefId type
Continue moving forward, changes to the stores
slowly moving along
Starting to see the fruit of those changes.
still many many error, but more and more Irun into a situation where a function is sandwiched between two functions that use the RefId type.
More replacements. Things are starting to get easier
I can see more and more often the issue is that the function is awaiting a RefId, but is given a string
there is less need to go down functions and to fix a long list of them.
Still moving forward, and for the first time error count is going down!
Good pace, not sure about topics though, mId and mName are actually the same thing and are used interchangeably
Cells are back to using string for the name, haven't fixed everything yet. Many other changes
Under the bar of 400 compilation errors.
more good progress <100 compile errors!
More progress
Game settings store can use string for find, it was a bit absurd how every use of it required to create refId from string
some more progress on other fronts
Mostly game settings clean
one error opened a lot of other errors. Down to 18, but more will prbably appear
only link errors left??
Fixed link errors
OpenMW compiles, and launches, with some issues, but still!
2022-09-25 13:17:09 +02:00
|
|
|
void Store<ESM::Dialogue>::listIdentifier(std::vector<ESM::RefId>& list) const
|
2022-03-19 12:02:26 +01:00
|
|
|
{
|
|
|
|
list.reserve(list.size() + getSize());
|
|
|
|
for (const auto& dialogue : mShared)
|
|
|
|
list.push_back(dialogue->mId);
|
|
|
|
}
|
|
|
|
|
2023-05-04 19:46:49 +02:00
|
|
|
const MWDialogue::KeywordSearch<int>& Store<ESM::Dialogue>::getDialogIdKeywordSearch() const
|
2021-12-24 00:54:00 +03:00
|
|
|
{
|
|
|
|
if (mKeywordSearchModFlag)
|
|
|
|
{
|
|
|
|
mKeywordSearch.clear();
|
|
|
|
|
|
|
|
std::vector<std::string> keywordList;
|
|
|
|
keywordList.reserve(getSize());
|
|
|
|
for (const auto& it : *this)
|
2023-05-04 19:46:49 +02:00
|
|
|
keywordList.push_back(Misc::StringUtils::lowerCase(it.mStringId));
|
2021-12-24 00:54:00 +03:00
|
|
|
sort(keywordList.begin(), keywordList.end());
|
|
|
|
|
|
|
|
for (const auto& it : keywordList)
|
|
|
|
mKeywordSearch.seed(it, 0 /*unused*/);
|
|
|
|
|
|
|
|
mKeywordSearchModFlag = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return mKeywordSearch;
|
|
|
|
}
|
2023-01-04 14:07:47 +01:00
|
|
|
|
2023-01-22 12:18:20 +01:00
|
|
|
// ESM4 Cell
|
|
|
|
//=========================================================================
|
|
|
|
|
|
|
|
const ESM4::Cell* Store<ESM4::Cell>::searchCellName(std::string_view cellName) const
|
|
|
|
{
|
|
|
|
const auto foundCell = mCellNameIndex.find(cellName);
|
|
|
|
if (foundCell == mCellNameIndex.end())
|
|
|
|
return nullptr;
|
|
|
|
return foundCell->second;
|
|
|
|
}
|
|
|
|
|
2023-05-12 13:24:59 +02:00
|
|
|
const ESM4::Cell* Store<ESM4::Cell>::searchExterior(ESM::ExteriorCellLocation cellIndex) const
|
2023-04-22 13:59:53 +02:00
|
|
|
{
|
2023-05-05 10:31:06 +02:00
|
|
|
const auto foundCell = mExteriors.find(cellIndex);
|
2023-05-02 22:37:18 +02:00
|
|
|
if (foundCell == mExteriors.end())
|
2023-04-22 13:59:53 +02:00
|
|
|
return nullptr;
|
|
|
|
return foundCell->second;
|
|
|
|
}
|
|
|
|
|
2023-01-22 12:18:20 +01:00
|
|
|
ESM4::Cell* Store<ESM4::Cell>::insert(const ESM4::Cell& item, bool overrideOnly)
|
|
|
|
{
|
|
|
|
auto cellPtr = TypedDynamicStore<ESM4::Cell>::insert(item, overrideOnly);
|
2023-05-09 22:46:59 +02:00
|
|
|
insertCell(cellPtr);
|
2023-01-22 12:18:20 +01:00
|
|
|
return cellPtr;
|
|
|
|
}
|
|
|
|
|
|
|
|
ESM4::Cell* Store<ESM4::Cell>::insertStatic(const ESM4::Cell& item)
|
|
|
|
{
|
|
|
|
auto cellPtr = TypedDynamicStore<ESM4::Cell>::insertStatic(item);
|
2023-05-09 22:46:59 +02:00
|
|
|
insertCell(cellPtr);
|
|
|
|
return cellPtr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Store<ESM4::Cell>::insertCell(ESM4::Cell* cellPtr)
|
|
|
|
{
|
2023-05-29 22:16:56 +02:00
|
|
|
// Do not index exterior cells with Rec_Persistent flag because they are not real cells.
|
|
|
|
// References from these cells are merged into normal cells.
|
|
|
|
if (cellPtr->isExterior() && cellPtr->mFlags & ESM4::Rec_Persistent)
|
|
|
|
return;
|
|
|
|
|
2023-04-22 19:12:24 +02:00
|
|
|
if (!cellPtr->mEditorId.empty())
|
|
|
|
mCellNameIndex[cellPtr->mEditorId] = cellPtr;
|
2023-04-22 13:59:53 +02:00
|
|
|
if (cellPtr->isExterior())
|
2023-05-29 22:16:56 +02:00
|
|
|
mExteriors[ESM::ExteriorCellLocation(cellPtr->mX, cellPtr->mY, cellPtr->mParent)] = cellPtr;
|
2023-01-22 12:18:20 +01:00
|
|
|
}
|
2023-04-22 19:12:24 +02:00
|
|
|
|
|
|
|
void Store<ESM4::Cell>::clearDynamic()
|
|
|
|
{
|
|
|
|
for (auto& cellToDeleteIt : mDynamic)
|
|
|
|
{
|
|
|
|
ESM4::Cell& cellToDelete = cellToDeleteIt.second;
|
|
|
|
if (cellToDelete.isExterior())
|
|
|
|
{
|
2023-05-02 22:37:18 +02:00
|
|
|
mExteriors.erase({ cellToDelete.mX, cellToDelete.mY, cellToDelete.mParent });
|
2023-04-22 19:12:24 +02:00
|
|
|
}
|
|
|
|
if (!cellToDelete.mEditorId.empty())
|
|
|
|
mCellNameIndex.erase(cellToDelete.mEditorId);
|
|
|
|
}
|
|
|
|
MWWorld::TypedDynamicStore<ESM4::Cell>::clearDynamic();
|
|
|
|
}
|
2023-05-16 02:49:42 +02:00
|
|
|
|
2023-05-19 22:44:40 +02:00
|
|
|
// ESM4 Land
|
|
|
|
//=========================================================================
|
|
|
|
// Needed to avoid include of ESM4::Land in header
|
|
|
|
Store<ESM4::Land>::Store() {}
|
|
|
|
|
2023-05-15 23:48:22 +02:00
|
|
|
void Store<ESM4::Land>::updateLandPositions(const Store<ESM4::Cell>& cells)
|
|
|
|
{
|
2023-05-20 00:31:38 +02:00
|
|
|
for (const auto& [id, value] : mStatic)
|
2023-05-15 23:48:22 +02:00
|
|
|
{
|
2023-05-20 00:31:38 +02:00
|
|
|
const ESM4::Cell* cell = cells.find(value.mCell);
|
|
|
|
mLands[cell->getExteriorCellLocation()] = &value;
|
2023-05-15 23:48:22 +02:00
|
|
|
}
|
2023-05-20 00:31:38 +02:00
|
|
|
for (const auto& [id, value] : mDynamic)
|
2023-05-15 23:48:22 +02:00
|
|
|
{
|
2023-05-20 00:31:38 +02:00
|
|
|
const ESM4::Cell* cell = cells.find(value.mCell);
|
|
|
|
mLands[cell->getExteriorCellLocation()] = &value;
|
2023-05-15 23:48:22 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const ESM4::Land* MWWorld::Store<ESM4::Land>::search(ESM::ExteriorCellLocation cellLocation) const
|
|
|
|
{
|
|
|
|
auto foundLand = mLands.find(cellLocation);
|
|
|
|
if (foundLand == mLands.end())
|
|
|
|
return nullptr;
|
2023-05-20 00:31:38 +02:00
|
|
|
return foundLand->second;
|
2023-05-15 23:48:22 +02:00
|
|
|
}
|
2023-05-19 22:44:40 +02:00
|
|
|
|
2023-05-16 02:49:42 +02:00
|
|
|
// ESM4 Reference
|
|
|
|
//=========================================================================
|
|
|
|
|
|
|
|
void Store<ESM4::Reference>::preprocessReferences(const Store<ESM4::Cell>& cells)
|
|
|
|
{
|
|
|
|
for (auto& [_, ref] : mStatic)
|
|
|
|
{
|
|
|
|
const ESM4::Cell* cell = cells.find(ref.mParent);
|
|
|
|
if (cell->isExterior() && (cell->mFlags & ESM4::Rec_Persistent))
|
|
|
|
{
|
2023-05-27 01:18:17 +02:00
|
|
|
const ESM4::Cell* actualCell = cells.searchExterior(
|
|
|
|
positionToExteriorCellLocation(ref.mPos.pos[0], ref.mPos.pos[1], cell->mParent));
|
2023-05-16 02:49:42 +02:00
|
|
|
if (actualCell)
|
|
|
|
ref.mParent = actualCell->mId;
|
|
|
|
}
|
|
|
|
mPerCellReferences[ref.mParent].push_back(&ref);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
std::span<const ESM4::Reference* const> Store<ESM4::Reference>::getByCell(ESM::RefId cellId) const
|
|
|
|
{
|
|
|
|
auto it = mPerCellReferences.find(cellId);
|
|
|
|
if (it == mPerCellReferences.end())
|
|
|
|
return {};
|
|
|
|
return it->second;
|
|
|
|
}
|
2013-04-28 16:36:12 +02:00
|
|
|
}
|
2015-07-09 19:22:04 +02:00
|
|
|
|
Initial commit: In ESM structures, replace the string members that are RefIds to other records, to a new strong type
The strong type is actually just a string underneath, but this will help in the future to have a distinction so it's easier to search and replace when we use an integer ID
Slowly going through all the changes to make, still hundreds of errors
a lot of functions/structures use std::string or stringview to designate an ID. So it takes time
Continues slowly replacing ids. There are technically more and more compilation errors
I have good hope that there is a point where the amount of errors will dramatically go down as all the main functions use the ESM::RefId type
Continue moving forward, changes to the stores
slowly moving along
Starting to see the fruit of those changes.
still many many error, but more and more Irun into a situation where a function is sandwiched between two functions that use the RefId type.
More replacements. Things are starting to get easier
I can see more and more often the issue is that the function is awaiting a RefId, but is given a string
there is less need to go down functions and to fix a long list of them.
Still moving forward, and for the first time error count is going down!
Good pace, not sure about topics though, mId and mName are actually the same thing and are used interchangeably
Cells are back to using string for the name, haven't fixed everything yet. Many other changes
Under the bar of 400 compilation errors.
more good progress <100 compile errors!
More progress
Game settings store can use string for find, it was a bit absurd how every use of it required to create refId from string
some more progress on other fronts
Mostly game settings clean
one error opened a lot of other errors. Down to 18, but more will prbably appear
only link errors left??
Fixed link errors
OpenMW compiles, and launches, with some issues, but still!
2022-09-25 13:17:09 +02:00
|
|
|
template class MWWorld::TypedDynamicStore<ESM::Activator>;
|
|
|
|
template class MWWorld::TypedDynamicStore<ESM::Apparatus>;
|
|
|
|
template class MWWorld::TypedDynamicStore<ESM::Armor>;
|
2015-07-10 20:21:55 +02:00
|
|
|
// template class MWWorld::Store<ESM::Attribute>;
|
Initial commit: In ESM structures, replace the string members that are RefIds to other records, to a new strong type
The strong type is actually just a string underneath, but this will help in the future to have a distinction so it's easier to search and replace when we use an integer ID
Slowly going through all the changes to make, still hundreds of errors
a lot of functions/structures use std::string or stringview to designate an ID. So it takes time
Continues slowly replacing ids. There are technically more and more compilation errors
I have good hope that there is a point where the amount of errors will dramatically go down as all the main functions use the ESM::RefId type
Continue moving forward, changes to the stores
slowly moving along
Starting to see the fruit of those changes.
still many many error, but more and more Irun into a situation where a function is sandwiched between two functions that use the RefId type.
More replacements. Things are starting to get easier
I can see more and more often the issue is that the function is awaiting a RefId, but is given a string
there is less need to go down functions and to fix a long list of them.
Still moving forward, and for the first time error count is going down!
Good pace, not sure about topics though, mId and mName are actually the same thing and are used interchangeably
Cells are back to using string for the name, haven't fixed everything yet. Many other changes
Under the bar of 400 compilation errors.
more good progress <100 compile errors!
More progress
Game settings store can use string for find, it was a bit absurd how every use of it required to create refId from string
some more progress on other fronts
Mostly game settings clean
one error opened a lot of other errors. Down to 18, but more will prbably appear
only link errors left??
Fixed link errors
OpenMW compiles, and launches, with some issues, but still!
2022-09-25 13:17:09 +02:00
|
|
|
template class MWWorld::TypedDynamicStore<ESM::BirthSign>;
|
|
|
|
template class MWWorld::TypedDynamicStore<ESM::BodyPart>;
|
|
|
|
template class MWWorld::TypedDynamicStore<ESM::Book>;
|
2015-07-10 20:21:55 +02:00
|
|
|
// template class MWWorld::Store<ESM::Cell>;
|
Initial commit: In ESM structures, replace the string members that are RefIds to other records, to a new strong type
The strong type is actually just a string underneath, but this will help in the future to have a distinction so it's easier to search and replace when we use an integer ID
Slowly going through all the changes to make, still hundreds of errors
a lot of functions/structures use std::string or stringview to designate an ID. So it takes time
Continues slowly replacing ids. There are technically more and more compilation errors
I have good hope that there is a point where the amount of errors will dramatically go down as all the main functions use the ESM::RefId type
Continue moving forward, changes to the stores
slowly moving along
Starting to see the fruit of those changes.
still many many error, but more and more Irun into a situation where a function is sandwiched between two functions that use the RefId type.
More replacements. Things are starting to get easier
I can see more and more often the issue is that the function is awaiting a RefId, but is given a string
there is less need to go down functions and to fix a long list of them.
Still moving forward, and for the first time error count is going down!
Good pace, not sure about topics though, mId and mName are actually the same thing and are used interchangeably
Cells are back to using string for the name, haven't fixed everything yet. Many other changes
Under the bar of 400 compilation errors.
more good progress <100 compile errors!
More progress
Game settings store can use string for find, it was a bit absurd how every use of it required to create refId from string
some more progress on other fronts
Mostly game settings clean
one error opened a lot of other errors. Down to 18, but more will prbably appear
only link errors left??
Fixed link errors
OpenMW compiles, and launches, with some issues, but still!
2022-09-25 13:17:09 +02:00
|
|
|
template class MWWorld::TypedDynamicStore<ESM::Class>;
|
|
|
|
template class MWWorld::TypedDynamicStore<ESM::Clothing>;
|
|
|
|
template class MWWorld::TypedDynamicStore<ESM::Container>;
|
|
|
|
template class MWWorld::TypedDynamicStore<ESM::Creature>;
|
|
|
|
template class MWWorld::TypedDynamicStore<ESM::CreatureLevList>;
|
2021-12-24 02:04:26 +03:00
|
|
|
// template class MWWorld::Store<ESM::Dialogue>;
|
Initial commit: In ESM structures, replace the string members that are RefIds to other records, to a new strong type
The strong type is actually just a string underneath, but this will help in the future to have a distinction so it's easier to search and replace when we use an integer ID
Slowly going through all the changes to make, still hundreds of errors
a lot of functions/structures use std::string or stringview to designate an ID. So it takes time
Continues slowly replacing ids. There are technically more and more compilation errors
I have good hope that there is a point where the amount of errors will dramatically go down as all the main functions use the ESM::RefId type
Continue moving forward, changes to the stores
slowly moving along
Starting to see the fruit of those changes.
still many many error, but more and more Irun into a situation where a function is sandwiched between two functions that use the RefId type.
More replacements. Things are starting to get easier
I can see more and more often the issue is that the function is awaiting a RefId, but is given a string
there is less need to go down functions and to fix a long list of them.
Still moving forward, and for the first time error count is going down!
Good pace, not sure about topics though, mId and mName are actually the same thing and are used interchangeably
Cells are back to using string for the name, haven't fixed everything yet. Many other changes
Under the bar of 400 compilation errors.
more good progress <100 compile errors!
More progress
Game settings store can use string for find, it was a bit absurd how every use of it required to create refId from string
some more progress on other fronts
Mostly game settings clean
one error opened a lot of other errors. Down to 18, but more will prbably appear
only link errors left??
Fixed link errors
OpenMW compiles, and launches, with some issues, but still!
2022-09-25 13:17:09 +02:00
|
|
|
template class MWWorld::TypedDynamicStore<ESM::Door>;
|
|
|
|
template class MWWorld::TypedDynamicStore<ESM::Enchantment>;
|
|
|
|
template class MWWorld::TypedDynamicStore<ESM::Faction>;
|
|
|
|
template class MWWorld::TypedDynamicStore<ESM::GameSetting>;
|
|
|
|
template class MWWorld::TypedDynamicStore<ESM::Global>;
|
|
|
|
template class MWWorld::TypedDynamicStore<ESM::Ingredient>;
|
|
|
|
template class MWWorld::TypedDynamicStore<ESM::ItemLevList>;
|
2015-07-10 20:21:55 +02:00
|
|
|
// template class MWWorld::Store<ESM::Land>;
|
2015-07-12 12:01:18 +03:00
|
|
|
// template class MWWorld::Store<ESM::LandTexture>;
|
Initial commit: In ESM structures, replace the string members that are RefIds to other records, to a new strong type
The strong type is actually just a string underneath, but this will help in the future to have a distinction so it's easier to search and replace when we use an integer ID
Slowly going through all the changes to make, still hundreds of errors
a lot of functions/structures use std::string or stringview to designate an ID. So it takes time
Continues slowly replacing ids. There are technically more and more compilation errors
I have good hope that there is a point where the amount of errors will dramatically go down as all the main functions use the ESM::RefId type
Continue moving forward, changes to the stores
slowly moving along
Starting to see the fruit of those changes.
still many many error, but more and more Irun into a situation where a function is sandwiched between two functions that use the RefId type.
More replacements. Things are starting to get easier
I can see more and more often the issue is that the function is awaiting a RefId, but is given a string
there is less need to go down functions and to fix a long list of them.
Still moving forward, and for the first time error count is going down!
Good pace, not sure about topics though, mId and mName are actually the same thing and are used interchangeably
Cells are back to using string for the name, haven't fixed everything yet. Many other changes
Under the bar of 400 compilation errors.
more good progress <100 compile errors!
More progress
Game settings store can use string for find, it was a bit absurd how every use of it required to create refId from string
some more progress on other fronts
Mostly game settings clean
one error opened a lot of other errors. Down to 18, but more will prbably appear
only link errors left??
Fixed link errors
OpenMW compiles, and launches, with some issues, but still!
2022-09-25 13:17:09 +02:00
|
|
|
template class MWWorld::TypedDynamicStore<ESM::Light>;
|
|
|
|
template class MWWorld::TypedDynamicStore<ESM::Lockpick>;
|
2015-07-10 20:21:55 +02:00
|
|
|
// template class MWWorld::Store<ESM::MagicEffect>;
|
Initial commit: In ESM structures, replace the string members that are RefIds to other records, to a new strong type
The strong type is actually just a string underneath, but this will help in the future to have a distinction so it's easier to search and replace when we use an integer ID
Slowly going through all the changes to make, still hundreds of errors
a lot of functions/structures use std::string or stringview to designate an ID. So it takes time
Continues slowly replacing ids. There are technically more and more compilation errors
I have good hope that there is a point where the amount of errors will dramatically go down as all the main functions use the ESM::RefId type
Continue moving forward, changes to the stores
slowly moving along
Starting to see the fruit of those changes.
still many many error, but more and more Irun into a situation where a function is sandwiched between two functions that use the RefId type.
More replacements. Things are starting to get easier
I can see more and more often the issue is that the function is awaiting a RefId, but is given a string
there is less need to go down functions and to fix a long list of them.
Still moving forward, and for the first time error count is going down!
Good pace, not sure about topics though, mId and mName are actually the same thing and are used interchangeably
Cells are back to using string for the name, haven't fixed everything yet. Many other changes
Under the bar of 400 compilation errors.
more good progress <100 compile errors!
More progress
Game settings store can use string for find, it was a bit absurd how every use of it required to create refId from string
some more progress on other fronts
Mostly game settings clean
one error opened a lot of other errors. Down to 18, but more will prbably appear
only link errors left??
Fixed link errors
OpenMW compiles, and launches, with some issues, but still!
2022-09-25 13:17:09 +02:00
|
|
|
template class MWWorld::TypedDynamicStore<ESM::Miscellaneous>;
|
|
|
|
template class MWWorld::TypedDynamicStore<ESM::NPC>;
|
2015-07-10 20:21:55 +02:00
|
|
|
// template class MWWorld::Store<ESM::Pathgrid>;
|
Initial commit: In ESM structures, replace the string members that are RefIds to other records, to a new strong type
The strong type is actually just a string underneath, but this will help in the future to have a distinction so it's easier to search and replace when we use an integer ID
Slowly going through all the changes to make, still hundreds of errors
a lot of functions/structures use std::string or stringview to designate an ID. So it takes time
Continues slowly replacing ids. There are technically more and more compilation errors
I have good hope that there is a point where the amount of errors will dramatically go down as all the main functions use the ESM::RefId type
Continue moving forward, changes to the stores
slowly moving along
Starting to see the fruit of those changes.
still many many error, but more and more Irun into a situation where a function is sandwiched between two functions that use the RefId type.
More replacements. Things are starting to get easier
I can see more and more often the issue is that the function is awaiting a RefId, but is given a string
there is less need to go down functions and to fix a long list of them.
Still moving forward, and for the first time error count is going down!
Good pace, not sure about topics though, mId and mName are actually the same thing and are used interchangeably
Cells are back to using string for the name, haven't fixed everything yet. Many other changes
Under the bar of 400 compilation errors.
more good progress <100 compile errors!
More progress
Game settings store can use string for find, it was a bit absurd how every use of it required to create refId from string
some more progress on other fronts
Mostly game settings clean
one error opened a lot of other errors. Down to 18, but more will prbably appear
only link errors left??
Fixed link errors
OpenMW compiles, and launches, with some issues, but still!
2022-09-25 13:17:09 +02:00
|
|
|
template class MWWorld::TypedDynamicStore<ESM::Potion>;
|
|
|
|
template class MWWorld::TypedDynamicStore<ESM::Probe>;
|
|
|
|
template class MWWorld::TypedDynamicStore<ESM::Race>;
|
|
|
|
template class MWWorld::TypedDynamicStore<ESM::Region>;
|
|
|
|
template class MWWorld::TypedDynamicStore<ESM::Repair>;
|
|
|
|
template class MWWorld::TypedDynamicStore<ESM::Script>;
|
2015-07-10 20:21:55 +02:00
|
|
|
// template class MWWorld::Store<ESM::Skill>;
|
Initial commit: In ESM structures, replace the string members that are RefIds to other records, to a new strong type
The strong type is actually just a string underneath, but this will help in the future to have a distinction so it's easier to search and replace when we use an integer ID
Slowly going through all the changes to make, still hundreds of errors
a lot of functions/structures use std::string or stringview to designate an ID. So it takes time
Continues slowly replacing ids. There are technically more and more compilation errors
I have good hope that there is a point where the amount of errors will dramatically go down as all the main functions use the ESM::RefId type
Continue moving forward, changes to the stores
slowly moving along
Starting to see the fruit of those changes.
still many many error, but more and more Irun into a situation where a function is sandwiched between two functions that use the RefId type.
More replacements. Things are starting to get easier
I can see more and more often the issue is that the function is awaiting a RefId, but is given a string
there is less need to go down functions and to fix a long list of them.
Still moving forward, and for the first time error count is going down!
Good pace, not sure about topics though, mId and mName are actually the same thing and are used interchangeably
Cells are back to using string for the name, haven't fixed everything yet. Many other changes
Under the bar of 400 compilation errors.
more good progress <100 compile errors!
More progress
Game settings store can use string for find, it was a bit absurd how every use of it required to create refId from string
some more progress on other fronts
Mostly game settings clean
one error opened a lot of other errors. Down to 18, but more will prbably appear
only link errors left??
Fixed link errors
OpenMW compiles, and launches, with some issues, but still!
2022-09-25 13:17:09 +02:00
|
|
|
template class MWWorld::TypedDynamicStore<ESM::Sound>;
|
|
|
|
template class MWWorld::TypedDynamicStore<ESM::SoundGenerator>;
|
|
|
|
template class MWWorld::TypedDynamicStore<ESM::Spell>;
|
|
|
|
template class MWWorld::TypedDynamicStore<ESM::StartScript>;
|
|
|
|
template class MWWorld::TypedDynamicStore<ESM::Static>;
|
|
|
|
template class MWWorld::TypedDynamicStore<ESM::Weapon>;
|
2022-12-28 20:48:25 +01:00
|
|
|
|
2023-04-09 14:16:58 +02:00
|
|
|
template class MWWorld::TypedDynamicStore<ESM4::Activator>;
|
|
|
|
template class MWWorld::TypedDynamicStore<ESM4::Potion>;
|
|
|
|
template class MWWorld::TypedDynamicStore<ESM4::Ammunition>;
|
|
|
|
template class MWWorld::TypedDynamicStore<ESM4::Armor>;
|
|
|
|
template class MWWorld::TypedDynamicStore<ESM4::Book>;
|
|
|
|
template class MWWorld::TypedDynamicStore<ESM4::Clothing>;
|
|
|
|
template class MWWorld::TypedDynamicStore<ESM4::Container>;
|
|
|
|
template class MWWorld::TypedDynamicStore<ESM4::Door>;
|
2023-05-20 18:43:55 +02:00
|
|
|
template class MWWorld::TypedDynamicStore<ESM4::Furniture>;
|
2023-04-09 14:16:58 +02:00
|
|
|
template class MWWorld::TypedDynamicStore<ESM4::Ingredient>;
|
|
|
|
template class MWWorld::TypedDynamicStore<ESM4::MiscItem>;
|
2022-12-28 20:48:25 +01:00
|
|
|
template class MWWorld::TypedDynamicStore<ESM4::Static>;
|
2023-05-20 18:43:55 +02:00
|
|
|
template class MWWorld::TypedDynamicStore<ESM4::Tree>;
|
2023-02-06 20:22:17 +01:00
|
|
|
template class MWWorld::TypedDynamicStore<ESM4::Light>;
|
2023-04-20 00:25:42 +02:00
|
|
|
template class MWWorld::TypedDynamicStore<ESM4::Reference, ESM::FormId>;
|
2022-12-28 20:48:25 +01:00
|
|
|
template class MWWorld::TypedDynamicStore<ESM4::Cell>;
|
2023-04-09 14:16:58 +02:00
|
|
|
template class MWWorld::TypedDynamicStore<ESM4::Weapon>;
|
2023-04-22 13:59:53 +02:00
|
|
|
template class MWWorld::TypedDynamicStore<ESM4::World>;
|
2023-05-15 23:48:22 +02:00
|
|
|
template class MWWorld::TypedDynamicStore<ESM4::Land>;
|