diff --git a/apps/essimporter/CMakeLists.txt b/apps/essimporter/CMakeLists.txt index add5ad6d05..4d53bc4cb3 100644 --- a/apps/essimporter/CMakeLists.txt +++ b/apps/essimporter/CMakeLists.txt @@ -5,7 +5,6 @@ set(ESSIMPORTER_FILES importnpcc.cpp importcrec.cpp importcellref.cpp - importacdt.cpp importinventory.cpp importklst.cpp importcntc.cpp diff --git a/apps/essimporter/converter.cpp b/apps/essimporter/converter.cpp index 3c08084ca9..97c20f5325 100644 --- a/apps/essimporter/converter.cpp +++ b/apps/essimporter/converter.cpp @@ -35,11 +35,11 @@ namespace objstate.mRef.mRefNum = cellref.mRefNum; if (cellref.mDeleted) objstate.mCount = 0; - convertSCRI(cellref.mSCRI, objstate.mLocals); + convertSCRI(cellref.mActorData.mSCRI, objstate.mLocals); objstate.mHasLocals = !objstate.mLocals.mVariables.empty(); - if (cellref.mHasANIS) - convertANIS(cellref.mANIS, objstate.mAnimationState); + if (cellref.mActorData.mHasANIS) + convertANIS(cellref.mActorData.mANIS, objstate.mAnimationState); } bool isIndexedRefId(const std::string& indexedRefId) @@ -268,7 +268,7 @@ namespace ESSImport } std::vector cellrefs; - while (esm.hasMoreSubs() && esm.isNextSub("FRMR")) + while (esm.hasMoreSubs() && esm.peekNextSub("FRMR")) { CellRef ref; ref.load (esm); @@ -369,13 +369,13 @@ namespace ESSImport objstate.mRef.mRefID = idLower; // TODO: need more micromanagement here so we don't overwrite values // from the ESM with default values - if (cellref.mHasACDT) - convertACDT(cellref.mACDT, objstate.mCreatureStats); + if (cellref.mActorData.mHasACDT) + convertACDT(cellref.mActorData.mACDT, objstate.mCreatureStats); else objstate.mCreatureStats.mMissingACDT = true; - if (cellref.mHasACSC) - convertACSC(cellref.mACSC, objstate.mCreatureStats); - convertNpcData(cellref, objstate.mNpcStats); + if (cellref.mActorData.mHasACSC) + convertACSC(cellref.mActorData.mACSC, objstate.mCreatureStats); + convertNpcData(cellref.mActorData, objstate.mNpcStats); convertNPCC(npccIt->second, objstate); convertCellRef(cellref, objstate); @@ -412,12 +412,12 @@ namespace ESSImport objstate.mRef.mRefID = idLower; // TODO: need more micromanagement here so we don't overwrite values // from the ESM with default values - if (cellref.mHasACDT) - convertACDT(cellref.mACDT, objstate.mCreatureStats); + if (cellref.mActorData.mHasACDT) + convertACDT(cellref.mActorData.mACDT, objstate.mCreatureStats); else objstate.mCreatureStats.mMissingACDT = true; - if (cellref.mHasACSC) - convertACSC(cellref.mACSC, objstate.mCreatureStats); + if (cellref.mActorData.mHasACSC) + convertACSC(cellref.mActorData.mACSC, objstate.mCreatureStats); convertCREC(crecIt->second, objstate); convertCellRef(cellref, objstate); diff --git a/apps/essimporter/converter.hpp b/apps/essimporter/converter.hpp index 4ae39b0e65..b22a7a5197 100644 --- a/apps/essimporter/converter.hpp +++ b/apps/essimporter/converter.hpp @@ -235,9 +235,9 @@ class ConvertREFR : public Converter public: void read(ESM::ESMReader &esm) override { - REFR refr; + CellRef refr; refr.load(esm); - assert(refr.mRefID == "PlayerSaveGame"); + assert(refr.mIndexedRefID == "PlayerSaveGame"); mContext->mPlayer.mObject.mPosition = refr.mPos; ESM::CreatureStats& cStats = mContext->mPlayer.mObject.mCreatureStats; diff --git a/apps/essimporter/importacdt.cpp b/apps/essimporter/importacdt.cpp deleted file mode 100644 index bab9b7b6b9..0000000000 --- a/apps/essimporter/importacdt.cpp +++ /dev/null @@ -1,137 +0,0 @@ -#include "importacdt.hpp" - -#include - -#include - -namespace ESSImport -{ - - void ActorData::load(ESM::ESMReader &esm) - { - blank(); - - if (esm.isNextSub("ACTN")) - { - /* - Activation flags: - ActivationFlag_UseEnabled = 1 - ActivationFlag_OnActivate = 2 - ActivationFlag_OnDeath = 10h - ActivationFlag_OnKnockout = 20h - ActivationFlag_OnMurder = 40h - ActivationFlag_DoorOpening = 100h - ActivationFlag_DoorClosing = 200h - ActivationFlag_DoorJammedOpening = 400h - ActivationFlag_DoorJammedClosing = 800h - */ - esm.skipHSub(); - } - - if (esm.isNextSub("STPR")) - esm.skipHSub(); - - if (esm.isNextSub("MNAM")) - esm.skipHSub(); - - bool isDeleted = false; - ESM::CellRef::loadData(esm, isDeleted); - - mHasACDT = false; - if (esm.isNextSub("ACDT")) - { - mHasACDT = true; - esm.getHT(mACDT); - } - - mHasACSC = false; - if (esm.isNextSub("ACSC")) - { - mHasACSC = true; - esm.getHT(mACSC); - } - - if (esm.isNextSub("ACSL")) - esm.skipHSubSize(112); - - if (esm.isNextSub("CSTN")) - esm.skipHSub(); // "PlayerSaveGame", link to some object? - - if (esm.isNextSub("LSTN")) - esm.skipHSub(); // "PlayerSaveGame", link to some object? - - // unsure at which point between LSTN and TGTN - if (esm.isNextSub("CSHN")) - esm.skipHSub(); // "PlayerSaveGame", link to some object? - - // unsure if before or after CSTN/LSTN - if (esm.isNextSub("LSHN")) - esm.skipHSub(); // "PlayerSaveGame", link to some object? - - while (esm.isNextSub("TGTN")) - esm.skipHSub(); // "PlayerSaveGame", link to some object? - - while (esm.isNextSub("FGTN")) - esm.getHString(); // fight target? - - // unsure at which point between TGTN and CRED - if (esm.isNextSub("AADT")) - { - // occurred when a creature was in the middle of its attack, 44 bytes - esm.skipHSub(); - } - - // unsure at which point between FGTN and CHRD - if (esm.isNextSub("PWPC")) - esm.skipHSub(); - if (esm.isNextSub("PWPS")) - esm.skipHSub(); - - if (esm.isNextSub("WNAM")) - { - std::string id = esm.getHString(); - - if (esm.isNextSub("XNAM")) - mSelectedEnchantItem = esm.getHString(); - else - mSelectedSpell = id; - - if (esm.isNextSub("YNAM")) - esm.skipHSub(); // 4 byte, 0 - } - - while (esm.isNextSub("APUD")) - { - // used power - esm.getSubHeader(); - std::string id = esm.getString(32); - (void)id; - // timestamp can't be used: this is the total hours passed, calculated by - // timestamp = 24 * (365 * year + cumulativeDays[month] + day) - // unfortunately cumulativeDays[month] is not clearly defined, - // in the (non-MCP) vanilla version the first month was missing, but MCP added it. - double timestamp; - esm.getT(timestamp); - } - - // FIXME: not all actors have this, add flag - if (esm.isNextSub("CHRD")) // npc only - esm.getHExact(mSkills, 27*2*sizeof(int)); - - if (esm.isNextSub("CRED")) // creature only - esm.getHExact(mCombatStats, 3*2*sizeof(int)); - - mSCRI.load(esm); - - if (esm.isNextSub("ND3D")) - esm.skipHSub(); - - mHasANIS = false; - if (esm.isNextSub("ANIS")) - { - mHasANIS = true; - esm.getHT(mANIS); - } - } - -} diff --git a/apps/essimporter/importacdt.hpp b/apps/essimporter/importacdt.hpp index 6ecb72e334..933cf0f577 100644 --- a/apps/essimporter/importacdt.hpp +++ b/apps/essimporter/importacdt.hpp @@ -3,8 +3,6 @@ #include -#include - #include "importscri.hpp" namespace ESM @@ -63,7 +61,7 @@ namespace ESSImport }; #pragma pack(pop) - struct ActorData : public ESM::CellRef + struct ActorData { bool mHasACDT; ACDT mACDT; @@ -85,10 +83,6 @@ namespace ESSImport bool mHasANIS; ANIS mANIS; // scripted animation state - - virtual void load(ESM::ESMReader& esm); - - virtual ~ActorData() = default; }; } diff --git a/apps/essimporter/importcellref.cpp b/apps/essimporter/importcellref.cpp index 22af1af5fa..3de1f73e70 100644 --- a/apps/essimporter/importcellref.cpp +++ b/apps/essimporter/importcellref.cpp @@ -9,8 +9,7 @@ namespace ESSImport { blank(); - // (FRMR subrecord name is already read by the loop in ConvertCell) - esm.getHT(mRefNum.mIndex); // FRMR + esm.getHNT(mRefNum.mIndex, "FRMR"); // this is required since openmw supports more than 255 content files int pluginIndex = (mRefNum.mIndex & 0xff000000) >> 24; @@ -19,7 +18,128 @@ namespace ESSImport mIndexedRefId = esm.getHNString("NAME"); - ActorData::load(esm); + if (esm.isNextSub("ACTN")) + { + /* + Activation flags: + ActivationFlag_UseEnabled = 1 + ActivationFlag_OnActivate = 2 + ActivationFlag_OnDeath = 10h + ActivationFlag_OnKnockout = 20h + ActivationFlag_OnMurder = 40h + ActivationFlag_DoorOpening = 100h + ActivationFlag_DoorClosing = 200h + ActivationFlag_DoorJammedOpening = 400h + ActivationFlag_DoorJammedClosing = 800h + */ + esm.skipHSub(); + } + + if (esm.isNextSub("STPR")) + esm.skipHSub(); + + if (esm.isNextSub("MNAM")) + esm.skipHSub(); + + bool isDeleted = false; + ESM::CellRef::loadData(esm, isDeleted); + + mActorData.mHasACDT = false; + if (esm.isNextSub("ACDT")) + { + mActorData.mHasACDT = true; + esm.getHT(mActorData.mACDT); + } + + mActorData.mHasACSC = false; + if (esm.isNextSub("ACSC")) + { + mActorData.mHasACSC = true; + esm.getHT(mActorData.mACSC); + } + + if (esm.isNextSub("ACSL")) + esm.skipHSubSize(112); + + if (esm.isNextSub("CSTN")) + esm.skipHSub(); // "PlayerSaveGame", link to some object? + + if (esm.isNextSub("LSTN")) + esm.skipHSub(); // "PlayerSaveGame", link to some object? + + // unsure at which point between LSTN and TGTN + if (esm.isNextSub("CSHN")) + esm.skipHSub(); // "PlayerSaveGame", link to some object? + + // unsure if before or after CSTN/LSTN + if (esm.isNextSub("LSHN")) + esm.skipHSub(); // "PlayerSaveGame", link to some object? + + while (esm.isNextSub("TGTN")) + esm.skipHSub(); // "PlayerSaveGame", link to some object? + + while (esm.isNextSub("FGTN")) + esm.getHString(); // fight target? + + // unsure at which point between TGTN and CRED + if (esm.isNextSub("AADT")) + { + // occurred when a creature was in the middle of its attack, 44 bytes + esm.skipHSub(); + } + + // unsure at which point between FGTN and CHRD + if (esm.isNextSub("PWPC")) + esm.skipHSub(); + if (esm.isNextSub("PWPS")) + esm.skipHSub(); + + if (esm.isNextSub("WNAM")) + { + std::string id = esm.getHString(); + + if (esm.isNextSub("XNAM")) + mActorData.mSelectedEnchantItem = esm.getHString(); + else + mActorData.mSelectedSpell = id; + + if (esm.isNextSub("YNAM")) + esm.skipHSub(); // 4 byte, 0 + } + + while (esm.isNextSub("APUD")) + { + // used power + esm.getSubHeader(); + std::string id = esm.getString(32); + (void)id; + // timestamp can't be used: this is the total hours passed, calculated by + // timestamp = 24 * (365 * year + cumulativeDays[month] + day) + // unfortunately cumulativeDays[month] is not clearly defined, + // in the (non-MCP) vanilla version the first month was missing, but MCP added it. + double timestamp; + esm.getT(timestamp); + } + + // FIXME: not all actors have this, add flag + if (esm.isNextSub("CHRD")) // npc only + esm.getHExact(mActorData.mSkills, 27*2*sizeof(int)); + + if (esm.isNextSub("CRED")) // creature only + esm.getHExact(mActorData.mCombatStats, 3*2*sizeof(int)); + + mActorData.mSCRI.load(esm); + + if (esm.isNextSub("ND3D")) + esm.skipHSub(); + + mActorData.mHasANIS = false; + if (esm.isNextSub("ANIS")) + { + mActorData.mHasANIS = true; + esm.getHT(mActorData.mANIS); + } + if (esm.isNextSub("LVCR")) { // occurs on levelled creature spawner references diff --git a/apps/essimporter/importcellref.hpp b/apps/essimporter/importcellref.hpp index d69a0a829d..dfc44711e6 100644 --- a/apps/essimporter/importcellref.hpp +++ b/apps/essimporter/importcellref.hpp @@ -15,7 +15,7 @@ namespace ESM namespace ESSImport { - struct CellRef : public ActorData + struct CellRef : public ESM::CellRef { std::string mIndexedRefId; @@ -25,9 +25,11 @@ namespace ESSImport bool mDeleted; - void load(ESM::ESMReader& esm) override; + ActorData mActorData; - ~CellRef() override = default; + void load(ESM::ESMReader& esm); + + ~CellRef() = default; }; } diff --git a/apps/essimporter/importplayer.cpp b/apps/essimporter/importplayer.cpp index f2ec57ab3f..3285ac15e3 100644 --- a/apps/essimporter/importplayer.cpp +++ b/apps/essimporter/importplayer.cpp @@ -5,17 +5,6 @@ namespace ESSImport { - void REFR::load(ESM::ESMReader &esm) - { - esm.getHNT(mRefNum.mIndex, "FRMR"); - - mRefID = esm.getHNString("NAME"); - - mActorData.load(esm); - - esm.getHNOTSized<24>(mPos, "DATA"); - } - void PCDT::load(ESM::ESMReader &esm) { while (esm.isNextSub("DNAM")) diff --git a/apps/essimporter/importplayer.hpp b/apps/essimporter/importplayer.hpp index 6c8f211c57..2f1a689510 100644 --- a/apps/essimporter/importplayer.hpp +++ b/apps/essimporter/importplayer.hpp @@ -18,18 +18,6 @@ namespace ESM namespace ESSImport { -/// Player-agnostic player data -struct REFR -{ - ActorData mActorData; - - std::string mRefID; - ESM::Position mPos; - ESM::RefNum mRefNum; - - void load(ESM::ESMReader& esm); -}; - /// Other player data struct PCDT {