diff --git a/apps/openmw/mwclass/esm4npc.cpp b/apps/openmw/mwclass/esm4npc.cpp
index 78cbd89b50..13e7866537 100644
--- a/apps/openmw/mwclass/esm4npc.cpp
+++ b/apps/openmw/mwclass/esm4npc.cpp
@@ -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)
             {
diff --git a/components/esm4/loadnpc.cpp b/components/esm4/loadnpc.cpp
index 251af13630..885263d67b 100644
--- a/components/esm4/loadnpc.cpp
+++ b/components/esm4/loadnpc.cpp
@@ -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:
diff --git a/components/esm4/loadnpc.hpp b/components/esm4/loadnpc.hpp
index 6f4b3c7e24..04e56b7bd9 100644
--- a/components/esm4/loadnpc.hpp
+++ b/components/esm4/loadnpc.hpp
@@ -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;