mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-02-03 17:54:06 +00:00
Allow targeting non-unique actors with StartScript (bug #2311)
This commit is contained in:
parent
7a6ba8bf7a
commit
3b4782959e
@ -2,6 +2,7 @@
|
|||||||
------
|
------
|
||||||
|
|
||||||
Bug #1952: Incorrect particle lighting
|
Bug #1952: Incorrect particle lighting
|
||||||
|
Bug #2311: Targeted scripts are not properly supported on non-unique RefIDs
|
||||||
Bug #3676: NiParticleColorModifier isn't applied properly
|
Bug #3676: NiParticleColorModifier isn't applied properly
|
||||||
Bug #5358: ForceGreeting always resets the dialogue window completely
|
Bug #5358: ForceGreeting always resets the dialogue window completely
|
||||||
Bug #5363: Enchantment autocalc not always 0/1
|
Bug #5363: Enchantment autocalc not always 0/1
|
||||||
|
@ -35,7 +35,7 @@ namespace MWBase
|
|||||||
|
|
||||||
virtual ~ScriptManager() {}
|
virtual ~ScriptManager() {}
|
||||||
|
|
||||||
virtual void run (const std::string& name, Interpreter::Context& interpreterContext) = 0;
|
virtual bool run (const std::string& name, Interpreter::Context& interpreterContext) = 0;
|
||||||
///< Run the script with the given name (compile first, if not compiled yet)
|
///< Run the script with the given name (compile first, if not compiled yet)
|
||||||
|
|
||||||
virtual bool compile (const std::string& name) = 0;
|
virtual bool compile (const std::string& name) = 0;
|
||||||
|
@ -189,6 +189,8 @@ namespace MWBase
|
|||||||
virtual MWWorld::Ptr searchPtrViaActorId (int actorId) = 0;
|
virtual MWWorld::Ptr searchPtrViaActorId (int actorId) = 0;
|
||||||
///< Search is limited to the active cells.
|
///< Search is limited to the active cells.
|
||||||
|
|
||||||
|
virtual MWWorld::Ptr searchPtrViaRefNum (const std::string& id, const ESM::RefNum& refNum) = 0;
|
||||||
|
|
||||||
virtual MWWorld::Ptr findContainer (const MWWorld::ConstPtr& ptr) = 0;
|
virtual MWWorld::Ptr findContainer (const MWWorld::ConstPtr& ptr) = 0;
|
||||||
///< Return a pointer to a liveCellRef which contains \a ptr.
|
///< Return a pointer to a liveCellRef which contains \a ptr.
|
||||||
/// \note Search is limited to the active cells.
|
/// \note Search is limited to the active cells.
|
||||||
|
@ -5,83 +5,171 @@
|
|||||||
#include <components/esm/esmwriter.hpp>
|
#include <components/esm/esmwriter.hpp>
|
||||||
#include <components/esm/globalscript.hpp>
|
#include <components/esm/globalscript.hpp>
|
||||||
|
|
||||||
|
#include "../mwworld/class.hpp"
|
||||||
#include "../mwworld/esmstore.hpp"
|
#include "../mwworld/esmstore.hpp"
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
|
#include "../mwbase/world.hpp"
|
||||||
#include "../mwbase/scriptmanager.hpp"
|
#include "../mwbase/scriptmanager.hpp"
|
||||||
|
|
||||||
|
#include "../mwmechanics/creaturestats.hpp"
|
||||||
|
|
||||||
#include "interpretercontext.hpp"
|
#include "interpretercontext.hpp"
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
struct ScriptCreatingVisitor : public boost::static_visitor<ESM::GlobalScript>
|
||||||
|
{
|
||||||
|
ESM::GlobalScript operator()(const MWWorld::Ptr &ptr) const
|
||||||
|
{
|
||||||
|
ESM::GlobalScript script;
|
||||||
|
script.mTargetRef.unset();
|
||||||
|
if (!ptr.isEmpty())
|
||||||
|
{
|
||||||
|
if (ptr.getCellRef().hasContentFile())
|
||||||
|
{
|
||||||
|
script.mTargetId = ptr.getCellRef().getRefId();
|
||||||
|
script.mTargetRef = ptr.getCellRef().getRefNum();
|
||||||
|
}
|
||||||
|
else if (MWBase::Environment::get().getWorld()->getPlayerPtr() == ptr)
|
||||||
|
script.mTargetId = ptr.getCellRef().getRefId();
|
||||||
|
}
|
||||||
|
return script;
|
||||||
|
}
|
||||||
|
|
||||||
|
ESM::GlobalScript operator()(const std::pair<ESM::RefNum, std::string> &pair) const
|
||||||
|
{
|
||||||
|
ESM::GlobalScript script;
|
||||||
|
script.mTargetId = pair.second;
|
||||||
|
script.mTargetRef = pair.first;
|
||||||
|
return script;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PtrGettingVisitor : public boost::static_visitor<const MWWorld::Ptr*>
|
||||||
|
{
|
||||||
|
const MWWorld::Ptr* operator()(const MWWorld::Ptr &ptr) const
|
||||||
|
{
|
||||||
|
return &ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const MWWorld::Ptr* operator()(const std::pair<ESM::RefNum, std::string> &pair) const
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PtrResolvingVisitor : public boost::static_visitor<MWWorld::Ptr>
|
||||||
|
{
|
||||||
|
MWWorld::Ptr operator()(const MWWorld::Ptr &ptr) const
|
||||||
|
{
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
MWWorld::Ptr operator()(const std::pair<ESM::RefNum, std::string> &pair) const
|
||||||
|
{
|
||||||
|
if (pair.second.empty())
|
||||||
|
return MWWorld::Ptr();
|
||||||
|
else if(pair.first.hasContentFile())
|
||||||
|
return MWBase::Environment::get().getWorld()->searchPtrViaRefNum(pair.second, pair.first);
|
||||||
|
return MWBase::Environment::get().getWorld()->searchPtr(pair.second, false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class MatchPtrVisitor : public boost::static_visitor<bool>
|
||||||
|
{
|
||||||
|
const MWWorld::Ptr& mPtr;
|
||||||
|
public:
|
||||||
|
MatchPtrVisitor(const MWWorld::Ptr& ptr) : mPtr(ptr) {}
|
||||||
|
|
||||||
|
bool operator()(const MWWorld::Ptr &ptr) const
|
||||||
|
{
|
||||||
|
return ptr == mPtr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator()(const std::pair<ESM::RefNum, std::string> &pair) const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
namespace MWScript
|
namespace MWScript
|
||||||
{
|
{
|
||||||
GlobalScriptDesc::GlobalScriptDesc() : mRunning (false) {}
|
GlobalScriptDesc::GlobalScriptDesc() : mRunning (false) {}
|
||||||
|
|
||||||
|
const MWWorld::Ptr* GlobalScriptDesc::getPtrIfPresent() const
|
||||||
|
{
|
||||||
|
return boost::apply_visitor(PtrGettingVisitor(), mTarget);
|
||||||
|
}
|
||||||
|
|
||||||
|
MWWorld::Ptr GlobalScriptDesc::getPtr()
|
||||||
|
{
|
||||||
|
MWWorld::Ptr ptr = boost::apply_visitor(PtrResolvingVisitor(), mTarget);
|
||||||
|
mTarget = ptr;
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
GlobalScripts::GlobalScripts (const MWWorld::ESMStore& store)
|
GlobalScripts::GlobalScripts (const MWWorld::ESMStore& store)
|
||||||
: mStore (store)
|
: mStore (store)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void GlobalScripts::addScript (const std::string& name, const std::string& targetId)
|
void GlobalScripts::addScript (const std::string& name, const MWWorld::Ptr& target)
|
||||||
{
|
{
|
||||||
std::map<std::string, GlobalScriptDesc>::iterator iter =
|
const auto iter = mScripts.find (::Misc::StringUtils::lowerCase (name));
|
||||||
mScripts.find (::Misc::StringUtils::lowerCase (name));
|
|
||||||
|
|
||||||
if (iter==mScripts.end())
|
if (iter==mScripts.end())
|
||||||
{
|
{
|
||||||
if (const ESM::Script *script = mStore.get<ESM::Script>().search(name))
|
if (const ESM::Script *script = mStore.get<ESM::Script>().search(name))
|
||||||
{
|
{
|
||||||
GlobalScriptDesc desc;
|
auto desc = std::make_shared<GlobalScriptDesc>();
|
||||||
desc.mRunning = true;
|
MWWorld::Ptr ptr = target;
|
||||||
desc.mLocals.configure (*script);
|
desc->mTarget = ptr;
|
||||||
desc.mId = targetId;
|
desc->mRunning = true;
|
||||||
|
desc->mLocals.configure (*script);
|
||||||
mScripts.insert (std::make_pair (name, desc));
|
mScripts.insert (std::make_pair(name, desc));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Log(Debug::Error) << "Failed to add global script " << name << ": script record not found";
|
Log(Debug::Error) << "Failed to add global script " << name << ": script record not found";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!iter->second.mRunning)
|
else if (!iter->second->mRunning)
|
||||||
{
|
{
|
||||||
iter->second.mRunning = true;
|
iter->second->mRunning = true;
|
||||||
iter->second.mId = targetId;
|
MWWorld::Ptr ptr = target;
|
||||||
|
iter->second->mTarget = ptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GlobalScripts::removeScript (const std::string& name)
|
void GlobalScripts::removeScript (const std::string& name)
|
||||||
{
|
{
|
||||||
std::map<std::string, GlobalScriptDesc>::iterator iter =
|
const auto iter = mScripts.find (::Misc::StringUtils::lowerCase (name));
|
||||||
mScripts.find (::Misc::StringUtils::lowerCase (name));
|
|
||||||
|
|
||||||
if (iter!=mScripts.end())
|
if (iter!=mScripts.end())
|
||||||
iter->second.mRunning = false;
|
iter->second->mRunning = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GlobalScripts::isRunning (const std::string& name) const
|
bool GlobalScripts::isRunning (const std::string& name) const
|
||||||
{
|
{
|
||||||
std::map<std::string, GlobalScriptDesc>::const_iterator iter =
|
const auto iter = mScripts.find (::Misc::StringUtils::lowerCase (name));
|
||||||
mScripts.find (::Misc::StringUtils::lowerCase (name));
|
|
||||||
|
|
||||||
if (iter==mScripts.end())
|
if (iter==mScripts.end())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return iter->second.mRunning;
|
return iter->second->mRunning;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GlobalScripts::run()
|
void GlobalScripts::run()
|
||||||
{
|
{
|
||||||
for (std::map<std::string, GlobalScriptDesc>::iterator iter (mScripts.begin());
|
for (const auto& script : mScripts)
|
||||||
iter!=mScripts.end(); ++iter)
|
|
||||||
{
|
{
|
||||||
if (iter->second.mRunning)
|
if (script.second->mRunning)
|
||||||
{
|
{
|
||||||
MWWorld::Ptr ptr;
|
MWScript::InterpreterContext context(script.second);
|
||||||
|
if (!MWBase::Environment::get().getScriptManager()->run(script.first, context))
|
||||||
MWScript::InterpreterContext interpreterContext (
|
script.second->mRunning = false;
|
||||||
&iter->second.mLocals, MWWorld::Ptr(), iter->second.mId);
|
|
||||||
|
|
||||||
MWBase::Environment::get().getScriptManager()->run (iter->first, interpreterContext);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -129,18 +217,15 @@ namespace MWScript
|
|||||||
|
|
||||||
void GlobalScripts::write (ESM::ESMWriter& writer, Loading::Listener& progress) const
|
void GlobalScripts::write (ESM::ESMWriter& writer, Loading::Listener& progress) const
|
||||||
{
|
{
|
||||||
for (std::map<std::string, GlobalScriptDesc>::const_iterator iter (mScripts.begin());
|
for (const auto& iter : mScripts)
|
||||||
iter!=mScripts.end(); ++iter)
|
|
||||||
{
|
{
|
||||||
ESM::GlobalScript script;
|
ESM::GlobalScript script = boost::apply_visitor (ScriptCreatingVisitor(), iter.second->mTarget);
|
||||||
|
|
||||||
script.mId = iter->first;
|
script.mId = iter.first;
|
||||||
|
|
||||||
iter->second.mLocals.write (script.mLocals, iter->first);
|
iter.second->mLocals.write (script.mLocals, iter.first);
|
||||||
|
|
||||||
script.mRunning = iter->second.mRunning ? 1 : 0;
|
script.mRunning = iter.second->mRunning ? 1 : 0;
|
||||||
|
|
||||||
script.mTargetId = iter->second.mId;
|
|
||||||
|
|
||||||
writer.startRecord (ESM::REC_GSCR);
|
writer.startRecord (ESM::REC_GSCR);
|
||||||
script.save (writer);
|
script.save (writer);
|
||||||
@ -155,8 +240,7 @@ namespace MWScript
|
|||||||
ESM::GlobalScript script;
|
ESM::GlobalScript script;
|
||||||
script.load (reader);
|
script.load (reader);
|
||||||
|
|
||||||
std::map<std::string, GlobalScriptDesc>::iterator iter =
|
auto iter = mScripts.find (script.mId);
|
||||||
mScripts.find (script.mId);
|
|
||||||
|
|
||||||
if (iter==mScripts.end())
|
if (iter==mScripts.end())
|
||||||
{
|
{
|
||||||
@ -164,8 +248,12 @@ namespace MWScript
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
GlobalScriptDesc desc;
|
auto desc = std::make_shared<GlobalScriptDesc>();
|
||||||
desc.mLocals.configure (*scriptRecord);
|
if (!script.mTargetId.empty())
|
||||||
|
{
|
||||||
|
desc->mTarget = std::make_pair(script.mTargetRef, script.mTargetId);
|
||||||
|
}
|
||||||
|
desc->mLocals.configure (*scriptRecord);
|
||||||
|
|
||||||
iter = mScripts.insert (std::make_pair (script.mId, desc)).first;
|
iter = mScripts.insert (std::make_pair (script.mId, desc)).first;
|
||||||
}
|
}
|
||||||
@ -182,9 +270,8 @@ namespace MWScript
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
iter->second.mRunning = script.mRunning!=0;
|
iter->second->mRunning = script.mRunning!=0;
|
||||||
iter->second.mLocals.read (script.mLocals, script.mId);
|
iter->second->mLocals.read (script.mLocals, script.mId);
|
||||||
iter->second.mId = script.mTargetId;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -195,18 +282,28 @@ namespace MWScript
|
|||||||
Locals& GlobalScripts::getLocals (const std::string& name)
|
Locals& GlobalScripts::getLocals (const std::string& name)
|
||||||
{
|
{
|
||||||
std::string name2 = ::Misc::StringUtils::lowerCase (name);
|
std::string name2 = ::Misc::StringUtils::lowerCase (name);
|
||||||
std::map<std::string, GlobalScriptDesc>::iterator iter = mScripts.find (name2);
|
auto iter = mScripts.find (name2);
|
||||||
|
|
||||||
if (iter==mScripts.end())
|
if (iter==mScripts.end())
|
||||||
{
|
{
|
||||||
const ESM::Script *script = mStore.get<ESM::Script>().find (name);
|
const ESM::Script *script = mStore.get<ESM::Script>().find (name);
|
||||||
|
|
||||||
GlobalScriptDesc desc;
|
auto desc = std::make_shared<GlobalScriptDesc>();
|
||||||
desc.mLocals.configure (*script);
|
desc->mLocals.configure (*script);
|
||||||
|
|
||||||
iter = mScripts.insert (std::make_pair (name2, desc)).first;
|
iter = mScripts.insert (std::make_pair (name2, desc)).first;
|
||||||
}
|
}
|
||||||
|
|
||||||
return iter->second.mLocals;
|
return iter->second->mLocals;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GlobalScripts::updatePtrs(const MWWorld::Ptr& base, const MWWorld::Ptr& updated)
|
||||||
|
{
|
||||||
|
MatchPtrVisitor visitor(base);
|
||||||
|
for (const auto& script : mScripts)
|
||||||
|
{
|
||||||
|
if (boost::apply_visitor (visitor, script.second->mTarget))
|
||||||
|
script.second->mTarget = updated;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,24 @@
|
|||||||
#ifndef GAME_SCRIPT_GLOBALSCRIPTS_H
|
#ifndef GAME_SCRIPT_GLOBALSCRIPTS_H
|
||||||
#define GAME_SCRIPT_GLOBALSCRIPTS_H
|
#define GAME_SCRIPT_GLOBALSCRIPTS_H
|
||||||
|
|
||||||
|
#include <boost/variant/variant.hpp>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "locals.hpp"
|
#include "locals.hpp"
|
||||||
|
|
||||||
|
#include "../mwworld/ptr.hpp"
|
||||||
|
|
||||||
namespace ESM
|
namespace ESM
|
||||||
{
|
{
|
||||||
class ESMWriter;
|
class ESMWriter;
|
||||||
class ESMReader;
|
class ESMReader;
|
||||||
|
struct RefNum;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Loading
|
namespace Loading
|
||||||
@ -30,21 +37,25 @@ namespace MWScript
|
|||||||
{
|
{
|
||||||
bool mRunning;
|
bool mRunning;
|
||||||
Locals mLocals;
|
Locals mLocals;
|
||||||
std::string mId; // ID used to start targeted script (empty if not a targeted script)
|
boost::variant<MWWorld::Ptr, std::pair<ESM::RefNum, std::string> > mTarget; // Used to start targeted script
|
||||||
|
|
||||||
GlobalScriptDesc();
|
GlobalScriptDesc();
|
||||||
|
|
||||||
|
const MWWorld::Ptr* getPtrIfPresent() const; // Returns a Ptr if one has been resolved
|
||||||
|
|
||||||
|
MWWorld::Ptr getPtr(); // Resolves mTarget to a Ptr and caches the (potentially empty) result
|
||||||
};
|
};
|
||||||
|
|
||||||
class GlobalScripts
|
class GlobalScripts
|
||||||
{
|
{
|
||||||
const MWWorld::ESMStore& mStore;
|
const MWWorld::ESMStore& mStore;
|
||||||
std::map<std::string, GlobalScriptDesc> mScripts;
|
std::map<std::string, std::shared_ptr<GlobalScriptDesc> > mScripts;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
GlobalScripts (const MWWorld::ESMStore& store);
|
GlobalScripts (const MWWorld::ESMStore& store);
|
||||||
|
|
||||||
void addScript (const std::string& name, const std::string& targetId = "");
|
void addScript (const std::string& name, const MWWorld::Ptr& target = MWWorld::Ptr());
|
||||||
|
|
||||||
void removeScript (const std::string& name);
|
void removeScript (const std::string& name);
|
||||||
|
|
||||||
@ -70,6 +81,9 @@ namespace MWScript
|
|||||||
Locals& getLocals (const std::string& name);
|
Locals& getLocals (const std::string& name);
|
||||||
///< If the script \a name has not been added as a global script yet, it is added
|
///< If the script \a name has not been added as a global script yet, it is added
|
||||||
/// automatically, but is not set to running state.
|
/// automatically, but is not set to running state.
|
||||||
|
|
||||||
|
void updatePtrs(const MWWorld::Ptr& base, const MWWorld::Ptr& updated);
|
||||||
|
///< Update the Ptrs stored in mTarget. Should be called after the reference has been moved to a new cell.
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
#include "interpretercontext.hpp"
|
#include "interpretercontext.hpp"
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <stdexcept>
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
#include <components/compiler/locals.hpp>
|
#include <components/compiler/locals.hpp>
|
||||||
@ -28,26 +27,6 @@
|
|||||||
|
|
||||||
namespace MWScript
|
namespace MWScript
|
||||||
{
|
{
|
||||||
MWWorld::Ptr InterpreterContext::getReferenceImp (
|
|
||||||
const std::string& id, bool activeOnly, bool doThrow)
|
|
||||||
{
|
|
||||||
if (!id.empty())
|
|
||||||
{
|
|
||||||
return MWBase::Environment::get().getWorld()->getPtr (id, activeOnly);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (mReference.isEmpty() && !mTargetId.empty())
|
|
||||||
mReference =
|
|
||||||
MWBase::Environment::get().getWorld()->searchPtr (mTargetId, false);
|
|
||||||
|
|
||||||
if (mReference.isEmpty() && doThrow)
|
|
||||||
throw std::runtime_error ("no implicit reference");
|
|
||||||
|
|
||||||
return mReference;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const MWWorld::Ptr InterpreterContext::getReferenceImp (
|
const MWWorld::Ptr InterpreterContext::getReferenceImp (
|
||||||
const std::string& id, bool activeOnly, bool doThrow) const
|
const std::string& id, bool activeOnly, bool doThrow) const
|
||||||
{
|
{
|
||||||
@ -57,12 +36,11 @@ namespace MWScript
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (mReference.isEmpty() && !mTargetId.empty())
|
if (mReference.isEmpty() && mGlobalScriptDesc)
|
||||||
mReference =
|
mReference = mGlobalScriptDesc->getPtr();
|
||||||
MWBase::Environment::get().getWorld()->searchPtr (mTargetId, false);
|
|
||||||
|
|
||||||
if (mReference.isEmpty() && doThrow)
|
if (mReference.isEmpty() && doThrow)
|
||||||
throw std::runtime_error ("no implicit reference");
|
throw MissingImplicitRefError();
|
||||||
|
|
||||||
return mReference;
|
return mReference;
|
||||||
}
|
}
|
||||||
@ -80,7 +58,7 @@ namespace MWScript
|
|||||||
{
|
{
|
||||||
const MWWorld::Ptr ptr = getReferenceImp (id, false);
|
const MWWorld::Ptr ptr = getReferenceImp (id, false);
|
||||||
|
|
||||||
id = ptr.getClass().getScript (ptr);
|
id = ptr.getClass().getScript (ptr);
|
||||||
|
|
||||||
ptr.getRefData().setLocals (
|
ptr.getRefData().setLocals (
|
||||||
*MWBase::Environment::get().getWorld()->getStore().get<ESM::Script>().find (id));
|
*MWBase::Environment::get().getWorld()->getStore().get<ESM::Script>().find (id));
|
||||||
@ -109,6 +87,8 @@ namespace MWScript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MissingImplicitRefError::MissingImplicitRefError() : std::runtime_error("no implicit reference") {}
|
||||||
|
|
||||||
int InterpreterContext::findLocalVariableIndex (const std::string& scriptId,
|
int InterpreterContext::findLocalVariableIndex (const std::string& scriptId,
|
||||||
const std::string& name, char type) const
|
const std::string& name, char type) const
|
||||||
{
|
{
|
||||||
@ -134,16 +114,21 @@ namespace MWScript
|
|||||||
throw std::runtime_error (stream.str().c_str());
|
throw std::runtime_error (stream.str().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
InterpreterContext::InterpreterContext (MWScript::Locals *locals, const MWWorld::Ptr& reference)
|
||||||
|
: mLocals (locals), mReference (reference)
|
||||||
|
{}
|
||||||
|
|
||||||
InterpreterContext::InterpreterContext (
|
InterpreterContext::InterpreterContext (std::shared_ptr<GlobalScriptDesc> globalScriptDesc)
|
||||||
MWScript::Locals *locals, const MWWorld::Ptr& reference, const std::string& targetId)
|
: mLocals (&(globalScriptDesc->mLocals))
|
||||||
: mLocals (locals), mReference (reference), mTargetId (targetId)
|
|
||||||
{
|
{
|
||||||
// If we run on a reference (local script, dialogue script or console with object
|
const MWWorld::Ptr* ptr = globalScriptDesc->getPtrIfPresent();
|
||||||
// selected), store the ID of that reference store it so it can be inherited by
|
// A nullptr here signifies that the script's target has not yet been resolved after loading the game.
|
||||||
// targeted scripts started from this one.
|
// Script targets are lazily resolved to MWWorld::Ptrs (which can, upon resolution, be empty)
|
||||||
if (targetId.empty() && !reference.isEmpty())
|
// because scripts started through dialogue often don't use their implicit target.
|
||||||
mTargetId = reference.getCellRef().getRefId();
|
if (ptr)
|
||||||
|
mReference = *ptr;
|
||||||
|
else
|
||||||
|
mGlobalScriptDesc = globalScriptDesc;
|
||||||
}
|
}
|
||||||
|
|
||||||
int InterpreterContext::getLocalShort (int index) const
|
int InterpreterContext::getLocalShort (int index) const
|
||||||
@ -437,7 +422,12 @@ namespace MWScript
|
|||||||
|
|
||||||
void InterpreterContext::startScript (const std::string& name, const std::string& targetId)
|
void InterpreterContext::startScript (const std::string& name, const std::string& targetId)
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getScriptManager()->getGlobalScripts().addScript (name, targetId);
|
MWWorld::Ptr target;
|
||||||
|
if (targetId.empty())
|
||||||
|
target = getReference(false);
|
||||||
|
else
|
||||||
|
target = getReferenceImp(targetId);
|
||||||
|
MWBase::Environment::get().getScriptManager()->getGlobalScripts().addScript (name, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InterpreterContext::stopScript (const std::string& name)
|
void InterpreterContext::stopScript (const std::string& name)
|
||||||
@ -449,12 +439,7 @@ namespace MWScript
|
|||||||
{
|
{
|
||||||
// NOTE: id may be empty, indicating an implicit reference
|
// NOTE: id may be empty, indicating an implicit reference
|
||||||
|
|
||||||
MWWorld::Ptr ref2;
|
MWWorld::Ptr ref2 = getReferenceImp(id);
|
||||||
|
|
||||||
if (id.empty())
|
|
||||||
ref2 = getReferenceImp();
|
|
||||||
else
|
|
||||||
ref2 = MWBase::Environment::get().getWorld()->getPtr(id, false);
|
|
||||||
|
|
||||||
if (ref2.getContainerStore()) // is the object contained?
|
if (ref2.getContainerStore()) // is the object contained?
|
||||||
{
|
{
|
||||||
@ -578,11 +563,6 @@ namespace MWScript
|
|||||||
return getReferenceImp ("", true, required);
|
return getReferenceImp ("", true, required);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string InterpreterContext::getTargetId() const
|
|
||||||
{
|
|
||||||
return mTargetId;
|
|
||||||
}
|
|
||||||
|
|
||||||
void InterpreterContext::updatePtr(const MWWorld::Ptr& base, const MWWorld::Ptr& updated)
|
void InterpreterContext::updatePtr(const MWWorld::Ptr& base, const MWWorld::Ptr& updated)
|
||||||
{
|
{
|
||||||
if (!mReference.isEmpty() && base == mReference)
|
if (!mReference.isEmpty() && base == mReference)
|
||||||
|
@ -1,8 +1,13 @@
|
|||||||
#ifndef GAME_SCRIPT_INTERPRETERCONTEXT_H
|
#ifndef GAME_SCRIPT_INTERPRETERCONTEXT_H
|
||||||
#define GAME_SCRIPT_INTERPRETERCONTEXT_H
|
#define GAME_SCRIPT_INTERPRETERCONTEXT_H
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
#include <components/interpreter/context.hpp>
|
#include <components/interpreter/context.hpp>
|
||||||
|
|
||||||
|
#include "globalscripts.hpp"
|
||||||
|
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
|
|
||||||
namespace MWSound
|
namespace MWSound
|
||||||
@ -19,17 +24,17 @@ namespace MWScript
|
|||||||
{
|
{
|
||||||
class Locals;
|
class Locals;
|
||||||
|
|
||||||
|
class MissingImplicitRefError : public std::runtime_error
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MissingImplicitRefError();
|
||||||
|
};
|
||||||
|
|
||||||
class InterpreterContext : public Interpreter::Context
|
class InterpreterContext : public Interpreter::Context
|
||||||
{
|
{
|
||||||
Locals *mLocals;
|
Locals *mLocals;
|
||||||
mutable MWWorld::Ptr mReference;
|
mutable MWWorld::Ptr mReference;
|
||||||
|
std::shared_ptr<GlobalScriptDesc> mGlobalScriptDesc;
|
||||||
std::string mTargetId;
|
|
||||||
|
|
||||||
/// If \a id is empty, a reference the script is run from is returned or in case
|
|
||||||
/// of a non-local script the reference derived from the target ID.
|
|
||||||
MWWorld::Ptr getReferenceImp (const std::string& id = "", bool activeOnly = false,
|
|
||||||
bool doThrow=true);
|
|
||||||
|
|
||||||
/// If \a id is empty, a reference the script is run from is returned or in case
|
/// If \a id is empty, a reference the script is run from is returned or in case
|
||||||
/// of a non-local script the reference derived from the target ID.
|
/// of a non-local script the reference derived from the target ID.
|
||||||
@ -47,9 +52,9 @@ namespace MWScript
|
|||||||
char type) const;
|
char type) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
InterpreterContext (std::shared_ptr<GlobalScriptDesc> globalScriptDesc);
|
||||||
|
|
||||||
InterpreterContext (MWScript::Locals *locals, const MWWorld::Ptr& reference,
|
InterpreterContext (MWScript::Locals *locals, const MWWorld::Ptr& reference);
|
||||||
const std::string& targetId = "");
|
|
||||||
///< The ownership of \a locals is not transferred. 0-pointer allowed.
|
///< The ownership of \a locals is not transferred. 0-pointer allowed.
|
||||||
|
|
||||||
virtual int getLocalShort (int index) const;
|
virtual int getLocalShort (int index) const;
|
||||||
@ -153,8 +158,6 @@ namespace MWScript
|
|||||||
|
|
||||||
void updatePtr(const MWWorld::Ptr& base, const MWWorld::Ptr& updated);
|
void updatePtr(const MWWorld::Ptr& base, const MWWorld::Ptr& updated);
|
||||||
///< Update the Ptr stored in mReference, if there is one stored there. Should be called after the reference has been moved to a new cell.
|
///< Update the Ptr stored in mReference, if there is one stored there. Should be called after the reference has been moved to a new cell.
|
||||||
|
|
||||||
virtual std::string getTargetId() const;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include "../mwworld/esmstore.hpp"
|
#include "../mwworld/esmstore.hpp"
|
||||||
|
|
||||||
#include "extensions.hpp"
|
#include "extensions.hpp"
|
||||||
|
#include "interpretercontext.hpp"
|
||||||
|
|
||||||
namespace MWScript
|
namespace MWScript
|
||||||
{
|
{
|
||||||
@ -88,7 +89,7 @@ namespace MWScript
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptManager::run (const std::string& name, Interpreter::Context& interpreterContext)
|
bool ScriptManager::run (const std::string& name, Interpreter::Context& interpreterContext)
|
||||||
{
|
{
|
||||||
// compile script
|
// compile script
|
||||||
ScriptCollection::iterator iter = mScripts.find (name);
|
ScriptCollection::iterator iter = mScripts.find (name);
|
||||||
@ -100,7 +101,7 @@ namespace MWScript
|
|||||||
// failed -> ignore script from now on.
|
// failed -> ignore script from now on.
|
||||||
std::vector<Interpreter::Type_Code> empty;
|
std::vector<Interpreter::Type_Code> empty;
|
||||||
mScripts.insert (std::make_pair (name, std::make_pair (empty, Compiler::Locals())));
|
mScripts.insert (std::make_pair (name, std::make_pair (empty, Compiler::Locals())));
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
iter = mScripts.find (name);
|
iter = mScripts.find (name);
|
||||||
@ -118,14 +119,19 @@ namespace MWScript
|
|||||||
}
|
}
|
||||||
|
|
||||||
mInterpreter.run (&iter->second.first[0], iter->second.first.size(), interpreterContext);
|
mInterpreter.run (&iter->second.first[0], iter->second.first.size(), interpreterContext);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (const MissingImplicitRefError& e)
|
||||||
|
{
|
||||||
|
Log(Debug::Error) << "Execution of script " << name << " failed: " << e.what();
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
Log(Debug::Error) << "Execution of script " << name << " failed:";
|
Log(Debug::Error) << "Execution of script " << name << " failed: " << e.what();
|
||||||
Log(Debug::Error) << e.what();
|
|
||||||
|
|
||||||
iter->second.first.clear(); // don't execute again.
|
iter->second.first.clear(); // don't execute again.
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<int, int> ScriptManager::compileAll()
|
std::pair<int, int> ScriptManager::compileAll()
|
||||||
|
@ -55,7 +55,7 @@ namespace MWScript
|
|||||||
Compiler::Context& compilerContext, int warningsMode,
|
Compiler::Context& compilerContext, int warningsMode,
|
||||||
const std::vector<std::string>& scriptBlacklist);
|
const std::vector<std::string>& scriptBlacklist);
|
||||||
|
|
||||||
virtual void run (const std::string& name, Interpreter::Context& interpreterContext);
|
virtual bool run (const std::string& name, Interpreter::Context& interpreterContext);
|
||||||
///< Run the script with the given name (compile first, if not compiled yet)
|
///< Run the script with the given name (compile first, if not compiled yet)
|
||||||
|
|
||||||
virtual bool compile (const std::string& name);
|
virtual bool compile (const std::string& name);
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include <components/esm/esmwriter.hpp>
|
#include <components/esm/esmwriter.hpp>
|
||||||
#include <components/esm/defs.hpp>
|
#include <components/esm/defs.hpp>
|
||||||
#include <components/esm/cellstate.hpp>
|
#include <components/esm/cellstate.hpp>
|
||||||
|
#include <components/esm/cellref.hpp>
|
||||||
#include <components/loadinglistener/loadinglistener.hpp>
|
#include <components/loadinglistener/loadinglistener.hpp>
|
||||||
#include <components/settings/settings.hpp>
|
#include <components/settings/settings.hpp>
|
||||||
|
|
||||||
@ -270,6 +271,37 @@ MWWorld::Ptr MWWorld::Cells::getPtr (const std::string& name)
|
|||||||
return Ptr();
|
return Ptr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MWWorld::Ptr MWWorld::Cells::getPtr (const std::string& id, const ESM::RefNum& refNum)
|
||||||
|
{
|
||||||
|
for (auto& pair : mInteriors)
|
||||||
|
{
|
||||||
|
Ptr ptr = getPtr(pair.second, id, refNum);
|
||||||
|
if (!ptr.isEmpty())
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
for (auto& pair : mExteriors)
|
||||||
|
{
|
||||||
|
Ptr ptr = getPtr(pair.second, id, refNum);
|
||||||
|
if (!ptr.isEmpty())
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
return Ptr();
|
||||||
|
}
|
||||||
|
|
||||||
|
MWWorld::Ptr MWWorld::Cells::getPtr(CellStore& cellStore, const std::string& id, const ESM::RefNum& refNum)
|
||||||
|
{
|
||||||
|
if (cellStore.getState() == CellStore::State_Unloaded)
|
||||||
|
cellStore.preload();
|
||||||
|
if (cellStore.getState() == CellStore::State_Preloaded)
|
||||||
|
{
|
||||||
|
if (cellStore.hasId(id))
|
||||||
|
cellStore.load();
|
||||||
|
else
|
||||||
|
return Ptr();
|
||||||
|
}
|
||||||
|
return cellStore.searchViaRefNum(refNum);
|
||||||
|
}
|
||||||
|
|
||||||
void MWWorld::Cells::getExteriorPtrs(const std::string &name, std::vector<MWWorld::Ptr> &out)
|
void MWWorld::Cells::getExteriorPtrs(const std::string &name, std::vector<MWWorld::Ptr> &out)
|
||||||
{
|
{
|
||||||
const MWWorld::Store<ESM::Cell> &cells = mStore.get<ESM::Cell>();
|
const MWWorld::Store<ESM::Cell> &cells = mStore.get<ESM::Cell>();
|
||||||
|
@ -13,6 +13,7 @@ namespace ESM
|
|||||||
class ESMWriter;
|
class ESMWriter;
|
||||||
struct CellId;
|
struct CellId;
|
||||||
struct Cell;
|
struct Cell;
|
||||||
|
struct RefNum;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Loading
|
namespace Loading
|
||||||
@ -41,6 +42,8 @@ namespace MWWorld
|
|||||||
|
|
||||||
Ptr getPtrAndCache (const std::string& name, CellStore& cellStore);
|
Ptr getPtrAndCache (const std::string& name, CellStore& cellStore);
|
||||||
|
|
||||||
|
Ptr getPtr(CellStore& cellStore, const std::string& id, const ESM::RefNum& refNum);
|
||||||
|
|
||||||
void writeCell (ESM::ESMWriter& writer, CellStore& cell) const;
|
void writeCell (ESM::ESMWriter& writer, CellStore& cell) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -62,6 +65,8 @@ namespace MWWorld
|
|||||||
/// @note name must be lower case
|
/// @note name must be lower case
|
||||||
Ptr getPtr (const std::string& name);
|
Ptr getPtr (const std::string& name);
|
||||||
|
|
||||||
|
Ptr getPtr(const std::string& id, const ESM::RefNum& refNum);
|
||||||
|
|
||||||
void rest (double hours);
|
void rest (double hours);
|
||||||
void recharge (float duration);
|
void recharge (float duration);
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include <components/esm/cellstate.hpp>
|
#include <components/esm/cellstate.hpp>
|
||||||
#include <components/esm/cellid.hpp>
|
#include <components/esm/cellid.hpp>
|
||||||
|
#include <components/esm/cellref.hpp>
|
||||||
#include <components/esm/esmreader.hpp>
|
#include <components/esm/esmreader.hpp>
|
||||||
#include <components/esm/esmwriter.hpp>
|
#include <components/esm/esmwriter.hpp>
|
||||||
#include <components/esm/objectstate.hpp>
|
#include <components/esm/objectstate.hpp>
|
||||||
@ -435,6 +436,32 @@ namespace MWWorld
|
|||||||
return Ptr();
|
return Ptr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class RefNumSearchVisitor
|
||||||
|
{
|
||||||
|
const ESM::RefNum& mRefNum;
|
||||||
|
public:
|
||||||
|
RefNumSearchVisitor(const ESM::RefNum& refNum) : mRefNum(refNum) {}
|
||||||
|
|
||||||
|
Ptr mFound;
|
||||||
|
|
||||||
|
bool operator()(const Ptr& ptr)
|
||||||
|
{
|
||||||
|
if (ptr.getCellRef().getRefNum() == mRefNum)
|
||||||
|
{
|
||||||
|
mFound = ptr;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ptr CellStore::searchViaRefNum (const ESM::RefNum& refNum)
|
||||||
|
{
|
||||||
|
RefNumSearchVisitor searchVisitor(refNum);
|
||||||
|
forEach(searchVisitor);
|
||||||
|
return searchVisitor.mFound;
|
||||||
|
}
|
||||||
|
|
||||||
float CellStore::getWaterLevel() const
|
float CellStore::getWaterLevel() const
|
||||||
{
|
{
|
||||||
if (isExterior())
|
if (isExterior())
|
||||||
|
@ -41,6 +41,7 @@ namespace ESM
|
|||||||
struct CellState;
|
struct CellState;
|
||||||
struct FogState;
|
struct FogState;
|
||||||
struct CellId;
|
struct CellId;
|
||||||
|
struct RefNum;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace MWWorld
|
namespace MWWorld
|
||||||
@ -242,6 +243,11 @@ namespace MWWorld
|
|||||||
Ptr searchViaActorId (int id);
|
Ptr searchViaActorId (int id);
|
||||||
///< Will return an empty Ptr if cell is not loaded.
|
///< Will return an empty Ptr if cell is not loaded.
|
||||||
|
|
||||||
|
Ptr searchViaRefNum (const ESM::RefNum& refNum);
|
||||||
|
///< Will return an empty Ptr if cell is not loaded. Does not check references in
|
||||||
|
/// containers.
|
||||||
|
/// @note Triggers CellStore hasState flag.
|
||||||
|
|
||||||
float getWaterLevel() const;
|
float getWaterLevel() const;
|
||||||
|
|
||||||
bool movedHere(const MWWorld::Ptr& ptr) const;
|
bool movedHere(const MWWorld::Ptr& ptr) const;
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include <components/esm/esmreader.hpp>
|
#include <components/esm/esmreader.hpp>
|
||||||
#include <components/esm/esmwriter.hpp>
|
#include <components/esm/esmwriter.hpp>
|
||||||
#include <components/esm/cellid.hpp>
|
#include <components/esm/cellid.hpp>
|
||||||
|
#include <components/esm/cellref.hpp>
|
||||||
|
|
||||||
#include <components/misc/constants.hpp>
|
#include <components/misc/constants.hpp>
|
||||||
#include <components/misc/resourcehelpers.hpp>
|
#include <components/misc/resourcehelpers.hpp>
|
||||||
@ -752,6 +753,11 @@ namespace MWWorld
|
|||||||
return mWorldScene->searchPtrViaActorId (actorId);
|
return mWorldScene->searchPtrViaActorId (actorId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ptr World::searchPtrViaRefNum (const std::string& id, const ESM::RefNum& refNum)
|
||||||
|
{
|
||||||
|
return mCells.getPtr (id, refNum);
|
||||||
|
}
|
||||||
|
|
||||||
struct FindContainerVisitor
|
struct FindContainerVisitor
|
||||||
{
|
{
|
||||||
ConstPtr mContainedPtr;
|
ConstPtr mContainedPtr;
|
||||||
@ -1290,6 +1296,7 @@ namespace MWWorld
|
|||||||
mRendering->updatePtr(ptr, newPtr);
|
mRendering->updatePtr(ptr, newPtr);
|
||||||
MWBase::Environment::get().getSoundManager()->updatePtr (ptr, newPtr);
|
MWBase::Environment::get().getSoundManager()->updatePtr (ptr, newPtr);
|
||||||
mPhysics->updatePtr(ptr, newPtr);
|
mPhysics->updatePtr(ptr, newPtr);
|
||||||
|
MWBase::Environment::get().getScriptManager()->getGlobalScripts().updatePtrs(ptr, newPtr);
|
||||||
|
|
||||||
MWBase::MechanicsManager *mechMgr = MWBase::Environment::get().getMechanicsManager();
|
MWBase::MechanicsManager *mechMgr = MWBase::Environment::get().getMechanicsManager();
|
||||||
mechMgr->updateCell(ptr, newPtr);
|
mechMgr->updateCell(ptr, newPtr);
|
||||||
|
@ -297,6 +297,8 @@ namespace MWWorld
|
|||||||
Ptr searchPtrViaActorId (int actorId) override;
|
Ptr searchPtrViaActorId (int actorId) override;
|
||||||
///< Search is limited to the active cells.
|
///< Search is limited to the active cells.
|
||||||
|
|
||||||
|
Ptr searchPtrViaRefNum (const std::string& id, const ESM::RefNum& refNum) override;
|
||||||
|
|
||||||
MWWorld::Ptr findContainer (const MWWorld::ConstPtr& ptr) override;
|
MWWorld::Ptr findContainer (const MWWorld::ConstPtr& ptr) override;
|
||||||
///< Return a pointer to a liveCellRef which contains \a ptr.
|
///< Return a pointer to a liveCellRef which contains \a ptr.
|
||||||
/// \note Search is limited to the active cells.
|
/// \note Search is limited to the active cells.
|
||||||
|
@ -12,7 +12,11 @@ void ESM::GlobalScript::load (ESMReader &esm)
|
|||||||
mRunning = 0;
|
mRunning = 0;
|
||||||
esm.getHNOT (mRunning, "RUN_");
|
esm.getHNOT (mRunning, "RUN_");
|
||||||
|
|
||||||
mTargetId = esm.getHNOString ("TARG");
|
mTargetRef.unset();
|
||||||
|
if (esm.peekNextSub("TARG"))
|
||||||
|
mTargetId = esm.getHNString ("TARG");
|
||||||
|
if (esm.peekNextSub("FRMR"))
|
||||||
|
mTargetRef.load(esm, true, "FRMR");
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESM::GlobalScript::save (ESMWriter &esm) const
|
void ESM::GlobalScript::save (ESMWriter &esm) const
|
||||||
@ -24,5 +28,10 @@ void ESM::GlobalScript::save (ESMWriter &esm) const
|
|||||||
if (mRunning)
|
if (mRunning)
|
||||||
esm.writeHNT ("RUN_", mRunning);
|
esm.writeHNT ("RUN_", mRunning);
|
||||||
|
|
||||||
esm.writeHNOString ("TARG", mTargetId);
|
if (!mTargetId.empty())
|
||||||
|
{
|
||||||
|
esm.writeHNOString ("TARG", mTargetId);
|
||||||
|
if (mTargetRef.hasContentFile())
|
||||||
|
mTargetRef.save (esm, true, "FRMR");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#define OPENMW_ESM_GLOBALSCRIPT_H
|
#define OPENMW_ESM_GLOBALSCRIPT_H
|
||||||
|
|
||||||
#include "locals.hpp"
|
#include "locals.hpp"
|
||||||
|
#include "cellref.hpp"
|
||||||
|
|
||||||
namespace ESM
|
namespace ESM
|
||||||
{
|
{
|
||||||
@ -16,6 +17,7 @@ namespace ESM
|
|||||||
Locals mLocals;
|
Locals mLocals;
|
||||||
int mRunning;
|
int mRunning;
|
||||||
std::string mTargetId; // for targeted scripts
|
std::string mTargetId; // for targeted scripts
|
||||||
|
RefNum mTargetRef;
|
||||||
|
|
||||||
void load (ESMReader &esm);
|
void load (ESMReader &esm);
|
||||||
void save (ESMWriter &esm) const;
|
void save (ESMWriter &esm) const;
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
#include "defs.hpp"
|
#include "defs.hpp"
|
||||||
|
|
||||||
unsigned int ESM::SavedGame::sRecordId = ESM::REC_SAVE;
|
unsigned int ESM::SavedGame::sRecordId = ESM::REC_SAVE;
|
||||||
int ESM::SavedGame::sCurrentFormat = 5;
|
int ESM::SavedGame::sCurrentFormat = 6;
|
||||||
|
|
||||||
void ESM::SavedGame::load (ESMReader &esm)
|
void ESM::SavedGame::load (ESMReader &esm)
|
||||||
{
|
{
|
||||||
|
@ -108,8 +108,6 @@ namespace Interpreter
|
|||||||
|
|
||||||
virtual void setMemberFloat (const std::string& id, const std::string& name, float value, bool global)
|
virtual void setMemberFloat (const std::string& id, const std::string& name, float value, bool global)
|
||||||
= 0;
|
= 0;
|
||||||
|
|
||||||
virtual std::string getTargetId() const = 0;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ namespace Interpreter
|
|||||||
{
|
{
|
||||||
std::string name = runtime.getStringLiteral (runtime[0].mInteger);
|
std::string name = runtime.getStringLiteral (runtime[0].mInteger);
|
||||||
runtime.pop();
|
runtime.pop();
|
||||||
runtime.getContext().startScript (name, runtime.getContext().getTargetId());
|
runtime.getContext().startScript (name);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user