Skip to content

Commit

Permalink
Optimize characters data in savegame
Browse files Browse the repository at this point in the history
  • Loading branch information
akortunov committed May 14, 2020
1 parent 019c843 commit e6ca951
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 98 deletions.
146 changes: 62 additions & 84 deletions components/esm/creaturestats.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand All @@ -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");
Expand All @@ -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");

Expand Down Expand Up @@ -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);

Expand All @@ -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);
Expand All @@ -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);

Expand All @@ -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);
Expand Down Expand Up @@ -247,7 +226,6 @@ void ESM::CreatureStats::blank()
mTradeTime.mDay = 0;
mGoldPool = 0;
mActorId = -1;
//mHitAttemptActorId = -1;
mHasAiSettings = false;
mDead = false;
mDeathAnimationFinished = false;
Expand Down
16 changes: 16 additions & 0 deletions components/esm/creaturestats.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
59 changes: 49 additions & 10 deletions components/esm/inventorystate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

void ESM::InventoryState::load (ESMReader &esm)
{
// obsolete
int index = 0;
while (esm.isNextSub ("IOBJ"))
{
Expand All @@ -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"))
{
Expand Down Expand Up @@ -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<ObjectState>::const_iterator iter (mItems.begin()); iter!=mItems.end(); ++iter)
int itemsCount = static_cast<int>(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<std::pair<std::string, std::string>, int>::const_iterator it = mLevelledItemMap.begin(); it != mLevelledItemMap.end(); ++it)
Expand All @@ -105,12 +139,17 @@ void ESM::InventoryState::save (ESMWriter &esm) const
}
}

for (std::map<int, int>::const_iterator it = mEquipmentSlots.begin(); it != mEquipmentSlots.end(); ++it)
int slotsCount = static_cast<int>(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<int, int>::const_iterator it = mEquipmentSlots.begin(); it != mEquipmentSlots.end(); ++it)
{
esm.writeT(it->first);
esm.writeT(it->second);
}
esm.endRecord("EQIP");
}

if (mSelectedEnchantItem != -1)
Expand Down
21 changes: 18 additions & 3 deletions components/esm/npcstats.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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<std::string>::const_iterator iter (mUsedIds.begin()); iter!=mUsedIds.end();
Expand Down
2 changes: 1 addition & 1 deletion components/esm/savedgame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down

0 comments on commit e6ca951

Please sign in to comment.