diff --git a/apps/esmtool/tes4.cpp b/apps/esmtool/tes4.cpp index 5a6080336b..6791694a7c 100644 --- a/apps/esmtool/tes4.cpp +++ b/apps/esmtool/tes4.cpp @@ -329,8 +329,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/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) diff --git a/components/esm4/actor.hpp b/components/esm4/actor.hpp index 9a408ca33d..769287b9d8 100644 --- a/components/esm4/actor.hpp +++ b/components/esm4/actor.hpp @@ -100,11 +100,25 @@ 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/common.hpp b/components/esm4/common.hpp index fb3dd71045..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,8 +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 + 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/loadachr.cpp b/components/esm4/loadachr.cpp index 537bb026ac..1a6d47497e 100644 --- a/components/esm4/loadachr.cpp +++ b/components/esm4/loadachr.cpp @@ -58,8 +58,26 @@ void ESM4::ActorCharacter::load(ESM4::Reader& reader) reader.get(mScale); break; case ESM4::SUB_XOWN: - reader.getFormId(mOwner); + { + switch (subHdr.dataSize) + { + case 4: + reader.getFormId(mOwner); + break; + case 12: + { + reader.getFormId(mOwner); + std::uint32_t dummy; + reader.get(dummy); // Unknown + reader.get(dummy); // No crime flag, FO4 + break; + } + default: + reader.skipSubRecordData(); + break; + } break; + } case ESM4::SUB_XESP: reader.getFormId(mEsp.parent); reader.get(mEsp.flags); @@ -93,6 +111,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: diff --git a/components/esm4/loadacti.cpp b/components/esm4/loadacti.cpp index 54af0732e1..74eaff2dab 100644 --- a/components/esm4/loadacti.cpp +++ b/components/esm4/loadacti.cpp @@ -71,14 +71,19 @@ 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: 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: @@ -87,6 +92,18 @@ void ESM4::Activator::load(ESM4::Reader& reader) case ESM4::SUB_PNAM: case ESM4::SUB_VMAD: case ESM4::SUB_WNAM: + case ESM4::SUB_CTDA: + case ESM4::SUB_CIS1: + case ESM4::SUB_CIS2: + case ESM4::SUB_CITC: + case ESM4::SUB_NVNM: + 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 35f6964b24..1ecfda25e8 100644 --- a/components/esm4/loadalch.cpp +++ b/components/esm4/loadalch.cpp @@ -88,15 +88,30 @@ 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: + 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_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 8dab2ba74c..8c5bc45c85 100644 --- a/components/esm4/loadammo.cpp +++ b/components/esm4/loadammo.cpp @@ -48,36 +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); - } - else - { - reader.skipSubRecordData(); + break; + default: + reader.skipSubRecordData(); + break; } break; case ESM4::SUB_DAT2: @@ -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; @@ -133,10 +146,25 @@ 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: + 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_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 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/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: diff --git a/components/esm4/loadarmo.cpp b/components/esm4/loadarmo.cpp index b2b90f2eb1..572cbd6ecd 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,46 @@ 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 - { - reader.get(mData.value); - reader.get(mData.weight); - mIsFO3 = true; - } - else if (mIsFONV || subHdr.dataSize == 12) - { - reader.get(mData.value); - reader.get(mData.health); - reader.get(mData.weight); - } - else + switch (subHdr.dataSize) { - reader.get(mData); // TES4 - mIsTES4 = true; + 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; } - case ESM4::SUB_MODL: // seems only for Dawnguard/Dragonborn? + case ESM4::SUB_INDX: // FO4 { - // 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()); + reader.get(currentIndex); + break; + } + case ESM4::SUB_MODL: + { + 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 +147,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); @@ -191,6 +214,24 @@ 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 + 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; 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 diff --git a/components/esm4/loadbook.cpp b/components/esm4/loadbook.cpp index df8697a608..f2842e5313 100644 --- a/components/esm4/loadbook.cpp +++ b/components/esm4/loadbook.cpp @@ -53,22 +53,33 @@ 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 + switch (subHdr.dataSize) { - static std::uint8_t dummy; - reader.get(mData.type); - reader.get(dummy); - reader.get(dummy); - reader.get(mData.teaches); + case 10: // TES4, FO3, FNV + reader.get(mData.flags); + reader.get(mData.bookSkill); + 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; + } + case 8: // FO4 + reader.get(mData.value); + reader.get(mData.weight); + break; + default: + reader.skipSubRecordData(); + break; } - else - { - reader.get(mData.bookSkill); - } - reader.get(mData.value); - reader.get(mData.weight); break; } case ESM4::SUB_ICON: @@ -94,14 +105,30 @@ 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: 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 + case ESM4::SUB_DNAM: // FO4 + case ESM4::SUB_FIMD: // FO4 + case ESM4::SUB_MICO: // FO4 + case ESM4::SUB_PTRN: // FO4 reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadbptd.cpp b/components/esm4/loadbptd.cpp index a9edc2b145..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); @@ -90,8 +94,18 @@ 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 + 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: diff --git a/components/esm4/loadcell.cpp b/components/esm4/loadcell.cpp index 0c320967d8..0091ab0bd6 100644 --- a/components/esm4/loadcell.cpp +++ b/components/esm4/loadcell.cpp @@ -71,7 +71,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 +105,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. @@ -128,28 +119,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 @@ -167,8 +146,26 @@ void ESM4::Cell::load(ESM4::Reader& reader) break; } case ESM4::SUB_XOWN: - reader.getFormId(mOwner); + { + switch (subHdr.dataSize) + { + case 4: + reader.getFormId(mOwner); + break; + case 12: + { + reader.getFormId(mOwner); + std::uint32_t dummy; + reader.get(dummy); // Unknown + reader.get(dummy); // No crime flag, FO4 + break; + } + default: + reader.skipSubRecordData(); + break; + } break; + } case ESM4::SUB_XGLB: reader.getFormId(mGlobal); break; // Oblivion only? @@ -183,21 +180,21 @@ void ESM4::Cell::load(ESM4::Reader& reader) break; case ESM4::SUB_XCLL: { - if (esmVer == ESM::VER_094 || esmVer == ESM::VER_170 || isFONV) + switch (subHdr.dataSize) { - if (subHdr.dataSize == 40) // FO3/FONV + case 36: // TES4 + reader.get(&mLighting, 36); + break; + case 40: // FO3/FNV + case 92: // TES5 (FIXME) + case 136: // FO4 (FIXME) reader.get(mLighting); - else if (subHdr.dataSize == 92) // TES5 - { - reader.get(mLighting); - reader.skipSubRecordData(52); // FIXME - } - else + reader.skipSubRecordData(subHdr.dataSize - 40); + break; + default: reader.skipSubRecordData(); + break; } - else - reader.get(&mLighting, 36); // TES4 - break; } case ESM4::SUB_XCMT: @@ -227,9 +224,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: 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/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/loadcont.cpp b/components/esm4/loadcont.cpp index 50a1c6b9bf..d650678093 100644 --- a/components/esm4/loadcont.cpp +++ b/components/esm4/loadcont.cpp @@ -74,18 +74,32 @@ 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 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_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(); break; default: 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/loaddoor.cpp b/components/esm4/loaddoor.cpp index 0f51caf64d..7fe38b6b7a 100644 --- a/components/esm4/loaddoor.cpp +++ b/components/esm4/loaddoor.cpp @@ -71,15 +71,27 @@ 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_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_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; default: diff --git a/components/esm4/loadflor.cpp b/components/esm4/loadflor.cpp index 6bbc31ffe2..69f1c82b13 100644 --- a/components/esm4/loadflor.cpp +++ b/components/esm4/loadflor.cpp @@ -65,13 +65,29 @@ 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_KSIZ: + case ESM4::SUB_KWDA: 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: // FO4 + case ESM4::SUB_PTRN: // FO4 + case ESM4::SUB_ATTX: // FO4 reader.skipSubRecordData(); break; default: 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; diff --git a/components/esm4/loadfurn.cpp b/components/esm4/loadfurn.cpp index 9d84312e26..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; @@ -59,10 +65,19 @@ 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: + 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: @@ -70,13 +85,33 @@ 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: case ESM4::SUB_VMAD: case ESM4::SUB_WBDT: case ESM4::SUB_XMRK: + case ESM4::SUB_PRPS: + 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: diff --git a/components/esm4/loadgmst.cpp b/components/esm4/loadgmst.cpp index b403d09be9..f22ed5848d 100644 --- a/components/esm4/loadgmst.cpp +++ b/components/esm4/loadgmst.cpp @@ -41,7 +41,13 @@ namespace ESM4 case 's': { std::string value; - reader.getZString(value); + reader.getLocalizedString(value); + return value; + } + case 'u': + { + std::uint32_t value = 0; + reader.get(value); return value; } default: 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 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 53b8a401ac..7592db5486 100644 --- a/components/esm4/loadhdpt.cpp +++ b/components/esm4/loadhdpt.cpp @@ -88,10 +88,13 @@ 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: reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadidle.cpp b/components/esm4/loadidle.cpp index e691addb18..310c43b2e1 100644 --- a/components/esm4/loadidle.cpp +++ b/components/esm4/loadidle.cpp @@ -51,9 +51,29 @@ void ESM4::IdleAnimation::load(ESM4::Reader& reader) reader.getZString(mEvent); break; case ESM4::SUB_ANAM: - reader.getFormId(mParent); - reader.getFormId(mPrevious); + { + switch (subHdr.dataSize) + { + 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; + } case ESM4::SUB_MODL: reader.getZString(mModel); break; @@ -61,7 +81,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: diff --git a/components/esm4/loadidlm.cpp b/components/esm4/loadidlm.cpp index 3c561e962f..3f1ed9518c 100644 --- a/components/esm4/loadidlm.cpp +++ b/components/esm4/loadidlm.cpp @@ -79,8 +79,13 @@ void ESM4::IdleMarker::load(ESM4::Reader& reader) reader.getZString(mModel); break; case ESM4::SUB_OBND: // object bounds - case ESM4::SUB_MODT: + 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: 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: diff --git a/components/esm4/loadingr.cpp b/components/esm4/loadingr.cpp index b1dde9de02..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: @@ -106,6 +108,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..9b0c280b8b 100644 --- a/components/esm4/loadkeym.cpp +++ b/components/esm4/loadkeym.cpp @@ -71,11 +71,24 @@ 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: 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_PTRN: // FO4 reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadland.cpp b/components/esm4/loadland.cpp index c448c29b29..f3e4c27681 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)) @@ -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)); } diff --git a/components/esm4/loadligh.cpp b/components/esm4/loadligh.cpp index 1ea88a490b..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); @@ -99,15 +96,29 @@ 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_DEST: // Destruction data start - case ESM4::SUB_DSTD: + 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_DSTF: // Destruction data end + 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; }; diff --git a/components/esm4/loadltex.cpp b/components/esm4/loadltex.cpp index 55409c75ae..955ac938e3 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,25 +46,18 @@ void ESM4::LandTexture::load(ESM4::Reader& reader) break; case ESM4::SUB_HNAM: { - if (isFONV) + switch (subHdr.dataSize) { - 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 - { - reader.get(mHavokFriction); - reader.get(mHavokRestitution); - } - else - { - if (subHdr.dataSize != 3) - throw std::runtime_error("LTEX unexpected HNAM size, expected 3"); - reader.get(mHavokMaterial); - reader.get(mHavokFriction); - reader.get(mHavokRestitution); + case 3: // TES4, FO3, FNV + reader.get(mHavokMaterial); + [[fallthrough]]; + case 2: + reader.get(mHavokFriction); + reader.get(mHavokRestitution); + break; + default: + reader.skipSubRecordData(); + break; } break; } @@ -77,14 +68,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; 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: diff --git a/components/esm4/loadlvln.cpp b/components/esm4/loadlvln.cpp index b1efddc255..febdcbeca9 100644 --- a/components/esm4/loadlvln.cpp +++ b/components/esm4/loadlvln.cpp @@ -91,7 +91,13 @@ 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 + case ESM4::SUB_LLKC: // FO4 + case ESM4::SUB_LVLG: // FO4 + case ESM4::SUB_LVLM: // FO4 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 90ebe1566c..6dfd69148d 100644 --- a/components/esm4/loadmisc.cpp +++ b/components/esm4/loadmisc.cpp @@ -71,19 +71,28 @@ 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 - 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_CDIX: // FO4 + case ESM4::SUB_CVPA: // FO4 + case ESM4::SUB_FIMD: // FO4 + case ESM4::SUB_PTRN: // FO4 reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadmstt.cpp b/components/esm4/loadmstt.cpp index e216e5e003..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; @@ -53,16 +56,26 @@ 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_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_FULL: + case ESM4::SUB_MODF: // Model data end case ESM4::SUB_MODB: + case ESM4::SUB_PRPS: + case ESM4::SUB_PTRN: // FO4 reader.skipSubRecordData(); break; default: 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; diff --git a/components/esm4/loadnavi.cpp b/components/esm4/loadnavi.cpp index 553e0f2c73..09868d258f 100644 --- a/components/esm4/loadnavi.cpp +++ b/components/esm4/loadnavi.cpp @@ -249,6 +249,13 @@ void ESM4::Navigation::load(ESM4::Reader& reader) } case ESM4::SUB_NVPP: { + // FIXME: this is both the version for FO4 and for some TES4 files + // How to distinguish? + if (esmVer == ESM::VER_100) + { + reader.skipSubRecordData(); + break; + } std::uint32_t total; std::uint32_t count; reader.get(total); @@ -333,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) + // 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/FONV have different form of NavMeshInfo + reader.skipSubRecordData(); break; } diff --git a/components/esm4/loadnavm.cpp b/components/esm4/loadnavm.cpp index 0032d9b084..6298964f28 100644 --- a/components/esm4/loadnavm.cpp +++ b/components/esm4/loadnavm.cpp @@ -194,8 +194,8 @@ 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 // FIXME: debugging only #if 0 @@ -206,10 +206,19 @@ 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: { + // See FIXME in ESM4::Navigation::load. + // FO4 updates the format + if (esmVer == ESM::VER_100) + { + reader.skipSubRecordData(); + break; + } + NVNMstruct nvnm; nvnm.load(reader); mData.push_back(nvnm); // FIXME try swap @@ -218,24 +227,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 - { - const ESM4::SubRecordHeader& subHdr = reader.subRecordHeader(); - 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 @@ -245,11 +236,11 @@ 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: - 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 diff --git a/components/esm4/loadnote.cpp b/components/esm4/loadnote.cpp index b51600d966..9c1b4b3140 100644 --- a/components/esm4/loadnote.cpp +++ b/components/esm4/loadnote.cpp @@ -53,13 +53,29 @@ 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: + case ESM4::SUB_MODF: // Model data end case ESM4::SUB_ONAM: case ESM4::SUB_SNAM: 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; default: 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; diff --git a/components/esm4/loadnpc.cpp b/components/esm4/loadnpc.cpp index bd8c15d5bb..65292e63a8 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,28 @@ 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 - + 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: { - 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 +152,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 +227,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; @@ -234,33 +248,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: @@ -295,6 +291,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_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; 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: 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: diff --git a/components/esm4/loadrace.cpp b/components/esm4/loadrace.cpp index ef8f423963..28f91787e6 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 @@ -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); @@ -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); @@ -407,10 +415,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 +564,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; } @@ -566,11 +589,22 @@ 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) + { + 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 ") // << formIdToString(formId) << " " << currentIndex << std::endl; // FIXME @@ -668,13 +702,69 @@ 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_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 + 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/loadrefr.cpp b/components/esm4/loadrefr.cpp index 5c7ccc2235..a193907ac4 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; @@ -69,8 +66,26 @@ void ESM4::Reference::load(ESM4::Reader& reader) reader.get(mScale); break; case ESM4::SUB_XOWN: - reader.getFormId(mOwner); + { + switch (subHdr.dataSize) + { + case 4: + reader.getFormId(mOwner); + break; + case 12: + { + reader.getFormId(mOwner); + std::uint32_t dummy; + reader.get(dummy); // Unknown + reader.get(dummy); // No crime flag, FO4 + break; + } + default: + reader.skipSubRecordData(); + break; + } break; + } case ESM4::SUB_XGLB: reader.getFormId(mGlobal); break; @@ -87,13 +102,27 @@ 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 - mDoor.flags = 0; - // std::cout << "REFR dest door: " << formIdToString(mDoor.destDoor) << std::endl;// FIXME + switch (subHdr.dataSize) + { + case 28: + case 32: // FO3, FNV, TES5 + case 36: // FO4 + { + reader.getFormId(mDoor.destDoor); + reader.get(mDoor.destPos); + mDoor.flags = 0; + if (subHdr.dataSize >= 32) + { + reader.get(mDoor.flags); + if (subHdr.dataSize == 36) + reader.getFormId(mDoor.transitionInterior); + } + break; + } + default: + reader.skipSubRecordData(); + break; + } break; } case ESM4::SUB_XSED: @@ -201,6 +230,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 +318,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 +342,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..af04a791c8 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 transitionInterior; }; struct RadioStationData 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 // diff --git a/components/esm4/loadscol.cpp b/components/esm4/loadscol.cpp index a795b63d10..dea900fe17 100644 --- a/components/esm4/loadscol.cpp +++ b/components/esm4/loadscol.cpp @@ -46,11 +46,19 @@ 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: + 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_FLTR: // FO4 + case ESM4::SUB_PTRN: // FO4 reader.skipSubRecordData(); break; default: 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; 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; 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: diff --git a/components/esm4/loadstat.cpp b/components/esm4/loadstat.cpp index 770312c11b..e3b51633cf 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; @@ -81,11 +84,18 @@ 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 case ESM4::SUB_RNAM: // FONV + 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/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; diff --git a/components/esm4/loadtact.cpp b/components/esm4/loadtact.cpp index 14d29d18b1..ad5efb9fbf 100644 --- a/components/esm4/loadtact.cpp +++ b/components/esm4/loadtact.cpp @@ -62,15 +62,23 @@ 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? + 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 5f14085d2d..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,9 +72,14 @@ 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: // 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 +89,25 @@ 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_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: 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: 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/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; diff --git a/components/esm4/loadweap.cpp b/components/esm4/loadweap.cpp index d6fa4cac06..2b80305690 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,16 +135,17 @@ 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 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 @@ -149,11 +153,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 @@ -176,6 +184,21 @@ 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: + case ESM4::SUB_STOP: // FO4 object template end reader.skipSubRecordData(); break; default: diff --git a/components/esm4/loadwrld.cpp b/components/esm4/loadwrld.cpp index ec0ff908cd..c0a3044437 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); @@ -64,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; @@ -75,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; @@ -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: @@ -164,18 +149,23 @@ 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 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: diff --git a/components/esm4/reader.cpp b/components/esm4/reader.cpp index 02bd78116f..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) @@ -558,9 +573,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 +594,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; }