/* Copyright (C) 2016, 2018-2021 cc9cii This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. cc9cii cc9c@iinet.net.au Much of the information on the data structures are based on the information from Tes4Mod:Mod_File_Format and Tes5Mod:File_Formats but also refined by trial & error. See http://en.uesp.net/wiki for details. */ #ifndef ESM4_NPC__H #define ESM4_NPC__H #include #include #include #include #include #include "actor.hpp" #include "inventory.hpp" namespace ESM4 { class Reader; class Writer; struct Npc { enum ACBS_TES4 { TES4_Female = 0x000001, TES4_Essential = 0x000002, TES4_Respawn = 0x000008, TES4_AutoCalcStats = 0x000010, TES4_PCLevelOffset = 0x000080, TES4_NoLowLevelProc = 0x000200, TES4_NoRumors = 0x002000, TES4_Summonable = 0x004000, TES4_NoPersuasion = 0x008000, // different meaning to crea TES4_CanCorpseCheck = 0x100000 // opposite of crea }; enum ACBS_FO3 { FO3_Female = 0x00000001, FO3_Essential = 0x00000002, FO3_PresetFace = 0x00000004, // Is CharGen Face Preset FO3_Respawn = 0x00000008, FO3_AutoCalcStats = 0x00000010, FO3_PCLevelMult = 0x00000080, FO3_UseTemplate = 0x00000100, FO3_NoLowLevelProc = 0x00000200, FO3_NoBloodSpray = 0x00000800, FO3_NoBloodDecal = 0x00001000, FO3_NoVATSMelee = 0x00100000, FO3_AnyRace = 0x00400000, FO3_AutoCalcServ = 0x00800000, FO3_NoKnockdown = 0x04000000, FO3_NotPushable = 0x08000000, FO3_NoRotateHead = 0x40000000 }; // In FO4 flags seem to be the same. enum ACBS_TES5 { TES5_Female = 0x00000001, TES5_Essential = 0x00000002, TES5_PresetFace = 0x00000004, // Is CharGen Face Preset TES5_Respawn = 0x00000008, TES5_AutoCalcStats = 0x00000010, TES5_Unique = 0x00000020, TES5_NoStealth = 0x00000040, // Doesn't affect stealth meter TES5_PCLevelMult = 0x00000080, // TES5_Unknown = 0x00000100, // Audio template? TES5_Protected = 0x00000800, TES5_Summonable = 0x00004000, TES5_NoBleeding = 0x00010000, TES5_Owned = 0x00040000, // owned/follow? (Horses, Atronachs, NOT Shadowmere) TES5_GenderAnim = 0x00080000, // Opposite Gender Anims TES5_SimpleActor = 0x00100000, TES5_LoopedScript = 0x00200000, // AAvenicci, Arcadia, Silvia, Afflicted, TortureVictims TES5_LoopedAudio = 0x10000000, // AAvenicci, Arcadia, Silvia, DA02 Cultists, Afflicted, TortureVictims TES5_IsGhost = 0x20000000, // Ghost/non-interactable (Ghosts, Nocturnal) TES5_Invulnerable = 0x80000000 }; // All FO3+ games. enum Template_Flags { 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) struct SkillValues { std::uint8_t armorer; std::uint8_t athletics; std::uint8_t blade; std::uint8_t block; std::uint8_t blunt; std::uint8_t handToHand; std::uint8_t heavyArmor; std::uint8_t alchemy; std::uint8_t alteration; std::uint8_t conjuration; std::uint8_t destruction; std::uint8_t illusion; std::uint8_t mysticism; std::uint8_t restoration; std::uint8_t acrobatics; std::uint8_t lightArmor; std::uint8_t marksman; std::uint8_t mercantile; std::uint8_t security; std::uint8_t sneak; std::uint8_t speechcraft; }; struct HairColour { std::uint8_t red; std::uint8_t green; std::uint8_t blue; std::uint8_t custom; // alpha? }; struct Data { SkillValues skills; std::uint32_t health; AttributeValues attribs; }; #pragma pack(pop) ESM::FormId mId; // from the header std::uint32_t mFlags; // from the header, see enum type RecordFlag for details bool mIsTES4; bool mIsFONV; bool mIsFO4 = false; std::string mEditorId; std::string mFullName; std::string mModel; // skeleton model (can be a marker in FO3/FONV) ESM::FormId mRace; ESM::FormId mClass; ESM::FormId mHair; // not for TES5, see mHeadParts ESM::FormId mEyes; std::vector mHeadParts; // FO3/FONV/TES5 float mHairLength; HairColour mHairColour; // TES4/FO3/FONV ESM::FormId mHairColourId; // TES5 ESM::FormId mBeardColourId; // FO4 ESM::FormId mDeathItem; std::vector mSpell; ESM::FormId mScriptId; AIData mAIData; std::vector mAIPackages; // seems to be in priority order, 0 = highest priority ActorBaseConfig mBaseConfig; // union ActorFaction mFaction; Data mData; ESM::FormId mCombatStyle; ESM::FormId mSoundBase; ESM::FormId mSound; std::uint8_t mSoundChance; float mFootWeight; float mBoundRadius; std::vector mKf; // filenames only, get directory path from mModel std::vector mInventory; ESM::FormId mBaseTemplate; // FO3/FONV/TES5 ESM::FormId mWornArmor; // TES5 only? ESM::FormId mDefaultOutfit; // TES5 OTFT ESM::FormId mSleepOutfit; // TES5 OTFT ESM::FormId mDefaultPkg; std::vector mSymShapeModeCoefficients; // size 0 or 50 std::vector mAsymShapeModeCoefficients; // size 0 or 30 std::vector mSymTextureModeCoefficients; // size 0 or 50 std::int16_t mFgRace; void load(ESM4::Reader& reader); // void save(ESM4::Writer& writer) const; // void blank(); static constexpr ESM::RecNameInts sRecordId = ESM::RecNameInts::REC_NPC_4; }; } #endif // ESM4_NPC__H