Merge ESM::RefNum and ESM4::FormId

depth-refraction
Petr Mikheev 2 years ago
parent 2365ba2ce0
commit f09a689a4f

@ -340,7 +340,7 @@ void CSMDoc::WriteCellCollectionStage::writeReferences(
char ignore;
istream >> ignore >> moved.mTarget[0] >> moved.mTarget[1];
refRecord.mRefNum.save(writer, false, "MVRF");
writer.writeFormId(refRecord.mRefNum, false, "MVRF");
writer.writeHNT("CNDT", moved.mTarget);
}

@ -55,7 +55,7 @@ namespace MWLua
static void saveEvent(ESM::ESMWriter& esm, const ESM::RefNum& dest, const Event& event)
{
esm.writeHNString("LUAE", event.mEventName);
dest.save(esm, true);
esm.writeFormId(dest, true);
if (!event.mEventData.empty())
saveLuaBinaryData(esm, event.mEventData);
}
@ -67,8 +67,7 @@ namespace MWLua
while (esm.isNextSub("LUAE"))
{
std::string name = esm.getHString();
ESM::RefNum dest;
dest.load(esm, true);
ESM::RefNum dest = esm.getFormId(true);
std::string data = loadLuaBinaryData(esm);
try
{

@ -82,15 +82,13 @@ namespace MWLua
void WorldView::load(ESM::ESMReader& esm)
{
esm.getHNT(mSimulationTime, "LUAW");
ObjectId lastAssignedId;
lastAssignedId.load(esm, true);
MWBase::Environment::get().getWorldModel()->setLastGeneratedRefNum(lastAssignedId);
MWBase::Environment::get().getWorldModel()->setLastGeneratedRefNum(esm.getFormId(true));
}
void WorldView::save(ESM::ESMWriter& esm) const
{
esm.writeHNT("LUAW", mSimulationTime);
MWBase::Environment::get().getWorldModel()->getLastGeneratedRefNum().save(esm, true);
esm.writeFormId(MWBase::Environment::get().getWorldModel()->getLastGeneratedRefNum(), true);
}
void WorldView::ObjectGroup::updateList()

@ -42,7 +42,8 @@ namespace osgViewer
namespace ESM
{
struct Cell;
struct RefNum;
struct FormId;
using RefNum = FormId;
}
namespace Terrain

@ -21,7 +21,8 @@ namespace ESM
{
class ESMWriter;
class ESMReader;
struct RefNum;
struct FormId;
using RefNum = FormId;
}
namespace Loading

@ -25,7 +25,7 @@ namespace MWWorld
const ESM::RefNum& CellRef::getRefNum() const
{
return std::visit(ESM::VisitOverload{
[&](const ESM4::Reference& /*ref*/) -> const ESM::RefNum& { return emptyRefNum; },
[&](const ESM4::Reference& ref) -> const ESM::RefNum& { return ref.mFormId; },
[&](const ESM::CellRef& ref) -> const ESM::RefNum& { return ref.mRefNum; },
},
mCellRef.mVariant);
@ -33,36 +33,33 @@ namespace MWWorld
const ESM::RefNum& CellRef::getOrAssignRefNum(ESM::RefNum& lastAssignedRefNum)
{
auto esm3Visit = [&](ESM::CellRef& ref) -> const ESM::RefNum& {
if (!ref.mRefNum.isSet())
ESM::RefNum& refNum = std::visit(ESM::VisitOverload{
[&](ESM4::Reference& ref) -> ESM::RefNum& { return ref.mFormId; },
[&](ESM::CellRef& ref) -> ESM::RefNum& { return ref.mRefNum; },
},
mCellRef.mVariant);
if (!refNum.isSet())
{
// Generated RefNums have negative mContentFile
assert(lastAssignedRefNum.mContentFile < 0);
lastAssignedRefNum.mIndex++;
if (lastAssignedRefNum.mIndex == 0) // mIndex overflow, so mContentFile should be changed
{
// Generated RefNums have negative mContentFile
assert(lastAssignedRefNum.mContentFile < 0);
lastAssignedRefNum.mIndex++;
if (lastAssignedRefNum.mIndex == 0) // mIndex overflow, so mContentFile should be changed
{
if (lastAssignedRefNum.mContentFile > std::numeric_limits<int32_t>::min())
lastAssignedRefNum.mContentFile--;
else
Log(Debug::Error) << "RefNum counter overflow in CellRef::getOrAssignRefNum";
}
ref.mRefNum = lastAssignedRefNum;
mChanged = true;
if (lastAssignedRefNum.mContentFile > std::numeric_limits<int32_t>::min())
lastAssignedRefNum.mContentFile--;
else
Log(Debug::Error) << "RefNum counter overflow in CellRef::getOrAssignRefNum";
}
return ref.mRefNum;
};
return std::visit(
ESM::VisitOverload{
[&](ESM4::Reference& /*ref*/) -> const ESM::RefNum& { return emptyRefNum; },
esm3Visit,
},
mCellRef.mVariant);
refNum = lastAssignedRefNum;
mChanged = true;
}
return refNum;
}
void CellRef::unsetRefNum()
{
std::visit(ESM::VisitOverload{
[&](ESM4::Reference& /*ref*/) {},
[&](ESM4::Reference& ref) { ref.mFormId = emptyRefNum; },
[&](ESM::CellRef& ref) { ref.mRefNum = emptyRefNum; },
},
mCellRef.mVariant);

@ -983,7 +983,7 @@ namespace MWWorld
ESM::RefNum refNum = base->mRef.getRefNum();
ESM::RefId movedTo = store->getCell()->getId();
refNum.save(writer, true, "MVRF");
writer.writeFormId(refNum, true, "MVRF");
writer.writeCellId(movedTo);
}
}
@ -1039,8 +1039,7 @@ namespace MWWorld
while (reader.isNextSub("MVRF"))
{
reader.cacheSubName();
ESM::RefNum refnum;
refnum.load(reader, true, "MVRF");
ESM::RefNum refnum = reader.getFormId(true, "MVRF");
ESM::RefId movedToId = reader.getCellId();
if (refnum.hasContentFile())
{

@ -27,7 +27,8 @@ namespace ESM
class ReadersCache;
struct Cell;
struct CellState;
struct RefNum;
struct FormId;
using RefNum = FormId;
struct Activator;
struct Potion;
struct Apparatus;

@ -9,6 +9,7 @@
#include <components/esm4/reader.hpp>
#include <components/files/conversion.hpp>
#include <components/files/openfile.hpp>
#include <components/misc/strings/lower.hpp>
#include <components/resource/resourcesystem.hpp>
#include "../mwbase/environment.hpp"
@ -66,10 +67,13 @@ namespace MWWorld
ESM4::Reader readerESM4(
std::move(stream), filepath, MWBase::Environment::get().getResourceSystem()->getVFS());
readerESM4.setEncoder(mReaders.getStatelessEncoder());
readerESM4.setModIndex(index);
readerESM4.updateModIndices(mNameToIndex);
mStore.loadESM4(readerESM4);
break;
}
}
mNameToIndex[Misc::StringUtils::lowerCase(Files::pathToUnicodeString(filepath.filename()))] = index;
}
} /* namespace MWWorld */

@ -1,6 +1,7 @@
#ifndef ESMLOADER_HPP
#define ESMLOADER_HPP
#include <map>
#include <optional>
#include <vector>
@ -38,6 +39,7 @@ namespace MWWorld
ESM::Dialogue* mDialogue;
std::optional<int> mMasterFileFormat;
std::vector<int>& mESMVersions;
std::map<std::string, int> mNameToIndex;
};
} /* namespace MWWorld */

@ -2848,8 +2848,9 @@ namespace MWWorld
{
foundCell = findInteriorPosition(cellName, pos);
}
catch (std::exception&)
catch (std::exception& e)
{
Log(Debug::Error) << e.what();
}
if (foundCell.empty())
{

@ -18,7 +18,6 @@ namespace ESM
class ESMWriter;
class ReadersCache;
struct Cell;
struct RefNum;
}
namespace ESM4

@ -26,7 +26,7 @@ namespace ESM
TEST(ESMRefIdTest, formIdRefIdIsNotEmpty)
{
const RefId refId = RefId::formIdRefId(42);
const RefId refId = RefId::formIdRefId({ 42, 0 });
EXPECT_FALSE(refId.empty());
}
@ -53,7 +53,7 @@ namespace ESM
TEST(ESMRefIdTest, defaultConstructedIsNotEqualToFormIdRefId)
{
const RefId a;
const RefId b = RefId::formIdRefId(42);
const RefId b = RefId::formIdRefId({ 42, 0 });
EXPECT_NE(a, b);
}
@ -98,8 +98,8 @@ namespace ESM
TEST(ESMRefIdTest, equalityIsDefinedForFormRefIdAndRefId)
{
const FormIdRefId formIdRefId(42);
const RefId refId = RefId::formIdRefId(42);
const FormIdRefId formIdRefId({ 42, 0 });
const RefId refId = RefId::formIdRefId({ 42, 0 });
EXPECT_EQ(formIdRefId, refId);
}
@ -125,8 +125,8 @@ namespace ESM
TEST(ESMRefIdTest, lessThanIsDefinedForFormRefIdAndRefId)
{
const FormIdRefId formIdRefId(13);
const RefId refId = RefId::formIdRefId(42);
const FormIdRefId formIdRefId({ 13, 0 });
const RefId refId = RefId::formIdRefId({ 42, 0 });
EXPECT_LT(formIdRefId, refId);
}
@ -164,14 +164,14 @@ namespace ESM
TEST(ESMRefIdTest, stringRefIdHasStrongOrderWithFormId)
{
const RefId stringRefId = RefId::stringRefId("a");
const RefId formIdRefId = RefId::formIdRefId(42);
const RefId formIdRefId = RefId::formIdRefId({ 42, 0 });
EXPECT_TRUE(stringRefId < formIdRefId);
EXPECT_FALSE(formIdRefId < stringRefId);
}
TEST(ESMRefIdTest, formIdRefIdHasStrongOrderWithStringView)
{
const RefId formIdRefId = RefId::formIdRefId(42);
const RefId formIdRefId = RefId::formIdRefId({ 42, 0 });
const std::string_view stringView = "42";
EXPECT_TRUE(stringView < formIdRefId);
EXPECT_FALSE(formIdRefId < stringView);
@ -192,7 +192,7 @@ namespace ESM
TEST(ESMRefIdTest, stringRefIdIsNotEqualToFormId)
{
const RefId stringRefId = RefId::stringRefId("\0");
const RefId formIdRefId = RefId::formIdRefId(0);
const RefId formIdRefId = RefId::formIdRefId({ 0, 0 });
EXPECT_NE(stringRefId, formIdRefId);
}
@ -235,7 +235,7 @@ namespace ESM
{ RefId(), std::string() },
{ RefId::stringRefId("foo"), "foo" },
{ RefId::stringRefId(std::string({ 'a', 0, -1, '\n', '\t' })), { 'a', 0, -1, '\n', '\t' } },
{ RefId::formIdRefId(42), "0x2a" },
{ RefId::formIdRefId({ 42, 0 }), "0x2a" },
{ RefId::generated(42), "0x2a" },
{ RefId::index(REC_ARMO, 42), "ARMO:0x2a" },
{ RefId::esm3ExteriorCell(-13, 42), "-13:42" },
@ -268,7 +268,7 @@ namespace ESM
{ RefId::stringRefId("foo"), "\"foo\"" },
{ RefId::stringRefId("BAR"), "\"BAR\"" },
{ RefId::stringRefId(std::string({ 'a', 0, -1, '\n', '\t' })), "\"a\\x0\\xFF\\xA\\x9\"" },
{ RefId::formIdRefId(42), "FormId:0x2a" },
{ RefId::formIdRefId({ 42, 0 }), "FormId:0x2a" },
{ RefId::generated(42), "Generated:0x2a" },
{ RefId::index(REC_ARMO, 42), "Index:ARMO:0x2a" },
{ RefId::esm3ExteriorCell(-13, 42), "Esm3ExteriorCell:-13:42" },
@ -295,10 +295,11 @@ namespace ESM
{ RefId::stringRefId("foo"), "foo" },
{ RefId::stringRefId("BAR"), "bar" },
{ RefId::stringRefId(std::string({ 'a', 0, -1, '\n', '\t' })), { 'a', 0, -1, '\n', '\t' } },
{ RefId::formIdRefId(0), "FormId:0x0" },
{ RefId::formIdRefId(1), "FormId:0x1" },
{ RefId::formIdRefId(0x1f), "FormId:0x1f" },
{ RefId::formIdRefId(std::numeric_limits<ESM4::FormId>::max()), "FormId:0xffffffff" },
{ RefId::formIdRefId({ 0, 0 }), "FormId:0x0" },
{ RefId::formIdRefId({ 1, 0 }), "FormId:0x1" },
{ RefId::formIdRefId({ 0x1f, 0 }), "FormId:0x1f" },
{ RefId::formIdRefId({ 0x1f, 2 }), "FormId:0x200001f" },
{ RefId::formIdRefId({ 0xffffff, 0x1abc }), "FormId:0x1abcffffff" },
{ RefId::generated(0), "Generated:0x0" },
{ RefId::generated(1), "Generated:0x1" },
{ RefId::generated(0x1f), "Generated:0x1f" },
@ -344,7 +345,7 @@ namespace ESM
template <>
struct GenerateRefId<FormIdRefId>
{
static RefId call() { return RefId::formIdRefId(42); }
static RefId call() { return RefId::formIdRefId({ 42, 0 }); }
};
template <>

@ -76,7 +76,7 @@ namespace ESM
const std::vector<std::pair<RefId, std::size_t>> refIdSizes = {
{ RefId(), 57 },
{ RefId::stringRefId(std::string(32, 'a')), 89 },
{ RefId::formIdRefId(0x1f), 61 },
{ RefId::formIdRefId({ 0x1f, 0 }), 65 },
{ RefId::generated(0x1f), 65 },
{ RefId::index(REC_INGR, 0x1f), 65 },
{ RefId::esm3ExteriorCell(-42, 42), 65 },

@ -86,6 +86,7 @@ add_component_dir (to_utf8
)
add_component_dir(esm attr common defs esmcommon records util luascripts format refid esmbridge
formid
formidrefid
stringrefid
generatedrefid

@ -0,0 +1,15 @@
#include "formid.hpp"
std::string ESM::FormId::toString() const
{
return std::to_string(mIndex) + "_" + std::to_string(mContentFile);
}
uint32_t ESM::FormId::toUint32() const
{
if (isSet() && !hasContentFile())
throw std::runtime_error("Generated FormId can not be converted to 32bit format");
if (mContentFile > 0xfe)
throw std::runtime_error("FormId with mContentFile > 0xFE can not be converted to 32bit format");
return (mIndex & 0xffffff) | ((hasContentFile() ? mContentFile : 0xff) << 24);
}

@ -0,0 +1,63 @@
#ifndef COMPONENT_ESM_FORMID_H
#define COMPONENT_ESM_FORMID_H
#include <cstdint>
#include <cstring>
#include <ostream>
#include <string>
#include <tuple>
namespace ESM
{
using FormId32 = uint32_t;
struct FormId
{
uint32_t mIndex = 0;
int32_t mContentFile = -1;
bool hasContentFile() const { return mContentFile >= 0; }
bool isSet() const { return mIndex != 0 || mContentFile != -1; }
// Used in ESM4 as a null reference
bool isZero() const { return mIndex == 0 && mContentFile == 0; }
std::string toString() const;
FormId32 toUint32() const;
static FormId fromUint32(FormId32 v) { return { v & 0xffffff, static_cast<int32_t>(v >> 24) }; }
};
inline constexpr bool operator==(const FormId& left, const FormId& right)
{
return left.mIndex == right.mIndex && left.mContentFile == right.mContentFile;
}
inline constexpr bool operator<(const FormId& left, const FormId& right)
{
return std::tie(left.mIndex, left.mContentFile) < std::tie(right.mIndex, right.mContentFile);
}
inline std::ostream& operator<<(std::ostream& stream, const FormId& formId)
{
return stream << formId.toString();
}
}
namespace std
{
// Needed to use ESM::FormId as a key in std::unordered_map
template <>
struct hash<ESM::FormId>
{
size_t operator()(const ESM::FormId& formId) const
{
static_assert(sizeof(ESM::FormId) == sizeof(size_t));
size_t s;
memcpy(&s, &formId, sizeof(size_t));
return hash<size_t>()(s);
}
};
}
#endif // COMPONENT_ESM_FORMID_H

@ -1,23 +1,28 @@
#include "formidrefid.hpp"
#include "serializerefid.hpp"
#include <cassert>
#include <ostream>
#include "serializerefid.hpp"
namespace ESM
{
std::string FormIdRefId::toString() const
{
std::string result;
result.resize(getHexIntegralSize(mValue) + 2, '\0');
serializeHexIntegral(mValue, 0, result);
assert((mValue.mIndex & 0xff000000) == 0);
size_t v = (static_cast<size_t>(mValue.mContentFile) << 24) | mValue.mIndex;
result.resize(getHexIntegralSize(v) + 2, '\0');
serializeHexIntegral(v, 0, result);
return result;
}
std::string FormIdRefId::toDebugString() const
{
std::string result;
serializeRefIdValue(mValue, formIdRefIdPrefix, result);
assert((mValue.mIndex & 0xff000000) == 0);
size_t v = (static_cast<size_t>(mValue.mContentFile) << 24) | mValue.mIndex;
serializeRefIdValue(v, formIdRefIdPrefix, result);
return result;
}

@ -4,7 +4,7 @@
#include <functional>
#include <iosfwd>
#include <components/esm4/formid.hpp>
#include <components/esm/formid.hpp>
namespace ESM
{
@ -13,12 +13,12 @@ namespace ESM
public:
constexpr FormIdRefId() = default;
constexpr explicit FormIdRefId(ESM4::FormId value) noexcept
constexpr explicit FormIdRefId(ESM::FormId value) noexcept
: mValue(value)
{
}
ESM4::FormId getValue() const { return mValue; }
ESM::FormId getValue() const { return mValue; }
std::string toString() const;
@ -33,7 +33,7 @@ namespace ESM
friend struct std::hash<FormIdRefId>;
private:
ESM4::FormId mValue = 0;
ESM::FormId mValue;
};
}
@ -42,10 +42,7 @@ namespace std
template <>
struct hash<ESM::FormIdRefId>
{
std::size_t operator()(ESM::FormIdRefId value) const noexcept
{
return std::hash<ESM4::FormId>{}(value.mValue);
}
std::size_t operator()(ESM::FormIdRefId value) const noexcept { return std::hash<ESM::FormId>{}(value.mValue); }
};
}

@ -225,7 +225,12 @@ namespace ESM
return ESM::RefId();
if (value.starts_with(formIdRefIdPrefix))
return ESM::RefId::formIdRefId(deserializeHexIntegral<ESM4::FormId>(formIdRefIdPrefix.size(), value));
{
uint64_t v = deserializeHexIntegral<uint64_t>(formIdRefIdPrefix.size(), value);
uint32_t index = static_cast<uint32_t>(v) & 0xffffff;
int contentFile = static_cast<int>(v >> 24);
return ESM::RefId::formIdRefId({ index, contentFile });
}
if (value.starts_with(generatedRefIdPrefix))
return ESM::RefId::generated(deserializeHexIntegral<std::uint64_t>(generatedRefIdPrefix.size(), value));

@ -62,8 +62,8 @@ namespace ESM
// Constructs RefId from a string using a pointer to a static set of strings.
static RefId stringRefId(std::string_view value);
// Constructs RefId from ESM4 FormId storing the value in-place.
static RefId formIdRefId(ESM4::FormId value) noexcept { return RefId(FormIdRefId(value)); }
// Constructs RefId from FormId storing the value in-place.
static RefId formIdRefId(FormId value) noexcept { return RefId(FormIdRefId(value)); }
// Constructs RefId from uint64 storing the value in-place. Should be used for generated records where id is a
// global counter.

@ -17,7 +17,7 @@ namespace ESM
esm.writeHNString("DISP", params.mDisplayName);
esm.writeHNT("TYPE", params.mType);
if (params.mItem.isSet())
params.mItem.save(esm, true, "ITEM");
esm.writeFormId(params.mItem, true, "ITEM");
if (params.mWorsenings >= 0)
{
esm.writeHNT("WORS", params.mWorsenings);
@ -56,7 +56,7 @@ namespace ESM
{
esm.getHNT(params.mType, "TYPE");
if (esm.peekNextSub("ITEM"))
params.mItem.load(esm, true, "ITEM");
params.mItem = esm.getFormId(true, "ITEM");
}
if (esm.isNextSub("WORS"))
{

@ -24,7 +24,7 @@ namespace ESM
if constexpr (load)
{
cellRef.blank();
cellRef.mRefNum.load(esm, wideRefNum);
cellRef.mRefNum = esm.getFormId(wideRefNum);
cellRef.mRefID = esm.getHNORefId("NAME");
if (cellRef.mRefID.empty())
@ -33,7 +33,7 @@ namespace ESM
}
else
{
RefNum{}.load(esm, wideRefNum);
esm.getFormId(wideRefNum);
esm.skipHNORefId("NAME");
}
}
@ -154,32 +154,6 @@ namespace ESM
}
}
void RefNum::load(ESMReader& esm, bool wide, NAME tag)
{
if (wide)
esm.getHNTSized<8>(*this, tag);
else
esm.getHNT(mIndex, tag);
}
void RefNum::save(ESMWriter& esm, bool wide, NAME tag) const
{
if (wide)
esm.writeHNT(tag, *this, 8);
else
{
if (isSet() && !hasContentFile())
throw std::runtime_error("Generated RefNum can not be saved in 32bit format");
int refNum = (mIndex & 0xffffff) | ((hasContentFile() ? mContentFile : 0xff) << 24);
esm.writeHNT(tag, refNum, 4);
}
}
std::string RefNum::toString() const
{
return std::to_string(mIndex) + "_" + std::to_string(mContentFile);
}
void CellRef::load(ESMReader& esm, bool& isDeleted, bool wideRefNum)
{
loadId(esm, wideRefNum);
@ -198,7 +172,7 @@ namespace ESM
void CellRef::save(ESMWriter& esm, bool wideRefNum, bool inInventory, bool isDeleted) const
{
mRefNum.save(esm, wideRefNum);
esm.writeFormId(mRefNum, wideRefNum);
esm.writeHNCRefId("NAME", mRefID);

@ -4,6 +4,7 @@
#include <limits>
#include <string>
#include "components/esm/common.hpp"
#include "components/esm/defs.hpp"
#include "components/esm/esmcommon.hpp"
#include "components/esm/refid.hpp"
@ -15,21 +16,7 @@ namespace ESM
const int UnbreakableLock = std::numeric_limits<int>::max();
struct RefNum
{
unsigned int mIndex = 0;
int mContentFile = -1;
void load(ESMReader& esm, bool wide = false, NAME tag = "FRMR");
void save(ESMWriter& esm, bool wide = false, NAME tag = "FRMR") const;
inline bool hasContentFile() const { return mContentFile >= 0; }
inline bool isSet() const { return mIndex != 0 || mContentFile != -1; }
std::string toString() const;
};
using RefNum = ESM::FormId;
/* Cell reference. This represents ONE object (of many) inside the
cell. The cell references are not loaded as part of the normal
@ -119,39 +106,6 @@ namespace ESM
};
void skipLoadCellRef(ESMReader& esm, bool wideRefNum = false);
inline bool operator==(const RefNum& left, const RefNum& right)
{
return left.mIndex == right.mIndex && left.mContentFile == right.mContentFile;
}
inline bool operator<(const RefNum& left, const RefNum& right)
{
if (left.mIndex < right.mIndex)
return true;
if (left.mIndex > right.mIndex)
return false;
return left.mContentFile < right.mContentFile;
}
}
namespace std
{
// Needed to use ESM::RefNum as a key in std::unordered_map
template <>
struct hash<ESM::RefNum>
{
size_t operator()(const ESM::RefNum& refNum) const
{
assert(sizeof(ESM::RefNum) == sizeof(size_t));
size_t s;
memcpy(&s, &refNum, sizeof(size_t));
return hash<size_t>()(s);
}
};
}
#endif

@ -248,6 +248,16 @@ namespace ESM
getHExact(p, size);
}
FormId ESMReader::getFormId(bool wide, NAME tag)
{
FormId res;
if (wide)
getHNTSized<8>(res, tag);
else
getHNT(res.mIndex, tag);
return res;
}
// Get the next subrecord name and check if it matches the parameter
void ESMReader::getSubNameIs(NAME name)
{
@ -473,7 +483,7 @@ namespace ESM
return RefId::stringRefId(getStringView(size - sizeof(refIdType)));
case RefIdType::FormId:
{
ESM4::FormId formId{};
FormId formId{};
getT(formId);
return RefId::formIdRefId(formId);
}

@ -195,6 +195,8 @@ namespace ESM
// Read the given number of bytes from a named subrecord
void getHNExact(void* p, int size, NAME name);
ESM::FormId getFormId(bool wide = false, NAME tag = "FRMR");
/*************************************************************************
*
* Low level sub-record methods

@ -340,6 +340,14 @@ namespace ESM
mStream->write(data, size);
}
void ESMWriter::writeFormId(const FormId& formId, bool wide, NAME tag)
{
if (wide)
writeHNT(tag, formId, 8);
else
writeHNT(tag, formId.toUint32(), 4);
}
void ESMWriter::setEncoder(ToUTF8::Utf8Encoder* encoder)
{
mEncoder = encoder;

@ -179,6 +179,8 @@ namespace ESM
void write(const char* data, size_t size);
void writeFormId(const ESM::FormId&, bool wide = false, NAME tag = "FRMR");
private:
std::list<RecordData> mRecords;
std::ostream* mStream;

@ -18,7 +18,7 @@ namespace ESM
mTargetRef = RefNum{};
mTargetId = esm.getHNORefId("TARG");
if (esm.peekNextSub("FRMR"))
mTargetRef.load(esm, true, "FRMR");
mTargetRef = esm.getFormId(true, "FRMR");
}
void GlobalScript::save(ESMWriter& esm) const
@ -34,7 +34,7 @@ namespace ESM
{
esm.writeHNORefId("TARG", mTargetId);
if (mTargetRef.isSet())
mTargetRef.save(esm, true, "FRMR");
esm.writeFormId(mTargetRef, true, "FRMR");
}
}

@ -109,7 +109,7 @@ namespace ESM4
struct ActorFaction
{
FormId faction;
FormId32 faction;
std::int8_t rank;
std::uint8_t unknown1;
std::uint8_t unknown2;

@ -27,18 +27,14 @@
#ifndef OPENMW_COMPONENTS_ESM4_CELLGRID_H
#define OPENMW_COMPONENTS_ESM4_CELLGRID_H
#include <cstdint>
#include <variant>
#include "formid.hpp"
#include "grid.hpp"
namespace ESM4
{
union CellGrid
{
FormId cellId;
Grid grid;
};
using CellGrid = std::variant<ESM::FormId, Grid>;
}
#endif // OPENMW_COMPONENTS_ESM4_CELLGRID_H

@ -42,7 +42,7 @@ namespace ESM4
struct ScriptEffect
{
FormId formId; // Script effect (Magic effect must be SEFF)
FormId32 formId; // Script effect (Magic effect must be SEFF)
std::int32_t school; // Magic school. See Magic schools for more information.
EFI_Label visualEffect; // Visual effect name or 0x00000000 if None
std::uint8_t flags; // 0x01 = Hostile

@ -22,56 +22,20 @@
*/
#include "formid.hpp"
#include <charconv>
#include <stdexcept>
#include <string>
#include <system_error>
namespace ESM4
{
void formIdToString(FormId formId, std::string& str)
std::string formIdToString(const FormId& formId)
{
std::string str;
char buf[8 + 1];
int res = snprintf(buf, 8 + 1, "%08X", formId);
int res = snprintf(buf, 8 + 1, "%08X", formId.toUint32());
if (res > 0 && res < 8 + 1)
str.assign(buf);
else
throw std::runtime_error("Possible buffer overflow while converting formId");
}
std::string formIdToString(FormId formId)
{
std::string str;
formIdToString(formId, str);
return str;
}
bool isFormId(const std::string& str, FormId* id)
{
if (str.size() != 8)
return false;
unsigned long value = 0;
if (auto [_ptr, ec] = std::from_chars(str.data(), str.data() + str.size(), value, 16); ec != std::errc())
return false;
if (id != nullptr)
*id = static_cast<FormId>(value);
return true;
}
FormId stringToFormId(const std::string& str)
{
if (str.size() != 8)
throw std::out_of_range("StringToFormId: incorrect string size");
unsigned long value = 0;
if (auto [_ptr, ec] = std::from_chars(str.data(), str.data() + str.size(), value, 16); ec != std::errc())
throw std::invalid_argument("StringToFormId: string not a valid hexadecimal number");
return static_cast<FormId>(value);
}
}

@ -23,20 +23,15 @@
#ifndef ESM4_FORMID_H
#define ESM4_FORMID_H
#include <cstdint>
#include <string>
#include <components/esm/formid.hpp>
namespace ESM4
{
typedef std::uint32_t FormId;
void formIdToString(FormId formId, std::string& str);
std::string formIdToString(FormId formId);
bool isFormId(const std::string& str, FormId* id = nullptr);
FormId stringToFormId(const std::string& str);
using FormId = ESM::FormId;
using FormId32 = uint32_t;
std::string formIdToString(const FormId& formId);
}
#endif // ESM4_FORMID_H

@ -39,14 +39,14 @@ namespace ESM4
{
std::int16_t level;
std::uint16_t unknown; // sometimes missing
FormId item;
FormId32 item;
std::int16_t count;
std::uint16_t unknown2; // sometimes missing
};
struct InventoryItem // NPC_, CREA, CONT
{
FormId item;
FormId32 item;
std::uint32_t count;
};
#pragma pack(pop)

@ -34,7 +34,7 @@
void ESM4::ActorCharacter::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mFlags = reader.hdr().record.flags;
mParent = reader.currCell(); // NOTE: only for persistent achr? (aren't they all persistent?)
@ -64,8 +64,8 @@ void ESM4::ActorCharacter::load(ESM4::Reader& reader)
break;
case ESM4::SUB_XESP:
{
reader.get(mEsp);
reader.adjustFormId(mEsp.parent);
reader.getFormId(mEsp.parent);
reader.get(mEsp.flags);
break;
}
case ESM4::SUB_XRGD: // ragdoll

@ -34,7 +34,7 @@
void ESM4::ActorCreature::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mFlags = reader.hdr().record.flags;
@ -57,8 +57,8 @@ void ESM4::ActorCreature::load(ESM4::Reader& reader)
break;
case ESM4::SUB_XESP:
{
reader.get(mEsp);
reader.adjustFormId(mEsp.parent);
reader.getFormId(mEsp.parent);
reader.get(mEsp.flags);
break;
}
case ESM4::SUB_XOWN:

@ -34,7 +34,7 @@
void ESM4::Activator::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mFlags = reader.hdr().record.flags;

@ -35,7 +35,7 @@
void ESM4::Potion::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mFlags = reader.hdr().record.flags;

@ -49,9 +49,9 @@ namespace ESM4
{
std::int32_t value;
std::uint32_t flags;
FormId withdrawl;
FormId32 withdrawl;
float chanceAddition;
FormId sound;
FormId32 sound;
};
#pragma pack(pop)

@ -38,7 +38,7 @@
void ESM4::MediaLocationController::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mFlags = reader.hdr().record.flags;

@ -33,7 +33,7 @@
void ESM4::Ammunition::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mFlags = reader.hdr().record.flags;

@ -33,7 +33,7 @@
void ESM4::AnimObject::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mFlags = reader.hdr().record.flags;

@ -33,7 +33,7 @@
void ESM4::Apparatus::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mFlags = reader.hdr().record.flags;

@ -34,7 +34,7 @@
void ESM4::ArmorAddon::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mFlags = reader.hdr().record.flags;

@ -34,7 +34,7 @@
void ESM4::Armor::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mFlags = reader.hdr().record.flags;
std::uint32_t esmVer = reader.esmVersion();

@ -34,7 +34,7 @@
void ESM4::AcousticSpace::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mFlags = reader.hdr().record.flags;

@ -33,7 +33,7 @@
void ESM4::Book::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mFlags = reader.hdr().record.flags;
// std::uint32_t esmVer = reader.esmVersion(); // currently unused

@ -46,7 +46,7 @@ void ESM4::BodyPartData::BodyPart::clear()
void ESM4::BodyPartData::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mFlags = reader.hdr().record.flags;

@ -66,14 +66,14 @@ namespace ESM4
std::uint8_t explExplosionChance; // %
std::uint16_t explDebrisCount;
FormId explDebris;
FormId explExplosion;
FormId32 explDebris;
FormId32 explExplosion;
float trackingMaxAngle;
float explDebrisScale;
std::int32_t sevDebrisCount;
FormId sevDebris;
FormId sevExplosion;
FormId32 sevDebris;
FormId32 sevExplosion;
float sevDebrisScale;
// Struct - Gore Effects Positioning
@ -84,8 +84,8 @@ namespace ESM4
float rotY;
float rotZ;
FormId sevImpactDataSet;
FormId explImpactDataSet;
FormId32 sevImpactDataSet;
FormId32 explImpactDataSet;
uint8_t sevDecalCount;
uint8_t explDecalCount;
uint16_t Unknown;

@ -50,7 +50,7 @@
// longer/shorter/same as loading the subrecords.
void ESM4::Cell::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mId = ESM::RefId::formIdRefId(mFormId);
mFlags = reader.hdr().record.flags;
@ -66,8 +66,7 @@ void ESM4::Cell::load(ESM4::Reader& reader)
&& reader.grp().label.grid[0] == 0)
{
ESM4::CellGrid currCellGrid;
currCellGrid.grid.x = 0;
currCellGrid.grid.y = 0;
currCellGrid = Grid{ 0, 0 };
reader.setCurrCellGrid(currCellGrid); // side effect: sets mCellGridValid true
}
@ -123,10 +122,7 @@ void ESM4::Cell::load(ESM4::Reader& reader)
// Remember cell grid for later (loading LAND, NAVM which should be CELL temporary children)
// Note that grids only apply for external cells. For interior cells use the cell's formid.
ESM4::CellGrid currCell;
currCell.grid.x = (int16_t)mX;
currCell.grid.y = (int16_t)mY;
reader.setCurrCellGrid(currCell);
reader.setCurrCellGrid(Grid{ static_cast<int16_t>(mX), static_cast<int16_t>(mY) });
break;
}
@ -156,7 +152,7 @@ void ESM4::Cell::load(ESM4::Reader& reader)
}
case ESM4::SUB_XCLR: // for exterior cells
{
mRegions.resize(subHdr.dataSize / sizeof(FormId));
mRegions.resize(subHdr.dataSize / sizeof(FormId32));
for (std::vector<FormId>::iterator it = mRegions.begin(); it != mRegions.end(); ++it)
{
reader.getFormId(*it);

@ -44,7 +44,6 @@ namespace ESM4
class Writer;
struct ReaderContext;
struct CellGroup;
typedef std::uint32_t FormId;
enum CellFlags // TES4 TES5
{ // ----------------------- ------------------------------------

@ -39,7 +39,7 @@
void ESM4::Class::load(ESM4::Reader& reader)
{
// mFormId = reader.adjustFormId(reader.hdr().record.id); // FIXME: use master adjusted?
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
mFlags = reader.hdr().record.flags;
while (reader.getSubRecordHeader())

@ -34,7 +34,7 @@
void ESM4::Colour::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mFlags = reader.hdr().record.flags;

@ -34,7 +34,7 @@
void ESM4::Clothing::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mFlags = reader.hdr().record.flags;

@ -33,7 +33,7 @@
void ESM4::Container::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mFlags = reader.hdr().record.flags;

@ -42,7 +42,7 @@
void ESM4::Creature::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mFlags = reader.hdr().record.flags;

@ -35,7 +35,7 @@
void ESM4::Dialogue::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mFlags = reader.hdr().record.flags;

@ -39,7 +39,7 @@
void ESM4::DefaultObj::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mFlags = reader.hdr().record.flags;

@ -33,7 +33,7 @@
void ESM4::Door::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mFlags = reader.hdr().record.flags;

@ -33,7 +33,7 @@
void ESM4::Eyes::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mFlags = reader.hdr().record.flags;

@ -33,7 +33,7 @@
void ESM4::Flora::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mFlags = reader.hdr().record.flags;

@ -34,7 +34,7 @@
void ESM4::FormIdList::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mFlags = reader.hdr().record.flags;

@ -33,7 +33,7 @@
void ESM4::Furniture::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mFlags = reader.hdr().record.flags;

@ -34,7 +34,7 @@
void ESM4::GlobalVariable::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mFlags = reader.hdr().record.flags;

@ -11,8 +11,7 @@ namespace ESM4
GameSetting::Data readData(FormId formId, std::string_view editorId, Reader& reader)
{
if (editorId.empty())
throw std::runtime_error(
"Unknown ESM4 GMST (" + std::to_string(formId) + ") data type: editor id is empty");
throw std::runtime_error("Unknown ESM4 GMST (" + formId.toString() + ") data type: editor id is empty");
const char type = editorId[0];
switch (type)
{
@ -36,14 +35,14 @@ namespace ESM4
}
default:
throw std::runtime_error(
"Unsupported ESM4 GMST (" + std::to_string(formId) + ") data type: " + std::string(editorId));
"Unsupported ESM4 GMST (" + formId.toString() + ") data type: " + std::string(editorId));
}
}
}
void GameSetting::load(Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mFlags = reader.hdr().record.flags;
@ -59,8 +58,8 @@ namespace ESM4
mData = readData(mFormId, mEditorId, reader);
break;
default:
throw std::runtime_error("Unknown ESM4 GMST (" + std::to_string(mFormId) + ") subrecord "
+ ESM::printName(subHdr.typeId));
throw std::runtime_error(
"Unknown ESM4 GMST (" + mFormId.toString() + ") subrecord " + ESM::printName(subHdr.typeId));
}
}
}

@ -33,7 +33,7 @@
void ESM4::Grass::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mFlags = reader.hdr().record.flags;

@ -34,7 +34,7 @@
void ESM4::Hair::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mFlags = reader.hdr().record.flags;

@ -35,7 +35,7 @@
void ESM4::HeadPart::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mFlags = reader.hdr().record.flags;

@ -33,7 +33,7 @@
void ESM4::IdleAnimation::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mFlags = reader.hdr().record.flags;

@ -34,7 +34,7 @@
void ESM4::IdleMarker::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mFlags = reader.hdr().record.flags;

@ -36,7 +36,7 @@
void ESM4::ItemMod::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mFlags = reader.hdr().record.flags;

@ -35,7 +35,7 @@
void ESM4::DialogInfo::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mFlags = reader.hdr().record.flags;

@ -34,7 +34,7 @@
void ESM4::Ingredient::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mFlags = reader.hdr().record.flags;

@ -33,7 +33,7 @@
void ESM4::Key::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mFlags = reader.hdr().record.flags;

@ -55,7 +55,7 @@
//
void ESM4::Land::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mFlags = reader.hdr().record.flags;
mDataTypes = 0;
@ -181,8 +181,9 @@ void ESM4::Land::load(ESM4::Reader& reader)
}
case ESM4::SUB_VTEX: // only in Oblivion?
{
int count = (int)reader.subRecordHeader().dataSize / sizeof(FormId);
assert((reader.subRecordHeader().dataSize % sizeof(FormId)) == 0 && "ESM4::LAND VTEX data size error");
int count = (int)reader.subRecordHeader().dataSize / sizeof(FormId32);
assert(
(reader.subRecordHeader().dataSize % sizeof(FormId32)) == 0 && "ESM4::LAND VTEX data size error");
if (count)
{
@ -212,7 +213,7 @@ void ESM4::Land::load(ESM4::Reader& reader)
bool missing = false;
for (int i = 0; i < 4; ++i)
{
if (mTextures[i].base.formId == 0)
if (mTextures[i].base.formId.isZero())
{
// std::cout << "ESM4::LAND " << ESM4::formIdToString(mFormId) << " missing base, quad " << i << std::endl;
// std::cout << "layers " << mTextures[i].layers.size() << std::endl;

@ -37,7 +37,7 @@
void ESM4::LightingTemplate::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mFlags = reader.hdr().record.flags;

@ -39,7 +39,6 @@ namespace ESM4
{
class Reader;
class Writer;
typedef std::uint32_t FormId;
struct LightingTemplate
{

@ -33,7 +33,7 @@
void ESM4::Light::load(ESM4::Reader& reader)
{
FormId formId = reader.hdr().record.id;
FormId formId = reader.hdr().record.getFormId();
reader.adjustFormId(formId);
mId = ESM::RefId::formIdRefId(formId);
mFlags = reader.hdr().record.flags;

@ -39,7 +39,7 @@
void ESM4::LandTexture::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mFlags = reader.hdr().record.flags;
std::uint32_t esmVer = reader.esmVersion();

@ -34,7 +34,7 @@
void ESM4::LevelledCreature::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mFlags = reader.hdr().record.flags;

@ -34,7 +34,7 @@
void ESM4::LevelledItem::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mFlags = reader.hdr().record.flags;

@ -34,7 +34,7 @@
void ESM4::LevelledNpc::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mFlags = reader.hdr().record.flags;
// std::uint32_t esmVer = reader.esmVersion(); // currently unused

@ -34,7 +34,7 @@
void ESM4::Material::load(ESM4::Reader& reader)
{
// mFormId = reader.adjustFormId(reader.hdr().record.id); // FIXME: use master adjusted?
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
mFlags = reader.hdr().record.flags;
while (reader.getSubRecordHeader())

@ -33,7 +33,7 @@
void ESM4::MiscItem::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mFlags = reader.hdr().record.flags;

@ -34,7 +34,7 @@
void ESM4::MediaSet::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mFlags = reader.hdr().record.flags;

@ -34,7 +34,7 @@
void ESM4::MovableStatic::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mFlags = reader.hdr().record.flags;

@ -38,7 +38,7 @@
void ESM4::Music::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mFlags = reader.hdr().record.flags;

@ -151,10 +151,12 @@ void ESM4::Navigation::NavMeshInfo::load(ESM4::Reader& reader)
reader.get(worldSpaceId);
// FLG_Tamriel = 0x0000003c, // grid info follows, possibly Tamriel?
// FLG_Morrowind = 0x01380000, // grid info follows, probably Skywind
if (worldSpaceId == 0x0000003c || worldSpaceId == 0x01380000)
if (worldSpaceId == FormId{ 0x3c, 0 } || worldSpaceId == FormId{ 0x380000, 1 })
{
reader.get(cellGrid.grid.y); // NOTE: reverse order
reader.get(cellGrid.grid.x);
Grid grid;
reader.get(grid.y); // NOTE: reverse order
reader.get(grid.x);
cellGrid = grid;
// FIXME: debugging only
#if 0
std::string padding;
@ -167,7 +169,9 @@ void ESM4::Navigation::NavMeshInfo::load(ESM4::Reader& reader)
}
else
{
reader.get(cellGrid.cellId);
FormId cellId;
reader.get(cellId);
cellGrid = cellId;
#if 0
if (worldSpaceId == 0) // interior
@ -237,7 +241,7 @@ void ESM4::Navigation::NavMeshInfo::load(ESM4::Reader& reader)
//
void ESM4::Navigation::load(ESM4::Reader& reader)
{
// mFormId = reader.hdr().record.id;
// mFormId = reader.hdr().record.getFormId();
// mFlags = reader.hdr().record.flags;
std::uint32_t esmVer = reader.esmVersion();
bool isFONV = esmVer == ESM::VER_132 || esmVer == ESM::VER_133 || esmVer == ESM::VER_134;
@ -312,8 +316,9 @@ void ESM4::Navigation::load(ESM4::Reader& reader)
std::cout << "node " << std::hex << node // FIXME: debugging only
<< ", index " << index << ", i " << std::dec << total+i << std::endl;
#endif
FormId nodeFormId = FormId::fromUint32(node); // should we apply reader.adjustFormId?
// std::pair<std::map<FormId, std::uint32_t>::iterator, bool> res =
mPathIndexMap.insert(std::make_pair(node, index));
mPathIndexMap.emplace(nodeFormId, index);
// FIXME: this throws if more than one file is being loaded
// if (!res.second)
// throw std::runtime_error ("node already exists in the preferred path index map");

@ -45,7 +45,7 @@ namespace ESM4
struct DoorRef
{
std::uint32_t unknown;
FormId formId;
FormId32 formId;
};
struct Triangle

@ -47,7 +47,7 @@ void ESM4::NavMesh::NVNMstruct::load(ESM4::Reader& reader)
reader.get(worldSpaceId);
// FLG_Tamriel = 0x0000003c, // grid info follows, possibly Tamriel?
// FLG_Morrowind = 0x01380000, // grid info follows, probably Skywind
if (worldSpaceId == 0x0000003c || worldSpaceId == 0x01380000)
if (worldSpaceId == FormId{ 0x3c, 0 } || worldSpaceId == FormId{ 380000, 1 })
{
// ^
// Y | X Y Index
@ -65,8 +65,10 @@ void ESM4::NavMesh::NVNMstruct::load(ESM4::Reader& reader)
//
// Formula seems to be floor(Skywind coord / 2) <cmath>
//
reader.get(cellGrid.grid.y); // NOTE: reverse order
reader.get(cellGrid.grid.x);
Grid grid;
reader.get(grid.y); // NOTE: reverse order
reader.get(grid.x);
cellGrid = grid;
// FIXME: debugging only
#if 0
std::string padding;
@ -79,7 +81,9 @@ void ESM4::NavMesh::NVNMstruct::load(ESM4::Reader& reader)
}
else
{
reader.get(cellGrid.cellId);
FormId cellId;
reader.get(cellId);
cellGrid = cellId;
#if 0
std::string padding; // FIXME
@ -186,7 +190,7 @@ void ESM4::NavMesh::NVNMstruct::load(ESM4::Reader& reader)
void ESM4::NavMesh::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
mFlags = reader.hdr().record.flags;
// std::cout << "NavMesh 0x" << std::hex << this << std::endl; // FIXME

@ -56,7 +56,7 @@ namespace ESM4
struct ExtConnection
{
std::uint32_t unknown;
FormId navMesh;
FormId32 navMesh;
std::uint16_t triangleIndex;
};
@ -64,7 +64,7 @@ namespace ESM4
{
std::uint16_t triangleIndex;
std::uint32_t unknown;
FormId doorRef;
FormId32 doorRef;
};
#pragma pack(pop)

@ -34,7 +34,7 @@
void ESM4::Note::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mFlags = reader.hdr().record.flags;

@ -42,7 +42,7 @@
void ESM4::Npc::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mFlags = reader.hdr().record.flags;

@ -34,7 +34,7 @@
void ESM4::Outfit::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mFlags = reader.hdr().record.flags;
@ -48,7 +48,7 @@ void ESM4::Outfit::load(ESM4::Reader& reader)
break;
case ESM4::SUB_INAM:
{
std::size_t numObj = subHdr.dataSize / sizeof(FormId);
std::size_t numObj = subHdr.dataSize / sizeof(FormId32);
for (std::size_t i = 0; i < numObj; ++i)
{
FormId formId;

@ -35,7 +35,7 @@
void ESM4::AIPackage::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mFlags = reader.hdr().record.flags;

@ -60,14 +60,14 @@ namespace ESM4
{
std::int32_t type = 0xff; // 0 = near ref, 1 = in cell, 2 = current loc, 3 = editor loc, 4 = obj id, 5 = obj
// type, 0xff = no location data
FormId location; // uint32_t if type = 5
FormId32 location; // uint32_t if type = 5
std::int32_t radius;
};
struct PTDT // target
{
std::int32_t type = 0xff; // 0 = specific ref, 1 = obj id, 2 = obj type, 0xff = no target data
FormId target; // uint32_t if type = 2
FormId32 target; // uint32_t if type = 2
std::int32_t distance;
};
@ -81,8 +81,8 @@ namespace ESM4
std::uint8_t unknown3; // probably padding
float compValue;
std::int32_t fnIndex;
FormId param1;
FormId param2;
FormId32 param1;
FormId32 param2;
std::uint32_t unknown4; // probably padding
};
#pragma pack(pop)

@ -36,7 +36,7 @@
void ESM4::Pathgrid::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mFlags = reader.hdr().record.flags;

@ -36,7 +36,7 @@
void ESM4::PlacedGrenade::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mFlags = reader.hdr().record.flags;

@ -36,7 +36,7 @@
void ESM4::PlaceableWater::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.id;
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
mFlags = reader.hdr().record.flags;

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save