1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-01-16 16:29:55 +00:00

store NPC state in saved game files

This commit is contained in:
Marc Zinnschlag 2014-02-16 15:06:34 +01:00
parent 9f721fd144
commit b0532e0c85
11 changed files with 383 additions and 5 deletions

View file

@ -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;

View file

@ -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;
}

View file

@ -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);
};
}

View file

@ -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;
}

View file

@ -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)

View file

@ -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

View file

@ -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);
}

View file

@ -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;

133
components/esm/npcstats.cpp Normal file
View file

@ -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);
}

View file

@ -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

View file

@ -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