From 08ad4d73bbf9873887a8c6716c37b641e2603026 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 18 Jan 2015 19:59:29 +0100 Subject: [PATCH] ESSImport: player is placed in correct cell, npc cellrefs work --- apps/essimporter/CMakeLists.txt | 4 ++- apps/essimporter/convertacdt.cpp | 42 ++++++++++++++++++++++ apps/essimporter/convertacdt.hpp | 22 ++++++++++++ apps/essimporter/converter.cpp | 54 +++++++++++++++++++++------- apps/essimporter/converter.hpp | 40 +++++---------------- apps/essimporter/convertnpcc.cpp | 22 ++++++++++++ apps/essimporter/convertnpcc.hpp | 15 ++++++++ apps/essimporter/importacdt.cpp | 28 +++++++++++++++ apps/essimporter/importacdt.hpp | 24 +++++++++++++ apps/essimporter/importcellref.cpp | 19 +++++----- apps/essimporter/importcellref.hpp | 4 ++- apps/essimporter/importer.cpp | 19 ++++++++-- apps/essimporter/importercontext.hpp | 30 +++------------- apps/essimporter/importnpcc.cpp | 25 ++++++++++--- apps/essimporter/importnpcc.hpp | 12 +++++-- apps/essimporter/importplayer.cpp | 14 +++----- apps/essimporter/importplayer.hpp | 5 +-- components/esm/creaturestate.cpp | 8 ++++- components/esm/creaturestate.hpp | 3 ++ components/esm/creaturestats.cpp | 36 +++++++++++++++++-- components/esm/creaturestats.hpp | 3 ++ components/esm/npcstate.cpp | 9 ++++- components/esm/npcstate.hpp | 3 ++ components/esm/npcstats.cpp | 15 ++++++++ components/esm/npcstats.hpp | 3 ++ components/esm/objectstate.cpp | 16 ++++++++- components/esm/objectstate.hpp | 5 ++- 27 files changed, 370 insertions(+), 110 deletions(-) create mode 100644 apps/essimporter/convertacdt.cpp create mode 100644 apps/essimporter/convertacdt.hpp create mode 100644 apps/essimporter/convertnpcc.cpp create mode 100644 apps/essimporter/convertnpcc.hpp create mode 100644 apps/essimporter/importacdt.cpp diff --git a/apps/essimporter/CMakeLists.txt b/apps/essimporter/CMakeLists.txt index 231e31fd8..257a466ee 100644 --- a/apps/essimporter/CMakeLists.txt +++ b/apps/essimporter/CMakeLists.txt @@ -5,9 +5,11 @@ set(ESSIMPORTER_FILES importnpcc.cpp importcrec.cpp importcellref.cpp - importacdt.hpp + importacdt.cpp importercontext.cpp converter.cpp + convertacdt.cpp + convertnpcc.cpp ) add_executable(openmw-essimporter diff --git a/apps/essimporter/convertacdt.cpp b/apps/essimporter/convertacdt.cpp new file mode 100644 index 000000000..81ab61084 --- /dev/null +++ b/apps/essimporter/convertacdt.cpp @@ -0,0 +1,42 @@ +#include "convertacdt.hpp" + +namespace ESSImport +{ + + int translateDynamicIndex(int mwIndex) + { + if (mwIndex == 1) + return 2; + else if (mwIndex == 2) + return 1; + return mwIndex; + } + + void convertACDT (const ACDT& acdt, ESM::CreatureStats& cStats) + { + for (int i=0; i<3; ++i) + { + int writeIndex = translateDynamicIndex(i); + cStats.mDynamic[writeIndex].mBase = acdt.mDynamic[i][1]; + cStats.mDynamic[writeIndex].mMod = acdt.mDynamic[i][1]; + cStats.mDynamic[writeIndex].mCurrent = acdt.mDynamic[i][0]; + } + for (int i=0; i<8; ++i) + { + cStats.mAttributes[i].mBase = acdt.mAttributes[i][1]; + cStats.mAttributes[i].mMod = acdt.mAttributes[i][0]; + cStats.mAttributes[i].mCurrent = acdt.mAttributes[i][0]; + } + } + + void convertNpcData (const ActorData& actorData, ESM::NpcStats& npcStats) + { + for (int i=0; i +#include +#include + +#include "importacdt.hpp" + +namespace ESSImport +{ + + // OpenMW uses Health,Magicka,Fatigue, MW uses Health,Fatigue,Magicka + int translateDynamicIndex(int mwIndex); + + + void convertACDT (const ACDT& acdt, ESM::CreatureStats& cStats); + + void convertNpcData (const ActorData& actorData, ESM::NpcStats& npcStats); +} + +#endif diff --git a/apps/essimporter/converter.cpp b/apps/essimporter/converter.cpp index 1ad60d7ba..2e7a954e0 100644 --- a/apps/essimporter/converter.cpp +++ b/apps/essimporter/converter.cpp @@ -43,8 +43,15 @@ namespace ESSImport { ESM::Cell cell; std::string id = esm.getHNString("NAME"); + cell.mName = id; cell.load(esm, false); + // note if the player is in a nameless exterior cell, we will assign the cellId later based on player position + if (id == mContext->mPlayerCellName) + { + mContext->mPlayer.mCellId = cell.getCellId(); + } + Cell newcell; newcell.mCell = cell; @@ -55,7 +62,12 @@ namespace ESSImport unsigned char nam8[32]; if (esm.isNextSub("NAM8")) { - esm.getHExact(nam8, 32); + esm.getSubHeader(); + // FIXME: different size in interior cells for some reason + if (esm.getSubSize() == 36) + esm.skip(4); + + esm.getExact(nam8, 32); newcell.mFogOfWar.reserve(16*16); for (int x=0; x<16; ++x) @@ -87,6 +99,8 @@ namespace ESSImport } newcell.mRefs = cellrefs; + + // FIXME: map by ID for exterior cells mCells[id] = newcell; } @@ -127,20 +141,36 @@ namespace ESSImport std::make_pair(refIndex, out.mRefID)); if (crecIt != mContext->mCreatureChanges.end()) { - std::cerr << "Can't' find CREC for " << refIndex << " " << out.mRefID << std::endl; + ESM::CreatureState objstate; + objstate.blank(); + convertACDT(cellref.mActorData.mACDT, objstate.mCreatureStats); + objstate.mEnabled = cellref.mEnabled; + objstate.mPosition = cellref.mPos; + objstate.mRef = out; + objstate.mRef.mRefNum = cellref.mRefNum; + esm.writeHNT ("OBJE", ESM::REC_CREA); + objstate.save(esm); + continue; + } + + std::map, NPCC>::const_iterator npccIt = mContext->mNpcChanges.find( + std::make_pair(refIndex, out.mRefID)); + if (npccIt != mContext->mNpcChanges.end()) + { + ESM::NpcState objstate; + objstate.blank(); + convertACDT(cellref.mActorData.mACDT, objstate.mCreatureStats); + convertNpcData(cellref.mActorData, objstate.mNpcStats); + objstate.mEnabled = cellref.mEnabled; + objstate.mPosition = cellref.mPos; + objstate.mRef = out; + objstate.mRef.mRefNum = cellref.mRefNum; + esm.writeHNT ("OBJE", ESM::REC_NPC_); + objstate.save(esm); continue; } - ESM::CreatureState objstate; - objstate.mCount = 1; - objstate.mEnabled = cellref.mEnabled; - objstate.mHasLocals = 0; - objstate.mLocalRotation[0] = objstate.mLocalRotation[1] = objstate.mLocalRotation[2] = 0; - objstate.mPosition = cellref.mPos; - objstate.mRef = out; - objstate.mRef.mRefNum = cellref.mRefNum; - esm.writeHNT ("OBJE", ESM::REC_CREA); - objstate.save(esm); + std::cerr << "Can't find type for " << refIndex << " " << out.mRefID << std::endl; } esm.endRecord(ESM::REC_CSTA); diff --git a/apps/essimporter/converter.hpp b/apps/essimporter/converter.hpp index 71eb3ab9f..7e9166902 100644 --- a/apps/essimporter/converter.hpp +++ b/apps/essimporter/converter.hpp @@ -14,6 +14,9 @@ #include "importercontext.hpp" #include "importcellref.hpp" +#include "convertacdt.hpp" +#include "convertnpcc.hpp" + namespace ESSImport { @@ -151,9 +154,10 @@ public: npcc.load(esm); if (id == "PlayerSaveGame") { - mContext->mPlayer.mObject.mNpcStats.mReputation = npcc.mNPDT.mReputation; + convertNPCC(npcc, mContext->mPlayer.mObject); } - //mContext->mNpcChanges.insert(std::make_pair(std::make_pair(npcc.mIndex,id), crec)); + else + mContext->mNpcChanges.insert(std::make_pair(std::make_pair(npcc.mIndex,id), npcc)); } }; @@ -168,36 +172,10 @@ public: mContext->mPlayer.mObject.mPosition = refr.mPos; ESM::CreatureStats& cStats = mContext->mPlayer.mObject.mCreatureStats; - for (int i=0; i<3; ++i) - { - int writeIndex = translateDynamicIndex(i); - cStats.mDynamic[writeIndex].mBase = refr.mACDT.mDynamic[i][1]; - cStats.mDynamic[writeIndex].mMod = refr.mACDT.mDynamic[i][1]; - cStats.mDynamic[writeIndex].mCurrent = refr.mACDT.mDynamic[i][0]; - } - for (int i=0; i<8; ++i) - { - cStats.mAttributes[i].mBase = refr.mACDT.mAttributes[i][1]; - cStats.mAttributes[i].mMod = refr.mACDT.mAttributes[i][0]; - cStats.mAttributes[i].mCurrent = refr.mACDT.mAttributes[i][0]; - } - ESM::NpcStats& npcStats = mContext->mPlayer.mObject.mNpcStats; - for (int i=0; imPlayer.mObject.mNpcStats; + convertNpcData(refr.mActorData, npcStats); } }; diff --git a/apps/essimporter/convertnpcc.cpp b/apps/essimporter/convertnpcc.cpp new file mode 100644 index 000000000..11e665bfd --- /dev/null +++ b/apps/essimporter/convertnpcc.cpp @@ -0,0 +1,22 @@ +#include "convertnpcc.hpp" + +namespace ESSImport +{ + + void convertNPCC(const NPCC &npcc, ESM::NpcState &npcState) + { + npcState.mNpcStats.mReputation = npcc.mNPDT.mReputation; + + for (std::vector::const_iterator it = npcc.mInventory.begin(); + it != npcc.mInventory.end(); ++it) + { + ESM::ObjectState obj; + obj.blank(); + obj.mRef.mRefID = it->mId; + obj.mRef.mCharge = it->mCondition; + + // Don't know type of object :( change save format? + // npcState.mInventory.mItems.push_back(std::make_pair(obj, std::make_pair(0,0))); + } + } +} diff --git a/apps/essimporter/convertnpcc.hpp b/apps/essimporter/convertnpcc.hpp new file mode 100644 index 000000000..eb12d8f3b --- /dev/null +++ b/apps/essimporter/convertnpcc.hpp @@ -0,0 +1,15 @@ +#ifndef OPENMW_ESSIMPORT_CONVERTNPCC_H +#define OPENMW_ESSIMPORT_CONVERTNPCC_H + +#include "importnpcc.hpp" + +#include + +namespace ESSImport +{ + + void convertNPCC (const NPCC& npcc, ESM::NpcState& npcState); + +} + +#endif diff --git a/apps/essimporter/importacdt.cpp b/apps/essimporter/importacdt.cpp new file mode 100644 index 000000000..b3e399f9f --- /dev/null +++ b/apps/essimporter/importacdt.cpp @@ -0,0 +1,28 @@ +#include "importacdt.hpp" + +#include + +namespace ESSImport +{ + + void ActorData::load(ESM::ESMReader &esm) + { + esm.getHNT(mACDT, "ACDT"); + + ACSC acsc; + esm.getHNOT(acsc, "ACSC"); + esm.getHNOT(acsc, "ACSL"); + + 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)); + + mScript = esm.getHNOString("SCRI"); + + if (esm.isNextSub("ND3D")) + esm.skipHSub(); + } + +} diff --git a/apps/essimporter/importacdt.hpp b/apps/essimporter/importacdt.hpp index 1d79f899e..6efae9dc5 100644 --- a/apps/essimporter/importacdt.hpp +++ b/apps/essimporter/importacdt.hpp @@ -1,9 +1,17 @@ #ifndef OPENMW_ESSIMPORT_ACDT_H #define OPENMW_ESSIMPORT_ACDT_H +#include + +namespace ESM +{ + struct ESMReader; +} + namespace ESSImport { + /// Actor data, shared by (at least) REFR and CellRef struct ACDT { @@ -14,6 +22,22 @@ namespace ESSImport unsigned char mUnknown3[120]; }; + struct ActorData + { + ACDT mACDT; + + int mSkills[27][2]; + + // creature combat stats, base and modified + // I think these can be ignored in the conversion, because it is not possible + // to change them ingame + int mCombatStats[3][2]; + + std::string mScript; + + void load(ESM::ESMReader& esm); + }; + /// Unknown, shared by (at least) REFR and CellRef struct ACSC { diff --git a/apps/essimporter/importcellref.cpp b/apps/essimporter/importcellref.cpp index 51e771081..76356769a 100644 --- a/apps/essimporter/importcellref.cpp +++ b/apps/essimporter/importcellref.cpp @@ -16,22 +16,19 @@ namespace ESSImport mIndexedRefId = esm.getHNString("NAME"); - esm.getHNT(mACDT, "ACDT"); + // the following two occur in ESM::CellRef too (Charge and Gold), + // but may have entirely different meanings here + int intv; + esm.getHNOT(intv, "INTV"); + int nam9; + esm.getHNOT(nam9, "NAM9"); - ACSC acsc; - esm.getHNOT(acsc, "ACSC"); - esm.getHNOT(acsc, "ACSL"); - - if (esm.isNextSub("CRED")) - esm.skipHSub(); - - if (esm.isNextSub("ND3D")) - esm.skipHSub(); + mActorData.load(esm); mEnabled = true; esm.getHNOT(mEnabled, "ZNAM"); - esm.getHNOT(mPos, "DATA", 24); + esm.getHNT(mPos, "DATA", 24); } } diff --git a/apps/essimporter/importcellref.hpp b/apps/essimporter/importcellref.hpp index 72c5af257..77763d434 100644 --- a/apps/essimporter/importcellref.hpp +++ b/apps/essimporter/importcellref.hpp @@ -21,10 +21,12 @@ namespace ESSImport std::string mIndexedRefId; ESM::RefNum mRefNum; - ACDT mACDT; + ActorData mActorData; ESM::Position mPos; + std::string mScript; + bool mEnabled; void load(ESM::ESMReader& esm); diff --git a/apps/essimporter/importer.cpp b/apps/essimporter/importer.cpp index b511dfe5e..572489d9a 100644 --- a/apps/essimporter/importer.cpp +++ b/apps/essimporter/importer.cpp @@ -185,6 +185,9 @@ namespace ESSImport Context context; + const ESM::Header& header = esm.getHeader(); + context.mPlayerCellName = header.mGameData.mCurrentCell.toString(); + const unsigned int recREFR = ESM::FourCC<'R','E','F','R'>::value; const unsigned int recPCDT = ESM::FourCC<'P','C','D','T'>::value; const unsigned int recFMAP = ESM::FourCC<'F','M','A','P'>::value; @@ -234,8 +237,6 @@ namespace ESSImport } } - const ESM::Header& header = esm.getHeader(); - ESM::ESMWriter writer; writer.setFormat (ESM::Header::CurrentFormat); @@ -247,6 +248,11 @@ namespace ESSImport writer.setAuthor(""); writer.setDescription(""); writer.setRecordCount (0); + + for (std::vector::const_iterator it = header.mMaster.begin(); + it != header.mMaster.end(); ++it) + writer.addMaster (it->name, 0); // not using the size information anyway -> use value of 0 + writer.save (stream); ESM::SavedGame profile; @@ -298,6 +304,15 @@ namespace ESSImport } writer.startRecord(ESM::REC_PLAY); + if (context.mPlayer.mCellId.mPaged) + { + // exterior cell -> determine cell coordinates based on position + const int cellSize = 8192; + int cellX = std::floor(context.mPlayer.mObject.mPosition.pos[0]/cellSize); + int cellY = std::floor(context.mPlayer.mObject.mPosition.pos[1]/cellSize); + context.mPlayer.mCellId.mIndex.mX = cellX; + context.mPlayer.mCellId.mIndex.mY = cellY; + } context.mPlayer.save(writer); writer.endRecord(ESM::REC_PLAY); } diff --git a/apps/essimporter/importercontext.hpp b/apps/essimporter/importercontext.hpp index 6f26e8329..9183e6179 100644 --- a/apps/essimporter/importercontext.hpp +++ b/apps/essimporter/importercontext.hpp @@ -17,6 +17,9 @@ namespace ESSImport struct Context { + // set from the TES3 header + std::string mPlayerCellName; + ESM::Player mPlayer; ESM::NPC mPlayerBase; std::string mCustomPlayerClassName; @@ -38,33 +41,8 @@ namespace ESSImport //mPlayer.mLastKnownExteriorPosition mPlayer.mHasMark = 0; // TODO mPlayer.mCurrentCrimeId = 0; // TODO - mPlayer.mObject.mCount = 1; - mPlayer.mObject.mEnabled = 1; - mPlayer.mObject.mHasLocals = false; + mPlayer.mObject.blank(); mPlayer.mObject.mRef.mRefID = "player"; // REFR.mRefID would be PlayerSaveGame - mPlayer.mObject.mCreatureStats.mHasAiSettings = true; - mPlayer.mObject.mCreatureStats.mDead = false; - mPlayer.mObject.mCreatureStats.mDied = false; - mPlayer.mObject.mCreatureStats.mKnockdown = false; - mPlayer.mObject.mCreatureStats.mKnockdownOneFrame = false; - mPlayer.mObject.mCreatureStats.mKnockdownOverOneFrame = false; - mPlayer.mObject.mCreatureStats.mHitRecovery = false; - mPlayer.mObject.mCreatureStats.mBlock = false; - mPlayer.mObject.mCreatureStats.mMovementFlags = 0; - mPlayer.mObject.mCreatureStats.mAttackStrength = 0.f; - mPlayer.mObject.mCreatureStats.mFallHeight = 0.f; - mPlayer.mObject.mCreatureStats.mRecalcDynamicStats = false; - mPlayer.mObject.mCreatureStats.mDrawState = 0; - mPlayer.mObject.mCreatureStats.mDeathAnimation = 0; - mPlayer.mObject.mNpcStats.mIsWerewolf = false; - mPlayer.mObject.mNpcStats.mTimeToStartDrowning = 20; - mPlayer.mObject.mNpcStats.mLevelProgress = 0; - mPlayer.mObject.mNpcStats.mDisposition = 0; - mPlayer.mObject.mNpcStats.mTimeToStartDrowning = 20; - mPlayer.mObject.mNpcStats.mReputation = 0; - mPlayer.mObject.mNpcStats.mCrimeId = -1; - mPlayer.mObject.mNpcStats.mWerewolfKills = 0; - mPlayer.mObject.mNpcStats.mProfit = 0; } }; diff --git a/apps/essimporter/importnpcc.cpp b/apps/essimporter/importnpcc.cpp index 192fe5da4..4cfc816c9 100644 --- a/apps/essimporter/importnpcc.cpp +++ b/apps/essimporter/importnpcc.cpp @@ -7,12 +7,29 @@ namespace ESSImport void NPCC::load(ESM::ESMReader &esm) { + mIndex = 0; + esm.getHNOT(mIndex, "INDX"); + esm.getHNT(mNPDT, "NPDT"); - // container: - // XIDX - // XHLT - condition - // WIDX - equipping? + while (esm.isNextSub("NPCO")) + { + InventoryItem item; + item.mId = esm.getHString(); + + if (esm.isNextSub("XIDX")) + esm.skipHSub(); + + item.mCondition = -1; + esm.getHNOT(item.mCondition, "XHLT"); + mInventory.push_back(item); + } + + while (esm.isNextSub("WIDX")) + { + // equipping? + esm.skipHSub(); + } } } diff --git a/apps/essimporter/importnpcc.hpp b/apps/essimporter/importnpcc.hpp index 12135850f..d10048fe0 100644 --- a/apps/essimporter/importnpcc.hpp +++ b/apps/essimporter/importnpcc.hpp @@ -1,7 +1,6 @@ #ifndef OPENMW_ESSIMPORT_NPCC_H #define OPENMW_ESSIMPORT_NPCC_H -#include #include namespace ESM @@ -12,7 +11,7 @@ namespace ESM namespace ESSImport { - struct NPCC : public ESM::NPC + struct NPCC { struct NPDT { @@ -21,6 +20,15 @@ namespace ESSImport unsigned char unknown2[5]; } mNPDT; + struct InventoryItem + { + std::string mId; + int mCondition; + }; + std::vector mInventory; + + int mIndex; + void load(ESM::ESMReader &esm); }; diff --git a/apps/essimporter/importplayer.cpp b/apps/essimporter/importplayer.cpp index 81f81e764..f8c78dab0 100644 --- a/apps/essimporter/importplayer.cpp +++ b/apps/essimporter/importplayer.cpp @@ -14,16 +14,7 @@ namespace ESSImport if (esm.isNextSub("STPR")) esm.skipHSub(); // ESS TODO - esm.getHNT(mACDT, "ACDT"); - - ACSC acsc; - esm.getHNOT(acsc, "ACSC"); - esm.getHNOT(acsc, "ACSL"); - - esm.getHNExact(mSkills, 27*2*sizeof(int), "CHRD"); - - if (esm.isNextSub("ND3D")) - esm.skipHSub(); // ESS TODO (1 byte) + mActorData.load(esm); esm.getHNOT(mPos, "DATA", 24); } @@ -45,6 +36,9 @@ namespace ESSImport if (esm.isNextSub("ENAM")) esm.skipHSub(); + if (esm.isNextSub("LNAM")) + esm.skipHSub(); + while (esm.isNextSub("FNAM")) { FNAM fnam; diff --git a/apps/essimporter/importplayer.hpp b/apps/essimporter/importplayer.hpp index 8a0a087a5..2493fcdad 100644 --- a/apps/essimporter/importplayer.hpp +++ b/apps/essimporter/importplayer.hpp @@ -21,15 +21,12 @@ namespace ESSImport /// Player-agnostic player data struct REFR { - ACDT mACDT; + ActorData mActorData; std::string mRefID; ESM::Position mPos; ESM::RefNum mRefNum; - int mSkills[27][2]; - float mAttributes[8][2]; - void load(ESM::ESMReader& esm); }; diff --git a/components/esm/creaturestate.cpp b/components/esm/creaturestate.cpp index 9e9b56102..c2838f78d 100644 --- a/components/esm/creaturestate.cpp +++ b/components/esm/creaturestate.cpp @@ -17,4 +17,10 @@ void ESM::CreatureState::save (ESMWriter &esm, bool inInventory) const mInventory.save (esm); mCreatureStats.save (esm); -} \ No newline at end of file +} + +void ESM::CreatureState::blank() +{ + ObjectState::blank(); + mCreatureStats.blank(); +} diff --git a/components/esm/creaturestate.hpp b/components/esm/creaturestate.hpp index 604c2f3a7..9a3d41daa 100644 --- a/components/esm/creaturestate.hpp +++ b/components/esm/creaturestate.hpp @@ -14,6 +14,9 @@ namespace ESM InventoryState mInventory; CreatureStats mCreatureStats; + /// Initialize to default state + void blank(); + virtual void load (ESMReader &esm); virtual void save (ESMWriter &esm, bool inInventory = false) const; }; diff --git a/components/esm/creaturestats.cpp b/components/esm/creaturestats.cpp index 1fdce703c..a1ef7eb0e 100644 --- a/components/esm/creaturestats.cpp +++ b/components/esm/creaturestats.cpp @@ -218,6 +218,38 @@ void ESM::CreatureStats::save (ESMWriter &esm) const } esm.writeHNT("AISE", mHasAiSettings); - for (int i=0; i<4; ++i) - mAiSettings[i].save(esm); + if (mHasAiSettings) + { + for (int i=0; i<4; ++i) + mAiSettings[i].save(esm); + } +} + +void ESM::CreatureStats::blank() +{ + mTradeTime.mHour = 0; + mTradeTime.mDay = 0; + mGoldPool = 0; + mActorId = 0; + mHasAiSettings = false; + mDead = false; + mDied = false; + mMurdered = false; + mFriendlyHits = 0; + mTalkedTo = false; + mAlarmed = false; + mAttacked = false; + mAttackingOrSpell = false; + mKnockdown = false; + mKnockdownOneFrame = false; + mKnockdownOverOneFrame = false; + mHitRecovery = false; + mBlock = false; + mMovementFlags = 0; + mAttackStrength = 0.f; + mFallHeight = 0.f; + mRecalcDynamicStats = false; + mDrawState = 0; + mDeathAnimation = 0; + mLevel = 1; } diff --git a/components/esm/creaturestats.hpp b/components/esm/creaturestats.hpp index 680577f93..91ee98333 100644 --- a/components/esm/creaturestats.hpp +++ b/components/esm/creaturestats.hpp @@ -66,6 +66,9 @@ namespace ESM SpellState mSpells; ActiveSpells mActiveSpells; + /// Initialize to default state + void blank(); + void load (ESMReader &esm); void save (ESMWriter &esm) const; }; diff --git a/components/esm/npcstate.cpp b/components/esm/npcstate.cpp index e59ec3e26..6134193c2 100644 --- a/components/esm/npcstate.cpp +++ b/components/esm/npcstate.cpp @@ -21,4 +21,11 @@ void ESM::NpcState::save (ESMWriter &esm, bool inInventory) const mNpcStats.save (esm); mCreatureStats.save (esm); -} \ No newline at end of file +} + +void ESM::NpcState::blank() +{ + ObjectState::blank(); + mNpcStats.blank(); + mCreatureStats.blank(); +} diff --git a/components/esm/npcstate.hpp b/components/esm/npcstate.hpp index 39858d553..b90cd85e6 100644 --- a/components/esm/npcstate.hpp +++ b/components/esm/npcstate.hpp @@ -16,6 +16,9 @@ namespace ESM NpcStats mNpcStats; CreatureStats mCreatureStats; + /// Initialize to default state + void blank(); + virtual void load (ESMReader &esm); virtual void save (ESMWriter &esm, bool inInventory = false) const; }; diff --git a/components/esm/npcstats.cpp b/components/esm/npcstats.cpp index 4ba0ce7e3..e305ddab0 100644 --- a/components/esm/npcstats.cpp +++ b/components/esm/npcstats.cpp @@ -150,3 +150,18 @@ void ESM::NpcStats::save (ESMWriter &esm) const if (mCrimeId != -1) esm.writeHNT ("CRID", mCrimeId); } + +void ESM::NpcStats::blank() +{ + mIsWerewolf = false; + mDisposition = 0; + mBounty = 0; + mReputation = 0; + mWerewolfKills = 0; + mProfit = 0; + mLevelProgress = 0; + for (int i=0; i<8; ++i) + mSkillIncrease[i] = 0; + mTimeToStartDrowning = 20; + mCrimeId = -1; +} diff --git a/components/esm/npcstats.hpp b/components/esm/npcstats.hpp index f6e9c1e58..a8ec4cf44 100644 --- a/components/esm/npcstats.hpp +++ b/components/esm/npcstats.hpp @@ -47,6 +47,9 @@ namespace ESM float mTimeToStartDrowning; int mCrimeId; + /// Initialize to default state + void blank(); + void load (ESMReader &esm); void save (ESMWriter &esm) const; }; diff --git a/components/esm/objectstate.cpp b/components/esm/objectstate.cpp index be00f3ef6..f7755f8cb 100644 --- a/components/esm/objectstate.cpp +++ b/components/esm/objectstate.cpp @@ -48,4 +48,18 @@ void ESM::ObjectState::save (ESMWriter &esm, bool inInventory) const } } -ESM::ObjectState::~ObjectState() {} \ No newline at end of file +void ESM::ObjectState::blank() +{ + mRef.blank(); + mHasLocals = 0; + mEnabled = false; + mCount = 1; + for (int i=0;i<3;++i) + { + mPosition.pos[i] = 0; + mPosition.rot[i] = 0; + mLocalRotation[i] = 0; + } +} + +ESM::ObjectState::~ObjectState() {} diff --git a/components/esm/objectstate.hpp b/components/esm/objectstate.hpp index 9c9ca5f2e..5b05e0949 100644 --- a/components/esm/objectstate.hpp +++ b/components/esm/objectstate.hpp @@ -29,8 +29,11 @@ namespace ESM virtual void load (ESMReader &esm); virtual void save (ESMWriter &esm, bool inInventory = false) const; + /// Initialize to default state + void blank(); + virtual ~ObjectState(); }; } -#endif \ No newline at end of file +#endif