store NPC state in saved game files

actorid
Marc Zinnschlag 11 years ago
parent 9f721fd144
commit b0532e0c85

@ -1278,8 +1278,10 @@ namespace MWClass
ensureCustomData (ptr);
dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mInventoryStore.
readState (state2.mInventory);
CustomData& customData = dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData());
customData.mInventoryStore.readState (state2.mInventory);
customData.mNpcStats.readState (state2.mNpcStats);
}
void Npc::writeAdditionalState (const MWWorld::Ptr& ptr, ESM::ObjectState& state)
@ -1289,8 +1291,10 @@ namespace MWClass
ensureCustomData (ptr);
dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mInventoryStore.
writeState (state2.mInventory);
CustomData& customData = dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData());
customData.mInventoryStore.writeState (state2.mInventory);
customData.mNpcStats.writeState (state2.mNpcStats);
}
const ESM::GameSetting *Npc::fMinWalkSpeed;

@ -12,6 +12,7 @@
#include <components/esm/loadclas.hpp>
#include <components/esm/loadgmst.hpp>
#include <components/esm/loadfact.hpp>
#include <components/esm/npcstats.hpp>
#include "../mwworld/class.hpp"
#include "../mwworld/esmstore.hpp"
@ -423,3 +424,79 @@ void MWMechanics::NpcStats::setTimeToStartDrowning(float time)
assert(time>=0 && time<=20);
mTimeToStartDrowning=time;
}
void MWMechanics::NpcStats::writeState (ESM::NpcStats& state) const
{
for (std::map<std::string, int>::const_iterator iter (mFactionRank.begin());
iter!=mFactionRank.end(); ++iter)
state.mFactions[iter->first].mRank = iter->second;
state.mDisposition = mDisposition;
for (int i=0; i<27; ++i)
{
mSkill[i].writeState (state.mSkills[i].mRegular);
mWerewolfSkill[i].writeState (state.mSkills[i].mWerewolf);
state.mSkills[i].mIncrease = mSkillIncreases[i];
}
state.mBounty = mBounty;
for (std::set<std::string>::const_iterator iter (mExpelled.begin());
iter!=mExpelled.end(); ++iter)
state.mFactions[*iter].mExpelled = true;
for (std::map<std::string, int>::const_iterator iter (mFactionReputation.begin());
iter!=mFactionReputation.end(); ++iter)
state.mFactions[iter->first].mReputation = iter->second;
state.mReputation = mReputation;
state.mWerewolfKills = mWerewolfKills;
state.mProfit = mProfit;
state.mAttackStrength = mAttackStrength;
state.mLevelProgress = mLevelProgress;
std::copy (mUsedIds.begin(), mUsedIds.end(), std::back_inserter (state.mUsedIds));
state.mTimeToStartDrowning = mTimeToStartDrowning;
state.mLastDrowningHit = mLastDrowningHit;
state.mLevelHealthBonus = mLevelHealthBonus;
}
void MWMechanics::NpcStats::readState (const ESM::NpcStats& state)
{
for (std::map<std::string, ESM::NpcStats::Faction>::const_iterator iter (state.mFactions.begin());
iter!=state.mFactions.end(); ++iter)
{
if (iter->second.mExpelled)
mExpelled.insert (iter->first);
if (iter->second.mRank)
mFactionRank.insert (std::make_pair (iter->first, iter->second.mRank));
if (iter->second.mReputation)
mFactionReputation.insert (std::make_pair (iter->first, iter->second.mReputation));
}
mDisposition = state.mDisposition;
for (int i=0; i<27; ++i)
{
mSkill[i].readState (state.mSkills[i].mRegular);
mWerewolfSkill[i].readState (state.mSkills[i].mWerewolf);
mSkillIncreases[i] = state.mSkills[i].mIncrease;
}
mBounty = state.mBounty;
mReputation = state.mReputation;
mWerewolfKills = state.mWerewolfKills;
mProfit = state.mProfit;
mAttackStrength = state.mAttackStrength;
mLevelProgress = state.mLevelProgress;
std::copy (state.mUsedIds.begin(), state.mUsedIds.end(), std::inserter (mUsedIds, mUsedIds.begin()));
mTimeToStartDrowning = state.mTimeToStartDrowning;
mLastDrowningHit = state.mLastDrowningHit;
mLevelHealthBonus = state.mLevelHealthBonus;
}

@ -13,6 +13,7 @@
namespace ESM
{
struct Class;
struct NpcStats;
}
namespace MWMechanics
@ -128,6 +129,10 @@ namespace MWMechanics
/// Sets time left for the creature to drown if it stays underwater.
/// @param time value from [0,20]
void setTimeToStartDrowning(float time);
void writeState (ESM::NpcStats& state) const;
void readState (const ESM::NpcStats& state);
};
}

@ -0,0 +1,29 @@
#include "stat.hpp"
void MWMechanics::AttributeValue::writeState (ESM::StatState<int>& state) const
{
state.mBase = mBase;
state.mMod = mModifier;
state.mDamage = mDamage;
}
void MWMechanics::AttributeValue::readState (const ESM::StatState<int>& state)
{
mBase = state.mBase;
mModifier = state.mMod;
mDamage = state.mDamage;
}
void MWMechanics::SkillValue::writeState (ESM::StatState<int>& state) const
{
AttributeValue::writeState (state);
state.mProgress = mProgress;
}
void MWMechanics::SkillValue::readState (const ESM::StatState<int>& state)
{
AttributeValue::readState (state);
mProgress = state.mProgress;
}

@ -6,6 +6,8 @@
#include <limits>
#include <components/esm/statstate.hpp>
namespace MWMechanics
{
template<typename T>
@ -225,6 +227,10 @@ namespace MWMechanics
void damage(int damage) { mDamage += damage; }
void restore(int amount) { mDamage -= std::min(mDamage, amount); }
int getDamage() const { return mDamage; }
void writeState (ESM::StatState<int>& state) const;
void readState (const ESM::StatState<int>& state);
};
class SkillValue : public AttributeValue
@ -234,6 +240,10 @@ namespace MWMechanics
SkillValue() : mProgress(0) {}
float getProgress() const { return mProgress; }
void setProgress(float progress) { mProgress = progress; }
void writeState (ESM::StatState<int>& state) const;
void readState (const ESM::StatState<int>& state);
};
inline bool operator== (const AttributeValue& left, const AttributeValue& right)

@ -44,7 +44,8 @@ add_component_dir (esm
loadinfo loadingr loadland loadlevlist loadligh loadlock loadprob loadrepa loadltex loadmgef loadmisc loadnpcc
loadnpc loadpgrd loadrace loadregn loadscpt loadskil loadsndg loadsoun loadspel loadsscr loadstat
loadweap records aipackage effectlist spelllist variant variantimp loadtes3 cellref filter
savedgame journalentry queststate locals globalscript player objectstate cellid cellstate globalmap lightstate inventorystate containerstate npcstate creaturestate dialoguestate
savedgame journalentry queststate locals globalscript player objectstate cellid cellstate globalmap lightstate inventorystate containerstate npcstate creaturestate dialoguestate statstate
npcstats
)
add_component_dir (misc

@ -6,6 +6,10 @@ void ESM::NpcState::load (ESMReader &esm)
ObjectState::load (esm);
mInventory.load (esm);
mNpcStats.load (esm);
mCreatureStats.load (esm);
}
void ESM::NpcState::save (ESMWriter &esm, bool inInventory) const
@ -13,4 +17,8 @@ void ESM::NpcState::save (ESMWriter &esm, bool inInventory) const
ObjectState::save (esm, inInventory);
mInventory.save (esm);
mNpcStats.save (esm);
mCreatureStats.save (esm);
}

@ -3,6 +3,8 @@
#include "objectstate.hpp"
#include "inventorystate.hpp"
#include "npcstats.hpp"
#include "creaturestats.hpp"
namespace ESM
{
@ -11,6 +13,8 @@ namespace ESM
struct NpcState : public ObjectState
{
InventoryState mInventory;
NpcStats mNpcStats;
CreatureStats mCreatureStats;
virtual void load (ESMReader &esm);
virtual void save (ESMWriter &esm, bool inInventory = false) const;

@ -0,0 +1,133 @@
#include "npcstats.hpp"
#include "esmreader.hpp"
#include "esmwriter.hpp"
ESM::NpcStats::Faction::Faction() : mExpelled (false), mRank (0), mReputation (0) {}
void ESM::NpcStats::load (ESMReader &esm)
{
while (esm.isNextSub ("FACT"))
{
std::string id = esm.getHString();
Faction faction;
int expelled = 0;
esm.getHNOT (expelled, "FAEX");
if (expelled)
faction.mExpelled = true;
esm.getHNOT (faction.mRank, "FARA");
esm.getHNOT (faction.mReputation, "FARE");
mFactions.insert (std::make_pair (id, faction));
}
mDisposition = 0;
esm.getHNOT (mDisposition, "DISP");
for (int i=0; i<27; ++i)
{
mSkills[i].mRegular.load (esm);
mSkills[i].mWerewolf.load (esm);
}
mBounty = 0;
esm.getHNOT (mBounty, "BOUN");
mReputation = 0;
esm.getHNOT (mReputation, "REPU");
mWerewolfKills = 0;
esm.getHNOT (mWerewolfKills, "WKIL");
mProfit = 0;
esm.getHNOT (mProfit, "PROF");
mAttackStrength = 0;
esm.getHNOT (mAttackStrength, "ASTR");
mLevelProgress = 0;
esm.getHNOT (mLevelProgress, "LPRO");
esm.getHNT (mSkillIncrease, "INCR");
while (esm.isNextSub ("USED"))
mUsedIds.push_back (esm.getHString());
mTimeToStartDrowning = 0;
esm.getHNOT (mTimeToStartDrowning, "DRTI");
mLastDrowningHit = 0;
esm.getHNOT (mLastDrowningHit, "DRLH");
mLevelHealthBonus = 0;
esm.getHNOT (mLevelHealthBonus, "LVLH");
}
void ESM::NpcStats::save (ESMWriter &esm) const
{
for (std::map<std::string, Faction>::const_iterator iter (mFactions.begin());
iter!=mFactions.end(); ++iter)
{
esm.writeHNString ("FACT", iter->first);
if (iter->second.mExpelled)
{
int expelled = 1;
esm.writeHNT ("FAEX", expelled);
}
if (iter->second.mRank)
esm.writeHNT ("FARA", iter->second.mRank);
if (iter->second.mReputation)
esm.writeHNT ("FARE", iter->second.mReputation);
}
if (mDisposition)
esm.writeHNT ("DISP", mDisposition);
for (int i=0; i<27; ++i)
{
mSkills[i].mRegular.save (esm);
mSkills[i].mWerewolf.save (esm);
}
if (mBounty)
esm.writeHNT ("BOUN", mBounty);
if (mReputation)
esm.writeHNT ("REPU", mReputation);
if (mWerewolfKills)
esm.writeHNT ("WKIL", mWerewolfKills);
if (mProfit)
esm.writeHNT ("PROF", mProfit);
if (mAttackStrength)
esm.writeHNT ("ASTR", mAttackStrength);
if (mLevelProgress)
esm.writeHNT ("LPRO", mLevelProgress);
esm.writeHNT ("INCR", mSkillIncrease);
for (std::vector<std::string>::const_iterator iter (mUsedIds.begin()); iter!=mUsedIds.end();
++iter)
esm.writeHNT ("USED", *iter);
if (mTimeToStartDrowning)
esm.writeHNT ("DRTI", mTimeToStartDrowning);
if (mLastDrowningHit)
esm.writeHNT ("DRLH", mLastDrowningHit);
if (mLevelHealthBonus)
esm.writeHNT ("LVLH", mLevelHealthBonus);
}

@ -0,0 +1,54 @@
#ifndef OPENMW_ESM_NPCSTATS_H
#define OPENMW_ESM_NPCSTATS_H
#include <string>
#include <vector>
#include <map>
#include "statstate.hpp"
namespace ESM
{
class ESMReader;
class ESMWriter;
// format 0, saved games only
struct NpcStats
{
struct Skill
{
StatState<int> mRegular;
StatState<int> mWerewolf;
};
struct Faction
{
bool mExpelled;
int mRank;
int mReputation;
Faction();
};
std::map<std::string, Faction> mFactions;
int mDisposition;
Skill mSkills[27];
int mBounty;
int mReputation;
int mWerewolfKills;
int mProfit;
float mAttackStrength;
int mLevelProgress;
int mSkillIncrease[8];
std::vector<std::string> mUsedIds;
float mTimeToStartDrowning;
float mLastDrowningHit;
float mLevelHealthBonus;
void load (ESMReader &esm);
void save (ESMWriter &esm) const;
};
}
#endif

@ -0,0 +1,53 @@
#ifndef OPENMW_ESM_STATSTATE_H
#define OPENMW_ESM_STATSTATE_H
#include "esmreader.hpp"
#include "esmwriter.hpp"
namespace ESM
{
// format 0, saved games only
template<typename T>
struct StatState
{
T mBase;
T mMod;
T mDamage;
float mProgress;
StatState();
void load (ESMReader &esm);
void save (ESMWriter &esm) const;
};
template<typename T>
StatState<T>::StatState() : mBase (0), mMod (0), mDamage (0), mProgress (0) {}
template<typename T>
void StatState<T>::load (ESMReader &esm)
{
esm.getHNT (mBase, "STBA");
esm.getHNT (mMod, "STMO");
mDamage = 0;
esm.getHNOT (mDamage, "STDA");
mProgress = 0;
esm.getHNOT (mProgress, "STPR");
}
template<typename T>
void StatState<T>::save (ESMWriter &esm) const
{
esm.writeHNT ("STBA", mBase);
esm.writeHNT ("STMO", mMod);
if (mDamage)
esm.writeHNT ("STDA", mDamage);
if (mProgress)
esm.writeHNT ("STPR", mProgress);
}
}
#endif
Loading…
Cancel
Save