mirror of
https://github.com/OpenMW/openmw.git
synced 2025-06-24 17:11:33 +00:00
Saving/loading for Lua scripts (saves format is changed)
This commit is contained in:
parent
914e604e06
commit
8c6d303730
16 changed files with 248 additions and 8 deletions
|
@ -56,7 +56,7 @@ add_openmw_dir (mwscript
|
||||||
)
|
)
|
||||||
|
|
||||||
add_openmw_dir (mwlua
|
add_openmw_dir (mwlua
|
||||||
luamanagerimp localscripts object worldview luabindings userdataserializer
|
luamanagerimp localscripts object worldview luabindings userdataserializer eventqueue
|
||||||
objectbindings asyncbindings
|
objectbindings asyncbindings
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,18 @@ namespace MWWorld
|
||||||
class Ptr;
|
class Ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Loading
|
||||||
|
{
|
||||||
|
class Listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace ESM
|
||||||
|
{
|
||||||
|
class ESMReader;
|
||||||
|
class ESMWriter;
|
||||||
|
class LuaScripts;
|
||||||
|
}
|
||||||
|
|
||||||
namespace MWBase
|
namespace MWBase
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -35,6 +47,18 @@ namespace MWBase
|
||||||
|
|
||||||
virtual void clear() = 0;
|
virtual void clear() = 0;
|
||||||
virtual void setupPlayer(const MWWorld::Ptr&) = 0;
|
virtual void setupPlayer(const MWWorld::Ptr&) = 0;
|
||||||
|
|
||||||
|
// Saving
|
||||||
|
int countSavedGameRecords() const { return 1; };
|
||||||
|
virtual void write(ESM::ESMWriter& writer, Loading::Listener& progress) = 0;
|
||||||
|
virtual void saveLocalScripts(const MWWorld::Ptr& ptr, ESM::LuaScripts& data) = 0;
|
||||||
|
|
||||||
|
// Loading from a save
|
||||||
|
virtual void readRecord(ESM::ESMReader& reader, uint32_t type) = 0;
|
||||||
|
virtual void loadLocalScripts(const MWWorld::Ptr& ptr, const ESM::LuaScripts& data) = 0;
|
||||||
|
|
||||||
|
// Should be called before loading. The map is used to fix refnums if the order of content files was changed.
|
||||||
|
virtual void setContentFileMapping(const std::map<int, int>&) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
63
apps/openmw/mwlua/eventqueue.cpp
Normal file
63
apps/openmw/mwlua/eventqueue.cpp
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
#include "eventqueue.hpp"
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
|
|
||||||
|
#include <components/esm/esmreader.hpp>
|
||||||
|
#include <components/esm/esmwriter.hpp>
|
||||||
|
#include <components/esm/luascripts.hpp>
|
||||||
|
|
||||||
|
#include <components/lua/serialization.hpp>
|
||||||
|
|
||||||
|
namespace MWLua
|
||||||
|
{
|
||||||
|
|
||||||
|
template <typename Event>
|
||||||
|
void saveEvent(ESM::ESMWriter& esm, const ObjectId& dest, const Event& event)
|
||||||
|
{
|
||||||
|
esm.writeHNString("LUAE", event.eventName);
|
||||||
|
dest.save(esm, true);
|
||||||
|
if (!event.eventData.empty())
|
||||||
|
saveLuaBinaryData(esm, event.eventData);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loadEvents(sol::state& lua, ESM::ESMReader& esm, GlobalEventQueue& globalEvents, LocalEventQueue& localEvents,
|
||||||
|
const std::map<int, int>& contentFileMapping, const LuaUtil::UserdataSerializer* serializer)
|
||||||
|
{
|
||||||
|
while (esm.isNextSub("LUAE"))
|
||||||
|
{
|
||||||
|
std::string name = esm.getHString();
|
||||||
|
ObjectId dest;
|
||||||
|
dest.load(esm, true);
|
||||||
|
std::string data = loadLuaBinaryData(esm);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
data = LuaUtil::serialize(LuaUtil::deserialize(lua, data, serializer), serializer);
|
||||||
|
}
|
||||||
|
catch (std::exception& e)
|
||||||
|
{
|
||||||
|
Log(Debug::Error) << "loadEvent: invalid event data: " << e.what();
|
||||||
|
}
|
||||||
|
if (dest.isSet())
|
||||||
|
{
|
||||||
|
auto it = contentFileMapping.find(dest.mContentFile);
|
||||||
|
if (it != contentFileMapping.end())
|
||||||
|
dest.mContentFile = it->second;
|
||||||
|
localEvents.push_back({dest, std::move(name), std::move(data)});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
globalEvents.push_back({std::move(name), std::move(data)});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void saveEvents(ESM::ESMWriter& esm, const GlobalEventQueue& globalEvents, const LocalEventQueue& localEvents)
|
||||||
|
{
|
||||||
|
ObjectId globalId;
|
||||||
|
globalId.unset(); // Used as a marker of a global event.
|
||||||
|
|
||||||
|
for (const GlobalEvent& e : globalEvents)
|
||||||
|
saveEvent(esm, globalId, e);
|
||||||
|
for (const LocalEvent& e : localEvents)
|
||||||
|
saveEvent(esm, e.dest, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -3,6 +3,22 @@
|
||||||
|
|
||||||
#include "object.hpp"
|
#include "object.hpp"
|
||||||
|
|
||||||
|
namespace ESM
|
||||||
|
{
|
||||||
|
class ESMReader;
|
||||||
|
class ESMWriter;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace LuaUtil
|
||||||
|
{
|
||||||
|
class UserdataSerializer;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace sol
|
||||||
|
{
|
||||||
|
class state;
|
||||||
|
}
|
||||||
|
|
||||||
namespace MWLua
|
namespace MWLua
|
||||||
{
|
{
|
||||||
struct GlobalEvent
|
struct GlobalEvent
|
||||||
|
@ -18,6 +34,10 @@ namespace MWLua
|
||||||
};
|
};
|
||||||
using GlobalEventQueue = std::vector<GlobalEvent>;
|
using GlobalEventQueue = std::vector<GlobalEvent>;
|
||||||
using LocalEventQueue = std::vector<LocalEvent>;
|
using LocalEventQueue = std::vector<LocalEvent>;
|
||||||
|
|
||||||
|
void loadEvents(sol::state& lua, ESM::ESMReader& esm, GlobalEventQueue&, LocalEventQueue&,
|
||||||
|
const std::map<int, int>& contentFileMapping, const LuaUtil::UserdataSerializer* serializer);
|
||||||
|
void saveEvents(ESM::ESMWriter& esm, const GlobalEventQueue&, const LocalEventQueue&);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // MWLUA_EVENTQUEUE_H
|
#endif // MWLUA_EVENTQUEUE_H
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
#include "luamanagerimp.hpp"
|
#include "luamanagerimp.hpp"
|
||||||
|
|
||||||
#include <components/debug/debuglog.hpp>
|
#include <components/debug/debuglog.hpp>
|
||||||
|
|
||||||
|
#include <components/esm/esmreader.hpp>
|
||||||
|
#include <components/esm/esmwriter.hpp>
|
||||||
|
#include <components/esm/luascripts.hpp>
|
||||||
|
|
||||||
#include <components/lua/utilpackage.hpp>
|
#include <components/lua/utilpackage.hpp>
|
||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
@ -15,8 +20,12 @@ namespace MWLua
|
||||||
LuaManager::LuaManager(const VFS::Manager* vfs) : mLua(vfs)
|
LuaManager::LuaManager(const VFS::Manager* vfs) : mLua(vfs)
|
||||||
{
|
{
|
||||||
Log(Debug::Info) << "Lua version: " << LuaUtil::getLuaVersion();
|
Log(Debug::Info) << "Lua version: " << LuaUtil::getLuaVersion();
|
||||||
|
|
||||||
mGlobalSerializer = createUserdataSerializer(false, mWorldView.getObjectRegistry());
|
mGlobalSerializer = createUserdataSerializer(false, mWorldView.getObjectRegistry());
|
||||||
mLocalSerializer = createUserdataSerializer(true, mWorldView.getObjectRegistry());
|
mLocalSerializer = createUserdataSerializer(true, mWorldView.getObjectRegistry());
|
||||||
|
mGlobalLoader = createUserdataSerializer(false, mWorldView.getObjectRegistry(), &mContentFileMapping);
|
||||||
|
mLocalLoader = createUserdataSerializer(true, mWorldView.getObjectRegistry(), &mContentFileMapping);
|
||||||
|
|
||||||
mGlobalScripts.setSerializer(mGlobalSerializer.get());
|
mGlobalScripts.setSerializer(mGlobalSerializer.get());
|
||||||
|
|
||||||
Context context;
|
Context context;
|
||||||
|
@ -210,4 +219,56 @@ namespace MWLua
|
||||||
return refData.getLuaScripts();
|
return refData.getLuaScripts();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LuaManager::write(ESM::ESMWriter& writer, Loading::Listener& progress)
|
||||||
|
{
|
||||||
|
writer.startRecord(ESM::REC_LUAM);
|
||||||
|
|
||||||
|
mWorldView.save(writer);
|
||||||
|
ESM::LuaScripts globalScripts;
|
||||||
|
mGlobalScripts.save(globalScripts);
|
||||||
|
globalScripts.save(writer);
|
||||||
|
saveEvents(writer, mGlobalEvents, mLocalEvents);
|
||||||
|
|
||||||
|
writer.endRecord(ESM::REC_LUAM);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LuaManager::readRecord(ESM::ESMReader& reader, uint32_t type)
|
||||||
|
{
|
||||||
|
if (type != ESM::REC_LUAM)
|
||||||
|
throw std::runtime_error("ESM::REC_LUAM is expected");
|
||||||
|
|
||||||
|
mWorldView.load(reader);
|
||||||
|
ESM::LuaScripts globalScripts;
|
||||||
|
globalScripts.load(reader);
|
||||||
|
loadEvents(mLua.sol(), reader, mGlobalEvents, mLocalEvents, mContentFileMapping, mGlobalLoader.get());
|
||||||
|
|
||||||
|
mGlobalScripts.setSerializer(mGlobalLoader.get());
|
||||||
|
mGlobalScripts.load(globalScripts, false);
|
||||||
|
mGlobalScripts.setSerializer(mGlobalSerializer.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
void LuaManager::saveLocalScripts(const MWWorld::Ptr& ptr, ESM::LuaScripts& data)
|
||||||
|
{
|
||||||
|
if (ptr.getRefData().getLuaScripts())
|
||||||
|
ptr.getRefData().getLuaScripts()->save(data);
|
||||||
|
else
|
||||||
|
data.mScripts.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LuaManager::loadLocalScripts(const MWWorld::Ptr& ptr, const ESM::LuaScripts& data)
|
||||||
|
{
|
||||||
|
if (data.mScripts.empty())
|
||||||
|
{
|
||||||
|
if (ptr.getRefData().getLuaScripts())
|
||||||
|
ptr.getRefData().setLuaScripts(nullptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mWorldView.getObjectRegistry()->registerPtr(ptr);
|
||||||
|
LocalScripts* scripts = createLocalScripts(ptr);
|
||||||
|
|
||||||
|
scripts->setSerializer(mLocalLoader.get());
|
||||||
|
scripts->load(data, true);
|
||||||
|
scripts->setSerializer(mLocalSerializer.get());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,15 @@ namespace MWLua
|
||||||
// Used only in luabindings.cpp
|
// Used only in luabindings.cpp
|
||||||
void addLocalScript(const MWWorld::Ptr&, const std::string& scriptPath);
|
void addLocalScript(const MWWorld::Ptr&, const std::string& scriptPath);
|
||||||
|
|
||||||
|
// Saving
|
||||||
|
void write(ESM::ESMWriter& writer, Loading::Listener& progress) override;
|
||||||
|
void saveLocalScripts(const MWWorld::Ptr& ptr, ESM::LuaScripts& data) override;
|
||||||
|
|
||||||
|
// Loading from a save
|
||||||
|
void readRecord(ESM::ESMReader& reader, uint32_t type) override;
|
||||||
|
void loadLocalScripts(const MWWorld::Ptr& ptr, const ESM::LuaScripts& data) override;
|
||||||
|
void setContentFileMapping(const std::map<int, int>& mapping) override { mContentFileMapping = mapping; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LocalScripts* createLocalScripts(const MWWorld::Ptr& ptr);
|
LocalScripts* createLocalScripts(const MWWorld::Ptr& ptr);
|
||||||
|
|
||||||
|
@ -69,6 +78,10 @@ namespace MWLua
|
||||||
std::unique_ptr<LuaUtil::UserdataSerializer> mGlobalSerializer;
|
std::unique_ptr<LuaUtil::UserdataSerializer> mGlobalSerializer;
|
||||||
std::unique_ptr<LuaUtil::UserdataSerializer> mLocalSerializer;
|
std::unique_ptr<LuaUtil::UserdataSerializer> mLocalSerializer;
|
||||||
|
|
||||||
|
std::map<int, int> mContentFileMapping;
|
||||||
|
std::unique_ptr<LuaUtil::UserdataSerializer> mGlobalLoader;
|
||||||
|
std::unique_ptr<LuaUtil::UserdataSerializer> mLocalLoader;
|
||||||
|
|
||||||
std::vector<SDL_Keysym> mKeyPressEvents;
|
std::vector<SDL_Keysym> mKeyPressEvents;
|
||||||
std::vector<ObjectId> mActorAddedEvents;
|
std::vector<ObjectId> mActorAddedEvents;
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,8 +11,8 @@ namespace MWLua
|
||||||
class Serializer final : public LuaUtil::UserdataSerializer
|
class Serializer final : public LuaUtil::UserdataSerializer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit Serializer(bool localSerializer, ObjectRegistry* registry)
|
explicit Serializer(bool localSerializer, ObjectRegistry* registry, std::map<int, int>* contentFileMapping)
|
||||||
: mLocalSerializer(localSerializer), mObjectRegistry(registry) {}
|
: mLocalSerializer(localSerializer), mObjectRegistry(registry), mContentFileMapping(contentFileMapping) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Appends serialized sol::userdata to the end of BinaryData.
|
// Appends serialized sol::userdata to the end of BinaryData.
|
||||||
|
@ -43,6 +43,12 @@ namespace MWLua
|
||||||
std::memcpy(&id, binaryData.data(), sizeof(ObjectId));
|
std::memcpy(&id, binaryData.data(), sizeof(ObjectId));
|
||||||
id.mIndex = Misc::fromLittleEndian(id.mIndex);
|
id.mIndex = Misc::fromLittleEndian(id.mIndex);
|
||||||
id.mContentFile = Misc::fromLittleEndian(id.mContentFile);
|
id.mContentFile = Misc::fromLittleEndian(id.mContentFile);
|
||||||
|
if (id.hasContentFile() && mContentFileMapping)
|
||||||
|
{
|
||||||
|
auto iter = mContentFileMapping->find(id.mContentFile);
|
||||||
|
if (iter != mContentFileMapping->end())
|
||||||
|
id.mContentFile = iter->second;
|
||||||
|
}
|
||||||
if (mLocalSerializer)
|
if (mLocalSerializer)
|
||||||
sol::stack::push<LObject>(lua, LObject(id, mObjectRegistry));
|
sol::stack::push<LObject>(lua, LObject(id, mObjectRegistry));
|
||||||
else
|
else
|
||||||
|
@ -54,11 +60,13 @@ namespace MWLua
|
||||||
|
|
||||||
bool mLocalSerializer;
|
bool mLocalSerializer;
|
||||||
ObjectRegistry* mObjectRegistry;
|
ObjectRegistry* mObjectRegistry;
|
||||||
|
std::map<int, int>* mContentFileMapping;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::unique_ptr<LuaUtil::UserdataSerializer> createUserdataSerializer(bool local, ObjectRegistry* registry)
|
std::unique_ptr<LuaUtil::UserdataSerializer> createUserdataSerializer(
|
||||||
|
bool local, ObjectRegistry* registry, std::map<int, int>* contentFileMapping)
|
||||||
{
|
{
|
||||||
return std::make_unique<Serializer>(local, registry);
|
return std::make_unique<Serializer>(local, registry, contentFileMapping);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,10 @@ namespace MWLua
|
||||||
// UserdataSerializer is an extension for components/lua/serialization.hpp
|
// UserdataSerializer is an extension for components/lua/serialization.hpp
|
||||||
// Needed to serialize references to objects.
|
// Needed to serialize references to objects.
|
||||||
// If local=true, then during deserialization creates LObject, otherwise creates GObject.
|
// If local=true, then during deserialization creates LObject, otherwise creates GObject.
|
||||||
std::unique_ptr<LuaUtil::UserdataSerializer> createUserdataSerializer(bool local, ObjectRegistry* registry);
|
// contentFileMapping is used only for deserialization. Needed to fix references if the order
|
||||||
|
// of content files was changed.
|
||||||
|
std::unique_ptr<LuaUtil::UserdataSerializer> createUserdataSerializer(
|
||||||
|
bool local, ObjectRegistry* registry, std::map<int, int>* contentFileMapping = nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // MWLUA_USERDATASERIALIZER_H
|
#endif // MWLUA_USERDATASERIALIZER_H
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
#include "worldview.hpp"
|
#include "worldview.hpp"
|
||||||
|
|
||||||
|
#include <components/esm/esmreader.hpp>
|
||||||
|
#include <components/esm/esmwriter.hpp>
|
||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
#include "../mwworld/timestamp.hpp"
|
#include "../mwworld/timestamp.hpp"
|
||||||
|
|
||||||
|
@ -43,6 +46,20 @@ namespace MWLua
|
||||||
return static_cast<double>(timeStamp.getDay()) * 24 + timeStamp.getHour();
|
return static_cast<double>(timeStamp.getDay()) * 24 + timeStamp.getHour();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WorldView::load(ESM::ESMReader& esm)
|
||||||
|
{
|
||||||
|
esm.getHNT(mGameSeconds, "LUAW");
|
||||||
|
ObjectId lastAssignedId;
|
||||||
|
lastAssignedId.load(esm, true);
|
||||||
|
mObjectRegistry.setLastAssignedId(lastAssignedId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorldView::save(ESM::ESMWriter& esm) const
|
||||||
|
{
|
||||||
|
esm.writeHNT("LUAW", mGameSeconds);
|
||||||
|
mObjectRegistry.getLastAssignedId().save(esm, true);
|
||||||
|
}
|
||||||
|
|
||||||
void WorldView::ObjectGroup::updateList()
|
void WorldView::ObjectGroup::updateList()
|
||||||
{
|
{
|
||||||
if (mChanged)
|
if (mChanged)
|
||||||
|
|
|
@ -3,6 +3,12 @@
|
||||||
|
|
||||||
#include "object.hpp"
|
#include "object.hpp"
|
||||||
|
|
||||||
|
namespace ESM
|
||||||
|
{
|
||||||
|
class ESMWriter;
|
||||||
|
class ESMReader;
|
||||||
|
}
|
||||||
|
|
||||||
namespace MWLua
|
namespace MWLua
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -31,6 +37,9 @@ namespace MWLua
|
||||||
void objectAddedToScene(const MWWorld::Ptr& ptr);
|
void objectAddedToScene(const MWWorld::Ptr& ptr);
|
||||||
void objectRemovedFromScene(const MWWorld::Ptr& ptr);
|
void objectRemovedFromScene(const MWWorld::Ptr& ptr);
|
||||||
|
|
||||||
|
void load(ESM::ESMReader& esm);
|
||||||
|
void save(ESM::ESMWriter& esm) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct ObjectGroup
|
struct ObjectGroup
|
||||||
{
|
{
|
||||||
|
|
|
@ -251,6 +251,7 @@ void MWState::StateManager::saveGame (const std::string& description, const Slot
|
||||||
|
|
||||||
int recordCount = 1 // saved game header
|
int recordCount = 1 // saved game header
|
||||||
+MWBase::Environment::get().getJournal()->countSavedGameRecords()
|
+MWBase::Environment::get().getJournal()->countSavedGameRecords()
|
||||||
|
+MWBase::Environment::get().getLuaManager()->countSavedGameRecords()
|
||||||
+MWBase::Environment::get().getWorld()->countSavedGameRecords()
|
+MWBase::Environment::get().getWorld()->countSavedGameRecords()
|
||||||
+MWBase::Environment::get().getScriptManager()->getGlobalScripts().countSavedGameRecords()
|
+MWBase::Environment::get().getScriptManager()->getGlobalScripts().countSavedGameRecords()
|
||||||
+MWBase::Environment::get().getDialogueManager()->countSavedGameRecords()
|
+MWBase::Environment::get().getDialogueManager()->countSavedGameRecords()
|
||||||
|
@ -274,6 +275,9 @@ void MWState::StateManager::saveGame (const std::string& description, const Slot
|
||||||
|
|
||||||
MWBase::Environment::get().getJournal()->write (writer, listener);
|
MWBase::Environment::get().getJournal()->write (writer, listener);
|
||||||
MWBase::Environment::get().getDialogueManager()->write (writer, listener);
|
MWBase::Environment::get().getDialogueManager()->write (writer, listener);
|
||||||
|
// LuaManager::write should be called before World::write because world also saves
|
||||||
|
// local scripts that depend on LuaManager.
|
||||||
|
MWBase::Environment::get().getLuaManager()->write(writer, listener);
|
||||||
MWBase::Environment::get().getWorld()->write (writer, listener);
|
MWBase::Environment::get().getWorld()->write (writer, listener);
|
||||||
MWBase::Environment::get().getScriptManager()->getGlobalScripts().write (writer, listener);
|
MWBase::Environment::get().getScriptManager()->getGlobalScripts().write (writer, listener);
|
||||||
MWBase::Environment::get().getWindowManager()->write(writer, listener);
|
MWBase::Environment::get().getWindowManager()->write(writer, listener);
|
||||||
|
@ -384,6 +388,7 @@ void MWState::StateManager::loadGame (const Character *character, const std::str
|
||||||
throw std::runtime_error("This save file was created using a newer version of OpenMW and is thus not supported. Please upgrade to the newest OpenMW version to load this file.");
|
throw std::runtime_error("This save file was created using a newer version of OpenMW and is thus not supported. Please upgrade to the newest OpenMW version to load this file.");
|
||||||
|
|
||||||
std::map<int, int> contentFileMap = buildContentFileIndexMap (reader);
|
std::map<int, int> contentFileMap = buildContentFileIndexMap (reader);
|
||||||
|
MWBase::Environment::get().getLuaManager()->setContentFileMapping(contentFileMap);
|
||||||
|
|
||||||
Loading::Listener& listener = *MWBase::Environment::get().getWindowManager()->getLoadingScreen();
|
Loading::Listener& listener = *MWBase::Environment::get().getWindowManager()->getLoadingScreen();
|
||||||
|
|
||||||
|
@ -482,6 +487,10 @@ void MWState::StateManager::loadGame (const Character *character, const std::str
|
||||||
MWBase::Environment::get().getInputManager()->readRecord(reader, n.intval);
|
MWBase::Environment::get().getInputManager()->readRecord(reader, n.intval);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ESM::REC_LUAM:
|
||||||
|
MWBase::Environment::get().getLuaManager()->readRecord(reader, n.intval);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
||||||
// ignore invalid records
|
// ignore invalid records
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
|
#include "../mwbase/luamanager.hpp"
|
||||||
|
|
||||||
#include "ptr.hpp"
|
#include "ptr.hpp"
|
||||||
#include "class.hpp"
|
#include "class.hpp"
|
||||||
|
@ -52,6 +53,8 @@ void MWWorld::LiveCellRefBase::loadImp (const ESM::ObjectState& state)
|
||||||
Log(Debug::Warning) << "Soul '" << mRef.getSoul() << "' not found, removing the soul from soul gem";
|
Log(Debug::Warning) << "Soul '" << mRef.getSoul() << "' not found, removing the soul from soul gem";
|
||||||
mRef.setSoul(std::string());
|
mRef.setSoul(std::string());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MWBase::Environment::get().getLuaManager()->loadLocalScripts(ptr, state.mLuaScripts);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MWWorld::LiveCellRefBase::saveImp (ESM::ObjectState& state) const
|
void MWWorld::LiveCellRefBase::saveImp (ESM::ObjectState& state) const
|
||||||
|
@ -61,6 +64,7 @@ void MWWorld::LiveCellRefBase::saveImp (ESM::ObjectState& state) const
|
||||||
ConstPtr ptr (this);
|
ConstPtr ptr (this);
|
||||||
|
|
||||||
mData.write (state, mClass->getScript (ptr));
|
mData.write (state, mClass->getScript (ptr));
|
||||||
|
MWBase::Environment::get().getLuaManager()->saveLocalScripts(Ptr(const_cast<LiveCellRefBase*>(this)), state.mLuaScripts);
|
||||||
|
|
||||||
mClass->writeAdditionalState (ptr, state);
|
mClass->writeAdditionalState (ptr, state);
|
||||||
}
|
}
|
||||||
|
|
|
@ -164,7 +164,10 @@ enum RecNameInts
|
||||||
|
|
||||||
// format 1
|
// format 1
|
||||||
REC_FILT = FourCC<'F','I','L','T'>::value,
|
REC_FILT = FourCC<'F','I','L','T'>::value,
|
||||||
REC_DBGP = FourCC<'D','B','G','P'>::value ///< only used in project files
|
REC_DBGP = FourCC<'D','B','G','P'>::value, ///< only used in project files
|
||||||
|
|
||||||
|
// format 16 - Lua scripts in saved games
|
||||||
|
REC_LUAM = FourCC<'L','U','A','M'>::value, // LuaManager data
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Common subrecords
|
/// Common subrecords
|
||||||
|
|
|
@ -20,6 +20,8 @@ void ESM::ObjectState::load (ESMReader &esm)
|
||||||
if (mHasLocals)
|
if (mHasLocals)
|
||||||
mLocals.load (esm);
|
mLocals.load (esm);
|
||||||
|
|
||||||
|
mLuaScripts.load(esm);
|
||||||
|
|
||||||
mEnabled = 1;
|
mEnabled = 1;
|
||||||
esm.getHNOT (mEnabled, "ENAB");
|
esm.getHNOT (mEnabled, "ENAB");
|
||||||
|
|
||||||
|
@ -56,6 +58,8 @@ void ESM::ObjectState::save (ESMWriter &esm, bool inInventory) const
|
||||||
mLocals.save (esm);
|
mLocals.save (esm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mLuaScripts.save(esm);
|
||||||
|
|
||||||
if (!mEnabled && !inInventory)
|
if (!mEnabled && !inInventory)
|
||||||
esm.writeHNT ("ENAB", mEnabled);
|
esm.writeHNT ("ENAB", mEnabled);
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include "cellref.hpp"
|
#include "cellref.hpp"
|
||||||
#include "locals.hpp"
|
#include "locals.hpp"
|
||||||
|
#include "luascripts.hpp"
|
||||||
#include "animationstate.hpp"
|
#include "animationstate.hpp"
|
||||||
|
|
||||||
namespace ESM
|
namespace ESM
|
||||||
|
@ -27,6 +28,7 @@ namespace ESM
|
||||||
|
|
||||||
unsigned char mHasLocals;
|
unsigned char mHasLocals;
|
||||||
Locals mLocals;
|
Locals mLocals;
|
||||||
|
LuaScripts mLuaScripts;
|
||||||
unsigned char mEnabled;
|
unsigned char mEnabled;
|
||||||
int mCount;
|
int mCount;
|
||||||
ESM::Position mPosition;
|
ESM::Position mPosition;
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#include "esmwriter.hpp"
|
#include "esmwriter.hpp"
|
||||||
|
|
||||||
unsigned int ESM::SavedGame::sRecordId = ESM::REC_SAVE;
|
unsigned int ESM::SavedGame::sRecordId = ESM::REC_SAVE;
|
||||||
int ESM::SavedGame::sCurrentFormat = 15;
|
int ESM::SavedGame::sCurrentFormat = 16;
|
||||||
|
|
||||||
void ESM::SavedGame::load (ESMReader &esm)
|
void ESM::SavedGame::load (ESMReader &esm)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue