mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-16 16:29:55 +00:00
Merge branch 'fallout4' into 'master'
ESM4 Loader: initial Fallout 4 support See merge request OpenMW/openmw!3347
This commit is contained in:
commit
16628a766f
74 changed files with 1791 additions and 823 deletions
|
@ -329,8 +329,7 @@ namespace EsmTool
|
|||
readTypedRecord<ESM4::HeadPart>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_IDLE:
|
||||
// FIXME: ESM4::IdleAnimation::load does not work with Oblivion.esm
|
||||
// readTypedRecord<ESM4::IdleAnimation>(params, reader);
|
||||
readTypedRecord<ESM4::IdleAnimation>(params, reader);
|
||||
return true;
|
||||
break;
|
||||
case ESM4::REC_IDLM:
|
||||
|
|
|
@ -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<QString> 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)
|
||||
|
|
|
@ -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
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -58,8 +58,26 @@ void ESM4::ActorCharacter::load(ESM4::Reader& reader)
|
|||
reader.get(mScale);
|
||||
break;
|
||||
case ESM4::SUB_XOWN:
|
||||
{
|
||||
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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -48,8 +48,10 @@ 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)
|
||||
{
|
||||
case 18: // TES4
|
||||
case 13: // FO3/FNV
|
||||
{
|
||||
reader.get(mData.mSpeed);
|
||||
reader.get(mData.mFlags);
|
||||
|
@ -64,20 +66,24 @@ void ESM4::Ammunition::load(ESM4::Reader& reader)
|
|||
reader.get(damageInt);
|
||||
mData.mDamage = static_cast<float>(damageInt);
|
||||
}
|
||||
break;
|
||||
}
|
||||
// TES5/SSE
|
||||
else if (subHdr.dataSize == 16 || 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);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
case 8:
|
||||
reader.get(mData.mValue);
|
||||
reader.get(mData.mWeight);
|
||||
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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
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:
|
||||
|
|
|
@ -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)
|
||||
switch (subHdr.dataSize)
|
||||
{
|
||||
case 14: // TES4
|
||||
reader.get(mData);
|
||||
break;
|
||||
case 12: // FO3, FNV, FO4
|
||||
reader.get(mData.value);
|
||||
reader.get(mData.health);
|
||||
reader.get(mData.weight);
|
||||
}
|
||||
else
|
||||
{
|
||||
reader.get(mData); // TES4
|
||||
mIsTES4 = true;
|
||||
}
|
||||
|
||||
break;
|
||||
case 8: // TES5
|
||||
reader.get(mData.value);
|
||||
reader.get(mData.weight);
|
||||
break;
|
||||
default:
|
||||
reader.skipSubRecordData();
|
||||
break;
|
||||
}
|
||||
case ESM4::SUB_MODL: // seems only for Dawnguard/Dragonborn?
|
||||
break;
|
||||
}
|
||||
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.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:
|
||||
// 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:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -53,23 +53,34 @@ void ESM4::Book::load(ESM4::Reader& reader)
|
|||
break;
|
||||
case ESM4::SUB_DATA:
|
||||
{
|
||||
switch (subHdr.dataSize)
|
||||
{
|
||||
case 10: // TES4, FO3, FNV
|
||||
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
|
||||
{
|
||||
static std::uint8_t dummy;
|
||||
reader.get(mData.type);
|
||||
reader.get(dummy);
|
||||
reader.get(dummy);
|
||||
reader.get(mData.teaches);
|
||||
}
|
||||
else
|
||||
{
|
||||
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;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ESM4::SUB_ICON:
|
||||
reader.getZString(mIcon);
|
||||
|
@ -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:
|
||||
|
|
|
@ -78,7 +78,11 @@ void ESM4::BodyPartData::load(ESM4::Reader& reader)
|
|||
reader.getZString(bodyPart.mIKStartNode);
|
||||
break;
|
||||
case ESM4::SUB_BPND:
|
||||
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:
|
||||
|
|
|
@ -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
|
||||
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,7 +119,6 @@ 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
|
||||
|
@ -139,17 +129,6 @@ void ESM4::Cell::load(ESM4::Reader& reader)
|
|||
reader.get(value);
|
||||
mCellFlags = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::uint8_t value = 0;
|
||||
reader.get(value); // 8 bits in Obvlivion
|
||||
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:
|
||||
{
|
||||
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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<ESM::FormId> mObjects;
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace ESM4
|
|||
|
||||
struct GameSetting
|
||||
{
|
||||
using Data = std::variant<std::monostate, bool, float, std::int32_t, std::string>;
|
||||
using Data = std::variant<std::monostate, bool, float, std::int32_t, std::string, std::uint32_t>;
|
||||
|
||||
ESM::FormId mId; // from the header
|
||||
std::uint32_t mFlags; // from the header, see enum type RecordFlag for details
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -51,9 +51,29 @@ void ESM4::IdleAnimation::load(ESM4::Reader& reader)
|
|||
reader.getZString(mEvent);
|
||||
break;
|
||||
case ESM4::SUB_ANAM:
|
||||
{
|
||||
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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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.nearClip);
|
||||
reader.get(mData.frequency);
|
||||
reader.get(mData.intensityAmplitude);
|
||||
reader.get(mData.movementAmplitude);
|
||||
}
|
||||
else if (subHdr.dataSize == 32) // TES4
|
||||
if (subHdr.dataSize == 64)
|
||||
{
|
||||
reader.get(mData.falloff);
|
||||
reader.get(mData.FOV);
|
||||
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:
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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");
|
||||
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));
|
||||
}
|
||||
|
|
|
@ -49,14 +49,14 @@ namespace ESM4
|
|||
std::uint8_t mHavokRestitution;
|
||||
|
||||
std::uint8_t mTextureSpecular; // default 30
|
||||
ESM::FormId mGrass;
|
||||
std::vector<ESM::FormId> mGrass;
|
||||
|
||||
// ------ TES4 only -----
|
||||
|
||||
std::string mTextureFile;
|
||||
std::uint8_t mHavokMaterial;
|
||||
|
||||
// ------ TES5 only -----
|
||||
// ------ TES5, FO4 -----
|
||||
|
||||
ESM::FormId mTexture;
|
||||
ESM::FormId mMaterial;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -73,6 +73,10 @@ void ESM4::Npc::load(ESM4::Reader& reader)
|
|||
break;
|
||||
case ESM4::SUB_SNAM:
|
||||
{
|
||||
// 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;
|
||||
|
||||
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<unsigned char> 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:
|
||||
|
|
|
@ -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<ESM::FormId> mSpell;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
@ -406,11 +414,17 @@ void ESM4::Race::load(ESM4::Reader& reader)
|
|||
break; /* 3, 6, 8 */
|
||||
//
|
||||
case ESM4::SUB_HNAM:
|
||||
{
|
||||
// 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:
|
||||
{
|
||||
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);
|
||||
|
||||
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:
|
||||
|
|
|
@ -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:
|
||||
{
|
||||
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;
|
||||
|
@ -86,14 +101,28 @@ void ESM4::Reference::load(ESM4::Reader& reader)
|
|||
break;
|
||||
}
|
||||
case ESM4::SUB_XTEL:
|
||||
{
|
||||
switch (subHdr.dataSize)
|
||||
{
|
||||
case 28:
|
||||
case 32: // FO3, FNV, TES5
|
||||
case 36: // FO4
|
||||
{
|
||||
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
|
||||
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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
//
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -68,10 +68,25 @@ void ESM4::SoundReference::load(ESM4::Reader& reader)
|
|||
reader.get(mLoopInfo);
|
||||
break;
|
||||
case ESM4::SUB_BNAM:
|
||||
{
|
||||
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:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -57,7 +57,11 @@ void ESM4::Terminal::load(ESM4::Reader& reader)
|
|||
reader.getFormId(mPasswordNote);
|
||||
break;
|
||||
case ESM4::SUB_SNAM:
|
||||
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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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<int>(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);
|
||||
|
||||
if (mIgnoreMissingLocalizedStrings && !mVFS->exists(vfsPath))
|
||||
std::string vfsPath = Files::pathToUnicodeString(path);
|
||||
if (!mVFS->exists(vfsPath))
|
||||
{
|
||||
Log(Debug::Warning) << "Ignore missing VFS strings file: " << vfsPath;
|
||||
return;
|
||||
path = strings / (prefix + altLanguage + suffix);
|
||||
vfsPath = Files::pathToUnicodeString(path);
|
||||
}
|
||||
|
||||
if (mVFS->exists(vfsPath))
|
||||
{
|
||||
const Files::IStreamPtr stream = mVFS->get(vfsPath);
|
||||
buildLStringIndex(stringType, *stream);
|
||||
return;
|
||||
}
|
||||
|
||||
const std::filesystem::path fsPath = mCtx.filename.parent_path() / path;
|
||||
|
||||
if (mIgnoreMissingLocalizedStrings && !std::filesystem::exists(fsPath))
|
||||
if (mIgnoreMissingLocalizedStrings)
|
||||
{
|
||||
Log(Debug::Warning) << "Ignore missing strings file: " << fsPath;
|
||||
Log(Debug::Warning) << "Ignore missing VFS strings file: " << vfsPath;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
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 (std::filesystem::exists(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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue