1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-03-29 13:20:35 +00:00

Merge branch 'REFACTOR_STORE' into 'master'

Refactoring the ESM store to better support many new ESM4 types

See merge request OpenMW/openmw!2161
This commit is contained in:
psi29a 2022-09-07 20:22:29 +00:00
commit fcd9b78cac
89 changed files with 796 additions and 545 deletions

View File

@ -5,6 +5,8 @@
#include <components/esm3/loadacti.hpp>
#include <components/misc/rng.hpp>
#include <components/sceneutil/positionattitudetransform.hpp>
#include <components/esm3/loadsoun.hpp>
#include <components/esm3/loadsndg.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp"

View File

@ -5,6 +5,7 @@
#include <components/esm3/loadarmo.hpp>
#include <components/esm3/loadskil.hpp>
#include <components/esm3/loadgmst.hpp>
#include <components/esm3/loadrace.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"

View File

@ -3,6 +3,7 @@
#include <MyGUI_TextIterator.h>
#include <components/esm3/loadbook.hpp>
#include <components/esm3/loadsoun.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"

View File

@ -3,6 +3,7 @@
#include <MyGUI_TextIterator.h>
#include <components/esm3/loadclot.hpp>
#include <components/esm3/loadrace.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"

View File

@ -5,6 +5,7 @@
#include <components/esm3/loadcont.hpp>
#include <components/esm3/containerstate.hpp>
#include <components/settings/settings.hpp>
#include <components/esm3/loadsoun.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"

View File

@ -5,6 +5,9 @@
#include <components/esm3/loadcrea.hpp>
#include <components/esm3/creaturestate.hpp>
#include <components/settings/settings.hpp>
#include <components/esm3/loadsoun.hpp>
#include <components/esm3/loadsndg.hpp>
#include <components/esm3/loadclas.hpp>
#include "../mwmechanics/creaturestats.hpp"
#include "../mwmechanics/magiceffects.hpp"

View File

@ -4,6 +4,7 @@
#include <components/esm3/loaddoor.hpp>
#include <components/esm3/doorstate.hpp>
#include <components/esm3/loadmgef.hpp>
#include <components/sceneutil/positionattitudetransform.hpp>
#include "../mwbase/environment.hpp"

View File

@ -16,6 +16,7 @@
#include <components/esm3/loadrace.hpp>
#include <components/esm3/loadclas.hpp>
#include <components/esm3/loadnpc.hpp>
#include <components/esm3/loadsoun.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"

View File

@ -10,6 +10,7 @@
#include <components/esm3/loadinfo.hpp>
#include <components/esm3/dialoguestate.hpp>
#include <components/esm3/esmwriter.hpp>
#include <components/esm3/loadfact.hpp>
#include <components/compiler/exception.hpp>
#include <components/compiler/errorhandler.hpp>

View File

@ -1,6 +1,8 @@
#include "filter.hpp"
#include <components/compiler/locals.hpp>
#include <components/esm3/loadmgef.hpp>
#include <components/esm3/loadfact.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"

View File

@ -16,6 +16,8 @@
#include <components/compiler/scanner.hpp>
#include <components/compiler/locals.hpp>
#include <components/compiler/scriptparser.hpp>
#include <components/esm3/loadnpc.hpp>
#include <components/esm3/loadcrea.hpp>
#include "filter.hpp"

View File

@ -7,6 +7,9 @@
#include <MyGUI_ControllerManager.h>
#include <MyGUI_ControllerRepeatClick.h>
#include <components/esm3/loadmgef.hpp>
#include <components/esm3/loadingr.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
#include "../mwbase/windowmanager.hpp"

View File

@ -7,6 +7,8 @@
#include <components/resource/resourcesystem.hpp>
#include <components/misc/resourcehelpers.hpp>
#include <components/esm3/loadbsgn.hpp>
#include <components/esm3/loadspel.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"

View File

@ -16,6 +16,7 @@
#include <components/resource/resourcesystem.hpp>
#include <components/misc/resourcehelpers.hpp>
#include <components/vfs/manager.hpp>
#include <components/esm3/loadnpc.hpp>
#include "tooltips.hpp"
#include "ustring.hpp"

View File

@ -111,7 +111,7 @@ namespace MWGui
for (MWWorld::ESMStore::iterator it = store.begin(); it != store.end(); ++it)
{
it->second->listIdentifier (mNames);
(*it)->listIdentifier (mNames);
}
// exterior cell names aren't technically identifiers, but since the COC function accepts them,

View File

@ -10,6 +10,8 @@
#include <components/widgets/box.hpp>
#include <components/widgets/list.hpp>
#include <components/translation/translation.hpp>
#include <components/esm3/loadcrea.hpp>
#include <components/esm3/loadfact.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp"

View File

@ -10,6 +10,8 @@
#include <components/misc/strings/format.hpp>
#include <components/settings/settings.hpp>
#include <components/esm3/loadgmst.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/mechanicsmanager.hpp"
#include "../mwbase/world.hpp"

View File

@ -10,6 +10,8 @@
#include <components/settings/settings.hpp>
#include <components/misc/resourcehelpers.hpp>
#include <components/resource/resourcesystem.hpp>
#include <components/esm3/loadgmst.hpp>
#include <components/esm3/loadmgef.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp"

View File

@ -10,6 +10,7 @@
#include <components/esm3/quickkeys.hpp>
#include <components/resource/resourcesystem.hpp>
#include <components/misc/resourcehelpers.hpp>
#include <components/esm3/loadmgef.hpp>
#include "../mwworld/inventorystore.hpp"
#include "../mwworld/class.hpp"

View File

@ -10,6 +10,9 @@
#include <components/debug/debuglog.hpp>
#include <components/myguiplatform/myguitexture.hpp>
#include <components/esm3/loadbody.hpp>
#include <components/esm3/loadrace.hpp>
#include "../mwworld/esmstore.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"

View File

@ -6,6 +6,8 @@
#include <components/misc/rng.hpp>
#include <components/esm3/loadcrea.hpp>
#include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp"

View File

@ -7,6 +7,10 @@
#include <MyGUI_ImageBox.h>
#include <MyGUI_Gui.h>
#include <components/esm3/loadbsgn.hpp>
#include <components/esm3/loadrace.hpp>
#include <components/esm3/loadspel.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
#include "../mwbase/windowmanager.hpp"

View File

@ -21,6 +21,8 @@
#include <components/files/memorystream.hpp>
#include <components/esm3/loadclas.hpp>
#include "../mwbase/statemanager.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"

View File

@ -15,7 +15,7 @@
#include <components/esm3/loadrepa.hpp>
#include <components/esm3/loadweap.hpp>
#include <components/esm3/loadench.hpp>
#include <components/esm3/loadcrea.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"

View File

@ -6,6 +6,10 @@
#include <components/misc/strings/lower.hpp>
#include <components/esm3/loadrace.hpp>
#include <components/esm3/loadgmst.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
#include "../mwbase/windowmanager.hpp"

View File

@ -9,6 +9,8 @@
#include <components/misc/resourcehelpers.hpp>
#include <components/resource/resourcesystem.hpp>
#include <components/esm3/loadgmst.hpp>
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/mechanicsmanager.hpp"
#include "../mwbase/environment.hpp"

View File

@ -3,6 +3,9 @@
#include <components/debug/debuglog.hpp>
#include <components/misc/utf8stream.hpp>
#include <components/esm3/loadmgef.hpp>
#include <components/esm3/loadench.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
#include "../mwbase/windowmanager.hpp"

View File

@ -5,6 +5,8 @@
#include <components/settings/settings.hpp>
#include <components/misc/strings/format.hpp>
#include <components/esm3/loadrace.hpp>
#include <components/esm3/loadbsgn.hpp>
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/environment.hpp"

View File

@ -1,5 +1,8 @@
#include "statswatcher.hpp"
#include <components/esm3/loadrace.hpp>
#include <components/esm3/loadclas.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/world.hpp"

View File

@ -9,6 +9,13 @@
#include <MyGUI_TextIterator.h>
#include <MyGUI_Gui.h>
#include <components/esm3/loadgmst.hpp>
#include <components/esm3/loadfact.hpp>
#include <components/esm3/loadspel.hpp>
#include <components/esm3/loadbsgn.hpp>
#include <components/esm3/loadclas.hpp>
#include <components/esm3/loadrace.hpp>
#include <components/settings/settings.hpp>
#include "../mwbase/environment.hpp"

View File

@ -10,6 +10,7 @@
#include <components/settings/settings.hpp>
#include <components/widgets/box.hpp>
#include <components/misc/resourcehelpers.hpp>
#include <components/esm/records.hpp>
#include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp"

View File

@ -16,6 +16,7 @@
#include "../mwmechanics/actorutil.hpp"
#include <components/settings/settings.hpp>
#include <components/esm3/loadclas.hpp>
#include "tooltips.hpp"

View File

@ -9,6 +9,7 @@
#include <components/widgets/box.hpp>
#include <components/settings/settings.hpp>
#include <components/misc/strings/format.hpp>
#include <components/esm3/loadregn.hpp>
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/world.hpp"

View File

@ -9,6 +9,9 @@
#include <components/resource/resourcesystem.hpp>
#include <components/misc/resourcehelpers.hpp>
#include <components/esm3/loadspel.hpp>
#include <components/esm3/loadmgef.hpp>
#include <components/esm/attr.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"

View File

@ -7,6 +7,7 @@
#include <variant>
#include <components/lua/luastate.hpp>
#include <components/esm3/loadclas.hpp>
#include "localscripts.hpp"
#include "luamanagerimp.hpp"

View File

@ -8,6 +8,7 @@
#include <apps/openmw/mwworld/esmstore.hpp>
#include <apps/openmw/mwbase/environment.hpp>
#include <apps/openmw/mwbase/world.hpp>
#include <components/esm3/loadskil.hpp>
namespace sol
{

View File

@ -8,6 +8,7 @@
#include <apps/openmw/mwbase/environment.hpp>
#include <apps/openmw/mwbase/world.hpp>
#include <components/esm3/loadalch.hpp>
namespace sol
{

View File

@ -10,6 +10,9 @@
#include <components/misc/strings/algorithm.hpp>
#include <components/esm3/loadmgef.hpp>
#include <components/esm3/loadstat.hpp>
#include <components/esm3/loadench.hpp>
#include <components/esm3/loadrace.hpp>
#include <components/settings/settings.hpp>

View File

@ -12,6 +12,10 @@
#include <components/settings/settings.hpp>
#include <components/misc/resourcehelpers.hpp>
#include <components/esm3/loadmgef.hpp>
#include <components/esm3/loadgmst.hpp>
#include "../mwworld/esmstore.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/inventorystore.hpp"

View File

@ -2,6 +2,11 @@
#include <limits>
#include <components/esm3/loadspel.hpp>
#include <components/esm3/loadrace.hpp>
#include <components/esm/attr.hpp>
#include <components/esm3/loadmgef.hpp>
#include "../mwworld/esmstore.hpp"
#include "../mwbase/world.hpp"

View File

@ -25,6 +25,7 @@
#include <components/misc/rng.hpp>
#include <components/misc/strings/algorithm.hpp>
#include <components/misc/resourcehelpers.hpp>
#include <components/esm/records.hpp>
#include <components/settings/settings.hpp>

View File

@ -6,6 +6,10 @@
#include <components/sceneutil/positionattitudetransform.hpp>
#include <components/esm3/loadench.hpp>
#include <components/esm3/loadmgef.hpp>
#include <components/esm3/loadsoun.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
#include "../mwbase/mechanicsmanager.hpp"

View File

@ -6,6 +6,7 @@
#include <components/esm3/creaturestats.hpp>
#include <components/esm3/esmreader.hpp>
#include <components/esm3/esmwriter.hpp>
#include <components/esm3/loadmgef.hpp>
#include "../mwworld/class.hpp"
#include "../mwworld/esmstore.hpp"

View File

@ -3,6 +3,7 @@
#include <components/misc/rng.hpp>
#include <components/misc/strings/format.hpp>
#include <components/esm3/loadmgef.hpp>
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/environment.hpp"

View File

@ -2,6 +2,8 @@
#include <components/misc/rng.hpp>
#include <components/settings/settings.hpp>
#include <components/esm3/loadcrea.hpp>
#include <components/esm3/loadmgef.hpp>
#include "../mwworld/manualref.hpp"
#include "../mwworld/class.hpp"

View File

@ -3,6 +3,7 @@
#include <components/debug/debuglog.hpp>
#include <components/misc/rng.hpp>
#include <components/esm3/loadlevlist.hpp>
#include "../mwworld/ptr.hpp"
#include "../mwworld/esmstore.hpp"

View File

@ -6,6 +6,9 @@
#include <components/esm3/esmwriter.hpp>
#include <components/esm3/stolenitems.hpp>
#include <components/esm3/loadgmst.hpp>
#include <components/esm3/loadmgef.hpp>
#include <components/esm/records.hpp>
#include <components/sceneutil/positionattitudetransform.hpp>

View File

@ -2,6 +2,8 @@
#include <components/misc/rng.hpp>
#include <components/misc/strings/format.hpp>
#include <components/esm3/loadench.hpp>
#include <components/esm3/loadcrea.hpp>
#include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp"

View File

@ -4,6 +4,8 @@
#include <components/misc/rng.hpp>
#include <components/misc/resourcehelpers.hpp>
#include <components/misc/strings/format.hpp>
#include <components/esm3/loadmgef.hpp>
#include <components/esm3/loadench.hpp>
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/soundmanager.hpp"

View File

@ -6,6 +6,7 @@
#include <components/misc/rng.hpp>
#include <components/settings/settings.hpp>
#include <components/misc/resourcehelpers.hpp>
#include <components/esm3/loadench.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/mechanicsmanager.hpp"

View File

@ -3,6 +3,8 @@
#include <algorithm>
#include <components/esm3/loadspel.hpp>
#include <components/esm3/loadcrea.hpp>
#include <components/esm3/loadnpc.hpp>
#include "spells.hpp"

View File

@ -4,6 +4,7 @@
#include <components/esm3/loadench.hpp>
#include <components/esm3/loadmgef.hpp>
#include <components/esm3/loadspel.hpp>
#include <components/esm3/loadrace.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"

View File

@ -2,6 +2,8 @@
#include <components/misc/rng.hpp>
#include <components/esm3/loadmgef.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"

View File

@ -5,6 +5,8 @@
#include <components/esm3/spellstate.hpp>
#include <components/misc/rng.hpp>
#include <components/esm3/loadmgef.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"

View File

@ -2,6 +2,8 @@
#include <limits>
#include <components/esm3/loadmgef.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"

View File

@ -2,6 +2,9 @@
#include <components/debug/debuglog.hpp>
#include <components/misc/resourcehelpers.hpp>
#include <components/esm3/loadmgef.hpp>
#include <components/esm3/loadspel.hpp>
#include <components/esm3/loadstat.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"

View File

@ -1,6 +1,8 @@
#include "weaponpriority.hpp"
#include <components/esm3/loadench.hpp>
#include <components/esm3/loadgmst.hpp>
#include <components/esm3/loadcrea.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"

View File

@ -28,6 +28,7 @@
#include <components/misc/convert.hpp>
#include <components/settings/settings.hpp>
#include <components/nifosg/particle.hpp> // FindRecIndexVisitor
#include <components/esm3/loadmgef.hpp>
#include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp"

View File

@ -21,6 +21,8 @@
#include <components/misc/constants.hpp>
#include <components/misc/pathhelpers.hpp>
#include <components/misc/resourcehelpers.hpp>
#include <components/esm3/loadmgef.hpp>
#include <components/esm3/loadrace.hpp>
#include <components/sceneutil/keyframe.hpp>

View File

@ -21,7 +21,13 @@
#include <components/sceneutil/skeleton.hpp>
#include <components/sceneutil/keyframe.hpp>
#include <components/sceneutil/depth.hpp>
#include <components/esm3/loadmgef.hpp>
#include <components/esm3/loadstat.hpp>
#include <components/esm3/loadacti.hpp>
#include <components/esm3/loaddoor.hpp>
#include <components/esm3/loadcont.hpp>
#include <components/esm3/loadbody.hpp>
#include <components/esm3/loadrace.hpp>
#include <components/settings/settings.hpp>
#include <components/vfs/manager.hpp>

View File

@ -11,6 +11,11 @@
#include <osgUtil/IncrementalCompileOperation>
#include <components/esm3/esmreader.hpp>
#include <components/esm3/loadstat.hpp>
#include <components/esm3/loadacti.hpp>
#include <components/esm3/loadcont.hpp>
#include <components/esm3/loaddoor.hpp>
#include <components/misc/resourcehelpers.hpp>
#include <components/resource/scenemanager.hpp>
#include <components/sceneutil/optimizer.hpp>

View File

@ -3,7 +3,8 @@
#include "../mwworld/esmstore.hpp"
#include <components/esm3/loaddial.hpp>
#include <components/esm3/loadscpt.hpp>
#include <components/esm/records.hpp>
#include <components/compiler/locals.hpp>
#include "../mwbase/environment.hpp"

View File

@ -16,6 +16,8 @@
#include <components/esm3/loadskil.hpp>
#include <components/esm3/loadlevlist.hpp>
#include <components/esm3/loadcrea.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/world.hpp"

View File

@ -4,6 +4,8 @@
#include <components/misc/strings/lower.hpp>
#include <components/esm3/esmwriter.hpp>
#include <components/esm3/globalscript.hpp>
#include <components/esm3/loadsscr.hpp>
#include <components/esm3/loadscpt.hpp>
#include "../mwworld/class.hpp"
#include "../mwworld/esmstore.hpp"

View File

@ -4,6 +4,7 @@
#include <sstream>
#include <components/compiler/locals.hpp>
#include <components/esm/records.hpp>
#include "../mwworld/esmstore.hpp"

View File

@ -7,6 +7,7 @@
#include <components/interpreter/interpreter.hpp>
#include <components/interpreter/runtime.hpp>
#include <components/interpreter/opcodes.hpp>
#include <components/esm3/loadregn.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"

View File

@ -12,6 +12,9 @@
#include <components/interpreter/interpreter.hpp>
#include <components/interpreter/runtime.hpp>
#include <components/interpreter/opcodes.hpp>
#include <components/esm3/loadfact.hpp>
#include <components/esm3/loadmgef.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/mechanicsmanager.hpp"

View File

@ -2,6 +2,7 @@
#include <components/fallback/fallback.hpp>
#include <components/misc/rng.hpp>
#include <components/esm3/loadregn.hpp>
#include <algorithm>
#include <numeric>

View File

@ -7,6 +7,7 @@
#include <components/debug/debuglog.hpp>
#include <components/settings/settings.hpp>
#include <components/vfs/manager.hpp>
#include <components/esm3/loadsoun.hpp>
#include <algorithm>
#include <cmath>

View File

@ -8,6 +8,7 @@
#include <components/esm3/esmreader.hpp>
#include <components/esm3/cellid.hpp>
#include <components/esm3/loadcell.hpp>
#include <components/esm3/loadclas.hpp>
#include <components/loadinglistener/loadinglistener.hpp>

View File

@ -1,5 +1,8 @@
#include "actionread.hpp"
#include <components/esm3/loadbook.hpp>
#include <components/esm3/loadclas.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/world.hpp"

View File

@ -1,6 +1,7 @@
#include "actionsoulgem.hpp"
#include <components/debug/debuglog.hpp>
#include <components/esm3/loadcrea.hpp>
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/environment.hpp"

View File

@ -18,6 +18,7 @@
#include <components/esm3/creaturelevliststate.hpp>
#include <components/esm3/doorstate.hpp>
#include <components/esm3/readerscache.hpp>
#include <components/esm3/loadench.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/luamanager.hpp"

View File

@ -3,6 +3,9 @@
#include <stdexcept>
#include <components/esm/defs.hpp>
#include <components/esm3/loadsoun.hpp>
#include <components/esm3/loadench.hpp>
#include <components/esm3/loadmgef.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp"

View File

@ -8,6 +8,7 @@
#include <components/misc/strings/algorithm.hpp>
#include <components/misc/strings/lower.hpp>
#include <components/sceneutil/positionattitudetransform.hpp>
#include <components/esm3/loadench.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"

View File

@ -2,6 +2,7 @@
#include <algorithm>
#include <fstream>
#include <tuple>
#include <components/debug/debuglog.hpp>
#include <components/esm3/esmreader.hpp>
@ -10,7 +11,10 @@
#include <components/lua/configuration.hpp>
#include <components/misc/algorithm.hpp>
#include <components/esm3/readerscache.hpp>
#include <components/esm/records.hpp>
#include <components/esmloader/load.hpp>
#include <components/esm4/common.hpp>
#include "../mwmechanics/spelllist.hpp"
@ -129,17 +133,105 @@ namespace
namespace MWWorld
{
using IDMap = std::unordered_map<std::string, int, Misc::StringUtils::CiHash, Misc::StringUtils::CiEqual>;
struct ESMStoreImp
{
ESMStore::StoreTuple mStores;
std::map<ESM::RecNameInts, DynamicStore*> mRecNameToStore;
// Lookup of all IDs. Makes looking up references faster. Just
// maps the id name to the record type.
IDMap mIds;
IDMap mStaticIds;
template<typename T>
static void assignStoreToIndex(ESMStore& stores, Store<T>& store)
{
const std::size_t storeIndex = ESMStore::getTypeIndex<T>();
if (stores.mStores.size() <= storeIndex)
stores.mStores.resize(storeIndex + 1);
assert(&store == &std::get<Store<T>>(stores.mStoreImp->mStores));
stores.mStores[storeIndex] = &store;
if constexpr (std::is_convertible_v<Store<T>*, DynamicStore*>)
{
stores.mDynamicStores.push_back(&store);
constexpr ESM::RecNameInts recName = T::sRecordId;
if constexpr (recName != ESM::REC_INTERNAL_PLAYER)
{
stores.mStoreImp->mRecNameToStore[recName] = &store;
}
}
}
};
int ESMStore::find(const std::string_view id) const
{
IDMap::const_iterator it = mStoreImp->mIds.find(id);
if (it == mStoreImp->mIds.end()) {
return 0;
}
return it->second;
}
int ESMStore::findStatic(const std::string_view id) const
{
IDMap::const_iterator it = mStoreImp-> mStaticIds.find(id);
if (it == mStoreImp->mStaticIds.end()) {
return 0;
}
return it->second;
}
ESMStore::ESMStore()
{
mStoreImp = std::make_unique<ESMStoreImp>();
std::apply([this](auto& ...x) {(ESMStoreImp::assignStoreToIndex(*this, x), ...); }, mStoreImp->mStores);
mDynamicCount = 0;
getWritable<ESM::Pathgrid>().setCells(getWritable<ESM::Cell>());
}
ESMStore::~ESMStore() = default;
void ESMStore::clearDynamic()
{
for (const auto& store : mDynamicStores)
store->clearDynamic();
movePlayerRecord();
}
static bool isCacheableRecord(int id)
{
if (id == ESM::REC_ACTI || id == ESM::REC_ALCH || id == ESM::REC_APPA || id == ESM::REC_ARMO ||
id == ESM::REC_BOOK || id == ESM::REC_CLOT || id == ESM::REC_CONT || id == ESM::REC_CREA ||
id == ESM::REC_DOOR || id == ESM::REC_INGR || id == ESM::REC_LEVC || id == ESM::REC_LEVI ||
id == ESM::REC_LIGH || id == ESM::REC_LOCK || id == ESM::REC_MISC || id == ESM::REC_NPC_ ||
id == ESM::REC_PROB || id == ESM::REC_REPA || id == ESM::REC_STAT || id == ESM::REC_WEAP ||
id == ESM::REC_BODY)
switch (id)
{
return true;
case ESM::REC_ACTI:
case ESM::REC_ALCH:
case ESM::REC_APPA:
case ESM::REC_ARMO:
case ESM::REC_BOOK:
case ESM::REC_CLOT:
case ESM::REC_CONT:
case ESM::REC_CREA:
case ESM::REC_DOOR:
case ESM::REC_INGR:
case ESM::REC_LEVC:
case ESM::REC_LEVI:
case ESM::REC_LIGH:
case ESM::REC_LOCK:
case ESM::REC_MISC:
case ESM::REC_NPC_:
case ESM::REC_PROB:
case ESM::REC_REPA:
case ESM::REC_STAT:
case ESM::REC_WEAP:
case ESM::REC_BODY:
return true;
break;
}
return false;
}
@ -152,7 +244,7 @@ void ESMStore::load(ESM::ESMReader &esm, Loading::Listener* listener, ESM::Dialo
// Land texture loading needs to use a separate internal store for each plugin.
// We set the number of plugins here so we can properly verify if valid plugin
// indices are being passed to the LandTexture Store retrieval methods.
mLandTextures.resize(esm.getIndex()+1);
getWritable<ESM::LandTexture>().resize(esm.getIndex()+1);
// Loop through all records
while(esm.hasMoreRecs())
@ -166,10 +258,11 @@ void ESMStore::load(ESM::ESMReader &esm, Loading::Listener* listener, ESM::Dialo
}
// Look up the record type.
std::map<int, StoreBase *>::iterator it = mStores.find(n.toInt());
ESM::RecNameInts recName = static_cast<ESM::RecNameInts>(n.toInt());
const auto& it = mStoreImp->mRecNameToStore.find(recName);
if (it == mStores.end()) {
if (n.toInt() == ESM::REC_INFO) {
if (it == mStoreImp->mRecNameToStore.end()) {
if (recName == ESM::REC_INFO) {
if (dialogue)
{
dialogue->readInfo(esm, esm.getIndex() != 0);
@ -180,9 +273,9 @@ void ESMStore::load(ESM::ESMReader &esm, Loading::Listener* listener, ESM::Dialo
esm.skipRecord();
}
} else if (n.toInt() == ESM::REC_MGEF) {
mMagicEffects.load (esm);
getWritable<ESM::MagicEffect>().load (esm);
} else if (n.toInt() == ESM::REC_SKIL) {
mSkills.load (esm);
getWritable<ESM::Skill>().load (esm);
}
else if (n.toInt() == ESM::REC_FILT || n.toInt() == ESM::REC_DBGP)
{
@ -208,7 +301,7 @@ void ESMStore::load(ESM::ESMReader &esm, Loading::Listener* listener, ESM::Dialo
}
if (n.toInt() == ESM::REC_DIAL) {
dialogue = const_cast<ESM::Dialogue*>(mDialogs.find(id.mId));
dialogue = const_cast<ESM::Dialogue*>(getWritable<ESM::Dialogue>().find(id.mId));
} else {
dialogue = nullptr;
}
@ -218,6 +311,18 @@ void ESMStore::load(ESM::ESMReader &esm, Loading::Listener* listener, ESM::Dialo
}
}
void ESMStore::setIdType(const std::string& id, ESM::RecNameInts type)
{
mStoreImp->mIds[id] = type;
}
static std::size_t sTypeIndexCounter = 0;
std::size_t ESMStore::geNextTypeIndex()
{
return sTypeIndexCounter++;
}
ESM::LuaScriptsCfg ESMStore::getLuaScriptsCfg() const
{
ESM::LuaScriptsCfg cfg;
@ -246,10 +351,10 @@ ESM::LuaScriptsCfg ESMStore::getLuaScriptsCfg() const
void ESMStore::setUp()
{
mIds.clear();
mStoreImp->mIds.clear();
std::map<int, StoreBase *>::iterator storeIt = mStores.begin();
for (; storeIt != mStores.end(); ++storeIt) {
std::map<ESM::RecNameInts, DynamicStore*>::iterator storeIt = mStoreImp->mRecNameToStore.begin();
for (; storeIt != mStoreImp->mRecNameToStore.end(); ++storeIt) {
storeIt->second->setUp();
if (isCacheableRecord(storeIt->first))
@ -258,18 +363,18 @@ void ESMStore::setUp()
storeIt->second->listIdentifier(identifiers);
for (std::vector<std::string>::const_iterator record = identifiers.begin(); record != identifiers.end(); ++record)
mIds[*record] = storeIt->first;
mStoreImp->mIds[*record] = storeIt->first;
}
}
if (mStaticIds.empty())
for (const auto& [k, v] : mIds)
mStaticIds.emplace(Misc::StringUtils::lowerCase(k), v);
if (mStoreImp->mStaticIds.empty())
for (const auto& [k, v] : mStoreImp->mIds)
mStoreImp->mStaticIds.emplace(Misc::StringUtils::lowerCase(k), v);
mSkills.setUp();
mMagicEffects.setUp();
mAttributes.setUp();
mDialogs.setUp();
getWritable<ESM::Skill>().setUp();
getWritable<ESM::MagicEffect>().setUp();;
getWritable<ESM::Attribute>().setUp();
getWritable<ESM::Dialogue>().setUp();
}
void ESMStore::validateRecords(ESM::ReadersCache& readers)
@ -286,9 +391,10 @@ void ESMStore::countAllCellRefs(ESM::ReadersCache& readers)
return;
std::vector<Ref> refs;
std::vector<std::string> refIDs;
for(auto it = mCells.intBegin(); it != mCells.intEnd(); ++it)
Store<ESM::Cell> Cells = getWritable < ESM::Cell>();
for(auto it = Cells.intBegin(); it != Cells.intEnd(); ++it)
readRefs(*it, refs, refIDs, readers);
for(auto it = mCells.extBegin(); it != mCells.extEnd(); ++it)
for(auto it = Cells.extBegin(); it != Cells.extEnd(); ++it)
readRefs(*it, refs, refIDs, readers);
const auto lessByRefNum = [] (const Ref& l, const Ref& r) { return l.mRefNum < r.mRefNum; };
std::stable_sort(refs.begin(), refs.end(), lessByRefNum);
@ -317,17 +423,19 @@ int ESMStore::getRefCount(std::string_view id) const
void ESMStore::validate()
{
std::vector<ESM::NPC> npcsToReplace = getNPCsToReplace(mFactions, mClasses, mNpcs.mStatic);
auto& npcs = getWritable<ESM::NPC>();
std::vector<ESM::NPC> npcsToReplace = getNPCsToReplace(getWritable<ESM::Faction>(), getWritable<ESM::Class>(), npcs.mStatic);
for (const ESM::NPC &npc : npcsToReplace)
{
mNpcs.eraseStatic(npc.mId);
mNpcs.insertStatic(npc);
npcs.eraseStatic(npc.mId);
npcs.insertStatic(npc);
}
// Validate spell effects for invalid arguments
std::vector<ESM::Spell> spellsToReplace;
for (ESM::Spell spell : mSpells)
auto& spells = getWritable<ESM::Spell>();
for (ESM::Spell spell : spells)
{
if (spell.mEffects.mList.empty())
continue;
@ -336,7 +444,7 @@ void ESMStore::validate()
auto iter = spell.mEffects.mList.begin();
while (iter != spell.mEffects.mList.end())
{
const ESM::MagicEffect* mgef = mMagicEffects.search(iter->mEffectID);
const ESM::MagicEffect* mgef = getWritable<ESM::MagicEffect>().search(iter->mEffectID);
if (!mgef)
{
Log(Debug::Verbose) << "Spell '" << spell.mId << "' has an invalid effect (index " << iter->mEffectID << ") present. Dropping the effect.";
@ -383,25 +491,35 @@ void ESMStore::validate()
for (const ESM::Spell &spell : spellsToReplace)
{
mSpells.eraseStatic(spell.mId);
mSpells.insertStatic(spell);
spells.eraseStatic(spell.mId);
spells.insertStatic(spell);
}
}
void ESMStore::movePlayerRecord()
{
auto& npcs = getWritable<ESM::NPC>();
auto player = npcs.find("player");
npcs.insert(*player);
}
void ESMStore::validateDynamic()
{
std::vector<ESM::NPC> npcsToReplace = getNPCsToReplace(mFactions, mClasses, mNpcs.mDynamic);
auto& npcs = getWritable<ESM::NPC>();
auto& scripts = getWritable<ESM::Script>();
std::vector<ESM::NPC> npcsToReplace = getNPCsToReplace(getWritable<ESM::Faction>(), getWritable<ESM::Class>(), npcs.mDynamic);
for (const ESM::NPC &npc : npcsToReplace)
mNpcs.insert(npc);
npcs.insert(npc);
removeMissingScripts(mScripts, mArmors.mDynamic);
removeMissingScripts(mScripts, mBooks.mDynamic);
removeMissingScripts(mScripts, mClothes.mDynamic);
removeMissingScripts(mScripts, mWeapons.mDynamic);
removeMissingScripts(scripts, getWritable<ESM::Armor>().mDynamic);
removeMissingScripts(scripts, getWritable<ESM::Book>().mDynamic);
removeMissingScripts(scripts, getWritable<ESM::Clothing>().mDynamic);
removeMissingScripts(scripts, getWritable<ESM::Weapon>().mDynamic);
removeMissingObjects(mCreatureLists);
removeMissingObjects(mItemLists);
removeMissingObjects(getWritable<ESM::CreatureLevList>());
removeMissingObjects(getWritable<ESM::ItemLevList>());
}
// Leveled lists can be modified by scripts. This removes items that no longer exist (presumably because the plugin was removed) from modified lists
@ -426,19 +544,20 @@ void ESMStore::removeMissingObjects(Store<T>& store)
int ESMStore::countSavedGameRecords() const
{
return 1 // DYNA (dynamic name counter)
+mPotions.getDynamicSize()
+mArmors.getDynamicSize()
+mBooks.getDynamicSize()
+mClasses.getDynamicSize()
+mClothes.getDynamicSize()
+mEnchants.getDynamicSize()
+mNpcs.getDynamicSize()
+mSpells.getDynamicSize()
+mWeapons.getDynamicSize()
+mCreatureLists.getDynamicSize()
+mItemLists.getDynamicSize()
+mCreatures.getDynamicSize()
+mContainers.getDynamicSize();
+ get<ESM::Potion>().getDynamicSize()
+ get<ESM::Armor>().getDynamicSize()
+ get<ESM::Book>().getDynamicSize()
+ get<ESM::Class>().getDynamicSize()
+ get<ESM::Clothing>().getDynamicSize()
+ get<ESM::Enchantment>().getDynamicSize()
+ get<ESM::NPC>().getDynamicSize()
+ get<ESM::Spell>().getDynamicSize()
+ get<ESM::Weapon>().getDynamicSize()
+ get<ESM::CreatureLevList>().getDynamicSize()
+ get<ESM::ItemLevList>().getDynamicSize()
+ get<ESM::Creature>().getDynamicSize()
+ get<ESM::Container>().getDynamicSize();
}
void ESMStore::write (ESM::ESMWriter& writer, Loading::Listener& progress) const
@ -449,23 +568,24 @@ void ESMStore::removeMissingObjects(Store<T>& store)
writer.endRecord("COUN");
writer.endRecord(ESM::REC_DYNA);
mPotions.write (writer, progress);
mArmors.write (writer, progress);
mBooks.write (writer, progress);
mClasses.write (writer, progress);
mClothes.write (writer, progress);
mEnchants.write (writer, progress);
mSpells.write (writer, progress);
mWeapons.write (writer, progress);
mNpcs.write (writer, progress);
mItemLists.write (writer, progress);
mCreatureLists.write (writer, progress);
mCreatures.write (writer, progress);
mContainers.write (writer, progress);
get<ESM::Potion>().write (writer, progress);
get<ESM::Armor>().write (writer, progress);
get<ESM::Book>().write (writer, progress);
get<ESM::Class>().write (writer, progress);
get<ESM::Clothing>().write (writer, progress);
get<ESM::Enchantment>().write (writer, progress);
get<ESM::NPC>().write (writer, progress);
get<ESM::Spell>().write (writer, progress);
get<ESM::Weapon>().write (writer, progress);
get<ESM::CreatureLevList>().write (writer, progress);
get<ESM::ItemLevList>().write (writer, progress);
get<ESM::Creature>().write (writer, progress);
get<ESM::Container>().write (writer, progress);
}
bool ESMStore::readRecord (ESM::ESMReader& reader, uint32_t type)
bool ESMStore::readRecord (ESM::ESMReader& reader, uint32_t type_id)
{
ESM::RecNameInts type = (ESM::RecNameInts)type_id;
switch (type)
{
case ESM::REC_ALCH:
@ -478,12 +598,12 @@ void ESMStore::removeMissingObjects(Store<T>& store)
case ESM::REC_WEAP:
case ESM::REC_LEVI:
case ESM::REC_LEVC:
mStores[type]->read (reader);
mStoreImp->mRecNameToStore[type]->read (reader);
return true;
case ESM::REC_NPC_:
case ESM::REC_CREA:
case ESM::REC_CONT:
mStores[type]->read (reader, true);
mStoreImp->mRecNameToStore[type]->read (reader, true);
return true;
case ESM::REC_DYNA:
@ -501,10 +621,10 @@ void ESMStore::removeMissingObjects(Store<T>& store)
{
setUp();
const ESM::NPC *player = mNpcs.find ("player");
const ESM::NPC *player = get<ESM::NPC>().find ("player");
if (!mRaces.find (player->mRace) ||
!mClasses.find (player->mClass))
if (!get<ESM::Race>().find (player->mRace) ||
!get<ESM::Class>().find (player->mClass))
throw std::runtime_error ("Invalid player record (race or class unavailable");
}
@ -526,4 +646,34 @@ void ESMStore::removeMissingObjects(Store<T>& store)
}
return {ptr, true};
}
template <>
const ESM::Cell *ESMStore::insert<ESM::Cell>(const ESM::Cell &cell) {
return getWritable<ESM::Cell>().insert(cell);
}
template <>
const ESM::NPC *ESMStore::insert<ESM::NPC>(const ESM::NPC &npc)
{
auto& npcs = getWritable<ESM::NPC>();
if (Misc::StringUtils::ciEqual(npc.mId, "player"))
{
return npcs.insert(npc);
}
const std::string id = "$dynamic" + std::to_string(mDynamicCount++);
if (npcs.search(id) != nullptr)
{
const std::string msg = "Try to override existing record '" + id + "'";
throw std::runtime_error(msg);
}
ESM::NPC record = npc;
record.mId = id;
ESM::NPC *ptr = npcs.insert(record);
mStoreImp->mIds[ptr->mId] = ESM::REC_NPC_;
return ptr;
}
} // end namespace

View File

@ -4,9 +4,11 @@
#include <memory>
#include <stdexcept>
#include <unordered_map>
#include <tuple>
#include <components/esm/luascripts.hpp>
#include <components/esm/records.hpp>
#include <components/esm3/loadgmst.hpp>
#include "store.hpp"
namespace Loading
@ -22,75 +24,139 @@ namespace MWMechanics
namespace ESM
{
class ReadersCache;
struct Activator;
struct Potion;
struct Apparatus;
struct Armor;
struct BodyPart;
struct Book;
struct BirthSign;
struct Class;
struct Clothing;
struct Container;
struct Creature;
struct Dialogue;
struct Door;
struct Enchantment;
struct Faction;
struct Global;
struct Ingredient;
struct CreatureLevList;
struct ItemLevList;
struct Light;
struct Lockpick;
struct Miscellaneous;
struct NPC;
struct Probe;
struct Race;
struct Region;
struct Repair;
struct SoundGenerator;
struct Sound;
struct Spell;
struct StartScript;
struct Static;
struct Weapon;
struct GameSetting;
class Script;
struct Cell;
struct Land;
struct LandTexture;
struct Pathgrid;
struct MagicEffect;
struct Skill;
struct Attribute;
}
namespace MWWorld
{
struct ESMStoreImp;
class ESMStore
{
Store<ESM::Activator> mActivators;
Store<ESM::Potion> mPotions;
Store<ESM::Apparatus> mAppas;
Store<ESM::Armor> mArmors;
Store<ESM::BodyPart> mBodyParts;
Store<ESM::Book> mBooks;
Store<ESM::BirthSign> mBirthSigns;
Store<ESM::Class> mClasses;
Store<ESM::Clothing> mClothes;
Store<ESM::Container> mContainers;
Store<ESM::Creature> mCreatures;
Store<ESM::Dialogue> mDialogs;
Store<ESM::Door> mDoors;
Store<ESM::Enchantment> mEnchants;
Store<ESM::Faction> mFactions;
Store<ESM::Global> mGlobals;
Store<ESM::Ingredient> mIngreds;
Store<ESM::CreatureLevList> mCreatureLists;
Store<ESM::ItemLevList> mItemLists;
Store<ESM::Light> mLights;
Store<ESM::Lockpick> mLockpicks;
Store<ESM::Miscellaneous> mMiscItems;
Store<ESM::NPC> mNpcs;
Store<ESM::Probe> mProbes;
Store<ESM::Race> mRaces;
Store<ESM::Region> mRegions;
Store<ESM::Repair> mRepairs;
Store<ESM::SoundGenerator> mSoundGens;
Store<ESM::Sound> mSounds;
Store<ESM::Spell> mSpells;
Store<ESM::StartScript> mStartScripts;
Store<ESM::Static> mStatics;
Store<ESM::Weapon> mWeapons;
friend struct ESMStoreImp; //This allows StoreImp to extend esmstore without beeing included everywhere
Store<ESM::GameSetting> mGameSettings;
Store<ESM::Script> mScripts;
using StoreTuple = std::tuple <
Store<ESM::Activator>,
Store<ESM::Potion>,
Store<ESM::Apparatus>,
Store<ESM::Armor>,
Store<ESM::BodyPart>,
Store<ESM::Book>,
Store<ESM::BirthSign>,
Store<ESM::Class>,
Store<ESM::Clothing>,
Store<ESM::Container>,
Store<ESM::Creature>,
Store<ESM::Dialogue>,
Store<ESM::Door>,
Store<ESM::Enchantment>,
Store<ESM::Faction>,
Store<ESM::Global>,
Store<ESM::Ingredient>,
Store<ESM::CreatureLevList>,
Store<ESM::ItemLevList>,
Store<ESM::Light>,
Store<ESM::Lockpick>,
Store<ESM::Miscellaneous>,
Store<ESM::NPC>,
Store<ESM::Probe>,
Store<ESM::Race>,
Store<ESM::Region>,
Store<ESM::Repair>,
Store<ESM::SoundGenerator>,
Store<ESM::Sound>,
Store<ESM::Spell>,
Store<ESM::StartScript>,
Store<ESM::Static>,
Store<ESM::Weapon>,
Store<ESM::GameSetting>,
Store<ESM::Script>,
// Lists that need special rules
Store<ESM::Cell> mCells;
Store<ESM::Land> mLands;
Store<ESM::LandTexture> mLandTextures;
Store<ESM::Pathgrid> mPathgrids;
// Lists that need special rules
Store<ESM::Cell>,
Store<ESM::Land>,
Store<ESM::LandTexture>,
Store<ESM::Pathgrid>,
Store<ESM::MagicEffect> mMagicEffects;
Store<ESM::Skill> mSkills;
Store<ESM::MagicEffect>,
Store<ESM::Skill>,
// Special entry which is hardcoded and not loaded from an ESM
Store<ESM::Attribute> mAttributes;
// Special entry which is hardcoded and not loaded from an ESM
Store<ESM::Attribute >>;
// Lookup of all IDs. Makes looking up references faster. Just
// maps the id name to the record type.
using IDMap = std::unordered_map<std::string, int, Misc::StringUtils::CiHash, Misc::StringUtils::CiEqual>;
IDMap mIds;
std::unordered_map<std::string, int> mStaticIds;
template <class T, class Tuple>
struct HasMember;
template <class T, class ... Args>
struct HasMember<T, std::tuple<Store<Args> ...>> {
static constexpr bool value = (std::is_same_v<T, Args> || ...);
};
static std::size_t geNextTypeIndex();
template<typename T>
static std::size_t getTypeIndex()
{
static_assert(HasMember<T, StoreTuple>::value);
static std::size_t sIndex = geNextTypeIndex();
return sIndex;
}
std::unique_ptr<ESMStoreImp> mStoreImp;
std::unordered_map<std::string, int> mRefCount;
std::map<int, StoreBase *> mStores;
std::vector<StoreBase*> mStores;
std::vector<DynamicStore*> mDynamicStores;
unsigned int mDynamicCount;
mutable std::unordered_map<std::string, std::weak_ptr<MWMechanics::SpellList>, Misc::StringUtils::CiHash, Misc::StringUtils::CiEqual> mSpellListCache;
template <class T>
Store<T>& getWritable() {return static_cast<Store<T>&>(*mStores[getTypeIndex<T>()]);}
/// Validate entries in store after setup
void validate();
@ -99,6 +165,8 @@ namespace MWWorld
template<class T>
void removeMissingObjects(Store<T>& store);
void setIdType(const std::string& id, ESM::RecNameInts type);
using LuaContent = std::variant<
ESM::LuaScriptsCfg, // data from an omwaddon
std::string>; // path to an omwscripts file
@ -109,93 +177,28 @@ namespace MWWorld
ESM::LuaScriptsCfg getLuaScriptsCfg() const;
/// \todo replace with SharedIterator<StoreBase>
typedef std::map<int, StoreBase *>::const_iterator iterator;
typedef std::vector<DynamicStore*>::const_iterator iterator;
iterator begin() const {
return mStores.begin();
return mDynamicStores.begin();
}
iterator end() const {
return mStores.end();
return mDynamicStores.end();
}
/// Look up the given ID in 'all'. Returns 0 if not found.
int find(std::string_view id) const
{
IDMap::const_iterator it = mIds.find(id);
if (it == mIds.end()) {
return 0;
}
return it->second;
}
int findStatic(const std::string &id) const
{
IDMap::const_iterator it = mStaticIds.find(id);
if (it == mStaticIds.end()) {
return 0;
}
return it->second;
}
int find(const std::string_view id) const;
ESMStore()
: mDynamicCount(0)
{
mStores[ESM::REC_ACTI] = &mActivators;
mStores[ESM::REC_ALCH] = &mPotions;
mStores[ESM::REC_APPA] = &mAppas;
mStores[ESM::REC_ARMO] = &mArmors;
mStores[ESM::REC_BODY] = &mBodyParts;
mStores[ESM::REC_BOOK] = &mBooks;
mStores[ESM::REC_BSGN] = &mBirthSigns;
mStores[ESM::REC_CELL] = &mCells;
mStores[ESM::REC_CLAS] = &mClasses;
mStores[ESM::REC_CLOT] = &mClothes;
mStores[ESM::REC_CONT] = &mContainers;
mStores[ESM::REC_CREA] = &mCreatures;
mStores[ESM::REC_DIAL] = &mDialogs;
mStores[ESM::REC_DOOR] = &mDoors;
mStores[ESM::REC_ENCH] = &mEnchants;
mStores[ESM::REC_FACT] = &mFactions;
mStores[ESM::REC_GLOB] = &mGlobals;
mStores[ESM::REC_GMST] = &mGameSettings;
mStores[ESM::REC_INGR] = &mIngreds;
mStores[ESM::REC_LAND] = &mLands;
mStores[ESM::REC_LEVC] = &mCreatureLists;
mStores[ESM::REC_LEVI] = &mItemLists;
mStores[ESM::REC_LIGH] = &mLights;
mStores[ESM::REC_LOCK] = &mLockpicks;
mStores[ESM::REC_LTEX] = &mLandTextures;
mStores[ESM::REC_MISC] = &mMiscItems;
mStores[ESM::REC_NPC_] = &mNpcs;
mStores[ESM::REC_PGRD] = &mPathgrids;
mStores[ESM::REC_PROB] = &mProbes;
mStores[ESM::REC_RACE] = &mRaces;
mStores[ESM::REC_REGN] = &mRegions;
mStores[ESM::REC_REPA] = &mRepairs;
mStores[ESM::REC_SCPT] = &mScripts;
mStores[ESM::REC_SNDG] = &mSoundGens;
mStores[ESM::REC_SOUN] = &mSounds;
mStores[ESM::REC_SPEL] = &mSpells;
mStores[ESM::REC_SSCR] = &mStartScripts;
mStores[ESM::REC_STAT] = &mStatics;
mStores[ESM::REC_WEAP] = &mWeapons;
int findStatic(const std::string_view id) const;
mPathgrids.setCells(mCells);
}
void clearDynamic ()
{
for (std::map<int, StoreBase *>::iterator it = mStores.begin(); it != mStores.end(); ++it)
it->second->clearDynamic();
ESMStore();
~ESMStore();
movePlayerRecord();
}
void clearDynamic();
void movePlayerRecord ()
{
auto player = mNpcs.find("player");
mNpcs.insert(*player);
}
void movePlayerRecord();
/// Validate entries in store after loading a save
void validateDynamic();
@ -203,9 +206,7 @@ namespace MWWorld
void load(ESM::ESMReader &esm, Loading::Listener* listener, ESM::Dialogue*& dialogue);
template <class T>
const Store<T> &get() const {
throw std::runtime_error("Storage for this type not exist");
}
const Store<T>& get() const {return static_cast<const Store<T>&>(*mStores[getTypeIndex<T>()]);}
/// Insert a custom record (i.e. with a generated ID that will not clash will pre-existing records)
template <class T>
@ -213,7 +214,7 @@ namespace MWWorld
{
const std::string id = "$dynamic" + std::to_string(mDynamicCount++);
Store<T> &store = const_cast<Store<T> &>(get<T>());
Store<T> &store = getWritable<T>();
if (store.search(id) != nullptr)
{
const std::string msg = "Try to override existing record '" + id + "'";
@ -224,10 +225,9 @@ namespace MWWorld
record.mId = id;
T *ptr = store.insert(record);
for (iterator it = mStores.begin(); it != mStores.end(); ++it) {
if (it->second == &store) {
mIds[ptr->mId] = it->first;
}
if constexpr (std::is_convertible_v<Store<T>*, DynamicStore*>)
{
setIdType(ptr->mId, T::sRecordId);
}
return ptr;
}
@ -235,13 +235,12 @@ namespace MWWorld
/// Insert a record with set ID, and allow it to override a pre-existing static record.
template <class T>
const T *overrideRecord(const T &x) {
Store<T> &store = const_cast<Store<T> &>(get<T>());
Store<T> &store = getWritable<T>();
T *ptr = store.insert(x);
for (iterator it = mStores.begin(); it != mStores.end(); ++it) {
if (it->second == &store) {
mIds[ptr->mId] = it->first;
}
if constexpr (std::is_convertible_v<Store<T>*, DynamicStore*>)
{
setIdType(ptr->mId, T::sRecordId);
}
return ptr;
}
@ -249,7 +248,7 @@ namespace MWWorld
template <class T>
const T *insertStatic(const T &x)
{
Store<T> &store = const_cast<Store<T> &>(get<T>());
Store<T>& store = getWritable<T>();
if (store.search(x.mId) != nullptr)
{
const std::string msg = "Try to override existing record '" + x.mId + "'";
@ -257,10 +256,9 @@ namespace MWWorld
}
T *ptr = store.insertStatic(x);
for (iterator it = mStores.begin(); it != mStores.end(); ++it) {
if (it->second == &store) {
mIds[ptr->mId] = it->first;
}
if constexpr (std::is_convertible_v<Store<T>*, DynamicStore*>)
{
setIdType(ptr->mId, T::sRecordId);
}
return ptr;
}
@ -286,245 +284,13 @@ namespace MWWorld
/// Actors with the same ID share spells, abilities, etc.
/// @return The shared spell list to use for this actor and whether or not it has already been initialized.
std::pair<std::shared_ptr<MWMechanics::SpellList>, bool> getSpellList(const std::string& id) const;
};
template <>
const ESM::Cell* ESMStore::insert<ESM::Cell>(const ESM::Cell& cell);
template <>
inline const ESM::Cell *ESMStore::insert<ESM::Cell>(const ESM::Cell &cell) {
return mCells.insert(cell);
}
template <>
inline const ESM::NPC *ESMStore::insert<ESM::NPC>(const ESM::NPC &npc)
{
if (Misc::StringUtils::ciEqual(npc.mId, "player"))
{
return mNpcs.insert(npc);
}
const std::string id = "$dynamic" + std::to_string(mDynamicCount++);
if (mNpcs.search(id) != nullptr)
{
const std::string msg = "Try to override existing record '" + id + "'";
throw std::runtime_error(msg);
}
ESM::NPC record = npc;
record.mId = id;
ESM::NPC *ptr = mNpcs.insert(record);
mIds[ptr->mId] = ESM::REC_NPC_;
return ptr;
}
template <>
inline const Store<ESM::Activator> &ESMStore::get<ESM::Activator>() const {
return mActivators;
}
template <>
inline const Store<ESM::Potion> &ESMStore::get<ESM::Potion>() const {
return mPotions;
}
template <>
inline const Store<ESM::Apparatus> &ESMStore::get<ESM::Apparatus>() const {
return mAppas;
}
template <>
inline const Store<ESM::Armor> &ESMStore::get<ESM::Armor>() const {
return mArmors;
}
template <>
inline const Store<ESM::BodyPart> &ESMStore::get<ESM::BodyPart>() const {
return mBodyParts;
}
template <>
inline const Store<ESM::Book> &ESMStore::get<ESM::Book>() const {
return mBooks;
}
template <>
inline const Store<ESM::BirthSign> &ESMStore::get<ESM::BirthSign>() const {
return mBirthSigns;
}
template <>
inline const Store<ESM::Class> &ESMStore::get<ESM::Class>() const {
return mClasses;
}
template <>
inline const Store<ESM::Clothing> &ESMStore::get<ESM::Clothing>() const {
return mClothes;
}
template <>
inline const Store<ESM::Container> &ESMStore::get<ESM::Container>() const {
return mContainers;
}
template <>
inline const Store<ESM::Creature> &ESMStore::get<ESM::Creature>() const {
return mCreatures;
}
template <>
inline const Store<ESM::Dialogue> &ESMStore::get<ESM::Dialogue>() const {
return mDialogs;
}
template <>
inline const Store<ESM::Door> &ESMStore::get<ESM::Door>() const {
return mDoors;
}
template <>
inline const Store<ESM::Enchantment> &ESMStore::get<ESM::Enchantment>() const {
return mEnchants;
}
template <>
inline const Store<ESM::Faction> &ESMStore::get<ESM::Faction>() const {
return mFactions;
}
template <>
inline const Store<ESM::Global> &ESMStore::get<ESM::Global>() const {
return mGlobals;
}
template <>
inline const Store<ESM::Ingredient> &ESMStore::get<ESM::Ingredient>() const {
return mIngreds;
}
template <>
inline const Store<ESM::CreatureLevList> &ESMStore::get<ESM::CreatureLevList>() const {
return mCreatureLists;
}
template <>
inline const Store<ESM::ItemLevList> &ESMStore::get<ESM::ItemLevList>() const {
return mItemLists;
}
template <>
inline const Store<ESM::Light> &ESMStore::get<ESM::Light>() const {
return mLights;
}
template <>
inline const Store<ESM::Lockpick> &ESMStore::get<ESM::Lockpick>() const {
return mLockpicks;
}
template <>
inline const Store<ESM::Miscellaneous> &ESMStore::get<ESM::Miscellaneous>() const {
return mMiscItems;
}
template <>
inline const Store<ESM::NPC> &ESMStore::get<ESM::NPC>() const {
return mNpcs;
}
template <>
inline const Store<ESM::Probe> &ESMStore::get<ESM::Probe>() const {
return mProbes;
}
template <>
inline const Store<ESM::Race> &ESMStore::get<ESM::Race>() const {
return mRaces;
}
template <>
inline const Store<ESM::Region> &ESMStore::get<ESM::Region>() const {
return mRegions;
}
template <>
inline const Store<ESM::Repair> &ESMStore::get<ESM::Repair>() const {
return mRepairs;
}
template <>
inline const Store<ESM::SoundGenerator> &ESMStore::get<ESM::SoundGenerator>() const {
return mSoundGens;
}
template <>
inline const Store<ESM::Sound> &ESMStore::get<ESM::Sound>() const {
return mSounds;
}
template <>
inline const Store<ESM::Spell> &ESMStore::get<ESM::Spell>() const {
return mSpells;
}
template <>
inline const Store<ESM::StartScript> &ESMStore::get<ESM::StartScript>() const {
return mStartScripts;
}
template <>
inline const Store<ESM::Static> &ESMStore::get<ESM::Static>() const {
return mStatics;
}
template <>
inline const Store<ESM::Weapon> &ESMStore::get<ESM::Weapon>() const {
return mWeapons;
}
template <>
inline const Store<ESM::GameSetting> &ESMStore::get<ESM::GameSetting>() const {
return mGameSettings;
}
template <>
inline const Store<ESM::Script> &ESMStore::get<ESM::Script>() const {
return mScripts;
}
template <>
inline const Store<ESM::Cell> &ESMStore::get<ESM::Cell>() const {
return mCells;
}
template <>
inline const Store<ESM::Land> &ESMStore::get<ESM::Land>() const {
return mLands;
}
template <>
inline const Store<ESM::LandTexture> &ESMStore::get<ESM::LandTexture>() const {
return mLandTextures;
}
template <>
inline const Store<ESM::Pathgrid> &ESMStore::get<ESM::Pathgrid>() const {
return mPathgrids;
}
template <>
inline const Store<ESM::MagicEffect> &ESMStore::get<ESM::MagicEffect>() const {
return mMagicEffects;
}
template <>
inline const Store<ESM::Skill> &ESMStore::get<ESM::Skill>() const {
return mSkills;
}
template <>
inline const Store<ESM::Attribute> &ESMStore::get<ESM::Attribute>() const {
return mAttributes;
}
const ESM::NPC* ESMStore::insert<ESM::NPC>(const ESM::NPC& npc);
}
#endif

View File

@ -4,6 +4,9 @@
#include <components/debug/debuglog.hpp>
#include <components/esm3/objectstate.hpp>
#include <components/esm3/loadcrea.hpp>
#include <components/esm3/loadclas.hpp>
#include <components/esm3/loadscpt.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"

View File

@ -1,6 +1,7 @@
#include "localscripts.hpp"
#include <components/debug/debuglog.hpp>
#include <components/esm3/loadscpt.hpp>
#include "esmstore.hpp"
#include "cellstore.hpp"

View File

@ -2,6 +2,13 @@
#include "esmstore.hpp"
#include <components/esm3/npcstate.hpp>
#include <components/esm3/loadspel.hpp>
#include <components/esm3/loadskil.hpp>
#include <components/esm3/loadench.hpp>
#include <components/esm3/loadmgef.hpp>
#include <components/esm3/loadarmo.hpp>
#include <components/esm3/loadclot.hpp>
#include <components/esm3/loadweap.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"

View File

@ -1,4 +1,5 @@
#include "manualref.hpp"
#include <components/esm/records.hpp>
#include "esmstore.hpp"

View File

@ -10,6 +10,7 @@
#include <components/esm/defs.hpp>
#include <components/esm3/loadbsgn.hpp>
#include <components/fallback/fallback.hpp>
#include <components/esm3/loadmgef.hpp>
#include "../mwworld/esmstore.hpp"
#include "../mwworld/inventorystore.hpp"

View File

@ -11,6 +11,9 @@
#include <components/esm3/esmwriter.hpp>
#include <components/esm3/projectilestate.hpp>
#include <components/esm3/loadrace.hpp>
#include <components/esm3/loadmgef.hpp>
#include <components/esm3/loadench.hpp>
#include <components/misc/constants.hpp>
#include <components/misc/convert.hpp>

View File

@ -43,10 +43,12 @@ namespace MWWorld
RecordId(const std::string &id = {}, bool isDeleted = false);
};
class StoreBase
class StoreBase {}; //Empty interface to be parent of all store types
class DynamicStore : public StoreBase
{
public:
virtual ~StoreBase() {}
virtual ~DynamicStore() {}
virtual void setUp() {}
@ -67,7 +69,7 @@ namespace MWWorld
};
template <class T>
class IndexedStore
class IndexedStore : public StoreBase
{
protected:
typedef typename std::map<int, T> Static;
@ -161,7 +163,7 @@ namespace MWWorld
class ESMStore;
template <class T>
class Store : public StoreBase
class Store : public DynamicStore
{
typedef std::unordered_map<std::string, T, Misc::StringUtils::CiHash, Misc::StringUtils::CiEqual> Static;
Static mStatic;
@ -220,7 +222,7 @@ namespace MWWorld
};
template <>
class Store<ESM::LandTexture> : public StoreBase
class Store<ESM::LandTexture> : public DynamicStore
{
// For multiple ESM/ESP files we need one list per file.
typedef std::vector<ESM::LandTexture> LandTextureList;
@ -248,7 +250,7 @@ namespace MWWorld
};
template <>
class Store<ESM::Land> : public StoreBase
class Store<ESM::Land> : public DynamicStore
{
struct SpatialComparator
{
@ -291,7 +293,7 @@ namespace MWWorld
};
template <>
class Store<ESM::Cell> : public StoreBase
class Store<ESM::Cell> : public DynamicStore
{
struct DynamicExtCmp
{
@ -366,7 +368,7 @@ namespace MWWorld
};
template <>
class Store<ESM::Pathgrid> : public StoreBase
class Store<ESM::Pathgrid> : public DynamicStore
{
private:
typedef std::unordered_map<std::string, ESM::Pathgrid, Misc::StringUtils::CiHash, Misc::StringUtils::CiEqual> Interior;
@ -433,7 +435,7 @@ namespace MWWorld
};
template <>
class Store<ESM::WeaponType> : public StoreBase
class Store<ESM::WeaponType> : public DynamicStore
{
std::map<int, ESM::WeaponType> mStatic;
@ -459,7 +461,7 @@ namespace MWWorld
};
template <>
class Store<ESM::Dialogue> : public StoreBase
class Store<ESM::Dialogue> : public DynamicStore
{
typedef std::unordered_map<std::string, ESM::Dialogue, Misc::StringUtils::CiHash, Misc::StringUtils::CiEqual> Static;
Static mStatic;

View File

@ -5,6 +5,7 @@
#include <components/esm3/esmreader.hpp>
#include <components/esm3/esmwriter.hpp>
#include <components/esm3/weatherstate.hpp>
#include <components/esm3/loadregn.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/soundmanager.hpp"

View File

@ -16,6 +16,11 @@
#include <components/esm3/esmwriter.hpp>
#include <components/esm3/cellid.hpp>
#include <components/esm3/cellref.hpp>
#include <components/esm3/loadgmst.hpp>
#include <components/esm3/loadregn.hpp>
#include <components/esm3/loadench.hpp>
#include <components/esm3/loadmgef.hpp>
#include <components/esm3/loadclas.hpp>
#include <components/misc/constants.hpp>
#include <components/misc/mathutil.hpp>

View File

@ -8,6 +8,7 @@
#include <components/files/configurationmanager.hpp>
#include <components/esm3/esmreader.hpp>
#include <components/esm3/esmwriter.hpp>
#include <components/esm/records.hpp>
#include <components/loadinglistener/loadinglistener.hpp>
#include <components/misc/strings/algorithm.hpp>

View File

@ -2,11 +2,14 @@
#define OPENMW_ESM_DEFS_H
#include <stdint.h>
#include <stdexcept>
#include <tuple>
#include <osg/Vec3f>
#include <components/esm4/common.hpp>
namespace ESM
{
@ -86,10 +89,20 @@ bool inline operator!= (const Position& left, const Position& right) noexcept
left.rot[2] != right.rot[2];
}
template<std::size_t len>
constexpr unsigned int fourCC(const char(&name)[len]) {
static_assert(len == 5, "Constant must be 4 characters long. (Plus null terminator)");
return static_cast<unsigned char>(name[0]) | (static_cast<unsigned char>(name[1]) << 8) | (static_cast<unsigned char>(name[2]) << 16) | (static_cast<unsigned char>(name[3]) << 24);
constexpr unsigned int sEsm4RecnameFlag = 0x00800000;
constexpr unsigned int esm3Recname(const char(&name)[5]) {
if ((fourCC(name) & sEsm4RecnameFlag) == 0)
return fourCC(name);
else
throw std::logic_error("there must be no collision between esm3 records and esm4 records");//The throw errors ensures at compile time that no collision between ESM4 and ESM3 is possible
}
constexpr unsigned int esm4Recname(const ESM4::RecordTypes recType) {
if ((recType & sEsm4RecnameFlag) == 0)
return (recType | sEsm4RecnameFlag);
else
throw std::logic_error("there must be no collision between esm3 records and esm4 records");//The throw errors ensures at compile time that no collision between ESM4 and ESM3 is possible
}
enum RecNameInts : unsigned int
@ -100,87 +113,227 @@ enum RecNameInts : unsigned int
REC_INTERNAL_MARKER = 1,
// format 0 / legacy
REC_ACTI = fourCC("ACTI"),
REC_ALCH = fourCC("ALCH"),
REC_APPA = fourCC("APPA"),
REC_ARMO = fourCC("ARMO"),
REC_BODY = fourCC("BODY"),
REC_BOOK = fourCC("BOOK"),
REC_BSGN = fourCC("BSGN"),
REC_CELL = fourCC("CELL"),
REC_CLAS = fourCC("CLAS"),
REC_CLOT = fourCC("CLOT"),
REC_CNTC = fourCC("CNTC"),
REC_CONT = fourCC("CONT"),
REC_CREA = fourCC("CREA"),
REC_CREC = fourCC("CREC"),
REC_DIAL = fourCC("DIAL"),
REC_DOOR = fourCC("DOOR"),
REC_ENCH = fourCC("ENCH"),
REC_FACT = fourCC("FACT"),
REC_GLOB = fourCC("GLOB"),
REC_GMST = fourCC("GMST"),
REC_INFO = fourCC("INFO"),
REC_INGR = fourCC("INGR"),
REC_LAND = fourCC("LAND"),
REC_LEVC = fourCC("LEVC"),
REC_LEVI = fourCC("LEVI"),
REC_LIGH = fourCC("LIGH"),
REC_LOCK = fourCC("LOCK"),
REC_LTEX = fourCC("LTEX"),
REC_MGEF = fourCC("MGEF"),
REC_MISC = fourCC("MISC"),
REC_NPC_ = fourCC("NPC_"),
REC_NPCC = fourCC("NPCC"),
REC_PGRD = fourCC("PGRD"),
REC_PROB = fourCC("PROB"),
REC_RACE = fourCC("RACE"),
REC_REGN = fourCC("REGN"),
REC_REPA = fourCC("REPA"),
REC_SCPT = fourCC("SCPT"),
REC_SKIL = fourCC("SKIL"),
REC_SNDG = fourCC("SNDG"),
REC_SOUN = fourCC("SOUN"),
REC_SPEL = fourCC("SPEL"),
REC_SSCR = fourCC("SSCR"),
REC_STAT = fourCC("STAT"),
REC_WEAP = fourCC("WEAP"),
REC_ACTI = esm3Recname("ACTI"),
REC_ALCH = esm3Recname("ALCH"),
REC_APPA = esm3Recname("APPA"),
REC_ARMO = esm3Recname("ARMO"),
REC_BODY = esm3Recname("BODY"),
REC_BOOK = esm3Recname("BOOK"),
REC_BSGN = esm3Recname("BSGN"),
REC_CELL = esm3Recname("CELL"),
REC_CLAS = esm3Recname("CLAS"),
REC_CLOT = esm3Recname("CLOT"),
REC_CNTC = esm3Recname("CNTC"),
REC_CONT = esm3Recname("CONT"),
REC_CREA = esm3Recname("CREA"),
REC_CREC = esm3Recname("CREC"),
REC_DIAL = esm3Recname("DIAL"),
REC_DOOR = esm3Recname("DOOR"),
REC_ENCH = esm3Recname("ENCH"),
REC_FACT = esm3Recname("FACT"),
REC_GLOB = esm3Recname("GLOB"),
REC_GMST = esm3Recname("GMST"),
REC_INFO = esm3Recname("INFO"),
REC_INGR = esm3Recname("INGR"),
REC_LAND = esm3Recname("LAND"),
REC_LEVC = esm3Recname("LEVC"),
REC_LEVI = esm3Recname("LEVI"),
REC_LIGH = esm3Recname("LIGH"),
REC_LOCK = esm3Recname("LOCK"),
REC_LTEX = esm3Recname("LTEX"),
REC_MGEF = esm3Recname("MGEF"),
REC_MISC = esm3Recname("MISC"),
REC_NPC_ = esm3Recname("NPC_"),
REC_NPCC = esm3Recname("NPCC"),
REC_PGRD = esm3Recname("PGRD"),
REC_PROB = esm3Recname("PROB"),
REC_RACE = esm3Recname("RACE"),
REC_REGN = esm3Recname("REGN"),
REC_REPA = esm3Recname("REPA"),
REC_SCPT = esm3Recname("SCPT"),
REC_SKIL = esm3Recname("SKIL"),
REC_SNDG = esm3Recname("SNDG"),
REC_SOUN = esm3Recname("SOUN"),
REC_SPEL = esm3Recname("SPEL"),
REC_SSCR = esm3Recname("SSCR"),
REC_STAT = esm3Recname("STAT"),
REC_WEAP = esm3Recname("WEAP"),
// format 0 - saved games
REC_SAVE = fourCC("SAVE"),
REC_JOUR_LEGACY = fourCC("\xa4UOR"), // "\xa4UOR", rather than "JOUR", little oversight when magic numbers were
REC_SAVE = esm3Recname("SAVE"),
REC_JOUR_LEGACY = esm3Recname("\xa4UOR"), // "\xa4UOR", rather than "JOUR", little oversight when magic numbers were
// calculated by hand, needs to be supported for older files now
REC_JOUR = fourCC("JOUR"),
REC_QUES = fourCC("QUES"),
REC_GSCR = fourCC("GSCR"),
REC_PLAY = fourCC("PLAY"),
REC_CSTA = fourCC("CSTA"),
REC_GMAP = fourCC("GMAP"),
REC_DIAS = fourCC("DIAS"),
REC_WTHR = fourCC("WTHR"),
REC_KEYS = fourCC("KEYS"),
REC_DYNA = fourCC("DYNA"),
REC_ASPL = fourCC("ASPL"),
REC_ACTC = fourCC("ACTC"),
REC_MPRJ = fourCC("MPRJ"),
REC_PROJ = fourCC("PROJ"),
REC_DCOU = fourCC("DCOU"),
REC_MARK = fourCC("MARK"),
REC_ENAB = fourCC("ENAB"),
REC_CAM_ = fourCC("CAM_"),
REC_STLN = fourCC("STLN"),
REC_INPU = fourCC("INPU"),
REC_JOUR = esm3Recname("JOUR"),
REC_QUES = esm3Recname("QUES"),
REC_GSCR = esm3Recname("GSCR"),
REC_PLAY = esm3Recname("PLAY"),
REC_CSTA = esm3Recname("CSTA"),
REC_GMAP = esm3Recname("GMAP"),
REC_DIAS = esm3Recname("DIAS"),
REC_WTHR = esm3Recname("WTHR"),
REC_KEYS = esm3Recname("KEYS"),
REC_DYNA = esm3Recname("DYNA"),
REC_ASPL = esm3Recname("ASPL"),
REC_ACTC = esm3Recname("ACTC"),
REC_MPRJ = esm3Recname("MPRJ"),
REC_PROJ = esm3Recname("PROJ"),
REC_DCOU = esm3Recname("DCOU"),
REC_MARK = esm3Recname("MARK"),
REC_ENAB = esm3Recname("ENAB"),
REC_CAM_ = esm3Recname("CAM_"),
REC_STLN = esm3Recname("STLN"),
REC_INPU = esm3Recname("INPU"),
// format 1
REC_FILT = fourCC("FILT"),
REC_DBGP = fourCC("DBGP"), ///< only used in project files
REC_LUAL = fourCC("LUAL"), // LuaScriptsCfg (only in omwgame or omwaddon)
REC_FILT = esm3Recname("FILT"),
REC_DBGP = esm3Recname("DBGP"), ///< only used in project files
REC_LUAL = esm3Recname("LUAL"), // LuaScriptsCfg (only in omwgame or omwaddon)
// format 16 - Lua scripts in saved games
REC_LUAM = fourCC("LUAM"), // LuaManager data
REC_LUAM = esm3Recname("LUAM"), // LuaManager data
// format 21 - Random state in saved games.
REC_RAND = fourCC("RAND"), // Random state.
REC_RAND = esm3Recname("RAND"), // Random state.
REC_AACT4 = esm4Recname(ESM4::REC_AACT), // Action
REC_ACHR4 = esm4Recname(ESM4::REC_ACHR), // Actor Reference
REC_ACTI4 = esm4Recname(ESM4::REC_ACTI), // Activator
REC_ADDN4 = esm4Recname(ESM4::REC_ADDN), // Addon Node
REC_ALCH4 = esm4Recname(ESM4::REC_ALCH), // Potion
REC_AMMO4 = esm4Recname(ESM4::REC_AMMO), // Ammo
REC_ANIO4 = esm4Recname(ESM4::REC_ANIO), // Animated Object
REC_APPA4 = esm4Recname(ESM4::REC_APPA), // Apparatus (probably unused)
REC_ARMA4 = esm4Recname(ESM4::REC_ARMA), // Armature (Model)
REC_ARMO4 = esm4Recname(ESM4::REC_ARMO), // Armor
REC_ARTO4 = esm4Recname(ESM4::REC_ARTO), // Art Object
REC_ASPC4 = esm4Recname(ESM4::REC_ASPC), // Acoustic Space
REC_ASTP4 = esm4Recname(ESM4::REC_ASTP), // Association Type
REC_AVIF4 = esm4Recname(ESM4::REC_AVIF), // Actor Values/Perk Tree Graphics
REC_BOOK4 = esm4Recname(ESM4::REC_BOOK), // Book
REC_BPTD4 = esm4Recname(ESM4::REC_BPTD), // Body Part Data
REC_CAMS4 = esm4Recname(ESM4::REC_CAMS), // Camera Shot
REC_CELL4 = esm4Recname(ESM4::REC_CELL), // Cell
REC_CLAS4 = esm4Recname(ESM4::REC_CLAS), // Class
REC_CLFM4 = esm4Recname(ESM4::REC_CLFM), // Color
REC_CLMT4 = esm4Recname(ESM4::REC_CLMT), // Climate
REC_CLOT4 = esm4Recname(ESM4::REC_CLOT), // Clothing
REC_COBJ4 = esm4Recname(ESM4::REC_COBJ), // Constructible Object (recipes)
REC_COLL4 = esm4Recname(ESM4::REC_COLL), // Collision Layer
REC_CONT4 = esm4Recname(ESM4::REC_CONT), // Container
REC_CPTH4 = esm4Recname(ESM4::REC_CPTH), // Camera Path
REC_CREA4 = esm4Recname(ESM4::REC_CREA), // Creature
REC_CSTY4 = esm4Recname(ESM4::REC_CSTY), // Combat Style
REC_DEBR4 = esm4Recname(ESM4::REC_DEBR), // Debris
REC_DIAL4 = esm4Recname(ESM4::REC_DIAL), // Dialog Topic
REC_DLBR4 = esm4Recname(ESM4::REC_DLBR), // Dialog Branch
REC_DLVW4 = esm4Recname(ESM4::REC_DLVW), // Dialog View
REC_DOBJ4 = esm4Recname(ESM4::REC_DOBJ), // Default Object Manager
REC_DOOR4 = esm4Recname(ESM4::REC_DOOR), // Door
REC_DUAL4 = esm4Recname(ESM4::REC_DUAL), // Dual Cast Data (possibly unused)
REC_ECZN4 = esm4Recname(ESM4::REC_ECZN), // Encounter Zone
REC_EFSH4 = esm4Recname(ESM4::REC_EFSH), // Effect Shader
REC_ENCH4 = esm4Recname(ESM4::REC_ENCH), // Enchantment
REC_EQUP4 = esm4Recname(ESM4::REC_EQUP), // Equip Slot (flag-type values)
REC_EXPL4 = esm4Recname(ESM4::REC_EXPL), // Explosion
REC_EYES4 = esm4Recname(ESM4::REC_EYES), // Eyes
REC_FACT4 = esm4Recname(ESM4::REC_FACT), // Faction
REC_FLOR4 = esm4Recname(ESM4::REC_FLOR), // Flora
REC_FLST4 = esm4Recname(ESM4::REC_FLST), // Form List (non-levelled list)
REC_FSTP4 = esm4Recname(ESM4::REC_FSTP), // Footstep
REC_FSTS4 = esm4Recname(ESM4::REC_FSTS), // Footstep Set
REC_FURN4 = esm4Recname(ESM4::REC_FURN), // Furniture
REC_GLOB4 = esm4Recname(ESM4::REC_GLOB), // Global Variable
REC_GMST4 = esm4Recname(ESM4::REC_GMST), // Game Setting
REC_GRAS4 = esm4Recname(ESM4::REC_GRAS), // Grass
REC_GRUP4 = esm4Recname(ESM4::REC_GRUP), // Form Group
REC_HAIR4 = esm4Recname(ESM4::REC_HAIR), // Hair
REC_HAZD4 = esm4Recname(ESM4::REC_HAZD), // Hazard
REC_HDPT4 = esm4Recname(ESM4::REC_HDPT), // Head Part
REC_IDLE4 = esm4Recname(ESM4::REC_IDLE), // Idle Animation
REC_IDLM4 = esm4Recname(ESM4::REC_IDLM), // Idle Marker
REC_IMAD4 = esm4Recname(ESM4::REC_IMAD), // Image Space Modifier
REC_IMGS4 = esm4Recname(ESM4::REC_IMGS), // Image Space
REC_INFO4 = esm4Recname(ESM4::REC_INFO), // Dialog Topic Info
REC_INGR4 = esm4Recname(ESM4::REC_INGR), // Ingredient
REC_IPCT4 = esm4Recname(ESM4::REC_IPCT), // Impact Data
REC_IPDS4 = esm4Recname(ESM4::REC_IPDS), // Impact Data Set
REC_KEYM4 = esm4Recname(ESM4::REC_KEYM), // Key
REC_KYWD4 = esm4Recname(ESM4::REC_KYWD), // Keyword
REC_LAND4 = esm4Recname(ESM4::REC_LAND), // Land
REC_LCRT4 = esm4Recname(ESM4::REC_LCRT), // Location Reference Type
REC_LCTN4 = esm4Recname(ESM4::REC_LCTN), // Location
REC_LGTM4 = esm4Recname(ESM4::REC_LGTM), // Lighting Template
REC_LIGH4 = esm4Recname(ESM4::REC_LIGH), // Light
REC_LSCR4 = esm4Recname(ESM4::REC_LSCR), // Load Screen
REC_LTEX4 = esm4Recname(ESM4::REC_LTEX), // Land Texture
REC_LVLC4 = esm4Recname(ESM4::REC_LVLC), // Leveled Creature
REC_LVLI4 = esm4Recname(ESM4::REC_LVLI), // Leveled Item
REC_LVLN4 = esm4Recname(ESM4::REC_LVLN), // Leveled Actor
REC_LVSP4 = esm4Recname(ESM4::REC_LVSP), // Leveled Spell
REC_MATO4 = esm4Recname(ESM4::REC_MATO), // Material Object
REC_MATT4 = esm4Recname(ESM4::REC_MATT), // Material Type
REC_MESG4 = esm4Recname(ESM4::REC_MESG), // Message
REC_MGEF4 = esm4Recname(ESM4::REC_MGEF), // Magic Effect
REC_MISC4 = esm4Recname(ESM4::REC_MISC), // Misc. Object
REC_MOVT4 = esm4Recname(ESM4::REC_MOVT), // Movement Type
REC_MSTT4 = esm4Recname(ESM4::REC_MSTT), // Movable Static
REC_MUSC4 = esm4Recname(ESM4::REC_MUSC), // Music Type
REC_MUST4 = esm4Recname(ESM4::REC_MUST), // Music Track
REC_NAVI4 = esm4Recname(ESM4::REC_NAVI), // Navigation (master data)
REC_NAVM4 = esm4Recname(ESM4::REC_NAVM), // Nav Mesh
REC_NOTE4 = esm4Recname(ESM4::REC_NOTE), // Note
REC_NPC_4 = esm4Recname(ESM4::REC_NPC_), // Actor (NPC, Creature)
REC_OTFT4 = esm4Recname(ESM4::REC_OTFT), // Outfit
REC_PACK4 = esm4Recname(ESM4::REC_PACK), // AI Package
REC_PERK4 = esm4Recname(ESM4::REC_PERK), // Perk
REC_PGRE4 = esm4Recname(ESM4::REC_PGRE), // Placed grenade
REC_PHZD4 = esm4Recname(ESM4::REC_PHZD), // Placed hazard
REC_PROJ4 = esm4Recname(ESM4::REC_PROJ), // Projectile
REC_QUST4 = esm4Recname(ESM4::REC_QUST), // Quest
REC_RACE4 = esm4Recname(ESM4::REC_RACE), // Race / Creature type
REC_REFR4 = esm4Recname(ESM4::REC_REFR), // Object Reference
REC_REGN4 = esm4Recname(ESM4::REC_REGN), // Region (Audio/Weather)
REC_RELA4 = esm4Recname(ESM4::REC_RELA), // Relationship
REC_REVB4 = esm4Recname(ESM4::REC_REVB), // Reverb Parameters
REC_RFCT4 = esm4Recname(ESM4::REC_RFCT), // Visual Effect
REC_SBSP4 = esm4Recname(ESM4::REC_SBSP), // Subspace (TES4 only?)
REC_SCEN4 = esm4Recname(ESM4::REC_SCEN), // Scene
REC_SCPT4 = esm4Recname(ESM4::REC_SCPT), // Script
REC_SCRL4 = esm4Recname(ESM4::REC_SCRL), // Scroll
REC_SGST4 = esm4Recname(ESM4::REC_SGST), // Sigil Stone
REC_SHOU4 = esm4Recname(ESM4::REC_SHOU), // Shout
REC_SLGM4 = esm4Recname(ESM4::REC_SLGM), // Soul Gem
REC_SMBN4 = esm4Recname(ESM4::REC_SMBN), // Story Manager Branch Node
REC_SMEN4 = esm4Recname(ESM4::REC_SMEN), // Story Manager Event Node
REC_SMQN4 = esm4Recname(ESM4::REC_SMQN), // Story Manager Quest Node
REC_SNCT4 = esm4Recname(ESM4::REC_SNCT), // Sound Category
REC_SNDR4 = esm4Recname(ESM4::REC_SNDR), // Sound Reference
REC_SOPM4 = esm4Recname(ESM4::REC_SOPM), // Sound Output Model
REC_SOUN4 = esm4Recname(ESM4::REC_SOUN), // Sound
REC_SPEL4 = esm4Recname(ESM4::REC_SPEL), // Spell
REC_SPGD4 = esm4Recname(ESM4::REC_SPGD), // Shader Particle Geometry
REC_STAT4 = esm4Recname(ESM4::REC_STAT), // Static
REC_TACT4 = esm4Recname(ESM4::REC_TACT), // Talking Activator
REC_TERM4 = esm4Recname(ESM4::REC_TERM), // Terminal
REC_TES44 = esm4Recname(ESM4::REC_TES4), // Plugin info
REC_TREE4 = esm4Recname(ESM4::REC_TREE), // Tree
REC_TXST4 = esm4Recname(ESM4::REC_TXST), // Texture Set
REC_VTYP4 = esm4Recname(ESM4::REC_VTYP), // Voice Type
REC_WATR4 = esm4Recname(ESM4::REC_WATR), // Water Type
REC_WEAP4 = esm4Recname(ESM4::REC_WEAP), // Weapon
REC_WOOP4 = esm4Recname(ESM4::REC_WOOP), // Word Of Power
REC_WRLD4 = esm4Recname(ESM4::REC_WRLD), // World Space
REC_WTHR4 = esm4Recname(ESM4::REC_WTHR), // Weather
REC_ACRE4 = esm4Recname(ESM4::REC_ACRE), // Placed Creature (TES4 only?)
REC_PGRD4 = esm4Recname(ESM4::REC_PGRD), // Pathgrid (TES4 only?)
REC_ROAD4 = esm4Recname(ESM4::REC_ROAD), // Road (TES4 only?)
REC_IMOD4 = esm4Recname(ESM4::REC_IMOD), // Item Mod
REC_PWAT4 = esm4Recname(ESM4::REC_PWAT), // Placeable Water
REC_SCOL4 = esm4Recname(ESM4::REC_SCOL), // Static Collection
REC_CCRD4 = esm4Recname(ESM4::REC_CCRD), // Caravan Card
REC_CMNY4 = esm4Recname(ESM4::REC_CMNY), // Caravan Money
REC_ALOC4 = esm4Recname(ESM4::REC_ALOC), // Audio Location Controller
REC_MSET4 = esm4Recname(ESM4::REC_MSET) // Media Set
};
/// Common subrecords

View File

@ -30,10 +30,17 @@
#include <cstdint>
#include <string>
#include <components/esm/defs.hpp>
#include "formid.hpp"
namespace ESM
{
template<std::size_t len>
constexpr unsigned int fourCC(const char(&name)[len]) {
static_assert(len == 5, "Constant must be 4 characters long. (Plus null terminator)");
return static_cast<unsigned char>(name[0]) | (static_cast<unsigned char>(name[1]) << 8) | (static_cast<unsigned char>(name[2]) << 16) | (static_cast<unsigned char>(name[3]) << 24);
}
}
namespace ESM4
{
using ESM::fourCC;