From acf8461841546f5691f3c2e817af7a0d59116433 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 21 Jan 2015 22:25:37 +0100 Subject: [PATCH] ESSImport: some fixes --- apps/essimporter/converter.cpp | 22 ++++++++++------------ apps/essimporter/converter.hpp | 9 +++++++-- apps/essimporter/importacdt.cpp | 10 ++++------ apps/essimporter/importacdt.hpp | 4 +++- apps/essimporter/importcellref.cpp | 21 ++++++++++++++++----- apps/essimporter/importcellref.hpp | 10 +++------- apps/essimporter/importcrec.cpp | 10 ++++++++++ apps/essimporter/importnpcc.cpp | 3 +++ 8 files changed, 56 insertions(+), 33 deletions(-) diff --git a/apps/essimporter/converter.cpp b/apps/essimporter/converter.cpp index 099987762..81521a028 100644 --- a/apps/essimporter/converter.cpp +++ b/apps/essimporter/converter.cpp @@ -27,6 +27,8 @@ namespace objstate.mEnabled = cellref.mEnabled; objstate.mPosition = cellref.mPos; objstate.mRef.mRefNum = cellref.mRefNum; + if (cellref.mDeleted) + objstate.mCount = 0; } bool isIndexedRefId(const std::string& indexedRefId) @@ -34,6 +36,10 @@ namespace if (indexedRefId.size() <= 8) return false; + if (indexedRefId.find_first_not_of("0123456789") == std::string::npos) + return false; // entirely numeric refid, this is a reference to + // a dynamically created record e.g. player-enchanted weapon + std::string index = indexedRefId.substr(indexedRefId.size()-8); if(index.find_first_not_of("0123456789ABCDEF") == std::string::npos ) return true; @@ -136,13 +142,6 @@ namespace ESSImport { CellRef ref; ref.load (esm); - if (esm.isNextSub("DELE")) - { - // TODO - // strangely this can be e.g. 52 instead of just 1, - //std::cout << "deleted ref " << ref.mIndexedRefId << std::endl; - esm.skipHSub(); - } cellrefs.push_back(ref); } @@ -201,8 +200,7 @@ namespace ESSImport for (std::vector::const_iterator refIt = cell.mRefs.begin(); refIt != cell.mRefs.end(); ++refIt) { const CellRef& cellref = *refIt; - ESM::CellRef out; - out.blank(); + ESM::CellRef out (cellref); if (!isIndexedRefId(cellref.mIndexedRefId)) { @@ -241,8 +239,8 @@ namespace ESSImport objstate.mRef.mRefID = idLower; // probably need more micromanagement here so we don't overwrite values // from the ESM with default values - convertACDT(cellref.mActorData.mACDT, objstate.mCreatureStats); - convertNpcData(cellref.mActorData, objstate.mNpcStats); + convertACDT(cellref.mACDT, objstate.mCreatureStats); + convertNpcData(cellref, objstate.mNpcStats); convertNPCC(npccIt->second, objstate); convertCellRef(cellref, objstate); esm.writeHNT ("OBJE", ESM::REC_NPC_); @@ -273,7 +271,7 @@ namespace ESSImport objstate.blank(); objstate.mRef = out; objstate.mRef.mRefID = idLower; - convertACDT(cellref.mActorData.mACDT, objstate.mCreatureStats); + convertACDT(cellref.mACDT, objstate.mCreatureStats); // probably need more micromanagement here so we don't overwrite values // from the ESM with default values convertCREC(crecIt->second, objstate); diff --git a/apps/essimporter/converter.hpp b/apps/essimporter/converter.hpp index b68f9a218..9f6ad49df 100644 --- a/apps/essimporter/converter.hpp +++ b/apps/essimporter/converter.hpp @@ -90,14 +90,19 @@ public: ESM::NPC npc; std::string id = esm.getHNString("NAME"); npc.load(esm); - if (id != "player") // seems to occur sometimes, with "chargen X" names + if (id != "player") + { + // this handles changes to the NPC struct, but since there is no index here + // it will apply to ALL instances of the class. seems to be the reason for the + // "feature" in MW where changing AI settings of one guard will change it for all guards of that refID. std::cerr << "non-player NPC record: " << id << std::endl; + } else { mContext->mPlayer.mObject.mCreatureStats.mLevel = npc.mNpdt52.mLevel; mContext->mPlayerBase = npc; std::map empty; - // FIXME: player start spells, racial spells and birthsign spells aren't listed here, + // FIXME: player start spells and birthsign spells aren't listed here, // need to fix openmw to account for this for (std::vector::const_iterator it = npc.mSpells.mList.begin(); it != npc.mSpells.mList.end(); ++it) mContext->mPlayer.mObject.mCreatureStats.mSpells.mSpells[*it] = empty; diff --git a/apps/essimporter/importacdt.cpp b/apps/essimporter/importacdt.cpp index 84c800897..4d4a87a35 100644 --- a/apps/essimporter/importacdt.cpp +++ b/apps/essimporter/importacdt.cpp @@ -9,18 +9,16 @@ namespace ESSImport void ActorData::load(ESM::ESMReader &esm) { - // unsure at which point between NAME and ESM::CellRef - if (esm.isNextSub("MNAM")) - esm.skipHSub(); - if (esm.isNextSub("ACTN")) esm.skipHSub(); if (esm.isNextSub("STPR")) esm.skipHSub(); - ESM::CellRef bla; - bla.ESM::CellRef::loadData(esm); + if (esm.isNextSub("MNAM")) + esm.skipHSub(); + + ESM::CellRef::loadData(esm); // FIXME: not all actors have this, add flag esm.getHNOT(mACDT, "ACDT"); diff --git a/apps/essimporter/importacdt.hpp b/apps/essimporter/importacdt.hpp index 79f67d2c2..271f6df74 100644 --- a/apps/essimporter/importacdt.hpp +++ b/apps/essimporter/importacdt.hpp @@ -3,6 +3,8 @@ #include +#include + namespace ESM { struct ESMReader; @@ -37,7 +39,7 @@ namespace ESSImport }; #pragma pack(pop) - struct ActorData + struct ActorData : public ESM::CellRef { ACDT mACDT; diff --git a/apps/essimporter/importcellref.cpp b/apps/essimporter/importcellref.cpp index fd58d5bc1..7c4af1e02 100644 --- a/apps/essimporter/importcellref.cpp +++ b/apps/essimporter/importcellref.cpp @@ -7,6 +7,8 @@ namespace ESSImport void CellRef::load(ESM::ESMReader &esm) { + blank(); + // (FRMR subrecord name is already read by the loop in ConvertCell) esm.getHT(mRefNum.mIndex); // FRMR @@ -25,17 +27,26 @@ namespace ESSImport esm.getHT(lvcr); //std::cout << "LVCR: " << (int)lvcr << std::endl; } - mActorData.load(esm); + ActorData::load(esm); mEnabled = true; esm.getHNOT(mEnabled, "ZNAM"); - // should occur for all references but not levelled creature spawners - esm.getHNOT(mPos, "DATA", 24); - - // i've seen DATA record TWICE on a creature record - and with the exact same content too! weird + // DATA should occur for all references, except leveled creature spawners + // I've seen DATA *twice* on a creature record, and with the exact same content too! weird // alarmvoi0000.ess esm.getHNOT(mPos, "DATA", 24); + esm.getHNOT(mPos, "DATA", 24); + + mDeleted = 0; + if (esm.isNextSub("DELE")) + { + int deleted; + esm.getHT(deleted); + // Neither of this seems to work right... + //mDeleted = (deleted != 0); + //mDeleted = (deleted&0x1); + } if (esm.isNextSub("MVRF")) { diff --git a/apps/essimporter/importcellref.hpp b/apps/essimporter/importcellref.hpp index 77763d434..556ed19bf 100644 --- a/apps/essimporter/importcellref.hpp +++ b/apps/essimporter/importcellref.hpp @@ -15,20 +15,16 @@ namespace ESM namespace ESSImport { - // Not sure if we can share any code with ESM::CellRef here - struct CellRef + struct CellRef : public ActorData { std::string mIndexedRefId; - ESM::RefNum mRefNum; - - ActorData mActorData; - - ESM::Position mPos; std::string mScript; bool mEnabled; + bool mDeleted; + void load(ESM::ESMReader& esm); }; diff --git a/apps/essimporter/importcrec.cpp b/apps/essimporter/importcrec.cpp index 9cf455588..28e5ac56f 100644 --- a/apps/essimporter/importcrec.cpp +++ b/apps/essimporter/importcrec.cpp @@ -14,6 +14,16 @@ namespace ESSImport float scale; esm.getHNOT(scale, "XSCL"); + // FIXME: use AiPackageList, need to fix getSubName() + if (esm.isNextSub("AI_W")) + esm.skipHSub(); + if (esm.isNextSub("AI_E")) + esm.skipHSub(); + if (esm.isNextSub("AI_T")) + esm.skipHSub(); + if (esm.isNextSub("AI_F")) + esm.skipHSub(); + mInventory.load(esm); } diff --git a/apps/essimporter/importnpcc.cpp b/apps/essimporter/importnpcc.cpp index c389ede7f..7b8dda371 100644 --- a/apps/essimporter/importnpcc.cpp +++ b/apps/essimporter/importnpcc.cpp @@ -9,6 +9,9 @@ namespace ESSImport { esm.getHNT(mNPDT, "NPDT"); + // FIXME: use AiPackageList, need to fix getSubName() + if (esm.isNextSub("AI_W")) + esm.skipHSub(); if (esm.isNextSub("AI_E")) esm.skipHSub(); if (esm.isNextSub("AI_T"))