From 471bbd0021789c3882fc95a5069ed7ed830fcaea Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 15 May 2014 00:23:53 +0200 Subject: [PATCH] Savegame: store levelled creature state and move to actorIds (Closes #1332) --- apps/openmw/mwclass/creaturelevlist.cpp | 59 ++++++++++++++++++------- apps/openmw/mwclass/creaturelevlist.hpp | 8 ++++ apps/openmw/mwworld/cellstore.cpp | 5 ++- components/CMakeLists.txt | 2 +- components/esm/creaturelevliststate.cpp | 25 +++++++++++ components/esm/creaturelevliststate.hpp | 19 ++++++++ 6 files changed, 100 insertions(+), 18 deletions(-) create mode 100644 components/esm/creaturelevliststate.cpp create mode 100644 components/esm/creaturelevliststate.hpp diff --git a/apps/openmw/mwclass/creaturelevlist.cpp b/apps/openmw/mwclass/creaturelevlist.cpp index 732038b2fc..be01b848a3 100644 --- a/apps/openmw/mwclass/creaturelevlist.cpp +++ b/apps/openmw/mwclass/creaturelevlist.cpp @@ -2,6 +2,7 @@ #include "creaturelevlist.hpp" #include +#include #include "../mwmechanics/levelledlist.hpp" @@ -11,7 +12,9 @@ namespace { struct CreatureLevListCustomData : public MWWorld::CustomData { - // TODO: save the creature we spawned here + // actorId of the creature we spawned + int mSpawnActorId; + virtual MWWorld::CustomData *clone() const; }; @@ -38,6 +41,25 @@ namespace MWClass void CreatureLevList::insertObjectRendering(const MWWorld::Ptr &ptr, MWRender::RenderingInterface &renderingInterface) const { ensureCustomData(ptr); + + CreatureLevListCustomData& customData = dynamic_cast (*ptr.getRefData().getCustomData()); + if (customData.mSpawnActorId != -1) + return; // TODO: handle respawning + + + MWWorld::LiveCellRef *ref = + ptr.get(); + + std::string id = MWMechanics::getLevelledItem(ref->mBase, true); + + if (!id.empty()) + { + const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); + MWWorld::ManualRef ref(store, id); + ref.getPtr().getCellRef().mPos = ptr.getCellRef().mPos; + MWWorld::Ptr placed = MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(), ptr.getCell() , ptr.getCellRef().mPos); + customData.mSpawnActorId = placed.getClass().getCreatureStats(placed).getActorId(); + } } void CreatureLevList::ensureCustomData(const MWWorld::Ptr &ptr) const @@ -45,22 +67,29 @@ namespace MWClass if (!ptr.getRefData().getCustomData()) { std::auto_ptr data (new CreatureLevListCustomData); - - MWWorld::LiveCellRef *ref = - ptr.get(); - - std::string id = MWMechanics::getLevelledItem(ref->mBase, true); - - if (!id.empty()) - { - const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); - MWWorld::ManualRef ref(store, id); - ref.getPtr().getCellRef().mPos = ptr.getCellRef().mPos; - // TODO: hold on to this for respawn purposes later - MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(), ptr.getCell() , ptr.getCellRef().mPos); - } + data->mSpawnActorId = -1; ptr.getRefData().setCustomData(data.release()); } } + + void CreatureLevList::readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state) + const + { + const ESM::CreatureLevListState& state2 = dynamic_cast (state); + + ensureCustomData(ptr); + CreatureLevListCustomData& customData = dynamic_cast (*ptr.getRefData().getCustomData()); + customData.mSpawnActorId = state2.mSpawnActorId; + } + + void CreatureLevList::writeAdditionalState (const MWWorld::Ptr& ptr, ESM::ObjectState& state) + const + { + ESM::CreatureLevListState& state2 = dynamic_cast (state); + + ensureCustomData(ptr); + CreatureLevListCustomData& customData = dynamic_cast (*ptr.getRefData().getCustomData()); + state2.mSpawnActorId = customData.mSpawnActorId; + } } diff --git a/apps/openmw/mwclass/creaturelevlist.hpp b/apps/openmw/mwclass/creaturelevlist.hpp index d2c02043eb..b67fb5523f 100644 --- a/apps/openmw/mwclass/creaturelevlist.hpp +++ b/apps/openmw/mwclass/creaturelevlist.hpp @@ -19,6 +19,14 @@ namespace MWClass virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering + + virtual void readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state) + const; + ///< Read additional state from \a state into \a ptr. + + virtual void writeAdditionalState (const MWWorld::Ptr& ptr, ESM::ObjectState& state) + const; + ///< Write additional state from \a ptr into \a state. }; } diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index 67ab44b779..3f94a77c43 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" @@ -592,7 +593,7 @@ namespace MWWorld writeReferenceCollection (writer, mCreatures); writeReferenceCollection (writer, mDoors); writeReferenceCollection (writer, mIngreds); - writeReferenceCollection (writer, mCreatureLists); + writeReferenceCollection (writer, mCreatureLists); writeReferenceCollection (writer, mItemLists); writeReferenceCollection (writer, mLights); writeReferenceCollection (writer, mLockpicks); @@ -668,7 +669,7 @@ namespace MWWorld case ESM::REC_LEVC: - readReferenceCollection (reader, mCreatureLists, contentFileMap); + readReferenceCollection (reader, mCreatureLists, contentFileMap); break; case ESM::REC_LEVI: diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 90570b260d..0f2ef13013 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -45,7 +45,7 @@ add_component_dir (esm 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 statstate - npcstats creaturestats weatherstate quickkeys fogstate spellstate activespells + npcstats creaturestats weatherstate quickkeys fogstate spellstate activespells creaturelevliststate ) add_component_dir (misc diff --git a/components/esm/creaturelevliststate.cpp b/components/esm/creaturelevliststate.cpp new file mode 100644 index 0000000000..164dae96e9 --- /dev/null +++ b/components/esm/creaturelevliststate.cpp @@ -0,0 +1,25 @@ +#include "creaturelevliststate.hpp" + +#include "esmreader.hpp" +#include "esmwriter.hpp" + +namespace ESM +{ + + void CreatureLevListState::load(ESMReader &esm) + { + ObjectState::load(esm); + + mSpawnActorId = -1; + esm.getHNOT (mSpawnActorId, "SPAW"); + } + + void CreatureLevListState::save(ESMWriter &esm, bool inInventory) const + { + ObjectState::save(esm, inInventory); + + if (mSpawnActorId != -1) + esm.writeHNT ("SPAW", mSpawnActorId); + } + +} diff --git a/components/esm/creaturelevliststate.hpp b/components/esm/creaturelevliststate.hpp new file mode 100644 index 0000000000..99b5a7fa2a --- /dev/null +++ b/components/esm/creaturelevliststate.hpp @@ -0,0 +1,19 @@ +#ifndef OPENMW_ESM_CREATURELEVLISTSTATE_H +#define OPENMW_ESM_CREATURELEVLISTSTATE_H + +#include "objectstate.hpp" + +namespace ESM +{ + // format 0, saved games only + + struct CreatureLevListState : public ObjectState + { + int mSpawnActorId; + + virtual void load (ESMReader &esm); + virtual void save (ESMWriter &esm, bool inInventory = false) const; + }; +} + +#endif