diff --git a/components/esm/creaturestats.cpp b/components/esm/creaturestats.cpp index d337b1434..2270bb6dd 100644 --- a/components/esm/creaturestats.cpp +++ b/components/esm/creaturestats.cpp @@ -17,53 +17,60 @@ void ESM::CreatureStats::load (ESMReader &esm) mTradeTime.mHour = 0; esm.getHNOT (mTradeTime, "TIME"); + int flags = 0; mDead = false; - esm.getHNOT (mDead, "DEAD"); - mDeathAnimationFinished = false; - esm.getHNOT (mDeathAnimationFinished, "DFNT"); - - if (esm.getFormat() < 3 && mDead) - mDeathAnimationFinished = true; - mDied = false; - esm.getHNOT (mDied, "DIED"); - mMurdered = false; - esm.getHNOT (mMurdered, "MURD"); - - if (esm.isNextSub("FRHT")) - esm.skipHSub(); // Friendly hits, no longer used - mTalkedTo = false; - esm.getHNOT (mTalkedTo, "TALK"); - mAlarmed = false; - esm.getHNOT (mAlarmed, "ALRM"); - mAttacked = false; - esm.getHNOT (mAttacked, "ATKD"); - - if (esm.isNextSub("HOST")) - esm.skipHSub(); // Hostile, no longer used - - if (esm.isNextSub("ATCK")) - esm.skipHSub(); // attackingOrSpell, no longer used - mKnockdown = false; - esm.getHNOT (mKnockdown, "KNCK"); - mKnockdownOneFrame = false; - esm.getHNOT (mKnockdownOneFrame, "KNC1"); - mKnockdownOverOneFrame = false; - esm.getHNOT (mKnockdownOverOneFrame, "KNCO"); - mHitRecovery = false; - esm.getHNOT (mHitRecovery, "HITR"); - mBlock = false; - esm.getHNOT (mBlock, "BLCK"); + mRecalcDynamicStats = false; + if (esm.getFormat() < 8) + { + esm.getHNOT (mDead, "DEAD"); + esm.getHNOT (mDeathAnimationFinished, "DFNT"); + if (esm.getFormat() < 3 && mDead) + mDeathAnimationFinished = true; + esm.getHNOT (mDied, "DIED"); + esm.getHNOT (mMurdered, "MURD"); + if (esm.isNextSub("FRHT")) + esm.skipHSub(); // Friendly hits, no longer used + esm.getHNOT (mTalkedTo, "TALK"); + esm.getHNOT (mAlarmed, "ALRM"); + esm.getHNOT (mAttacked, "ATKD"); + if (esm.isNextSub("HOST")) + esm.skipHSub(); // Hostile, no longer used + if (esm.isNextSub("ATCK")) + esm.skipHSub(); // attackingOrSpell, no longer used + esm.getHNOT (mKnockdown, "KNCK"); + esm.getHNOT (mKnockdownOneFrame, "KNC1"); + esm.getHNOT (mKnockdownOverOneFrame, "KNCO"); + esm.getHNOT (mHitRecovery, "HITR"); + esm.getHNOT (mBlock, "BLCK"); + } + else + { + esm.getHNOT(flags, "AFLG"); + mDead = flags & Dead; + mDeathAnimationFinished = flags & DeathAnimationFinished; + mDied = flags & Died; + mMurdered = flags & Murdered; + mTalkedTo = flags & TalkedTo; + mAlarmed = flags & Alarmed; + mAttacked = flags & Attacked; + mKnockdown = flags & Knockdown; + mKnockdownOneFrame = flags & KnockdownOneFrame; + mKnockdownOverOneFrame = flags & KnockdownOverOneFrame; + mHitRecovery = flags & HitRecovery; + mBlock = flags & Block; + mRecalcDynamicStats = flags & RecalcDynamicStats; + } mMovementFlags = 0; esm.getHNOT (mMovementFlags, "MOVE"); @@ -78,8 +85,8 @@ void ESM::CreatureStats::load (ESMReader &esm) mLastHitAttemptObject = esm.getHNOString ("LHAT"); - mRecalcDynamicStats = false; - esm.getHNOT (mRecalcDynamicStats, "CALC"); + if (esm.getFormat() < 8) + esm.getHNOT (mRecalcDynamicStats, "CALC"); mDrawState = 0; esm.getHNOT (mDrawState, "DRAW"); @@ -90,9 +97,6 @@ void ESM::CreatureStats::load (ESMReader &esm) mActorId = -1; esm.getHNOT (mActorId, "ACID"); - //mHitAttemptActorId = -1; - //esm.getHNOT(mHitAttemptActorId, "HAID"); - mDeathAnimation = -1; esm.getHNOT (mDeathAnimation, "DANM"); @@ -134,7 +138,6 @@ void ESM::CreatureStats::load (ESMReader &esm) void ESM::CreatureStats::save (ESMWriter &esm) const { - for (int i=0; i<8; ++i) mAttributes[i].save (esm); @@ -147,41 +150,23 @@ void ESM::CreatureStats::save (ESMWriter &esm) const if (mTradeTime.mDay != 0 || mTradeTime.mHour != 0) esm.writeHNT ("TIME", mTradeTime); - if (mDead) - esm.writeHNT ("DEAD", mDead); - - if (mDeathAnimationFinished) - esm.writeHNT ("DFNT", mDeathAnimationFinished); - - if (mDied) - esm.writeHNT ("DIED", mDied); - - if (mMurdered) - esm.writeHNT ("MURD", mMurdered); - - if (mTalkedTo) - esm.writeHNT ("TALK", mTalkedTo); - - if (mAlarmed) - esm.writeHNT ("ALRM", mAlarmed); - - if (mAttacked) - esm.writeHNT ("ATKD", mAttacked); - - if (mKnockdown) - esm.writeHNT ("KNCK", mKnockdown); - - if (mKnockdownOneFrame) - esm.writeHNT ("KNC1", mKnockdownOneFrame); - - if (mKnockdownOverOneFrame) - esm.writeHNT ("KNCO", mKnockdownOverOneFrame); - - if (mHitRecovery) - esm.writeHNT ("HITR", mHitRecovery); - - if (mBlock) - esm.writeHNT ("BLCK", mBlock); + int flags = 0; + if (mDead) flags |= Dead; + if (mDeathAnimationFinished) flags |= DeathAnimationFinished; + if (mDied) flags |= Died; + if (mMurdered) flags |= Murdered; + if (mTalkedTo) flags |= TalkedTo; + if (mAlarmed) flags |= Alarmed; + if (mAttacked) flags |= Attacked; + if (mKnockdown) flags |= Knockdown; + if (mKnockdownOneFrame) flags |= KnockdownOneFrame; + if (mKnockdownOverOneFrame) flags |= KnockdownOverOneFrame; + if (mHitRecovery) flags |= HitRecovery; + if (mBlock) flags |= Block; + if (mRecalcDynamicStats) flags |= RecalcDynamicStats; + + if (flags) + esm.writeHNT ("AFLG", flags); if (mMovementFlags) esm.writeHNT ("MOVE", mMovementFlags); @@ -195,9 +180,6 @@ void ESM::CreatureStats::save (ESMWriter &esm) const if (!mLastHitAttemptObject.empty()) esm.writeHNString ("LHAT", mLastHitAttemptObject); - if (mRecalcDynamicStats) - esm.writeHNT ("CALC", mRecalcDynamicStats); - if (mDrawState) esm.writeHNT ("DRAW", mDrawState); @@ -207,13 +189,10 @@ void ESM::CreatureStats::save (ESMWriter &esm) const if (mActorId != -1) esm.writeHNT ("ACID", mActorId); - //if (mHitAttemptActorId != -1) - // esm.writeHNT("HAID", mHitAttemptActorId); - if (mDeathAnimation != -1) esm.writeHNT ("DANM", mDeathAnimation); - if (mTimeOfDeath.mHour != 0 && mTimeOfDeath.mDay != 0) + if (mTimeOfDeath.mHour != 0 || mTimeOfDeath.mDay != 0) esm.writeHNT ("DTIM", mTimeOfDeath); mSpells.save(esm); @@ -247,7 +226,6 @@ void ESM::CreatureStats::blank() mTradeTime.mDay = 0; mGoldPool = 0; mActorId = -1; - //mHitAttemptActorId = -1; mHasAiSettings = false; mDead = false; mDeathAnimationFinished = false; diff --git a/components/esm/creaturestats.hpp b/components/esm/creaturestats.hpp index 7e7e5dac3..8c69553a3 100644 --- a/components/esm/creaturestats.hpp +++ b/components/esm/creaturestats.hpp @@ -40,6 +40,22 @@ namespace ESM int mActorId; //int mHitAttemptActorId; + enum Flags + { + Dead = 0x0001, + DeathAnimationFinished = 0x0002, + Died = 0x0004, + Murdered = 0x0008, + TalkedTo = 0x0010, + Alarmed = 0x0020, + Attacked = 0x0040, + Knockdown = 0x0080, + KnockdownOneFrame = 0x0100, + KnockdownOverOneFrame = 0x0200, + HitRecovery = 0x0400, + Block = 0x0800, + RecalcDynamicStats = 0x1000 + }; bool mDead; bool mDeathAnimationFinished; bool mDied; diff --git a/components/esm/inventorystate.cpp b/components/esm/inventorystate.cpp index 73db72b00..fe54762c5 100644 --- a/components/esm/inventorystate.cpp +++ b/components/esm/inventorystate.cpp @@ -5,6 +5,7 @@ void ESM::InventoryState::load (ESMReader &esm) { + // obsolete int index = 0; while (esm.isNextSub ("IOBJ")) { @@ -31,6 +32,22 @@ void ESM::InventoryState::load (ESMReader &esm) ++index; } + + int itemsCount = 0; + esm.getHNOT(itemsCount, "ICNT"); + for (int i = 0; i < itemsCount; i++) + { + ObjectState state; + + state.mRef.loadId(esm, true); + state.load (esm); + + if (state.mCount == 0) + continue; + + mItems.push_back (state); + } + //Next item is Levelled item while (esm.isNextSub("LEVM")) { @@ -72,18 +89,35 @@ void ESM::InventoryState::load (ESMReader &esm) mEquipmentSlots[equipIndex] = slot; } + if (esm.isNextSub("EQIP")) + { + esm.getSubHeader(); + int slotsCount = 0; + esm.getT(slotsCount); + for (int i = 0; i < slotsCount; i++) + { + int equipIndex; + esm.getT(equipIndex); + int slot; + esm.getT(slot); + mEquipmentSlots[equipIndex] = slot; + } + } + mSelectedEnchantItem = -1; esm.getHNOT(mSelectedEnchantItem, "SELE"); } void ESM::InventoryState::save (ESMWriter &esm) const { - for (std::vector::const_iterator iter (mItems.begin()); iter!=mItems.end(); ++iter) + int itemsCount = static_cast(mItems.size()); + if (itemsCount > 0) { - int unused = 0; - esm.writeHNT ("IOBJ", unused); - - iter->save (esm, true); + esm.writeHNT ("ICNT", itemsCount); + for (const ObjectState& state : mItems) + { + state.save (esm, true); + } } for (std::map, int>::const_iterator it = mLevelledItemMap.begin(); it != mLevelledItemMap.end(); ++it) @@ -105,12 +139,17 @@ void ESM::InventoryState::save (ESMWriter &esm) const } } - for (std::map::const_iterator it = mEquipmentSlots.begin(); it != mEquipmentSlots.end(); ++it) + int slotsCount = static_cast(mEquipmentSlots.size()); + if (slotsCount > 0) { - esm.startSubRecord("EQUI"); - esm.writeT(it->first); - esm.writeT(it->second); - esm.endRecord("EQUI"); + esm.startSubRecord("EQIP"); + esm.writeT(slotsCount); + for (std::map::const_iterator it = mEquipmentSlots.begin(); it != mEquipmentSlots.end(); ++it) + { + esm.writeT(it->first); + esm.writeT(it->second); + } + esm.endRecord("EQIP"); } if (mSelectedEnchantItem != -1) diff --git a/components/esm/npcstats.cpp b/components/esm/npcstats.cpp index a12879109..c5fa2a09e 100644 --- a/components/esm/npcstats.cpp +++ b/components/esm/npcstats.cpp @@ -35,7 +35,7 @@ void ESM::NpcStats::load (ESMReader &esm) mSkills[i].load (esm); mWerewolfDeprecatedData = false; - if (esm.peekNextSub("STBA")) + if (esm.getFormat() < 8 && esm.peekNextSub("STBA")) { // we have deprecated werewolf skills, stored interleaved // Load into one big vector, then remove every 2nd value @@ -95,7 +95,9 @@ void ESM::NpcStats::load (ESMReader &esm) mLevelProgress = 0; esm.getHNOT (mLevelProgress, "LPRO"); - esm.getHNT (mSkillIncrease, "INCR"); + for (int i = 0; i < 8; ++i) + mSkillIncrease[i] = 0; + esm.getHNOT (mSkillIncrease, "INCR"); for (int i=0; i<3; ++i) mSpecIncreases[i] = 0; @@ -160,8 +162,21 @@ void ESM::NpcStats::save (ESMWriter &esm) const if (mLevelProgress) esm.writeHNT ("LPRO", mLevelProgress); - esm.writeHNT ("INCR", mSkillIncrease); + bool saveSkillIncreases = false; + for (int i = 0; i < 8; ++i) + { + if (mSkillIncrease[i] != 0) + { + saveSkillIncreases = true; + break; + } + } + if (saveSkillIncreases) + esm.writeHNT ("INCR", mSkillIncrease); + if (mSpecIncreases[0] != 0 || + mSpecIncreases[1] != 0 || + mSpecIncreases[2] != 0) esm.writeHNT ("SPEC", mSpecIncreases); for (std::vector::const_iterator iter (mUsedIds.begin()); iter!=mUsedIds.end(); diff --git a/components/esm/savedgame.cpp b/components/esm/savedgame.cpp index e88c7cd8b..f2ebc7bf0 100644 --- a/components/esm/savedgame.cpp +++ b/components/esm/savedgame.cpp @@ -5,7 +5,7 @@ #include "defs.hpp" unsigned int ESM::SavedGame::sRecordId = ESM::REC_SAVE; -int ESM::SavedGame::sCurrentFormat = 7; +int ESM::SavedGame::sCurrentFormat = 8; void ESM::SavedGame::load (ESMReader &esm) {