mirror of https://github.com/OpenMW/openmw.git
Merge branch 'master' into 'sort_me_baby_one_more_time'
# Conflicts: # components/nif/niffile.cppC++20
commit
b011809056
@ -0,0 +1,159 @@
|
||||
#include <components/to_utf8/to_utf8.hpp>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#ifndef OPENMW_TEST_SUITE_SOURCE_DIR
|
||||
#define OPENMW_TEST_SUITE_SOURCE_DIR ""
|
||||
#endif
|
||||
|
||||
namespace
|
||||
{
|
||||
using namespace testing;
|
||||
using namespace ToUTF8;
|
||||
|
||||
struct Params
|
||||
{
|
||||
FromType mLegacyEncoding;
|
||||
std::string mLegacyEncodingFileName;
|
||||
std::string mUtf8FileName;
|
||||
};
|
||||
|
||||
std::string readContent(const std::string& fileName)
|
||||
{
|
||||
std::ifstream file;
|
||||
file.exceptions(std::ios::failbit | std::ios::badbit);
|
||||
file.open(std::string(OPENMW_TEST_SUITE_SOURCE_DIR) + "/toutf8/data/" + fileName);
|
||||
std::stringstream buffer;
|
||||
buffer << file.rdbuf();
|
||||
return buffer.str();
|
||||
}
|
||||
|
||||
struct Utf8EncoderTest : TestWithParam<Params> {};
|
||||
|
||||
TEST(Utf8EncoderTest, getUtf8ShouldReturnEmptyAsIs)
|
||||
{
|
||||
Utf8Encoder encoder(FromType::CP437);
|
||||
EXPECT_EQ(encoder.getUtf8(std::string_view()), std::string_view());
|
||||
}
|
||||
|
||||
TEST(Utf8EncoderTest, getUtf8ShouldReturnAsciiOnlyAsIs)
|
||||
{
|
||||
std::string input;
|
||||
for (int c = 1; c <= std::numeric_limits<char>::max(); ++c)
|
||||
input.push_back(c);
|
||||
Utf8Encoder encoder(FromType::CP437);
|
||||
const std::string_view result = encoder.getUtf8(input);
|
||||
EXPECT_EQ(result.data(), input.data());
|
||||
EXPECT_EQ(result.size(), input.size());
|
||||
}
|
||||
|
||||
TEST(Utf8EncoderTest, getUtf8ShouldLookUpUntilZero)
|
||||
{
|
||||
const std::string input("a\0b");
|
||||
Utf8Encoder encoder(FromType::CP437);
|
||||
const std::string_view result = encoder.getUtf8(input);
|
||||
EXPECT_EQ(result, "a");
|
||||
}
|
||||
|
||||
TEST(Utf8EncoderTest, getUtf8ShouldLookUpUntilEndOfInputForAscii)
|
||||
{
|
||||
const std::string input("abc");
|
||||
Utf8Encoder encoder(FromType::CP437);
|
||||
const std::string_view result = encoder.getUtf8(std::string_view(input.data(), 2));
|
||||
EXPECT_EQ(result, "ab");
|
||||
}
|
||||
|
||||
TEST(Utf8EncoderTest, getUtf8ShouldLookUpUntilEndOfInputForNonAscii)
|
||||
{
|
||||
const std::string input("a\x92" "b");
|
||||
Utf8Encoder encoder(FromType::WINDOWS_1252);
|
||||
const std::string_view result = encoder.getUtf8(std::string_view(input.data(), 2));
|
||||
EXPECT_EQ(result, "a\xE2\x80\x99");
|
||||
}
|
||||
|
||||
TEST_P(Utf8EncoderTest, getUtf8ShouldConvertFromLegacyEncodingToUtf8)
|
||||
{
|
||||
const std::string input(readContent(GetParam().mLegacyEncodingFileName));
|
||||
const std::string expected(readContent(GetParam().mUtf8FileName));
|
||||
Utf8Encoder encoder(GetParam().mLegacyEncoding);
|
||||
const std::string_view result = encoder.getUtf8(input);
|
||||
EXPECT_EQ(result, expected);
|
||||
}
|
||||
|
||||
TEST(Utf8EncoderTest, getLegacyEncShouldReturnEmptyAsIs)
|
||||
{
|
||||
Utf8Encoder encoder(FromType::CP437);
|
||||
EXPECT_EQ(encoder.getLegacyEnc(std::string_view()), std::string_view());
|
||||
}
|
||||
|
||||
TEST(Utf8EncoderTest, getLegacyEncShouldReturnAsciiOnlyAsIs)
|
||||
{
|
||||
std::string input;
|
||||
for (int c = 1; c <= std::numeric_limits<char>::max(); ++c)
|
||||
input.push_back(c);
|
||||
Utf8Encoder encoder(FromType::CP437);
|
||||
const std::string_view result = encoder.getLegacyEnc(input);
|
||||
EXPECT_EQ(result.data(), input.data());
|
||||
EXPECT_EQ(result.size(), input.size());
|
||||
}
|
||||
|
||||
TEST(Utf8EncoderTest, getLegacyEncShouldLookUpUntilZero)
|
||||
{
|
||||
const std::string input("a\0b");
|
||||
Utf8Encoder encoder(FromType::CP437);
|
||||
const std::string_view result = encoder.getLegacyEnc(input);
|
||||
EXPECT_EQ(result, "a");
|
||||
}
|
||||
|
||||
TEST(Utf8EncoderTest, getLegacyEncShouldLookUpUntilEndOfInputForAscii)
|
||||
{
|
||||
const std::string input("abc");
|
||||
Utf8Encoder encoder(FromType::CP437);
|
||||
const std::string_view result = encoder.getLegacyEnc(std::string_view(input.data(), 2));
|
||||
EXPECT_EQ(result, "ab");
|
||||
}
|
||||
|
||||
TEST(Utf8EncoderTest, getLegacyEncShouldStripIncompleteCharacters)
|
||||
{
|
||||
const std::string input("a\xc3\xa2\xe2\x80\x99");
|
||||
Utf8Encoder encoder(FromType::WINDOWS_1252);
|
||||
const std::string_view result = encoder.getLegacyEnc(std::string_view(input.data(), 5));
|
||||
EXPECT_EQ(result, "a\xe2");
|
||||
}
|
||||
|
||||
TEST_P(Utf8EncoderTest, getLegacyEncShouldConvertFromUtf8ToLegacyEncoding)
|
||||
{
|
||||
const std::string input(readContent(GetParam().mUtf8FileName));
|
||||
const std::string expected(readContent(GetParam().mLegacyEncodingFileName));
|
||||
Utf8Encoder encoder(GetParam().mLegacyEncoding);
|
||||
const std::string_view result = encoder.getLegacyEnc(input);
|
||||
EXPECT_EQ(result, expected);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(Files, Utf8EncoderTest, Values(
|
||||
Params {ToUTF8::WINDOWS_1251, "russian-win1251.txt", "russian-utf8.txt"},
|
||||
Params {ToUTF8::WINDOWS_1252, "french-win1252.txt", "french-utf8.txt"}
|
||||
));
|
||||
|
||||
TEST(StatelessUtf8EncoderTest, shouldCleanupBuffer)
|
||||
{
|
||||
std::string buffer;
|
||||
StatelessUtf8Encoder encoder(FromType::WINDOWS_1252);
|
||||
encoder.getUtf8(std::string_view("long string\x92"), BufferAllocationPolicy::UseGrowFactor, buffer);
|
||||
const std::string shortString("short\x92");
|
||||
ASSERT_GT(buffer.size(), shortString.size());
|
||||
const std::string_view shortUtf8 = encoder.getUtf8(shortString, BufferAllocationPolicy::UseGrowFactor, buffer);
|
||||
ASSERT_GE(buffer.size(), shortUtf8.size());
|
||||
EXPECT_EQ(buffer[shortUtf8.size()], '\0') << buffer;
|
||||
}
|
||||
|
||||
TEST(StatelessUtf8EncoderTest, withFitToRequiredSizeShouldResizeBuffer)
|
||||
{
|
||||
std::string buffer;
|
||||
StatelessUtf8Encoder encoder(FromType::WINDOWS_1252);
|
||||
const std::string_view utf8 = encoder.getUtf8(std::string_view("long string\x92"), BufferAllocationPolicy::FitToRequiredSize, buffer);
|
||||
EXPECT_EQ(buffer.size(), utf8.size());
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
#include "sstream"
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
std::string printName(const std::uint32_t typeId)
|
||||
{
|
||||
unsigned char typeName[4];
|
||||
typeName[0] = typeId & 0xff;
|
||||
typeName[1] = (typeId >> 8) & 0xff;
|
||||
typeName[2] = (typeId >> 16) & 0xff;
|
||||
typeName[3] = (typeId >> 24) & 0xff;
|
||||
|
||||
return std::string((char*)typeName, 4);
|
||||
}
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
#ifndef COMPONENT_ESM_COMMON_H
|
||||
#define COMPONENT_ESM_COMMON_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
#pragma pack(push, 1)
|
||||
union ESMVersion
|
||||
{
|
||||
float f;
|
||||
std::uint32_t ui;
|
||||
};
|
||||
|
||||
union TypeId
|
||||
{
|
||||
std::uint32_t value;
|
||||
char name[4]; // record type in ascii
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
enum ESMVersions
|
||||
{
|
||||
VER_120 = 0x3f99999a, // TES3
|
||||
VER_130 = 0x3fa66666, // TES3
|
||||
VER_080 = 0x3f4ccccd, // TES4
|
||||
VER_100 = 0x3f800000, // TES4
|
||||
VER_132 = 0x3fa8f5c3, // FONV Courier's Stash, DeadMoney
|
||||
VER_133 = 0x3faa3d71, // FONV HonestHearts
|
||||
VER_134 = 0x3fab851f, // FONV, GunRunnersArsenal, LonesomeRoad, OldWorldBlues
|
||||
VER_094 = 0x3f70a3d7, // TES5/FO3
|
||||
VER_170 = 0x3fd9999a // TES5
|
||||
};
|
||||
|
||||
// Defines another files (esm or esp) that this file depends upon.
|
||||
struct MasterData
|
||||
{
|
||||
std::string name;
|
||||
std::uint64_t size;
|
||||
};
|
||||
|
||||
enum VarType
|
||||
{
|
||||
VT_Unknown = 0,
|
||||
VT_None,
|
||||
VT_Short, // stored as a float, kinda
|
||||
VT_Int,
|
||||
VT_Long, // stored as a float
|
||||
VT_Float,
|
||||
VT_String
|
||||
};
|
||||
|
||||
std::string printName(const std::uint32_t typeId);
|
||||
}
|
||||
|
||||
#endif // COMPONENT_ESM_COMMON_H
|
@ -0,0 +1,86 @@
|
||||
#include "reader.hpp"
|
||||
|
||||
//#ifdef NDEBUG
|
||||
//#undef NDEBUG
|
||||
//#endif
|
||||
|
||||
#include <cassert>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <components/files/constrainedfilestream.hpp>
|
||||
|
||||
#include "components/esm3/esmreader.hpp"
|
||||
#include "components/esm4/reader.hpp"
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
Reader* Reader::getReader(const std::string &filename)
|
||||
{
|
||||
Files::IStreamPtr esmStream(Files::openConstrainedFileStream (filename.c_str ()));
|
||||
|
||||
std::uint32_t modVer = 0; // get the first 4 bytes of the record header only
|
||||
esmStream->read((char*)&modVer, sizeof(modVer));
|
||||
if (esmStream->gcount() == sizeof(modVer))
|
||||
{
|
||||
esmStream->seekg(0);
|
||||
|
||||
if (modVer == ESM4::REC_TES4)
|
||||
{
|
||||
return new ESM4::Reader(esmStream, filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
//return new ESM3::ESMReader(esmStream, filename);
|
||||
}
|
||||
}
|
||||
|
||||
throw std::runtime_error("Unknown file format");
|
||||
}
|
||||
|
||||
bool Reader::getStringImpl(std::string& str, std::size_t size,
|
||||
Files::IStreamPtr filestream, ToUTF8::StatelessUtf8Encoder* encoder, bool hasNull)
|
||||
{
|
||||
std::size_t newSize = size;
|
||||
|
||||
if (encoder)
|
||||
{
|
||||
std::string input(size, '\0');
|
||||
filestream->read(input.data(), size);
|
||||
if (filestream->gcount() == static_cast<std::streamsize>(size))
|
||||
{
|
||||
encoder->getUtf8(input, ToUTF8::BufferAllocationPolicy::FitToRequiredSize, str);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (hasNull)
|
||||
newSize -= 1; // don't read the null terminator yet
|
||||
|
||||
str.resize(newSize); // assumed C++11
|
||||
filestream->read(&str[0], newSize);
|
||||
if ((std::size_t)filestream->gcount() == newSize)
|
||||
{
|
||||
if (hasNull)
|
||||
{
|
||||
char ch;
|
||||
filestream->read(&ch, 1); // read the null terminator
|
||||
assert (ch == '\0'
|
||||
&& "ESM4::Reader::getString string is not terminated with a null");
|
||||
}
|
||||
#if 0
|
||||
else
|
||||
{
|
||||
// NOTE: normal ESMs don't but omwsave has locals or spells with null terminator
|
||||
assert (str[newSize - 1] != '\0'
|
||||
&& "ESM4::Reader::getString string is unexpectedly terminated with a null");
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
str.clear();
|
||||
return false; // FIXME: throw instead?
|
||||
}
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
#ifndef COMPONENT_ESM_READER_H
|
||||
#define COMPONENT_ESM_READER_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <components/files/constrainedfilestream.hpp>
|
||||
#include <components/to_utf8/to_utf8.hpp>
|
||||
|
||||
#include "common.hpp" // MasterData
|
||||
|
||||
namespace ToUTF8
|
||||
{
|
||||
class Utf8Encoder;
|
||||
}
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
class Reader
|
||||
{
|
||||
std::vector<Reader*>* mGlobalReaderList;
|
||||
|
||||
public:
|
||||
virtual ~Reader() {}
|
||||
|
||||
static Reader* getReader(const std::string& filename);
|
||||
|
||||
void setGlobalReaderList(std::vector<Reader*> *list) {mGlobalReaderList = list;}
|
||||
std::vector<Reader*> *getGlobalReaderList() {return mGlobalReaderList;}
|
||||
|
||||
virtual inline bool isEsm4() const = 0;
|
||||
|
||||
virtual inline bool hasMoreRecs() const = 0;
|
||||
|
||||
virtual inline void setEncoder(ToUTF8::StatelessUtf8Encoder* encoder) = 0;
|
||||
|
||||
// used to check for dependencies e.g. CS::Editor::run()
|
||||
virtual inline const std::vector<ESM::MasterData>& getGameFiles() const = 0;
|
||||
|
||||
// used by ContentSelector::ContentModel::addFiles()
|
||||
virtual inline const std::string getAuthor() const = 0;
|
||||
virtual inline const std::string getDesc() const = 0;
|
||||
virtual inline int getFormat() const = 0;
|
||||
|
||||
virtual inline std::string getFileName() const = 0;
|
||||
|
||||
// used by CSMWorld::Data::startLoading() and getTotalRecords() for loading progress bar
|
||||
virtual inline int getRecordCount() const = 0;
|
||||
|
||||
virtual void setModIndex(std::uint32_t index) = 0;
|
||||
|
||||
// used by CSMWorld::Data::getTotalRecords()
|
||||
virtual void close() = 0;
|
||||
|
||||
protected:
|
||||
bool getStringImpl(std::string& str, std::size_t size,
|
||||
Files::IStreamPtr filestream, ToUTF8::StatelessUtf8Encoder* encoder, bool hasNull = false);
|
||||
};
|
||||
}
|
||||
|
||||
#endif // COMPONENT_ESM_READER_H
|
@ -0,0 +1,70 @@
|
||||
/*
|
||||
Copyright (C) 2016, 2018, 2020 cc9cii
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
cc9cii cc9c@iinet.net.au
|
||||
|
||||
Much of the information on the data structures are based on the information
|
||||
from Tes4Mod:Mod_File_Format and Tes5Mod:File_Formats but also refined by
|
||||
trial & error. See http://en.uesp.net/wiki for details.
|
||||
|
||||
*/
|
||||
#ifndef ESM4_ACTI_H
|
||||
#define ESM4_ACTI_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include "formid.hpp"
|
||||
|
||||
namespace ESM4
|
||||
{
|
||||
class Reader;
|
||||
class Writer;
|
||||
|
||||
struct Activator
|
||||
{
|
||||
FormId mFormId; // from the header
|
||||
std::uint32_t mFlags; // from the header, see enum type RecordFlag for details
|
||||
|
||||
std::string mEditorId;
|
||||
std::string mFullName;
|
||||
std::string mModel;
|
||||
|
||||
FormId mScriptId;
|
||||
FormId mLoopingSound; // SOUN
|
||||
FormId mActivationSound; // SOUN
|
||||
|
||||
float mBoundRadius;
|
||||
|
||||
FormId mRadioTemplate; // SOUN
|
||||
FormId mRadioStation; // TACT
|
||||
|
||||
std::string mActivationPrompt;
|
||||
|
||||
Activator();
|
||||
virtual ~Activator();
|
||||
|
||||
virtual void load(ESM4::Reader& reader);
|
||||
//virtual void save(ESM4::Writer& writer) const;
|
||||
|
||||
//void blank();
|
||||
};
|
||||
}
|
||||
|
||||
#endif // ESM4_ACTI_H
|
@ -0,0 +1,163 @@
|
||||
/*
|
||||
Copyright (C) 2020 cc9cii
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
cc9cii cc9c@iinet.net.au
|
||||
|
||||
Much of the information on the data structures are based on the information
|
||||
from Tes4Mod:Mod_File_Format and Tes5Mod:File_Formats but also refined by
|
||||
trial & error. See http://en.uesp.net/wiki for details.
|
||||
|
||||
*/
|
||||
#ifndef ESM4_ACTOR_H
|
||||
#define ESM4_ACTOR_H
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "formid.hpp"
|
||||
|
||||
namespace ESM4
|
||||
{
|
||||
#pragma pack(push, 1)
|
||||
struct AIData // NPC_, CREA
|
||||
{
|
||||
std::uint8_t aggression;
|
||||
std::uint8_t confidence;
|
||||
std::uint8_t energyLevel;
|
||||
std::uint8_t responsibility;
|
||||
std::uint32_t aiFlags;
|
||||
std::uint8_t trainSkill;
|
||||
std::uint8_t trainLevel;
|
||||
std::uint16_t unknown;
|
||||
};
|
||||
|
||||
struct AttributeValues
|
||||
{
|
||||
std::uint8_t strength;
|
||||
std::uint8_t intelligence;
|
||||
std::uint8_t willpower;
|
||||
std::uint8_t agility;
|
||||
std::uint8_t speed;
|
||||
std::uint8_t endurance;
|
||||
std::uint8_t personality;
|
||||
std::uint8_t luck;
|
||||
};
|
||||
|
||||
struct ACBS_TES4
|
||||
{
|
||||
std::uint32_t flags;
|
||||
std::uint16_t baseSpell;
|
||||
std::uint16_t fatigue;
|
||||
std::uint16_t barterGold;
|
||||
std::int16_t levelOrOffset;
|
||||
std::uint16_t calcMin;
|
||||
std::uint16_t calcMax;
|
||||
std::uint32_t padding1;
|
||||
std::uint32_t padding2;
|
||||
};
|
||||
|
||||
struct ACBS_FO3
|
||||
{
|
||||
std::uint32_t flags;
|
||||
std::uint16_t fatigue;
|
||||
std::uint16_t barterGold;
|
||||
std::int16_t levelOrMult;
|
||||
std::uint16_t calcMinlevel;
|
||||
std::uint16_t calcMaxlevel;
|
||||
std::uint16_t speedMultiplier;
|
||||
float karma;
|
||||
std::int16_t dispositionBase;
|
||||
std::uint16_t templateFlags;
|
||||
};
|
||||
|
||||
struct ACBS_TES5
|
||||
{
|
||||
std::uint32_t flags;
|
||||
std::uint16_t magickaOffset;
|
||||
std::uint16_t staminaOffset;
|
||||
std::uint16_t levelOrMult; // TODO: check if int16_t
|
||||
std::uint16_t calcMinlevel;
|
||||
std::uint16_t calcMaxlevel;
|
||||
std::uint16_t speedMultiplier;
|
||||
std::uint16_t dispositionBase; // TODO: check if int16_t
|
||||
std::uint16_t templateFlags;
|
||||
std::uint16_t healthOffset;
|
||||
std::uint16_t bleedoutOverride;
|
||||
};
|
||||
|
||||
union ActorBaseConfig
|
||||
{
|
||||
ACBS_TES4 tes4;
|
||||
ACBS_FO3 fo3;
|
||||
ACBS_TES5 tes5;
|
||||
};
|
||||
|
||||
struct ActorFaction
|
||||
{
|
||||
FormId faction;
|
||||
std::int8_t rank;
|
||||
std::uint8_t unknown1;
|
||||
std::uint8_t unknown2;
|
||||
std::uint8_t unknown3;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
struct BodyTemplate // TES5
|
||||
{
|
||||
// 0x00000001 - Head
|
||||
// 0x00000002 - Hair
|
||||
// 0x00000004 - Body
|
||||
// 0x00000008 - Hands
|
||||
// 0x00000010 - Forearms
|
||||
// 0x00000020 - Amulet
|
||||
// 0x00000040 - Ring
|
||||
// 0x00000080 - Feet
|
||||
// 0x00000100 - Calves
|
||||
// 0x00000200 - Shield
|
||||
// 0x00000400 - Tail
|
||||
// 0x00000800 - Long Hair
|
||||
// 0x00001000 - Circlet
|
||||
// 0x00002000 - Ears
|
||||
// 0x00004000 - Body AddOn 3
|
||||
// 0x00008000 - Body AddOn 4
|
||||
// 0x00010000 - Body AddOn 5
|
||||
// 0x00020000 - Body AddOn 6
|
||||
// 0x00040000 - Body AddOn 7
|
||||
// 0x00080000 - Body AddOn 8
|
||||
// 0x00100000 - Decapitate Head
|
||||
// 0x00200000 - Decapitate
|
||||
// 0x00400000 - Body AddOn 9
|
||||
// 0x00800000 - Body AddOn 10
|
||||
// 0x01000000 - Body AddOn 11
|
||||
// 0x02000000 - Body AddOn 12
|
||||
// 0x04000000 - Body AddOn 13
|
||||
// 0x08000000 - Body AddOn 14
|
||||
// 0x10000000 - Body AddOn 15
|
||||
// 0x20000000 - Body AddOn 16
|
||||
// 0x40000000 - Body AddOn 17
|
||||
// 0x80000000 - FX01
|
||||
std::uint32_t bodyPart;
|
||||
std::uint8_t flags;
|
||||
std::uint8_t unknown1; // probably padding
|
||||
std::uint8_t unknown2; // probably padding
|
||||
std::uint8_t unknown3; // probably padding
|
||||
std::uint32_t type; // 0 = light, 1 = heavy, 2 = none (cloth?)
|
||||
};
|
||||
}
|
||||
|
||||
#endif // ESM4_ACTOR_H
|
@ -0,0 +1,100 @@
|
||||
/*
|
||||
Copyright (C) 2015-2016, 2018, 2021 cc9cii
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
cc9cii cc9c@iinet.net.au
|
||||
|
||||
Much of the information on the data structures are based on the information
|
||||
from Tes4Mod:Mod_File_Format and Tes5Mod:File_Formats but also refined by
|
||||
trial & error. See http://en.uesp.net/wiki for details.
|
||||
|
||||
*/
|
||||
#include "common.hpp"
|
||||
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "formid.hpp"
|
||||
|
||||
namespace ESM4
|
||||
{
|
||||
const char *sGroupType[] =
|
||||
{
|
||||
"Record Type", "World Child", "Interior Cell", "Interior Sub Cell", "Exterior Cell",
|
||||
"Exterior Sub Cell", "Cell Child", "Topic Child", "Cell Persistent Child",
|
||||
"Cell Temporary Child", "Cell Visible Dist Child", "Unknown"
|
||||
};
|
||||
|
||||
std::string printLabel(const GroupLabel& label, const std::uint32_t type)
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss << std::string(sGroupType[std::min(type, (uint32_t)11)]); // avoid out of range
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case ESM4::Grp_RecordType:
|
||||
{
|
||||
ss << ": " << std::string((char*)label.recordType, 4);
|
||||
break;
|
||||
}
|
||||
case ESM4::Grp_ExteriorCell:
|
||||
case ESM4::Grp_ExteriorSubCell:
|
||||
{
|
||||
//short x, y;
|
||||
//y = label & 0xff;
|
||||
//x = (label >> 16) & 0xff;
|
||||
ss << ": grid (x, y) " << std::dec << label.grid[1] << ", " << label.grid[0];
|
||||
|
||||
break;
|
||||
}
|
||||
case ESM4::Grp_InteriorCell:
|
||||
case ESM4::Grp_InteriorSubCell:
|
||||
{
|
||||
ss << ": block 0x" << std::hex << label.value;
|
||||
break;
|
||||
}
|
||||
case ESM4::Grp_WorldChild:
|
||||
case ESM4::Grp_CellChild:
|
||||
case ESM4::Grp_TopicChild:
|
||||
case ESM4::Grp_CellPersistentChild:
|
||||
case ESM4::Grp_CellTemporaryChild:
|
||||
case ESM4::Grp_CellVisibleDistChild:
|
||||
{
|
||||
ss << ": FormId 0x" << formIdToString(label.value);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
void gridToString(std::int16_t x, std::int16_t y, std::string& str)
|
||||
{
|
||||
char buf[6+6+2+1]; // longest signed 16 bit number is 6 characters (-32768)
|
||||
int res = snprintf(buf, 6+6+2+1, "#%d %d", x, y);
|
||||
if (res > 0 && res < 6+6+2+1)
|
||||
str.assign(buf);
|
||||
else
|
||||
throw std::runtime_error("possible buffer overflow while converting grid");
|
||||
}
|
||||
}
|
@ -0,0 +1,939 @@
|
||||
/*
|
||||
Copyright (C) 2015-2020 cc9cii
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
cc9cii cc9c@iinet.net.au
|
||||
|
||||
Much of the information on the data structures are based on the information
|
||||
from Tes4Mod:Mod_File_Format and Tes5Mod:File_Formats but also refined by
|
||||
trial & error. See http://en.uesp.net/wiki for details.
|
||||
|
||||
MKTAG macro was adapated from ScummVM.
|
||||
|
||||
*/
|
||||
#ifndef ESM4_COMMON_H
|
||||
#define ESM4_COMMON_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include "formid.hpp"
|
||||
|
||||
// From ScummVM's endianness.h but for little endian
|
||||
#ifndef MKTAG
|
||||
#define MKTAG(a0,a1,a2,a3) ((std::uint32_t)((a0) | ((a1) << 8) | ((a2) << 16) | ((a3) << 24)))
|
||||
#endif
|
||||
|
||||
namespace ESM4
|
||||
{
|
||||
|
||||
// Based on http://www.uesp.net/wiki/Tes5Mod:Mod_File_Format
|
||||
enum RecordTypes
|
||||
{
|
||||
REC_AACT = MKTAG('A','A','C','T'), // Action
|
||||
REC_ACHR = MKTAG('A','C','H','R'), // Actor Reference
|
||||
REC_ACTI = MKTAG('A','C','T','I'), // Activator
|
||||
REC_ADDN = MKTAG('A','D','D','N'), // Addon Node
|
||||
REC_ALCH = MKTAG('A','L','C','H'), // Potion
|
||||
REC_AMMO = MKTAG('A','M','M','O'), // Ammo
|
||||
REC_ANIO = MKTAG('A','N','I','O'), // Animated Object
|
||||
REC_APPA = MKTAG('A','P','P','A'), // Apparatus (probably unused)
|
||||
REC_ARMA = MKTAG('A','R','M','A'), // Armature (Model)
|
||||
REC_ARMO = MKTAG('A','R','M','O'), // Armor
|
||||
REC_ARTO = MKTAG('A','R','T','O'), // Art Object
|
||||
REC_ASPC = MKTAG('A','S','P','C'), // Acoustic Space
|
||||
REC_ASTP = MKTAG('A','S','T','P'), // Association Type
|
||||
REC_AVIF = MKTAG('A','V','I','F'), // Actor Values/Perk Tree Graphics
|
||||
REC_BOOK = MKTAG('B','O','O','K'), // Book
|
||||
REC_BPTD = MKTAG('B','P','T','D'), // Body Part Data
|
||||
REC_CAMS = MKTAG('C','A','M','S'), // Camera Shot
|
||||
REC_CELL = MKTAG('C','E','L','L'), // Cell
|
||||
REC_CLAS = MKTAG('C','L','A','S'), // Class
|
||||
REC_CLFM = MKTAG('C','L','F','M'), // Color
|
||||
REC_CLMT = MKTAG('C','L','M','T'), // Climate
|
||||
REC_CLOT = MKTAG('C','L','O','T'), // Clothing
|
||||
REC_COBJ = MKTAG('C','O','B','J'), // Constructible Object (recipes)
|
||||
REC_COLL = MKTAG('C','O','L','L'), // Collision Layer
|
||||
REC_CONT = MKTAG('C','O','N','T'), // Container
|
||||
REC_CPTH = MKTAG('C','P','T','H'), // Camera Path
|
||||
REC_CREA = MKTAG('C','R','E','A'), // Creature
|
||||
REC_CSTY = MKTAG('C','S','T','Y'), // Combat Style
|
||||
REC_DEBR = MKTAG('D','E','B','R'), // Debris
|
||||
REC_DIAL = MKTAG('D','I','A','L'), // Dialog Topic
|
||||
REC_DLBR = MKTAG('D','L','B','R'), // Dialog Branch
|
||||
REC_DLVW = MKTAG('D','L','V','W'), // Dialog View
|
||||
REC_DOBJ = MKTAG('D','O','B','J'), // Default Object Manager
|
||||
REC_DOOR = MKTAG('D','O','O','R'), // Door
|
||||
REC_DUAL = MKTAG('D','U','A','L'), // Dual Cast Data (possibly unused)
|
||||
//REC_ECZN = MKTAG('E','C','Z','N'), // Encounter Zone
|
||||
REC_EFSH = MKTAG('E','F','S','H'), // Effect Shader
|
||||
REC_ENCH = MKTAG('E','N','C','H'), // Enchantment
|
||||
REC_EQUP = MKTAG('E','Q','U','P'), // Equip Slot (flag-type values)
|
||||
REC_EXPL = MKTAG('E','X','P','L'), // Explosion
|
||||
REC_EYES = MKTAG('E','Y','E','S'), // Eyes
|
||||
REC_FACT = MKTAG('F','A','C','T'), // Faction
|
||||
REC_FLOR = MKTAG('F','L','O','R'), // Flora
|
||||
REC_FLST = MKTAG('F','L','S','T'), // Form List (non-levelled list)
|
||||
REC_FSTP = MKTAG('F','S','T','P'), // Footstep
|
||||
REC_FSTS = MKTAG('F','S','T','S'), // Footstep Set
|
||||
REC_FURN = MKTAG('F','U','R','N'), // Furniture
|
||||
REC_GLOB = MKTAG('G','L','O','B'), // Global Variable
|
||||
REC_GMST = MKTAG('G','M','S','T'), // Game Setting
|
||||
REC_GRAS = MKTAG('G','R','A','S'), // Grass
|
||||
REC_GRUP = MKTAG('G','R','U','P'), // Form Group
|
||||
REC_HAIR = MKTAG('H','A','I','R'), // Hair
|
||||
//REC_HAZD = MKTAG('H','A','Z','D'), // Hazard
|
||||
REC_HDPT = MKTAG('H','D','P','T'), // Head Part
|
||||
REC_IDLE = MKTAG('I','D','L','E'), // Idle Animation
|
||||
REC_IDLM = MKTAG('I','D','L','M'), // Idle Marker
|
||||
REC_IMAD = MKTAG('I','M','A','D'), // Image Space Modifier
|
||||
REC_IMGS = MKTAG('I','M','G','S'), // Image Space
|
||||
REC_INFO = MKTAG('I','N','F','O'), // Dialog Topic Info
|
||||
REC_INGR = MKTAG('I','N','G','R'), // Ingredient
|
||||
REC_IPCT = MKTAG('I','P','C','T'), // Impact Data
|
||||
REC_IPDS = MKTAG('I','P','D','S'), // Impact Data Set
|
||||
REC_KEYM = MKTAG('K','E','Y','M'), // Key
|
||||
REC_KYWD = MKTAG('K','Y','W','D'), // Keyword
|
||||
REC_LAND = MKTAG('L','A','N','D'), // Land
|
||||
REC_LCRT = MKTAG('L','C','R','T'), // Location Reference Type
|
||||
REC_LCTN = MKTAG('L','C','T','N'), // Location
|
||||
REC_LGTM = MKTAG('L','G','T','M'), // Lighting Template
|
||||
REC_LIGH = MKTAG('L','I','G','H'), // Light
|
||||
REC_LSCR = MKTAG('L','S','C','R'), // Load Screen
|
||||
REC_LTEX = MKTAG('L','T','E','X'), // Land Texture
|
||||
REC_LVLC = MKTAG('L','V','L','C'), // Leveled Creature
|
||||
REC_LVLI = MKTAG('L','V','L','I'), // Leveled Item
|
||||
REC_LVLN = MKTAG('L','V','L','N'), // Leveled Actor
|
||||
REC_LVSP = MKTAG('L','V','S','P'), // Leveled Spell
|
||||
REC_MATO = MKTAG('M','A','T','O'), // Material Object
|
||||
REC_MATT = MKTAG('M','A','T','T'), // Material Type
|
||||
REC_MESG = MKTAG('M','E','S','G'), // Message
|
||||
REC_MGEF = MKTAG('M','G','E','F'), // Magic Effect
|
||||
REC_MISC = MKTAG('M','I','S','C'), // Misc. Object
|
||||
REC_MOVT = MKTAG('M','O','V','T'), // Movement Type
|
||||
REC_MSTT = MKTAG('M','S','T','T'), // Movable Static
|
||||
REC_MUSC = MKTAG('M','U','S','C'), // Music Type
|
||||
REC_MUST = MKTAG('M','U','S','T'), // Music Track
|
||||
REC_NAVI = MKTAG('N','A','V','I'), // Navigation (master data)
|
||||
REC_NAVM = MKTAG('N','A','V','M'), // Nav Mesh
|
||||
REC_NOTE = MKTAG('N','O','T','E'), // Note
|
||||
REC_NPC_ = MKTAG('N','P','C','_'), // Actor (NPC, Creature)
|
||||
REC_OTFT = MKTAG('O','T','F','T'), // Outfit
|
||||
REC_PACK = MKTAG('P','A','C','K'), // AI Package
|
||||
REC_PERK = MKTAG('P','E','R','K'), // Perk
|
||||
REC_PGRE = MKTAG('P','G','R','E'), // Placed grenade
|
||||
REC_PHZD = MKTAG('P','H','Z','D'), // Placed hazard
|
||||
REC_PROJ = MKTAG('P','R','O','J'), // Projectile
|
||||
REC_QUST = MKTAG('Q','U','S','T'), // Quest
|
||||
REC_RACE = MKTAG('R','A','C','E'), // Race / Creature type
|
||||
REC_REFR = MKTAG('R','E','F','R'), // Object Reference
|
||||
REC_REGN = MKTAG('R','E','G','N'), // Region (Audio/Weather)
|
||||
REC_RELA = MKTAG('R','E','L','A'), // Relationship
|
||||
REC_REVB = MKTAG('R','E','V','B'), // Reverb Parameters
|
||||
REC_RFCT = MKTAG('R','F','C','T'), // Visual Effect
|
||||
REC_SBSP = MKTAG('S','B','S','P'), // Subspace (TES4 only?)
|
||||
REC_SCEN = MKTAG('S','C','E','N'), // Scene
|
||||
REC_SCPT = MKTAG('S','C','P','T'), // Script
|
||||
REC_SCRL = MKTAG('S','C','R','L'), // Scroll
|
||||
REC_SGST = MKTAG('S','G','S','T'), // Sigil Stone
|
||||
REC_SHOU = MKTAG('S','H','O','U'), // Shout
|
||||
REC_SLGM = MKTAG('S','L','G','M'), // Soul Gem
|
||||
REC_SMBN = MKTAG('S','M','B','N'), // Story Manager Branch Node
|
||||
REC_SMEN = MKTAG('S','M','E','N'), // Story Manager Event Node
|
||||
REC_SMQN = MKTAG('S','M','Q','N'), // Story Manager Quest Node
|
||||
REC_SNCT = MKTAG('S','N','C','T'), // Sound Category
|
||||
REC_SNDR = MKTAG('S','N','D','R'), // Sound Reference
|
||||
REC_SOPM = MKTAG('S','O','P','M'), // Sound Output Model
|
||||
REC_SOUN = MKTAG('S','O','U','N'), // Sound
|
||||
REC_SPEL = MKTAG('S','P','E','L'), // Spell
|
||||
REC_SPGD = MKTAG('S','P','G','D'), // Shader Particle Geometry
|
||||
REC_STAT = MKTAG('S','T','A','T'), // Static
|
||||
REC_TACT = MKTAG('T','A','C','T'), // Talking Activator
|
||||
REC_TERM = MKTAG('T','E','R','M'), // Terminal
|
||||
REC_TES4 = MKTAG('T','E','S','4'), // Plugin info
|
||||
REC_TREE = MKTAG('T','R','E','E'), // Tree
|
||||
REC_TXST = MKTAG('T','X','S','T'), // Texture Set
|
||||
REC_VTYP = MKTAG('V','T','Y','P'), // Voice Type
|
||||
REC_WATR = MKTAG('W','A','T','R'), // Water Type
|
||||
REC_WEAP = MKTAG('W','E','A','P'), // Weapon
|
||||
REC_WOOP = MKTAG('W','O','O','P'), // Word Of Power
|
||||
REC_WRLD = MKTAG('W','R','L','D'), // World Space
|
||||
REC_WTHR = MKTAG('W','T','H','R'), // Weather
|
||||
REC_ACRE = MKTAG('A','C','R','E'), // Placed Creature (TES4 only?)
|
||||
REC_PGRD = MKTAG('P','G','R','D'), // Pathgrid (TES4 only?)
|
||||
REC_ROAD = MKTAG('R','O','A','D'), // Road (TES4 only?)
|
||||
REC_IMOD = MKTAG('I','M','O','D'), // Item Mod
|
||||
REC_PWAT = MKTAG('P','W','A','T'), // Placeable Water
|
||||
REC_SCOL = MKTAG('S','C','O','L'), // Static Collection
|
||||
REC_CCRD = MKTAG('C','C','R','D'), // Caravan Card
|
||||
REC_CMNY = MKTAG('C','M','N','Y'), // Caravan Money
|
||||
REC_ALOC = MKTAG('A','L','O','C'), // Audio Location Controller
|
||||
REC_MSET = MKTAG('M','S','E','T') // Media Set
|
||||
};
|
||||
|
||||
enum SubRecordTypes
|
||||
{
|
||||
SUB_HEDR = MKTAG('H','E','D','R'),
|
||||
SUB_CNAM = MKTAG('C','N','A','M'),
|
||||
SUB_SNAM = MKTAG('S','N','A','M'), // TES4 only?
|
||||
SUB_MAST = MKTAG('M','A','S','T'),
|
||||
SUB_DATA = MKTAG('D','A','T','A'),
|
||||
SUB_ONAM = MKTAG('O','N','A','M'),
|
||||
SUB_INTV = MKTAG('I','N','T','V'),
|
||||
SUB_INCC = MKTAG('I','N','C','C'),
|
||||
SUB_OFST = MKTAG('O','F','S','T'), // TES4 only?
|
||||
SUB_DELE = MKTAG('D','E','L','E'), // TES4 only?
|
||||
|
||||
SUB_DNAM = MKTAG('D','N','A','M'),
|
||||
SUB_EDID = MKTAG('E','D','I','D'),
|
||||
SUB_FULL = MKTAG('F','U','L','L'),
|
||||
SUB_LTMP = MKTAG('L','T','M','P'),
|
||||
SUB_MHDT = MKTAG('M','H','D','T'),
|
||||
SUB_MNAM = MKTAG('M','N','A','M'),
|
||||
SUB_MODL = MKTAG('M','O','D','L'),
|
||||
SUB_NAM0 = MKTAG('N','A','M','0'),
|
||||
SUB_NAM2 = MKTAG('N','A','M','2'),
|
||||
SUB_NAM3 = MKTAG('N','A','M','3'),
|
||||
SUB_NAM4 = MKTAG('N','A','M','4'),
|
||||
SUB_NAM9 = MKTAG('N','A','M','9'),
|
||||
SUB_NAMA = MKTAG('N','A','M','A'),
|
||||
SUB_PNAM = MKTAG('P','N','A','M'),
|
||||
SUB_RNAM = MKTAG('R','N','A','M'),
|
||||
SUB_TNAM = MKTAG('T','N','A','M'),
|
||||
SUB_UNAM = MKTAG('U','N','A','M'),
|
||||
SUB_WCTR = MKTAG('W','C','T','R'),
|
||||
SUB_WNAM = MKTAG('W','N','A','M'),
|
||||
SUB_XEZN = MKTAG('X','E','Z','N'),
|
||||
SUB_XLCN = MKTAG('X','L','C','N'),
|
||||
SUB_XXXX = MKTAG('X','X','X','X'),
|
||||
SUB_ZNAM = MKTAG('Z','N','A','M'),
|
||||
SUB_MODT = MKTAG('M','O','D','T'),
|
||||
SUB_ICON = MKTAG('I','C','O','N'), // TES4 only?
|
||||
|
||||
SUB_NVER = MKTAG('N','V','E','R'),
|
||||
SUB_NVMI = MKTAG('N','V','M','I'),
|
||||
SUB_NVPP = MKTAG('N','V','P','P'),
|
||||
SUB_NVSI = MKTAG('N','V','S','I'),
|
||||
|
||||
SUB_NVNM = MKTAG('N','V','N','M'),
|
||||
SUB_NNAM = MKTAG('N','N','A','M'),
|
||||
|
||||
SUB_XCLC = MKTAG('X','C','L','C'),
|
||||
SUB_XCLL = MKTAG('X','C','L','L'),
|
||||
SUB_TVDT = MKTAG('T','V','D','T'),
|
||||
SUB_XCGD = MKTAG('X','C','G','D'),
|
||||
SUB_LNAM = MKTAG('L','N','A','M'),
|
||||
SUB_XCLW = MKTAG('X','C','L','W'),
|
||||
SUB_XNAM = MKTAG('X','N','A','M'),
|
||||
SUB_XCLR = MKTAG('X','C','L','R'),
|
||||
SUB_XWCS = MKTAG('X','W','C','S'),
|
||||
SUB_XWCN = MKTAG('X','W','C','N'),
|
||||
SUB_XWCU = MKTAG('X','W','C','U'),
|
||||
SUB_XCWT = MKTAG('X','C','W','T'),
|
||||
SUB_XOWN = MKTAG('X','O','W','N'),
|
||||
SUB_XILL = MKTAG('X','I','L','L'),
|
||||
SUB_XWEM = MKTAG('X','W','E','M'),
|
||||
SUB_XCCM = MKTAG('X','C','C','M'),
|
||||
SUB_XCAS = MKTAG('X','C','A','S'),
|
||||
SUB_XCMO = MKTAG('X','C','M','O'),
|
||||
SUB_XCIM = MKTAG('X','C','I','M'),
|
||||
SUB_XCMT = MKTAG('X','C','M','T'), // TES4 only?
|
||||
SUB_XRNK = MKTAG('X','R','N','K'), // TES4 only?
|
||||
SUB_XGLB = MKTAG('X','G','L','B'), // TES4 only?
|
||||
|
||||
SUB_VNML = MKTAG('V','N','M','L'),
|
||||
SUB_VHGT = MKTAG('V','H','G','T'),
|
||||
SUB_VCLR = MKTAG('V','C','L','R'),
|
||||
SUA_BTXT = MKTAG('B','T','X','T'),
|
||||
SUB_ATXT = MKTAG('A','T','X','T'),
|
||||
SUB_VTXT = MKTAG('V','T','X','T'),
|
||||
SUB_VTEX = MKTAG('V','T','E','X'),
|
||||
|
||||
SUB_HNAM = MKTAG('H','N','A','M'),
|
||||
SUB_GNAM = MKTAG('G','N','A','M'),
|
||||
|
||||
SUB_RCLR = MKTAG('R','C','L','R'),
|
||||
SUB_RPLI = MKTAG('R','P','L','I'),
|
||||
SUB_RPLD = MKTAG('R','P','L','D'),
|
||||
SUB_RDAT = MKTAG('R','D','A','T'),
|
||||
SUB_RDMD = MKTAG('R','D','M','D'), // TES4 only?
|
||||
SUB_RDSD = MKTAG('R','D','S','D'), // TES4 only?
|
||||
SUB_RDGS = MKTAG('R','D','G','S'), // TES4 only?
|
||||
SUB_RDMO = MKTAG('R','D','M','O'),
|
||||
SUB_RDSA = MKTAG('R','D','S','A'),
|
||||
SUB_RDWT = MKTAG('R','D','W','T'),
|
||||
SUB_RDOT = MKTAG('R','D','O','T'),
|
||||
SUB_RDMP = MKTAG('R','D','M','P'),
|
||||
|
||||
SUB_MODB = MKTAG('M','O','D','B'),
|
||||
SUB_OBND = MKTAG('O','B','N','D'),
|
||||
SUB_MODS = MKTAG('M','O','D','S'),
|
||||
|
||||
SUB_NAME = MKTAG('N','A','M','E'),
|
||||
SUB_XMRK = MKTAG('X','M','R','K'),
|
||||
SUB_FNAM = MKTAG('F','N','A','M'),
|
||||
SUB_XSCL = MKTAG('X','S','C','L'),
|
||||
SUB_XTEL = MKTAG('X','T','E','L'),
|
||||
SUB_XTRG = MKTAG('X','T','R','G'),
|
||||
SUB_XSED = MKTAG('X','S','E','D'),
|
||||
SUB_XLOD = MKTAG('X','L','O','D'),
|
||||
SUB_XPCI = MKTAG('X','P','C','I'),
|
||||
SUB_XLOC = MKTAG('X','L','O','C'),
|
||||
SUB_XESP = MKTAG('X','E','S','P'),
|
||||
SUB_XLCM = MKTAG('X','L','C','M'),
|
||||
SUB_XRTM = MKTAG('X','R','T','M'),
|
||||
SUB_XACT = MKTAG('X','A','C','T'),
|
||||
SUB_XCNT = MKTAG('X','C','N','T'),
|
||||
SUB_VMAD = MKTAG('V','M','A','D'),
|
||||
SUB_XPRM = MKTAG('X','P','R','M'),
|
||||
SUB_XMBO = MKTAG('X','M','B','O'),
|
||||
SUB_XPOD = MKTAG('X','P','O','D'),
|
||||
SUB_XRMR = MKTAG('X','R','M','R'),
|
||||
SUB_INAM = MKTAG('I','N','A','M'),
|
||||
SUB_SCHR = MKTAG('S','C','H','R'),
|
||||
SUB_XLRM = MKTAG('X','L','R','M'),
|
||||
SUB_XRGD = MKTAG('X','R','G','D'),
|
||||
SUB_XRDS = MKTAG('X','R','D','S'),
|
||||
SUB_XEMI = MKTAG('X','E','M','I'),
|
||||
SUB_XLIG = MKTAG('X','L','I','G'),
|
||||
SUB_XALP = MKTAG('X','A','L','P'),
|
||||
SUB_XNDP = MKTAG('X','N','D','P'),
|
||||
SUB_XAPD = MKTAG('X','A','P','D'),
|
||||
SUB_XAPR = MKTAG('X','A','P','R'),
|
||||
SUB_XLIB = MKTAG('X','L','I','B'),
|
||||
SUB_XLKR = MKTAG('X','L','K','R'),
|
||||
SUB_XLRT = MKTAG('X','L','R','T'),
|
||||
SUB_XCVL = MKTAG('X','C','V','L'),
|
||||
SUB_XCVR = MKTAG('X','C','V','R'),
|
||||
SUB_XCZA = MKTAG('X','C','Z','A'),
|
||||
SUB_XCZC = MKTAG('X','C','Z','C'),
|
||||
SUB_XFVC = MKTAG('X','F','V','C'),
|
||||
SUB_XHTW = MKTAG('X','H','T','W'),
|
||||
SUB_XIS2 = MKTAG('X','I','S','2'),
|
||||
SUB_XMBR = MKTAG('X','M','B','R'),
|
||||
SUB_XCCP = MKTAG('X','C','C','P'),
|
||||
SUB_XPWR = MKTAG('X','P','W','R'),
|
||||
SUB_XTRI = MKTAG('X','T','R','I'),
|
||||
SUB_XATR = MKTAG('X','A','T','R'),
|
||||
SUB_XPRD = MKTAG('X','P','R','D'),
|
||||
SUB_XPPA = MKTAG('X','P','P','A'),
|
||||
SUB_PDTO = MKTAG('P','D','T','O'),
|
||||
SUB_XLRL = MKTAG('X','L','R','L'),
|
||||
|
||||
SUB_QNAM = MKTAG('Q','N','A','M'),
|
||||
SUB_COCT = MKTAG('C','O','C','T'),
|
||||
SUB_COED = MKTAG('C','O','E','D'),
|
||||
SUB_CNTO = MKTAG('C','N','T','O'),
|
||||
SUB_SCRI = MKTAG('S','C','R','I'),
|
||||
|
||||
SUB_BNAM = MKTAG('B','N','A','M'),
|
||||
|
||||
SUB_BMDT = MKTAG('B','M','D','T'),
|
||||
SUB_MOD2 = MKTAG('M','O','D','2'),
|
||||
SUB_MOD3 = MKTAG('M','O','D','3'),
|
||||
SUB_MOD4 = MKTAG('M','O','D','4'),
|
||||
SUB_MO2B = MKTAG('M','O','2','B'),
|
||||
SUB_MO3B = MKTAG('M','O','3','B'),
|
||||
SUB_MO4B = MKTAG('M','O','4','B'),
|
||||
SUB_MO2T = MKTAG('M','O','2','T'),
|
||||
SUB_MO3T = MKTAG('M','O','3','T'),
|
||||
SUB_MO4T = MKTAG('M','O','4','T'),
|
||||
SUB_ANAM = MKTAG('A','N','A','M'),
|
||||
SUB_ENAM = MKTAG('E','N','A','M'),
|
||||
SUB_ICO2 = MKTAG('I','C','O','2'),
|
||||
|
||||
SUB_ACBS = MKTAG('A','C','B','S'),
|
||||
SUB_SPLO = MKTAG('S','P','L','O'),
|
||||
SUB_AIDT = MKTAG('A','I','D','T'),
|
||||
SUB_PKID = MKTAG('P','K','I','D'),
|
||||
SUB_HCLR = MKTAG('H','C','L','R'),
|
||||
SUB_FGGS = MKTAG('F','G','G','S'),
|
||||
SUB_FGGA = MKTAG('F','G','G','A'),
|
||||
SUB_FGTS = MKTAG('F','G','T','S'),
|
||||
SUB_KFFZ = MKTAG('K','F','F','Z'),
|
||||
|
||||
SUB_PFIG = MKTAG('P','F','I','G'),
|
||||
SUB_PFPC = MKTAG('P','F','P','C'),
|
||||
|
||||
SUB_XHRS = MKTAG('X','H','R','S'),
|
||||
SUB_XMRC = MKTAG('X','M','R','C'),
|
||||
|
||||
SUB_SNDD = MKTAG('S','N','D','D'),
|
||||
SUB_SNDX = MKTAG('S','N','D','X'),
|
||||
|
||||
SUB_DESC = MKTAG('D','E','S','C'),
|
||||
|
||||
SUB_ENIT = MKTAG('E','N','I','T'),
|
||||
SUB_EFID = MKTAG('E','F','I','D'),
|
||||
SUB_EFIT = MKTAG('E','F','I','T'),
|
||||
SUB_SCIT = MKTAG('S','C','I','T'),
|
||||
|
||||
SUB_SOUL = MKTAG('S','O','U','L'),
|
||||
SUB_SLCP = MKTAG('S','L','C','P'),
|
||||
|
||||
SUB_CSCR = MKTAG('C','S','C','R'),
|
||||
SUB_CSDI = MKTAG('C','S','D','I'),
|
||||
SUB_CSDC = MKTAG('C','S','D','C'),
|
||||
SUB_NIFZ = MKTAG('N','I','F','Z'),
|
||||
SUB_CSDT = MKTAG('C','S','D','T'),
|
||||
SUB_NAM1 = MKTAG('N','A','M','1'),
|
||||
SUB_NIFT = MKTAG('N','I','F','T'),
|
||||
|
||||
SUB_LVLD = MKTAG('L','V','L','D'),
|
||||
SUB_LVLF = MKTAG('L','V','L','F'),
|
||||
SUB_LVLO = MKTAG('L','V','L','O'),
|
||||
|
||||
SUB_BODT = MKTAG('B','O','D','T'),
|
||||
SUB_YNAM = MKTAG('Y','N','A','M'),
|
||||
SUB_DEST = MKTAG('D','E','S','T'),
|
||||
SUB_DMDL = MKTAG('D','M','D','L'),
|
||||
SUB_DMDS = MKTAG('D','M','D','S'),
|
||||
SUB_DMDT = MKTAG('D','M','D','T'),
|
||||
SUB_DSTD = MKTAG('D','S','T','D'),
|
||||
SUB_DSTF = MKTAG('D','S','T','F'),
|
||||
SUB_KNAM = MKTAG('K','N','A','M'),
|
||||
SUB_KSIZ = MKTAG('K','S','I','Z'),
|
||||
SUB_KWDA = MKTAG('K','W','D','A'),
|
||||
SUB_VNAM = MKTAG('V','N','A','M'),
|
||||
SUB_SDSC = MKTAG('S','D','S','C'),
|
||||
SUB_MO2S = MKTAG('M','O','2','S'),
|
||||
SUB_MO4S = MKTAG('M','O','4','S'),
|
||||
SUB_BOD2 = MKTAG('B','O','D','2'),
|
||||
SUB_BAMT = MKTAG('B','A','M','T'),
|
||||
SUB_BIDS = MKTAG('B','I','D','S'),
|
||||
SUB_ETYP = MKTAG('E','T','Y','P'),
|
||||
SUB_BMCT = MKTAG('B','M','C','T'),
|
||||
SUB_MICO = MKTAG('M','I','C','O'),
|
||||
SUB_MIC2 = MKTAG('M','I','C','2'),
|
||||
SUB_EAMT = MKTAG('E','A','M','T'),
|
||||
SUB_EITM = MKTAG('E','I','T','M'),
|
||||
|
||||
SUB_SCTX = MKTAG('S','C','T','X'),
|
||||
SUB_XLTW = MKTAG('X','L','T','W'),
|
||||
SUB_XMBP = MKTAG('X','M','B','P'),
|
||||
SUB_XOCP = MKTAG('X','O','C','P'),
|
||||
SUB_XRGB = MKTAG('X','R','G','B'),
|
||||
SUB_XSPC = MKTAG('X','S','P','C'),
|
||||
SUB_XTNM = MKTAG('X','T','N','M'),
|
||||
SUB_ATKR = MKTAG('A','T','K','R'),
|
||||
SUB_CRIF = MKTAG('C','R','I','F'),
|
||||
SUB_DOFT = MKTAG('D','O','F','T'),
|
||||
SUB_DPLT = MKTAG('D','P','L','T'),
|
||||
SUB_ECOR = MKTAG('E','C','O','R'),
|
||||
SUB_ATKD = MKTAG('A','T','K','D'),
|
||||
SUB_ATKE = MKTAG('A','T','K','E'),
|
||||
SUB_FTST = MKTAG('F','T','S','T'),
|
||||
SUB_HCLF = MKTAG('H','C','L','F'),
|
||||
SUB_NAM5 = MKTAG('N','A','M','5'),
|
||||
SUB_NAM6 = MKTAG('N','A','M','6'),
|
||||
SUB_NAM7 = MKTAG('N','A','M','7'),
|
||||
SUB_NAM8 = MKTAG('N','A','M','8'),
|
||||
SUB_PRKR = MKTAG('P','R','K','R'),
|
||||
SUB_PRKZ = MKTAG('P','R','K','Z'),
|
||||
SUB_SOFT = MKTAG('S','O','F','T'),
|
||||
SUB_SPCT = MKTAG('S','P','C','T'),
|
||||
SUB_TINC = MKTAG('T','I','N','C'),
|
||||
SUB_TIAS = MKTAG('T','I','A','S'),
|
||||
SUB_TINI = MKTAG('T','I','N','I'),
|
||||
SUB_TINV = MKTAG('T','I','N','V'),
|
||||
SUB_TPLT = MKTAG('T','P','L','T'),
|
||||
SUB_VTCK = MKTAG('V','T','C','K'),
|
||||
SUB_SHRT = MKTAG('S','H','R','T'),
|
||||
SUB_SPOR = MKTAG('S','P','O','R'),
|
||||
SUB_XHOR = MKTAG('X','H','O','R'),
|
||||
SUB_CTDA = MKTAG('C','T','D','A'),
|
||||
SUB_CRDT = MKTAG('C','R','D','T'),
|
||||
SUB_FNMK = MKTAG('F','N','M','K'),
|
||||
SUB_FNPR = MKTAG('F','N','P','R'),
|
||||
SUB_WBDT = MKTAG('W','B','D','T'),
|
||||
SUB_QUAL = MKTAG('Q','U','A','L'),
|
||||
SUB_INDX = MKTAG('I','N','D','X'),
|
||||
SUB_ATTR = MKTAG('A','T','T','R'),
|
||||
SUB_MTNM = MKTAG('M','T','N','M'),
|
||||
SUB_UNES = MKTAG('U','N','E','S'),
|
||||
SUB_TIND = MKTAG('T','I','N','D'),
|
||||
SUB_TINL = MKTAG('T','I','N','L'),
|
||||
SUB_TINP = MKTAG('T','I','N','P'),
|
||||
SUB_TINT = MKTAG('T','I','N','T'),
|
||||
SUB_TIRS = MKTAG('T','I','R','S'),
|
||||
SUB_PHWT = MKTAG('P','H','W','T'),
|
||||
SUB_AHCF = MKTAG('A','H','C','F'),
|
||||
SUB_AHCM = MKTAG('A','H','C','M'),
|
||||
SUB_HEAD = MKTAG('H','E','A','D'),
|
||||
SUB_MPAI = MKTAG('M','P','A','I'),
|
||||
SUB_MPAV = MKTAG('M','P','A','V'),
|
||||
SUB_DFTF = MKTAG('D','F','T','F'),
|
||||
SUB_DFTM = MKTAG('D','F','T','M'),
|
||||
SUB_FLMV = MKTAG('F','L','M','V'),
|
||||
SUB_FTSF = MKTAG('F','T','S','F'),
|
||||
SUB_FTSM = MKTAG('F','T','S','M'),
|
||||
SUB_MTYP = MKTAG('M','T','Y','P'),
|
||||
SUB_PHTN = MKTAG('P','H','T','N'),
|
||||
SUB_RNMV = MKTAG('R','N','M','V'),
|
||||
SUB_RPRF = MKTAG('R','P','R','F'),
|
||||
SUB_RPRM = MKTAG('R','P','R','M'),
|
||||
SUB_SNMV = MKTAG('S','N','M','V'),
|
||||
SUB_SPED = MKTAG('S','P','E','D'),
|
||||
SUB_SWMV = MKTAG('S','W','M','V'),
|
||||
SUB_WKMV = MKTAG('W','K','M','V'),
|
||||
SUB_LLCT = MKTAG('L','L','C','T'),
|
||||
SUB_IDLF = MKTAG('I','D','L','F'),
|
||||
SUB_IDLA = MKTAG('I','D','L','A'),
|
||||
SUB_IDLC = MKTAG('I','D','L','C'),
|
||||
SUB_IDLT = MKTAG('I','D','L','T'),
|
||||
SUB_DODT = MKTAG('D','O','D','T'),
|
||||
SUB_TX00 = MKTAG('T','X','0','0'),
|
||||
SUB_TX01 = MKTAG('T','X','0','1'),
|
||||
SUB_TX02 = MKTAG('T','X','0','2'),
|
||||
SUB_TX03 = MKTAG('T','X','0','3'),
|
||||
SUB_TX04 = MKTAG('T','X','0','4'),
|
||||
SUB_TX05 = MKTAG('T','X','0','5'),
|
||||
SUB_TX06 = MKTAG('T','X','0','6'),
|
||||
SUB_TX07 = MKTAG('T','X','0','7'),
|
||||
SUB_BPND = MKTAG('B','P','N','D'),
|
||||
SUB_BPTN = MKTAG('B','P','T','N'),
|
||||
SUB_BPNN = MKTAG('B','P','N','N'),
|
||||
SUB_BPNT = MKTAG('B','P','N','T'),
|
||||
SUB_BPNI = MKTAG('B','P','N','I'),
|
||||
SUB_RAGA = MKTAG('R','A','G','A'),
|
||||
|
||||
SUB_QSTI = MKTAG('Q','S','T','I'),
|
||||
SUB_QSTR = MKTAG('Q','S','T','R'),
|
||||
SUB_QSDT = MKTAG('Q','S','D','T'),
|
||||
SUB_SCDA = MKTAG('S','C','D','A'),
|
||||
SUB_SCRO = MKTAG('S','C','R','O'),
|
||||
SUB_QSTA = MKTAG('Q','S','T','A'),
|
||||
SUB_CTDT = MKTAG('C','T','D','T'),
|
||||
SUB_SCHD = MKTAG('S','C','H','D'),
|
||||
SUB_TCLF = MKTAG('T','C','L','F'),
|
||||
SUB_TCLT = MKTAG('T','C','L','T'),
|
||||
SUB_TRDT = MKTAG('T','R','D','T'),
|
||||
SUB_TPIC = MKTAG('T','P','I','C'),
|
||||
|
||||
SUB_PKDT = MKTAG('P','K','D','T'),
|
||||
SUB_PSDT = MKTAG('P','S','D','T'),
|
||||
SUB_PLDT = MKTAG('P','L','D','T'),
|
||||
SUB_PTDT = MKTAG('P','T','D','T'),
|
||||
SUB_PGRP = MKTAG('P','G','R','P'),
|
||||
SUB_PGRR = MKTAG('P','G','R','R'),
|
||||
SUB_PGRI = MKTAG('P','G','R','I'),
|
||||
SUB_PGRL = MKTAG('P','G','R','L'),
|
||||
SUB_PGAG = MKTAG('P','G','A','G'),
|
||||
SUB_FLTV = MKTAG('F','L','T','V'),
|
||||
|
||||
SUB_XHLT = MKTAG('X','H','L','T'), // Unofficial Oblivion Patch
|
||||
SUB_XCHG = MKTAG('X','C','H','G'), // thievery.exp
|
||||
|
||||
SUB_ITXT = MKTAG('I','T','X','T'),
|
||||
SUB_MO5T = MKTAG('M','O','5','T'),
|
||||
SUB_MOD5 = MKTAG('M','O','D','5'),
|
||||
SUB_MDOB = MKTAG('M','D','O','B'),
|
||||
SUB_SPIT = MKTAG('S','P','I','T'),
|
||||
SUB_PTDA = MKTAG('P','T','D','A'), // TES5
|
||||
SUB_PFOR = MKTAG('P','F','O','R'), // TES5
|
||||
SUB_PFO2 = MKTAG('P','F','O','2'), // TES5
|
||||
SUB_PRCB = MKTAG('P','R','C','B'), // TES5
|
||||
SUB_PKCU = MKTAG('P','K','C','U'), // TES5
|
||||
SUB_PKC2 = MKTAG('P','K','C','2'), // TES5
|
||||
SUB_CITC = MKTAG('C','I','T','C'), // TES5
|
||||
SUB_CIS1 = MKTAG('C','I','S','1'), // TES5
|
||||
SUB_CIS2 = MKTAG('C','I','S','2'), // TES5
|
||||
SUB_TIFC = MKTAG('T','I','F','C'), // TES5
|
||||
SUB_ALCA = MKTAG('A','L','C','A'), // TES5
|
||||
SUB_ALCL = MKTAG('A','L','C','L'), // TES5
|
||||
SUB_ALCO = MKTAG('A','L','C','O'), // TES5
|
||||
SUB_ALDN = MKTAG('A','L','D','N'), // TES5
|
||||
SUB_ALEA = MKTAG('A','L','E','A'), // TES5
|
||||
SUB_ALED = MKTAG('A','L','E','D'), // TES5
|
||||
SUB_ALEQ = MKTAG('A','L','E','Q'), // TES5
|
||||
SUB_ALFA = MKTAG('A','L','F','A'), // TES5
|
||||
SUB_ALFC = MKTAG('A','L','F','C'), // TES5
|
||||
SUB_ALFD = MKTAG('A','L','F','D'), // TES5
|
||||
SUB_ALFE = MKTAG('A','L','F','E'), // TES5
|
||||
SUB_ALFI = MKTAG('A','L','F','I'), // TES5
|
||||
SUB_ALFL = MKTAG('A','L','F','L'), // TES5
|
||||
SUB_ALFR = MKTAG('A','L','F','R'), // TES5
|
||||
SUB_ALID = MKTAG('A','L','I','D'), // TES5
|
||||
SUB_ALLS = MKTAG('A','L','L','S'), // TES5
|
||||
SUB_ALNA = MKTAG('A','L','N','A'), // TES5
|
||||
SUB_ALNT = MKTAG('A','L','N','T'), // TES5
|
||||
SUB_ALPC = MKTAG('A','L','P','C'), // TES5
|
||||
SUB_ALRT = MKTAG('A','L','R','T'), // TES5
|
||||
SUB_ALSP = MKTAG('A','L','S','P'), // TES5
|
||||
SUB_ALST = MKTAG('A','L','S','T'), // TES5
|
||||
SUB_ALUA = MKTAG('A','L','U','A'), // TES5
|
||||
SUB_FLTR = MKTAG('F','L','T','R'), // TES5
|
||||
SUB_QTGL = MKTAG('Q','T','G','L'), // TES5
|
||||
SUB_TWAT = MKTAG('T','W','A','T'), // TES5
|
||||
SUB_XIBS = MKTAG('X','I','B','S'), // FO3
|
||||
SUB_REPL = MKTAG('R','E','P','L'), // FO3
|
||||
SUB_BIPL = MKTAG('B','I','P','L'), // FO3
|
||||
SUB_MODD = MKTAG('M','O','D','D'), // FO3
|
||||
SUB_MOSD = MKTAG('M','O','S','D'), // FO3
|
||||
SUB_MO3S = MKTAG('M','O','3','S'), // FO3
|
||||
SUB_XCET = MKTAG('X','C','E','T'), // FO3
|
||||
SUB_LVLG = MKTAG('L','V','L','G'), // FO3
|
||||
SUB_NVCI = MKTAG('N','V','C','I'), // FO3
|
||||
SUB_NVVX = MKTAG('N','V','V','X'), // FO3
|
||||
SUB_NVTR = MKTAG('N','V','T','R'), // FO3
|
||||
SUB_NVCA = MKTAG('N','V','C','A'), // FO3
|
||||
SUB_NVDP = MKTAG('N','V','D','P'), // FO3
|
||||
SUB_NVGD = MKTAG('N','V','G','D'), // FO3
|
||||
SUB_NVEX = MKTAG('N','V','E','X'), // FO3
|
||||
SUB_XHLP = MKTAG('X','H','L','P'), // FO3
|
||||
SUB_XRDO = MKTAG('X','R','D','O'), // FO3
|
||||
SUB_XAMT = MKTAG('X','A','M','T'), // FO3
|
||||
SUB_XAMC = MKTAG('X','A','M','C'), // FO3
|
||||
SUB_XRAD = MKTAG('X','R','A','D'), // FO3
|
||||
SUB_XORD = MKTAG('X','O','R','D'), // FO3
|
||||
SUB_XCLP = MKTAG('X','C','L','P'), // FO3
|
||||
SUB_NEXT = MKTAG('N','E','X','T'), // FO3
|
||||
SUB_QOBJ = MKTAG('Q','O','B','J'), // FO3
|
||||
SUB_POBA = MKTAG('P','O','B','A'), // FO3
|
||||
SUB_POCA = MKTAG('P','O','C','A'), // FO3
|
||||
SUB_POEA = MKTAG('P','O','E','A'), // FO3
|
||||
SUB_PKDD = MKTAG('P','K','D','D'), // FO3
|
||||
SUB_PKD2 = MKTAG('P','K','D','2'), // FO3
|
||||
SUB_PKPT = MKTAG('P','K','P','T'), // FO3
|
||||
SUB_PKED = MKTAG('P','K','E','D'), // FO3
|
||||
SUB_PKE2 = MKTAG('P','K','E','2'), // FO3
|
||||
SUB_PKAM = MKTAG('P','K','A','M'), // FO3
|
||||
SUB_PUID = MKTAG('P','U','I','D'), // FO3
|
||||
SUB_PKW3 = MKTAG('P','K','W','3'), // FO3
|
||||
SUB_PTD2 = MKTAG('P','T','D','2'), // FO3
|
||||
SUB_PLD2 = MKTAG('P','L','D','2'), // FO3
|
||||
SUB_PKFD = MKTAG('P','K','F','D'), // FO3
|
||||
SUB_IDLB = MKTAG('I','D','L','B'), // FO3
|
||||
SUB_XDCR = MKTAG('X','D','C','R'), // FO3
|
||||
SUB_DALC = MKTAG('D','A','L','C'), // FO3
|
||||
SUB_IMPS = MKTAG('I','M','P','S'), // FO3 Anchorage
|
||||
SUB_IMPF = MKTAG('I','M','P','F'), // FO3 Anchorage
|
||||
|
||||
SUB_XATO = MKTAG('X','A','T','O'), // FONV
|
||||
SUB_INFC = MKTAG('I','N','F','C'), // FONV
|
||||
SUB_INFX = MKTAG('I','N','F','X'), // FONV
|
||||
SUB_TDUM = MKTAG('T','D','U','M'), // FONV
|
||||
SUB_TCFU = MKTAG('T','C','F','U'), // FONV
|
||||
SUB_DAT2 = MKTAG('D','A','T','2'), // FONV
|
||||
SUB_RCIL = MKTAG('R','C','I','L'), // FONV
|
||||
SUB_MMRK = MKTAG('M','M','R','K'), // FONV
|
||||
SUB_SCRV = MKTAG('S','C','R','V'), // FONV
|
||||
SUB_SCVR = MKTAG('S','C','V','R'), // FONV
|
||||
SUB_SLSD = MKTAG('S','L','S','D'), // FONV
|
||||
SUB_XSRF = MKTAG('X','S','R','F'), // FONV
|
||||
SUB_XSRD = MKTAG('X','S','R','D'), // FONV
|
||||
SUB_WMI1 = MKTAG('W','M','I','1'), // FONV
|
||||
SUB_RDID = MKTAG('R','D','I','D'), // FONV
|
||||
SUB_RDSB = MKTAG('R','D','S','B'), // FONV
|
||||
SUB_RDSI = MKTAG('R','D','S','I'), // FONV
|
||||
SUB_BRUS = MKTAG('B','R','U','S'), // FONV
|
||||
SUB_VATS = MKTAG('V','A','T','S'), // FONV
|
||||
SUB_VANM = MKTAG('V','A','N','M'), // FONV
|
||||
SUB_MWD1 = MKTAG('M','W','D','1'), // FONV
|
||||
SUB_MWD2 = MKTAG('M','W','D','2'), // FONV
|
||||
SUB_MWD3 = MKTAG('M','W','D','3'), // FONV
|
||||
SUB_MWD4 = MKTAG('M','W','D','4'), // FONV
|
||||
SUB_MWD5 = MKTAG('M','W','D','5'), // FONV
|
||||
SUB_MWD6 = MKTAG('M','W','D','6'), // FONV
|
||||
SUB_MWD7 = MKTAG('M','W','D','7'), // FONV
|
||||
SUB_WMI2 = MKTAG('W','M','I','2'), // FONV
|
||||
SUB_WMI3 = MKTAG('W','M','I','3'), // FONV
|
||||
SUB_WMS1 = MKTAG('W','M','S','1'), // FONV
|
||||
SUB_WMS2 = MKTAG('W','M','S','2'), // FONV
|
||||
SUB_WNM1 = MKTAG('W','N','M','1'), // FONV
|
||||
SUB_WNM2 = MKTAG('W','N','M','2'), // FONV
|
||||
SUB_WNM3 = MKTAG('W','N','M','3'), // FONV
|
||||
SUB_WNM4 = MKTAG('W','N','M','4'), // FONV
|
||||
SUB_WNM5 = MKTAG('W','N','M','5'), // FONV
|
||||
SUB_WNM6 = MKTAG('W','N','M','6'), // FONV
|
||||
SUB_WNM7 = MKTAG('W','N','M','7'), // FONV
|
||||
SUB_JNAM = MKTAG('J','N','A','M'), // FONV
|
||||
SUB_EFSD = MKTAG('E','F','S','D'), // FONV DeadMoney
|
||||
};
|
||||
|
||||
enum MagicEffectID
|
||||
{
|
||||
// Alteration
|
||||
EFI_BRDN = MKTAG('B','R','D','N'),
|
||||
EFI_FTHR = MKTAG('F','T','H','R'),
|
||||
EFI_FISH = MKTAG('F','I','S','H'),
|
||||
EFI_FRSH = MKTAG('F','R','S','H'),
|
||||
EFI_OPEN = MKTAG('O','P','N','N'),
|
||||
EFI_SHLD = MKTAG('S','H','L','D'),
|
||||
EFI_LISH = MKTAG('L','I','S','H'),
|
||||
EFI_WABR = MKTAG('W','A','B','R'),
|
||||
EFI_WAWA = MKTAG('W','A','W','A'),
|
||||
|
||||
// Conjuration
|
||||
EFI_BABO = MKTAG('B','A','B','O'), // Bound Boots
|
||||
EFI_BACU = MKTAG('B','A','C','U'), // Bound Cuirass
|
||||
EFI_BAGA = MKTAG('B','A','G','A'), // Bound Gauntlets
|
||||
EFI_BAGR = MKTAG('B','A','G','R'), // Bound Greaves
|
||||
EFI_BAHE = MKTAG('B','A','H','E'), // Bound Helmet
|
||||
EFI_BASH = MKTAG('B','A','S','H'), // Bound Shield
|
||||
EFI_BWAX = MKTAG('B','W','A','X'), // Bound Axe
|
||||
EFI_BWBO = MKTAG('B','W','B','O'), // Bound Bow
|
||||
EFI_BWDA = MKTAG('B','W','D','A'), // Bound Dagger
|
||||
EFI_BWMA = MKTAG('B','W','M','A'), // Bound Mace
|
||||
EFI_BWSW = MKTAG('B','W','S','W'), // Bound Sword
|
||||
EFI_Z001 = MKTAG('Z','0','0','1'), // Summon Rufio's Ghost
|
||||
EFI_Z002 = MKTAG('Z','0','0','2'), // Summon Ancestor Guardian
|
||||
EFI_Z003 = MKTAG('Z','0','0','3'), // Summon Spiderling
|
||||
EFI_Z005 = MKTAG('Z','0','0','5'), // Summon Bear
|
||||
EFI_ZCLA = MKTAG('Z','C','L','A'), // Summon Clannfear
|
||||
EFI_ZDAE = MKTAG('Z','D','A','E'), // Summon Daedroth
|
||||
EFI_ZDRE = MKTAG('Z','D','R','E'), // Summon Dremora
|
||||
EFI_ZDRL = MKTAG('Z','D','R','L'), // Summon Dremora Lord
|
||||
EFI_ZFIA = MKTAG('Z','F','I','A'), // Summon Flame Atronach
|
||||
EFI_ZFRA = MKTAG('Z','F','R','A'), // Summon Frost Atronach
|
||||
EFI_ZGHO = MKTAG('Z','G','H','O'), // Summon Ghost
|
||||
EFI_ZHDZ = MKTAG('Z','H','D','Z'), // Summon Headless Zombie
|
||||
EFI_ZLIC = MKTAG('Z','L','I','C'), // Summon Lich
|
||||
EFI_ZSCA = MKTAG('Z','S','C','A'), // Summon Scamp
|
||||
EFI_ZSKE = MKTAG('Z','S','K','E'), // Summon Skeleton
|
||||
EFI_ZSKA = MKTAG('Z','S','K','A'), // Summon Skeleton Guardian
|
||||
EFI_ZSKH = MKTAG('Z','S','K','H'), // Summon Skeleton Hero
|
||||
EFI_ZSKC = MKTAG('Z','S','K','C'), // Summon Skeleton Champion
|
||||
EFI_ZSPD = MKTAG('Z','S','P','D'), // Summon Spider Daedra
|
||||
EFI_ZSTA = MKTAG('Z','S','T','A'), // Summon Storm Atronach
|
||||
EFI_ZWRA = MKTAG('Z','W','R','A'), // Summon Faded Wraith
|
||||
EFI_ZWRL = MKTAG('Z','W','R','L'), // Summon Gloom Wraith
|
||||
EFI_ZXIV = MKTAG('Z','X','I','V'), // Summon Xivilai
|
||||
EFI_ZZOM = MKTAG('Z','Z','O','M'), // Summon Zombie
|
||||
EFI_TURN = MKTAG('T','U','R','N'), // Turn Undead
|
||||
|
||||
// Destruction
|
||||
EFI_DGAT = MKTAG('D','G','A','T'), // Damage Attribute
|
||||
EFI_DGFA = MKTAG('D','G','F','A'), // Damage Fatigue
|
||||
EFI_DGHE = MKTAG('D','G','H','E'), // Damage Health
|
||||
EFI_DGSP = MKTAG('D','G','S','P'), // Damage Magicka
|
||||
EFI_DIAR = MKTAG('D','I','A','R'), // Disintegrate Armor
|
||||
EFI_DIWE = MKTAG('D','I','W','E'), // Disintegrate Weapon
|
||||
EFI_DRAT = MKTAG('D','R','A','T'), // Drain Attribute
|
||||
EFI_DRFA = MKTAG('D','R','F','A'), // Drain Fatigue
|
||||
EFI_DRHE = MKTAG('D','R','H','E'), // Drain Health
|
||||
EFI_DRSP = MKTAG('D','R','S','P'), // Drain Magicka
|
||||
EFI_DRSK = MKTAG('D','R','S','K'), // Drain Skill
|
||||
EFI_FIDG = MKTAG('F','I','D','G'), // Fire Damage
|
||||
EFI_FRDG = MKTAG('F','R','D','G'), // Frost Damage
|
||||
EFI_SHDG = MKTAG('S','H','D','G'), // Shock Damage
|
||||
EFI_WKDI = MKTAG('W','K','D','I'), // Weakness to Disease
|
||||
EFI_WKFI = MKTAG('W','K','F','I'), // Weakness to Fire
|
||||
EFI_WKFR = MKTAG('W','K','F','R'), // Weakness to Frost
|
||||
EFI_WKMA = MKTAG('W','K','M','A'), // Weakness to Magic
|
||||
EFI_WKNW = MKTAG('W','K','N','W'), // Weakness to Normal Weapons
|
||||
EFI_WKPO = MKTAG('W','K','P','O'), // Weakness to Poison
|
||||
EFI_WKSH = MKTAG('W','K','S','H'), // Weakness to Shock
|
||||
|
||||
// Illusion
|
||||
EFI_CALM = MKTAG('C','A','L','M'), // Calm
|
||||
EFI_CHML = MKTAG('C','H','M','L'), // Chameleon
|
||||
EFI_CHRM = MKTAG('C','H','R','M'), // Charm
|
||||
EFI_COCR = MKTAG('C','O','C','R'), // Command Creature
|
||||
EFI_COHU = MKTAG('C','O','H','U'), // Command Humanoid
|
||||
EFI_DEMO = MKTAG('D','E','M','O'), // Demoralize
|
||||
EFI_FRNZ = MKTAG('F','R','N','Z'), // Frenzy
|
||||
EFI_INVI = MKTAG('I','N','V','I'), // Invisibility
|
||||
EFI_LGHT = MKTAG('L','G','H','T'), // Light
|
||||
EFI_NEYE = MKTAG('N','E','Y','E'), // Night-Eye
|
||||
EFI_PARA = MKTAG('P','A','R','A'), // Paralyze
|
||||
EFI_RALY = MKTAG('R','A','L','Y'), // Rally
|
||||
EFI_SLNC = MKTAG('S','L','N','C'), // Silence
|
||||
|
||||
// Mysticism
|
||||
EFI_DTCT = MKTAG('D','T','C','T'), // Detect Life
|
||||
EFI_DSPL = MKTAG('D','S','P','L'), // Dispel
|
||||
EFI_REDG = MKTAG('R','E','D','G'), // Reflect Damage
|
||||
EFI_RFLC = MKTAG('R','F','L','C'), // Reflect Spell
|
||||
EFI_STRP = MKTAG('S','T','R','P'), // Soul Trap
|
||||
EFI_SABS = MKTAG('S','A','B','S'), // Spell Absorption
|
||||
EFI_TELE = MKTAG('T','E','L','E'), // Telekinesis
|
||||
|
||||
// Restoration
|
||||
EFI_ABAT = MKTAG('A','B','A','T'), // Absorb Attribute
|
||||
EFI_ABFA = MKTAG('A','B','F','A'), // Absorb Fatigue
|
||||
EFI_ABHe = MKTAG('A','B','H','e'), // Absorb Health
|
||||
EFI_ABSP = MKTAG('A','B','S','P'), // Absorb Magicka
|
||||
EFI_ABSK = MKTAG('A','B','S','K'), // Absorb Skill
|
||||
EFI_1400 = MKTAG('1','4','0','0'), // Cure Disease
|
||||
EFI_CUPA = MKTAG('C','U','P','A'), // Cure Paralysis
|
||||
EFI_CUPO = MKTAG('C','U','P','O'), // Cure Poison
|
||||
EFI_FOAT = MKTAG('F','O','A','T'), // Fortify Attribute
|
||||
EFI_FOFA = MKTAG('F','O','F','A'), // Fortify Fatigue
|
||||
EFI_FOHE = MKTAG('F','O','H','E'), // Fortify Health
|
||||
EFI_FOSP = MKTAG('F','O','S','P'), // Fortify Magicka
|
||||
EFI_FOSK = MKTAG('F','O','S','K'), // Fortify Skill
|
||||
EFI_RSDI = MKTAG('R','S','D','I'), // Resist Disease
|
||||
EFI_RSFI = MKTAG('R','S','F','I'), // Resist Fire
|
||||
EFI_RSFR = MKTAG('R','S','F','R'), // Resist Frost
|
||||
EFI_RSMA = MKTAG('R','S','M','A'), // Resist Magic
|
||||
EFI_RSNW = MKTAG('R','S','N','W'), // Resist Normal Weapons
|
||||
EFI_RSPA = MKTAG('R','S','P','A'), // Resist Paralysis
|
||||
EFI_RSPO = MKTAG('R','S','P','O'), // Resist Poison
|
||||
EFI_RSSH = MKTAG('R','S','S','H'), // Resist Shock
|
||||
EFI_REAT = MKTAG('R','E','A','T'), // Restore Attribute
|
||||
EFI_REFA = MKTAG('R','E','F','A'), // Restore Fatigue
|
||||
EFI_REHE = MKTAG('R','E','H','E'), // Restore Health
|
||||
EFI_RESP = MKTAG('R','E','S','P'), // Restore Magicka
|
||||
|
||||
// Effects
|
||||
EFI_LOCK = MKTAG('L','O','C','K'), // Lock Lock
|
||||
EFI_SEFF = MKTAG('S','E','F','F'), // Script Effect
|
||||
EFI_Z020 = MKTAG('Z','0','2','0'), // Summon 20 Extra
|
||||
EFI_MYHL = MKTAG('M','Y','H','L'), // Summon Mythic Dawn Helmet
|
||||
EFI_MYTH = MKTAG('M','Y','T','H'), // Summon Mythic Dawn Armor
|
||||
EFI_REAN = MKTAG('R','E','A','N'), // Reanimate
|
||||
EFI_DISE = MKTAG('D','I','S','E'), // Disease Info
|
||||
EFI_POSN = MKTAG('P','O','S','N'), // Poison Info
|
||||
EFI_DUMY = MKTAG('D','U','M','Y'), // Mehrunes Dagon Custom Effect
|
||||
EFI_STMA = MKTAG('S','T','M','A'), // Stunted Magicka
|
||||
EFI_SUDG = MKTAG('S','U','D','G'), // Sun Damage
|
||||
EFI_VAMP = MKTAG('V','A','M','P'), // Vampirism
|
||||
EFI_DARK = MKTAG('D','A','R','K'), // Darkness
|
||||
EFI_RSWD = MKTAG('R','S','W','D') // Resist Water Damage
|
||||
};
|
||||
|
||||
// Based on http://www.uesp.net/wiki/Tes5Mod:Mod_File_Format#Groups
|
||||
enum GroupType
|
||||
{
|
||||
Grp_RecordType = 0,
|
||||
Grp_WorldChild = 1,
|
||||
Grp_InteriorCell = 2,
|
||||
Grp_InteriorSubCell = 3,
|
||||
Grp_ExteriorCell = 4,
|
||||
Grp_ExteriorSubCell = 5,
|
||||
Grp_CellChild = 6,
|
||||
Grp_TopicChild = 7,
|
||||
Grp_CellPersistentChild = 8,
|
||||
Grp_CellTemporaryChild = 9,
|
||||
Grp_CellVisibleDistChild = 10
|
||||
};
|
||||
|
||||
// Based on http://www.uesp.net/wiki/Tes5Mod:Mod_File_Format#Records
|
||||
enum RecordFlag
|
||||
{
|
||||
Rec_ESM = 0x00000001, // (TES4 record only) Master (ESM) file.
|
||||
Rec_Deleted = 0x00000020, // Deleted
|
||||
Rec_Constant = 0x00000040, // Constant
|
||||
Rec_HiddenLMap = 0x00000040, // (REFR) Hidden From Local Map (Needs Confirmation: Related to shields)
|
||||
Rec_Localized = 0x00000080, // (TES4 record only) Is localized. This will make Skyrim load the
|
||||
// .STRINGS, .DLSTRINGS, and .ILSTRINGS files associated with the mod.
|
||||
// If this flag is not set, lstrings are treated as zstrings.
|
||||
Rec_FireOff = 0x00000080, // (PHZD) Turn off fire
|
||||
Rec_UpdateAnim = 0x00000100, // Must Update Anims
|
||||
Rec_NoAccess = 0x00000100, // (REFR) Inaccessible
|
||||
Rec_Hidden = 0x00000200, // (REFR) Hidden from local map
|
||||
Rec_StartDead = 0x00000200, // (ACHR) Starts dead /(REFR) MotionBlurCastsShadows
|
||||
Rec_Persistent = 0x00000400, // Quest item / Persistent reference
|
||||
Rec_DispMenu = 0x00000400, // (LSCR) Displays in Main Menu
|
||||
Rec_Disabled = 0x00000800, // Initially disabled
|
||||
Rec_Ignored = 0x00001000, // Ignored
|
||||
Rec_VisDistant = 0x00008000, // Visible when distant
|
||||
Rec_RandAnim = 0x00010000, // (ACTI) Random Animation Start
|
||||
Rec_Danger = 0x00020000, // (ACTI) Dangerous / Off limits (Interior cell)
|
||||
// Dangerous Can't be set withough Ignore Object Interaction
|
||||
Rec_Compressed = 0x00040000, // Data is compressed
|
||||
Rec_CanNotWait = 0x00080000, // Can't wait
|
||||
Rec_IgnoreObj = 0x00100000, // (ACTI) Ignore Object Interaction
|
||||
// Ignore Object Interaction Sets Dangerous Automatically
|
||||
Rec_Marker = 0x00800000, // Is Marker
|
||||
Rec_Obstacle = 0x02000000, // (ACTI) Obstacle / (REFR) No AI Acquire
|
||||
Rec_NavMFilter = 0x04000000, // NavMesh Gen - Filter
|
||||
Rec_NavMBBox = 0x08000000, // NavMesh Gen - Bounding Box
|
||||
Rec_ExitToTalk = 0x10000000, // (FURN) Must Exit to Talk
|
||||
Rec_Refected = 0x10000000, // (REFR) Reflected By Auto Water
|
||||
Rec_ChildUse = 0x20000000, // (FURN/IDLM) Child Can Use
|
||||
Rec_NoHavok = 0x20000000, // (REFR) Don't Havok Settle
|
||||
Rec_NavMGround = 0x40000000, // NavMesh Gen - Ground
|
||||
Rec_NoRespawn = 0x40000000, // (REFR) NoRespawn
|
||||
Rec_MultiBound = 0x80000000 // (REFR) MultiBound
|
||||
};
|
||||
|
||||
#pragma pack(push, 1)
|
||||
// NOTE: the label field of a group is not reliable (http://www.uesp.net/wiki/Tes4Mod:Mod_File_Format)
|
||||
union GroupLabel
|
||||
{
|
||||
std::uint32_t value; // formId, blockNo or raw int representation of type
|
||||
char recordType[4]; // record type in ascii
|
||||
std::int16_t grid[2]; // grid y, x (note the reverse order)
|
||||
};
|
||||
|
||||
struct GroupTypeHeader
|
||||
{
|
||||
std::uint32_t typeId;
|
||||
std::uint32_t groupSize; // includes the 24 bytes (20 for TES4) of header (i.e. this struct)
|
||||
GroupLabel label; // format based on type
|
||||
std::int32_t type;
|
||||
std::uint16_t stamp; // & 0xff for day, & 0xff00 for months since Dec 2002 (i.e. 1 = Jan 2003)
|
||||
std::uint16_t unknown;
|
||||
std::uint16_t version; // not in TES4
|
||||
std::uint16_t unknown2; // not in TES4
|
||||
};
|
||||
|
||||
struct RecordTypeHeader
|
||||
{
|
||||
std::uint32_t typeId;
|
||||
std::uint32_t dataSize; // does *not* include 24 bytes (20 for TES4) of header
|
||||
std::uint32_t flags;
|
||||
FormId id;
|
||||
std::uint32_t revision;
|
||||
std::uint16_t version; // not in TES4
|
||||
std::uint16_t unknown; // not in TES4
|
||||
};
|
||||
|
||||
union RecordHeader
|
||||
{
|
||||
struct GroupTypeHeader group;
|
||||
struct RecordTypeHeader record;
|
||||
};
|
||||
|
||||
struct SubRecordHeader
|
||||
{
|
||||
std::uint32_t typeId;
|
||||
std::uint16_t dataSize;
|
||||
};
|
||||
|
||||
// Grid, CellGrid and Vertex are shared by NVMI(NAVI) and NVNM(NAVM)
|
||||
|
||||
struct Grid
|
||||
{
|
||||
std::int16_t x;
|
||||
std::int16_t y;
|
||||
};
|
||||
|
||||
union CellGrid
|
||||
{
|
||||
FormId cellId;
|
||||
Grid grid;
|
||||
};
|
||||
|
||||
struct Vertex
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
// For pretty printing GroupHeader labels
|
||||
std::string printLabel(const GroupLabel& label, const std::uint32_t type);
|
||||
|
||||
void gridToString(std::int16_t x, std::int16_t y, std::string& str);
|
||||
}
|
||||
|
||||
#endif // ESM4_COMMON_H
|
@ -0,0 +1,46 @@
|
||||
/*
|
||||
Copyright (C) 2020 cc9cii
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
cc9cii cc9c@iinet.net.au
|
||||
|
||||
Much of the information on the data structures are based on the information
|
||||
from Tes4Mod:Mod_File_Format and Tes5Mod:File_Formats but also refined by
|
||||
trial & error. See http://en.uesp.net/wiki for details.
|
||||
|
||||
*/
|
||||
#ifndef ESM4_DIALOGUE_H
|
||||
#define ESM4_DIALOGUE_H
|
||||
|
||||
namespace ESM4
|
||||
{
|
||||
enum DialType
|
||||
{
|
||||
DTYP_Topic = 0,
|
||||
DTYP_Conversation = 1,
|
||||
DTYP_Combat = 2,
|
||||
DTYP_Persuation = 3,
|
||||
DTYP_Detection = 4,
|
||||
DTYP_Service = 5,
|
||||
DTYP_Miscellaneous = 6,
|
||||
// below FO3/FONV
|
||||
DTYP_Radio = 7
|
||||
};
|
||||
}
|
||||
|
||||
#endif // ESM4_DIALOGUE_H
|
@ -0,0 +1,56 @@
|
||||
/*
|
||||
Copyright (C) 2020 cc9cii
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
cc9cii cc9c@iinet.net.au
|
||||
|
||||
Much of the information on the data structures are based on the information
|
||||
from Tes4Mod:Mod_File_Format and Tes5Mod:File_Formats but also refined by
|
||||
trial & error. See http://en.uesp.net/wiki for details.
|
||||
|
||||
*/
|
||||
#ifndef ESM4_EFFECT_H
|
||||
#define ESM4_EFFECT_H
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "formid.hpp"
|
||||
|
||||
namespace ESM4
|
||||
{
|
||||
#pragma pack(push, 1)
|
||||
union EFI_Label
|
||||
{
|
||||
std::uint32_t value;
|
||||
char effect[4];
|
||||
};
|
||||
|
||||
struct ScriptEffect
|
||||
{
|
||||
FormId 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
|
||||
std::uint8_t unknown1;
|
||||
std::uint8_t unknown2;
|
||||
std::uint8_t unknown3;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
}
|
||||
|
||||
#endif // ESM4_EFFECT_H
|
@ -0,0 +1,78 @@
|
||||
/*
|
||||
Copyright (C) 2016, 2020-2021 cc9cii
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
cc9cii cc9c@iinet.net.au
|
||||
|
||||
*/
|
||||
#include "formid.hpp"
|
||||
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
#include <cstdlib> // strtol
|
||||
#include <climits> // LONG_MIN, LONG_MAX for gcc
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace ESM4
|
||||
{
|
||||
void formIdToString(FormId formId, std::string& str)
|
||||
{
|
||||
char buf[8+1];
|
||||
int res = snprintf(buf, 8+1, "%08X", formId);
|
||||
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;
|
||||
|
||||
char *tmp;
|
||||
errno = 0;
|
||||
unsigned long val = strtol(str.c_str(), &tmp, 16);
|
||||
|
||||
if (tmp == str.c_str() || *tmp != '\0'
|
||||
|| ((val == (unsigned long)LONG_MIN || val == (unsigned long)LONG_MAX) && errno == ERANGE))
|
||||
return false;
|
||||
|
||||
if (id != nullptr)
|
||||
*id = static_cast<FormId>(val);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
FormId stringToFormId(const std::string& str)
|
||||
{
|
||||
if (str.size() != 8)
|
||||
throw std::out_of_range("StringToFormId: incorrect string size");
|
||||
|
||||
return static_cast<FormId>(std::stoul(str, nullptr, 16));
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
Copyright (C) 2016 cc9cii
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
cc9cii cc9c@iinet.net.au
|
||||
|
||||
*/
|
||||
#ifndef ESM4_FORMID_H
|
||||
#define ESM4_FORMID_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
#endif // ESM4_FORMID_H
|
@ -0,0 +1,55 @@
|
||||
/*
|
||||
Copyright (C) 2020 cc9cii
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
cc9cii cc9c@iinet.net.au
|
||||
|
||||
Much of the information on the data structures are based on the information
|
||||
from Tes4Mod:Mod_File_Format and Tes5Mod:File_Formats but also refined by
|
||||
trial & error. See http://en.uesp.net/wiki for details.
|
||||
|
||||
*/
|
||||
#ifndef ESM4_INVENTORY_H
|
||||
#define ESM4_INVENTORY_H
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "formid.hpp"
|
||||
|
||||
namespace ESM4
|
||||
{
|
||||
#pragma pack(push, 1)
|
||||
// LVLC, LVLI
|
||||
struct LVLO
|
||||
{
|
||||
std::int16_t level;
|
||||
std::uint16_t unknown; // sometimes missing
|
||||
FormId item;
|
||||
std::int16_t count;
|
||||
std::uint16_t unknown2; // sometimes missing
|
||||
};
|
||||
|
||||
struct InventoryItem // NPC_, CREA, CONT
|
||||
{
|
||||
FormId item;
|
||||
std::uint32_t count;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
}
|
||||
|
||||
#endif // ESM4_INVENTORY_H
|
@ -0,0 +1,79 @@
|
||||
/*
|
||||
Copyright (C) 2020 cc9cii
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
cc9cii cc9c@iinet.net.au
|
||||
|
||||
Much of the information on the data structures are based on the information
|
||||
from Tes4Mod:Mod_File_Format and Tes5Mod:File_Formats but also refined by
|
||||
trial & error. See http://en.uesp.net/wiki for details.
|
||||
|
||||
*/
|
||||
#ifndef ESM4_LIGHTING_H
|
||||
#define ESM4_LIGHTING_H
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace ESM4
|
||||
{
|
||||
#pragma pack(push, 1)
|
||||
// guesses only for TES4
|
||||
struct Lighting
|
||||
{ // | Aichan Prison values
|
||||
std::uint32_t ambient; // | 16 17 19 00 (RGBA)
|
||||
std::uint32_t directional; // | 00 00 00 00 (RGBA)
|
||||
std::uint32_t fogColor; // | 1D 1B 16 00 (RGBA)
|
||||
float fogNear; // Fog Near | 00 00 00 00 = 0.f
|
||||
float fogFar; // Fog Far | 00 80 3B 45 = 3000.f
|
||||
std::int32_t rotationXY; // rotation xy | 00 00 00 00 = 0
|
||||
std::int32_t rotationZ; // rotation z | 00 00 00 00 = 0
|
||||
float fogDirFade; // Fog dir fade | 00 00 80 3F = 1.f
|
||||
float fogClipDist; // Fog clip dist | 00 80 3B 45 = 3000.f
|
||||
float fogPower;
|
||||
};
|
||||
|
||||
struct Lighting_TES5
|
||||
{
|
||||
std::uint32_t ambient;
|
||||
std::uint32_t directional;
|
||||
std::uint32_t fogColor;
|
||||
float fogNear;
|
||||
float fogFar;
|
||||
std::int32_t rotationXY;
|
||||
std::int32_t rotationZ;
|
||||
float fogDirFade;
|
||||
float fogClipDist;
|
||||
float fogPower;
|
||||
std::uint32_t unknown1;
|
||||
std::uint32_t unknown2;
|
||||
std::uint32_t unknown3;
|
||||
std::uint32_t unknown4;
|
||||
std::uint32_t unknown5;
|
||||
std::uint32_t unknown6;
|
||||
std::uint32_t unknown7;
|
||||
std::uint32_t unknown8;
|
||||
std::uint32_t fogColorFar;
|
||||
float fogMax;
|
||||
float LightFadeStart;
|
||||
float LightFadeEnd;
|
||||
std::uint32_t padding;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
}
|
||||
|
||||
#endif // ESM4_LIGHTING_H
|
@ -0,0 +1,124 @@
|
||||
/*
|
||||
Copyright (C) 2016, 2018, 2020-2021 cc9cii
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
cc9cii cc9c@iinet.net.au
|
||||
|
||||
Much of the information on the data structures are based on the information
|
||||
from Tes4Mod:Mod_File_Format and Tes5Mod:File_Formats but also refined by
|
||||
trial & error. See http://en.uesp.net/wiki for details.
|
||||
|
||||
*/
|
||||
#include "loadachr.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
//#include <iostream>
|
||||
|
||||
#include "reader.hpp"
|
||||
//#include "writer.hpp"
|
||||
|
||||
ESM4::ActorCharacter::ActorCharacter() : mFormId(0), mFlags(0), mBaseObj(0),
|
||||
mScale(1.f), mOwner(0), mGlobal(0), mInitiallyDisabled(false)
|
||||
{
|
||||
mEditorId.clear();
|
||||
mFullName.clear();
|
||||
|
||||
mEsp.parent = 0;
|
||||
mEsp.flags = 0;
|
||||
}
|
||||
|
||||
ESM4::ActorCharacter::~ActorCharacter()
|
||||
{
|
||||
}
|
||||
|
||||
void ESM4::ActorCharacter::load(ESM4::Reader& reader)
|
||||
{
|
||||
mFormId = reader.hdr().record.id;
|
||||
reader.adjustFormId(mFormId);
|
||||
mFlags = reader.hdr().record.flags;
|
||||
mParent = reader.currCell(); // NOTE: only for persistent achr? (aren't they all persistent?)
|
||||
|
||||
while (reader.getSubRecordHeader())
|
||||
{
|
||||
const ESM4::SubRecordHeader& subHdr = reader.subRecordHeader();
|
||||
switch (subHdr.typeId)
|
||||
{
|
||||
case ESM4::SUB_EDID: reader.getZString(mEditorId); break;
|
||||
case ESM4::SUB_FULL: reader.getZString(mFullName); break;
|
||||
case ESM4::SUB_NAME: reader.getFormId(mBaseObj); break;
|
||||
case ESM4::SUB_DATA: reader.get(mPlacement); break;
|
||||
case ESM4::SUB_XSCL: reader.get(mScale); break;
|
||||
case ESM4::SUB_XOWN: reader.get(mOwner); break;
|
||||
case ESM4::SUB_XESP:
|
||||
{
|
||||
reader.get(mEsp);
|
||||
reader.adjustFormId(mEsp.parent);
|
||||
break;
|
||||
}
|
||||
case ESM4::SUB_XRGD: // ragdoll
|
||||
case ESM4::SUB_XRGB: // ragdoll biped
|
||||
{
|
||||
//std::cout << "ACHR " << ESM::printName(subHdr.typeId) << " skipping..." << std::endl;
|
||||
reader.skipSubRecordData();
|
||||
break;
|
||||
}
|
||||
case ESM4::SUB_XHRS: // horse formId
|
||||
case ESM4::SUB_XMRC: // merchant container formId
|
||||
// TES5
|
||||
case ESM4::SUB_XAPD: // activation parent
|
||||
case ESM4::SUB_XAPR: // active parent
|
||||
case ESM4::SUB_XEZN: // encounter zone
|
||||
case ESM4::SUB_XHOR:
|
||||
case ESM4::SUB_XLCM: // levelled creature
|
||||
case ESM4::SUB_XLCN: // location
|
||||
case ESM4::SUB_XLKR: // location route?
|
||||
case ESM4::SUB_XLRT: // location type
|
||||
//
|
||||
case ESM4::SUB_XPRD:
|
||||
case ESM4::SUB_XPPA:
|
||||
case ESM4::SUB_INAM:
|
||||
case ESM4::SUB_PDTO:
|
||||
//
|
||||
case ESM4::SUB_XIS2:
|
||||
case ESM4::SUB_XPCI: // formId
|
||||
case ESM4::SUB_XLOD:
|
||||
case ESM4::SUB_VMAD:
|
||||
case ESM4::SUB_XLRL: // Unofficial Skyrim Patch
|
||||
case ESM4::SUB_XRDS: // FO3
|
||||
case ESM4::SUB_XIBS: // FO3
|
||||
case ESM4::SUB_SCHR: // FO3
|
||||
case ESM4::SUB_TNAM: // FO3
|
||||
case ESM4::SUB_XATO: // FONV
|
||||
{
|
||||
//std::cout << "ACHR " << ESM::printName(subHdr.typeId) << " skipping..." << std::endl;
|
||||
reader.skipSubRecordData();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw std::runtime_error("ESM4::ACHR::load - Unknown subrecord " + ESM::printName(subHdr.typeId));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//void ESM4::ActorCharacter::save(ESM4::Writer& writer) const
|
||||
//{
|
||||
//}
|
||||
|
||||
//void ESM4::ActorCharacter::blank()
|
||||
//{
|
||||
//}
|
@ -0,0 +1,70 @@
|
||||
/*
|
||||
Copyright (C) 2016, 2018, 2020-2021 cc9cii
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
cc9cii cc9c@iinet.net.au
|
||||
|
||||
Much of the information on the data structures are based on the information
|
||||
from Tes4Mod:Mod_File_Format and Tes5Mod:File_Formats but also refined by
|
||||
trial & error. See http://en.uesp.net/wiki for details.
|
||||
|
||||
*/
|
||||
#ifndef ESM4_ACHR_H
|
||||
#define ESM4_ACHR_H
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "reference.hpp" // FormId, Placement, EnableParent
|
||||
|
||||
namespace ESM4
|
||||
{
|
||||
class Reader;
|
||||
class Writer;
|
||||
|
||||
struct ActorCharacter
|
||||
{
|
||||
FormId mParent; // cell formId, from the loading sequence
|
||||
// NOTE: for exterior cells it will be the dummy cell FormId
|
||||
|
||||
FormId mFormId; // from the header
|
||||
std::uint32_t mFlags; // from the header, see enum type RecordFlag for details
|
||||
|
||||
std::string mEditorId;
|
||||
std::string mFullName;
|
||||
FormId mBaseObj;
|
||||
|
||||
Placement mPlacement;
|
||||
float mScale; // default 1.f
|
||||
FormId mOwner;
|
||||
FormId mGlobal;
|
||||
|
||||
bool mInitiallyDisabled; // TODO may need to check mFlags & 0x800 (initially disabled)
|
||||
|
||||
EnableParent mEsp;
|
||||
|
||||
ActorCharacter();
|
||||
virtual ~ActorCharacter();
|
||||
|
||||
virtual void load(ESM4::Reader& reader);
|
||||
//virtual void save(ESM4::Writer& writer) const;
|
||||
|
||||
//void blank();
|
||||
};
|
||||
}
|
||||
|
||||
#endif // ESM4_ACHR_H
|
@ -0,0 +1,106 @@
|
||||
/*
|
||||
Copyright (C) 2016, 2018, 2020 cc9cii
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
cc9cii cc9c@iinet.net.au
|
||||
|
||||
Much of the information on the data structures are based on the information
|
||||
from Tes4Mod:Mod_File_Format and Tes5Mod:File_Formats but also refined by
|
||||
trial & error. See http://en.uesp.net/wiki for details.
|
||||
|
||||
*/
|
||||
#include "loadacre.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
//#include <iostream>
|
||||
|
||||
#include "reader.hpp"
|
||||
//#include "writer.hpp"
|
||||
|
||||
ESM4::ActorCreature::ActorCreature() : mFormId(0), mFlags(0), mBaseObj(0), mScale(1.f),
|
||||
mOwner(0), mGlobal(0), mFactionRank(0), mInitiallyDisabled(false)
|
||||
{
|
||||
mEditorId.clear();
|
||||
|
||||
mEsp.parent = 0;
|
||||
mEsp.flags = 0;
|
||||
}
|
||||
|
||||
ESM4::ActorCreature::~ActorCreature()
|
||||
{
|
||||
}
|
||||
|
||||
void ESM4::ActorCreature::load(ESM4::Reader& reader)
|
||||
{
|
||||
mFormId = reader.hdr().record.id;
|
||||
reader.adjustFormId(mFormId);
|
||||
mFlags = reader.hdr().record.flags;
|
||||
|
||||
while (reader.getSubRecordHeader())
|
||||
{
|
||||
const ESM4::SubRecordHeader& subHdr = reader.subRecordHeader();
|
||||
switch (subHdr.typeId)
|
||||
{
|
||||
case ESM4::SUB_EDID: reader.getZString(mEditorId); break;
|
||||
case ESM4::SUB_NAME: reader.getFormId(mBaseObj); break;
|
||||
case ESM4::SUB_DATA: reader.get(mPlacement); break;
|
||||
case ESM4::SUB_XSCL: reader.get(mScale); break;
|
||||
case ESM4::SUB_XESP:
|
||||
{
|
||||
reader.get(mEsp);
|
||||
reader.adjustFormId(mEsp.parent);
|
||||
break;
|
||||
}
|
||||
case ESM4::SUB_XOWN: reader.getFormId(mOwner); break;
|
||||
case ESM4::SUB_XGLB: reader.get(mGlobal); break; // FIXME: formId?
|
||||
case ESM4::SUB_XRNK: reader.get(mFactionRank); break;
|
||||
case ESM4::SUB_XRGD: // ragdoll
|
||||
case ESM4::SUB_XRGB: // ragdoll biped
|
||||
{
|
||||
// seems to occur only for dead bodies, e.g. DeadMuffy, DeadDogVicious
|
||||
//std::cout << "ACRE " << ESM::printName(subHdr.typeId) << " skipping..." << std::endl;
|
||||
reader.skipSubRecordData();
|
||||
break;
|
||||
}
|
||||
case ESM4::SUB_XLKR: // FO3
|
||||
case ESM4::SUB_XLCM: // FO3
|
||||
case ESM4::SUB_XEZN: // FO3
|
||||
case ESM4::SUB_XMRC: // FO3
|
||||
case ESM4::SUB_XAPD: // FO3
|
||||
case ESM4::SUB_XAPR: // FO3
|
||||
case ESM4::SUB_XRDS: // FO3
|
||||
case ESM4::SUB_XPRD: // FO3
|
||||
case ESM4::SUB_XATO: // FONV
|
||||
{
|
||||
//std::cout << "ACRE " << ESM::printName(subHdr.typeId) << " skipping..." << std::endl;
|
||||
reader.skipSubRecordData();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw std::runtime_error("ESM4::ACRE::load - Unknown subrecord " + ESM::printName(subHdr.typeId));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//void ESM4::ActorCreature::save(ESM4::Writer& writer) const
|
||||
//{
|
||||
//}
|
||||
|
||||
//void ESM4::ActorCreature::blank()
|
||||
//{
|
||||
//}
|
@ -0,0 +1,67 @@
|
||||
/*
|
||||
Copyright (C) 2016, 2018, 2020 cc9cii
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
cc9cii cc9c@iinet.net.au
|
||||
|
||||
Much of the information on the data structures are based on the information
|
||||
from Tes4Mod:Mod_File_Format and Tes5Mod:File_Formats but also refined by
|
||||
trial & error. See http://en.uesp.net/wiki for details.
|
||||
|
||||
*/
|
||||
#ifndef ESM4_ACRE_H
|
||||
#define ESM4_ACRE_H
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "reference.hpp" // FormId, Placement, EnableParent
|
||||
|
||||
namespace ESM4
|
||||
{
|
||||
class Reader;
|
||||
class Writer;
|
||||
|
||||
struct ActorCreature
|
||||
{
|
||||
FormId mFormId; // from the header
|
||||
std::uint32_t mFlags; // from the header, see enum type RecordFlag for details
|
||||
|
||||
std::string mEditorId;
|
||||
FormId mBaseObj;
|
||||
|
||||
Placement mPlacement;
|
||||
float mScale; // default 1.f
|
||||
FormId mOwner;
|
||||
FormId mGlobal;
|
||||
std::uint32_t mFactionRank;
|
||||
|
||||
bool mInitiallyDisabled; // TODO may need to check mFlags & 0x800 (initially disabled)
|
||||
|
||||
EnableParent mEsp;
|
||||
|
||||
ActorCreature();
|
||||
virtual ~ActorCreature();
|
||||
|
||||
virtual void load(ESM4::Reader& reader);
|
||||
//virtual void save(ESM4::Writer& writer) const;
|
||||
|
||||
//void blank();
|
||||
};
|
||||
}
|
||||
|
||||
#endif // ESM4_ACRE_H
|
@ -0,0 +1,103 @@
|
||||
/*
|
||||
Copyright (C) 2016, 2018, 2020-2021 cc9cii
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
cc9cii cc9c@iinet.net.au
|
||||
|
||||
Much of the information on the data structures are based on the information
|
||||
from Tes4Mod:Mod_File_Format and Tes5Mod:File_Formats but also refined by
|
||||
trial & error. See http://en.uesp.net/wiki for details.
|
||||
|
||||
*/
|
||||
#include "acti.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <iostream> // FIXME
|
||||
|
||||
#include "reader.hpp"
|
||||
//#include "writer.hpp"
|
||||
|
||||
ESM4::Activator::Activator() : mFormId(0), mFlags(0), mScriptId(0), mLoopingSound(0), mActivationSound(0),
|
||||
mBoundRadius(0.f), mRadioTemplate(0), mRadioStation(0)
|
||||
{
|
||||
mEditorId.clear();
|
||||
mFullName.clear();
|
||||
mModel.clear();
|
||||
|
||||
mActivationPrompt.clear();
|
||||
}
|
||||
|
||||
ESM4::Activator::~Activator()
|
||||
{
|
||||
}
|
||||
|
||||
void ESM4::Activator::load(ESM4::Reader& reader)
|
||||
{
|
||||
mFormId = reader.hdr().record.id;
|
||||
reader.adjustFormId(mFormId);
|
||||
mFlags = reader.hdr().record.flags;
|
||||
|
||||
while (reader.getSubRecordHeader())
|
||||
{
|
||||
const ESM4::SubRecordHeader& subHdr = reader.subRecordHeader();
|
||||
switch (subHdr.typeId)
|
||||
{
|
||||
case ESM4::SUB_EDID: reader.getZString(mEditorId); break;
|
||||
case ESM4::SUB_FULL: reader.getLocalizedString(mFullName); break;
|
||||
case ESM4::SUB_MODL: reader.getZString(mModel); break;
|
||||
case ESM4::SUB_SCRI: reader.getFormId(mScriptId); break;
|
||||
case ESM4::SUB_SNAM: reader.getFormId(mLoopingSound); break;
|
||||
case ESM4::SUB_VNAM: reader.getFormId(mActivationSound); break;
|
||||
case ESM4::SUB_MODB: reader.get(mBoundRadius); break;
|
||||
case ESM4::SUB_INAM: reader.getFormId(mRadioTemplate); break; // FONV
|
||||
case ESM4::SUB_RNAM: reader.getFormId(mRadioStation); break;
|
||||
case ESM4::SUB_XATO: reader.getZString(mActivationPrompt); break; // FONV
|
||||
case ESM4::SUB_MODT:
|
||||
case ESM4::SUB_MODS:
|
||||
case ESM4::SUB_DEST:
|
||||
case ESM4::SUB_DMDL:
|
||||
case ESM4::SUB_DMDS:
|
||||
case ESM4::SUB_DMDT:
|
||||
case ESM4::SUB_DSTD:
|
||||
case ESM4::SUB_DSTF:
|
||||
case ESM4::SUB_FNAM:
|
||||
case ESM4::SUB_KNAM:
|
||||
case ESM4::SUB_KSIZ:
|
||||
case ESM4::SUB_KWDA:
|
||||
case ESM4::SUB_OBND:
|
||||
case ESM4::SUB_PNAM:
|
||||
case ESM4::SUB_VMAD:
|
||||
case ESM4::SUB_WNAM:
|
||||
{
|
||||
//std::cout << "ACTI " << ESM::printName(subHdr.typeId) << " skipping..." << std::endl;
|
||||
reader.skipSubRecordData();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw std::runtime_error("ESM4::ACTI::load - Unknown subrecord " + ESM::printName(subHdr.typeId));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//void ESM4::Activator::save(ESM4::Writer& writer) const
|
||||
//{
|
||||
//}
|
||||
|
||||
//void ESM4::Activator::blank()
|
||||
//{
|
||||
//}
|
@ -0,0 +1,121 @@
|
||||
/*
|
||||
Copyright (C) 2016, 2018, 2020-2021 cc9cii
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
cc9cii cc9c@iinet.net.au
|
||||
|
||||
Much of the information on the data structures are based on the information
|
||||
from Tes4Mod:Mod_File_Format and Tes5Mod:File_Formats but also refined by
|
||||
trial & error. See http://en.uesp.net/wiki for details.
|
||||
|
||||
*/
|
||||
#include "loadalch.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <cstring>
|
||||
//#include <iostream> // FIXME
|
||||
|
||||
#include "reader.hpp"
|
||||
//#include "writer.hpp"
|
||||
|
||||
ESM4::Potion::Potion() : mFormId(0), mFlags(0), mPickUpSound(0), mDropSound(0), mScriptId(0), mBoundRadius(0.f)
|
||||
{
|
||||
mEditorId.clear();
|
||||
mFullName.clear();
|
||||
mModel.clear();
|
||||
mIcon.clear();
|
||||
mMiniIcon.clear();
|
||||
|
||||
mData.weight = 0.f;
|
||||
|
||||
std::memset(&mEffect, 0, sizeof(ScriptEffect));
|
||||
}
|
||||
|
||||
ESM4::Potion::~Potion()
|
||||
{
|
||||
}
|
||||
|
||||
void ESM4::Potion::load(ESM4::Reader& reader)
|
||||
{
|
||||
mFormId = reader.hdr().record.id;
|
||||
reader.adjustFormId(mFormId);
|
||||
mFlags = reader.hdr().record.flags;
|
||||
|
||||
while (reader.getSubRecordHeader())
|
||||
{
|
||||
const ESM4::SubRecordHeader& subHdr = reader.subRecordHeader();
|
||||
switch (subHdr.typeId)
|
||||
{
|
||||
case ESM4::SUB_EDID: reader.getZString(mEditorId); break;
|
||||
case ESM4::SUB_FULL: reader.getLocalizedString(mFullName); break;
|
||||
case ESM4::SUB_MODL: reader.getZString(mModel); break;
|
||||
case ESM4::SUB_ICON: reader.getZString(mIcon); break;
|
||||
case ESM4::SUB_MICO: reader.getZString(mMiniIcon); break; // FO3
|
||||
case ESM4::SUB_DATA: reader.get(mData); break;
|
||||
case ESM4::SUB_SCRI: reader.getFormId(mScriptId); break;
|
||||
case ESM4::SUB_MODB: reader.get(mBoundRadius); break;
|
||||
case ESM4::SUB_SCIT:
|
||||
{
|
||||
reader.get(mEffect);
|
||||
reader.adjustFormId(mEffect.formId);
|
||||
break;
|
||||
}
|
||||
case ESM4::SUB_ENIT:
|
||||
{
|
||||
if (subHdr.dataSize == 8) // TES4
|
||||
{
|
||||
reader.get(&mItem, 8);
|
||||
mItem.withdrawl = 0;
|
||||
mItem.sound = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
reader.get(mItem);
|
||||
reader.adjustFormId(mItem.withdrawl);
|
||||
reader.adjustFormId(mItem.sound);
|
||||
break;
|
||||
}
|
||||
case ESM4::SUB_YNAM: reader.getFormId(mPickUpSound); break;
|
||||
case ESM4::SUB_ZNAM: reader.getFormId(mDropSound); break;
|
||||
case ESM4::SUB_MODT:
|
||||
case ESM4::SUB_EFID:
|
||||
case ESM4::SUB_EFIT:
|
||||
case ESM4::SUB_CTDA:
|
||||
case ESM4::SUB_KSIZ:
|
||||
case ESM4::SUB_KWDA:
|
||||
case ESM4::SUB_MODS:
|
||||
case ESM4::SUB_OBND:
|
||||
case ESM4::SUB_ETYP: // FO3
|
||||
{
|
||||
//std::cout << "ALCH " << ESM::printName(subHdr.typeId) << " skipping..." << std::endl;
|
||||
reader.skipSubRecordData();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw std::runtime_error("ESM4::ALCH::load - Unknown subrecord " + ESM::printName(subHdr.typeId));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//void ESM4::Potion::save(ESM4::Writer& writer) const
|
||||
//{
|
||||
//}
|
||||
|
||||
//void ESM4::Potion::blank()
|
||||
//{
|
||||
//}
|
@ -0,0 +1,88 @@
|
||||
/*
|
||||
Copyright (C) 2016, 2018, 2020 cc9cii
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
cc9cii cc9c@iinet.net.au
|
||||
|
||||
Much of the information on the data structures are based on the information
|
||||
from Tes4Mod:Mod_File_Format and Tes5Mod:File_Formats but also refined by
|
||||
trial & error. See http://en.uesp.net/wiki for details.
|
||||
|
||||
*/
|
||||
#ifndef ESM4_ALCH_H
|
||||
#define ESM4_ALCH_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include "effect.hpp" // FormId, ScriptEffect
|
||||
|
||||
namespace ESM4
|
||||
{
|
||||
class Reader;
|
||||
class Writer;
|
||||
|
||||
struct Potion
|
||||
{
|
||||
#pragma pack(push, 1)
|
||||
struct Data
|
||||
{
|
||||
float weight;
|
||||
};
|
||||
|
||||
struct EnchantedItem
|
||||
{
|
||||
std::int32_t value;
|
||||
std::uint32_t flags;
|
||||
FormId withdrawl;
|
||||
float chanceAddition;
|
||||
FormId sound;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
FormId mFormId; // from the header
|
||||
std::uint32_t mFlags; // from the header, see enum type RecordFlag for details
|
||||
|
||||
std::string mEditorId;
|
||||
std::string mFullName;
|
||||
std::string mModel;
|
||||
std::string mIcon; // inventory
|
||||
std::string mMiniIcon; // inventory
|
||||
|
||||
FormId mPickUpSound;
|
||||
FormId mDropSound;
|
||||
|
||||
FormId mScriptId;
|
||||
ScriptEffect mEffect;
|
||||
|
||||
float mBoundRadius;
|
||||
|
||||
Data mData;
|
||||
EnchantedItem mItem;
|
||||
|
||||
Potion();
|
||||
virtual ~Potion();
|
||||
|
||||
virtual void load(ESM4::Reader& reader);
|
||||
//virtual void save(ESM4::Writer& writer) const;
|
||||
|
||||
//void blank();
|
||||
};
|
||||
}
|
||||
|
||||
#endif // ESM4_ALCH_H
|
@ -0,0 +1,172 @@
|
||||
/*
|
||||
Copyright (C) 2020-2021 cc9cii
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
cc9cii cc9c@iinet.net.au
|
||||
|
||||
Much of the information on the data structures are based on the information
|
||||
from Tes4Mod:Mod_File_Format and Tes5Mod:File_Formats but also refined by
|
||||
trial & error. See http://en.uesp.net/wiki for details.
|
||||
|
||||
*/
|
||||
#include "loadaloc.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <cstring>
|
||||
//#include <iostream> // FIXME: for debugging only
|
||||
//#include <iomanip> // FIXME: for debugging only
|
||||
|
||||
//#include <boost/scoped_array.hpp> // FIXME
|
||||
|
||||
//#include "formid.hpp" // FIXME:
|
||||
|
||||
#include "reader.hpp"
|
||||
//#include "writer.hpp"
|
||||
|
||||
ESM4::MediaLocationController::MediaLocationController() : mFormId(0), mFlags(0),
|
||||
mConditionalFaction(0), mLocationDelay(0.f), mRetriggerDelay(0.f), mDayStart(0), mNightStart(0)
|
||||
{
|
||||
mEditorId.clear();
|
||||
mFullName.clear();
|
||||
|
||||
std::memset(&mMediaFlags, 0, sizeof(MLC_Flags));
|
||||
}
|
||||
|
||||
ESM4::MediaLocationController::~MediaLocationController()
|
||||
{
|
||||
}
|
||||
|
||||
void ESM4::MediaLocationController::load(ESM4::Reader& reader)
|
||||
{
|
||||
mFormId = reader.hdr().record.id;
|
||||
reader.adjustFormId(mFormId);
|
||||
mFlags = reader.hdr().record.flags;
|
||||
|
||||
while (reader.getSubRecordHeader())
|
||||
{
|
||||
const ESM4::SubRecordHeader& subHdr = reader.subRecordHeader();
|
||||
switch (subHdr.typeId)
|
||||
{
|
||||
case ESM4::SUB_EDID: reader.getZString(mEditorId); break;
|
||||
case ESM4::SUB_FULL: reader.getZString(mFullName); break;
|
||||
case ESM4::SUB_GNAM:
|
||||
{
|
||||
FormId id;
|
||||
reader.getFormId(id);
|
||||
mBattleSets.push_back(id);
|
||||
|
||||
break;
|
||||
}
|
||||
case ESM4::SUB_LNAM:
|
||||
{
|
||||
FormId id;
|
||||
reader.getFormId(id);
|
||||
mLocationSets.push_back(id);
|
||||
|
||||
break;
|
||||
}
|
||||
case ESM4::SUB_YNAM:
|
||||
{
|
||||
FormId id;
|
||||
reader.getFormId(id);
|
||||
mEnemySets.push_back(id);
|
||||
|
||||
break;
|
||||
}
|
||||
case ESM4::SUB_HNAM:
|
||||
{
|
||||
FormId id;
|
||||
reader.getFormId(id);
|
||||
mNeutralSets.push_back(id);
|
||||
|
||||
break;
|
||||
}
|
||||
case ESM4::SUB_XNAM:
|
||||
{
|
||||
FormId id;
|
||||
reader.getFormId(id);
|
||||
mFriendSets.push_back(id);
|
||||
|
||||
break;
|
||||
}
|
||||
case ESM4::SUB_ZNAM:
|
||||
{
|
||||
FormId id;
|
||||
reader.getFormId(id);
|
||||
mAllySets.push_back(id);
|
||||
|
||||
break;
|
||||
}
|
||||
case ESM4::SUB_RNAM: reader.getFormId(mConditionalFaction); break;
|
||||
case ESM4::SUB_NAM1:
|
||||
{
|
||||
reader.get(mMediaFlags);
|
||||
std::uint8_t flags = mMediaFlags.loopingOptions;
|
||||
mMediaFlags.loopingOptions = (flags & 0xF0) >> 4;
|
||||
mMediaFlags.factionNotFound = flags & 0x0F; // WARN: overwriting data
|
||||
break;
|
||||
}
|
||||
case ESM4::SUB_NAM4: reader.get(mLocationDelay); break;
|
||||
case ESM4::SUB_NAM7: reader.get(mRetriggerDelay); break;
|
||||
case ESM4::SUB_NAM5: reader.get(mDayStart); break;
|
||||
case ESM4::SUB_NAM6: reader.get(mNightStart); break;
|
||||
case ESM4::SUB_NAM2: // always 0? 4 bytes
|
||||
case ESM4::SUB_NAM3: // always 0? 4 bytes
|
||||
case ESM4::SUB_FNAM: // always 0? 4 bytes
|
||||
{
|
||||
#if 0
|
||||
boost::scoped_array<unsigned char> mDataBuf(new unsigned char[subHdr.dataSize]);
|
||||
reader.get(&mDataBuf[0], subHdr.dataSize);
|
||||
|
||||
std::ostringstream ss;
|
||||
ss << mEditorId << " " << ESM::printName(subHdr.typeId) << ":size " << subHdr.dataSize << "\n";
|
||||
for (std::size_t i = 0; i < subHdr.dataSize; ++i)
|
||||
{
|
||||
//if (mDataBuf[i] > 64 && mDataBuf[i] < 91) // looks like printable ascii char
|
||||
//ss << (char)(mDataBuf[i]) << " ";
|
||||
//else
|
||||
ss << std::setfill('0') << std::setw(2) << std::hex << (int)(mDataBuf[i]);
|
||||
if ((i & 0x000f) == 0xf) // wrap around
|
||||
ss << "\n";
|
||||
else if (i < subHdr.dataSize-1)
|
||||
ss << " ";
|
||||
}
|
||||
std::cout << ss.str() << std::endl;
|
||||
#else
|
||||
//std::cout << "ALOC " << ESM::printName(subHdr.typeId) << " skipping..."
|
||||
//<< subHdr.dataSize << std::endl;
|
||||
reader.skipSubRecordData();
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
default:
|
||||
//std::cout << "ALOC " << ESM::printName(subHdr.typeId) << " skipping..."
|
||||
//<< subHdr.dataSize << std::endl;
|
||||
//reader.skipSubRecordData();
|
||||
throw std::runtime_error("ESM4::ALOC::load - Unknown subrecord " + ESM::printName(subHdr.typeId));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//void ESM4::MediaLocationController::save(ESM4::Writer& writer) const
|
||||
//{
|
||||
//}
|
||||
|
||||
//void ESM4::MediaLocationController::blank()
|
||||
//{
|
||||
//}
|
@ -0,0 +1,88 @@
|
||||
/*
|
||||
Copyright (C) 2020 cc9cii
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
cc9cii cc9c@iinet.net.au
|
||||
|
||||
Much of the information on the data structures are based on the information
|
||||
from Tes4Mod:Mod_File_Format and Tes5Mod:File_Formats but also refined by
|
||||
trial & error. See http://en.uesp.net/wiki for details.
|
||||
|
||||
*/
|
||||
#ifndef ESM4_ALOC_H
|
||||
#define ESM4_ALOC_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "formid.hpp"
|
||||
|
||||
namespace ESM4
|
||||
{
|
||||
class Reader;
|
||||
class Writer;
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct MLC_Flags
|
||||
{
|
||||
// use day/night transition: 0 = loop, 1 = random, 2 = retrigger, 3 = none
|
||||
// use defaults (6:00/23:54): 4 = loop, 5 = random, 6 = retrigger, 7 = none
|
||||
std::uint8_t loopingOptions;
|
||||
// 0 = neutral, 1 = enemy, 2 = ally, 3 = friend, 4 = location, 5 = none
|
||||
std::uint8_t factionNotFound; // WARN: overwriting whatever is in this
|
||||
std::uint16_t unknown; // padding?
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
struct MediaLocationController
|
||||
{
|
||||
FormId mFormId; // from the header
|
||||
std::uint32_t mFlags; // from the header, see enum type RecordFlag for details
|
||||
|
||||
std::string mEditorId;
|
||||
std::string mFullName;
|
||||
|
||||
std::vector<FormId> mBattleSets;
|
||||
std::vector<FormId> mLocationSets;
|
||||
std::vector<FormId> mEnemySets;
|
||||
std::vector<FormId> mNeutralSets;
|
||||
std::vector<FormId> mFriendSets;
|
||||
std::vector<FormId> mAllySets;
|
||||
|
||||
MLC_Flags mMediaFlags;
|
||||
|
||||
FormId mConditionalFaction;
|
||||
|
||||
float mLocationDelay;
|
||||
float mRetriggerDelay;
|
||||
|
||||
std::uint32_t mDayStart;
|
||||
std::uint32_t mNightStart;
|
||||
|
||||
MediaLocationController();
|
||||
virtual ~MediaLocationController();
|
||||
|
||||
virtual void load(ESM4::Reader& reader);
|
||||
//virtual void save(ESM4::Writer& writer) const;
|
||||
|
||||
//void blank();
|
||||
};
|
||||
}
|
||||
|
||||
#endif // ESM4_ALOC_H
|
@ -0,0 +1,133 @@
|
||||
/*
|
||||
Copyright (C) 2016, 2018-2021 cc9cii
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
cc9cii cc9c@iinet.net.au
|
||||
|
||||
Much of the information on the data structures are based on the information
|
||||
from Tes4Mod:Mod_File_Format and Tes5Mod:File_Formats but also refined by
|
||||
trial & error. See http://en.uesp.net/wiki for details.
|
||||
|
||||
*/
|
||||
#include "loadammo.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "reader.hpp"
|
||||
//#include "writer.hpp"
|
||||
|
||||
ESM4::Ammunition::Ammunition() : mFormId(0), mFlags(0), mPickUpSound(0), mDropSound(0), mBoundRadius(0.f)
|
||||
{
|
||||
mEditorId.clear();
|
||||
mFullName.clear();
|
||||
mModel.clear();
|
||||
mText.clear();
|
||||
mIcon.clear();
|
||||
mMiniIcon.clear();
|
||||
}
|
||||
|
||||
ESM4::Ammunition::~Ammunition()
|
||||
{
|
||||
}
|
||||
|
||||
void ESM4::Ammunition::load(ESM4::Reader& reader)
|
||||
{
|
||||
mFormId = reader.hdr().record.id;
|
||||
reader.adjustFormId(mFormId);
|
||||
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;
|
||||
|
||||
while (reader.getSubRecordHeader())
|
||||
{
|
||||
const ESM4::SubRecordHeader& subHdr = reader.subRecordHeader();
|
||||
switch (subHdr.typeId)
|
||||
{
|
||||
case ESM4::SUB_EDID: reader.getZString(mEditorId); break;
|
||||
case ESM4::SUB_FULL: reader.getLocalizedString(mFullName); break;
|
||||
case ESM4::SUB_DATA:
|
||||
{
|
||||
//if (reader.esmVersion() == ESM::VER_094 || reader.esmVersion() == ESM::VER_170)
|
||||
if (subHdr.dataSize == 16) // FO3 has 13 bytes even though VER_094
|
||||
{
|
||||
FormId projectile;
|
||||
reader.get(projectile); // FIXME: add to mData
|
||||
reader.get(mData.flags);
|
||||
reader.get(mData.weight);
|
||||
float damageInFloat;
|
||||
reader.get(damageInFloat); // FIXME: add to mData
|
||||
}
|
||||
else if (isFONV || subHdr.dataSize == 13)
|
||||
{
|
||||
reader.get(mData.speed);
|
||||
std::uint8_t flags;
|
||||
reader.get(flags);
|
||||
mData.flags = flags;
|
||||
static std::uint8_t dummy;
|
||||
reader.get(dummy);
|
||||
reader.get(dummy);
|
||||
reader.get(dummy);
|
||||
reader.get(mData.value);
|
||||
reader.get(mData.clipRounds);
|
||||
}
|
||||
else // TES4
|
||||
{
|
||||
reader.get(mData.speed);
|
||||
reader.get(mData.flags);
|
||||
reader.get(mData.value);
|
||||
reader.get(mData.weight);
|
||||
reader.get(mData.damage);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ESM4::SUB_ICON: reader.getZString(mIcon); break;
|
||||
case ESM4::SUB_MICO: reader.getZString(mMiniIcon); break; // FO3
|
||||
case ESM4::SUB_MODL: reader.getZString(mModel); break;
|
||||
case ESM4::SUB_ANAM: reader.get(mEnchantmentPoints); break;
|
||||
case ESM4::SUB_ENAM: reader.getFormId(mEnchantment); break;
|
||||
case ESM4::SUB_MODB: reader.get(mBoundRadius); break;
|
||||
case ESM4::SUB_DESC: reader.getLocalizedString(mText); break;
|
||||
case ESM4::SUB_YNAM: reader.getFormId(mPickUpSound); break;
|
||||
case ESM4::SUB_ZNAM: reader.getFormId(mDropSound); break;
|
||||
case ESM4::SUB_MODT:
|
||||
case ESM4::SUB_OBND:
|
||||
case ESM4::SUB_KSIZ:
|
||||
case ESM4::SUB_KWDA:
|
||||
case ESM4::SUB_ONAM: // FO3
|
||||
case ESM4::SUB_DAT2: // FONV
|
||||
case ESM4::SUB_QNAM: // FONV
|
||||
case ESM4::SUB_RCIL: // FONV
|
||||
case ESM4::SUB_SCRI: // FONV
|
||||
{
|
||||
//std::cout << "AMMO " << ESM::printName(subHdr.typeId) << " skipping..." << std::endl;
|
||||
reader.skipSubRecordData();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw std::runtime_error("ESM4::AMMO::load - Unknown subrecord " + ESM::printName(subHdr.typeId));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//void ESM4::Ammunition::save(ESM4::Writer& writer) const
|
||||
//{
|
||||
//}
|
||||
|
||||
//void ESM4::Ammunition::blank()
|
||||
//{
|
||||
//}
|
@ -0,0 +1,84 @@
|
||||
/*
|
||||
Copyright (C) 2016, 2018-2020 cc9cii
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
cc9cii cc9c@iinet.net.au
|
||||
|
||||
Much of the information on the data structures are based on the information
|
||||
from Tes4Mod:Mod_File_Format and Tes5Mod:File_Formats but also refined by
|
||||
trial & error. See http://en.uesp.net/wiki for details.
|
||||
|
||||
*/
|
||||
#ifndef ESM4_AMMO_H
|
||||
#define ESM4_AMMO_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include "formid.hpp"
|
||||
|
||||
namespace ESM4
|
||||
{
|
||||
class Reader;
|
||||
class Writer;
|
||||
|
||||
struct Ammunition
|
||||
{
|
||||
struct Data // FIXME: TES5 projectile, damage (float)
|
||||
{
|
||||
float speed;
|
||||
std::uint32_t flags;
|
||||
std::uint32_t value; // gold
|
||||
float weight;
|
||||
std::uint16_t damage;
|
||||
std::uint8_t clipRounds; // only in FO3/FONV
|
||||
|
||||
Data() : speed(0.f), flags(0), value(0), weight(0.f), damage(0), clipRounds(0) {}
|
||||
};
|
||||
|
||||
FormId mFormId; // from the header
|
||||
std::uint32_t mFlags; // from the header, see enum type RecordFlag for details
|
||||
|
||||
std::string mEditorId;
|
||||
std::string mFullName;
|
||||
std::string mModel;
|
||||
std::string mText;
|
||||
std::string mIcon; // inventory
|
||||
std::string mMiniIcon; // inventory
|
||||
|
||||
FormId mPickUpSound;
|
||||
FormId mDropSound;
|
||||
|
||||
float mBoundRadius;
|
||||
|
||||
std::uint16_t mEnchantmentPoints;
|
||||
FormId mEnchantment;
|
||||
|
||||
Data mData;
|
||||
|
||||
Ammunition();
|
||||
virtual ~Ammunition();
|
||||
|
||||
virtual void load(ESM4::Reader& reader);
|
||||
//virtual void save(ESM4::Writer& writer) const;
|
||||
|
||||
//void blank();
|
||||
};
|
||||
}
|
||||
|
||||
#endif // ESM4_AMMO_H
|
@ -0,0 +1,80 @@
|
||||
/*
|
||||
Copyright (C) 2016, 2018 cc9cii
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
cc9cii cc9c@iinet.net.au
|
||||
|
||||
Much of the information on the data structures are based on the information
|
||||
from Tes4Mod:Mod_File_Format and Tes5Mod:File_Formats but also refined by
|
||||
trial & error. See http://en.uesp.net/wiki for details.
|
||||
|
||||
*/
|
||||
#include "loadanio.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "reader.hpp"
|
||||
//#include "writer.hpp"
|
||||
|
||||
ESM4::AnimObject::AnimObject() : mFormId(0), mFlags(0), mBoundRadius(0.f), mIdleAnim(0)
|
||||
{
|
||||
mEditorId.clear();
|
||||
mModel.clear();
|
||||
mUnloadEvent.clear();
|
||||
}
|
||||
|
||||
ESM4::AnimObject::~AnimObject()
|
||||
{
|
||||
}
|
||||
|
||||
void ESM4::AnimObject::load(ESM4::Reader& reader)
|
||||
{
|
||||
mFormId = reader.hdr().record.id;
|
||||
reader.adjustFormId(mFormId);
|
||||
mFlags = reader.hdr().record.flags;
|
||||
|
||||
while (reader.getSubRecordHeader())
|
||||
{
|
||||
const ESM4::SubRecordHeader& subHdr = reader.subRecordHeader();
|
||||
switch (subHdr.typeId)
|
||||
{
|
||||
case ESM4::SUB_EDID: reader.getZString(mEditorId); break;
|
||||
case ESM4::SUB_MODL: reader.getZString(mModel); break;
|
||||
case ESM4::SUB_BNAM: reader.getZString(mUnloadEvent); break;
|
||||
case ESM4::SUB_DATA: reader.getFormId(mIdleAnim); break;
|
||||
case ESM4::SUB_MODB: reader.get(mBoundRadius); break;
|
||||
case ESM4::SUB_MODT: // TES5 only
|
||||
case ESM4::SUB_MODS: // TES5 only
|
||||
{
|
||||
//std::cout << "ANIO " << ESM::printName(subHdr.typeId) << " skipping..." << std::endl;
|
||||
reader.skipSubRecordData();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw std::runtime_error("ESM4::ANIO::load - Unknown subrecord " + ESM::printName(subHdr.typeId));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//void ESM4::AnimObject::save(ESM4::Writer& writer) const
|
||||
//{
|
||||
//}
|
||||
|
||||
//void ESM4::AnimObject::blank()
|
||||
//{
|
||||
//}
|
@ -0,0 +1,63 @@
|
||||
/*
|
||||
Copyright (C) 2016, 2018, 2020 cc9cii
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
cc9cii cc9c@iinet.net.au
|
||||
|
||||
Much of the information on the data structures are based on the information
|
||||
from Tes4Mod:Mod_File_Format and Tes5Mod:File_Formats but also refined by
|
||||
trial & error. See http://en.uesp.net/wiki for details.
|
||||
|
||||
*/
|
||||
#ifndef ESM4_ANIO_H
|
||||
#define ESM4_ANIO_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include "formid.hpp"
|
||||
|
||||
namespace ESM4
|
||||
{
|
||||
class Reader;
|
||||
class Writer;
|
||||
|
||||
struct AnimObject
|
||||
{
|
||||
FormId mFormId; // from the header
|
||||
std::uint32_t mFlags; // from the header, see enum type RecordFlag for details
|
||||
|
||||
std::string mEditorId;
|
||||
std::string mModel;
|
||||
|
||||
float mBoundRadius;
|
||||
|
||||
FormId mIdleAnim; // only in TES4
|
||||
std::string mUnloadEvent; // only in TES5
|
||||
|
||||
AnimObject();
|
||||
virtual ~AnimObject();
|
||||
|
||||
virtual void load(ESM4::Reader& reader);
|
||||
//virtual void save(ESM4::Writer& writer) const;
|
||||
|
||||
//void blank();
|
||||
};
|
||||
}
|
||||
|
||||
#endif // ESM4_ANIO_H
|
@ -0,0 +1,106 @@
|
||||
/*
|
||||
Copyright (C) 2016, 2018-2021 cc9cii
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
cc9cii cc9c@iinet.net.au
|
||||
|
||||
Much of the information on the data structures are based on the information
|
||||
from Tes4Mod:Mod_File_Format and Tes5Mod:File_Formats but also refined by
|
||||
trial & error. See http://en.uesp.net/wiki for details.
|
||||
|
||||
*/
|
||||
#include "loadappa.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "reader.hpp"
|
||||
//#include "writer.hpp"
|
||||
|
||||
ESM4::Apparatus::Apparatus() : mFormId(0), mFlags(0), mBoundRadius(0.f), mScriptId(0)
|
||||
{
|
||||
mEditorId.clear();
|
||||
mFullName.clear();
|
||||
mModel.clear();
|
||||
mText.clear();
|
||||
mIcon.clear();
|
||||
|
||||
mData.type = 0;
|
||||
mData.value = 0;
|
||||
mData.weight = 0.f;
|
||||
mData.quality = 0.f;
|
||||
}
|
||||
|
||||
ESM4::Apparatus::~Apparatus()
|
||||
{
|
||||
}
|
||||
|
||||
void ESM4::Apparatus::load(ESM4::Reader& reader)
|
||||
{
|
||||
mFormId = reader.hdr().record.id;
|
||||
reader.adjustFormId(mFormId);
|
||||
mFlags = reader.hdr().record.flags;
|
||||
|
||||
while (reader.getSubRecordHeader())
|
||||
{
|
||||
const ESM4::SubRecordHeader& subHdr = reader.subRecordHeader();
|
||||
switch (subHdr.typeId)
|
||||
{
|
||||
case ESM4::SUB_EDID: reader.getZString(mEditorId); break;
|
||||
case ESM4::SUB_FULL: reader.getLocalizedString(mFullName); break;
|
||||
case ESM4::SUB_DATA:
|
||||
{
|
||||
if (reader.esmVersion() == ESM::VER_094 || reader.esmVersion() == ESM::VER_170)
|
||||
{
|
||||
reader.get(mData.value);
|
||||
reader.get(mData.weight);
|
||||
}
|
||||
else
|
||||
{
|
||||
reader.get(mData.type);
|
||||
reader.get(mData.value);
|
||||
reader.get(mData.weight);
|
||||
reader.get(mData.quality);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ESM4::SUB_ICON: reader.getZString(mIcon); break;
|
||||
case ESM4::SUB_MODL: reader.getZString(mModel); break;
|
||||
case ESM4::SUB_SCRI: reader.getFormId(mScriptId); break;
|
||||
case ESM4::SUB_MODB: reader.get(mBoundRadius); break;
|
||||
case ESM4::SUB_DESC: reader.getLocalizedString(mText); break;
|
||||
case ESM4::SUB_MODT:
|
||||
case ESM4::SUB_OBND:
|
||||
case ESM4::SUB_QUAL:
|
||||
{
|
||||
//std::cout << "APPA " << ESM::printName(subHdr.typeId) << " skipping..." << std::endl;
|
||||
reader.skipSubRecordData();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw std::runtime_error("ESM4::APPA::load - Unknown subrecord " + ESM::printName(subHdr.typeId));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//void ESM4::Apparatus::save(ESM4::Writer& writer) const
|
||||
//{
|
||||
//}
|
||||
|
||||
//void ESM4::Apparatus::blank()
|
||||
//{
|
||||
//}
|
@ -0,0 +1,75 @@
|
||||
/*
|
||||
Copyright (C) 2016, 2018-2020 cc9cii
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
cc9cii cc9c@iinet.net.au
|
||||
|
||||
Much of the information on the data structures are based on the information
|
||||
from Tes4Mod:Mod_File_Format and Tes5Mod:File_Formats but also refined by
|
||||
trial & error. See http://en.uesp.net/wiki for details.
|
||||
|
||||
*/
|
||||
#ifndef ESM4_APPA_H
|
||||
#define ESM4_APPA_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include "formid.hpp"
|
||||
|
||||
namespace ESM4
|
||||
{
|
||||
class Reader;
|
||||
class Writer;
|
||||
|
||||
struct Apparatus
|
||||
{
|
||||
struct Data
|
||||
{
|
||||
std::uint8_t type; // 0 = Mortar and Pestle, 1 = Alembic, 2 = Calcinator, 3 = Retort
|
||||
std::uint32_t value; // gold
|
||||
float weight;
|
||||
float quality;
|
||||
};
|
||||
|
||||
FormId mFormId; // from the header
|
||||
std::uint32_t mFlags; // from the header, see enum type RecordFlag for details
|
||||
|
||||
std::string mEditorId;
|
||||
std::string mFullName;
|
||||
std::string mModel;
|
||||
std::string mText;
|
||||
std::string mIcon; // inventory
|
||||
|
||||
float mBoundRadius;
|
||||
|
||||
FormId mScriptId;
|
||||
|
||||
Data mData;
|
||||
|
||||
Apparatus();
|
||||
virtual ~Apparatus();
|
||||
|
||||
virtual void load(ESM4::Reader& reader);
|
||||
//virtual void save(ESM4::Writer& writer) const;
|
||||
|
||||
//void blank();
|
||||
};
|
||||
}
|
||||
|
||||
#endif // ESM4_APPA_H
|
@ -0,0 +1,151 @@
|
||||
/*
|
||||
Copyright (C) 2019, 2020 cc9cii
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
cc9cii cc9c@iinet.net.au
|
||||
|
||||
Much of the information on the data structures are based on the information
|
||||
from Tes4Mod:Mod_File_Format and Tes5Mod:File_Formats but also refined by
|
||||
trial & error. See http://en.uesp.net/wiki for details.
|
||||
|
||||
*/
|
||||
#include "loadarma.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
//#include <iostream> // FIXME: testing only
|
||||
|
||||
#include "reader.hpp"
|
||||
//#include "writer.hpp"
|
||||
|
||||
ESM4::ArmorAddon::ArmorAddon() : mFormId(0), mFlags(0), mTextureMale(0), mTextureFemale(0),
|
||||
mRacePrimary(0)
|
||||
{
|
||||
mEditorId.clear();
|
||||
|
||||
mModelMale.clear();
|
||||
mModelFemale.clear();
|
||||
}
|
||||
|
||||
ESM4::ArmorAddon::~ArmorAddon()
|
||||
{
|
||||
}
|
||||
|
||||
void ESM4::ArmorAddon::load(ESM4::Reader& reader)
|
||||
{
|
||||
mFormId = reader.hdr().record.id;
|
||||
reader.adjustFormId(mFormId);
|
||||
mFlags = reader.hdr().record.flags;
|
||||
|
||||
std::uint32_t esmVer = reader.esmVersion();
|
||||
|
||||
while (reader.getSubRecordHeader())
|
||||
{
|
||||
const ESM4::SubRecordHeader& subHdr = reader.subRecordHeader();
|
||||
switch (subHdr.typeId)
|
||||
{
|
||||
case ESM4::SUB_EDID: reader.getZString(mEditorId); break;
|
||||
case ESM4::SUB_MOD2: reader.getZString(mModelMale); break;
|
||||
case ESM4::SUB_MOD3: reader.getZString(mModelFemale); break;
|
||||
case ESM4::SUB_MOD4:
|
||||
case ESM4::SUB_MOD5:
|
||||
{
|
||||
std::string model;
|
||||
reader.getZString(model);
|
||||
|
||||
//std::cout << mEditorId << " " << ESM::printName(subHdr.typeId) << " " << model << std::endl;
|
||||
|
||||
break;
|
||||
}
|
||||
case ESM4::SUB_NAM0: reader.getFormId(mTextureMale); break;
|
||||
case ESM4::SUB_NAM1: reader.getFormId(mTextureFemale); break;
|
||||
case ESM4::SUB_RNAM: reader.getFormId(mRacePrimary); break;
|
||||
case ESM4::SUB_MODL:
|
||||
{
|
||||
if ((esmVer == ESM::VER_094 || esmVer == ESM::VER_170) && subHdr.dataSize == 4) // TES5
|
||||
{
|
||||
FormId formId;
|
||||
reader.getFormId(formId);
|
||||
mRaces.push_back(formId);
|
||||
}
|
||||
else
|
||||
reader.skipSubRecordData(); // FIXME: this should be mModelMale for FO3/FONV
|
||||
|
||||
break;
|
||||
}
|
||||
case ESM4::SUB_BODT: // body template
|
||||
{
|
||||
reader.get(mBodyTemplate.bodyPart);
|
||||
reader.get(mBodyTemplate.flags);
|
||||
reader.get(mBodyTemplate.unknown1); // probably padding
|
||||
reader.get(mBodyTemplate.unknown2); // probably padding
|
||||
reader.get(mBodyTemplate.unknown3); // probably padding
|
||||
reader.get(mBodyTemplate.type);
|
||||
|
||||
break;
|
||||
}
|
||||
case ESM4::SUB_BOD2: // TES5
|
||||
{
|
||||
reader.get(mBodyTemplate.bodyPart);
|
||||
mBodyTemplate.flags = 0;
|
||||
mBodyTemplate.unknown1 = 0; // probably padding
|
||||
mBodyTemplate.unknown2 = 0; // probably padding
|
||||
mBodyTemplate.unknown3 = 0; // probably padding
|
||||
reader.get(mBodyTemplate.type);
|
||||
|
||||
break;
|
||||
}
|
||||
case ESM4::SUB_DNAM:
|
||||
case ESM4::SUB_MO2T: // FIXME: should group with MOD2
|
||||
case ESM4::SUB_MO2S: // FIXME: should group with MOD2
|
||||
case ESM4::SUB_MO3T: // FIXME: should group with MOD3
|
||||
case ESM4::SUB_MO3S: // FIXME: should group with MOD3
|
||||
case ESM4::SUB_MOSD: // FO3 // FIXME: should group with MOD3
|
||||
case ESM4::SUB_MO4T: // FIXME: should group with MOD4
|
||||
case ESM4::SUB_MO4S: // FIXME: should group with MOD4
|
||||
case ESM4::SUB_MO5T:
|
||||
case ESM4::SUB_NAM2: // txst formid male
|
||||
case ESM4::SUB_NAM3: // txst formid female
|
||||
case ESM4::SUB_SNDD: // footset sound formid
|
||||
case ESM4::SUB_BMDT: // FO3
|
||||
case ESM4::SUB_DATA: // FO3
|
||||
case ESM4::SUB_ETYP: // FO3
|
||||
case ESM4::SUB_FULL: // FO3
|
||||
case ESM4::SUB_ICO2: // FO3 // female
|
||||
case ESM4::SUB_ICON: // FO3 // male
|
||||
case ESM4::SUB_MODT: // FO3 // FIXME: should group with MODL
|
||||
case ESM4::SUB_MODS: // FO3 // FIXME: should group with MODL
|
||||
case ESM4::SUB_MODD: // FO3 // FIXME: should group with MODL
|
||||
case ESM4::SUB_OBND: // FO3
|
||||
{
|
||||
//std::cout << "ARMA " << ESM::printName(subHdr.typeId) << " skipping..." << std::endl;
|
||||
reader.skipSubRecordData();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw std::runtime_error("ESM4::ARMA::load - Unknown subrecord " + ESM::printName(subHdr.typeId));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//void ESM4::ArmorAddon::save(ESM4::Writer& writer) const
|
||||
//{
|
||||
//}
|
||||
|
||||
//void ESM4::ArmorAddon::blank()
|
||||
//{
|
||||
//}
|
@ -0,0 +1,70 @@
|
||||
/*
|
||||
Copyright (C) 2019, 2020 cc9cii
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
cc9cii cc9c@iinet.net.au
|
||||
|
||||
Much of the information on the data structures are based on the information
|
||||
from Tes4Mod:Mod_File_Format and Tes5Mod:File_Formats but also refined by
|
||||
trial & error. See http://en.uesp.net/wiki for details.
|
||||
|
||||
*/
|
||||
#ifndef ESM4_ARMA_H
|
||||
#define ESM4_ARMA_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "formid.hpp"
|
||||
#include "actor.hpp" // BodyTemplate
|
||||
|
||||
namespace ESM4
|
||||
{
|
||||
class Reader;
|
||||
class Writer;
|
||||
|
||||
struct ArmorAddon
|
||||
{
|
||||
FormId mFormId; // from the header
|
||||
std::uint32_t mFlags; // from the header, see enum type RecordFlag for details
|
||||
|
||||
std::string mEditorId;
|
||||
|
||||
std::string mModelMale;
|
||||
std::string mModelFemale;
|
||||
|
||||
FormId mTextureMale;
|
||||
FormId mTextureFemale;
|
||||
|
||||
FormId mRacePrimary;
|
||||
std::vector<FormId> mRaces; // TES5 only
|
||||
|
||||
BodyTemplate mBodyTemplate; // TES5
|
||||
|
||||
ArmorAddon();
|
||||
virtual ~ArmorAddon();
|
||||
|
||||
virtual void load(ESM4::Reader& reader);
|
||||
//virtual void save(ESM4::Writer& writer) const;
|
||||
|
||||
//void blank();
|
||||
};
|
||||
}
|
||||
|
||||
#endif // ESM4_ARMA_H
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue