From 891be9744dc905cbe4f5ebd5b75ed3ce5d9d8c0f Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Tue, 15 Aug 2023 04:42:09 +0300 Subject: [PATCH 01/64] Skip TES4::TNAM --- components/esm4/loadtes4.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/components/esm4/loadtes4.cpp b/components/esm4/loadtes4.cpp index b1d2fa2957..a2fbe8b139 100644 --- a/components/esm4/loadtes4.cpp +++ b/components/esm4/loadtes4.cpp @@ -99,6 +99,7 @@ void ESM4::Header::load(ESM4::Reader& reader) case ESM4::SUB_INCC: case ESM4::SUB_OFST: // Oblivion only? case ESM4::SUB_DELE: // Oblivion only? + case ESM4::SUB_TNAM: // Fallout 4 (CK only) reader.skipSubRecordData(); break; default: From 0e94ff4a7305b3497f0d0167a9ba951ff879b98f Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Tue, 15 Aug 2023 05:09:59 +0300 Subject: [PATCH 02/64] Support unsigned int GMSTs --- components/esm4/loadgmst.cpp | 6 ++++++ components/esm4/loadgmst.hpp | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/components/esm4/loadgmst.cpp b/components/esm4/loadgmst.cpp index b403d09be9..087eed6057 100644 --- a/components/esm4/loadgmst.cpp +++ b/components/esm4/loadgmst.cpp @@ -44,6 +44,12 @@ namespace ESM4 reader.getZString(value); return value; } + case 'u': + { + std::uint32_t value = 0; + reader.get(value); + return value; + } default: throw std::runtime_error( "Unsupported ESM4 GMST (" + formId.toString() + ") data type: " + std::string(editorId)); diff --git a/components/esm4/loadgmst.hpp b/components/esm4/loadgmst.hpp index a8790bad26..2bc71a734e 100644 --- a/components/esm4/loadgmst.hpp +++ b/components/esm4/loadgmst.hpp @@ -14,7 +14,7 @@ namespace ESM4 struct GameSetting { - using Data = std::variant; + using Data = std::variant; ESM::FormId mId; // from the header std::uint32_t mFlags; // from the header, see enum type RecordFlag for details From e426dd045fec621d7907bf69eddb2ef3d7a22241 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Tue, 15 Aug 2023 05:10:28 +0300 Subject: [PATCH 03/64] Read string GMSTs correctly in >=TES5 --- components/esm4/loadgmst.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/esm4/loadgmst.cpp b/components/esm4/loadgmst.cpp index 087eed6057..f22ed5848d 100644 --- a/components/esm4/loadgmst.cpp +++ b/components/esm4/loadgmst.cpp @@ -41,7 +41,7 @@ namespace ESM4 case 's': { std::string value; - reader.getZString(value); + reader.getLocalizedString(value); return value; } case 'u': From 84d693324ba5134ea3404016868452c63122004c Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Tue, 15 Aug 2023 05:21:54 +0300 Subject: [PATCH 04/64] ESM4: read texture set material --- components/esm4/loadtxst.cpp | 3 +++ components/esm4/loadtxst.hpp | 1 + 2 files changed, 4 insertions(+) diff --git a/components/esm4/loadtxst.cpp b/components/esm4/loadtxst.cpp index cd17820cc6..3f1aebafb4 100644 --- a/components/esm4/loadtxst.cpp +++ b/components/esm4/loadtxst.cpp @@ -68,6 +68,9 @@ void ESM4::TextureSet::load(ESM4::Reader& reader) case ESM4::SUB_TX07: reader.getZString(mSpecular); break; + case ESM4::SUB_MNAM: + reader.getZString(mMaterial); + break; case ESM4::SUB_DNAM: case ESM4::SUB_DODT: case ESM4::SUB_OBND: // object bounds diff --git a/components/esm4/loadtxst.hpp b/components/esm4/loadtxst.hpp index eedfe433ef..0b55f37f8c 100644 --- a/components/esm4/loadtxst.hpp +++ b/components/esm4/loadtxst.hpp @@ -53,6 +53,7 @@ namespace ESM4 std::string mEnvMap; std::string mUnknown; std::string mSpecular; + std::string mMaterial; void load(ESM4::Reader& reader); // void save(ESM4::Writer& writer) const; From 22fb7447517b3c7c7e1ff4b084e3ee49ee3551ee Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Tue, 15 Aug 2023 05:33:06 +0300 Subject: [PATCH 05/64] Skip PRPS object property subrecords --- components/esm4/common.hpp | 2 ++ components/esm4/loadacti.cpp | 1 + components/esm4/loadclas.cpp | 1 + components/esm4/loadcont.cpp | 1 + components/esm4/loadflor.cpp | 1 + components/esm4/loadfurn.cpp | 1 + components/esm4/loadligh.cpp | 1 + components/esm4/loadmstt.cpp | 1 + components/esm4/loadnpc.cpp | 1 + components/esm4/loadrace.cpp | 1 + components/esm4/loadstat.cpp | 1 + components/esm4/loadterm.cpp | 1 + 12 files changed, 13 insertions(+) diff --git a/components/esm4/common.hpp b/components/esm4/common.hpp index fb3dd71045..89adf6f368 100644 --- a/components/esm4/common.hpp +++ b/components/esm4/common.hpp @@ -657,6 +657,8 @@ namespace ESM4 SUB_WNM7 = fourCC("WNM7"), // FONV SUB_JNAM = fourCC("JNAM"), // FONV SUB_EFSD = fourCC("EFSD"), // FONV DeadMoney + + SUB_PRPS = fourCC("PRPS"), // FO4 }; // Based on http://www.uesp.net/wiki/Tes5Mod:Mod_File_Format#Records diff --git a/components/esm4/loadacti.cpp b/components/esm4/loadacti.cpp index 54af0732e1..dfcf1edcdf 100644 --- a/components/esm4/loadacti.cpp +++ b/components/esm4/loadacti.cpp @@ -87,6 +87,7 @@ void ESM4::Activator::load(ESM4::Reader& reader) case ESM4::SUB_PNAM: case ESM4::SUB_VMAD: case ESM4::SUB_WNAM: + case ESM4::SUB_PRPS: reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadclas.cpp b/components/esm4/loadclas.cpp index 17d745baeb..7d232a0aa1 100644 --- a/components/esm4/loadclas.cpp +++ b/components/esm4/loadclas.cpp @@ -55,6 +55,7 @@ void ESM4::Class::load(ESM4::Reader& reader) break; case ESM4::SUB_DATA: case ESM4::SUB_ATTR: + case ESM4::SUB_PRPS: reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadcont.cpp b/components/esm4/loadcont.cpp index 50a1c6b9bf..66219f2fae 100644 --- a/components/esm4/loadcont.cpp +++ b/components/esm4/loadcont.cpp @@ -86,6 +86,7 @@ void ESM4::Container::load(ESM4::Reader& reader) case ESM4::SUB_DMDL: // FONV case ESM4::SUB_DMDT: // FONV case ESM4::SUB_RNAM: // FONV + case ESM4::SUB_PRPS: // FO4 reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadflor.cpp b/components/esm4/loadflor.cpp index 6bbc31ffe2..95bbef61a2 100644 --- a/components/esm4/loadflor.cpp +++ b/components/esm4/loadflor.cpp @@ -72,6 +72,7 @@ void ESM4::Flora::load(ESM4::Reader& reader) case ESM4::SUB_PNAM: case ESM4::SUB_RNAM: case ESM4::SUB_VMAD: + case ESM4::SUB_PRPS: reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadfurn.cpp b/components/esm4/loadfurn.cpp index 9d84312e26..90ba59eb1d 100644 --- a/components/esm4/loadfurn.cpp +++ b/components/esm4/loadfurn.cpp @@ -77,6 +77,7 @@ void ESM4::Furniture::load(ESM4::Reader& reader) case ESM4::SUB_VMAD: case ESM4::SUB_WBDT: case ESM4::SUB_XMRK: + case ESM4::SUB_PRPS: reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadligh.cpp b/components/esm4/loadligh.cpp index 1ea88a490b..12746623f7 100644 --- a/components/esm4/loadligh.cpp +++ b/components/esm4/loadligh.cpp @@ -108,6 +108,7 @@ void ESM4::Light::load(ESM4::Reader& reader) case ESM4::SUB_DMDT: case ESM4::SUB_DMDS: case ESM4::SUB_DSTF: // Destruction data end + case ESM4::SUB_PRPS: reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadmstt.cpp b/components/esm4/loadmstt.cpp index e216e5e003..3ace680eb9 100644 --- a/components/esm4/loadmstt.cpp +++ b/components/esm4/loadmstt.cpp @@ -63,6 +63,7 @@ void ESM4::MovableStatic::load(ESM4::Reader& reader) case ESM4::SUB_MODS: case ESM4::SUB_FULL: case ESM4::SUB_MODB: + case ESM4::SUB_PRPS: reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadnpc.cpp b/components/esm4/loadnpc.cpp index bd8c15d5bb..e4bfefbe51 100644 --- a/components/esm4/loadnpc.cpp +++ b/components/esm4/loadnpc.cpp @@ -295,6 +295,7 @@ void ESM4::Npc::load(ESM4::Reader& reader) case ESM4::SUB_EAMT: // FO3 case ESM4::SUB_NAM4: // FO3 case ESM4::SUB_COED: // FO3 + case ESM4::SUB_PRPS: // FO4 reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadrace.cpp b/components/esm4/loadrace.cpp index ef8f423963..576bde773f 100644 --- a/components/esm4/loadrace.cpp +++ b/components/esm4/loadrace.cpp @@ -675,6 +675,7 @@ void ESM4::Race::load(ESM4::Reader& reader) case ESM4::SUB_MODT: // FO3 case ESM4::SUB_MODD: // FO3 case ESM4::SUB_ONAM: // FO3 + case ESM4::SUB_PRPS: // FO4 reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadstat.cpp b/components/esm4/loadstat.cpp index 770312c11b..d3a1c86b85 100644 --- a/components/esm4/loadstat.cpp +++ b/components/esm4/loadstat.cpp @@ -86,6 +86,7 @@ void ESM4::Static::load(ESM4::Reader& reader) case ESM4::SUB_DNAM: case ESM4::SUB_BRUS: // FONV case ESM4::SUB_RNAM: // FONV + case ESM4::SUB_PRPS: reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadterm.cpp b/components/esm4/loadterm.cpp index 5f14085d2d..b190145e5f 100644 --- a/components/esm4/loadterm.cpp +++ b/components/esm4/loadterm.cpp @@ -81,6 +81,7 @@ void ESM4::Terminal::load(ESM4::Reader& reader) case ESM4::SUB_TNAM: case ESM4::SUB_OBND: case ESM4::SUB_MODS: // FONV + case ESM4::SUB_PRPS: // FO4 reader.skipSubRecordData(); break; default: From 0c05bbea37ab0d2ec5918c18c684a7dcc2cb9bda Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Tue, 15 Aug 2023 06:29:08 +0300 Subject: [PATCH 06/64] Skip CTDA target condition subrecords --- components/esm4/loadacti.cpp | 1 + components/esm4/loadclfm.cpp | 3 +++ components/esm4/loadfurn.cpp | 1 + components/esm4/loadhdpt.cpp | 1 + 4 files changed, 6 insertions(+) diff --git a/components/esm4/loadacti.cpp b/components/esm4/loadacti.cpp index dfcf1edcdf..418da82b4b 100644 --- a/components/esm4/loadacti.cpp +++ b/components/esm4/loadacti.cpp @@ -88,6 +88,7 @@ void ESM4::Activator::load(ESM4::Reader& reader) case ESM4::SUB_VMAD: case ESM4::SUB_WNAM: case ESM4::SUB_PRPS: + case ESM4::SUB_CTDA: reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadclfm.cpp b/components/esm4/loadclfm.cpp index cb03076fc8..bc887cd15c 100644 --- a/components/esm4/loadclfm.cpp +++ b/components/esm4/loadclfm.cpp @@ -56,6 +56,9 @@ void ESM4::Colour::load(ESM4::Reader& reader) case ESM4::SUB_FNAM: reader.get(mPlayable); break; + case ESM4::SUB_CTDA: + reader.skipSubRecordData(); + break; default: throw std::runtime_error("ESM4::CLFM::load - Unknown subrecord " + ESM::printName(subHdr.typeId)); } diff --git a/components/esm4/loadfurn.cpp b/components/esm4/loadfurn.cpp index 90ba59eb1d..b69d92d305 100644 --- a/components/esm4/loadfurn.cpp +++ b/components/esm4/loadfurn.cpp @@ -78,6 +78,7 @@ void ESM4::Furniture::load(ESM4::Reader& reader) case ESM4::SUB_WBDT: case ESM4::SUB_XMRK: case ESM4::SUB_PRPS: + case ESM4::SUB_CTDA: reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadhdpt.cpp b/components/esm4/loadhdpt.cpp index 53b8a401ac..d74642314f 100644 --- a/components/esm4/loadhdpt.cpp +++ b/components/esm4/loadhdpt.cpp @@ -92,6 +92,7 @@ void ESM4::HeadPart::load(ESM4::Reader& reader) case ESM4::SUB_MODT: case ESM4::SUB_RNAM: case ESM4::SUB_CNAM: + case ESM4::SUB_CTDA: reader.skipSubRecordData(); break; default: From 4605894a5a108a81f86236722daec2c08be30303 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Tue, 15 Aug 2023 08:06:32 +0300 Subject: [PATCH 07/64] Updating RACE for FO4, first pass --- components/esm4/common.hpp | 48 +++++++++++++++++- components/esm4/loadrace.cpp | 95 ++++++++++++++++++++++++++++++------ 2 files changed, 127 insertions(+), 16 deletions(-) diff --git a/components/esm4/common.hpp b/components/esm4/common.hpp index 89adf6f368..06994be71a 100644 --- a/components/esm4/common.hpp +++ b/components/esm4/common.hpp @@ -658,7 +658,53 @@ namespace ESM4 SUB_JNAM = fourCC("JNAM"), // FONV SUB_EFSD = fourCC("EFSD"), // FONV DeadMoney - SUB_PRPS = fourCC("PRPS"), // FO4 + // Introduced in FO4 + SUB_APPR = fourCC("APPR"), + SUB_ATKS = fourCC("ATKS"), + SUB_ATKT = fourCC("ATKT"), + SUB_ATKW = fourCC("ATKW"), + SUB_BMMP = fourCC("BMMP"), + SUB_BSMB = fourCC("BSMB"), + SUB_BSMP = fourCC("BSMP"), + SUB_BSMS = fourCC("BSMS"), + SUB_FMRI = fourCC("FMRI"), + SUB_FMRN = fourCC("FMRN"), + SUB_HLTX = fourCC("HLTX"), + SUB_MLSI = fourCC("MLSI"), + SUB_MPGN = fourCC("MPGN"), + SUB_MPGS = fourCC("MPGS"), + SUB_MPPC = fourCC("MPPC"), + SUB_MPPF = fourCC("MPPF"), + SUB_MPPI = fourCC("MPPI"), + SUB_MPPK = fourCC("MPPK"), + SUB_MPPM = fourCC("MPPM"), + SUB_MPPN = fourCC("MPPN"), + SUB_MPPT = fourCC("MPPT"), + SUB_MSID = fourCC("MSID"), + SUB_MSM0 = fourCC("MSM0"), + SUB_MSM1 = fourCC("MSM1"), + SUB_NTOP = fourCC("NTOP"), + SUB_PRPS = fourCC("PRPS"), + SUB_PTOP = fourCC("PTOP"), + SUB_RBPC = fourCC("RBPC"), + SUB_SADD = fourCC("SADD"), + SUB_SAKD = fourCC("SAKD"), + SUB_SAPT = fourCC("SAPT"), + SUB_SGNM = fourCC("SGNM"), + SUB_SRAC = fourCC("SRAC"), + SUB_SRAF = fourCC("SRAF"), + SUB_STCP = fourCC("STCP"), + SUB_STKD = fourCC("STKD"), + SUB_TETI = fourCC("TETI"), + SUB_TTEB = fourCC("TTEB"), + SUB_TTEC = fourCC("TTEC"), + SUB_TTED = fourCC("TTED"), + SUB_TTEF = fourCC("TTEF"), + SUB_TTET = fourCC("TTET"), + SUB_TTGE = fourCC("TTGE"), + SUB_TTGP = fourCC("TTGP"), + SUB_UNWP = fourCC("UNWP"), + SUB_WMAP = fourCC("WMAP"), }; // Based on http://www.uesp.net/wiki/Tes5Mod:Mod_File_Format#Records diff --git a/components/esm4/loadrace.cpp b/components/esm4/loadrace.cpp index 576bde773f..8f5f525790 100644 --- a/components/esm4/loadrace.cpp +++ b/components/esm4/loadrace.cpp @@ -139,7 +139,7 @@ void ESM4::Race::load(ESM4::Reader& reader) reader.get(mWeightFemale); reader.get(mRaceFlags); } - else if (subHdr.dataSize >= 128 && subHdr.dataSize <= 164) // TES5 + else if (subHdr.dataSize == 128 || subHdr.dataSize == 164) // TES5 { mIsTES5 = true; @@ -188,7 +188,7 @@ void ESM4::Race::load(ESM4::Reader& reader) reader.get(dummy); // angular tolerance reader.get(dummy2); // flags - if (subHdr.dataSize > 128) + if (subHdr.dataSize == 164) { reader.get(dummy2); // unknown 1 reader.get(dummy2); // unknown 2 @@ -217,7 +217,7 @@ void ESM4::Race::load(ESM4::Reader& reader) break; } - case ESM4::SUB_CNAM: // Only in TES4? + case ESM4::SUB_CNAM: // CNAM SNAM VNAM // Sheogorath 0x0 0000 98 2b 10011000 00101011 // Golden Saint 0x3 0011 26 46 00100110 01000110 @@ -407,10 +407,16 @@ void ESM4::Race::load(ESM4::Reader& reader) // case ESM4::SUB_HNAM: { - std::size_t numHairChoices = subHdr.dataSize / sizeof(ESM::FormId32); - mHairChoices.resize(numHairChoices); - for (unsigned int i = 0; i < numHairChoices; ++i) - reader.getFormId(mHairChoices.at(i)); + // FIXME: this is a texture name in FO4 + if (subHdr.dataSize % sizeof(ESM::FormId32) != 0) + reader.skipSubRecordData(); + else + { + std::size_t numHairChoices = subHdr.dataSize / sizeof(ESM::FormId32); + mHairChoices.resize(numHairChoices); + for (unsigned int i = 0; i < numHairChoices; ++i) + reader.getFormId(mHairChoices.at(i)); + } break; } @@ -550,14 +556,23 @@ void ESM4::Race::load(ESM4::Reader& reader) break; } - case ESM4::SUB_BOD2: // TES5 + case ESM4::SUB_BOD2: { - 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); + if (subHdr.dataSize == 8 || subHdr.dataSize == 4) // TES5, FO4 + { + reader.get(mBodyTemplate.bodyPart); + mBodyTemplate.flags = 0; + mBodyTemplate.unknown1 = 0; // probably padding + mBodyTemplate.unknown2 = 0; // probably padding + mBodyTemplate.unknown3 = 0; // probably padding + mBodyTemplate.type = 0; + if (subHdr.dataSize == 8) + reader.get(mBodyTemplate.type); + } + else + { + reader.skipSubRecordData(); + } break; } @@ -675,7 +690,57 @@ void ESM4::Race::load(ESM4::Reader& reader) case ESM4::SUB_MODT: // FO3 case ESM4::SUB_MODD: // FO3 case ESM4::SUB_ONAM: // FO3 - case ESM4::SUB_PRPS: // FO4 + // FO4 + case ESM4::SUB_APPR: + case ESM4::SUB_ATKS: + case ESM4::SUB_ATKT: + case ESM4::SUB_ATKW: + case ESM4::SUB_BMMP: + case ESM4::SUB_BSMB: + case ESM4::SUB_BSMP: + case ESM4::SUB_BSMS: + case ESM4::SUB_CTDA: + case ESM4::SUB_FMRI: + case ESM4::SUB_FMRN: + case ESM4::SUB_HLTX: + case ESM4::SUB_MLSI: + case ESM4::SUB_MPGN: + case ESM4::SUB_MPGS: + case ESM4::SUB_MPPC: + case ESM4::SUB_MPPF: + case ESM4::SUB_MPPI: + case ESM4::SUB_MPPK: + case ESM4::SUB_MPPM: + case ESM4::SUB_MPPN: + case ESM4::SUB_MPPT: + case ESM4::SUB_MSID: + case ESM4::SUB_MSM0: + case ESM4::SUB_MSM1: + case ESM4::SUB_NNAM: + case ESM4::SUB_NTOP: + case ESM4::SUB_PRPS: + case ESM4::SUB_PTOP: + case ESM4::SUB_QSTI: + case ESM4::SUB_RBPC: + case ESM4::SUB_SADD: + case ESM4::SUB_SAKD: + case ESM4::SUB_SAPT: + case ESM4::SUB_SGNM: + case ESM4::SUB_SRAC: + case ESM4::SUB_SRAF: + case ESM4::SUB_STCP: + case ESM4::SUB_STKD: + case ESM4::SUB_TETI: + case ESM4::SUB_TTEB: + case ESM4::SUB_TTEC: + case ESM4::SUB_TTED: + case ESM4::SUB_TTEF: + case ESM4::SUB_TTET: + case ESM4::SUB_TTGE: + case ESM4::SUB_TTGP: + case ESM4::SUB_UNWP: + case ESM4::SUB_WMAP: + case ESM4::SUB_ZNAM: reader.skipSubRecordData(); break; default: From 426eae384334ccee488da3408178e548cdadb98f Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Tue, 15 Aug 2023 10:03:52 +0300 Subject: [PATCH 08/64] ESM4::RACE: don't use current index if it's unset To be safer. Doesn't help with FO4 segfaults though --- components/esm4/loadrace.cpp | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/components/esm4/loadrace.cpp b/components/esm4/loadrace.cpp index 8f5f525790..1b568379dd 100644 --- a/components/esm4/loadrace.cpp +++ b/components/esm4/loadrace.cpp @@ -315,7 +315,11 @@ void ESM4::Race::load(ESM4::Reader& reader) } case ESM4::SUB_MODL: { - if (curr_part == 0) // head part + if (currentIndex == 0xffffffff) + { + reader.skipSubRecordData(); + } + else if (curr_part == 0) // head part { if (isMale || isTES4) reader.getZString(mHeadParts[currentIndex].mesh); @@ -351,7 +355,11 @@ void ESM4::Race::load(ESM4::Reader& reader) break; // always 0x0000? case ESM4::SUB_ICON: { - if (curr_part == 0) // head part + if (currentIndex == 0xffffffff) + { + reader.skipSubRecordData(); + } + else if (curr_part == 0) // head part { if (isMale || isTES4) reader.getZString(mHeadParts[currentIndex].texture); @@ -581,11 +589,14 @@ void ESM4::Race::load(ESM4::Reader& reader) ESM::FormId formId; reader.getFormId(formId); - // FIXME: no order? head, mouth, eyes, brow, hair - if (isMale) - mHeadPartIdsMale[currentIndex] = formId; - else - mHeadPartIdsFemale[currentIndex] = formId; + if (currentIndex != 0xffffffff) + { + // FIXME: no order? head, mouth, eyes, brow, hair + if (isMale) + mHeadPartIdsMale[currentIndex] = formId; + else + mHeadPartIdsFemale[currentIndex] = formId; + } // std::cout << mEditorId << (isMale ? " male head " : " female head ") // << formIdToString(formId) << " " << currentIndex << std::endl; // FIXME From 5e5a25f9011ab1b38f267b4c3b0f8cdf1ec11ee4 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Tue, 15 Aug 2023 22:22:28 +0300 Subject: [PATCH 09/64] Show BA2 files in the launcher --- apps/launcher/datafilespage.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index d81f6dda58..756aaba131 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -40,7 +40,7 @@ namespace { void contentSubdirs(const QString& path, QStringList& dirs) { - QStringList fileFilter{ "*.esm", "*.esp", "*.omwaddon", "*.bsa", "*.omwscripts" }; + QStringList fileFilter{ "*.esm", "*.esp", "*.omwaddon", "*.bsa", "*.ba2", "*.omwscripts" }; QStringList dirFilter{ "bookart", "icons", "meshes", "music", "sound", "textures" }; QDir currentDir(path); @@ -722,13 +722,14 @@ void Launcher::DataFilesPage::addArchive(const QString& name, Qt::CheckState sel void Launcher::DataFilesPage::addArchivesFromDir(const QString& path) { - QDir dir(path, "*.bsa"); + QStringList archiveFilter{ "*.bsa", "*.ba2" }; + QDir dir(path); std::unordered_set archives; for (int i = 0; i < ui.archiveListWidget->count(); ++i) archives.insert(ui.archiveListWidget->item(i)->text()); - for (const auto& fileinfo : dir.entryInfoList()) + for (const auto& fileinfo : dir.entryInfoList(archiveFilter)) { const auto absPath = fileinfo.absoluteFilePath(); if (Bsa::BSAFile::detectVersion(Files::pathFromQString(absPath)) == Bsa::BSAVER_UNKNOWN) From c706a46dc4aada97848f6056ed23a34e31d98751 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Tue, 15 Aug 2023 22:44:49 +0300 Subject: [PATCH 10/64] ESM4::RACE: fix loading more than 5 head parts in FO4 --- components/esm4/loadrace.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/components/esm4/loadrace.cpp b/components/esm4/loadrace.cpp index 1b568379dd..a2da871a4a 100644 --- a/components/esm4/loadrace.cpp +++ b/components/esm4/loadrace.cpp @@ -287,7 +287,7 @@ void ESM4::Race::load(ESM4::Reader& reader) } else if (isTES4) mHeadParts.resize(9); // assumed based on Construction Set - else + else // Optimized for TES5 { mHeadPartIdsMale.resize(5); mHeadPartIdsFemale.resize(5); @@ -593,9 +593,17 @@ void ESM4::Race::load(ESM4::Reader& reader) { // FIXME: no order? head, mouth, eyes, brow, hair if (isMale) + { + if (currentIndex >= mHeadPartIdsMale.size()) + mHeadPartIdsMale.resize(currentIndex + 1); mHeadPartIdsMale[currentIndex] = formId; + } else + { + if (currentIndex >= mHeadPartIdsFemale.size()) + mHeadPartIdsFemale.resize(currentIndex + 1); mHeadPartIdsFemale[currentIndex] = formId; + } } // std::cout << mEditorId << (isMale ? " male head " : " female head ") From 1a7d68cd33a245f9323d4cfc150682fb515014cf Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Tue, 15 Aug 2023 22:54:25 +0300 Subject: [PATCH 11/64] Skip FO4 SOUN::REPT --- components/esm4/common.hpp | 1 + components/esm4/loadsoun.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/components/esm4/common.hpp b/components/esm4/common.hpp index 06994be71a..2badf02f44 100644 --- a/components/esm4/common.hpp +++ b/components/esm4/common.hpp @@ -687,6 +687,7 @@ namespace ESM4 SUB_PRPS = fourCC("PRPS"), SUB_PTOP = fourCC("PTOP"), SUB_RBPC = fourCC("RBPC"), + SUB_REPT = fourCC("REPT"), SUB_SADD = fourCC("SADD"), SUB_SAKD = fourCC("SAKD"), SUB_SAPT = fourCC("SAPT"), diff --git a/components/esm4/loadsoun.cpp b/components/esm4/loadsoun.cpp index 440aaaf8d2..a5ae005fe2 100644 --- a/components/esm4/loadsoun.cpp +++ b/components/esm4/loadsoun.cpp @@ -65,6 +65,7 @@ void ESM4::Sound::load(ESM4::Reader& reader) case ESM4::SUB_GNAM: // FO3 case ESM4::SUB_HNAM: // FO3 case ESM4::SUB_RNAM: // FONV + case ESM4::SUB_REPT: // FO4 reader.skipSubRecordData(); break; default: From 5bce6d8d445eaf85b6c0d4647501a85cf33ae786 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Tue, 15 Aug 2023 23:14:21 +0300 Subject: [PATCH 12/64] Maybe load some FO4 static records --- components/esm4/common.hpp | 2 ++ components/esm4/loadstat.cpp | 8 ++++++++ components/esm4/loadstat.hpp | 1 + 3 files changed, 11 insertions(+) diff --git a/components/esm4/common.hpp b/components/esm4/common.hpp index 2badf02f44..ca43bfca56 100644 --- a/components/esm4/common.hpp +++ b/components/esm4/common.hpp @@ -669,6 +669,7 @@ namespace ESM4 SUB_BSMS = fourCC("BSMS"), SUB_FMRI = fourCC("FMRI"), SUB_FMRN = fourCC("FMRN"), + SUB_FTYP = fourCC("FTYP"), SUB_HLTX = fourCC("HLTX"), SUB_MLSI = fourCC("MLSI"), SUB_MPGN = fourCC("MPGN"), @@ -686,6 +687,7 @@ namespace ESM4 SUB_NTOP = fourCC("NTOP"), SUB_PRPS = fourCC("PRPS"), SUB_PTOP = fourCC("PTOP"), + SUB_PTRN = fourCC("PTRN"), SUB_RBPC = fourCC("RBPC"), SUB_REPT = fourCC("REPT"), SUB_SADD = fourCC("SADD"), diff --git a/components/esm4/loadstat.cpp b/components/esm4/loadstat.cpp index d3a1c86b85..640db00d1e 100644 --- a/components/esm4/loadstat.cpp +++ b/components/esm4/loadstat.cpp @@ -44,6 +44,9 @@ void ESM4::Static::load(ESM4::Reader& reader) case ESM4::SUB_EDID: reader.getZString(mEditorId); break; + case ESM4::SUB_FULL: + reader.getLocalizedString(mFullName); + break; case ESM4::SUB_MODL: reader.getZString(mModel); break; @@ -86,7 +89,12 @@ void ESM4::Static::load(ESM4::Reader& reader) case ESM4::SUB_DNAM: case ESM4::SUB_BRUS: // FONV case ESM4::SUB_RNAM: // FONV + // FO4 + case ESM4::SUB_FTYP: + case ESM4::SUB_NVNM: case ESM4::SUB_PRPS: + case ESM4::SUB_PTRN: + case ESM4::SUB_VMAD: reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadstat.hpp b/components/esm4/loadstat.hpp index 266d07b78f..3c1f047bae 100644 --- a/components/esm4/loadstat.hpp +++ b/components/esm4/loadstat.hpp @@ -47,6 +47,7 @@ namespace ESM4 std::uint32_t mFlags; // from the header, see enum type RecordFlag for details std::string mEditorId; + std::string mFullName; std::string mModel; float mBoundRadius; From d74df61ce5cf6033655d13bc06b46b5aa8843b67 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Tue, 15 Aug 2023 23:52:55 +0300 Subject: [PATCH 13/64] Load FO4 acoustic space records --- components/esm4/loadaspc.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/components/esm4/loadaspc.cpp b/components/esm4/loadaspc.cpp index 0cb3590404..d79df9d8ef 100644 --- a/components/esm4/loadaspc.cpp +++ b/components/esm4/loadaspc.cpp @@ -56,10 +56,16 @@ void ESM4::AcousticSpace::load(ESM4::Reader& reader) case ESM4::SUB_INAM: reader.get(mIsInterior); break; - case ESM4::SUB_WNAM: // usually 0 for FONV (maybe # of close Actors for Walla to trigger) + case ESM4::SUB_XTRI: + std::uint8_t isInterior; + reader.get(isInterior); + mIsInterior = isInterior; + break; + case ESM4::SUB_WNAM: { - std::uint32_t dummy; - reader.get(dummy); + // usually 0 for FONV (maybe # of close Actors for Walla to trigger) (4 bytes) + // Weather attenuation in FO4 (2 bytes) + reader.skipSubRecordData(); break; } case ESM4::SUB_BNAM: // TES5 reverb formid From a2ed295f1f47d407749662db361ae372d90b6ee1 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 16 Aug 2023 00:09:20 +0300 Subject: [PATCH 14/64] Update ESM4 LTEX loading Load grasses into a list Fix FO4 loading Load Havok parameters for FNV --- components/esm4/loadltex.cpp | 27 +++++++++++---------------- components/esm4/loadltex.hpp | 4 ++-- 2 files changed, 13 insertions(+), 18 deletions(-) diff --git a/components/esm4/loadltex.cpp b/components/esm4/loadltex.cpp index 55409c75ae..b6f083dd03 100644 --- a/components/esm4/loadltex.cpp +++ b/components/esm4/loadltex.cpp @@ -35,8 +35,6 @@ void ESM4::LandTexture::load(ESM4::Reader& reader) { mId = reader.getFormIdFromHeader(); 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()) { @@ -48,26 +46,23 @@ void ESM4::LandTexture::load(ESM4::Reader& reader) break; case ESM4::SUB_HNAM: { - if (isFONV) - { - reader.skipSubRecordData(); // FIXME: skip FONV for now - break; - } - - if ((reader.esmVersion() == ESM::VER_094 || reader.esmVersion() == ESM::VER_170) - && subHdr.dataSize == 2) // FO3 is VER_094 but dataSize 3 + // TES5+ + if (subHdr.dataSize == 2) { reader.get(mHavokFriction); reader.get(mHavokRestitution); } - else + // TES4, FO3, FNV + else if (subHdr.dataSize == 3) { - if (subHdr.dataSize != 3) - throw std::runtime_error("LTEX unexpected HNAM size, expected 3"); reader.get(mHavokMaterial); reader.get(mHavokFriction); reader.get(mHavokRestitution); } + else + { + reader.skipSubRecordData(); + } break; } case ESM4::SUB_ICON: @@ -77,14 +72,14 @@ void ESM4::LandTexture::load(ESM4::Reader& reader) reader.get(mTextureSpecular); break; case ESM4::SUB_GNAM: - reader.getFormId(mGrass); + reader.getFormId(mGrass.emplace_back()); break; case ESM4::SUB_TNAM: reader.getFormId(mTexture); - break; // TES5 only + break; // TES5, FO4 case ESM4::SUB_MNAM: reader.getFormId(mMaterial); - break; // TES5 only + break; // TES5, FO4 default: throw std::runtime_error("ESM4::LTEX::load - Unknown subrecord " + ESM::printName(subHdr.typeId)); } diff --git a/components/esm4/loadltex.hpp b/components/esm4/loadltex.hpp index 5fea61d0d0..bed5887f5c 100644 --- a/components/esm4/loadltex.hpp +++ b/components/esm4/loadltex.hpp @@ -49,14 +49,14 @@ namespace ESM4 std::uint8_t mHavokRestitution; std::uint8_t mTextureSpecular; // default 30 - ESM::FormId mGrass; + std::vector mGrass; // ------ TES4 only ----- std::string mTextureFile; std::uint8_t mHavokMaterial; - // ------ TES5 only ----- + // ------ TES5, FO4 ----- ESM::FormId mTexture; ESM::FormId mMaterial; From d15f3011933e43941bcb85ae7133343d42e527c9 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 16 Aug 2023 00:22:16 +0300 Subject: [PATCH 15/64] Load FO4 activator records --- components/esm4/common.hpp | 3 +++ components/esm4/loadacti.cpp | 13 ++++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/components/esm4/common.hpp b/components/esm4/common.hpp index ca43bfca56..768cdbfccb 100644 --- a/components/esm4/common.hpp +++ b/components/esm4/common.hpp @@ -663,6 +663,7 @@ namespace ESM4 SUB_ATKS = fourCC("ATKS"), SUB_ATKT = fourCC("ATKT"), SUB_ATKW = fourCC("ATKW"), + SUB_ATTX = fourCC("ATTX"), SUB_BMMP = fourCC("BMMP"), SUB_BSMB = fourCC("BSMB"), SUB_BSMP = fourCC("BSMP"), @@ -685,9 +686,11 @@ namespace ESM4 SUB_MSM0 = fourCC("MSM0"), SUB_MSM1 = fourCC("MSM1"), SUB_NTOP = fourCC("NTOP"), + SUB_NTRM = fourCC("NTRM"), SUB_PRPS = fourCC("PRPS"), SUB_PTOP = fourCC("PTOP"), SUB_PTRN = fourCC("PTRN"), + SUB_RADR = fourCC("RADR"), SUB_RBPC = fourCC("RBPC"), SUB_REPT = fourCC("REPT"), SUB_SADD = fourCC("SADD"), diff --git a/components/esm4/loadacti.cpp b/components/esm4/loadacti.cpp index 418da82b4b..91336a5bee 100644 --- a/components/esm4/loadacti.cpp +++ b/components/esm4/loadacti.cpp @@ -87,8 +87,19 @@ void ESM4::Activator::load(ESM4::Reader& reader) case ESM4::SUB_PNAM: case ESM4::SUB_VMAD: case ESM4::SUB_WNAM: - case ESM4::SUB_PRPS: case ESM4::SUB_CTDA: + case ESM4::SUB_CIS1: + case ESM4::SUB_CIS2: + case ESM4::SUB_CITC: + case ESM4::SUB_NVNM: + // Introduced in FO4 + case ESM4::SUB_ATTX: + case ESM4::SUB_FTYP: + case ESM4::SUB_NTRM: + case ESM4::SUB_PTRN: + case ESM4::SUB_PRPS: + case ESM4::SUB_RADR: + case ESM4::SUB_STCP: reader.skipSubRecordData(); break; default: From 0efc9865f6b0bbeecf0de759ae70142be224ba06 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 16 Aug 2023 03:25:19 +0300 Subject: [PATCH 16/64] Alphabetize SubRecordTypes and include all subrecords used in FO4 SUA_BTXT => SUB_BTXT --- components/esm4/common.hpp | 1112 +++++++++++++++++++--------------- components/esm4/loadland.cpp | 2 +- 2 files changed, 629 insertions(+), 485 deletions(-) diff --git a/components/esm4/common.hpp b/components/esm4/common.hpp index 768cdbfccb..8f37bfb8d4 100644 --- a/components/esm4/common.hpp +++ b/components/esm4/common.hpp @@ -33,7 +33,6 @@ namespace ESM4 { using ESM::fourCC; - // Based on http://www.uesp.net/wiki/Tes5Mod:Mod_File_Format enum RecordTypes { REC_AACT = fourCC("AACT"), // Action @@ -179,376 +178,23 @@ namespace ESM4 enum SubRecordTypes { - SUB_HEDR = fourCC("HEDR"), - SUB_CNAM = fourCC("CNAM"), - SUB_SNAM = fourCC("SNAM"), // TES4 only? - SUB_MAST = fourCC("MAST"), - SUB_DATA = fourCC("DATA"), - SUB_ONAM = fourCC("ONAM"), - SUB_INTV = fourCC("INTV"), - SUB_INCC = fourCC("INCC"), - SUB_OFST = fourCC("OFST"), // TES4 only? - SUB_DELE = fourCC("DELE"), // TES4 only? - - SUB_DNAM = fourCC("DNAM"), - SUB_EDID = fourCC("EDID"), - SUB_FULL = fourCC("FULL"), - SUB_LTMP = fourCC("LTMP"), - SUB_MHDT = fourCC("MHDT"), - SUB_MNAM = fourCC("MNAM"), - SUB_MODL = fourCC("MODL"), - SUB_NAM0 = fourCC("NAM0"), - SUB_NAM2 = fourCC("NAM2"), - SUB_NAM3 = fourCC("NAM3"), - SUB_NAM4 = fourCC("NAM4"), - SUB_NAM9 = fourCC("NAM9"), - SUB_NAMA = fourCC("NAMA"), - SUB_PNAM = fourCC("PNAM"), - SUB_RNAM = fourCC("RNAM"), - SUB_TNAM = fourCC("TNAM"), - SUB_UNAM = fourCC("UNAM"), - SUB_WCTR = fourCC("WCTR"), - SUB_WNAM = fourCC("WNAM"), - SUB_XEZN = fourCC("XEZN"), - SUB_XLCN = fourCC("XLCN"), - SUB_XXXX = fourCC("XXXX"), - SUB_ZNAM = fourCC("ZNAM"), - SUB_MODT = fourCC("MODT"), - SUB_ICON = fourCC("ICON"), // TES4 only? - - SUB_NVER = fourCC("NVER"), - SUB_NVMI = fourCC("NVMI"), - SUB_NVPP = fourCC("NVPP"), - SUB_NVSI = fourCC("NVSI"), - - SUB_NVNM = fourCC("NVNM"), - SUB_NNAM = fourCC("NNAM"), - - SUB_XCLC = fourCC("XCLC"), - SUB_XCLL = fourCC("XCLL"), - SUB_TVDT = fourCC("TVDT"), - SUB_XCGD = fourCC("XCGD"), - SUB_LNAM = fourCC("LNAM"), - SUB_XCLW = fourCC("XCLW"), - SUB_XNAM = fourCC("XNAM"), - SUB_XCLR = fourCC("XCLR"), - SUB_XWCS = fourCC("XWCS"), - SUB_XWCN = fourCC("XWCN"), - SUB_XWCU = fourCC("XWCU"), - SUB_XCWT = fourCC("XCWT"), - SUB_XOWN = fourCC("XOWN"), - SUB_XILL = fourCC("XILL"), - SUB_XWEM = fourCC("XWEM"), - SUB_XCCM = fourCC("XCCM"), - SUB_XCAS = fourCC("XCAS"), - SUB_XCMO = fourCC("XCMO"), - SUB_XCIM = fourCC("XCIM"), - SUB_XCMT = fourCC("XCMT"), // TES4 only? - SUB_XRNK = fourCC("XRNK"), // TES4 only? - SUB_XGLB = fourCC("XGLB"), // TES4 only? - - SUB_VNML = fourCC("VNML"), - SUB_VHGT = fourCC("VHGT"), - SUB_VCLR = fourCC("VCLR"), - SUA_BTXT = fourCC("BTXT"), - SUB_ATXT = fourCC("ATXT"), - SUB_VTXT = fourCC("VTXT"), - SUB_VTEX = fourCC("VTEX"), - - SUB_HNAM = fourCC("HNAM"), - SUB_GNAM = fourCC("GNAM"), - - SUB_RCLR = fourCC("RCLR"), - SUB_RPLI = fourCC("RPLI"), - SUB_RPLD = fourCC("RPLD"), - SUB_RDAT = fourCC("RDAT"), - SUB_RDMD = fourCC("RDMD"), // TES4 only? - SUB_RDSD = fourCC("RDSD"), // TES4 only? - SUB_RDGS = fourCC("RDGS"), // TES4 only? - SUB_RDMO = fourCC("RDMO"), - SUB_RDSA = fourCC("RDSA"), - SUB_RDWT = fourCC("RDWT"), - SUB_RDOT = fourCC("RDOT"), - SUB_RDMP = fourCC("RDMP"), - - SUB_MODB = fourCC("MODB"), - SUB_OBND = fourCC("OBND"), - SUB_MODS = fourCC("MODS"), - - SUB_NAME = fourCC("NAME"), - SUB_XMRK = fourCC("XMRK"), - SUB_FNAM = fourCC("FNAM"), - SUB_XSCL = fourCC("XSCL"), - SUB_XTEL = fourCC("XTEL"), - SUB_XTRG = fourCC("XTRG"), - SUB_XSED = fourCC("XSED"), - SUB_XLOD = fourCC("XLOD"), - SUB_XPCI = fourCC("XPCI"), - SUB_XLOC = fourCC("XLOC"), - SUB_XESP = fourCC("XESP"), - SUB_XLCM = fourCC("XLCM"), - SUB_XRTM = fourCC("XRTM"), - SUB_XACT = fourCC("XACT"), - SUB_XCNT = fourCC("XCNT"), - SUB_VMAD = fourCC("VMAD"), - SUB_XPRM = fourCC("XPRM"), - SUB_XMBO = fourCC("XMBO"), - SUB_XPOD = fourCC("XPOD"), - SUB_XPTL = fourCC("XPTL"), - SUB_XRMR = fourCC("XRMR"), - SUB_INAM = fourCC("INAM"), - SUB_SCHR = fourCC("SCHR"), - SUB_XLRM = fourCC("XLRM"), - SUB_XRGD = fourCC("XRGD"), - SUB_XRDS = fourCC("XRDS"), - SUB_XEMI = fourCC("XEMI"), - SUB_XLIG = fourCC("XLIG"), - SUB_XALP = fourCC("XALP"), - SUB_XNDP = fourCC("XNDP"), - SUB_XAPD = fourCC("XAPD"), - SUB_XAPR = fourCC("XAPR"), - SUB_XLIB = fourCC("XLIB"), - SUB_XLKR = fourCC("XLKR"), - SUB_XLRT = fourCC("XLRT"), - SUB_XCVL = fourCC("XCVL"), - SUB_XCVR = fourCC("XCVR"), - SUB_XCZA = fourCC("XCZA"), - SUB_XCZC = fourCC("XCZC"), - SUB_XFVC = fourCC("XFVC"), - SUB_XHTW = fourCC("XHTW"), - SUB_XIS2 = fourCC("XIS2"), - SUB_XMBR = fourCC("XMBR"), - SUB_XCCP = fourCC("XCCP"), - SUB_XPWR = fourCC("XPWR"), - SUB_XTRI = fourCC("XTRI"), - SUB_XATR = fourCC("XATR"), - SUB_XPRD = fourCC("XPRD"), - SUB_XPPA = fourCC("XPPA"), - SUB_PDTO = fourCC("PDTO"), - SUB_XLRL = fourCC("XLRL"), - - SUB_QNAM = fourCC("QNAM"), - SUB_COCT = fourCC("COCT"), - SUB_COED = fourCC("COED"), - SUB_CNTO = fourCC("CNTO"), - SUB_SCRI = fourCC("SCRI"), - - SUB_BNAM = fourCC("BNAM"), - - SUB_BMDT = fourCC("BMDT"), - SUB_MOD2 = fourCC("MOD2"), - SUB_MOD3 = fourCC("MOD3"), - SUB_MOD4 = fourCC("MOD4"), - SUB_MO2B = fourCC("MO2B"), - SUB_MO3B = fourCC("MO3B"), - SUB_MO4B = fourCC("MO4B"), - SUB_MO2T = fourCC("MO2T"), - SUB_MO3T = fourCC("MO3T"), - SUB_MO4T = fourCC("MO4T"), - SUB_ANAM = fourCC("ANAM"), - SUB_ENAM = fourCC("ENAM"), - SUB_ICO2 = fourCC("ICO2"), - - SUB_ACBS = fourCC("ACBS"), - SUB_SPLO = fourCC("SPLO"), - SUB_AIDT = fourCC("AIDT"), - SUB_PKID = fourCC("PKID"), - SUB_HCLR = fourCC("HCLR"), - SUB_FGGS = fourCC("FGGS"), - SUB_FGGA = fourCC("FGGA"), - SUB_FGTS = fourCC("FGTS"), - SUB_KFFZ = fourCC("KFFZ"), - - SUB_PFIG = fourCC("PFIG"), - SUB_PFPC = fourCC("PFPC"), - - SUB_XHRS = fourCC("XHRS"), - SUB_XMRC = fourCC("XMRC"), - - SUB_SNDD = fourCC("SNDD"), - SUB_SNDX = fourCC("SNDX"), - - SUB_DESC = fourCC("DESC"), - - SUB_ENIT = fourCC("ENIT"), - SUB_EFID = fourCC("EFID"), - SUB_EFIT = fourCC("EFIT"), - SUB_SCIT = fourCC("SCIT"), - - SUB_SOUL = fourCC("SOUL"), - SUB_SLCP = fourCC("SLCP"), - - SUB_CSCR = fourCC("CSCR"), - SUB_CSDI = fourCC("CSDI"), - SUB_CSDC = fourCC("CSDC"), - SUB_NIFZ = fourCC("NIFZ"), - SUB_CSDT = fourCC("CSDT"), - SUB_NAM1 = fourCC("NAM1"), - SUB_NIFT = fourCC("NIFT"), - - SUB_LVLD = fourCC("LVLD"), - SUB_LVLF = fourCC("LVLF"), - SUB_LVLO = fourCC("LVLO"), - - SUB_BODT = fourCC("BODT"), - SUB_YNAM = fourCC("YNAM"), - SUB_DEST = fourCC("DEST"), - SUB_DMDL = fourCC("DMDL"), - SUB_DMDS = fourCC("DMDS"), - SUB_DMDT = fourCC("DMDT"), - SUB_DSTD = fourCC("DSTD"), - SUB_DSTF = fourCC("DSTF"), - SUB_KNAM = fourCC("KNAM"), - SUB_KSIZ = fourCC("KSIZ"), - SUB_KWDA = fourCC("KWDA"), - SUB_VNAM = fourCC("VNAM"), - SUB_SDSC = fourCC("SDSC"), - SUB_MO2S = fourCC("MO2S"), - SUB_MO4S = fourCC("MO4S"), - SUB_BOD2 = fourCC("BOD2"), - SUB_BAMT = fourCC("BAMT"), - SUB_BIDS = fourCC("BIDS"), - SUB_ETYP = fourCC("ETYP"), - SUB_BMCT = fourCC("BMCT"), - SUB_MICO = fourCC("MICO"), - SUB_MIC2 = fourCC("MIC2"), - SUB_EAMT = fourCC("EAMT"), - SUB_EITM = fourCC("EITM"), - - SUB_SCTX = fourCC("SCTX"), - SUB_XLTW = fourCC("XLTW"), - SUB_XMBP = fourCC("XMBP"), - SUB_XOCP = fourCC("XOCP"), - SUB_XRGB = fourCC("XRGB"), - SUB_XSPC = fourCC("XSPC"), - SUB_XTNM = fourCC("XTNM"), - SUB_ATKR = fourCC("ATKR"), - SUB_CRIF = fourCC("CRIF"), - SUB_DOFT = fourCC("DOFT"), - SUB_DPLT = fourCC("DPLT"), - SUB_ECOR = fourCC("ECOR"), - SUB_ATKD = fourCC("ATKD"), - SUB_ATKE = fourCC("ATKE"), - SUB_FTST = fourCC("FTST"), - SUB_HCLF = fourCC("HCLF"), - SUB_NAM5 = fourCC("NAM5"), - SUB_NAM6 = fourCC("NAM6"), - SUB_NAM7 = fourCC("NAM7"), - SUB_NAM8 = fourCC("NAM8"), - SUB_PRKR = fourCC("PRKR"), - SUB_PRKZ = fourCC("PRKZ"), - SUB_SOFT = fourCC("SOFT"), - SUB_SPCT = fourCC("SPCT"), - SUB_TINC = fourCC("TINC"), - SUB_TIAS = fourCC("TIAS"), - SUB_TINI = fourCC("TINI"), - SUB_TINV = fourCC("TINV"), - SUB_TPLT = fourCC("TPLT"), - SUB_VTCK = fourCC("VTCK"), - SUB_SHRT = fourCC("SHRT"), - SUB_SPOR = fourCC("SPOR"), - SUB_XHOR = fourCC("XHOR"), - SUB_CTDA = fourCC("CTDA"), - SUB_CRDT = fourCC("CRDT"), - SUB_FNMK = fourCC("FNMK"), - SUB_FNPR = fourCC("FNPR"), - SUB_WBDT = fourCC("WBDT"), - SUB_QUAL = fourCC("QUAL"), - SUB_INDX = fourCC("INDX"), - SUB_ATTR = fourCC("ATTR"), - SUB_MTNM = fourCC("MTNM"), - SUB_UNES = fourCC("UNES"), - SUB_TIND = fourCC("TIND"), - SUB_TINL = fourCC("TINL"), - SUB_TINP = fourCC("TINP"), - SUB_TINT = fourCC("TINT"), - SUB_TIRS = fourCC("TIRS"), - SUB_PHWT = fourCC("PHWT"), - SUB_AHCF = fourCC("AHCF"), - SUB_AHCM = fourCC("AHCM"), - SUB_HEAD = fourCC("HEAD"), - SUB_MPAI = fourCC("MPAI"), - SUB_MPAV = fourCC("MPAV"), - SUB_DFTF = fourCC("DFTF"), - SUB_DFTM = fourCC("DFTM"), - SUB_FLMV = fourCC("FLMV"), - SUB_FTSF = fourCC("FTSF"), - SUB_FTSM = fourCC("FTSM"), - SUB_MTYP = fourCC("MTYP"), - SUB_PHTN = fourCC("PHTN"), - SUB_RNMV = fourCC("RNMV"), - SUB_RPRF = fourCC("RPRF"), - SUB_RPRM = fourCC("RPRM"), - SUB_SNMV = fourCC("SNMV"), - SUB_SPED = fourCC("SPED"), - SUB_SWMV = fourCC("SWMV"), - SUB_WKMV = fourCC("WKMV"), - SUB_LLCT = fourCC("LLCT"), - SUB_IDLF = fourCC("IDLF"), - SUB_IDLA = fourCC("IDLA"), - SUB_IDLC = fourCC("IDLC"), - SUB_IDLT = fourCC("IDLT"), - SUB_DODT = fourCC("DODT"), - SUB_TX00 = fourCC("TX00"), - SUB_TX01 = fourCC("TX01"), - SUB_TX02 = fourCC("TX02"), - SUB_TX03 = fourCC("TX03"), - SUB_TX04 = fourCC("TX04"), - SUB_TX05 = fourCC("TX05"), - SUB_TX06 = fourCC("TX06"), - SUB_TX07 = fourCC("TX07"), - SUB_BPND = fourCC("BPND"), - SUB_BPTN = fourCC("BPTN"), - SUB_BPNN = fourCC("BPNN"), - SUB_BPNT = fourCC("BPNT"), - SUB_BPNI = fourCC("BPNI"), - SUB_RAGA = fourCC("RAGA"), - - SUB_QSTI = fourCC("QSTI"), - SUB_QSTR = fourCC("QSTR"), - SUB_QSDT = fourCC("QSDT"), - SUB_SCDA = fourCC("SCDA"), - SUB_SCRO = fourCC("SCRO"), - SUB_QSTA = fourCC("QSTA"), - SUB_CTDT = fourCC("CTDT"), - SUB_SCHD = fourCC("SCHD"), - SUB_TCLF = fourCC("TCLF"), - SUB_TCLT = fourCC("TCLT"), - SUB_TRDT = fourCC("TRDT"), - SUB_TPIC = fourCC("TPIC"), - - SUB_PKDT = fourCC("PKDT"), - SUB_PSDT = fourCC("PSDT"), - SUB_PLDT = fourCC("PLDT"), - SUB_PTDT = fourCC("PTDT"), - SUB_PGRP = fourCC("PGRP"), - SUB_PGRR = fourCC("PGRR"), - SUB_PGRI = fourCC("PGRI"), - SUB_PGRL = fourCC("PGRL"), - SUB_PGAG = fourCC("PGAG"), - SUB_FLTV = fourCC("FLTV"), - - SUB_XHLT = fourCC("XHLT"), // Unofficial Oblivion Patch - SUB_XCHG = fourCC("XCHG"), // thievery.exp - - SUB_ITXT = fourCC("ITXT"), - SUB_MO5T = fourCC("MO5T"), - SUB_MOD5 = fourCC("MOD5"), - SUB_MDOB = fourCC("MDOB"), - SUB_SPIT = fourCC("SPIT"), - SUB_PTDA = fourCC("PTDA"), // TES5 - SUB_PFOR = fourCC("PFOR"), // TES5 - SUB_PFO2 = fourCC("PFO2"), // TES5 - SUB_PRCB = fourCC("PRCB"), // TES5 - SUB_PKCU = fourCC("PKCU"), // TES5 - SUB_PKC2 = fourCC("PKC2"), // TES5 - SUB_CITC = fourCC("CITC"), // TES5 - SUB_CIS1 = fourCC("CIS1"), // TES5 - SUB_CIS2 = fourCC("CIS2"), // TES5 - SUB_TIFC = fourCC("TIFC"), // TES5 + SUB_ACBS = fourCC("ACBS"), + SUB_ACEC = fourCC("ACEC"), // TES5 Dawnguard + SUB_ACEP = fourCC("ACEP"), // TES5 Dawnguard + SUB_ACID = fourCC("ACID"), // TES5 Dawnguard + SUB_ACPR = fourCC("ACPR"), // TES5 + SUB_ACSR = fourCC("ACSR"), // TES5 Dawnguard + SUB_ACTV = fourCC("ACTV"), // FO4 + SUB_ACUN = fourCC("ACUN"), // TES5 Dawnguard + SUB_AHCF = fourCC("AHCF"), + SUB_AHCM = fourCC("AHCM"), + SUB_AIDT = fourCC("AIDT"), SUB_ALCA = fourCC("ALCA"), // TES5 + SUB_ALCC = fourCC("ALCC"), // FO4 SUB_ALCL = fourCC("ALCL"), // TES5 SUB_ALCO = fourCC("ALCO"), // TES5 + SUB_ALCS = fourCC("ALCS"), // FO4 + SUB_ALDI = fourCC("ALDI"), // FO4 SUB_ALDN = fourCC("ALDN"), // TES5 SUB_ALEA = fourCC("ALEA"), // TES5 SUB_ALED = fourCC("ALED"), // TES5 @@ -560,8 +206,11 @@ namespace ESM4 SUB_ALFI = fourCC("ALFI"), // TES5 SUB_ALFL = fourCC("ALFL"), // TES5 SUB_ALFR = fourCC("ALFR"), // TES5 + SUB_ALFV = fourCC("ALFV"), // FO4 SUB_ALID = fourCC("ALID"), // TES5 + SUB_ALLA = fourCC("ALLA"), // FO4 SUB_ALLS = fourCC("ALLS"), // TES5 + SUB_ALMI = fourCC("ALMI"), // FO4 SUB_ALNA = fourCC("ALNA"), // TES5 SUB_ALNT = fourCC("ALNT"), // TES5 SUB_ALPC = fourCC("ALPC"), // TES5 @@ -569,85 +218,525 @@ namespace ESM4 SUB_ALSP = fourCC("ALSP"), // TES5 SUB_ALST = fourCC("ALST"), // TES5 SUB_ALUA = fourCC("ALUA"), // TES5 - SUB_FLTR = fourCC("FLTR"), // TES5 - SUB_QTGL = fourCC("QTGL"), // TES5 - SUB_TWAT = fourCC("TWAT"), // TES5 - SUB_SPMV = fourCC("SPMV"), // TES5 - SUB_XIBS = fourCC("XIBS"), // FO3 - SUB_REPL = fourCC("REPL"), // FO3 + SUB_ANAM = fourCC("ANAM"), + SUB_AOR2 = fourCC("AOR2"), // FO4 + SUB_APPR = fourCC("APPR"), // FO4 + SUB_ATKD = fourCC("ATKD"), + SUB_ATKE = fourCC("ATKE"), + SUB_ATKR = fourCC("ATKR"), + SUB_ATKS = fourCC("ATKS"), // FO4 + SUB_ATKT = fourCC("ATKT"), // FO4 + SUB_ATKW = fourCC("ATKW"), // FO4 + SUB_ATTN = fourCC("ATTN"), // FO4 + SUB_ATTR = fourCC("ATTR"), + SUB_ATTX = fourCC("ATTX"), // FO4 + SUB_ATXT = fourCC("ATXT"), + SUB_AVFL = fourCC("AVFL"), // FO4 + SUB_AVSK = fourCC("AVSK"), // TES5 + SUB_BAMT = fourCC("BAMT"), + SUB_BCLF = fourCC("BCLF"), // FO4 + SUB_BIDS = fourCC("BIDS"), SUB_BIPL = fourCC("BIPL"), // FO3 + SUB_BMCT = fourCC("BMCT"), + SUB_BMDT = fourCC("BMDT"), + SUB_BMMP = fourCC("BMMP"), // FO4 + SUB_BNAM = fourCC("BNAM"), + SUB_BOD2 = fourCC("BOD2"), + SUB_BODT = fourCC("BODT"), + SUB_BPND = fourCC("BPND"), + SUB_BPNI = fourCC("BPNI"), + SUB_BPNN = fourCC("BPNN"), + SUB_BPNT = fourCC("BPNT"), + SUB_BPTN = fourCC("BPTN"), + SUB_BRUS = fourCC("BRUS"), // FONV + SUB_BSIZ = fourCC("BSIZ"), // FO4 + SUB_BSMB = fourCC("BSMB"), // FO4 + SUB_BSMP = fourCC("BSMP"), // FO4 + SUB_BSMS = fourCC("BSMS"), // FO4 + SUB_BTXT = fourCC("BTXT"), + SUB_CDIX = fourCC("CDIX"), // FO4 + SUB_CIS1 = fourCC("CIS1"), // TES5 + SUB_CIS2 = fourCC("CIS2"), // TES5 + SUB_CITC = fourCC("CITC"), // TES5 + SUB_CLSZ = fourCC("CLSZ"), // FO4 + SUB_CNAM = fourCC("CNAM"), + SUB_CNTO = fourCC("CNTO"), + SUB_COCT = fourCC("COCT"), + SUB_COED = fourCC("COED"), + SUB_CRDT = fourCC("CRDT"), + SUB_CRGR = fourCC("CRGR"), // TES5 + SUB_CRIF = fourCC("CRIF"), + SUB_CRIS = fourCC("CRIS"), // FO4 + SUB_CRVA = fourCC("CRVA"), // TES5 + SUB_CS2D = fourCC("CS2D"), // FO4 + SUB_CS2E = fourCC("CS2E"), // FO4 + SUB_CS2F = fourCC("CS2F"), // FO4 + SUB_CS2H = fourCC("CS2H"), // FO4 + SUB_CS2K = fourCC("CS2K"), // FO4 + SUB_CSCR = fourCC("CSCR"), + SUB_CSCV = fourCC("CSCV"), // FO4 + SUB_CSDC = fourCC("CSDC"), + SUB_CSDI = fourCC("CSDI"), + SUB_CSDT = fourCC("CSDT"), + SUB_CSFL = fourCC("CSFL"), // TES5 + SUB_CSGD = fourCC("CSGD"), // TES5 + SUB_CSLR = fourCC("CSLR"), // TES5 + SUB_CSMD = fourCC("CSMD"), // TES5 + SUB_CSME = fourCC("CSME"), // TES5 + SUB_CSRA = fourCC("CSRA"), // FO4 + SUB_CTDA = fourCC("CTDA"), + SUB_CTDT = fourCC("CTDT"), + SUB_CUSD = fourCC("CUSD"), // FO4 + SUB_CVPA = fourCC("CVPA"), // FO4 + SUB_DALC = fourCC("DALC"), // FO3 + SUB_DAMA = fourCC("DAMA"), // FO4 + SUB_DAMC = fourCC("DAMC"), // FO4 + SUB_DAT2 = fourCC("DAT2"), // FONV + SUB_DATA = fourCC("DATA"), + SUB_DELE = fourCC("DELE"), + SUB_DEMO = fourCC("DEMO"), // TES5 + SUB_DESC = fourCC("DESC"), + SUB_DEST = fourCC("DEST"), + SUB_DEVA = fourCC("DEVA"), // TES5 + SUB_DFTF = fourCC("DFTF"), + SUB_DFTM = fourCC("DFTM"), + SUB_DMAX = fourCC("DMAX"), // TES5 + SUB_DMDC = fourCC("DMDC"), // FO4 + SUB_DMDL = fourCC("DMDL"), + SUB_DMDS = fourCC("DMDS"), + SUB_DMDT = fourCC("DMDT"), + SUB_DMIN = fourCC("DMIN"), // TES5 + SUB_DNAM = fourCC("DNAM"), + SUB_DODT = fourCC("DODT"), + SUB_DOFT = fourCC("DOFT"), + SUB_DPLT = fourCC("DPLT"), + SUB_DSTA = fourCC("DSTA"), // FO4 + SUB_DSTD = fourCC("DSTD"), + SUB_DSTF = fourCC("DSTF"), + SUB_DTGT = fourCC("DTGT"), // FO4 + SUB_DTID = fourCC("DTID"), // FO4 + SUB_EAMT = fourCC("EAMT"), + SUB_ECOR = fourCC("ECOR"), + SUB_EDID = fourCC("EDID"), + SUB_EFID = fourCC("EFID"), + SUB_EFIT = fourCC("EFIT"), + SUB_EFSD = fourCC("EFSD"), // FONV DeadMoney + SUB_EITM = fourCC("EITM"), + SUB_ENAM = fourCC("ENAM"), + SUB_ENIT = fourCC("ENIT"), + SUB_EPF2 = fourCC("EPF2"), + SUB_EPF3 = fourCC("EPF3"), + SUB_EPFB = fourCC("EPFB"), // FO4 + SUB_EPFD = fourCC("EPFD"), + SUB_EPFT = fourCC("EPFT"), + SUB_ESCE = fourCC("ESCE"), + SUB_ETYP = fourCC("ETYP"), + SUB_FCHT = fourCC("FCHT"), // TES5 + SUB_FCPL = fourCC("FCPL"), // FO4 + SUB_FFFF = fourCC("FFFF"), + SUB_FGGA = fourCC("FGGA"), + SUB_FGGS = fourCC("FGGS"), + SUB_FGTS = fourCC("FGTS"), + SUB_FIMD = fourCC("FIMD"), // FO4 + SUB_FLMV = fourCC("FLMV"), + SUB_FLTR = fourCC("FLTR"), // TES5 + SUB_FLTV = fourCC("FLTV"), + SUB_FMIN = fourCC("FMIN"), // FO4 + SUB_FMRI = fourCC("FMRI"), // FO4 + SUB_FMRN = fourCC("FMRN"), // FO4 + SUB_FMRS = fourCC("FMRS"), // FO4 + SUB_FNAM = fourCC("FNAM"), + SUB_FNMK = fourCC("FNMK"), + SUB_FNPR = fourCC("FNPR"), + SUB_FPRT = fourCC("FPRT"), // TES5 + SUB_FTSF = fourCC("FTSF"), + SUB_FTSM = fourCC("FTSM"), + SUB_FTST = fourCC("FTST"), + SUB_FTYP = fourCC("FTYP"), // FO4 + SUB_FULL = fourCC("FULL"), + SUB_FVPA = fourCC("FVPA"), // FO4 + SUB_GNAM = fourCC("GNAM"), + SUB_GREE = fourCC("GREE"), // FO4 + SUB_GWOR = fourCC("GWOR"), // TES5 + SUB_HCLF = fourCC("HCLF"), + SUB_HCLR = fourCC("HCLR"), + SUB_HEAD = fourCC("HEAD"), + SUB_HEDR = fourCC("HEDR"), + SUB_HLTX = fourCC("HLTX"), // FO4 + SUB_HNAM = fourCC("HNAM"), + SUB_HTID = fourCC("HTID"), // TES5 + SUB_ICO2 = fourCC("ICO2"), + SUB_ICON = fourCC("ICON"), + SUB_IDLA = fourCC("IDLA"), + SUB_IDLB = fourCC("IDLB"), // FO3 + SUB_IDLC = fourCC("IDLC"), + SUB_IDLF = fourCC("IDLF"), + SUB_IDLT = fourCC("IDLT"), + SUB_IMPF = fourCC("IMPF"), // FO3 Anchorage + SUB_IMPS = fourCC("IMPS"), // FO3 Anchorage + SUB_IMSP = fourCC("IMSP"), // TES5 + SUB_INAM = fourCC("INAM"), + SUB_INCC = fourCC("INCC"), + SUB_INDX = fourCC("INDX"), + SUB_INFC = fourCC("INFC"), // FONV + SUB_INFX = fourCC("INFX"), // FONV + SUB_INRD = fourCC("INRD"), // FO4 + SUB_INTT = fourCC("INTT"), // FO4 + SUB_INTV = fourCC("INTV"), + SUB_IOVR = fourCC("IOVR"), // FO4 + SUB_ISIZ = fourCC("ISIZ"), // FO4 + SUB_ITID = fourCC("ITID"), // FO4 + SUB_ITMC = fourCC("ITMC"), // FO4 + SUB_ITME = fourCC("ITME"), // FO4 + SUB_ITMS = fourCC("ITMS"), // FO4 + SUB_ITXT = fourCC("ITXT"), + SUB_JAIL = fourCC("JAIL"), // TES5 + SUB_JNAM = fourCC("JNAM"), // FONV + SUB_JOUT = fourCC("JOUT"), // TES5 + SUB_KFFZ = fourCC("KFFZ"), + SUB_KNAM = fourCC("KNAM"), + SUB_KSIZ = fourCC("KSIZ"), + SUB_KWDA = fourCC("KWDA"), + SUB_LCEC = fourCC("LCEC"), // TES5 + SUB_LCEP = fourCC("LCEP"), // TES5 + SUB_LCID = fourCC("LCID"), // TES5 + SUB_LCPR = fourCC("LCPR"), // TES5 + SUB_LCSR = fourCC("LCSR"), // TES5 + SUB_LCUN = fourCC("LCUN"), // TES5 + SUB_LFSD = fourCC("LFSD"), // FO4 + SUB_LFSP = fourCC("LFSP"), // FO4 + SUB_LLCT = fourCC("LLCT"), + SUB_LLKC = fourCC("LLKC"), // FO4 + SUB_LNAM = fourCC("LNAM"), + SUB_LTMP = fourCC("LTMP"), + SUB_LTPC = fourCC("LTPC"), // FO4 + SUB_LTPT = fourCC("LTPT"), // FO4 + SUB_LVLD = fourCC("LVLD"), + SUB_LVLF = fourCC("LVLF"), + SUB_LVLG = fourCC("LVLG"), // FO3 + SUB_LVLM = fourCC("LVLM"), // FO4 + SUB_LVLO = fourCC("LVLO"), + SUB_LVSG = fourCC("LVSG"), // FO4 + SUB_MASE = fourCC("MASE"), // FO4 + SUB_MAST = fourCC("MAST"), + SUB_MCHT = fourCC("MCHT"), // TES5 + SUB_MDOB = fourCC("MDOB"), + SUB_MHDT = fourCC("MHDT"), + SUB_MIC2 = fourCC("MIC2"), + SUB_MICO = fourCC("MICO"), + SUB_MLSI = fourCC("MLSI"), // FO4 + SUB_MMRK = fourCC("MMRK"), // FONV + SUB_MNAM = fourCC("MNAM"), + SUB_MO2B = fourCC("MO2B"), + SUB_MO2C = fourCC("MO2C"), // FO4 + SUB_MO2F = fourCC("MO2F"), // FO4 + SUB_MO2S = fourCC("MO2S"), + SUB_MO2T = fourCC("MO2T"), + SUB_MO3B = fourCC("MO3B"), + SUB_MO3C = fourCC("MO3C"), // FO4 + SUB_MO3F = fourCC("MO3F"), // FO4 + SUB_MO3S = fourCC("MO3S"), // FO3 + SUB_MO3T = fourCC("MO3T"), + SUB_MO4B = fourCC("MO4B"), + SUB_MO4C = fourCC("MO4C"), // FO4 + SUB_MO4F = fourCC("MO4F"), // FO4 + SUB_MO4S = fourCC("MO4S"), + SUB_MO4T = fourCC("MO4T"), + SUB_MO5C = fourCC("MO5C"), // FO4 + SUB_MO5F = fourCC("MO5F"), // FO4 + SUB_MO5S = fourCC("MO5S"), // TES5 + SUB_MO5T = fourCC("MO5T"), + SUB_MOD2 = fourCC("MOD2"), + SUB_MOD3 = fourCC("MOD3"), + SUB_MOD4 = fourCC("MOD4"), + SUB_MOD5 = fourCC("MOD5"), + SUB_MODB = fourCC("MODB"), + SUB_MODC = fourCC("MODC"), // FO4 SUB_MODD = fourCC("MODD"), // FO3 + SUB_MODF = fourCC("MODF"), // FO4 + SUB_MODL = fourCC("MODL"), + SUB_MODQ = fourCC("MODQ"), // FO4 + SUB_MODS = fourCC("MODS"), + SUB_MODT = fourCC("MODT"), SUB_MOSD = fourCC("MOSD"), // FO3 - SUB_MO3S = fourCC("MO3S"), // FO3 - SUB_XCET = fourCC("XCET"), // FO3 - SUB_LVLG = fourCC("LVLG"), // FO3 - SUB_NVCI = fourCC("NVCI"), // FO3 - SUB_NVVX = fourCC("NVVX"), // FO3 - SUB_NVTR = fourCC("NVTR"), // FO3 + SUB_MPAI = fourCC("MPAI"), + SUB_MPAV = fourCC("MPAV"), + SUB_MPCD = fourCC("MPCD"), // FO4 + SUB_MPGN = fourCC("MPGN"), // FO4 + SUB_MPGS = fourCC("MPGS"), // FO4 + SUB_MPPC = fourCC("MPPC"), // FO4 + SUB_MPPF = fourCC("MPPF"), // FO4 + SUB_MPPI = fourCC("MPPI"), // FO4 + SUB_MPPK = fourCC("MPPK"), // FO4 + SUB_MPPM = fourCC("MPPM"), // FO4 + SUB_MPPN = fourCC("MPPN"), // FO4 + SUB_MPPT = fourCC("MPPT"), // FO4 + SUB_MPRT = fourCC("MPRT"), // TES5 + SUB_MRSV = fourCC("MRSV"), // FO4 + SUB_MSDK = fourCC("MSDK"), // FO4 + SUB_MSDV = fourCC("MSDV"), // FO4 + SUB_MSID = fourCC("MSID"), // FO4 + SUB_MSM0 = fourCC("MSM0"), // FO4 + SUB_MSM1 = fourCC("MSM1"), // FO4 + SUB_MTNM = fourCC("MTNM"), + SUB_MTYP = fourCC("MTYP"), + SUB_MWD1 = fourCC("MWD1"), // FONV + SUB_MWD2 = fourCC("MWD2"), // FONV + SUB_MWD3 = fourCC("MWD3"), // FONV + SUB_MWD4 = fourCC("MWD4"), // FONV + SUB_MWD5 = fourCC("MWD5"), // FONV + SUB_MWD6 = fourCC("MWD6"), // FONV + SUB_MWD7 = fourCC("MWD7"), // FONV + SUB_MWGT = fourCC("MWGT"), // FO4 + SUB_NAM0 = fourCC("NAM0"), + SUB_NAM1 = fourCC("NAM1"), + SUB_NAM2 = fourCC("NAM2"), + SUB_NAM3 = fourCC("NAM3"), + SUB_NAM4 = fourCC("NAM4"), + SUB_NAM5 = fourCC("NAM5"), + SUB_NAM6 = fourCC("NAM6"), + SUB_NAM7 = fourCC("NAM7"), + SUB_NAM8 = fourCC("NAM8"), + SUB_NAM9 = fourCC("NAM9"), + SUB_NAMA = fourCC("NAMA"), + SUB_NAME = fourCC("NAME"), + SUB_NETO = fourCC("NETO"), // FO4 + SUB_NEXT = fourCC("NEXT"), // FO3 + SUB_NIFT = fourCC("NIFT"), + SUB_NIFZ = fourCC("NIFZ"), + SUB_NNAM = fourCC("NNAM"), + SUB_NNGS = fourCC("NNGS"), // FO4 + SUB_NNGT = fourCC("NNGT"), // FO4 + SUB_NNUS = fourCC("NNUS"), // FO4 + SUB_NNUT = fourCC("NNUT"), // FO4 + SUB_NONE = fourCC("NONE"), // FO4 + SUB_NPOS = fourCC("NPOS"), // FO4 + SUB_NPOT = fourCC("NPOT"), // FO4 + SUB_NQUS = fourCC("NQUS"), // FO4 + SUB_NQUT = fourCC("NQUT"), // FO4 + SUB_NTOP = fourCC("NTOP"), // FO4 + SUB_NTRM = fourCC("NTRM"), // FO4 + SUB_NULL = fourCC("NULL"), SUB_NVCA = fourCC("NVCA"), // FO3 + SUB_NVCI = fourCC("NVCI"), // FO3 SUB_NVDP = fourCC("NVDP"), // FO3 - SUB_NVGD = fourCC("NVGD"), // FO3 + SUB_NVER = fourCC("NVER"), SUB_NVEX = fourCC("NVEX"), // FO3 - SUB_XHLP = fourCC("XHLP"), // FO3 - SUB_XRDO = fourCC("XRDO"), // FO3 - SUB_XAMT = fourCC("XAMT"), // FO3 - SUB_XAMC = fourCC("XAMC"), // FO3 - SUB_XRAD = fourCC("XRAD"), // FO3 - SUB_XORD = fourCC("XORD"), // FO3 - SUB_XCLP = fourCC("XCLP"), // FO3 - SUB_NEXT = fourCC("NEXT"), // FO3 - SUB_QOBJ = fourCC("QOBJ"), // FO3 - SUB_POBA = fourCC("POBA"), // FO3 - SUB_POCA = fourCC("POCA"), // FO3 - SUB_POEA = fourCC("POEA"), // FO3 - SUB_PKDD = fourCC("PKDD"), // FO3 + SUB_NVGD = fourCC("NVGD"), // FO3 + SUB_NVMI = fourCC("NVMI"), + SUB_NVNM = fourCC("NVNM"), + SUB_NVPP = fourCC("NVPP"), + SUB_NVSI = fourCC("NVSI"), + SUB_NVTR = fourCC("NVTR"), // FO3 + SUB_NVVX = fourCC("NVVX"), // FO3 + SUB_OBND = fourCC("OBND"), + SUB_OBTE = fourCC("OBTE"), // FO4 + SUB_OBTF = fourCC("OBTF"), // FO4 + SUB_OBTS = fourCC("OBTS"), // FO4 + SUB_OCOR = fourCC("OCOR"), // TES5 + SUB_OFST = fourCC("OFST"), // TES4 only? + SUB_ONAM = fourCC("ONAM"), + SUB_PCMB = fourCC("PCMB"), // FO4 + SUB_PDTO = fourCC("PDTO"), + SUB_PFIG = fourCC("PFIG"), + SUB_PFO2 = fourCC("PFO2"), // TES5 + SUB_PFOR = fourCC("PFOR"), // TES5 + SUB_PFPC = fourCC("PFPC"), + SUB_PFRN = fourCC("PFRN"), // FO4 + SUB_PGAG = fourCC("PGAG"), + SUB_PGRI = fourCC("PGRI"), + SUB_PGRL = fourCC("PGRL"), + SUB_PGRP = fourCC("PGRP"), + SUB_PGRR = fourCC("PGRR"), + SUB_PHTN = fourCC("PHTN"), + SUB_PHWT = fourCC("PHWT"), + SUB_PKAM = fourCC("PKAM"), // FO3 + SUB_PKC2 = fourCC("PKC2"), // TES5 + SUB_PKCU = fourCC("PKCU"), // TES5 SUB_PKD2 = fourCC("PKD2"), // FO3 - SUB_PKPT = fourCC("PKPT"), // FO3 - SUB_PKED = fourCC("PKED"), // FO3 + SUB_PKDD = fourCC("PKDD"), // FO3 + SUB_PKDT = fourCC("PKDT"), SUB_PKE2 = fourCC("PKE2"), // FO3 - SUB_PKAM = fourCC("PKAM"), // FO3 - SUB_PUID = fourCC("PUID"), // FO3 + SUB_PKED = fourCC("PKED"), // FO3 + SUB_PKFD = fourCC("PKFD"), // FO3 + SUB_PKID = fourCC("PKID"), + SUB_PKPT = fourCC("PKPT"), // FO3 SUB_PKW3 = fourCC("PKW3"), // FO3 - SUB_PTD2 = fourCC("PTD2"), // FO3 + SUB_PLCN = fourCC("PLCN"), // TES5 SUB_PLD2 = fourCC("PLD2"), // FO3 - SUB_PKFD = fourCC("PKFD"), // FO3 - SUB_IDLB = fourCC("IDLB"), // FO3 - SUB_XDCR = fourCC("XDCR"), // FO3 - SUB_DALC = fourCC("DALC"), // FO3 - SUB_IMPS = fourCC("IMPS"), // FO3 Anchorage - SUB_IMPF = fourCC("IMPF"), // FO3 Anchorage - - SUB_XATO = fourCC("XATO"), // FONV - SUB_INFC = fourCC("INFC"), // FONV - SUB_INFX = fourCC("INFX"), // FONV - SUB_TDUM = fourCC("TDUM"), // FONV - SUB_TCFU = fourCC("TCFU"), // FONV - SUB_DAT2 = fourCC("DAT2"), // FONV + SUB_PLDT = fourCC("PLDT"), + SUB_PLVD = fourCC("PLVD"), // TES5 + SUB_PNAM = fourCC("PNAM"), + SUB_POBA = fourCC("POBA"), // FO3 + SUB_POCA = fourCC("POCA"), // FO3 + SUB_POEA = fourCC("POEA"), // FO3 + SUB_PRCB = fourCC("PRCB"), // TES5 + SUB_PRKC = fourCC("PRKC"), + SUB_PRKE = fourCC("PRKE"), + SUB_PRKF = fourCC("PRKF"), + SUB_PRKR = fourCC("PRKR"), + SUB_PRKZ = fourCC("PRKZ"), + SUB_PRPS = fourCC("PRPS"), // FO4 + SUB_PSDT = fourCC("PSDT"), + SUB_PTD2 = fourCC("PTD2"), // FO3 + SUB_PTDA = fourCC("PTDA"), // TES5 + SUB_PTDT = fourCC("PTDT"), + SUB_PTOP = fourCC("PTOP"), // FO4 + SUB_PTRN = fourCC("PTRN"), // FO4 + SUB_PUID = fourCC("PUID"), // FO3 + SUB_QNAM = fourCC("QNAM"), + SUB_QOBJ = fourCC("QOBJ"), // FO3 + SUB_QSDT = fourCC("QSDT"), + SUB_QSTA = fourCC("QSTA"), + SUB_QSTI = fourCC("QSTI"), + SUB_QSTR = fourCC("QSTR"), + SUB_QTGL = fourCC("QTGL"), // TES5 + SUB_QTOP = fourCC("QTOP"), // FO4 + SUB_QUAL = fourCC("QUAL"), + SUB_RADR = fourCC("RADR"), // FO4 + SUB_RAGA = fourCC("RAGA"), + SUB_RBPC = fourCC("RBPC"), // FO4 + SUB_RCEC = fourCC("RCEC"), // TES5 SUB_RCIL = fourCC("RCIL"), // FONV - SUB_MMRK = fourCC("MMRK"), // FONV - SUB_SCRV = fourCC("SCRV"), // FONV - SUB_SCVR = fourCC("SCVR"), // FONV - SUB_SLSD = fourCC("SLSD"), // FONV - SUB_XSRF = fourCC("XSRF"), // FONV - SUB_XSRD = fourCC("XSRD"), // FONV - SUB_WMI1 = fourCC("WMI1"), // FONV + SUB_RCLR = fourCC("RCLR"), + SUB_RCPR = fourCC("RCPR"), // TES5 Dawnguard + SUB_RCSR = fourCC("RCSR"), // TES5 + SUB_RCUN = fourCC("RCUN"), // TES5 + SUB_RDAT = fourCC("RDAT"), + SUB_RDGS = fourCC("RDGS"), SUB_RDID = fourCC("RDID"), // FONV + SUB_RDMD = fourCC("RDMD"), // TES4 only? + SUB_RDMO = fourCC("RDMO"), + SUB_RDMP = fourCC("RDMP"), + SUB_RDOT = fourCC("RDOT"), + SUB_RDSA = fourCC("RDSA"), SUB_RDSB = fourCC("RDSB"), // FONV + SUB_RDSD = fourCC("RDSD"), // TES4 only? SUB_RDSI = fourCC("RDSI"), // FONV - SUB_BRUS = fourCC("BRUS"), // FONV - SUB_VATS = fourCC("VATS"), // FONV + SUB_RDWT = fourCC("RDWT"), + SUB_REPL = fourCC("REPL"), // FO3 + SUB_REPT = fourCC("REPT"), // FO4 + SUB_RLDM = fourCC("RLDM"), // FO4 + SUB_RNAM = fourCC("RNAM"), + SUB_RNMV = fourCC("RNMV"), + SUB_RPLD = fourCC("RPLD"), + SUB_RPLI = fourCC("RPLI"), + SUB_RPRF = fourCC("RPRF"), + SUB_RPRM = fourCC("RPRM"), + SUB_RVIS = fourCC("RVIS"), // FO4 + SUB_SADD = fourCC("SADD"), // FO4 + SUB_SAKD = fourCC("SAKD"), // FO4 + SUB_SAPT = fourCC("SAPT"), // FO4 + SUB_SCDA = fourCC("SCDA"), + SUB_SCHD = fourCC("SCHD"), + SUB_SCHR = fourCC("SCHR"), + SUB_SCIT = fourCC("SCIT"), + SUB_SCQS = fourCC("SCQS"), // FO4 + SUB_SCRI = fourCC("SCRI"), + SUB_SCRN = fourCC("SCRN"), + SUB_SCRO = fourCC("SCRO"), + SUB_SCRV = fourCC("SCRV"), // FONV + SUB_SCTX = fourCC("SCTX"), + SUB_SCVR = fourCC("SCVR"), // FONV + SUB_SDSC = fourCC("SDSC"), + SUB_SGNM = fourCC("SGNM"), // FO4 + SUB_SHRT = fourCC("SHRT"), + SUB_SLCP = fourCC("SLCP"), + SUB_SLSD = fourCC("SLSD"), // FONV + SUB_SNAM = fourCC("SNAM"), + SUB_SNDD = fourCC("SNDD"), + SUB_SNDX = fourCC("SNDX"), + SUB_SNMV = fourCC("SNMV"), + SUB_SOFT = fourCC("SOFT"), + SUB_SOUL = fourCC("SOUL"), + SUB_SPCT = fourCC("SPCT"), + SUB_SPED = fourCC("SPED"), + SUB_SPIT = fourCC("SPIT"), + SUB_SPLO = fourCC("SPLO"), + SUB_SPMV = fourCC("SPMV"), // TES5 + SUB_SPOR = fourCC("SPOR"), + SUB_SRAC = fourCC("SRAC"), // FO4 + SUB_SRAF = fourCC("SRAF"), // FO4 + SUB_SSPN = fourCC("SSPN"), // FO4 + SUB_STCP = fourCC("STCP"), // FO4 + SUB_STKD = fourCC("STKD"), // FO4 + SUB_STOL = fourCC("STOL"), // TES5 + SUB_STOP = fourCC("STOP"), // FO4 + SUB_STSC = fourCC("STSC"), // FO4 + SUB_SWMV = fourCC("SWMV"), + SUB_TCFU = fourCC("TCFU"), // FONV + SUB_TCLF = fourCC("TCLF"), + SUB_TCLT = fourCC("TCLT"), + SUB_TDUM = fourCC("TDUM"), // FONV + SUB_TEND = fourCC("TEND"), // FO4 + SUB_TETI = fourCC("TETI"), // FO4 + SUB_TIAS = fourCC("TIAS"), + SUB_TIFC = fourCC("TIFC"), // TES5 + SUB_TINC = fourCC("TINC"), + SUB_TIND = fourCC("TIND"), + SUB_TINI = fourCC("TINI"), + SUB_TINL = fourCC("TINL"), + SUB_TINP = fourCC("TINP"), + SUB_TINT = fourCC("TINT"), + SUB_TINV = fourCC("TINV"), + SUB_TIQS = fourCC("TIQS"), // FO4 + SUB_TIRS = fourCC("TIRS"), + SUB_TNAM = fourCC("TNAM"), + SUB_TPIC = fourCC("TPIC"), + SUB_TPLT = fourCC("TPLT"), + SUB_TPTA = fourCC("TPTA"), // FO4 + SUB_TRDA = fourCC("TRDA"), // FO4 + SUB_TRDT = fourCC("TRDT"), + SUB_TSCE = fourCC("TSCE"), // FO4 + SUB_TTEB = fourCC("TTEB"), // FO4 + SUB_TTEC = fourCC("TTEC"), // FO4 + SUB_TTED = fourCC("TTED"), // FO4 + SUB_TTEF = fourCC("TTEF"), // FO4 + SUB_TTET = fourCC("TTET"), // FO4 + SUB_TTGE = fourCC("TTGE"), // FO4 + SUB_TTGP = fourCC("TTGP"), // FO4 + SUB_TVDT = fourCC("TVDT"), + SUB_TWAT = fourCC("TWAT"), // TES5 + SUB_TX00 = fourCC("TX00"), + SUB_TX01 = fourCC("TX01"), + SUB_TX02 = fourCC("TX02"), + SUB_TX03 = fourCC("TX03"), + SUB_TX04 = fourCC("TX04"), + SUB_TX05 = fourCC("TX05"), + SUB_TX06 = fourCC("TX06"), + SUB_TX07 = fourCC("TX07"), + SUB_UNAM = fourCC("UNAM"), + SUB_UNES = fourCC("UNES"), + SUB_UNWP = fourCC("UNWP"), // FO4 SUB_VANM = fourCC("VANM"), // FONV - SUB_MWD1 = fourCC("MWD1"), // FONV - SUB_MWD2 = fourCC("MWD2"), // FONV - SUB_MWD3 = fourCC("MWD3"), // FONV - SUB_MWD4 = fourCC("MWD4"), // FONV - SUB_MWD5 = fourCC("MWD5"), // FONV - SUB_MWD6 = fourCC("MWD6"), // FONV - SUB_MWD7 = fourCC("MWD7"), // FONV + SUB_VATS = fourCC("VATS"), // FONV + SUB_VCLR = fourCC("VCLR"), + SUB_VENC = fourCC("VENC"), // TES5 + SUB_VEND = fourCC("VEND"), // TES5 + SUB_VENV = fourCC("VENV"), // TES5 + SUB_VHGT = fourCC("VHGT"), + SUB_VISI = fourCC("VISI"), // FO4 + SUB_VMAD = fourCC("VMAD"), + SUB_VNAM = fourCC("VNAM"), + SUB_VNML = fourCC("VNML"), + SUB_VTCK = fourCC("VTCK"), + SUB_VTEX = fourCC("VTEX"), + SUB_VTXT = fourCC("VTXT"), + SUB_WAIT = fourCC("WAIT"), // TES5 + SUB_WAMD = fourCC("WAMD"), // FO4 + SUB_WBDT = fourCC("WBDT"), + SUB_WCTR = fourCC("WCTR"), + SUB_WGDR = fourCC("WGDR"), // FO4 + SUB_WKMV = fourCC("WKMV"), + SUB_WLEV = fourCC("WLEV"), // FO4 + SUB_WLST = fourCC("WLST"), + SUB_WMAP = fourCC("WMAP"), // FO4 + SUB_WMI1 = fourCC("WMI1"), // FONV SUB_WMI2 = fourCC("WMI2"), // FONV SUB_WMI3 = fourCC("WMI3"), // FONV SUB_WMS1 = fourCC("WMS1"), // FONV SUB_WMS2 = fourCC("WMS2"), // FONV + SUB_WNAM = fourCC("WNAM"), SUB_WNM1 = fourCC("WNM1"), // FONV SUB_WNM2 = fourCC("WNM2"), // FONV SUB_WNM3 = fourCC("WNM3"), // FONV @@ -655,62 +744,117 @@ namespace ESM4 SUB_WNM5 = fourCC("WNM5"), // FONV SUB_WNM6 = fourCC("WNM6"), // FONV SUB_WNM7 = fourCC("WNM7"), // FONV - SUB_JNAM = fourCC("JNAM"), // FONV - SUB_EFSD = fourCC("EFSD"), // FONV DeadMoney - - // Introduced in FO4 - SUB_APPR = fourCC("APPR"), - SUB_ATKS = fourCC("ATKS"), - SUB_ATKT = fourCC("ATKT"), - SUB_ATKW = fourCC("ATKW"), - SUB_ATTX = fourCC("ATTX"), - SUB_BMMP = fourCC("BMMP"), - SUB_BSMB = fourCC("BSMB"), - SUB_BSMP = fourCC("BSMP"), - SUB_BSMS = fourCC("BSMS"), - SUB_FMRI = fourCC("FMRI"), - SUB_FMRN = fourCC("FMRN"), - SUB_FTYP = fourCC("FTYP"), - SUB_HLTX = fourCC("HLTX"), - SUB_MLSI = fourCC("MLSI"), - SUB_MPGN = fourCC("MPGN"), - SUB_MPGS = fourCC("MPGS"), - SUB_MPPC = fourCC("MPPC"), - SUB_MPPF = fourCC("MPPF"), - SUB_MPPI = fourCC("MPPI"), - SUB_MPPK = fourCC("MPPK"), - SUB_MPPM = fourCC("MPPM"), - SUB_MPPN = fourCC("MPPN"), - SUB_MPPT = fourCC("MPPT"), - SUB_MSID = fourCC("MSID"), - SUB_MSM0 = fourCC("MSM0"), - SUB_MSM1 = fourCC("MSM1"), - SUB_NTOP = fourCC("NTOP"), - SUB_NTRM = fourCC("NTRM"), - SUB_PRPS = fourCC("PRPS"), - SUB_PTOP = fourCC("PTOP"), - SUB_PTRN = fourCC("PTRN"), - SUB_RADR = fourCC("RADR"), - SUB_RBPC = fourCC("RBPC"), - SUB_REPT = fourCC("REPT"), - SUB_SADD = fourCC("SADD"), - SUB_SAKD = fourCC("SAKD"), - SUB_SAPT = fourCC("SAPT"), - SUB_SGNM = fourCC("SGNM"), - SUB_SRAC = fourCC("SRAC"), - SUB_SRAF = fourCC("SRAF"), - SUB_STCP = fourCC("STCP"), - SUB_STKD = fourCC("STKD"), - SUB_TETI = fourCC("TETI"), - SUB_TTEB = fourCC("TTEB"), - SUB_TTEC = fourCC("TTEC"), - SUB_TTED = fourCC("TTED"), - SUB_TTEF = fourCC("TTEF"), - SUB_TTET = fourCC("TTET"), - SUB_TTGE = fourCC("TTGE"), - SUB_TTGP = fourCC("TTGP"), - SUB_UNWP = fourCC("UNWP"), - SUB_WMAP = fourCC("WMAP"), + SUB_WZMD = fourCC("WZMD"), // FO4 + SUB_XACT = fourCC("XACT"), + SUB_XALP = fourCC("XALP"), + SUB_XAMC = fourCC("XAMC"), // FO3 + SUB_XAMT = fourCC("XAMT"), // FO3 + SUB_XAPD = fourCC("XAPD"), + SUB_XAPR = fourCC("XAPR"), + SUB_XASP = fourCC("XASP"), // FO4 + SUB_XATO = fourCC("XATO"), // FONV + SUB_XATP = fourCC("XATP"), // FO4 + SUB_XATR = fourCC("XATR"), + SUB_XBSD = fourCC("XBSD"), // FO4 + SUB_XCAS = fourCC("XCAS"), + SUB_XCCM = fourCC("XCCM"), + SUB_XCCP = fourCC("XCCP"), + SUB_XCET = fourCC("XCET"), // FO3 + SUB_XCGD = fourCC("XCGD"), + SUB_XCHG = fourCC("XCHG"), // thievery.exp + SUB_XCIM = fourCC("XCIM"), + SUB_XCLC = fourCC("XCLC"), + SUB_XCLL = fourCC("XCLL"), + SUB_XCLP = fourCC("XCLP"), // FO3 + SUB_XCLR = fourCC("XCLR"), + SUB_XCLW = fourCC("XCLW"), + SUB_XCMO = fourCC("XCMO"), + SUB_XCMT = fourCC("XCMT"), // TES4 only? + SUB_XCNT = fourCC("XCNT"), + SUB_XCRI = fourCC("XCRI"), // FO4 + SUB_XCVL = fourCC("XCVL"), + SUB_XCVR = fourCC("XCVR"), + SUB_XCWT = fourCC("XCWT"), + SUB_XCZA = fourCC("XCZA"), + SUB_XCZC = fourCC("XCZC"), + SUB_XCZR = fourCC("XCZR"), // TES5 + SUB_XDCR = fourCC("XDCR"), // FO3 + SUB_XEMI = fourCC("XEMI"), + SUB_XESP = fourCC("XESP"), + SUB_XEZN = fourCC("XEZN"), + SUB_XFVC = fourCC("XFVC"), + SUB_XGDR = fourCC("XGDR"), // FO4 + SUB_XGLB = fourCC("XGLB"), + SUB_XHLP = fourCC("XHLP"), // FO3 + SUB_XHLT = fourCC("XHLT"), // Unofficial Oblivion Patch + SUB_XHOR = fourCC("XHOR"), + SUB_XHRS = fourCC("XHRS"), + SUB_XHTW = fourCC("XHTW"), + SUB_XIBS = fourCC("XIBS"), // FO3 + SUB_XILL = fourCC("XILL"), + SUB_XILW = fourCC("XILW"), // FO4 + SUB_XIS2 = fourCC("XIS2"), + SUB_XLCM = fourCC("XLCM"), + SUB_XLCN = fourCC("XLCN"), + SUB_XLIB = fourCC("XLIB"), + SUB_XLIG = fourCC("XLIG"), + SUB_XLKR = fourCC("XLKR"), + SUB_XLKT = fourCC("XLKT"), // FO4 + SUB_XLOC = fourCC("XLOC"), + SUB_XLOD = fourCC("XLOD"), + SUB_XLRL = fourCC("XLRL"), + SUB_XLRM = fourCC("XLRM"), + SUB_XLRT = fourCC("XLRT"), + SUB_XLTW = fourCC("XLTW"), + SUB_XLYR = fourCC("XLYR"), // FO4 + SUB_XMBO = fourCC("XMBO"), + SUB_XMBP = fourCC("XMBP"), + SUB_XMBR = fourCC("XMBR"), + SUB_XMRC = fourCC("XMRC"), + SUB_XMRK = fourCC("XMRK"), + SUB_XMSP = fourCC("XMSP"), // FO4 + SUB_XNAM = fourCC("XNAM"), + SUB_XNDP = fourCC("XNDP"), + SUB_XOCP = fourCC("XOCP"), + SUB_XORD = fourCC("XORD"), // FO3 + SUB_XOWN = fourCC("XOWN"), + SUB_XPCI = fourCC("XPCI"), + SUB_XPDD = fourCC("XPDD"), // FO4 + SUB_XPLK = fourCC("XPLK"), // FO4 + SUB_XPOD = fourCC("XPOD"), + SUB_XPPA = fourCC("XPPA"), + SUB_XPRD = fourCC("XPRD"), + SUB_XPRI = fourCC("XPRI"), // FO4 + SUB_XPRM = fourCC("XPRM"), + SUB_XPTL = fourCC("XPTL"), + SUB_XPWR = fourCC("XPWR"), + SUB_XRAD = fourCC("XRAD"), // FO3 + SUB_XRDO = fourCC("XRDO"), // FO3 + SUB_XRDS = fourCC("XRDS"), + SUB_XRFG = fourCC("XRFG"), // FO4 + SUB_XRGB = fourCC("XRGB"), + SUB_XRGD = fourCC("XRGD"), + SUB_XRMR = fourCC("XRMR"), + SUB_XRNK = fourCC("XRNK"), // TES4 only? + SUB_XRTM = fourCC("XRTM"), + SUB_XSCL = fourCC("XSCL"), + SUB_XSED = fourCC("XSED"), + SUB_XSPC = fourCC("XSPC"), + SUB_XSRD = fourCC("XSRD"), // FONV + SUB_XSRF = fourCC("XSRF"), // FONV + SUB_XTEL = fourCC("XTEL"), + SUB_XTNM = fourCC("XTNM"), + SUB_XTRG = fourCC("XTRG"), + SUB_XTRI = fourCC("XTRI"), + SUB_XWCN = fourCC("XWCN"), + SUB_XWCS = fourCC("XWCS"), + SUB_XWCU = fourCC("XWCU"), + SUB_XWEM = fourCC("XWEM"), + SUB_XWPG = fourCC("XWPG"), // FO4 + SUB_XWPN = fourCC("XWPN"), // FO4 + SUB_XXXX = fourCC("XXXX"), + SUB_YNAM = fourCC("YNAM"), + SUB_ZNAM = fourCC("ZNAM"), }; // Based on http://www.uesp.net/wiki/Tes5Mod:Mod_File_Format#Records diff --git a/components/esm4/loadland.cpp b/components/esm4/loadland.cpp index c448c29b29..d7adfb75a2 100644 --- a/components/esm4/loadland.cpp +++ b/components/esm4/loadland.cpp @@ -94,7 +94,7 @@ void ESM4::Land::load(ESM4::Reader& reader) mDataTypes |= LAND_VCLR; break; } - case ESM4::SUA_BTXT: + case ESM4::SUB_BTXT: { BTXT base; if (reader.getExact(base)) From 271c14030a36ee95ae98b706d52cb87d1cfd1a52 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 16 Aug 2023 04:06:50 +0300 Subject: [PATCH 17/64] Maybe load FO4 ingestible records --- components/esm4/loadalch.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/components/esm4/loadalch.cpp b/components/esm4/loadalch.cpp index 35f6964b24..297a503ea1 100644 --- a/components/esm4/loadalch.cpp +++ b/components/esm4/loadalch.cpp @@ -97,6 +97,21 @@ void ESM4::Potion::load(ESM4::Reader& reader) case ESM4::SUB_MODS: case ESM4::SUB_OBND: case ESM4::SUB_ETYP: // FO3 + case ESM4::SUB_DESC: + // Destructible + case ESM4::SUB_DAMC: + case ESM4::SUB_DEST: + case ESM4::SUB_DMDC: + case ESM4::SUB_DMDL: + case ESM4::SUB_DMDT: + case ESM4::SUB_DMDS: + case ESM4::SUB_DSTA: + case ESM4::SUB_DSTD: + case ESM4::SUB_DSTF: + // FO4 + case ESM4::SUB_DNAM: + case ESM4::SUB_PTRN: + case ESM4::SUB_CUSD: reader.skipSubRecordData(); break; default: From 3118800dbd6b15985dff9fcc89e4db64cc6eebd8 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 16 Aug 2023 04:26:08 +0300 Subject: [PATCH 18/64] Skip ESM4 destructible data for all relevant records --- components/esm4/loadacti.cpp | 7 +++++-- components/esm4/loadalch.cpp | 5 ++--- components/esm4/loadammo.cpp | 9 +++++++++ components/esm4/loadarmo.cpp | 9 +++++++++ components/esm4/loadbook.cpp | 9 +++++++++ components/esm4/loadcont.cpp | 14 +++++++++----- components/esm4/loaddoor.cpp | 14 +++++++++----- components/esm4/loadflor.cpp | 9 +++++++++ components/esm4/loadfurn.cpp | 8 +++++++- components/esm4/loadingr.cpp | 9 +++++++++ components/esm4/loadkeym.cpp | 9 +++++++++ components/esm4/loadligh.cpp | 9 ++++++--- components/esm4/loadmisc.cpp | 9 ++++++--- components/esm4/loadmstt.cpp | 12 ++++++++---- components/esm4/loadnpc.cpp | 32 +++++++------------------------- components/esm4/loadtact.cpp | 12 +++++++++--- components/esm4/loadweap.cpp | 14 +++++++++----- 17 files changed, 131 insertions(+), 59 deletions(-) diff --git a/components/esm4/loadacti.cpp b/components/esm4/loadacti.cpp index 91336a5bee..d09a96417a 100644 --- a/components/esm4/loadacti.cpp +++ b/components/esm4/loadacti.cpp @@ -73,12 +73,15 @@ void ESM4::Activator::load(ESM4::Reader& reader) break; // FONV case ESM4::SUB_MODT: case ESM4::SUB_MODS: + case ESM4::SUB_DAMC: // Destructible case ESM4::SUB_DEST: + case ESM4::SUB_DMDC: case ESM4::SUB_DMDL: - case ESM4::SUB_DMDS: case ESM4::SUB_DMDT: + case ESM4::SUB_DMDS: + case ESM4::SUB_DSTA: case ESM4::SUB_DSTD: - case ESM4::SUB_DSTF: + case ESM4::SUB_DSTF: // Destructible end case ESM4::SUB_FNAM: case ESM4::SUB_KNAM: case ESM4::SUB_KSIZ: diff --git a/components/esm4/loadalch.cpp b/components/esm4/loadalch.cpp index 297a503ea1..ab9bf2b1a6 100644 --- a/components/esm4/loadalch.cpp +++ b/components/esm4/loadalch.cpp @@ -98,8 +98,7 @@ void ESM4::Potion::load(ESM4::Reader& reader) case ESM4::SUB_OBND: case ESM4::SUB_ETYP: // FO3 case ESM4::SUB_DESC: - // Destructible - case ESM4::SUB_DAMC: + case ESM4::SUB_DAMC: // Destructible case ESM4::SUB_DEST: case ESM4::SUB_DMDC: case ESM4::SUB_DMDL: @@ -107,7 +106,7 @@ void ESM4::Potion::load(ESM4::Reader& reader) case ESM4::SUB_DMDS: case ESM4::SUB_DSTA: case ESM4::SUB_DSTD: - case ESM4::SUB_DSTF: + case ESM4::SUB_DSTF: // Destructible end // FO4 case ESM4::SUB_DNAM: case ESM4::SUB_PTRN: diff --git a/components/esm4/loadammo.cpp b/components/esm4/loadammo.cpp index 8dab2ba74c..78a022189a 100644 --- a/components/esm4/loadammo.cpp +++ b/components/esm4/loadammo.cpp @@ -137,6 +137,15 @@ void ESM4::Ammunition::load(ESM4::Reader& reader) case ESM4::SUB_OBND: case ESM4::SUB_KSIZ: case ESM4::SUB_KWDA: + case ESM4::SUB_DAMC: // Destructible + case ESM4::SUB_DEST: + case ESM4::SUB_DMDC: + case ESM4::SUB_DMDL: + case ESM4::SUB_DMDT: + case ESM4::SUB_DMDS: + case ESM4::SUB_DSTA: + case ESM4::SUB_DSTD: + case ESM4::SUB_DSTF: // Destructible end reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadarmo.cpp b/components/esm4/loadarmo.cpp index b2b90f2eb1..ac21852411 100644 --- a/components/esm4/loadarmo.cpp +++ b/components/esm4/loadarmo.cpp @@ -191,6 +191,15 @@ void ESM4::Armor::load(ESM4::Reader& reader) case ESM4::SUB_MO3S: // FO3 case ESM4::SUB_BNAM: // FONV case ESM4::SUB_SNAM: // FONV + case ESM4::SUB_DAMC: // Destructible + case ESM4::SUB_DEST: + case ESM4::SUB_DMDC: + case ESM4::SUB_DMDL: + case ESM4::SUB_DMDT: + case ESM4::SUB_DMDS: + case ESM4::SUB_DSTA: + case ESM4::SUB_DSTD: + case ESM4::SUB_DSTF: // Destructible end reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadbook.cpp b/components/esm4/loadbook.cpp index df8697a608..64cacfe81d 100644 --- a/components/esm4/loadbook.cpp +++ b/components/esm4/loadbook.cpp @@ -102,6 +102,15 @@ void ESM4::Book::load(ESM4::Reader& reader) case ESM4::SUB_CNAM: case ESM4::SUB_INAM: case ESM4::SUB_VMAD: + case ESM4::SUB_DAMC: // Destructible + case ESM4::SUB_DEST: + case ESM4::SUB_DMDC: + case ESM4::SUB_DMDL: + case ESM4::SUB_DMDT: + case ESM4::SUB_DMDS: + case ESM4::SUB_DSTA: + case ESM4::SUB_DSTD: + case ESM4::SUB_DSTF: // Destructible end reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadcont.cpp b/components/esm4/loadcont.cpp index 66219f2fae..cd1aa45229 100644 --- a/components/esm4/loadcont.cpp +++ b/components/esm4/loadcont.cpp @@ -80,11 +80,15 @@ void ESM4::Container::load(ESM4::Reader& reader) case ESM4::SUB_OBND: // TES5 only case ESM4::SUB_COCT: // TES5 only case ESM4::SUB_COED: // TES5 only - case ESM4::SUB_DEST: // FONV - case ESM4::SUB_DSTD: // FONV - case ESM4::SUB_DSTF: // FONV - case ESM4::SUB_DMDL: // FONV - case ESM4::SUB_DMDT: // FONV + case ESM4::SUB_DAMC: // Destructible + case ESM4::SUB_DEST: + case ESM4::SUB_DMDC: + case ESM4::SUB_DMDL: + case ESM4::SUB_DMDT: + case ESM4::SUB_DMDS: + case ESM4::SUB_DSTA: + case ESM4::SUB_DSTD: + case ESM4::SUB_DSTF: // Destructible end case ESM4::SUB_RNAM: // FONV case ESM4::SUB_PRPS: // FO4 reader.skipSubRecordData(); diff --git a/components/esm4/loaddoor.cpp b/components/esm4/loaddoor.cpp index 0f51caf64d..d65b1489e6 100644 --- a/components/esm4/loaddoor.cpp +++ b/components/esm4/loaddoor.cpp @@ -75,11 +75,15 @@ void ESM4::Door::load(ESM4::Reader& reader) case ESM4::SUB_MODS: case ESM4::SUB_OBND: case ESM4::SUB_VMAD: - case ESM4::SUB_DEST: // FO3 - case ESM4::SUB_DSTD: // FO3 - case ESM4::SUB_DSTF: // FO3 - case ESM4::SUB_DMDL: // FO3 - case ESM4::SUB_DMDT: // FO3 + case ESM4::SUB_DAMC: // Destructible + case ESM4::SUB_DEST: + case ESM4::SUB_DMDC: + case ESM4::SUB_DMDL: + case ESM4::SUB_DMDT: + case ESM4::SUB_DMDS: + case ESM4::SUB_DSTA: + case ESM4::SUB_DSTD: + case ESM4::SUB_DSTF: // Destructible end reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadflor.cpp b/components/esm4/loadflor.cpp index 95bbef61a2..24c62b1291 100644 --- a/components/esm4/loadflor.cpp +++ b/components/esm4/loadflor.cpp @@ -72,6 +72,15 @@ void ESM4::Flora::load(ESM4::Reader& reader) case ESM4::SUB_PNAM: case ESM4::SUB_RNAM: case ESM4::SUB_VMAD: + case ESM4::SUB_DAMC: // Destructible + case ESM4::SUB_DEST: + case ESM4::SUB_DMDC: + case ESM4::SUB_DMDL: + case ESM4::SUB_DMDT: + case ESM4::SUB_DMDS: + case ESM4::SUB_DSTA: + case ESM4::SUB_DSTD: + case ESM4::SUB_DSTF: // Destructible end case ESM4::SUB_PRPS: reader.skipSubRecordData(); break; diff --git a/components/esm4/loadfurn.cpp b/components/esm4/loadfurn.cpp index b69d92d305..1c49b46662 100644 --- a/components/esm4/loadfurn.cpp +++ b/components/esm4/loadfurn.cpp @@ -60,9 +60,15 @@ void ESM4::Furniture::load(ESM4::Reader& reader) reader.get(mBoundRadius); break; case ESM4::SUB_MODT: + case ESM4::SUB_DAMC: // Destructible case ESM4::SUB_DEST: + case ESM4::SUB_DMDC: + case ESM4::SUB_DMDL: + case ESM4::SUB_DMDT: + case ESM4::SUB_DMDS: + case ESM4::SUB_DSTA: case ESM4::SUB_DSTD: - case ESM4::SUB_DSTF: + case ESM4::SUB_DSTF: // Destructible end case ESM4::SUB_ENAM: case ESM4::SUB_FNAM: case ESM4::SUB_FNMK: diff --git a/components/esm4/loadingr.cpp b/components/esm4/loadingr.cpp index b1dde9de02..8c40d32512 100644 --- a/components/esm4/loadingr.cpp +++ b/components/esm4/loadingr.cpp @@ -106,6 +106,15 @@ void ESM4::Ingredient::load(ESM4::Reader& reader) case ESM4::SUB_YNAM: case ESM4::SUB_ZNAM: case ESM4::SUB_ETYP: // FO3 + case ESM4::SUB_DAMC: // Destructible + case ESM4::SUB_DEST: + case ESM4::SUB_DMDC: + case ESM4::SUB_DMDL: + case ESM4::SUB_DMDT: + case ESM4::SUB_DMDS: + case ESM4::SUB_DSTA: + case ESM4::SUB_DSTD: + case ESM4::SUB_DSTF: // Destructible end { reader.skipSubRecordData(); break; diff --git a/components/esm4/loadkeym.cpp b/components/esm4/loadkeym.cpp index a46aa95f88..fa242a365e 100644 --- a/components/esm4/loadkeym.cpp +++ b/components/esm4/loadkeym.cpp @@ -76,6 +76,15 @@ void ESM4::Key::load(ESM4::Reader& reader) case ESM4::SUB_KWDA: case ESM4::SUB_OBND: case ESM4::SUB_VMAD: + case ESM4::SUB_DAMC: // Destructible + case ESM4::SUB_DEST: + case ESM4::SUB_DMDC: + case ESM4::SUB_DMDL: + case ESM4::SUB_DMDT: + case ESM4::SUB_DMDS: + case ESM4::SUB_DSTA: + case ESM4::SUB_DSTD: + case ESM4::SUB_DSTF: // Destructible end reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadligh.cpp b/components/esm4/loadligh.cpp index 12746623f7..29acef98a7 100644 --- a/components/esm4/loadligh.cpp +++ b/components/esm4/loadligh.cpp @@ -102,12 +102,15 @@ void ESM4::Light::load(ESM4::Reader& reader) case ESM4::SUB_MODT: case ESM4::SUB_OBND: case ESM4::SUB_VMAD: // Dragonborn only? - case ESM4::SUB_DEST: // Destruction data start - case ESM4::SUB_DSTD: + case ESM4::SUB_DAMC: // Destructible + case ESM4::SUB_DEST: + case ESM4::SUB_DMDC: case ESM4::SUB_DMDL: case ESM4::SUB_DMDT: case ESM4::SUB_DMDS: - case ESM4::SUB_DSTF: // Destruction data end + case ESM4::SUB_DSTA: + case ESM4::SUB_DSTD: + case ESM4::SUB_DSTF: // Destructible end case ESM4::SUB_PRPS: reader.skipSubRecordData(); break; diff --git a/components/esm4/loadmisc.cpp b/components/esm4/loadmisc.cpp index 90ebe1566c..3a1f835d8c 100644 --- a/components/esm4/loadmisc.cpp +++ b/components/esm4/loadmisc.cpp @@ -78,12 +78,15 @@ void ESM4::MiscItem::load(ESM4::Reader& reader) case ESM4::SUB_OBND: case ESM4::SUB_VMAD: case ESM4::SUB_RNAM: // FONV - case ESM4::SUB_DEST: // Destruction data start - case ESM4::SUB_DSTD: + case ESM4::SUB_DAMC: // Destructible + case ESM4::SUB_DEST: + case ESM4::SUB_DMDC: case ESM4::SUB_DMDL: case ESM4::SUB_DMDT: case ESM4::SUB_DMDS: - case ESM4::SUB_DSTF: // Destruction data end + case ESM4::SUB_DSTA: + case ESM4::SUB_DSTD: + case ESM4::SUB_DSTF: // Destructible end reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadmstt.cpp b/components/esm4/loadmstt.cpp index 3ace680eb9..b461dddfab 100644 --- a/components/esm4/loadmstt.cpp +++ b/components/esm4/loadmstt.cpp @@ -53,13 +53,17 @@ void ESM4::MovableStatic::load(ESM4::Reader& reader) case ESM4::SUB_SNAM: reader.getFormId(mLoopingSound); break; - case ESM4::SUB_DEST: // destruction data - case ESM4::SUB_OBND: // object bounds - case ESM4::SUB_MODT: // model texture data + case ESM4::SUB_DAMC: // Destructible + case ESM4::SUB_DEST: + case ESM4::SUB_DMDC: case ESM4::SUB_DMDL: case ESM4::SUB_DMDT: + case ESM4::SUB_DMDS: + case ESM4::SUB_DSTA: case ESM4::SUB_DSTD: - case ESM4::SUB_DSTF: + case ESM4::SUB_DSTF: // Destructible end + case ESM4::SUB_OBND: // object bounds + case ESM4::SUB_MODT: // model texture data case ESM4::SUB_MODS: case ESM4::SUB_FULL: case ESM4::SUB_MODB: diff --git a/components/esm4/loadnpc.cpp b/components/esm4/loadnpc.cpp index e4bfefbe51..8872e5e4ef 100644 --- a/components/esm4/loadnpc.cpp +++ b/components/esm4/loadnpc.cpp @@ -234,33 +234,15 @@ void ESM4::Npc::load(ESM4::Reader& reader) case ESM4::SUB_DPLT: reader.getFormId(mDefaultPkg); break; // AI package list + case ESM4::SUB_DAMC: // Destructible case ESM4::SUB_DEST: + case ESM4::SUB_DMDC: + case ESM4::SUB_DMDL: + case ESM4::SUB_DMDT: + case ESM4::SUB_DMDS: + case ESM4::SUB_DSTA: case ESM4::SUB_DSTD: - case ESM4::SUB_DSTF: - { -#if 0 - std::vector dataBuf(subHdr.dataSize); - reader.get(dataBuf.data(), 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 (dataBuf[i] > 64 && dataBuf[i] < 91) // looks like printable ascii char - ss << (char)(dataBuf[i]) << " "; - else - ss << std::setfill('0') << std::setw(2) << std::hex << (int)(dataBuf[i]); - if ((i & 0x000f) == 0xf) // wrap around - ss << "\n"; - else if (i < (size_t)(subHdr.dataSize - 1)) // quiesce gcc - ss << " "; - } - std::cout << ss.str() << std::endl; -#else - reader.skipSubRecordData(); -#endif - break; - } + case ESM4::SUB_DSTF: // Destructible end case ESM4::SUB_NAM6: // height mult case ESM4::SUB_NAM7: // weight mult case ESM4::SUB_ATKR: diff --git a/components/esm4/loadtact.cpp b/components/esm4/loadtact.cpp index 14d29d18b1..695616f613 100644 --- a/components/esm4/loadtact.cpp +++ b/components/esm4/loadtact.cpp @@ -62,9 +62,15 @@ void ESM4::TalkingActivator::load(ESM4::Reader& reader) case ESM4::SUB_MODL: reader.getZString(mModel); break; - case ESM4::SUB_DEST: // FO3 destruction - case ESM4::SUB_DSTD: // FO3 destruction - case ESM4::SUB_DSTF: // FO3 destruction + case ESM4::SUB_DAMC: // Destructible + case ESM4::SUB_DEST: + case ESM4::SUB_DMDC: + case ESM4::SUB_DMDL: + case ESM4::SUB_DMDT: + case ESM4::SUB_DMDS: + case ESM4::SUB_DSTA: + case ESM4::SUB_DSTD: + case ESM4::SUB_DSTF: // Destructible end case ESM4::SUB_FNAM: case ESM4::SUB_PNAM: case ESM4::SUB_MODT: // texture file hash? diff --git a/components/esm4/loadweap.cpp b/components/esm4/loadweap.cpp index d6fa4cac06..bf95c08e5b 100644 --- a/components/esm4/loadweap.cpp +++ b/components/esm4/loadweap.cpp @@ -149,11 +149,15 @@ void ESM4::Weapon::load(ESM4::Reader& reader) case ESM4::SUB_MO3S: // FO3 case ESM4::SUB_MODD: // FO3 // case ESM4::SUB_MOSD: // FO3 - case ESM4::SUB_DEST: // FO3 - case ESM4::SUB_DSTD: // FO3 - case ESM4::SUB_DSTF: // FO3 - case ESM4::SUB_DMDL: // FO3 - case ESM4::SUB_DMDT: // FO3 + case ESM4::SUB_DAMC: // Destructible + case ESM4::SUB_DEST: + case ESM4::SUB_DMDC: + case ESM4::SUB_DMDL: + case ESM4::SUB_DMDT: + case ESM4::SUB_DMDS: + case ESM4::SUB_DSTA: + case ESM4::SUB_DSTD: + case ESM4::SUB_DSTF: // Destructible end case ESM4::SUB_VATS: // FONV case ESM4::SUB_VANM: // FONV case ESM4::SUB_MWD1: // FONV From db6f76fea8c474225a7c6d04682a82a1538a4bae Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 16 Aug 2023 04:48:14 +0300 Subject: [PATCH 19/64] Skip more CIS1/CIS2 and skip all PRTN subrecords Avoid formatting problems with newly added skipped FO4 blocks --- components/esm4/loadacti.cpp | 15 +++-- components/esm4/loadalch.cpp | 7 +-- components/esm4/loadammo.cpp | 1 + components/esm4/loadarmo.cpp | 1 + components/esm4/loadbook.cpp | 1 + components/esm4/loadcont.cpp | 1 + components/esm4/loaddoor.cpp | 1 + components/esm4/loadflor.cpp | 3 +- components/esm4/loadfurn.cpp | 3 + components/esm4/loadkeym.cpp | 1 + components/esm4/loadligh.cpp | 3 +- components/esm4/loadmisc.cpp | 1 + components/esm4/loadmstt.cpp | 1 + components/esm4/loadnote.cpp | 1 + components/esm4/loadnpc.cpp | 1 + components/esm4/loadrace.cpp | 104 ++++++++++++++++++----------------- components/esm4/loadscol.cpp | 1 + components/esm4/loadstat.cpp | 11 ++-- components/esm4/loadterm.cpp | 1 + components/esm4/loadweap.cpp | 1 + 20 files changed, 88 insertions(+), 71 deletions(-) diff --git a/components/esm4/loadacti.cpp b/components/esm4/loadacti.cpp index d09a96417a..9533feba48 100644 --- a/components/esm4/loadacti.cpp +++ b/components/esm4/loadacti.cpp @@ -95,14 +95,13 @@ void ESM4::Activator::load(ESM4::Reader& reader) case ESM4::SUB_CIS2: case ESM4::SUB_CITC: case ESM4::SUB_NVNM: - // Introduced in FO4 - case ESM4::SUB_ATTX: - case ESM4::SUB_FTYP: - case ESM4::SUB_NTRM: - case ESM4::SUB_PTRN: - case ESM4::SUB_PRPS: - case ESM4::SUB_RADR: - case ESM4::SUB_STCP: + case ESM4::SUB_ATTX: // FO4 + case ESM4::SUB_FTYP: // FO4 + case ESM4::SUB_NTRM: // FO4 + case ESM4::SUB_PTRN: // FO4 + case ESM4::SUB_PRPS: // FO4 + case ESM4::SUB_RADR: // FO4 + case ESM4::SUB_STCP: // FO4 reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadalch.cpp b/components/esm4/loadalch.cpp index ab9bf2b1a6..2e3a762ed1 100644 --- a/components/esm4/loadalch.cpp +++ b/components/esm4/loadalch.cpp @@ -107,10 +107,9 @@ void ESM4::Potion::load(ESM4::Reader& reader) case ESM4::SUB_DSTA: case ESM4::SUB_DSTD: case ESM4::SUB_DSTF: // Destructible end - // FO4 - case ESM4::SUB_DNAM: - case ESM4::SUB_PTRN: - case ESM4::SUB_CUSD: + case ESM4::SUB_DNAM: // FO4 + case ESM4::SUB_PTRN: // FO4 + case ESM4::SUB_CUSD: // FO4 reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadammo.cpp b/components/esm4/loadammo.cpp index 78a022189a..31442f125d 100644 --- a/components/esm4/loadammo.cpp +++ b/components/esm4/loadammo.cpp @@ -146,6 +146,7 @@ void ESM4::Ammunition::load(ESM4::Reader& reader) case ESM4::SUB_DSTA: case ESM4::SUB_DSTD: case ESM4::SUB_DSTF: // Destructible end + case ESM4::SUB_PTRN: // FO4 reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadarmo.cpp b/components/esm4/loadarmo.cpp index ac21852411..fd11278ddb 100644 --- a/components/esm4/loadarmo.cpp +++ b/components/esm4/loadarmo.cpp @@ -200,6 +200,7 @@ void ESM4::Armor::load(ESM4::Reader& reader) case ESM4::SUB_DSTA: case ESM4::SUB_DSTD: case ESM4::SUB_DSTF: // Destructible end + case ESM4::SUB_PTRN: // FO4 reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadbook.cpp b/components/esm4/loadbook.cpp index 64cacfe81d..4201b6ddb5 100644 --- a/components/esm4/loadbook.cpp +++ b/components/esm4/loadbook.cpp @@ -111,6 +111,7 @@ void ESM4::Book::load(ESM4::Reader& reader) case ESM4::SUB_DSTA: case ESM4::SUB_DSTD: case ESM4::SUB_DSTF: // Destructible end + case ESM4::SUB_PTRN: // FO4 reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadcont.cpp b/components/esm4/loadcont.cpp index cd1aa45229..ced92c20a1 100644 --- a/components/esm4/loadcont.cpp +++ b/components/esm4/loadcont.cpp @@ -91,6 +91,7 @@ void ESM4::Container::load(ESM4::Reader& reader) case ESM4::SUB_DSTF: // Destructible end case ESM4::SUB_RNAM: // FONV case ESM4::SUB_PRPS: // FO4 + case ESM4::SUB_PTRN: // FO4 reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loaddoor.cpp b/components/esm4/loaddoor.cpp index d65b1489e6..4c8f53ac77 100644 --- a/components/esm4/loaddoor.cpp +++ b/components/esm4/loaddoor.cpp @@ -84,6 +84,7 @@ void ESM4::Door::load(ESM4::Reader& reader) case ESM4::SUB_DSTA: case ESM4::SUB_DSTD: case ESM4::SUB_DSTF: // Destructible end + case ESM4::SUB_PTRN: // FO4 reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadflor.cpp b/components/esm4/loadflor.cpp index 24c62b1291..65e4cf1353 100644 --- a/components/esm4/loadflor.cpp +++ b/components/esm4/loadflor.cpp @@ -81,7 +81,8 @@ void ESM4::Flora::load(ESM4::Reader& reader) case ESM4::SUB_DSTA: case ESM4::SUB_DSTD: case ESM4::SUB_DSTF: // Destructible end - case ESM4::SUB_PRPS: + case ESM4::SUB_PRPS: // FO4 + case ESM4::SUB_PTRN: // FO4 reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadfurn.cpp b/components/esm4/loadfurn.cpp index 1c49b46662..a84a980401 100644 --- a/components/esm4/loadfurn.cpp +++ b/components/esm4/loadfurn.cpp @@ -85,6 +85,9 @@ void ESM4::Furniture::load(ESM4::Reader& reader) case ESM4::SUB_XMRK: case ESM4::SUB_PRPS: case ESM4::SUB_CTDA: + case ESM4::SUB_CIS1: + case ESM4::SUB_CIS2: + case ESM4::SUB_PTRN: // FO4 reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadkeym.cpp b/components/esm4/loadkeym.cpp index fa242a365e..fb5d28b246 100644 --- a/components/esm4/loadkeym.cpp +++ b/components/esm4/loadkeym.cpp @@ -85,6 +85,7 @@ void ESM4::Key::load(ESM4::Reader& reader) case ESM4::SUB_DSTA: case ESM4::SUB_DSTD: case ESM4::SUB_DSTF: // Destructible end + case ESM4::SUB_PTRN: // FO4 reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadligh.cpp b/components/esm4/loadligh.cpp index 29acef98a7..52e6c06c5e 100644 --- a/components/esm4/loadligh.cpp +++ b/components/esm4/loadligh.cpp @@ -111,7 +111,8 @@ void ESM4::Light::load(ESM4::Reader& reader) case ESM4::SUB_DSTA: case ESM4::SUB_DSTD: case ESM4::SUB_DSTF: // Destructible end - case ESM4::SUB_PRPS: + case ESM4::SUB_PRPS: // FO4 + case ESM4::SUB_PTRN: // FO4 reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadmisc.cpp b/components/esm4/loadmisc.cpp index 3a1f835d8c..b3c8be7d8a 100644 --- a/components/esm4/loadmisc.cpp +++ b/components/esm4/loadmisc.cpp @@ -87,6 +87,7 @@ void ESM4::MiscItem::load(ESM4::Reader& reader) case ESM4::SUB_DSTA: case ESM4::SUB_DSTD: case ESM4::SUB_DSTF: // Destructible end + case ESM4::SUB_PTRN: // FO4 reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadmstt.cpp b/components/esm4/loadmstt.cpp index b461dddfab..3e67affd51 100644 --- a/components/esm4/loadmstt.cpp +++ b/components/esm4/loadmstt.cpp @@ -68,6 +68,7 @@ void ESM4::MovableStatic::load(ESM4::Reader& reader) case ESM4::SUB_FULL: case ESM4::SUB_MODB: case ESM4::SUB_PRPS: + case ESM4::SUB_PTRN: // FO4 reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadnote.cpp b/components/esm4/loadnote.cpp index b51600d966..4861ebe653 100644 --- a/components/esm4/loadnote.cpp +++ b/components/esm4/loadnote.cpp @@ -60,6 +60,7 @@ void ESM4::Note::load(ESM4::Reader& reader) case ESM4::SUB_TNAM: case ESM4::SUB_XNAM: case ESM4::SUB_OBND: + case ESM4::SUB_PTRN: // FO4 reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadnpc.cpp b/components/esm4/loadnpc.cpp index 8872e5e4ef..2fb15a18b5 100644 --- a/components/esm4/loadnpc.cpp +++ b/components/esm4/loadnpc.cpp @@ -278,6 +278,7 @@ void ESM4::Npc::load(ESM4::Reader& reader) case ESM4::SUB_NAM4: // FO3 case ESM4::SUB_COED: // FO3 case ESM4::SUB_PRPS: // FO4 + case ESM4::SUB_PTRN: // FO4 reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadrace.cpp b/components/esm4/loadrace.cpp index a2da871a4a..0b8ced1fb4 100644 --- a/components/esm4/loadrace.cpp +++ b/components/esm4/loadrace.cpp @@ -702,6 +702,9 @@ void ESM4::Race::load(ESM4::Reader& reader) case ESM4::SUB_WKMV: case ESM4::SUB_SPMV: case ESM4::SUB_ATKR: + case ESM4::SUB_CTDA: + case ESM4::SUB_CIS1: + case ESM4::SUB_CIS2: // case ESM4::SUB_YNAM: // FO3 case ESM4::SUB_NAM2: // FO3 @@ -709,57 +712,56 @@ void ESM4::Race::load(ESM4::Reader& reader) case ESM4::SUB_MODT: // FO3 case ESM4::SUB_MODD: // FO3 case ESM4::SUB_ONAM: // FO3 - // FO4 - case ESM4::SUB_APPR: - case ESM4::SUB_ATKS: - case ESM4::SUB_ATKT: - case ESM4::SUB_ATKW: - case ESM4::SUB_BMMP: - case ESM4::SUB_BSMB: - case ESM4::SUB_BSMP: - case ESM4::SUB_BSMS: - case ESM4::SUB_CTDA: - case ESM4::SUB_FMRI: - case ESM4::SUB_FMRN: - case ESM4::SUB_HLTX: - case ESM4::SUB_MLSI: - case ESM4::SUB_MPGN: - case ESM4::SUB_MPGS: - case ESM4::SUB_MPPC: - case ESM4::SUB_MPPF: - case ESM4::SUB_MPPI: - case ESM4::SUB_MPPK: - case ESM4::SUB_MPPM: - case ESM4::SUB_MPPN: - case ESM4::SUB_MPPT: - case ESM4::SUB_MSID: - case ESM4::SUB_MSM0: - case ESM4::SUB_MSM1: - case ESM4::SUB_NNAM: - case ESM4::SUB_NTOP: - case ESM4::SUB_PRPS: - case ESM4::SUB_PTOP: - case ESM4::SUB_QSTI: - case ESM4::SUB_RBPC: - case ESM4::SUB_SADD: - case ESM4::SUB_SAKD: - case ESM4::SUB_SAPT: - case ESM4::SUB_SGNM: - case ESM4::SUB_SRAC: - case ESM4::SUB_SRAF: - case ESM4::SUB_STCP: - case ESM4::SUB_STKD: - case ESM4::SUB_TETI: - case ESM4::SUB_TTEB: - case ESM4::SUB_TTEC: - case ESM4::SUB_TTED: - case ESM4::SUB_TTEF: - case ESM4::SUB_TTET: - case ESM4::SUB_TTGE: - case ESM4::SUB_TTGP: - case ESM4::SUB_UNWP: - case ESM4::SUB_WMAP: - case ESM4::SUB_ZNAM: + case ESM4::SUB_APPR: // FO4 + case ESM4::SUB_ATKS: // FO4 + case ESM4::SUB_ATKT: // FO4 + case ESM4::SUB_ATKW: // FO4 + case ESM4::SUB_BMMP: // FO4 + case ESM4::SUB_BSMB: // FO4 + case ESM4::SUB_BSMP: // FO4 + case ESM4::SUB_BSMS: // FO4 + + case ESM4::SUB_FMRI: // FO4 + case ESM4::SUB_FMRN: // FO4 + case ESM4::SUB_HLTX: // FO4 + case ESM4::SUB_MLSI: // FO4 + case ESM4::SUB_MPGN: // FO4 + case ESM4::SUB_MPGS: // FO4 + case ESM4::SUB_MPPC: // FO4 + case ESM4::SUB_MPPF: // FO4 + case ESM4::SUB_MPPI: // FO4 + case ESM4::SUB_MPPK: // FO4 + case ESM4::SUB_MPPM: // FO4 + case ESM4::SUB_MPPN: // FO4 + case ESM4::SUB_MPPT: // FO4 + case ESM4::SUB_MSID: // FO4 + case ESM4::SUB_MSM0: // FO4 + case ESM4::SUB_MSM1: // FO4 + case ESM4::SUB_NNAM: // FO4 + case ESM4::SUB_NTOP: // FO4 + case ESM4::SUB_PRPS: // FO4 + case ESM4::SUB_PTOP: // FO4 + case ESM4::SUB_QSTI: // FO4 + case ESM4::SUB_RBPC: // FO4 + case ESM4::SUB_SADD: // FO4 + case ESM4::SUB_SAKD: // FO4 + case ESM4::SUB_SAPT: // FO4 + case ESM4::SUB_SGNM: // FO4 + case ESM4::SUB_SRAC: // FO4 + case ESM4::SUB_SRAF: // FO4 + case ESM4::SUB_STCP: // FO4 + case ESM4::SUB_STKD: // FO4 + case ESM4::SUB_TETI: // FO4 + case ESM4::SUB_TTEB: // FO4 + case ESM4::SUB_TTEC: // FO4 + case ESM4::SUB_TTED: // FO4 + case ESM4::SUB_TTEF: // FO4 + case ESM4::SUB_TTET: // FO4 + case ESM4::SUB_TTGE: // FO4 + case ESM4::SUB_TTGP: // FO4 + case ESM4::SUB_UNWP: // FO4 + case ESM4::SUB_WMAP: // FO4 + case ESM4::SUB_ZNAM: // FO4 reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadscol.cpp b/components/esm4/loadscol.cpp index a795b63d10..380e8fbe0f 100644 --- a/components/esm4/loadscol.cpp +++ b/components/esm4/loadscol.cpp @@ -51,6 +51,7 @@ void ESM4::StaticCollection::load(ESM4::Reader& reader) case ESM4::SUB_MODT: case ESM4::SUB_ONAM: case ESM4::SUB_DATA: + case ESM4::SUB_PTRN: // FO4 reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadstat.cpp b/components/esm4/loadstat.cpp index 640db00d1e..a3bb7618c7 100644 --- a/components/esm4/loadstat.cpp +++ b/components/esm4/loadstat.cpp @@ -89,12 +89,11 @@ void ESM4::Static::load(ESM4::Reader& reader) case ESM4::SUB_DNAM: case ESM4::SUB_BRUS: // FONV case ESM4::SUB_RNAM: // FONV - // FO4 - case ESM4::SUB_FTYP: - case ESM4::SUB_NVNM: - case ESM4::SUB_PRPS: - case ESM4::SUB_PTRN: - case ESM4::SUB_VMAD: + case ESM4::SUB_FTYP: // FO4 + case ESM4::SUB_NVNM: // FO4 + case ESM4::SUB_PRPS: // FO4 + case ESM4::SUB_PTRN: // FO4 + case ESM4::SUB_VMAD: // FO4 reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadterm.cpp b/components/esm4/loadterm.cpp index b190145e5f..c33afed2d6 100644 --- a/components/esm4/loadterm.cpp +++ b/components/esm4/loadterm.cpp @@ -82,6 +82,7 @@ void ESM4::Terminal::load(ESM4::Reader& reader) case ESM4::SUB_OBND: case ESM4::SUB_MODS: // FONV case ESM4::SUB_PRPS: // FO4 + case ESM4::SUB_PTRN: // FO4 reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadweap.cpp b/components/esm4/loadweap.cpp index bf95c08e5b..f266291fc2 100644 --- a/components/esm4/loadweap.cpp +++ b/components/esm4/loadweap.cpp @@ -180,6 +180,7 @@ void ESM4::Weapon::load(ESM4::Reader& reader) case ESM4::SUB_WNM6: // FONV case ESM4::SUB_WNM7: // FONV case ESM4::SUB_EFSD: // FONV DeadMoney + case ESM4::SUB_PTRN: // FO4 reader.skipSubRecordData(); break; default: From aedcc28294100adcb85760ed7396798200831c07 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 16 Aug 2023 05:12:45 +0300 Subject: [PATCH 20/64] Maybe load FO4 armor records --- components/esm4/loadarmo.cpp | 72 +++++++++++++++++++++++++++--------- components/esm4/loadarmo.hpp | 4 -- 2 files changed, 54 insertions(+), 22 deletions(-) diff --git a/components/esm4/loadarmo.cpp b/components/esm4/loadarmo.cpp index fd11278ddb..9f304a884f 100644 --- a/components/esm4/loadarmo.cpp +++ b/components/esm4/loadarmo.cpp @@ -35,9 +35,7 @@ void ESM4::Armor::load(ESM4::Reader& reader) { mId = reader.getFormIdFromHeader(); mFlags = reader.hdr().record.flags; - std::uint32_t esmVer = reader.esmVersion(); - mIsFONV = esmVer == ESM::VER_132 || esmVer == ESM::VER_133 || esmVer == ESM::VER_134; - + uint16_t currentIndex = 0xFFFF; while (reader.getSubRecordHeader()) { const ESM4::SubRecordHeader& subHdr = reader.subRecordHeader(); @@ -51,32 +49,51 @@ void ESM4::Armor::load(ESM4::Reader& reader) break; case ESM4::SUB_DATA: { - // if (reader.esmVersion() == ESM::VER_094 || reader.esmVersion() == ESM::VER_170) - if (subHdr.dataSize == 8) // FO3 has 12 bytes even though VER_094 + // TES5 + if (subHdr.dataSize == 8) { reader.get(mData.value); reader.get(mData.weight); - mIsFO3 = true; } - else if (mIsFONV || subHdr.dataSize == 12) + // FO3, FNV, FO4 + else if (subHdr.dataSize == 12) { reader.get(mData.value); reader.get(mData.health); reader.get(mData.weight); } + // TES4 + else if (subHdr.dataSize == 14) + { + reader.get(mData); + } else { - reader.get(mData); // TES4 - mIsTES4 = true; + reader.skipSubRecordData(); } - break; } - case ESM4::SUB_MODL: // seems only for Dawnguard/Dragonborn? + case ESM4::SUB_INDX: // FO4 + { + reader.get(currentIndex); + break; + } + case ESM4::SUB_MODL: { - // if (esmVer == ESM::VER_094 || esmVer == ESM::VER_170 || isFONV) - if (subHdr.dataSize == 4) // FO3 has zstring even though VER_094 - reader.getFormId(mAddOns.emplace_back()); + if (subHdr.dataSize == 4) + { + // Assuming TES5 + if (currentIndex == 0xFFFF) + reader.getFormId(mAddOns.emplace_back()); + // FO4 + else + { + if (mAddOns.size() <= currentIndex) + mAddOns.resize(currentIndex + 1); + reader.getFormId(mAddOns[currentIndex]); + } + + } else { if (!reader.getZString(mModelMale)) @@ -135,10 +152,21 @@ void ESM4::Armor::load(ESM4::Reader& reader) break; } case ESM4::SUB_BOD2: - reader.get(mArmorFlags); - reader.get(mGeneralFlags); - mGeneralFlags &= 0x0000000f; // 0 (light), 1 (heavy) or 2 (none) - mGeneralFlags |= TYPE_TES5; + // FO4, TES5 + if (subHdr.dataSize == 4 || subHdr.dataSize == 8) + { + reader.get(mArmorFlags); + if (subHdr.dataSize == 8) + { + reader.get(mGeneralFlags); + mGeneralFlags &= 0x0000000f; // 0 (light), 1 (heavy) or 2 (none) + mGeneralFlags |= TYPE_TES5; + } + } + else + { + reader.skipSubRecordData(); + } break; case ESM4::SUB_SCRI: reader.getFormId(mScriptId); @@ -200,7 +228,15 @@ void ESM4::Armor::load(ESM4::Reader& reader) case ESM4::SUB_DSTA: case ESM4::SUB_DSTD: case ESM4::SUB_DSTF: // Destructible end + case ESM4::SUB_APPR: // FO4 + case ESM4::SUB_DAMA: // FO4 + case ESM4::SUB_FNAM: // FO4 + case ESM4::SUB_INRD: // FO4 case ESM4::SUB_PTRN: // FO4 + case ESM4::SUB_OBTE: // FO4 object template start + case ESM4::SUB_OBTF: + case ESM4::SUB_OBTS: + case ESM4::SUB_STOP: // FO4 object template end reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadarmo.hpp b/components/esm4/loadarmo.hpp index 43832db00a..366b01780a 100644 --- a/components/esm4/loadarmo.hpp +++ b/components/esm4/loadarmo.hpp @@ -152,10 +152,6 @@ namespace ESM4 ESM::FormId mId; // from the header std::uint32_t mFlags; // from the header, see enum type RecordFlag for details - bool mIsTES4; // TODO: check that these match the general flags - bool mIsFO3; - bool mIsFONV; - std::string mEditorId; std::string mFullName; std::string mModelMale; From d9ebdc6e4165a1895f6ea8dcc06dc609e0610ebd Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 16 Aug 2023 05:41:13 +0300 Subject: [PATCH 21/64] Maybe load FO4 book records --- components/esm4/loadbook.cpp | 41 ++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/components/esm4/loadbook.cpp b/components/esm4/loadbook.cpp index 4201b6ddb5..d78c7ada6a 100644 --- a/components/esm4/loadbook.cpp +++ b/components/esm4/loadbook.cpp @@ -53,22 +53,31 @@ void ESM4::Book::load(ESM4::Reader& reader) break; case ESM4::SUB_DATA: { - reader.get(mData.flags); - // if (reader.esmVersion() == ESM::VER_094 || reader.esmVersion() == ESM::VER_170) - if (subHdr.dataSize == 16) // FO3 has 10 bytes even though VER_094 + if (subHdr.dataSize == 8 || subHdr.dataSize == 10 || subHdr.dataSize == 16) { - static std::uint8_t dummy; - reader.get(mData.type); - reader.get(dummy); - reader.get(dummy); - reader.get(mData.teaches); + // TES4, FO3, FNV + if (subHdr.dataSize == 10) + { + reader.get(mData.flags); + reader.get(mData.bookSkill); + } + // TES5 + else if (subHdr.dataSize == 16) + { + reader.get(mData.flags); + reader.get(mData.type); + std::uint16_t dummy; + reader.get(dummy); + reader.get(mData.teaches); + } + // else: FO4 + reader.get(mData.value); + reader.get(mData.weight); } else { - reader.get(mData.bookSkill); + reader.skipSubRecordData(); } - reader.get(mData.value); - reader.get(mData.weight); break; } case ESM4::SUB_ICON: @@ -94,8 +103,11 @@ void ESM4::Book::load(ESM4::Reader& reader) break; case ESM4::SUB_ZNAM: reader.getFormId(mDropSound); - break; // TODO: does this exist? - case ESM4::SUB_MODT: + break; + case ESM4::SUB_MODT: // Model data + case ESM4::SUB_MODC: + case ESM4::SUB_MODS: + case ESM4::SUB_MODF: // Model data end case ESM4::SUB_OBND: case ESM4::SUB_KSIZ: case ESM4::SUB_KWDA: @@ -111,6 +123,9 @@ void ESM4::Book::load(ESM4::Reader& reader) case ESM4::SUB_DSTA: case ESM4::SUB_DSTD: case ESM4::SUB_DSTF: // Destructible end + case ESM4::SUB_DNAM: // FO4 + case ESM4::SUB_FIMD: // FO4 + case ESM4::SUB_MICO: // FO4 case ESM4::SUB_PTRN: // FO4 reader.skipSubRecordData(); break; From 60813345ae251d0339477b243b83bacfd4cbb36d Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Thu, 17 Aug 2023 02:14:15 +0300 Subject: [PATCH 22/64] ESM4: Acknowledge all model data records --- components/esm4/loadacti.cpp | 4 +++- components/esm4/loadalch.cpp | 6 ++++-- components/esm4/loadammo.cpp | 5 ++++- components/esm4/loadanio.cpp | 6 ++++-- components/esm4/loadbptd.cpp | 4 +++- components/esm4/loadcont.cpp | 6 ++++-- components/esm4/loaddoor.cpp | 4 +++- components/esm4/loadflor.cpp | 4 +++- components/esm4/loadfurn.cpp | 6 ++++-- components/esm4/loadgras.cpp | 5 ++++- components/esm4/loadhdpt.cpp | 4 +++- components/esm4/loadidlm.cpp | 4 +++- components/esm4/loadingr.cpp | 6 ++++-- components/esm4/loadkeym.cpp | 5 ++++- components/esm4/loadligh.cpp | 5 ++++- components/esm4/loadlvln.cpp | 5 ++++- components/esm4/loadmato.cpp | 4 ++++ components/esm4/loadmisc.cpp | 6 ++++-- components/esm4/loadmstt.cpp | 4 +++- components/esm4/loadnote.cpp | 4 ++++ components/esm4/loadrace.cpp | 5 ++++- components/esm4/loadscol.cpp | 5 ++++- components/esm4/loadstat.cpp | 2 ++ components/esm4/loadtact.cpp | 6 ++++-- components/esm4/loadterm.cpp | 6 ++++-- components/esm4/loadtree.cpp | 5 ++++- components/esm4/loadweap.cpp | 6 ++++-- components/esm4/loadwrld.cpp | 7 +++++-- 28 files changed, 104 insertions(+), 35 deletions(-) diff --git a/components/esm4/loadacti.cpp b/components/esm4/loadacti.cpp index 9533feba48..74eaff2dab 100644 --- a/components/esm4/loadacti.cpp +++ b/components/esm4/loadacti.cpp @@ -71,8 +71,10 @@ void ESM4::Activator::load(ESM4::Reader& reader) case ESM4::SUB_XATO: reader.getZString(mActivationPrompt); break; // FONV - case ESM4::SUB_MODT: + case ESM4::SUB_MODT: // Model data + case ESM4::SUB_MODC: case ESM4::SUB_MODS: + case ESM4::SUB_MODF: // Model data end case ESM4::SUB_DAMC: // Destructible case ESM4::SUB_DEST: case ESM4::SUB_DMDC: diff --git a/components/esm4/loadalch.cpp b/components/esm4/loadalch.cpp index 2e3a762ed1..1ecfda25e8 100644 --- a/components/esm4/loadalch.cpp +++ b/components/esm4/loadalch.cpp @@ -88,13 +88,15 @@ void ESM4::Potion::load(ESM4::Reader& reader) case ESM4::SUB_ZNAM: reader.getFormId(mDropSound); break; - case ESM4::SUB_MODT: + case ESM4::SUB_MODT: // Model data + case ESM4::SUB_MODC: + case ESM4::SUB_MODS: + case ESM4::SUB_MODF: // Model data end 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 case ESM4::SUB_DESC: diff --git a/components/esm4/loadammo.cpp b/components/esm4/loadammo.cpp index 31442f125d..bc05d007e6 100644 --- a/components/esm4/loadammo.cpp +++ b/components/esm4/loadammo.cpp @@ -133,7 +133,10 @@ void ESM4::Ammunition::load(ESM4::Reader& reader) case ESM4::SUB_SCRI: reader.getFormId(mScript); break; - case ESM4::SUB_MODT: + case ESM4::SUB_MODT: // Model data + case ESM4::SUB_MODC: + case ESM4::SUB_MODS: + case ESM4::SUB_MODF: // Model data end case ESM4::SUB_OBND: case ESM4::SUB_KSIZ: case ESM4::SUB_KWDA: diff --git a/components/esm4/loadanio.cpp b/components/esm4/loadanio.cpp index 768e4d7822..fa440f5ace 100644 --- a/components/esm4/loadanio.cpp +++ b/components/esm4/loadanio.cpp @@ -56,8 +56,10 @@ void ESM4::AnimObject::load(ESM4::Reader& reader) case ESM4::SUB_MODB: reader.get(mBoundRadius); break; - case ESM4::SUB_MODT: // TES5 only - case ESM4::SUB_MODS: // TES5 only + case ESM4::SUB_MODT: // Model data + case ESM4::SUB_MODC: + case ESM4::SUB_MODS: + case ESM4::SUB_MODF: // Model data end reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadbptd.cpp b/components/esm4/loadbptd.cpp index a9edc2b145..b4c783c5ff 100644 --- a/components/esm4/loadbptd.cpp +++ b/components/esm4/loadbptd.cpp @@ -90,8 +90,10 @@ void ESM4::BodyPartData::load(ESM4::Reader& reader) break; case ESM4::SUB_NAM5: case ESM4::SUB_RAGA: // ragdoll + case ESM4::SUB_MODT: // Model data + case ESM4::SUB_MODC: case ESM4::SUB_MODS: - case ESM4::SUB_MODT: + case ESM4::SUB_MODF: // Model data end reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadcont.cpp b/components/esm4/loadcont.cpp index ced92c20a1..2aa7f57b5d 100644 --- a/components/esm4/loadcont.cpp +++ b/components/esm4/loadcont.cpp @@ -74,8 +74,10 @@ void ESM4::Container::load(ESM4::Reader& reader) case ESM4::SUB_MODB: reader.get(mBoundRadius); break; - case ESM4::SUB_MODT: - case ESM4::SUB_MODS: // TES5 only + case ESM4::SUB_MODT: // Model data + case ESM4::SUB_MODC: + case ESM4::SUB_MODS: + case ESM4::SUB_MODF: // Model data end case ESM4::SUB_VMAD: // TES5 only case ESM4::SUB_OBND: // TES5 only case ESM4::SUB_COCT: // TES5 only diff --git a/components/esm4/loaddoor.cpp b/components/esm4/loaddoor.cpp index 4c8f53ac77..8ee771fd0c 100644 --- a/components/esm4/loaddoor.cpp +++ b/components/esm4/loaddoor.cpp @@ -71,8 +71,10 @@ void ESM4::Door::load(ESM4::Reader& reader) case ESM4::SUB_MODB: reader.get(mBoundRadius); break; - case ESM4::SUB_MODT: + case ESM4::SUB_MODT: // Model data + case ESM4::SUB_MODC: case ESM4::SUB_MODS: + case ESM4::SUB_MODF: // Model data end case ESM4::SUB_OBND: case ESM4::SUB_VMAD: case ESM4::SUB_DAMC: // Destructible diff --git a/components/esm4/loadflor.cpp b/components/esm4/loadflor.cpp index 65e4cf1353..b3ea69e0d0 100644 --- a/components/esm4/loadflor.cpp +++ b/components/esm4/loadflor.cpp @@ -65,8 +65,10 @@ void ESM4::Flora::load(ESM4::Reader& reader) case ESM4::SUB_MODB: reader.get(mBoundRadius); break; - case ESM4::SUB_MODT: + case ESM4::SUB_MODT: // Model data + case ESM4::SUB_MODC: case ESM4::SUB_MODS: + case ESM4::SUB_MODF: // Model data end case ESM4::SUB_FNAM: case ESM4::SUB_OBND: case ESM4::SUB_PNAM: diff --git a/components/esm4/loadfurn.cpp b/components/esm4/loadfurn.cpp index a84a980401..9f00827772 100644 --- a/components/esm4/loadfurn.cpp +++ b/components/esm4/loadfurn.cpp @@ -59,7 +59,10 @@ void ESM4::Furniture::load(ESM4::Reader& reader) case ESM4::SUB_MODB: reader.get(mBoundRadius); break; - case ESM4::SUB_MODT: + case ESM4::SUB_MODT: // Model data + case ESM4::SUB_MODC: + case ESM4::SUB_MODS: + case ESM4::SUB_MODF: // Model data end case ESM4::SUB_DAMC: // Destructible case ESM4::SUB_DEST: case ESM4::SUB_DMDC: @@ -76,7 +79,6 @@ void ESM4::Furniture::load(ESM4::Reader& reader) case ESM4::SUB_KNAM: case ESM4::SUB_KSIZ: case ESM4::SUB_KWDA: - case ESM4::SUB_MODS: case ESM4::SUB_NAM0: case ESM4::SUB_OBND: case ESM4::SUB_PNAM: diff --git a/components/esm4/loadgras.cpp b/components/esm4/loadgras.cpp index 88147ecae9..ebcdde04a1 100644 --- a/components/esm4/loadgras.cpp +++ b/components/esm4/loadgras.cpp @@ -53,7 +53,10 @@ void ESM4::Grass::load(ESM4::Reader& reader) case ESM4::SUB_MODB: reader.get(mBoundRadius); break; - case ESM4::SUB_MODT: + case ESM4::SUB_MODT: // Model data + case ESM4::SUB_MODC: + case ESM4::SUB_MODS: + case ESM4::SUB_MODF: // Model data end case ESM4::SUB_OBND: reader.skipSubRecordData(); break; diff --git a/components/esm4/loadhdpt.cpp b/components/esm4/loadhdpt.cpp index d74642314f..7592db5486 100644 --- a/components/esm4/loadhdpt.cpp +++ b/components/esm4/loadhdpt.cpp @@ -88,8 +88,10 @@ void ESM4::HeadPart::load(ESM4::Reader& reader) reader.getFormId(mBaseTexture); break; case ESM4::SUB_PNAM: + case ESM4::SUB_MODT: // Model data + case ESM4::SUB_MODC: case ESM4::SUB_MODS: - case ESM4::SUB_MODT: + case ESM4::SUB_MODF: // Model data end case ESM4::SUB_RNAM: case ESM4::SUB_CNAM: case ESM4::SUB_CTDA: diff --git a/components/esm4/loadidlm.cpp b/components/esm4/loadidlm.cpp index 3c561e962f..4b476c46f0 100644 --- a/components/esm4/loadidlm.cpp +++ b/components/esm4/loadidlm.cpp @@ -79,8 +79,10 @@ void ESM4::IdleMarker::load(ESM4::Reader& reader) reader.getZString(mModel); break; case ESM4::SUB_OBND: // object bounds - case ESM4::SUB_MODT: + case ESM4::SUB_MODT: // Model data + case ESM4::SUB_MODC: case ESM4::SUB_MODS: + case ESM4::SUB_MODF: // Model data end reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadingr.cpp b/components/esm4/loadingr.cpp index 8c40d32512..d0b81fd4a1 100644 --- a/components/esm4/loadingr.cpp +++ b/components/esm4/loadingr.cpp @@ -95,8 +95,10 @@ void ESM4::Ingredient::load(ESM4::Reader& reader) reader.adjustFormId(mEffect.formId); break; } - case ESM4::SUB_MODT: - case ESM4::SUB_MODS: // Dragonborn only? + case ESM4::SUB_MODT: // Model data + case ESM4::SUB_MODC: + case ESM4::SUB_MODS: + case ESM4::SUB_MODF: // Model data end case ESM4::SUB_EFID: case ESM4::SUB_EFIT: case ESM4::SUB_OBND: diff --git a/components/esm4/loadkeym.cpp b/components/esm4/loadkeym.cpp index fb5d28b246..9b0c280b8b 100644 --- a/components/esm4/loadkeym.cpp +++ b/components/esm4/loadkeym.cpp @@ -71,7 +71,10 @@ void ESM4::Key::load(ESM4::Reader& reader) case ESM4::SUB_ZNAM: reader.getFormId(mDropSound); break; - case ESM4::SUB_MODT: + case ESM4::SUB_MODT: // Model data + case ESM4::SUB_MODC: + case ESM4::SUB_MODS: + case ESM4::SUB_MODF: // Model data end case ESM4::SUB_KSIZ: case ESM4::SUB_KWDA: case ESM4::SUB_OBND: diff --git a/components/esm4/loadligh.cpp b/components/esm4/loadligh.cpp index 52e6c06c5e..79ff307dc0 100644 --- a/components/esm4/loadligh.cpp +++ b/components/esm4/loadligh.cpp @@ -99,7 +99,10 @@ void ESM4::Light::load(ESM4::Reader& reader) case ESM4::SUB_FNAM: reader.get(mFade); break; - case ESM4::SUB_MODT: + case ESM4::SUB_MODT: // Model data + case ESM4::SUB_MODC: + case ESM4::SUB_MODS: + case ESM4::SUB_MODF: // Model data end case ESM4::SUB_OBND: case ESM4::SUB_VMAD: // Dragonborn only? case ESM4::SUB_DAMC: // Destructible diff --git a/components/esm4/loadlvln.cpp b/components/esm4/loadlvln.cpp index b1efddc255..b994577b41 100644 --- a/components/esm4/loadlvln.cpp +++ b/components/esm4/loadlvln.cpp @@ -91,7 +91,10 @@ void ESM4::LevelledNpc::load(ESM4::Reader& reader) } case ESM4::SUB_COED: // owner case ESM4::SUB_OBND: // object bounds - case ESM4::SUB_MODT: // model texture data + case ESM4::SUB_MODT: // Model data + case ESM4::SUB_MODC: + case ESM4::SUB_MODS: + case ESM4::SUB_MODF: // Model data end reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadmato.cpp b/components/esm4/loadmato.cpp index a3b55ce1f2..13d5e7d83d 100644 --- a/components/esm4/loadmato.cpp +++ b/components/esm4/loadmato.cpp @@ -49,6 +49,10 @@ void ESM4::Material::load(ESM4::Reader& reader) break; case ESM4::SUB_DNAM: case ESM4::SUB_DATA: + case ESM4::SUB_MODT: // Model data + case ESM4::SUB_MODC: + case ESM4::SUB_MODS: + case ESM4::SUB_MODF: // Model data end reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadmisc.cpp b/components/esm4/loadmisc.cpp index b3c8be7d8a..646154309e 100644 --- a/components/esm4/loadmisc.cpp +++ b/components/esm4/loadmisc.cpp @@ -71,10 +71,12 @@ void ESM4::MiscItem::load(ESM4::Reader& reader) case ESM4::SUB_ZNAM: reader.getFormId(mDropSound); break; - case ESM4::SUB_MODT: + case ESM4::SUB_MODT: // Model data + case ESM4::SUB_MODC: + case ESM4::SUB_MODS: + case ESM4::SUB_MODF: // Model data end case ESM4::SUB_KSIZ: case ESM4::SUB_KWDA: - case ESM4::SUB_MODS: case ESM4::SUB_OBND: case ESM4::SUB_VMAD: case ESM4::SUB_RNAM: // FONV diff --git a/components/esm4/loadmstt.cpp b/components/esm4/loadmstt.cpp index 3e67affd51..75a4afe76e 100644 --- a/components/esm4/loadmstt.cpp +++ b/components/esm4/loadmstt.cpp @@ -63,8 +63,10 @@ void ESM4::MovableStatic::load(ESM4::Reader& reader) case ESM4::SUB_DSTD: case ESM4::SUB_DSTF: // Destructible end case ESM4::SUB_OBND: // object bounds - case ESM4::SUB_MODT: // model texture data + case ESM4::SUB_MODT: // Model data + case ESM4::SUB_MODC: case ESM4::SUB_MODS: + case ESM4::SUB_MODF: // Model data end case ESM4::SUB_FULL: case ESM4::SUB_MODB: case ESM4::SUB_PRPS: diff --git a/components/esm4/loadnote.cpp b/components/esm4/loadnote.cpp index 4861ebe653..fbfd4031c3 100644 --- a/components/esm4/loadnote.cpp +++ b/components/esm4/loadnote.cpp @@ -55,6 +55,10 @@ void ESM4::Note::load(ESM4::Reader& reader) break; case ESM4::SUB_DATA: case ESM4::SUB_MODB: + case ESM4::SUB_MODT: // Model data + case ESM4::SUB_MODC: + case ESM4::SUB_MODS: + case ESM4::SUB_MODF: // Model data end case ESM4::SUB_ONAM: case ESM4::SUB_SNAM: case ESM4::SUB_TNAM: diff --git a/components/esm4/loadrace.cpp b/components/esm4/loadrace.cpp index 0b8ced1fb4..28f91787e6 100644 --- a/components/esm4/loadrace.cpp +++ b/components/esm4/loadrace.cpp @@ -705,11 +705,14 @@ void ESM4::Race::load(ESM4::Reader& reader) case ESM4::SUB_CTDA: case ESM4::SUB_CIS1: case ESM4::SUB_CIS2: + case ESM4::SUB_MODT: // Model data + case ESM4::SUB_MODC: + case ESM4::SUB_MODS: + case ESM4::SUB_MODF: // Model data end // case ESM4::SUB_YNAM: // FO3 case ESM4::SUB_NAM2: // FO3 case ESM4::SUB_VTCK: // FO3 - case ESM4::SUB_MODT: // FO3 case ESM4::SUB_MODD: // FO3 case ESM4::SUB_ONAM: // FO3 case ESM4::SUB_APPR: // FO4 diff --git a/components/esm4/loadscol.cpp b/components/esm4/loadscol.cpp index 380e8fbe0f..6f1aef0202 100644 --- a/components/esm4/loadscol.cpp +++ b/components/esm4/loadscol.cpp @@ -47,8 +47,11 @@ void ESM4::StaticCollection::load(ESM4::Reader& reader) reader.getZString(mEditorId); break; case ESM4::SUB_OBND: - case ESM4::SUB_MODL: + case ESM4::SUB_MODL: // Model data start case ESM4::SUB_MODT: + case ESM4::SUB_MODC: + case ESM4::SUB_MODS: + case ESM4::SUB_MODF: // Model data end case ESM4::SUB_ONAM: case ESM4::SUB_DATA: case ESM4::SUB_PTRN: // FO4 diff --git a/components/esm4/loadstat.cpp b/components/esm4/loadstat.cpp index a3bb7618c7..e3b51633cf 100644 --- a/components/esm4/loadstat.cpp +++ b/components/esm4/loadstat.cpp @@ -84,7 +84,9 @@ void ESM4::Static::load(ESM4::Reader& reader) } break; } + case ESM4::SUB_MODC: // More model data case ESM4::SUB_MODS: + case ESM4::SUB_MODF: // Model data end case ESM4::SUB_OBND: case ESM4::SUB_DNAM: case ESM4::SUB_BRUS: // FONV diff --git a/components/esm4/loadtact.cpp b/components/esm4/loadtact.cpp index 695616f613..ad5efb9fbf 100644 --- a/components/esm4/loadtact.cpp +++ b/components/esm4/loadtact.cpp @@ -73,10 +73,12 @@ void ESM4::TalkingActivator::load(ESM4::Reader& reader) case ESM4::SUB_DSTF: // Destructible end case ESM4::SUB_FNAM: case ESM4::SUB_PNAM: - case ESM4::SUB_MODT: // texture file hash? + case ESM4::SUB_MODT: // Model data + case ESM4::SUB_MODC: + case ESM4::SUB_MODS: + case ESM4::SUB_MODF: // Model data end case ESM4::SUB_OBND: case ESM4::SUB_VMAD: - case ESM4::SUB_MODS: reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadterm.cpp b/components/esm4/loadterm.cpp index c33afed2d6..d2b11b98c0 100644 --- a/components/esm4/loadterm.cpp +++ b/components/esm4/loadterm.cpp @@ -70,7 +70,10 @@ void ESM4::Terminal::load(ESM4::Reader& reader) case ESM4::SUB_CTDA: case ESM4::SUB_INAM: case ESM4::SUB_ITXT: // Menu Item - case ESM4::SUB_MODT: // texture hash? + case ESM4::SUB_MODT: // Model data + case ESM4::SUB_MODC: + case ESM4::SUB_MODS: + case ESM4::SUB_MODF: // Model data end case ESM4::SUB_SCDA: case ESM4::SUB_SCHR: case ESM4::SUB_SCRO: @@ -80,7 +83,6 @@ void ESM4::Terminal::load(ESM4::Reader& reader) case ESM4::SUB_SLSD: case ESM4::SUB_TNAM: case ESM4::SUB_OBND: - case ESM4::SUB_MODS: // FONV case ESM4::SUB_PRPS: // FO4 case ESM4::SUB_PTRN: // FO4 reader.skipSubRecordData(); diff --git a/components/esm4/loadtree.cpp b/components/esm4/loadtree.cpp index 42ae3ce543..9290ae79c4 100644 --- a/components/esm4/loadtree.cpp +++ b/components/esm4/loadtree.cpp @@ -53,7 +53,10 @@ void ESM4::Tree::load(ESM4::Reader& reader) case ESM4::SUB_MODB: reader.get(mBoundRadius); break; - case ESM4::SUB_MODT: + case ESM4::SUB_MODT: // Model data + case ESM4::SUB_MODC: + case ESM4::SUB_MODS: + case ESM4::SUB_MODF: // Model data end case ESM4::SUB_CNAM: case ESM4::SUB_BNAM: case ESM4::SUB_SNAM: diff --git a/components/esm4/loadweap.cpp b/components/esm4/loadweap.cpp index f266291fc2..9cd134326b 100644 --- a/components/esm4/loadweap.cpp +++ b/components/esm4/loadweap.cpp @@ -109,7 +109,10 @@ void ESM4::Weapon::load(ESM4::Reader& reader) case ESM4::SUB_ZNAM: reader.getFormId(mDropSound); break; - case ESM4::SUB_MODT: + case ESM4::SUB_MODT: // Model data + case ESM4::SUB_MODC: + case ESM4::SUB_MODS: + case ESM4::SUB_MODF: // Model data end case ESM4::SUB_BAMT: case ESM4::SUB_BIDS: case ESM4::SUB_INAM: @@ -132,7 +135,6 @@ void ESM4::Weapon::load(ESM4::Reader& reader) case ESM4::SUB_WNAM: case ESM4::SUB_XNAM: // Dawnguard only? case ESM4::SUB_NNAM: - case ESM4::SUB_MODS: case ESM4::SUB_NAM0: // FO3 case ESM4::SUB_REPL: // FO3 case ESM4::SUB_MOD2: // FO3 diff --git a/components/esm4/loadwrld.cpp b/components/esm4/loadwrld.cpp index ec0ff908cd..2df127c8d3 100644 --- a/components/esm4/loadwrld.cpp +++ b/components/esm4/loadwrld.cpp @@ -164,13 +164,16 @@ void ESM4::World::load(ESM4::Reader& reader) case ESM4::SUB_XLCN: case ESM4::SUB_NAM3: case ESM4::SUB_NAM4: - case ESM4::SUB_MODL: case ESM4::SUB_NAMA: case ESM4::SUB_ONAM: case ESM4::SUB_TNAM: case ESM4::SUB_UNAM: case ESM4::SUB_XWEM: - case ESM4::SUB_MODT: // from Dragonborn onwards? + case ESM4::SUB_MODL: // Model data start + case ESM4::SUB_MODT: + case ESM4::SUB_MODC: + case ESM4::SUB_MODS: + case ESM4::SUB_MODF: // Model data end case ESM4::SUB_INAM: // FO3 case ESM4::SUB_NNAM: // FO3 case ESM4::SUB_XNAM: // FO3 From 2b9b05c01062ace5639acaf50fbe04ce09cf3204 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 16 Aug 2023 06:10:34 +0300 Subject: [PATCH 23/64] Maybe load FO4 container records --- components/esm4/loadcont.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/components/esm4/loadcont.cpp b/components/esm4/loadcont.cpp index 2aa7f57b5d..d650678093 100644 --- a/components/esm4/loadcont.cpp +++ b/components/esm4/loadcont.cpp @@ -91,7 +91,13 @@ void ESM4::Container::load(ESM4::Reader& reader) case ESM4::SUB_DSTA: case ESM4::SUB_DSTD: case ESM4::SUB_DSTF: // Destructible end + case ESM4::SUB_KSIZ: + case ESM4::SUB_KWDA: + case ESM4::SUB_ONAM: case ESM4::SUB_RNAM: // FONV + case ESM4::SUB_TNAM: + case ESM4::SUB_FTYP: // FO4 + case ESM4::SUB_NTRM: // FO4 case ESM4::SUB_PRPS: // FO4 case ESM4::SUB_PTRN: // FO4 reader.skipSubRecordData(); From 24d7a096ba7c268f42823b30e968fe3c88eedecd Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 16 Aug 2023 06:18:17 +0300 Subject: [PATCH 24/64] Maybe load FO4 door records --- components/esm4/loaddoor.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/components/esm4/loaddoor.cpp b/components/esm4/loaddoor.cpp index 8ee771fd0c..7fe38b6b7a 100644 --- a/components/esm4/loaddoor.cpp +++ b/components/esm4/loaddoor.cpp @@ -86,6 +86,11 @@ void ESM4::Door::load(ESM4::Reader& reader) case ESM4::SUB_DSTA: case ESM4::SUB_DSTD: case ESM4::SUB_DSTF: // Destructible end + case ESM4::SUB_KSIZ: + case ESM4::SUB_KWDA: + case ESM4::SUB_CNAM: // FO4 + case ESM4::SUB_NTRM: // FO4 + case ESM4::SUB_ONAM: // FO4 case ESM4::SUB_PTRN: // FO4 reader.skipSubRecordData(); break; From f2449df2f728f3368c455bbf14bd1ece87a4529d Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 16 Aug 2023 06:43:23 +0300 Subject: [PATCH 25/64] Maybe load FO4 light records --- components/esm4/loadligh.cpp | 41 +++++++++++++++++++----------------- components/esm4/loadligh.hpp | 15 +++++++------ 2 files changed, 31 insertions(+), 25 deletions(-) diff --git a/components/esm4/loadligh.cpp b/components/esm4/loadligh.cpp index 79ff307dc0..0848ee8435 100644 --- a/components/esm4/loadligh.cpp +++ b/components/esm4/loadligh.cpp @@ -35,9 +35,6 @@ void ESM4::Light::load(ESM4::Reader& reader) { mId = reader.getFormIdFromHeader(); 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(); @@ -51,31 +48,31 @@ void ESM4::Light::load(ESM4::Reader& reader) break; case ESM4::SUB_DATA: { - // FIXME: TES4 might be uint32 as well, need to check - if (isFONV || (esmVer == ESM::VER_094 && subHdr.dataSize == 32) /*FO3*/) + if (subHdr.dataSize != 32 && subHdr.dataSize != 48 && subHdr.dataSize != 64) { - reader.get(mData.time); // uint32 + reader.skipSubRecordData(); + break; } - else - reader.get(mData.duration); // float - + reader.get(mData.time); reader.get(mData.radius); reader.get(mData.colour); reader.get(mData.flags); - // if (reader.esmVersion() == ESM::VER_094 || reader.esmVersion() == ESM::VER_170) - if (subHdr.dataSize == 48) + reader.get(mData.falloff); + reader.get(mData.FOV); + // TES5, FO4 + if (subHdr.dataSize >= 48) { - reader.get(mData.falloff); - reader.get(mData.FOV); reader.get(mData.nearClip); reader.get(mData.frequency); reader.get(mData.intensityAmplitude); reader.get(mData.movementAmplitude); - } - else if (subHdr.dataSize == 32) // TES4 - { - reader.get(mData.falloff); - reader.get(mData.FOV); + if (subHdr.dataSize == 64) + { + reader.get(mData.constant); + reader.get(mData.scalar); + reader.get(mData.exponent); + reader.get(mData.godRaysNearClip); + } } reader.get(mData.value); reader.get(mData.weight); @@ -104,7 +101,7 @@ void ESM4::Light::load(ESM4::Reader& reader) case ESM4::SUB_MODS: case ESM4::SUB_MODF: // Model data end case ESM4::SUB_OBND: - case ESM4::SUB_VMAD: // Dragonborn only? + case ESM4::SUB_VMAD: case ESM4::SUB_DAMC: // Destructible case ESM4::SUB_DEST: case ESM4::SUB_DMDC: @@ -114,8 +111,14 @@ void ESM4::Light::load(ESM4::Reader& reader) case ESM4::SUB_DSTA: case ESM4::SUB_DSTD: case ESM4::SUB_DSTF: // Destructible end + case ESM4::SUB_KSIZ: + case ESM4::SUB_KWDA: + case ESM4::SUB_LNAM: // FO4 + case ESM4::SUB_MICO: // FO4 + case ESM4::SUB_NAM0: // FO4 case ESM4::SUB_PRPS: // FO4 case ESM4::SUB_PTRN: // FO4 + case ESM4::SUB_WGDR: // FO4 reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadligh.hpp b/components/esm4/loadligh.hpp index ea33a91231..5845f3769a 100644 --- a/components/esm4/loadligh.hpp +++ b/components/esm4/loadligh.hpp @@ -56,8 +56,7 @@ namespace ESM4 struct Data { - std::uint32_t time; // FO/FONV only - float duration = -1; + std::int32_t time; std::uint32_t radius; std::uint32_t colour; // RGBA // flags: @@ -74,10 +73,14 @@ namespace ESM4 std::int32_t flags; float falloff = 1.f; float FOV = 90; // FIXME: FOV in degrees or radians? - float nearClip; // TES5 only - float frequency; // TES5 only - float intensityAmplitude; // TES5 only - float movementAmplitude; // TES5 only + float nearClip; // TES5+ + float frequency; // TES5+ + float intensityAmplitude; // TES5+ + float movementAmplitude; // TES5+ + float constant; // FO4 + float scalar; // FO4 + float exponent; // FO4 + float godRaysNearClip; // FO4 std::uint32_t value; // gold float weight; }; From a3069ea8633a76d45a0efa4013f7b415a625ed98 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 16 Aug 2023 06:53:53 +0300 Subject: [PATCH 26/64] Maybe load FO4 misc records --- components/esm4/loadmisc.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/components/esm4/loadmisc.cpp b/components/esm4/loadmisc.cpp index 646154309e..6dfd69148d 100644 --- a/components/esm4/loadmisc.cpp +++ b/components/esm4/loadmisc.cpp @@ -89,6 +89,9 @@ void ESM4::MiscItem::load(ESM4::Reader& reader) case ESM4::SUB_DSTA: case ESM4::SUB_DSTD: case ESM4::SUB_DSTF: // Destructible end + case ESM4::SUB_CDIX: // FO4 + case ESM4::SUB_CVPA: // FO4 + case ESM4::SUB_FIMD: // FO4 case ESM4::SUB_PTRN: // FO4 reader.skipSubRecordData(); break; From 4d3edec59fd12c7340917787ac2df134dcb2b6ec Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 16 Aug 2023 07:03:29 +0300 Subject: [PATCH 27/64] Maybe load FO4 static collection records --- components/esm4/loadscol.cpp | 4 ++++ components/esm4/loadscol.hpp | 1 + 2 files changed, 5 insertions(+) diff --git a/components/esm4/loadscol.cpp b/components/esm4/loadscol.cpp index 6f1aef0202..dea900fe17 100644 --- a/components/esm4/loadscol.cpp +++ b/components/esm4/loadscol.cpp @@ -46,6 +46,9 @@ void ESM4::StaticCollection::load(ESM4::Reader& reader) case ESM4::SUB_EDID: reader.getZString(mEditorId); break; + case ESM4::SUB_FULL: + reader.getLocalizedString(mFullName); + break; case ESM4::SUB_OBND: case ESM4::SUB_MODL: // Model data start case ESM4::SUB_MODT: @@ -54,6 +57,7 @@ void ESM4::StaticCollection::load(ESM4::Reader& reader) case ESM4::SUB_MODF: // Model data end case ESM4::SUB_ONAM: case ESM4::SUB_DATA: + case ESM4::SUB_FLTR: // FO4 case ESM4::SUB_PTRN: // FO4 reader.skipSubRecordData(); break; diff --git a/components/esm4/loadscol.hpp b/components/esm4/loadscol.hpp index 3be0f0d70f..f3ae3a622e 100644 --- a/components/esm4/loadscol.hpp +++ b/components/esm4/loadscol.hpp @@ -46,6 +46,7 @@ namespace ESM4 std::uint32_t mFlags; // from the header, see enum type RecordFlag for details std::string mEditorId; + std::string mFullName; void load(ESM4::Reader& reader); // void save(ESM4::Writer& writer) const; From 90d4f375b83008757b6679bcfc4c9f4b6b67c101 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 16 Aug 2023 07:15:57 +0300 Subject: [PATCH 28/64] Maybe load FO4 moveable static records --- components/esm4/loadmstt.cpp | 7 ++++++- components/esm4/loadmstt.hpp | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/components/esm4/loadmstt.cpp b/components/esm4/loadmstt.cpp index 75a4afe76e..14091e96f0 100644 --- a/components/esm4/loadmstt.cpp +++ b/components/esm4/loadmstt.cpp @@ -44,6 +44,9 @@ void ESM4::MovableStatic::load(ESM4::Reader& reader) case ESM4::SUB_EDID: reader.getZString(mEditorId); break; + case ESM4::SUB_FULL: + reader.getLocalizedString(mFullName); + break; case ESM4::SUB_MODL: reader.getZString(mModel); break; @@ -63,11 +66,13 @@ void ESM4::MovableStatic::load(ESM4::Reader& reader) case ESM4::SUB_DSTD: case ESM4::SUB_DSTF: // Destructible end case ESM4::SUB_OBND: // object bounds + case ESM4::SUB_KSIZ: + case ESM4::SUB_KWDA: + case ESM4::SUB_VMAD: case ESM4::SUB_MODT: // Model data case ESM4::SUB_MODC: case ESM4::SUB_MODS: case ESM4::SUB_MODF: // Model data end - case ESM4::SUB_FULL: case ESM4::SUB_MODB: case ESM4::SUB_PRPS: case ESM4::SUB_PTRN: // FO4 diff --git a/components/esm4/loadmstt.hpp b/components/esm4/loadmstt.hpp index 1e5b074b68..cb6a4bc01d 100644 --- a/components/esm4/loadmstt.hpp +++ b/components/esm4/loadmstt.hpp @@ -43,6 +43,7 @@ namespace ESM4 std::uint32_t mFlags; // from the header, see enum type RecordFlag for details std::string mEditorId; + std::string mFullName; std::string mModel; std::int8_t mData; From a9454fdc0a34206872ddfb8b263f0545688ee955 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 16 Aug 2023 07:21:52 +0300 Subject: [PATCH 29/64] Improve FO3 idle marker record loading --- components/esm4/loadidlm.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/components/esm4/loadidlm.cpp b/components/esm4/loadidlm.cpp index 4b476c46f0..3f1ed9518c 100644 --- a/components/esm4/loadidlm.cpp +++ b/components/esm4/loadidlm.cpp @@ -79,10 +79,13 @@ void ESM4::IdleMarker::load(ESM4::Reader& reader) reader.getZString(mModel); break; case ESM4::SUB_OBND: // object bounds + case ESM4::SUB_KSIZ: + case ESM4::SUB_KWDA: case ESM4::SUB_MODT: // Model data case ESM4::SUB_MODC: case ESM4::SUB_MODS: case ESM4::SUB_MODF: // Model data end + case ESM4::SUB_QNAM: reader.skipSubRecordData(); break; default: From 4237da5dfda143d1a56ae6a44d25c4f9e8b072b3 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 16 Aug 2023 07:31:09 +0300 Subject: [PATCH 30/64] Maybe load FO4 flora records --- components/esm4/loadflor.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/components/esm4/loadflor.cpp b/components/esm4/loadflor.cpp index b3ea69e0d0..69f1c82b13 100644 --- a/components/esm4/loadflor.cpp +++ b/components/esm4/loadflor.cpp @@ -71,6 +71,8 @@ void ESM4::Flora::load(ESM4::Reader& reader) case ESM4::SUB_MODF: // Model data end case ESM4::SUB_FNAM: case ESM4::SUB_OBND: + case ESM4::SUB_KSIZ: + case ESM4::SUB_KWDA: case ESM4::SUB_PNAM: case ESM4::SUB_RNAM: case ESM4::SUB_VMAD: @@ -85,6 +87,7 @@ void ESM4::Flora::load(ESM4::Reader& reader) case ESM4::SUB_DSTF: // Destructible end case ESM4::SUB_PRPS: // FO4 case ESM4::SUB_PTRN: // FO4 + case ESM4::SUB_ATTX: // FO4 reader.skipSubRecordData(); break; default: From a188a90023af31c57c384a0bc9ff8135451ca2f8 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 16 Aug 2023 07:47:21 +0300 Subject: [PATCH 31/64] Maybe load FO4 furniture records --- components/esm4/loadfurn.cpp | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/components/esm4/loadfurn.cpp b/components/esm4/loadfurn.cpp index 9f00827772..40ea04955e 100644 --- a/components/esm4/loadfurn.cpp +++ b/components/esm4/loadfurn.cpp @@ -45,8 +45,14 @@ void ESM4::Furniture::load(ESM4::Reader& reader) reader.getZString(mEditorId); break; case ESM4::SUB_FULL: - reader.getLocalizedString(mFullName); + { + std::string name; + reader.getLocalizedString(name); + // FIXME: subsequent FULL subrecords name object combinations (FO4) + if (mFullName.empty()) + mFullName = name; break; + } case ESM4::SUB_MODL: reader.getZString(mModel); break; @@ -89,7 +95,23 @@ void ESM4::Furniture::load(ESM4::Reader& reader) case ESM4::SUB_CTDA: case ESM4::SUB_CIS1: case ESM4::SUB_CIS2: + case ESM4::SUB_APPR: // FO4 + case ESM4::SUB_ATTX: // FO4 + case ESM4::SUB_CITC: // FO4 + case ESM4::SUB_CNTO: // FO4 + case ESM4::SUB_COCT: // FO4 + case ESM4::SUB_COED: // FO4 + case ESM4::SUB_FTYP: // FO4 + case ESM4::SUB_NAM1: // FO4 + case ESM4::SUB_NTRM: // FO4 + case ESM4::SUB_NVNM: // FO4 case ESM4::SUB_PTRN: // FO4 + case ESM4::SUB_SNAM: // FO4 + case ESM4::SUB_WNAM: // FO4 + case ESM4::SUB_OBTE: // FO4 object template start + case ESM4::SUB_OBTF: + case ESM4::SUB_OBTS: + case ESM4::SUB_STOP: // FO4 object template end reader.skipSubRecordData(); break; default: From ad8d691352881dfd2cd4c9aae47b70f748db8e99 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 16 Aug 2023 07:52:48 +0300 Subject: [PATCH 32/64] Load object templates in FO4 NPC and weapon records --- components/esm4/loadnpc.cpp | 4 ++++ components/esm4/loadweap.cpp | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/components/esm4/loadnpc.cpp b/components/esm4/loadnpc.cpp index 2fb15a18b5..b43c42d57a 100644 --- a/components/esm4/loadnpc.cpp +++ b/components/esm4/loadnpc.cpp @@ -279,6 +279,10 @@ void ESM4::Npc::load(ESM4::Reader& reader) case ESM4::SUB_COED: // FO3 case ESM4::SUB_PRPS: // FO4 case ESM4::SUB_PTRN: // FO4 + case ESM4::SUB_OBTE: // FO4 object template start + case ESM4::SUB_OBTF: + case ESM4::SUB_OBTS: + case ESM4::SUB_STOP: // FO4 object template end reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadweap.cpp b/components/esm4/loadweap.cpp index 9cd134326b..fd0b270495 100644 --- a/components/esm4/loadweap.cpp +++ b/components/esm4/loadweap.cpp @@ -183,6 +183,10 @@ void ESM4::Weapon::load(ESM4::Reader& reader) case ESM4::SUB_WNM7: // FONV case ESM4::SUB_EFSD: // FONV DeadMoney case ESM4::SUB_PTRN: // FO4 + case ESM4::SUB_OBTE: // FO4 object template start + case ESM4::SUB_OBTF: + case ESM4::SUB_OBTS: + case ESM4::SUB_STOP: // FO4 object template end reader.skipSubRecordData(); break; default: From dcb791083e52f23fe4245f9e41a67af6fc3377fa Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 16 Aug 2023 08:08:23 +0300 Subject: [PATCH 33/64] Maybe load FO4 weapon records --- components/esm4/loadarmo.cpp | 1 - components/esm4/loadweap.cpp | 18 +++++++++++++++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/components/esm4/loadarmo.cpp b/components/esm4/loadarmo.cpp index 9f304a884f..6c4e1e9a3e 100644 --- a/components/esm4/loadarmo.cpp +++ b/components/esm4/loadarmo.cpp @@ -92,7 +92,6 @@ void ESM4::Armor::load(ESM4::Reader& reader) mAddOns.resize(currentIndex + 1); reader.getFormId(mAddOns[currentIndex]); } - } else { diff --git a/components/esm4/loadweap.cpp b/components/esm4/loadweap.cpp index fd0b270495..2b80305690 100644 --- a/components/esm4/loadweap.cpp +++ b/components/esm4/loadweap.cpp @@ -141,9 +141,11 @@ void ESM4::Weapon::load(ESM4::Reader& reader) case ESM4::SUB_MO2T: // FO3 case ESM4::SUB_MO2S: // FO3 case ESM4::SUB_NAM6: // FO3 - case ESM4::SUB_MOD4: // FO3 - case ESM4::SUB_MO4T: // FO3 - case ESM4::SUB_MO4S: // FO3 + case ESM4::SUB_MOD4: // First person model data + case ESM4::SUB_MO4T: + case ESM4::SUB_MO4S: + case ESM4::SUB_MO4C: + case ESM4::SUB_MO4F: // First person model data end case ESM4::SUB_BIPL: // FO3 case ESM4::SUB_NAM7: // FO3 case ESM4::SUB_MOD3: // FO3 @@ -182,7 +184,17 @@ void ESM4::Weapon::load(ESM4::Reader& reader) case ESM4::SUB_WNM6: // FONV case ESM4::SUB_WNM7: // FONV case ESM4::SUB_EFSD: // FONV DeadMoney + case ESM4::SUB_APPR: // FO4 + case ESM4::SUB_DAMA: // FO4 + case ESM4::SUB_FLTR: // FO4 + case ESM4::SUB_FNAM: // FO4 + case ESM4::SUB_INRD: // FO4 + case ESM4::SUB_LNAM: // FO4 + case ESM4::SUB_MASE: // FO4 case ESM4::SUB_PTRN: // FO4 + case ESM4::SUB_STCP: // FO4 + case ESM4::SUB_WAMD: // FO4 + case ESM4::SUB_WZMD: // FO4 case ESM4::SUB_OBTE: // FO4 object template start case ESM4::SUB_OBTF: case ESM4::SUB_OBTS: From e9f9da98cf2d9f67ec85d09ff8a66308e9797ea7 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 16 Aug 2023 09:05:14 +0300 Subject: [PATCH 34/64] Maybe load FO4 ammunition records --- components/esm4/loadammo.cpp | 15 +++++++++++++++ components/esm4/loadammo.hpp | 1 + 2 files changed, 16 insertions(+) diff --git a/components/esm4/loadammo.cpp b/components/esm4/loadammo.cpp index bc05d007e6..28da90255b 100644 --- a/components/esm4/loadammo.cpp +++ b/components/esm4/loadammo.cpp @@ -75,6 +75,12 @@ void ESM4::Ammunition::load(ESM4::Reader& reader) if (subHdr.dataSize == 20) reader.get(mData.mWeight); } + // FO4 + else if (subHdr.dataSize == 8) + { + reader.get(mData.mValue); + reader.get(mData.mWeight); + } else { reader.skipSubRecordData(); @@ -94,6 +100,13 @@ void ESM4::Ammunition::load(ESM4::Reader& reader) reader.skipSubRecordData(); } break; + case ESM4::SUB_DNAM: + reader.getFormId(mData.mProjectile); + reader.get(mData.mFlags); + mData.mFlags &= 0xFF; + reader.get(mData.mDamage); + reader.get(mData.mHealth); + break; case ESM4::SUB_ICON: reader.getZString(mIcon); break; @@ -150,6 +163,8 @@ void ESM4::Ammunition::load(ESM4::Reader& reader) case ESM4::SUB_DSTD: case ESM4::SUB_DSTF: // Destructible end case ESM4::SUB_PTRN: // FO4 + case ESM4::SUB_NAM1: // FO4 casing model data + case ESM4::SUB_NAM2: // reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadammo.hpp b/components/esm4/loadammo.hpp index efeca3c156..b85c39a9aa 100644 --- a/components/esm4/loadammo.hpp +++ b/components/esm4/loadammo.hpp @@ -53,6 +53,7 @@ namespace ESM4 ESM::FormId mProjectile; ESM::FormId mConsumedAmmo; float mConsumedPercentage{ 0.f }; + std::uint32_t mHealth{ 0u }; }; ESM::FormId mId; // from the header From 4dc4add62dd156c29aee99dd7244d167652ab49a Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 16 Aug 2023 11:34:29 +0300 Subject: [PATCH 35/64] Maybe load FO4 NPC records --- components/esm4/actor.hpp | 15 ++++++++ components/esm4/loadnpc.cpp | 70 +++++++++++++++++++++++++++++-------- components/esm4/loadnpc.hpp | 1 + 3 files changed, 72 insertions(+), 14 deletions(-) diff --git a/components/esm4/actor.hpp b/components/esm4/actor.hpp index 9a408ca33d..5079182557 100644 --- a/components/esm4/actor.hpp +++ b/components/esm4/actor.hpp @@ -100,11 +100,26 @@ namespace ESM4 std::uint16_t bleedoutOverride; }; + struct ACBS_FO4 + { + std::uint32_t flags; + std::int16_t xpOffset; + std::int16_t levelOrMult; + std::uint16_t calcMinlevel; + std::uint16_t calcMaxlevel; + std::int16_t dispositionBase; + std::uint16_t templateFlags; + std::uint16_t bleedoutOverride; + std::uint16_t padding; + }; + + union ActorBaseConfig { ACBS_TES4 tes4; ACBS_FO3 fo3; ACBS_TES5 tes5; + ACBS_FO4 fo4; }; struct ActorFaction diff --git a/components/esm4/loadnpc.cpp b/components/esm4/loadnpc.cpp index b43c42d57a..5bbb5ae0a0 100644 --- a/components/esm4/loadnpc.cpp +++ b/components/esm4/loadnpc.cpp @@ -73,7 +73,11 @@ void ESM4::Npc::load(ESM4::Reader& reader) break; case ESM4::SUB_SNAM: { - reader.get(mFaction); + // FO4, FO76 + if (subHdr.dataSize == 5) + reader.get(&mFaction, 5); + else + reader.get(mFaction); reader.adjustFormId(mFaction.faction); break; } @@ -99,7 +103,7 @@ void ESM4::Npc::load(ESM4::Reader& reader) // case ESM4::SUB_AIDT: { - if (esmVer == ESM::VER_094 || esmVer == ESM::VER_170 || mIsFONV) + if (subHdr.dataSize != 12) { reader.skipSubRecordData(); // FIXME: process the subrecord rather than skip break; @@ -110,24 +114,26 @@ void ESM4::Npc::load(ESM4::Reader& reader) } case ESM4::SUB_ACBS: { - // if (esmVer == ESM::VER_094 || esmVer == ESM::VER_170 || mIsFONV) if (subHdr.dataSize == 24) reader.get(mBaseConfig); - else - reader.get(&mBaseConfig, 16); // TES4 + // TES4 + else if (subHdr.dataSize == 16) + reader.get(&mBaseConfig, 16); + // FO4 + else if (subHdr.dataSize == 20) + reader.get(&mBaseConfig, 20); break; } case ESM4::SUB_DATA: { - if (esmVer == ESM::VER_094 || esmVer == ESM::VER_170 || mIsFONV) - { - if (subHdr.dataSize != 0) // FIXME FO3 - reader.skipSubRecordData(); - break; // zero length - } + if (subHdr.dataSize == 0) + break; - reader.get(&mData, 33); // FIXME: check packing + if (subHdr.dataSize == 33) + reader.get(&mData, 33); // FIXME: check packing + else // FIXME FO3 + reader.skipSubRecordData(); break; } case ESM4::SUB_ZNAM: @@ -144,6 +150,7 @@ void ESM4::Npc::load(ESM4::Reader& reader) break; case ESM4::SUB_WNAM: { + // FIXME: should be read into mWornArmor for FO4 if (reader.esmVersion() == ESM::VER_094 || reader.esmVersion() == ESM::VER_170) reader.getFormId(mWornArmor); else @@ -218,6 +225,11 @@ void ESM4::Npc::load(ESM4::Reader& reader) break; } + case ESM4::SUB_BCLF: + { + reader.getFormId(mBeardColourId); + break; + } case ESM4::SUB_COCT: // TES5 { std::uint32_t count; @@ -277,12 +289,42 @@ void ESM4::Npc::load(ESM4::Reader& reader) case ESM4::SUB_EAMT: // FO3 case ESM4::SUB_NAM4: // FO3 case ESM4::SUB_COED: // FO3 + case ESM4::SUB_APPR: // FO4 + case ESM4::SUB_ATKS: // FO4 + case ESM4::SUB_ATKT: // FO4 + case ESM4::SUB_ATKW: // FO4 + case ESM4::SUB_ATTX: // FO4 + case ESM4::SUB_FTYP: // FO4 + case ESM4::SUB_LTPT: // FO4 + case ESM4::SUB_LTPC: // FO4 + case ESM4::SUB_MWGT: // FO4 + case ESM4::SUB_NTRM: // FO4 + case ESM4::SUB_PFRN: // FO4 case ESM4::SUB_PRPS: // FO4 case ESM4::SUB_PTRN: // FO4 + case ESM4::SUB_STCP: // FO4 + case ESM4::SUB_TETI: // FO4 + case ESM4::SUB_TEND: // FO4 + case ESM4::SUB_TPTA: // FO4 case ESM4::SUB_OBTE: // FO4 object template start - case ESM4::SUB_OBTF: - case ESM4::SUB_OBTS: + case ESM4::SUB_OBTF: // + case ESM4::SUB_OBTS: // case ESM4::SUB_STOP: // FO4 object template end + case ESM4::SUB_OCOR: // FO4 new package lists start + case ESM4::SUB_GWOR: // + case ESM4::SUB_FCPL: // + case ESM4::SUB_RCLR: // FO4 new package lists end + case ESM4::SUB_CS2D: // FO4 actor sound subrecords + case ESM4::SUB_CS2E: // + case ESM4::SUB_CS2F: // + case ESM4::SUB_CS2H: // + case ESM4::SUB_CS2K: // FO4 actor sound subrecords end + case ESM4::SUB_MSDK: // FO4 morph subrecords start + case ESM4::SUB_MSDV: // + case ESM4::SUB_MRSV: // + case ESM4::SUB_FMRI: // + case ESM4::SUB_FMRS: // + case ESM4::SUB_FMIN: // FO4 morph subrecords end reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadnpc.hpp b/components/esm4/loadnpc.hpp index 530b1fdfb7..6f4b3c7e24 100644 --- a/components/esm4/loadnpc.hpp +++ b/components/esm4/loadnpc.hpp @@ -187,6 +187,7 @@ namespace ESM4 float mHairLength; HairColour mHairColour; // TES4/FO3/FONV ESM::FormId mHairColourId; // TES5 + ESM::FormId mBeardColourId; // FO4 ESM::FormId mDeathItem; std::vector mSpell; From cfa19cf719ccd89e1fe2c290920611f871e9797f Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 16 Aug 2023 12:04:12 +0300 Subject: [PATCH 36/64] Maybe load FO4 levelled actor records --- components/esm4/loadlvln.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/components/esm4/loadlvln.cpp b/components/esm4/loadlvln.cpp index b994577b41..febdcbeca9 100644 --- a/components/esm4/loadlvln.cpp +++ b/components/esm4/loadlvln.cpp @@ -95,6 +95,9 @@ void ESM4::LevelledNpc::load(ESM4::Reader& reader) case ESM4::SUB_MODC: case ESM4::SUB_MODS: case ESM4::SUB_MODF: // Model data end + case ESM4::SUB_LLKC: // FO4 + case ESM4::SUB_LVLG: // FO4 + case ESM4::SUB_LVLM: // FO4 reader.skipSubRecordData(); break; default: From 32f8d08dd3f559b0ca08f12743aa4f6012f046f7 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 16 Aug 2023 12:12:30 +0300 Subject: [PATCH 37/64] Maybe load FO4 note records --- components/esm4/loadnote.cpp | 13 ++++++++++++- components/esm4/loadnote.hpp | 5 +++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/components/esm4/loadnote.cpp b/components/esm4/loadnote.cpp index fbfd4031c3..9c1b4b3140 100644 --- a/components/esm4/loadnote.cpp +++ b/components/esm4/loadnote.cpp @@ -53,8 +53,16 @@ void ESM4::Note::load(ESM4::Reader& reader) case ESM4::SUB_ICON: reader.getZString(mIcon); break; - case ESM4::SUB_DATA: case ESM4::SUB_MODB: + reader.get(mBoundRadius); + break; + case ESM4::SUB_YNAM: + reader.getFormId(mPickUpSound); + break; + case ESM4::SUB_ZNAM: + reader.getFormId(mDropSound); + break; + case ESM4::SUB_DATA: case ESM4::SUB_MODT: // Model data case ESM4::SUB_MODC: case ESM4::SUB_MODS: @@ -64,6 +72,9 @@ void ESM4::Note::load(ESM4::Reader& reader) case ESM4::SUB_TNAM: case ESM4::SUB_XNAM: case ESM4::SUB_OBND: + case ESM4::SUB_VMAD: + case ESM4::SUB_DNAM: // FO4 + case ESM4::SUB_PNAM: // FO4 case ESM4::SUB_PTRN: // FO4 reader.skipSubRecordData(); break; diff --git a/components/esm4/loadnote.hpp b/components/esm4/loadnote.hpp index f9d94a6b69..65222521ce 100644 --- a/components/esm4/loadnote.hpp +++ b/components/esm4/loadnote.hpp @@ -48,6 +48,11 @@ namespace ESM4 std::string mModel; std::string mIcon; + float mBoundRadius; + + ESM::FormId mPickUpSound; + ESM::FormId mDropSound; + void load(ESM4::Reader& reader); // void save(ESM4::Writer& writer) const; From 1b29077206dd1ff55b05f904e1a630837829d64e Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 16 Aug 2023 12:37:17 +0300 Subject: [PATCH 38/64] Maybe load FO4 terminal records --- components/esm4/loadterm.cpp | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/components/esm4/loadterm.cpp b/components/esm4/loadterm.cpp index d2b11b98c0..39f26391e8 100644 --- a/components/esm4/loadterm.cpp +++ b/components/esm4/loadterm.cpp @@ -57,7 +57,11 @@ void ESM4::Terminal::load(ESM4::Reader& reader) reader.getFormId(mPasswordNote); break; case ESM4::SUB_SNAM: - reader.getFormId(mSound); + if (subHdr.dataSize == 4) + reader.getFormId(mSound); + // FIXME: FO4 sound marker params + else + reader.skipSubRecordData(); break; case ESM4::SUB_MODL: reader.getZString(mModel); @@ -68,6 +72,8 @@ void ESM4::Terminal::load(ESM4::Reader& reader) case ESM4::SUB_DNAM: // difficulty case ESM4::SUB_ANAM: // flags case ESM4::SUB_CTDA: + case ESM4::SUB_CIS1: + case ESM4::SUB_CIS2: case ESM4::SUB_INAM: case ESM4::SUB_ITXT: // Menu Item case ESM4::SUB_MODT: // Model data @@ -83,8 +89,25 @@ void ESM4::Terminal::load(ESM4::Reader& reader) case ESM4::SUB_SLSD: case ESM4::SUB_TNAM: case ESM4::SUB_OBND: + case ESM4::SUB_VMAD: + case ESM4::SUB_KSIZ: + case ESM4::SUB_KWDA: + case ESM4::SUB_BSIZ: // FO4 + case ESM4::SUB_BTXT: // FO4 + case ESM4::SUB_COCT: // FO4 + case ESM4::SUB_CNTO: // FO4 + case ESM4::SUB_FNAM: // FO4 + case ESM4::SUB_ISIZ: // FO4 + case ESM4::SUB_ITID: // FO4 + case ESM4::SUB_MNAM: // FO4 + case ESM4::SUB_NAM0: // FO4 case ESM4::SUB_PRPS: // FO4 case ESM4::SUB_PTRN: // FO4 + case ESM4::SUB_UNAM: // FO4 + case ESM4::SUB_VNAM: // FO4 + case ESM4::SUB_WBDT: // FO4 + case ESM4::SUB_WNAM: // FO4 + case ESM4::SUB_XMRK: // FO4 reader.skipSubRecordData(); break; default: From bcaa4023152ed4ef70bb8506be6617823f6310c1 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 16 Aug 2023 12:46:00 +0300 Subject: [PATCH 39/64] Maybe load FO4 levelled item records --- components/esm4/loadlvli.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/components/esm4/loadlvli.cpp b/components/esm4/loadlvli.cpp index dcdd45341c..cab8db4a21 100644 --- a/components/esm4/loadlvli.cpp +++ b/components/esm4/loadlvli.cpp @@ -80,6 +80,10 @@ void ESM4::LevelledItem::load(ESM4::Reader& reader) case ESM4::SUB_OBND: // FO3/FONV case ESM4::SUB_COED: // FO3/FONV case ESM4::SUB_LVLG: // FO3/FONV + case ESM4::SUB_LLKC: // FO4 + case ESM4::SUB_LVLM: // FO4 + case ESM4::SUB_LVSG: // FO4 + case ESM4::SUB_ONAM: // FO4 reader.skipSubRecordData(); break; default: From 6c82aef29ffa32a78d74c9f28a638ca75d6a9078 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 16 Aug 2023 13:02:02 +0300 Subject: [PATCH 40/64] Maybe load FO4 region records --- components/esm4/loadregn.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/components/esm4/loadregn.cpp b/components/esm4/loadregn.cpp index 4beb27afea..2f10ea22d8 100644 --- a/components/esm4/loadregn.cpp +++ b/components/esm4/loadregn.cpp @@ -122,6 +122,8 @@ void ESM4::Region::load(ESM4::Reader& reader) case ESM4::SUB_RDSB: // FONV case ESM4::SUB_RDSI: // FONV case ESM4::SUB_NVMI: // TES5 + case ESM4::SUB_ANAM: // FO4 + case ESM4::SUB_RLDM: // FO4 // RDAT skipping... following is a map // RDMP skipping... map name // From 2b1ca84cb22719d128595fe8bb385ee435c70dee Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 16 Aug 2023 13:28:41 +0300 Subject: [PATCH 41/64] Skip FO4 navmesh data --- components/esm4/loadnavi.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/components/esm4/loadnavi.cpp b/components/esm4/loadnavi.cpp index 553e0f2c73..6c8fe94b76 100644 --- a/components/esm4/loadnavi.cpp +++ b/components/esm4/loadnavi.cpp @@ -249,6 +249,12 @@ void ESM4::Navigation::load(ESM4::Reader& reader) } case ESM4::SUB_NVPP: { + // FO4 + if (esmVer == 0x3F800000) + { + reader.skipSubRecordData(); + break; + } std::uint32_t total; std::uint32_t count; reader.get(total); @@ -333,9 +339,9 @@ void ESM4::Navigation::load(ESM4::Reader& reader) } case ESM4::SUB_NVMI: // multiple { - if (esmVer == ESM::VER_094 || esmVer == ESM::VER_170 || isFONV) + if (esmVer == ESM::VER_094 || esmVer == ESM::VER_170 || isFONV || esmVer == 0x3F800000) { - reader.skipSubRecordData(); // FIXME: FO3/FONV have different form of NavMeshInfo + reader.skipSubRecordData(); // FIXME: FO3+ have different form of NavMeshInfo break; } From 5a73b351e269f8e3125d5061edcc717dd1c19a0a Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 16 Aug 2023 13:50:42 +0300 Subject: [PATCH 42/64] Maybe load FO4 cell records --- components/esm4/loadcell.cpp | 64 +++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 30 deletions(-) diff --git a/components/esm4/loadcell.cpp b/components/esm4/loadcell.cpp index 0c320967d8..59d6e1b4d5 100644 --- a/components/esm4/loadcell.cpp +++ b/components/esm4/loadcell.cpp @@ -128,28 +128,16 @@ void ESM4::Cell::load(ESM4::Reader& reader) break; case ESM4::SUB_DATA: { - if (esmVer == ESM::VER_094 || esmVer == ESM::VER_170 || isFONV) - if (subHdr.dataSize == 2) - reader.get(mCellFlags); - else - { - if (subHdr.dataSize != 1) - throw std::runtime_error("CELL unexpected DATA flag size"); - std::uint8_t value = 0; - reader.get(value); - mCellFlags = value; - } + if (subHdr.dataSize == 2) + reader.get(mCellFlags); else { + if (subHdr.dataSize != 1) + throw std::runtime_error("CELL unexpected DATA flag size"); std::uint8_t value = 0; - reader.get(value); // 8 bits in Obvlivion + reader.get(value); mCellFlags = value; } -#if 0 - std::string padding; - padding.insert(0, reader.stackSize()*2, ' '); - std::cout << padding << "flags: " << std::hex << mCellFlags << std::endl; -#endif break; } case ESM4::SUB_XCLR: // for exterior cells @@ -183,21 +171,28 @@ void ESM4::Cell::load(ESM4::Reader& reader) break; case ESM4::SUB_XCLL: { - if (esmVer == ESM::VER_094 || esmVer == ESM::VER_170 || isFONV) + // TES4 + if (subHdr.dataSize == 36) + reader.get(&mLighting, 36); + // FO3, FONV + else if (subHdr.dataSize == 40) + reader.get(mLighting); + // TES5 + else if (subHdr.dataSize == 92) { - if (subHdr.dataSize == 40) // FO3/FONV - reader.get(mLighting); - else if (subHdr.dataSize == 92) // TES5 - { - reader.get(mLighting); - reader.skipSubRecordData(52); // FIXME - } - else - reader.skipSubRecordData(); + reader.get(mLighting); + reader.skipSubRecordData(52); // FIXME + } + // FO4 + else if (subHdr.dataSize == 136) + { + reader.get(mLighting); + reader.skipSubRecordData(96); // FIXME } else - reader.get(&mLighting, 36); // TES4 - + { + reader.skipSubRecordData(); + } break; } case ESM4::SUB_XCMT: @@ -227,9 +222,18 @@ void ESM4::Cell::load(ESM4::Reader& reader) case ESM4::SUB_XEZN: case ESM4::SUB_XWEM: case ESM4::SUB_XILL: - case ESM4::SUB_XRNK: // Oblivion only? + case ESM4::SUB_XRNK: case ESM4::SUB_XCET: // FO3 case ESM4::SUB_IMPF: // FO3 Zeta + case ESM4::SUB_CNAM: // FO4 + case ESM4::SUB_PCMB: // FO4 + case ESM4::SUB_RVIS: // FO4 + case ESM4::SUB_VISI: // FO4 + case ESM4::SUB_XGDR: // FO4 + case ESM4::SUB_XILW: // FO4 + case ESM4::SUB_XCRI: // FO4 + case ESM4::SUB_XPRI: // FO4 + case ESM4::SUB_ZNAM: // FO4 reader.skipSubRecordData(); break; default: From 95488d6ec98be15364ecddcc832d9e4eeca03f50 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 16 Aug 2023 14:26:05 +0300 Subject: [PATCH 43/64] Maybe load FO4 cell references --- components/esm4/loadrefr.cpp | 41 +++++++++++++++++++++++++++--------- components/esm4/loadrefr.hpp | 1 + 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/components/esm4/loadrefr.cpp b/components/esm4/loadrefr.cpp index 5c7ccc2235..c56b1ab7a0 100644 --- a/components/esm4/loadrefr.cpp +++ b/components/esm4/loadrefr.cpp @@ -38,9 +38,6 @@ void ESM4::Reference::load(ESM4::Reader& reader) mFlags = reader.hdr().record.flags; mParent = reader.currCell(); - std::uint32_t esmVer = reader.esmVersion(); - bool isFONV = esmVer == ESM::VER_132 || esmVer == ESM::VER_133 || esmVer == ESM::VER_134; - ESM::FormId mid; ESM::FormId sid; @@ -87,13 +84,23 @@ void ESM4::Reference::load(ESM4::Reader& reader) } case ESM4::SUB_XTEL: { - reader.getFormId(mDoor.destDoor); - reader.get(mDoor.destPos); - if (esmVer == ESM::VER_094 || esmVer == ESM::VER_170 || isFONV) - reader.get(mDoor.flags); // not in Obvlivion - else + if (subHdr.dataSize == 28 || subHdr.dataSize == 32 || subHdr.dataSize == 36) + { + reader.getFormId(mDoor.destDoor); + reader.get(mDoor.destPos); mDoor.flags = 0; - // std::cout << "REFR dest door: " << formIdToString(mDoor.destDoor) << std::endl;// FIXME + if (subHdr.dataSize == 32 || subHdr.dataSize == 36) + { + reader.get(mDoor.flags); + // FO4 + if (subHdr.dataSize == 36) + reader.getFormId(mDoor.transitionInt); + } + } + else + { + reader.skipSubRecordData(); + } break; } case ESM4::SUB_XSED: @@ -201,6 +208,7 @@ void ESM4::Reference::load(ESM4::Reader& reader) break; // FONV case ESM4::SUB_XRDO: // FO3 { + // FIXME: completely different meaning in FO4 reader.get(mRadio.rangeRadius); reader.get(mRadio.broadcastRange); reader.get(mRadio.staticPercentage); @@ -288,7 +296,7 @@ void ESM4::Reference::load(ESM4::Reader& reader) case ESM4::SUB_XTRI: case ESM4::SUB_XWCN: case ESM4::SUB_XWCU: - case ESM4::SUB_XATR: // Dawnguard only? + case ESM4::SUB_XATR: case ESM4::SUB_XHLT: // Unofficial Oblivion Patch case ESM4::SUB_XCHG: // thievery.exp case ESM4::SUB_XHLP: // FO3 @@ -312,6 +320,19 @@ void ESM4::Reference::load(ESM4::Reader& reader) case ESM4::SUB_XSRD: // FONV case ESM4::SUB_WMI1: // FONV case ESM4::SUB_XLRL: // Unofficial Skyrim Patch + case ESM4::SUB_XASP: // FO4 + case ESM4::SUB_XATP: // FO4 + case ESM4::SUB_XBSD: // FO4 + case ESM4::SUB_XCVR: // FO4 + case ESM4::SUB_XCZR: // FO4 + case ESM4::SUB_XLKT: // FO4 + case ESM4::SUB_XLYR: // FO4 + case ESM4::SUB_XMSP: // FO4 + case ESM4::SUB_XPDD: // FO4 + case ESM4::SUB_XPLK: // FO4 + case ESM4::SUB_XRFG: // FO4 + case ESM4::SUB_XWPG: // FO4 + case ESM4::SUB_XWPN: // FO4 // if (mFormId == 0x0007e90f) // XPRM XPOD // if (mBaseObj == 0x17) //XPRM XOCP occlusion plane data XMBO bound half extents reader.skipSubRecordData(); diff --git a/components/esm4/loadrefr.hpp b/components/esm4/loadrefr.hpp index 00ae175b9a..4c9f4e0c77 100644 --- a/components/esm4/loadrefr.hpp +++ b/components/esm4/loadrefr.hpp @@ -61,6 +61,7 @@ namespace ESM4 ESM::FormId destDoor; ESM::Position destPos; std::uint32_t flags = 0; // 0x01 no alarm (only in TES5) + ESM::FormId transitionInt; }; struct RadioStationData From 10e841b00f7d21fe74a8097ce64c96cc262f12b4 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 16 Aug 2023 19:32:11 +0300 Subject: [PATCH 44/64] Fix formatting --- components/esm4/actor.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/components/esm4/actor.hpp b/components/esm4/actor.hpp index 5079182557..769287b9d8 100644 --- a/components/esm4/actor.hpp +++ b/components/esm4/actor.hpp @@ -113,7 +113,6 @@ namespace ESM4 std::uint16_t padding; }; - union ActorBaseConfig { ACBS_TES4 tes4; From 0a514db0b54e70195e711853a21109e62e6c2bc0 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 16 Aug 2023 19:50:58 +0300 Subject: [PATCH 45/64] Skip more FO4 navmesh data --- components/esm4/loadnavm.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/components/esm4/loadnavm.cpp b/components/esm4/loadnavm.cpp index 0032d9b084..46d67f094d 100644 --- a/components/esm4/loadnavm.cpp +++ b/components/esm4/loadnavm.cpp @@ -194,6 +194,7 @@ void ESM4::NavMesh::load(ESM4::Reader& reader) mId = reader.getFormIdFromHeader(); mFlags = reader.hdr().record.flags; + std::uint32_t esmVer = reader.esmVersion(); // std::cout << "NavMesh 0x" << std::hex << this << std::endl; // FIXME std::uint32_t subSize = 0; // for XXXX sub record @@ -210,6 +211,13 @@ void ESM4::NavMesh::load(ESM4::Reader& reader) { case ESM4::SUB_NVNM: { + // FIXME: FO4 appears to have a different format + if (esmVer == 0x3F800000) + { + reader.skipSubRecordData(); + break; + } + NVNMstruct nvnm; nvnm.load(reader); mData.push_back(nvnm); // FIXME try swap @@ -245,6 +253,7 @@ void ESM4::NavMesh::load(ESM4::Reader& reader) case ESM4::SUB_NVGD: // FO3 case ESM4::SUB_NVEX: // FO3 case ESM4::SUB_EDID: // FO3 + case ESM4::SUB_MNAM: // FO4 reader.skipSubRecordData(); break; default: From 8822df7e4a7a06542a67de7bb3fc421a48f79945 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 16 Aug 2023 20:07:05 +0300 Subject: [PATCH 46/64] Maybe load FO4 placed NPC records --- components/esm4/loadachr.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/components/esm4/loadachr.cpp b/components/esm4/loadachr.cpp index 537bb026ac..c52cd55bab 100644 --- a/components/esm4/loadachr.cpp +++ b/components/esm4/loadachr.cpp @@ -93,6 +93,20 @@ void ESM4::ActorCharacter::load(ESM4::Reader& reader) case ESM4::SUB_SCHR: // FO3 case ESM4::SUB_TNAM: // FO3 case ESM4::SUB_XATO: // FONV + case ESM4::SUB_MNAM: // FO4 + case ESM4::SUB_XATP: // FO4 + case ESM4::SUB_XCNT: // FO4 + case ESM4::SUB_XEMI: // FO4 + case ESM4::SUB_XFVC: // FO4 + case ESM4::SUB_XHLT: // FO4 + case ESM4::SUB_XHTW: // FO4 + case ESM4::SUB_XLKT: // FO4 + case ESM4::SUB_XLYR: // FO4 + case ESM4::SUB_XMBR: // FO4 + case ESM4::SUB_XMSP: // FO4 + case ESM4::SUB_XPLK: // FO4 + case ESM4::SUB_XRFG: // FO4 + case ESM4::SUB_XRNK: // FO4 reader.skipSubRecordData(); break; default: From ae828064a49cf6cfe7b846a19f8cd6ffd9c7d573 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 16 Aug 2023 21:16:24 +0300 Subject: [PATCH 47/64] ESM4::NAVM: fix loading of NVNM after XXXX --- components/esm4/loadnavm.cpp | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/components/esm4/loadnavm.cpp b/components/esm4/loadnavm.cpp index 46d67f094d..bd982f4279 100644 --- a/components/esm4/loadnavm.cpp +++ b/components/esm4/loadnavm.cpp @@ -207,14 +207,25 @@ void ESM4::NavMesh::load(ESM4::Reader& reader) #endif while (reader.getSubRecordHeader()) { - switch (reader.subRecordHeader().typeId) + const ESM4::SubRecordHeader& subHdr = reader.subRecordHeader(); + switch (subHdr.typeId) { case ESM4::SUB_NVNM: { - // FIXME: FO4 appears to have a different format if (esmVer == 0x3F800000) { - reader.skipSubRecordData(); + // TODO: check if any valid TES5 plugin prepends XXXX to NVNM + if (subSize) + { + reader.skipSubRecordData(subSize); + reader.updateRecordRead(subSize); + subSize = 0; + } + else + { + // FIXME: FO4 appears to have a different format + reader.skipSubRecordData(); + } break; } @@ -235,7 +246,6 @@ void ESM4::NavMesh::load(ESM4::Reader& reader) } else { - const ESM4::SubRecordHeader& subHdr = reader.subRecordHeader(); Log(Debug::Verbose) << ESM::printName(subHdr.typeId) << " skipping..."; reader.skipSubRecordData(); // FIXME: process the subrecord rather than skip } @@ -257,8 +267,7 @@ void ESM4::NavMesh::load(ESM4::Reader& reader) reader.skipSubRecordData(); break; default: - throw std::runtime_error( - "ESM4::NAVM::load - Unknown subrecord " + ESM::printName(reader.subRecordHeader().typeId)); + throw std::runtime_error("ESM4::NAVM::load - Unknown subrecord " + ESM::printName(subHdr.typeId)); } } // std::cout << "num nvnm " << std::dec << mData.size() << std::endl; // FIXME From 3b3545fa582607a6378879d5f84c58cd7714acfa Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 16 Aug 2023 21:21:38 +0300 Subject: [PATCH 48/64] Fix cell grid and owner subrecord loading for FO4 --- components/esm4/loadachr.cpp | 17 ++++++++++++++++- components/esm4/loadcell.cpp | 32 ++++++++++++++++++++------------ components/esm4/loadrefr.cpp | 17 ++++++++++++++++- 3 files changed, 52 insertions(+), 14 deletions(-) diff --git a/components/esm4/loadachr.cpp b/components/esm4/loadachr.cpp index c52cd55bab..fb2f304a51 100644 --- a/components/esm4/loadachr.cpp +++ b/components/esm4/loadachr.cpp @@ -58,8 +58,23 @@ void ESM4::ActorCharacter::load(ESM4::Reader& reader) reader.get(mScale); break; case ESM4::SUB_XOWN: - reader.getFormId(mOwner); + { + if (subHdr.dataSize == 4 || subHdr.dataSize == 12) + { + reader.getFormId(mOwner); + if (subHdr.dataSize == 12) + { + std::uint32_t dummy; + reader.get(dummy); // Unknown + reader.get(dummy); // Flags + } + } + else + { + reader.skipSubRecordData(); + } break; + } case ESM4::SUB_XESP: reader.getFormId(mEsp.parent); reader.get(mEsp.flags); diff --git a/components/esm4/loadcell.cpp b/components/esm4/loadcell.cpp index 59d6e1b4d5..47afe5bca9 100644 --- a/components/esm4/loadcell.cpp +++ b/components/esm4/loadcell.cpp @@ -30,6 +30,8 @@ #include #include +#include + #include "grouptype.hpp" #include "reader.hpp" // #include "writer.hpp" @@ -71,7 +73,6 @@ void ESM4::Cell::load(ESM4::Reader& reader) // (may be easier to update the context before saving?) reader.setCurrCell(formId); // save for LAND (and other children) to access later std::uint32_t esmVer = reader.esmVersion(); - bool isFONV = esmVer == ESM::VER_132 || esmVer == ESM::VER_133 || esmVer == ESM::VER_134; bool isSkyrim = (esmVer == ESM::VER_170 || esmVer == ESM::VER_094); while (reader.getSubRecordHeader()) @@ -106,16 +107,8 @@ void ESM4::Cell::load(ESM4::Reader& reader) uint32_t flags; reader.get(mX); reader.get(mY); -#if 0 - std::string padding; - padding.insert(0, reader.stackSize()*2, ' '); - std::cout << padding << "CELL group " << ESM4::printLabel(reader.grp().label, reader.grp().type) << std::endl; - std::cout << padding << "CELL formId " << std::hex << reader.hdr().record.id << std::endl; - std::cout << padding << "CELL X " << std::dec << mX << ", Y " << mY << std::endl; -#endif - if (esmVer == ESM::VER_094 || esmVer == ESM::VER_170 || isFONV) - if (subHdr.dataSize == 12) - reader.get(flags); // not in Obvlivion, nor FO3/FONV + if (subHdr.dataSize == 12) + reader.get(flags); // Remember cell grid for later (loading LAND, NAVM which should be CELL temporary children) // Note that grids only apply for external cells. For interior cells use the cell's formid. @@ -155,8 +148,23 @@ void ESM4::Cell::load(ESM4::Reader& reader) break; } case ESM4::SUB_XOWN: - reader.getFormId(mOwner); + { + if (subHdr.dataSize == 4 || subHdr.dataSize == 12) + { + reader.getFormId(mOwner); + if (subHdr.dataSize == 12) + { + std::uint32_t dummy; + reader.get(dummy); // Unknown + reader.get(dummy); // Flags + } + } + else + { + reader.skipSubRecordData(); + } break; + } case ESM4::SUB_XGLB: reader.getFormId(mGlobal); break; // Oblivion only? diff --git a/components/esm4/loadrefr.cpp b/components/esm4/loadrefr.cpp index c56b1ab7a0..63cac33115 100644 --- a/components/esm4/loadrefr.cpp +++ b/components/esm4/loadrefr.cpp @@ -66,8 +66,23 @@ void ESM4::Reference::load(ESM4::Reader& reader) reader.get(mScale); break; case ESM4::SUB_XOWN: - reader.getFormId(mOwner); + { + if (subHdr.dataSize == 4 || subHdr.dataSize == 12) + { + reader.getFormId(mOwner); + if (subHdr.dataSize == 12) + { + std::uint32_t dummy; + reader.get(dummy); // Unknown + reader.get(dummy); // Flags + } + } + else + { + reader.skipSubRecordData(); + } break; + } case ESM4::SUB_XGLB: reader.getFormId(mGlobal); break; From ed75c0b3115b8b3253a526cd1535e45a3d0741df Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 16 Aug 2023 21:55:38 +0300 Subject: [PATCH 49/64] Maybe load FO4 placed grenade subrecords --- components/esm4/loadpgre.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/components/esm4/loadpgre.cpp b/components/esm4/loadpgre.cpp index 8466122528..4e473bd47a 100644 --- a/components/esm4/loadpgre.cpp +++ b/components/esm4/loadpgre.cpp @@ -62,6 +62,7 @@ void ESM4::PlacedGrenade::load(ESM4::Reader& reader) case ESM4::SUB_XPWR: case ESM4::SUB_XDCR: case ESM4::SUB_XLKR: + case ESM4::SUB_XLKT: // FO4 case ESM4::SUB_XCLP: case ESM4::SUB_XAPD: case ESM4::SUB_XAPR: @@ -72,6 +73,21 @@ void ESM4::PlacedGrenade::load(ESM4::Reader& reader) case ESM4::SUB_XIBS: case ESM4::SUB_XSCL: case ESM4::SUB_DATA: + case ESM4::SUB_VMAD: + case ESM4::SUB_MNAM: // FO4 + case ESM4::SUB_XAMC: // FO4 + case ESM4::SUB_XASP: // FO4 + case ESM4::SUB_XATP: // FO4 + case ESM4::SUB_XCVR: // FO4 + case ESM4::SUB_XFVC: // FO4 + case ESM4::SUB_XHTW: // FO4 + case ESM4::SUB_XIS2: // FO4 + case ESM4::SUB_XLOD: // FO4 + case ESM4::SUB_XLRL: // FO4 + case ESM4::SUB_XLRT: // FO4 + case ESM4::SUB_XLYR: // FO4 + case ESM4::SUB_XMSP: // FO4 + case ESM4::SUB_XRFG: // FO4 reader.skipSubRecordData(); break; default: From 47af96eb12c66ea07d9d5d1b2370b1ba6b88f8f2 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 16 Aug 2023 22:33:00 +0300 Subject: [PATCH 50/64] Generalize extended storage subrecord handling --- components/esm4/loadnavm.cpp | 31 +------------------------------ components/esm4/loadwrld.cpp | 15 --------------- components/esm4/reader.cpp | 17 ++++++++++++++--- 3 files changed, 15 insertions(+), 48 deletions(-) diff --git a/components/esm4/loadnavm.cpp b/components/esm4/loadnavm.cpp index bd982f4279..20fcf90982 100644 --- a/components/esm4/loadnavm.cpp +++ b/components/esm4/loadnavm.cpp @@ -196,7 +196,6 @@ void ESM4::NavMesh::load(ESM4::Reader& reader) std::uint32_t esmVer = reader.esmVersion(); // std::cout << "NavMesh 0x" << std::hex << this << std::endl; // FIXME - std::uint32_t subSize = 0; // for XXXX sub record // FIXME: debugging only #if 0 @@ -214,18 +213,7 @@ void ESM4::NavMesh::load(ESM4::Reader& reader) { if (esmVer == 0x3F800000) { - // TODO: check if any valid TES5 plugin prepends XXXX to NVNM - if (subSize) - { - reader.skipSubRecordData(subSize); - reader.updateRecordRead(subSize); - subSize = 0; - } - else - { - // FIXME: FO4 appears to have a different format - reader.skipSubRecordData(); - } + reader.skipSubRecordData(); break; } @@ -237,23 +225,6 @@ void ESM4::NavMesh::load(ESM4::Reader& reader) case ESM4::SUB_ONAM: case ESM4::SUB_PNAM: case ESM4::SUB_NNAM: - { - if (subSize) - { - reader.skipSubRecordData(subSize); // special post XXXX - reader.updateRecordRead(subSize); // WARNING: manual update - subSize = 0; - } - else - { - Log(Debug::Verbose) << ESM::printName(subHdr.typeId) << " skipping..."; - reader.skipSubRecordData(); // FIXME: process the subrecord rather than skip - } - break; - } - case ESM4::SUB_XXXX: - reader.get(subSize); - break; case ESM4::SUB_NVER: // FO3 case ESM4::SUB_DATA: // FO3 case ESM4::SUB_NVVX: // FO3 diff --git a/components/esm4/loadwrld.cpp b/components/esm4/loadwrld.cpp index 2df127c8d3..2a77833a44 100644 --- a/components/esm4/loadwrld.cpp +++ b/components/esm4/loadwrld.cpp @@ -45,8 +45,6 @@ void ESM4::World::load(ESM4::Reader& reader) // corrupted by the use of ignore flag (TODO: should check to verify). reader.setCurrWorld(mId); // save for CELL later - std::uint32_t subSize = 0; // for XXXX sub record - std::uint32_t esmVer = reader.esmVersion(); // bool isTES4 = (esmVer == ESM::VER_080 || esmVer == ESM::VER_100); // bool isFONV = (esmVer == ESM::VER_132 || esmVer == ESM::VER_133 || esmVer == ESM::VER_134); @@ -144,19 +142,6 @@ void ESM4::World::load(ESM4::Reader& reader) reader.get(mParentUseFlags); break; case ESM4::SUB_OFST: - if (subSize) - { - reader.skipSubRecordData(subSize); // special post XXXX - reader.updateRecordRead(subSize); // WARNING: manually update - subSize = 0; - } - else - reader.skipSubRecordData(); // FIXME: process the subrecord rather than skip - - break; - case ESM4::SUB_XXXX: - reader.get(subSize); - break; case ESM4::SUB_RNAM: // multiple case ESM4::SUB_MHDT: case ESM4::SUB_LTMP: diff --git a/components/esm4/reader.cpp b/components/esm4/reader.cpp index 02bd78116f..2e626cc557 100644 --- a/components/esm4/reader.cpp +++ b/components/esm4/reader.cpp @@ -558,9 +558,6 @@ namespace ESM4 { bool result = false; // NOTE: some SubRecords have 0 dataSize (e.g. SUB_RDSD in one of REC_REGN records in Oblivion.esm). - // Also SUB_XXXX has zero dataSize and the following 4 bytes represent the actual dataSize - // - hence it require manual updtes to mCtx.recordRead via updateRecordRead() - // See ESM4::NavMesh and ESM4::World. if (mCtx.recordHeader.record.dataSize - mCtx.recordRead >= sizeof(mCtx.subRecordHeader)) { result = getExact(mCtx.subRecordHeader); @@ -582,6 +579,20 @@ namespace ESM4 return false; } + // Extended storage subrecord redefines the following subrecord's size. + // Would need to redesign the loader to support that, so skip over both subrecords. + if (result && mCtx.subRecordHeader.typeId == ESM4::SUB_XXXX) + { + std::uint32_t extDataSize; + get(extDataSize); + if (!getSubRecordHeader()) + return false; + + skipSubRecordData(extDataSize); + mCtx.recordRead += extDataSize - mCtx.subRecordHeader.dataSize; + return getSubRecordHeader(); + } + return result; } From a2e185d0f9ffdecb834f9a8dca806e4f1414094f Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 16 Aug 2023 22:49:06 +0300 Subject: [PATCH 51/64] Maybe load FO4 worldspace records --- components/esm4/loadwrld.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/components/esm4/loadwrld.cpp b/components/esm4/loadwrld.cpp index 2a77833a44..c0a3044437 100644 --- a/components/esm4/loadwrld.cpp +++ b/components/esm4/loadwrld.cpp @@ -62,9 +62,9 @@ void ESM4::World::load(ESM4::Reader& reader) case ESM4::SUB_FULL: reader.getLocalizedString(mFullName); break; - case ESM4::SUB_WCTR: + case ESM4::SUB_WCTR: // TES5+ reader.get(mCenterCell); - break; // Center cell, TES5 only + break; case ESM4::SUB_WNAM: reader.getFormId(mParent); break; @@ -73,7 +73,7 @@ void ESM4::World::load(ESM4::Reader& reader) break; // sound, Oblivion only? case ESM4::SUB_ICON: reader.getZString(mMapFile); - break; // map filename, Oblivion only? + break; case ESM4::SUB_CNAM: reader.getFormId(mClimate); break; @@ -164,6 +164,8 @@ void ESM4::World::load(ESM4::Reader& reader) case ESM4::SUB_XNAM: // FO3 case ESM4::SUB_IMPS: // FO3 Anchorage case ESM4::SUB_IMPF: // FO3 Anchorage + case ESM4::SUB_CLSZ: // FO4 + case ESM4::SUB_WLEV: // FO4 reader.skipSubRecordData(); break; default: From db66149891ae99312f337d3797f1d5fc1db558d9 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 16 Aug 2023 23:06:46 +0300 Subject: [PATCH 52/64] Skip LAND::MPCD subrecord --- components/esm4/loadland.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/components/esm4/loadland.cpp b/components/esm4/loadland.cpp index d7adfb75a2..f3e4c27681 100644 --- a/components/esm4/loadland.cpp +++ b/components/esm4/loadland.cpp @@ -191,6 +191,9 @@ void ESM4::Land::load(ESM4::Reader& reader) } break; } + case ESM4::SUB_MPCD: // FO4 + reader.skipSubRecordData(); + break; default: throw std::runtime_error("ESM4::LAND::load - Unknown subrecord " + ESM::printName(subHdr.typeId)); } From cb7e9f4a01874184a775cbbcf3de2c77613b16dc Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 16 Aug 2023 23:33:11 +0300 Subject: [PATCH 53/64] Maybe load FO4 quest records --- components/esm4/loadqust.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/components/esm4/loadqust.cpp b/components/esm4/loadqust.cpp index 305a510f61..b7f9b33db9 100644 --- a/components/esm4/loadqust.cpp +++ b/components/esm4/loadqust.cpp @@ -142,6 +142,7 @@ void ESM4::Quest::load(ESM4::Reader& reader) case ESM4::SUB_ALSP: // TES5 case ESM4::SUB_ALST: // TES5 case ESM4::SUB_ALUA: // TES5 + case ESM4::SUB_CIS1: // TES5 case ESM4::SUB_CIS2: // TES5 case ESM4::SUB_CNTO: // TES5 case ESM4::SUB_COCT: // TES5 @@ -155,6 +156,19 @@ void ESM4::Quest::load(ESM4::Reader& reader) case ESM4::SUB_SPOR: // TES5 case ESM4::SUB_VMAD: // TES5 case ESM4::SUB_VTCK: // TES5 + case ESM4::SUB_ALCC: // FO4 + case ESM4::SUB_ALCS: // FO4 + case ESM4::SUB_ALDI: // FO4 + case ESM4::SUB_ALFV: // FO4 + case ESM4::SUB_ALLA: // FO4 + case ESM4::SUB_ALMI: // FO4 + case ESM4::SUB_GNAM: // FO4 + case ESM4::SUB_GWOR: // FO4 + case ESM4::SUB_LNAM: // FO4 + case ESM4::SUB_NAM2: // FO4 + case ESM4::SUB_OCOR: // FO4 + case ESM4::SUB_SNAM: // FO4 + case ESM4::SUB_XNAM: // FO4 reader.skipSubRecordData(); break; default: From b7efdc4addec3aed8d1fff96c182a9a60fece099 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 16 Aug 2023 23:46:42 +0300 Subject: [PATCH 54/64] Use the correct filenames for FO4 string tables --- components/esm4/reader.cpp | 47 +++++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/components/esm4/reader.cpp b/components/esm4/reader.cpp index 2e626cc557..4a78fd21ea 100644 --- a/components/esm4/reader.cpp +++ b/components/esm4/reader.cpp @@ -61,11 +61,11 @@ namespace ESM4 switch (type) { case LocalizedStringType::Strings: - return u8"_English.STRINGS"; + return u8".STRINGS"; case LocalizedStringType::ILStrings: - return u8"_English.ILSTRINGS"; + return u8".ILSTRINGS"; case LocalizedStringType::DLStrings: - return u8"_English.DLSTRINGS"; + return u8".DLSTRINGS"; } throw std::logic_error("Unsupported LocalizedStringType: " + std::to_string(static_cast(type))); @@ -322,34 +322,49 @@ namespace ESM4 void Reader::buildLStringIndex(LocalizedStringType stringType, const std::u8string& prefix) { static const std::filesystem::path strings("Strings"); + const std::u8string language(u8"_En"); + const std::u8string altLanguage(u8"_English"); const std::u8string suffix(getStringsSuffix(stringType)); - std::filesystem::path path = strings / (prefix + suffix); - + std::filesystem::path path = strings / (prefix + language + suffix); if (mVFS != nullptr) { - const std::string vfsPath = Files::pathToUnicodeString(path); + std::string vfsPath = Files::pathToUnicodeString(path); + if (!mVFS->exists(vfsPath)) + { + path = strings / (prefix + altLanguage + suffix); + vfsPath = Files::pathToUnicodeString(path); + } - if (mIgnoreMissingLocalizedStrings && !mVFS->exists(vfsPath)) + if (mVFS->exists(vfsPath)) { - Log(Debug::Warning) << "Ignore missing VFS strings file: " << vfsPath; + const Files::IStreamPtr stream = mVFS->get(vfsPath); + buildLStringIndex(stringType, *stream); return; } - const Files::IStreamPtr stream = mVFS->get(vfsPath); - buildLStringIndex(stringType, *stream); - return; + if (mIgnoreMissingLocalizedStrings) + { + Log(Debug::Warning) << "Ignore missing VFS strings file: " << vfsPath; + return; + } } - const std::filesystem::path fsPath = mCtx.filename.parent_path() / path; + std::filesystem::path fsPath = mCtx.filename.parent_path() / path; + if (!std::filesystem::exists(fsPath)) + { + path = strings / (prefix + altLanguage + suffix); + fsPath = mCtx.filename.parent_path() / path; + } - if (mIgnoreMissingLocalizedStrings && !std::filesystem::exists(fsPath)) + if (std::filesystem::exists(fsPath)) { - Log(Debug::Warning) << "Ignore missing strings file: " << fsPath; + const Files::IStreamPtr stream = Files::openConstrainedFileStream(fsPath); + buildLStringIndex(stringType, *stream); return; } - const Files::IStreamPtr stream = Files::openConstrainedFileStream(fsPath); - buildLStringIndex(stringType, *stream); + if (mIgnoreMissingLocalizedStrings) + Log(Debug::Warning) << "Ignore missing strings file: " << fsPath; } void Reader::buildLStringIndex(LocalizedStringType stringType, std::istream& stream) From f302f06e98fd6afd2ffb7e77b6ddf2b9325b4754 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Thu, 17 Aug 2023 00:09:21 +0300 Subject: [PATCH 55/64] Maybe load FO4 dialogue records The entirety of Fallout4.esm can be read now (well, in esmtool, at least) --- components/esm4/loaddial.cpp | 3 ++- components/esm4/loadinfo.cpp | 20 +++++++++++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/components/esm4/loaddial.cpp b/components/esm4/loaddial.cpp index 9f7950e40c..19e1099482 100644 --- a/components/esm4/loaddial.cpp +++ b/components/esm4/loaddial.cpp @@ -46,7 +46,7 @@ void ESM4::Dialogue::load(ESM4::Reader& reader) reader.getZString(mEditorId); break; case ESM4::SUB_FULL: - reader.getZString(mTopicName); + reader.getLocalizedString(mTopicName); break; case ESM4::SUB_QSTI: reader.getFormId(mQuests.emplace_back()); @@ -87,6 +87,7 @@ void ESM4::Dialogue::load(ESM4::Reader& reader) case ESM4::SUB_BNAM: // TES5 case ESM4::SUB_SNAM: // TES5 case ESM4::SUB_TIFC: // TES5 + case ESM4::SUB_KNAM: // FO4 reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadinfo.cpp b/components/esm4/loadinfo.cpp index 6f0e230300..1b001c1665 100644 --- a/components/esm4/loadinfo.cpp +++ b/components/esm4/loadinfo.cpp @@ -71,7 +71,7 @@ void ESM4::DialogInfo::load(ESM4::Reader& reader) break; } case ESM4::SUB_NAM1: - reader.getZString(mResponse); + reader.getLocalizedString(mResponse); break; // response text case ESM4::SUB_NAM2: reader.getZString(mNotes); @@ -185,6 +185,7 @@ void ESM4::DialogInfo::load(ESM4::Reader& reader) case ESM4::SUB_TCFU: // FONV case ESM4::SUB_TIFC: // TES5 case ESM4::SUB_TWAT: // TES5 + case ESM4::SUB_CIS1: // TES5 case ESM4::SUB_CIS2: // TES5 case ESM4::SUB_CNAM: // TES5 case ESM4::SUB_ENAM: // TES5 @@ -195,6 +196,23 @@ void ESM4::DialogInfo::load(ESM4::Reader& reader) case ESM4::SUB_ONAM: // TES5 case ESM4::SUB_QNAM: // TES5 for mScript case ESM4::SUB_RNAM: // TES5 + case ESM4::SUB_ALFA: // FO4 + case ESM4::SUB_GNAM: // FO4 + case ESM4::SUB_GREE: // FO4 + case ESM4::SUB_INAM: // FO4 + case ESM4::SUB_INCC: // FO4 + case ESM4::SUB_INTV: // FO4 + case ESM4::SUB_IOVR: // FO4 + case ESM4::SUB_MODQ: // FO4 + case ESM4::SUB_NAM0: // FO4 + case ESM4::SUB_NAM4: // FO4 + case ESM4::SUB_NAM9: // FO4 + case ESM4::SUB_SRAF: // FO4 + case ESM4::SUB_TIQS: // FO4 + case ESM4::SUB_TNAM: // FO4 + case ESM4::SUB_TRDA: // FO4 + case ESM4::SUB_TSCE: // FO4 + case ESM4::SUB_WZMD: // FO4 reader.skipSubRecordData(); break; default: From f7a85be5044ef037ce734587b9548e933c6de5d6 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Thu, 17 Aug 2023 01:04:17 +0300 Subject: [PATCH 56/64] Maybe load FO4 armor addon records You still can't load into the game because of some unclear localization string problem. But if getLocalizedString doesn't throw an exception, then it'll work. Sort of. --- components/esm4/loadarma.cpp | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/components/esm4/loadarma.cpp b/components/esm4/loadarma.cpp index 8fa3dc8fc3..3390e59828 100644 --- a/components/esm4/loadarma.cpp +++ b/components/esm4/loadarma.cpp @@ -83,24 +83,35 @@ void ESM4::ArmorAddon::load(ESM4::Reader& reader) reader.get(mBodyTemplate.unknown3); // probably padding reader.get(mBodyTemplate.type); break; - case ESM4::SUB_BOD2: // TES5 + 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); + mBodyTemplate.type = 0; + if (subHdr.dataSize == 8) + 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_MO2C: // FIXME: should group with MOD2 + case ESM4::SUB_MO2F: // 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_MO3C: // FIXME: should group with MOD3 + case ESM4::SUB_MO3F: // 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_MO4C: // FIXME: should group with MOD4 + case ESM4::SUB_MO4F: // FIXME: should group with MOD4 case ESM4::SUB_MO5T: + case ESM4::SUB_MO5S: + case ESM4::SUB_MO5C: + case ESM4::SUB_MO5F: case ESM4::SUB_NAM2: // txst formid male case ESM4::SUB_NAM3: // txst formid female case ESM4::SUB_SNDD: // footset sound formid @@ -114,6 +125,10 @@ void ESM4::ArmorAddon::load(ESM4::Reader& reader) 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 + case ESM4::SUB_BSMB: // FO4 + case ESM4::SUB_BSMP: // FO4 + case ESM4::SUB_BSMS: // FO4 + case ESM4::SUB_ONAM: // FO4 reader.skipSubRecordData(); break; default: From 07c85addb213058bb1fde27560fd66b69535921b Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Thu, 17 Aug 2023 01:36:24 +0300 Subject: [PATCH 57/64] Cleanup --- components/esm4/loadcell.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/components/esm4/loadcell.cpp b/components/esm4/loadcell.cpp index 47afe5bca9..53f12c3dde 100644 --- a/components/esm4/loadcell.cpp +++ b/components/esm4/loadcell.cpp @@ -30,8 +30,6 @@ #include #include -#include - #include "grouptype.hpp" #include "reader.hpp" // #include "writer.hpp" From 9ec68e864c4f36cf87812375448e93d11e99b397 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Thu, 17 Aug 2023 03:56:23 +0300 Subject: [PATCH 58/64] Load ESM4 idle animations correctly for every game --- apps/esmtool/tes4.cpp | 3 +-- components/esm4/loadidle.cpp | 28 +++++++++++++++++++++++++--- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/apps/esmtool/tes4.cpp b/apps/esmtool/tes4.cpp index 0b1c07920f..91b98b04a4 100644 --- a/apps/esmtool/tes4.cpp +++ b/apps/esmtool/tes4.cpp @@ -334,8 +334,7 @@ namespace EsmTool readTypedRecord(params, reader); return true; case ESM4::REC_IDLE: - // FIXME: ESM4::IdleAnimation::load does not work with Oblivion.esm - // readTypedRecord(params, reader); + readTypedRecord(params, reader); return true; break; case ESM4::REC_IDLM: diff --git a/components/esm4/loadidle.cpp b/components/esm4/loadidle.cpp index e691addb18..f0e1f986f2 100644 --- a/components/esm4/loadidle.cpp +++ b/components/esm4/loadidle.cpp @@ -51,9 +51,24 @@ void ESM4::IdleAnimation::load(ESM4::Reader& reader) reader.getZString(mEvent); break; case ESM4::SUB_ANAM: - reader.getFormId(mParent); - reader.getFormId(mPrevious); + { + if (subHdr.dataSize == 8) + { + reader.getFormId(mParent); + reader.getFormId(mPrevious); + } + // Animation Group Section. TES4 stores the IDs above in DATA + else if (subHdr.dataSize == 1) + { + uint8_t dummy; + reader.get(dummy); + } + else + { + reader.skipSubRecordData(); + } break; + } case ESM4::SUB_MODL: reader.getZString(mModel); break; @@ -61,7 +76,14 @@ void ESM4::IdleAnimation::load(ESM4::Reader& reader) reader.get(mBoundRadius); break; case ESM4::SUB_CTDA: // formId - case ESM4::SUB_DATA: // formId + case ESM4::SUB_CTDT: + case ESM4::SUB_CIS1: + case ESM4::SUB_CIS2: + case ESM4::SUB_DATA: + case ESM4::SUB_MODD: + case ESM4::SUB_MODS: + case ESM4::SUB_MODT: + case ESM4::SUB_GNAM: // FO4 reader.skipSubRecordData(); break; default: From f3c1b0e7ebd3b8f5533489b3fb3eedd71315b026 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Thu, 17 Aug 2023 04:43:47 +0300 Subject: [PATCH 59/64] Load FO4 form lists --- components/esm4/loadflst.cpp | 3 +++ components/esm4/loadflst.hpp | 1 + 2 files changed, 4 insertions(+) diff --git a/components/esm4/loadflst.cpp b/components/esm4/loadflst.cpp index a1e8e3ef16..9da17bc84b 100644 --- a/components/esm4/loadflst.cpp +++ b/components/esm4/loadflst.cpp @@ -44,6 +44,9 @@ void ESM4::FormIdList::load(ESM4::Reader& reader) case ESM4::SUB_EDID: reader.getZString(mEditorId); break; + case ESM4::SUB_FULL: + reader.getLocalizedString(mFullName); + break; case ESM4::SUB_LNAM: reader.getFormId(mObjects.emplace_back()); break; diff --git a/components/esm4/loadflst.hpp b/components/esm4/loadflst.hpp index 816cb11f5e..fb90b0dd38 100644 --- a/components/esm4/loadflst.hpp +++ b/components/esm4/loadflst.hpp @@ -45,6 +45,7 @@ namespace ESM4 std::uint32_t mFlags; // from the header, see enum type RecordFlag for details std::string mEditorId; + std::string mFullName; std::vector mObjects; From da9a834ce823afe27a0373efd435f86136f357b2 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Thu, 17 Aug 2023 04:54:06 +0300 Subject: [PATCH 60/64] Maybe load FO4 body part data records --- components/esm4/loadbptd.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/components/esm4/loadbptd.cpp b/components/esm4/loadbptd.cpp index b4c783c5ff..509eadfcf1 100644 --- a/components/esm4/loadbptd.cpp +++ b/components/esm4/loadbptd.cpp @@ -78,7 +78,11 @@ void ESM4::BodyPartData::load(ESM4::Reader& reader) reader.getZString(bodyPart.mIKStartNode); break; case ESM4::SUB_BPND: - reader.get(bodyPart.mData); + if (subHdr.dataSize == sizeof(bodyPart.mData)) + reader.get(bodyPart.mData); + // FIXME: FO4 + else + reader.skipSubRecordData(); break; case ESM4::SUB_NAM1: reader.getZString(bodyPart.mLimbReplacementModel); @@ -94,6 +98,14 @@ void ESM4::BodyPartData::load(ESM4::Reader& reader) case ESM4::SUB_MODC: case ESM4::SUB_MODS: case ESM4::SUB_MODF: // Model data end + case ESM4::SUB_BNAM: // FO4 + case ESM4::SUB_CNAM: // FO4 + case ESM4::SUB_DNAM: // FO4 + case ESM4::SUB_ENAM: // FO4 + case ESM4::SUB_FNAM: // FO4 + case ESM4::SUB_INAM: // FO4 + case ESM4::SUB_JNAM: // FO4 + case ESM4::SUB_NAM2: // FO4 reader.skipSubRecordData(); break; default: From 9da6ce23e9ea7294a9f862392397d83a14d436e2 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Thu, 17 Aug 2023 05:09:26 +0300 Subject: [PATCH 61/64] Maybe load FO4 sound descriptor records --- components/esm4/loadsndr.cpp | 17 ++++++++++++++++- components/esm4/loadsndr.hpp | 1 + 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/components/esm4/loadsndr.cpp b/components/esm4/loadsndr.cpp index ce1b9d6d52..830cdfdc54 100644 --- a/components/esm4/loadsndr.cpp +++ b/components/esm4/loadsndr.cpp @@ -68,10 +68,25 @@ void ESM4::SoundReference::load(ESM4::Reader& reader) reader.get(mLoopInfo); break; case ESM4::SUB_BNAM: - reader.get(mData); + { + if (subHdr.dataSize == 6) + reader.get(mData); + else if (subHdr.dataSize == 4) + reader.getFormId(mBaseDescriptor); + else + reader.skipSubRecordData(); break; + } + case ESM4::SUB_CIS1: + case ESM4::SUB_CIS2: case ESM4::SUB_CNAM: // CRC32 hash + case ESM4::SUB_DNAM: // FO4 case ESM4::SUB_FNAM: // unknown + case ESM4::SUB_INTV: // FO4 + case ESM4::SUB_ITMC: // FO4 + case ESM4::SUB_ITME: // FO4 + case ESM4::SUB_ITMS: // FO4 + case ESM4::SUB_NNAM: // FO4 reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadsndr.hpp b/components/esm4/loadsndr.hpp index 5e52499f12..8110f3154a 100644 --- a/components/esm4/loadsndr.hpp +++ b/components/esm4/loadsndr.hpp @@ -67,6 +67,7 @@ namespace ESM4 ESM::FormId mSoundCategory; // SNCT ESM::FormId mSoundId; // another SNDR ESM::FormId mOutputModel; // SOPM + ESM::FormId mBaseDescriptor; // BNAM std::string mSoundFile; LoopInfo mLoopInfo; From 42c6b3b99361745e061b8e4773e358ef6072a6a7 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Thu, 17 Aug 2023 21:36:49 +0300 Subject: [PATCH 62/64] Use VER_100 named constant, note precautions --- components/esm4/loadnavi.cpp | 11 +++++++---- components/esm4/loadnavm.cpp | 4 +++- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/components/esm4/loadnavi.cpp b/components/esm4/loadnavi.cpp index 6c8fe94b76..09868d258f 100644 --- a/components/esm4/loadnavi.cpp +++ b/components/esm4/loadnavi.cpp @@ -249,8 +249,9 @@ void ESM4::Navigation::load(ESM4::Reader& reader) } case ESM4::SUB_NVPP: { - // FO4 - if (esmVer == 0x3F800000) + // FIXME: this is both the version for FO4 and for some TES4 files + // How to distinguish? + if (esmVer == ESM::VER_100) { reader.skipSubRecordData(); break; @@ -339,9 +340,11 @@ void ESM4::Navigation::load(ESM4::Reader& reader) } case ESM4::SUB_NVMI: // multiple { - if (esmVer == ESM::VER_094 || esmVer == ESM::VER_170 || isFONV || esmVer == 0x3F800000) + // Can only read TES4 navmesh data + // Note FO4 FIXME above + if (esmVer == ESM::VER_094 || esmVer == ESM::VER_170 || isFONV || esmVer == ESM::VER_100) { - reader.skipSubRecordData(); // FIXME: FO3+ have different form of NavMeshInfo + reader.skipSubRecordData(); break; } diff --git a/components/esm4/loadnavm.cpp b/components/esm4/loadnavm.cpp index 20fcf90982..6298964f28 100644 --- a/components/esm4/loadnavm.cpp +++ b/components/esm4/loadnavm.cpp @@ -211,7 +211,9 @@ void ESM4::NavMesh::load(ESM4::Reader& reader) { case ESM4::SUB_NVNM: { - if (esmVer == 0x3F800000) + // See FIXME in ESM4::Navigation::load. + // FO4 updates the format + if (esmVer == ESM::VER_100) { reader.skipSubRecordData(); break; From 1a62b2e6b5acb1fccccdc332e79a8ec6ab14b51c Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Thu, 17 Aug 2023 21:39:50 +0300 Subject: [PATCH 63/64] ESM4: use switch-cases when relevant --- components/esm4/loadachr.cpp | 19 ++++++----- components/esm4/loadammo.cpp | 64 ++++++++++++++++++------------------ components/esm4/loadarmo.cpp | 36 +++++++++----------- components/esm4/loadbook.cpp | 30 +++++++++-------- components/esm4/loadcell.cpp | 52 ++++++++++++++--------------- components/esm4/loadidle.cpp | 31 +++++++++-------- components/esm4/loadltex.cpp | 26 +++++++-------- components/esm4/loadnpc.cpp | 20 ++++++----- components/esm4/loadrefr.cpp | 50 ++++++++++++++++------------ 9 files changed, 168 insertions(+), 160 deletions(-) diff --git a/components/esm4/loadachr.cpp b/components/esm4/loadachr.cpp index fb2f304a51..1a6d47497e 100644 --- a/components/esm4/loadachr.cpp +++ b/components/esm4/loadachr.cpp @@ -59,19 +59,22 @@ void ESM4::ActorCharacter::load(ESM4::Reader& reader) break; case ESM4::SUB_XOWN: { - if (subHdr.dataSize == 4 || subHdr.dataSize == 12) + switch (subHdr.dataSize) { - reader.getFormId(mOwner); - if (subHdr.dataSize == 12) + case 4: + reader.getFormId(mOwner); + break; + case 12: { + reader.getFormId(mOwner); std::uint32_t dummy; reader.get(dummy); // Unknown - reader.get(dummy); // Flags + reader.get(dummy); // No crime flag, FO4 + break; } - } - else - { - reader.skipSubRecordData(); + default: + reader.skipSubRecordData(); + break; } break; } diff --git a/components/esm4/loadammo.cpp b/components/esm4/loadammo.cpp index 28da90255b..8c5bc45c85 100644 --- a/components/esm4/loadammo.cpp +++ b/components/esm4/loadammo.cpp @@ -48,42 +48,42 @@ void ESM4::Ammunition::load(ESM4::Reader& reader) reader.getLocalizedString(mFullName); break; case ESM4::SUB_DATA: - // FO3/FNV or TES4 - if (subHdr.dataSize == 13 || subHdr.dataSize == 18) + switch (subHdr.dataSize) { - reader.get(mData.mSpeed); - reader.get(mData.mFlags); - mData.mFlags &= 0xFF; - reader.get(mData.mValue); - if (subHdr.dataSize == 13) - reader.get(mData.mClipRounds); - else + case 18: // TES4 + case 13: // FO3/FNV { - reader.get(mData.mWeight); - std::uint16_t damageInt; - reader.get(damageInt); - mData.mDamage = static_cast(damageInt); + reader.get(mData.mSpeed); + reader.get(mData.mFlags); + mData.mFlags &= 0xFF; + reader.get(mData.mValue); + if (subHdr.dataSize == 13) + reader.get(mData.mClipRounds); + else + { + reader.get(mData.mWeight); + std::uint16_t damageInt; + reader.get(damageInt); + mData.mDamage = static_cast(damageInt); + } + break; } - } - // TES5/SSE - else if (subHdr.dataSize == 16 || subHdr.dataSize == 20) - { - reader.getFormId(mData.mProjectile); - reader.get(mData.mFlags); - reader.get(mData.mDamage); - reader.get(mData.mValue); - if (subHdr.dataSize == 20) + case 16: // TES5 + case 20: // SSE + reader.getFormId(mData.mProjectile); + reader.get(mData.mFlags); + reader.get(mData.mDamage); + reader.get(mData.mValue); + if (subHdr.dataSize == 20) + reader.get(mData.mWeight); + break; + case 8: + reader.get(mData.mValue); reader.get(mData.mWeight); - } - // FO4 - else if (subHdr.dataSize == 8) - { - reader.get(mData.mValue); - reader.get(mData.mWeight); - } - else - { - reader.skipSubRecordData(); + break; + default: + reader.skipSubRecordData(); + break; } break; case ESM4::SUB_DAT2: diff --git a/components/esm4/loadarmo.cpp b/components/esm4/loadarmo.cpp index 6c4e1e9a3e..572cbd6ecd 100644 --- a/components/esm4/loadarmo.cpp +++ b/components/esm4/loadarmo.cpp @@ -49,27 +49,23 @@ void ESM4::Armor::load(ESM4::Reader& reader) break; case ESM4::SUB_DATA: { - // TES5 - if (subHdr.dataSize == 8) + switch (subHdr.dataSize) { - reader.get(mData.value); - reader.get(mData.weight); - } - // FO3, FNV, FO4 - else if (subHdr.dataSize == 12) - { - reader.get(mData.value); - reader.get(mData.health); - reader.get(mData.weight); - } - // TES4 - else if (subHdr.dataSize == 14) - { - reader.get(mData); - } - else - { - reader.skipSubRecordData(); + case 14: // TES4 + reader.get(mData); + break; + case 12: // FO3, FNV, FO4 + reader.get(mData.value); + reader.get(mData.health); + reader.get(mData.weight); + break; + case 8: // TES5 + reader.get(mData.value); + reader.get(mData.weight); + break; + default: + reader.skipSubRecordData(); + break; } break; } diff --git a/components/esm4/loadbook.cpp b/components/esm4/loadbook.cpp index d78c7ada6a..f2842e5313 100644 --- a/components/esm4/loadbook.cpp +++ b/components/esm4/loadbook.cpp @@ -53,30 +53,32 @@ void ESM4::Book::load(ESM4::Reader& reader) break; case ESM4::SUB_DATA: { - if (subHdr.dataSize == 8 || subHdr.dataSize == 10 || subHdr.dataSize == 16) + switch (subHdr.dataSize) { - // TES4, FO3, FNV - if (subHdr.dataSize == 10) - { + case 10: // TES4, FO3, FNV reader.get(mData.flags); reader.get(mData.bookSkill); - } - // TES5 - else if (subHdr.dataSize == 16) + reader.get(mData.value); + reader.get(mData.weight); + break; + case 16: // TES5 { reader.get(mData.flags); reader.get(mData.type); std::uint16_t dummy; reader.get(dummy); reader.get(mData.teaches); + reader.get(mData.value); + reader.get(mData.weight); + break; } - // else: FO4 - reader.get(mData.value); - reader.get(mData.weight); - } - else - { - reader.skipSubRecordData(); + case 8: // FO4 + reader.get(mData.value); + reader.get(mData.weight); + break; + default: + reader.skipSubRecordData(); + break; } break; } diff --git a/components/esm4/loadcell.cpp b/components/esm4/loadcell.cpp index 53f12c3dde..0091ab0bd6 100644 --- a/components/esm4/loadcell.cpp +++ b/components/esm4/loadcell.cpp @@ -147,19 +147,22 @@ void ESM4::Cell::load(ESM4::Reader& reader) } case ESM4::SUB_XOWN: { - if (subHdr.dataSize == 4 || subHdr.dataSize == 12) + switch (subHdr.dataSize) { - reader.getFormId(mOwner); - if (subHdr.dataSize == 12) + case 4: + reader.getFormId(mOwner); + break; + case 12: { + reader.getFormId(mOwner); std::uint32_t dummy; reader.get(dummy); // Unknown - reader.get(dummy); // Flags + reader.get(dummy); // No crime flag, FO4 + break; } - } - else - { - reader.skipSubRecordData(); + default: + reader.skipSubRecordData(); + break; } break; } @@ -177,27 +180,20 @@ void ESM4::Cell::load(ESM4::Reader& reader) break; case ESM4::SUB_XCLL: { - // TES4 - if (subHdr.dataSize == 36) - reader.get(&mLighting, 36); - // FO3, FONV - else if (subHdr.dataSize == 40) - reader.get(mLighting); - // TES5 - else if (subHdr.dataSize == 92) - { - reader.get(mLighting); - reader.skipSubRecordData(52); // FIXME - } - // FO4 - else if (subHdr.dataSize == 136) - { - reader.get(mLighting); - reader.skipSubRecordData(96); // FIXME - } - else + switch (subHdr.dataSize) { - reader.skipSubRecordData(); + case 36: // TES4 + reader.get(&mLighting, 36); + break; + case 40: // FO3/FNV + case 92: // TES5 (FIXME) + case 136: // FO4 (FIXME) + reader.get(mLighting); + reader.skipSubRecordData(subHdr.dataSize - 40); + break; + default: + reader.skipSubRecordData(); + break; } break; } diff --git a/components/esm4/loadidle.cpp b/components/esm4/loadidle.cpp index f0e1f986f2..310c43b2e1 100644 --- a/components/esm4/loadidle.cpp +++ b/components/esm4/loadidle.cpp @@ -52,20 +52,25 @@ void ESM4::IdleAnimation::load(ESM4::Reader& reader) break; case ESM4::SUB_ANAM: { - if (subHdr.dataSize == 8) + switch (subHdr.dataSize) { - reader.getFormId(mParent); - reader.getFormId(mPrevious); - } - // Animation Group Section. TES4 stores the IDs above in DATA - else if (subHdr.dataSize == 1) - { - uint8_t dummy; - reader.get(dummy); - } - else - { - reader.skipSubRecordData(); + case 1: // TES4 + { + // Animation group section + uint8_t dummy; + reader.get(dummy); + break; + } + case 8: // Everything else + { + // These IDs go into DATA for TES4 + reader.getFormId(mParent); + reader.getFormId(mPrevious); + break; + } + default: + reader.skipSubRecordData(); + break; } break; } diff --git a/components/esm4/loadltex.cpp b/components/esm4/loadltex.cpp index b6f083dd03..955ac938e3 100644 --- a/components/esm4/loadltex.cpp +++ b/components/esm4/loadltex.cpp @@ -46,22 +46,18 @@ void ESM4::LandTexture::load(ESM4::Reader& reader) break; case ESM4::SUB_HNAM: { - // TES5+ - if (subHdr.dataSize == 2) + switch (subHdr.dataSize) { - reader.get(mHavokFriction); - reader.get(mHavokRestitution); - } - // TES4, FO3, FNV - else if (subHdr.dataSize == 3) - { - reader.get(mHavokMaterial); - reader.get(mHavokFriction); - reader.get(mHavokRestitution); - } - else - { - reader.skipSubRecordData(); + case 3: // TES4, FO3, FNV + reader.get(mHavokMaterial); + [[fallthrough]]; + case 2: + reader.get(mHavokFriction); + reader.get(mHavokRestitution); + break; + default: + reader.skipSubRecordData(); + break; } break; } diff --git a/components/esm4/loadnpc.cpp b/components/esm4/loadnpc.cpp index 5bbb5ae0a0..65292e63a8 100644 --- a/components/esm4/loadnpc.cpp +++ b/components/esm4/loadnpc.cpp @@ -114,15 +114,17 @@ void ESM4::Npc::load(ESM4::Reader& reader) } case ESM4::SUB_ACBS: { - if (subHdr.dataSize == 24) - reader.get(mBaseConfig); - // TES4 - else if (subHdr.dataSize == 16) - reader.get(&mBaseConfig, 16); - // FO4 - else if (subHdr.dataSize == 20) - reader.get(&mBaseConfig, 20); - + switch (subHdr.dataSize) + { + case 16: // TES4 + case 24: // FO3/FNV, TES5 + case 20: // FO4 + reader.get(&mBaseConfig, subHdr.dataSize); + break; + default: + reader.skipSubRecordData(); + break; + } break; } case ESM4::SUB_DATA: diff --git a/components/esm4/loadrefr.cpp b/components/esm4/loadrefr.cpp index 63cac33115..5f37800b3c 100644 --- a/components/esm4/loadrefr.cpp +++ b/components/esm4/loadrefr.cpp @@ -67,19 +67,22 @@ void ESM4::Reference::load(ESM4::Reader& reader) break; case ESM4::SUB_XOWN: { - if (subHdr.dataSize == 4 || subHdr.dataSize == 12) + switch (subHdr.dataSize) { - reader.getFormId(mOwner); - if (subHdr.dataSize == 12) + case 4: + reader.getFormId(mOwner); + break; + case 12: { + reader.getFormId(mOwner); std::uint32_t dummy; reader.get(dummy); // Unknown - reader.get(dummy); // Flags + reader.get(dummy); // No crime flag, FO4 + break; } - } - else - { - reader.skipSubRecordData(); + default: + reader.skipSubRecordData(); + break; } break; } @@ -99,22 +102,27 @@ void ESM4::Reference::load(ESM4::Reader& reader) } case ESM4::SUB_XTEL: { - if (subHdr.dataSize == 28 || subHdr.dataSize == 32 || subHdr.dataSize == 36) + switch (subHdr.dataSize) { - reader.getFormId(mDoor.destDoor); - reader.get(mDoor.destPos); - mDoor.flags = 0; - if (subHdr.dataSize == 32 || subHdr.dataSize == 36) + case 28: + case 32: // FO3, FNV, TES5 + case 36: // FO4 { - reader.get(mDoor.flags); - // FO4 - if (subHdr.dataSize == 36) - reader.getFormId(mDoor.transitionInt); + reader.getFormId(mDoor.destDoor); + reader.get(mDoor.destPos); + mDoor.flags = 0; + if (subHdr.dataSize >= 32) + { + reader.get(mDoor.flags); + // FO4 + if (subHdr.dataSize == 36) + reader.getFormId(mDoor.transitionInt); + } + break; } - } - else - { - reader.skipSubRecordData(); + default: + reader.skipSubRecordData(); + break; } break; } From 1bd2667c66b260a035b4f2781a32bbe8e83d911b Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Thu, 17 Aug 2023 23:28:35 +0300 Subject: [PATCH 64/64] Rename REFR::XTEL transition interior field --- components/esm4/loadrefr.cpp | 3 +-- components/esm4/loadrefr.hpp | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/components/esm4/loadrefr.cpp b/components/esm4/loadrefr.cpp index 5f37800b3c..a193907ac4 100644 --- a/components/esm4/loadrefr.cpp +++ b/components/esm4/loadrefr.cpp @@ -114,9 +114,8 @@ void ESM4::Reference::load(ESM4::Reader& reader) if (subHdr.dataSize >= 32) { reader.get(mDoor.flags); - // FO4 if (subHdr.dataSize == 36) - reader.getFormId(mDoor.transitionInt); + reader.getFormId(mDoor.transitionInterior); } break; } diff --git a/components/esm4/loadrefr.hpp b/components/esm4/loadrefr.hpp index 4c9f4e0c77..af04a791c8 100644 --- a/components/esm4/loadrefr.hpp +++ b/components/esm4/loadrefr.hpp @@ -61,7 +61,7 @@ namespace ESM4 ESM::FormId destDoor; ESM::Position destPos; std::uint32_t flags = 0; // 0x01 no alarm (only in TES5) - ESM::FormId transitionInt; + ESM::FormId transitionInterior; }; struct RadioStationData