forked from mirror/openmw-tes3mp
make sure local variables are loaded when trying to access them from outside of a script (Fixes #2659)
This commit is contained in:
parent
ceada145ab
commit
2a981a5272
6 changed files with 75 additions and 32 deletions
|
@ -198,13 +198,12 @@ namespace MWScript
|
||||||
|
|
||||||
if (iter==mScripts.end())
|
if (iter==mScripts.end())
|
||||||
{
|
{
|
||||||
if (const ESM::Script *script = mStore.get<ESM::Script>().find (name))
|
const ESM::Script *script = mStore.get<ESM::Script>().find (name);
|
||||||
{
|
|
||||||
GlobalScriptDesc desc;
|
|
||||||
desc.mLocals.configure (*script);
|
|
||||||
|
|
||||||
iter = mScripts.insert (std::make_pair (name, desc)).first;
|
GlobalScriptDesc desc;
|
||||||
}
|
desc.mLocals.configure (*script);
|
||||||
|
|
||||||
|
iter = mScripts.insert (std::make_pair (name2, desc)).first;
|
||||||
}
|
}
|
||||||
|
|
||||||
return iter->second.mLocals;
|
return iter->second.mLocals;
|
||||||
|
|
|
@ -9,13 +9,32 @@
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/scriptmanager.hpp"
|
#include "../mwbase/scriptmanager.hpp"
|
||||||
|
#include "../mwbase/world.hpp"
|
||||||
|
|
||||||
|
#include "../mwworld/esmstore.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
namespace MWScript
|
namespace MWScript
|
||||||
{
|
{
|
||||||
void Locals::configure (const ESM::Script& script)
|
void Locals::ensure (const std::string& scriptName)
|
||||||
{
|
{
|
||||||
|
if (!mInitialised)
|
||||||
|
{
|
||||||
|
const ESM::Script *script = MWBase::Environment::get().getWorld()->getStore().
|
||||||
|
get<ESM::Script>().find (scriptName);
|
||||||
|
|
||||||
|
configure (*script);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Locals::Locals() : mInitialised (false) {}
|
||||||
|
|
||||||
|
bool Locals::configure (const ESM::Script& script)
|
||||||
|
{
|
||||||
|
if (mInitialised)
|
||||||
|
return false;
|
||||||
|
|
||||||
const Compiler::Locals& locals =
|
const Compiler::Locals& locals =
|
||||||
MWBase::Environment::get().getScriptManager()->getLocals (script.mId);
|
MWBase::Environment::get().getScriptManager()->getLocals (script.mId);
|
||||||
|
|
||||||
|
@ -25,6 +44,9 @@ namespace MWScript
|
||||||
mLongs.resize (locals.get ('l').size(), 0);
|
mLongs.resize (locals.get ('l').size(), 0);
|
||||||
mFloats.clear();
|
mFloats.clear();
|
||||||
mFloats.resize (locals.get ('f').size(), 0);
|
mFloats.resize (locals.get ('f').size(), 0);
|
||||||
|
|
||||||
|
mInitialised = true;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Locals::isEmpty() const
|
bool Locals::isEmpty() const
|
||||||
|
@ -36,6 +58,8 @@ namespace MWScript
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
ensure (script);
|
||||||
|
|
||||||
const Compiler::Locals& locals =
|
const Compiler::Locals& locals =
|
||||||
MWBase::Environment::get().getScriptManager()->getLocals(script);
|
MWBase::Environment::get().getScriptManager()->getLocals(script);
|
||||||
int index = locals.getIndex(var);
|
int index = locals.getIndex(var);
|
||||||
|
@ -49,6 +73,8 @@ namespace MWScript
|
||||||
|
|
||||||
int Locals::getIntVar(const std::string &script, const std::string &var)
|
int Locals::getIntVar(const std::string &script, const std::string &var)
|
||||||
{
|
{
|
||||||
|
ensure (script);
|
||||||
|
|
||||||
const Compiler::Locals& locals = MWBase::Environment::get().getScriptManager()->getLocals(script);
|
const Compiler::Locals& locals = MWBase::Environment::get().getScriptManager()->getLocals(script);
|
||||||
int index = locals.getIndex(var);
|
int index = locals.getIndex(var);
|
||||||
char type = locals.getType(var);
|
char type = locals.getType(var);
|
||||||
|
@ -73,6 +99,8 @@ namespace MWScript
|
||||||
|
|
||||||
bool Locals::setVarByInt(const std::string& script, const std::string& var, int val)
|
bool Locals::setVarByInt(const std::string& script, const std::string& var, int val)
|
||||||
{
|
{
|
||||||
|
ensure (script);
|
||||||
|
|
||||||
const Compiler::Locals& locals = MWBase::Environment::get().getScriptManager()->getLocals(script);
|
const Compiler::Locals& locals = MWBase::Environment::get().getScriptManager()->getLocals(script);
|
||||||
int index = locals.getIndex(var);
|
int index = locals.getIndex(var);
|
||||||
char type = locals.getType(var);
|
char type = locals.getType(var);
|
||||||
|
@ -94,8 +122,11 @@ namespace MWScript
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Locals::write (ESM::Locals& locals, const std::string& script) const
|
bool Locals::write (ESM::Locals& locals, const std::string& script) const
|
||||||
{
|
{
|
||||||
|
if (!mInitialised)
|
||||||
|
return false;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
const Compiler::Locals& declarations =
|
const Compiler::Locals& declarations =
|
||||||
|
@ -132,10 +163,14 @@ namespace MWScript
|
||||||
catch (const Compiler::SourceException&)
|
catch (const Compiler::SourceException&)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Locals::read (const ESM::Locals& locals, const std::string& script)
|
void Locals::read (const ESM::Locals& locals, const std::string& script)
|
||||||
{
|
{
|
||||||
|
ensure (script);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
const Compiler::Locals& declarations =
|
const Compiler::Locals& declarations =
|
||||||
|
|
|
@ -15,30 +15,50 @@ namespace MWScript
|
||||||
{
|
{
|
||||||
class Locals
|
class Locals
|
||||||
{
|
{
|
||||||
|
bool mInitialised;
|
||||||
|
|
||||||
|
void ensure (const std::string& scriptName);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::vector<Interpreter::Type_Short> mShorts;
|
std::vector<Interpreter::Type_Short> mShorts;
|
||||||
std::vector<Interpreter::Type_Integer> mLongs;
|
std::vector<Interpreter::Type_Integer> mLongs;
|
||||||
std::vector<Interpreter::Type_Float> mFloats;
|
std::vector<Interpreter::Type_Float> mFloats;
|
||||||
|
|
||||||
|
Locals();
|
||||||
|
|
||||||
/// Are there any locals?
|
/// Are there any locals?
|
||||||
|
///
|
||||||
|
/// \note Will return false, if locals have not been configured yet.
|
||||||
bool isEmpty() const;
|
bool isEmpty() const;
|
||||||
|
|
||||||
void configure (const ESM::Script& script);
|
/// \return Did the state of *this change from uninitialised to initialised?
|
||||||
|
bool configure (const ESM::Script& script);
|
||||||
|
|
||||||
/// @note var needs to be in lowercase
|
/// @note var needs to be in lowercase
|
||||||
|
///
|
||||||
|
/// \note Locals will be automatically configured first, if necessary
|
||||||
bool setVarByInt(const std::string& script, const std::string& var, int val);
|
bool setVarByInt(const std::string& script, const std::string& var, int val);
|
||||||
|
|
||||||
|
/// \note Locals will be automatically configured first, if necessary
|
||||||
|
//
|
||||||
|
// \note If it can not be determined if the variable exists, the error will be
|
||||||
|
// ignored and false will be returned.
|
||||||
bool hasVar(const std::string& script, const std::string& var);
|
bool hasVar(const std::string& script, const std::string& var);
|
||||||
|
|
||||||
/// if var does not exist, returns 0
|
/// if var does not exist, returns 0
|
||||||
/// @note var needs to be in lowercase
|
/// @note var needs to be in lowercase
|
||||||
|
///
|
||||||
|
/// \note Locals will be automatically configured first, if necessary
|
||||||
int getIntVar (const std::string& script, const std::string& var);
|
int getIntVar (const std::string& script, const std::string& var);
|
||||||
|
|
||||||
void write (ESM::Locals& locals, const std::string& script) const;
|
/// \note If locals have not been configured yet, no data is written.
|
||||||
|
///
|
||||||
|
/// \return Locals written?
|
||||||
|
bool write (ESM::Locals& locals, const std::string& script) const;
|
||||||
|
|
||||||
|
/// \note Locals will be automatically configured first, if necessary
|
||||||
void read (const ESM::Locals& locals, const std::string& script);
|
void read (const ESM::Locals& locals, const std::string& script);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -170,7 +170,7 @@ namespace MWScript
|
||||||
return iter->second;
|
return iter->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (const ESM::Script *script = mStore.get<ESM::Script>().find (name2))
|
if (const ESM::Script *script = mStore.get<ESM::Script>().search (name2))
|
||||||
{
|
{
|
||||||
if (mVerbose)
|
if (mVerbose)
|
||||||
std::cout
|
std::cout
|
||||||
|
|
|
@ -14,7 +14,6 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
mBaseNode = refData.mBaseNode;
|
mBaseNode = refData.mBaseNode;
|
||||||
mLocals = refData.mLocals;
|
mLocals = refData.mLocals;
|
||||||
mHasLocals = refData.mHasLocals;
|
|
||||||
mEnabled = refData.mEnabled;
|
mEnabled = refData.mEnabled;
|
||||||
mCount = refData.mCount;
|
mCount = refData.mCount;
|
||||||
mPosition = refData.mPosition;
|
mPosition = refData.mPosition;
|
||||||
|
@ -34,7 +33,7 @@ namespace MWWorld
|
||||||
}
|
}
|
||||||
|
|
||||||
RefData::RefData()
|
RefData::RefData()
|
||||||
: mBaseNode(0), mDeleted(false), mHasLocals (false), mEnabled (true), mCount (1), mCustomData (0), mChanged(false)
|
: mBaseNode(0), mDeleted(false), mEnabled (true), mCount (1), mCustomData (0), mChanged(false)
|
||||||
{
|
{
|
||||||
for (int i=0; i<3; ++i)
|
for (int i=0; i<3; ++i)
|
||||||
{
|
{
|
||||||
|
@ -45,7 +44,7 @@ namespace MWWorld
|
||||||
}
|
}
|
||||||
|
|
||||||
RefData::RefData (const ESM::CellRef& cellRef)
|
RefData::RefData (const ESM::CellRef& cellRef)
|
||||||
: mBaseNode(0), mDeleted(false), mHasLocals (false), mEnabled (true),
|
: mBaseNode(0), mDeleted(false), mEnabled (true),
|
||||||
mCount (1), mPosition (cellRef.mPos),
|
mCount (1), mPosition (cellRef.mPos),
|
||||||
mCustomData (0),
|
mCustomData (0),
|
||||||
mChanged(false) // Loading from ESM/ESP files -> assume unchanged
|
mChanged(false) // Loading from ESM/ESP files -> assume unchanged
|
||||||
|
@ -56,13 +55,13 @@ namespace MWWorld
|
||||||
}
|
}
|
||||||
|
|
||||||
RefData::RefData (const ESM::ObjectState& objectState)
|
RefData::RefData (const ESM::ObjectState& objectState)
|
||||||
: mBaseNode(0), mDeleted(false), mHasLocals (false),
|
: mBaseNode(0), mDeleted(false),
|
||||||
mEnabled (objectState.mEnabled != 0),
|
mEnabled (objectState.mEnabled != 0),
|
||||||
mCount (objectState.mCount),
|
mCount (objectState.mCount),
|
||||||
mPosition (objectState.mPosition),
|
mPosition (objectState.mPosition),
|
||||||
mCustomData (0),
|
mCustomData (0),
|
||||||
mChanged(true) // Loading from a savegame -> assume changed
|
mChanged(true) // Loading from a savegame -> assume changed
|
||||||
{
|
{
|
||||||
for (int i=0; i<3; ++i)
|
for (int i=0; i<3; ++i)
|
||||||
mLocalRotation.rot[i] = objectState.mLocalRotation[i];
|
mLocalRotation.rot[i] = objectState.mLocalRotation[i];
|
||||||
}
|
}
|
||||||
|
@ -83,10 +82,7 @@ namespace MWWorld
|
||||||
|
|
||||||
void RefData::write (ESM::ObjectState& objectState, const std::string& scriptId) const
|
void RefData::write (ESM::ObjectState& objectState, const std::string& scriptId) const
|
||||||
{
|
{
|
||||||
objectState.mHasLocals = mHasLocals;
|
objectState.mHasLocals = mLocals.write (objectState.mLocals, scriptId);
|
||||||
|
|
||||||
if (mHasLocals)
|
|
||||||
mLocals.write (objectState.mLocals, scriptId);
|
|
||||||
|
|
||||||
objectState.mEnabled = mEnabled;
|
objectState.mEnabled = mEnabled;
|
||||||
objectState.mCount = mCount;
|
objectState.mCount = mCount;
|
||||||
|
@ -139,13 +135,8 @@ namespace MWWorld
|
||||||
|
|
||||||
void RefData::setLocals (const ESM::Script& script)
|
void RefData::setLocals (const ESM::Script& script)
|
||||||
{
|
{
|
||||||
if (!mHasLocals)
|
if (mLocals.configure (script) && !mLocals.isEmpty())
|
||||||
{
|
mChanged = true;
|
||||||
mLocals.configure (script);
|
|
||||||
mHasLocals = true;
|
|
||||||
if (!mLocals.isEmpty())
|
|
||||||
mChanged = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RefData::setCount (int count)
|
void RefData::setCount (int count)
|
||||||
|
|
|
@ -31,11 +31,9 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
osg::PositionAttitudeTransform* mBaseNode;
|
osg::PositionAttitudeTransform* mBaseNode;
|
||||||
|
|
||||||
MWScript::Locals mLocals; // if we find the overhead of heaving a locals
|
MWScript::Locals mLocals;
|
||||||
// object in the refdata of refs without a script,
|
|
||||||
// we can make this a pointer later.
|
|
||||||
bool mDeleted; // separate delete flag used for deletion by a content file
|
bool mDeleted; // separate delete flag used for deletion by a content file
|
||||||
bool mHasLocals;
|
|
||||||
bool mEnabled;
|
bool mEnabled;
|
||||||
int mCount; // 0: deleted
|
int mCount; // 0: deleted
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue