1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-01-01 03:21:41 +00:00

Use correct template flags for FONV and FO4 NPCs

This commit is contained in:
Petr Mikheev 2023-10-31 11:47:42 +01:00
parent bff4666b7b
commit 6c01ce2672
3 changed files with 53 additions and 26 deletions

View File

@ -34,11 +34,26 @@ namespace MWClass
static const ESM4::Npc* chooseTemplate(const std::vector<const ESM4::Npc*>& recs, uint16_t flag)
{
// In case of FO3 the function may return nullptr that will lead to "ESM4 NPC traits not found"
// exception and the NPC will not be added to the scene. But in any way it shouldn't cause a crash.
for (const auto* rec : recs)
if (rec->mIsTES4 || rec->mIsFONV || !(rec->mBaseConfig.tes5.templateFlags & flag))
{
if (rec->mIsTES4)
return rec;
else if (rec->mIsFONV)
{
// TODO: FO3 should use this branch as well. But it is not clear how to distinguish FO3 from
// TES5. Currently FO3 uses wrong template flags that can lead to "ESM4 NPC traits not found"
// exception the NPC will not be added to the scene. But in any way it shouldn't cause a crash.
if (!(rec->mBaseConfig.fo3.templateFlags & flag))
return rec;
}
else if (rec->mIsFO4)
{
if (!(rec->mBaseConfig.fo4.templateFlags & flag))
return rec;
}
else if (!(rec->mBaseConfig.tes5.templateFlags & flag))
return rec;
}
return nullptr;
}
@ -75,8 +90,8 @@ namespace MWClass
const MWWorld::ESMStore* store = MWBase::Environment::get().getESMStore();
auto npcRecs = withBaseTemplates<ESM4::LevelledNpc, ESM4::Npc>(ptr.get<ESM4::Npc>()->mBase);
data->mTraits = chooseTemplate(npcRecs, ESM4::Npc::TES5_UseTraits);
data->mBaseData = chooseTemplate(npcRecs, ESM4::Npc::TES5_UseBaseData);
data->mTraits = chooseTemplate(npcRecs, ESM4::Npc::Template_UseTraits);
data->mBaseData = chooseTemplate(npcRecs, ESM4::Npc::Template_UseBaseData);
if (!data->mTraits)
throw std::runtime_error("ESM4 NPC traits not found");
@ -88,10 +103,13 @@ namespace MWClass
data->mIsFemale = data->mTraits->mBaseConfig.tes4.flags & ESM4::Npc::TES4_Female;
else if (data->mTraits->mIsFONV)
data->mIsFemale = data->mTraits->mBaseConfig.fo3.flags & ESM4::Npc::FO3_Female;
else if (data->mTraits->mIsFO4)
data->mIsFemale
= data->mTraits->mBaseConfig.fo4.flags & ESM4::Npc::TES5_Female; // FO4 flags are same as TES5
else
data->mIsFemale = data->mTraits->mBaseConfig.tes5.flags & ESM4::Npc::TES5_Female;
if (auto inv = chooseTemplate(npcRecs, ESM4::Npc::TES5_UseInventory))
if (auto inv = chooseTemplate(npcRecs, ESM4::Npc::Template_UseInventory))
{
for (const ESM4::InventoryItem& item : inv->mInventory)
{

View File

@ -116,9 +116,11 @@ void ESM4::Npc::load(ESM4::Reader& reader)
{
switch (subHdr.dataSize)
{
case 20: // FO4
mIsFO4 = true;
[[fallthrough]];
case 16: // TES4
case 24: // FO3/FNV, TES5
case 20: // FO4
reader.get(&mBaseConfig, subHdr.dataSize);
break;
default:

View File

@ -78,6 +78,7 @@ namespace ESM4
FO3_NoRotateHead = 0x40000000
};
// In FO4 flags seem to be the same.
enum ACBS_TES5
{
TES5_Female = 0x00000001,
@ -101,27 +102,32 @@ namespace ESM4
TES5_Invulnerable = 0x80000000
};
// All FO3+ games.
enum Template_Flags
{
TES5_UseTraits = 0x0001, // Destructible Object; Traits tab, including race, gender, height, weight,
// voice type, death item; Sounds tab; Animation tab; Character Gen tabs
TES5_UseStats = 0x0002, // Stats tab, including level, autocalc, skills, health/magicka/stamina,
// speed, bleedout, class
TES5_UseFactions = 0x0004, // both factions and assigned crime faction
TES5_UseSpellList = 0x0008, // both spells and perks
TES5_UseAIData = 0x0010, // AI Data tab, including aggression/confidence/morality, combat style and
// gift filter
TES5_UseAIPackage = 0x0020, // only the basic Packages listed on the AI Packages tab;
// rest of tab controlled by Def Pack List
TES5_UseBaseData = 0x0080, // including name and short name, and flags for Essential, Protected,
// Respawn, Summonable, Simple Actor, and Doesn't affect stealth meter
TES5_UseInventory = 0x0100, // Inventory tab, including all outfits and geared-up item
// -- but not death item
TES5_UseScript = 0x0200,
TES5_UseDefined = 0x0400, // Def Pack List (the dropdown-selected package lists on the AI Packages tab)
TES5_UseAtkData = 0x0800, // Attack Data tab, including override from behavior graph race,
// events, and data)
TES5_UseKeywords = 0x1000
Template_UseTraits = 0x0001, // Destructible Object; Traits tab, including race, gender, height, weight,
// voice type, death item; Sounds tab; Animation tab; Character Gen tabs
Template_UseStats = 0x0002, // Stats tab, including level, autocalc, skills, health/magicka/stamina,
// speed, bleedout, class
Template_UseFactions = 0x0004, // both factions and assigned crime faction
Template_UseSpellList = 0x0008, // both spells and perks
Template_UseAIData = 0x0010, // AI Data tab, including aggression/confidence/morality, combat style and
// gift filter
Template_UseAIPackage = 0x0020, // only the basic Packages listed on the AI Packages tab;
// rest of tab controlled by Def Pack List
Template_UseModel = 0x0040, // FO3, FONV; probably not used in TES5+
Template_UseBaseData = 0x0080, // including name and short name, and flags for Essential, Protected,
// Respawn, Summonable, Simple Actor, and Doesn't affect stealth meter
Template_UseInventory = 0x0100, // Inventory tab, including all outfits and geared-up item,
// but not death item
Template_UseScript = 0x0200,
// The following flags were added in TES5+:
Template_UseDefined = 0x0400, // Def Pack List (the dropdown-selected package lists on the AI Packages tab)
Template_UseAtkData = 0x0800, // Attack Data tab, including override from behavior graph race,
// events, and data)
Template_UseKeywords = 0x1000
};
#pragma pack(push, 1)
@ -172,6 +178,7 @@ namespace ESM4
bool mIsTES4;
bool mIsFONV;
bool mIsFO4 = false;
std::string mEditorId;
std::string mFullName;