1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-02-06 23:15:35 +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) 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) for (const auto* rec : recs)
if (rec->mIsTES4 || rec->mIsFONV || !(rec->mBaseConfig.tes5.templateFlags & flag)) {
if (rec->mIsTES4)
return rec; 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; return nullptr;
} }
@ -75,8 +90,8 @@ namespace MWClass
const MWWorld::ESMStore* store = MWBase::Environment::get().getESMStore(); const MWWorld::ESMStore* store = MWBase::Environment::get().getESMStore();
auto npcRecs = withBaseTemplates<ESM4::LevelledNpc, ESM4::Npc>(ptr.get<ESM4::Npc>()->mBase); auto npcRecs = withBaseTemplates<ESM4::LevelledNpc, ESM4::Npc>(ptr.get<ESM4::Npc>()->mBase);
data->mTraits = chooseTemplate(npcRecs, ESM4::Npc::TES5_UseTraits); data->mTraits = chooseTemplate(npcRecs, ESM4::Npc::Template_UseTraits);
data->mBaseData = chooseTemplate(npcRecs, ESM4::Npc::TES5_UseBaseData); data->mBaseData = chooseTemplate(npcRecs, ESM4::Npc::Template_UseBaseData);
if (!data->mTraits) if (!data->mTraits)
throw std::runtime_error("ESM4 NPC traits not found"); 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; data->mIsFemale = data->mTraits->mBaseConfig.tes4.flags & ESM4::Npc::TES4_Female;
else if (data->mTraits->mIsFONV) else if (data->mTraits->mIsFONV)
data->mIsFemale = data->mTraits->mBaseConfig.fo3.flags & ESM4::Npc::FO3_Female; 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 else
data->mIsFemale = data->mTraits->mBaseConfig.tes5.flags & ESM4::Npc::TES5_Female; 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) for (const ESM4::InventoryItem& item : inv->mInventory)
{ {

View file

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

View file

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