mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-19 19:10:12 +00:00
Merge branch 'lua_mwscript' into 'master'
Access local mwscript variables in Lua scripts See merge request OpenMW/openmw!2589
This commit is contained in:
commit
0028127b42
5 changed files with 87 additions and 67 deletions
|
@ -1,6 +1,7 @@
|
|||
#include "localscripts.hpp"
|
||||
|
||||
#include <components/esm3/loadcell.hpp>
|
||||
#include <components/misc/strings/lower.hpp>
|
||||
|
||||
#include "../mwmechanics/aicombat.hpp"
|
||||
#include "../mwmechanics/aiescort.hpp"
|
||||
|
@ -17,6 +18,14 @@
|
|||
#include "context.hpp"
|
||||
#include "worldview.hpp"
|
||||
|
||||
namespace MWLua
|
||||
{
|
||||
struct LocalMWScript
|
||||
{
|
||||
LObject mSelf;
|
||||
};
|
||||
}
|
||||
|
||||
namespace sol
|
||||
{
|
||||
template <>
|
||||
|
@ -27,6 +36,10 @@ namespace sol
|
|||
struct is_automagical<MWLua::LocalScripts::SelfObject> : std::false_type
|
||||
{
|
||||
};
|
||||
template <>
|
||||
struct is_automagical<MWLua::LocalMWScript> : std::false_type
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
namespace MWLua
|
||||
|
@ -61,6 +74,27 @@ namespace MWLua
|
|||
selfAPI["controls"] = sol::readonly_property([](SelfObject& self) { return &self.mControls; });
|
||||
selfAPI["isActive"] = [](SelfObject& self) { return &self.mIsActive; };
|
||||
selfAPI["enableAI"] = [](SelfObject& self, bool v) { self.mControls.mDisableAI = !v; };
|
||||
selfAPI["mwscript"] = sol::readonly_property([](SelfObject& self) -> sol::optional<LocalMWScript> {
|
||||
if (self.ptr().getRefData().getLocals().getScriptId().empty())
|
||||
return sol::nullopt;
|
||||
else
|
||||
return LocalMWScript{ LObject(self.id()) };
|
||||
});
|
||||
|
||||
sol::usertype<LocalMWScript> mwscript = context.mLua->sol().new_usertype<LocalMWScript>("LocalMWScript");
|
||||
mwscript[sol::meta_function::to_string] = [](const LocalMWScript& s) {
|
||||
return s.mSelf.ptr().getRefData().getLocals().getScriptId().getRefIdString();
|
||||
};
|
||||
mwscript[sol::meta_function::index] = [](const LocalMWScript& s, std::string_view var) {
|
||||
MWScript::Locals& locals = s.mSelf.ptr().getRefData().getLocals();
|
||||
return locals.getVarAsDouble(locals.getScriptId(), Misc::StringUtils::lowerCase(var));
|
||||
};
|
||||
mwscript[sol::meta_function::new_index] = [](const LocalMWScript& s, std::string_view var, double val) {
|
||||
MWScript::Locals& locals = s.mSelf.ptr().getRefData().getLocals();
|
||||
if (!locals.setVar(locals.getScriptId(), Misc::StringUtils::lowerCase(var), val))
|
||||
throw std::runtime_error("No variable \"" + std::string(var) + "\" in mwscript \""
|
||||
+ locals.getScriptId().getRefIdString() + "\"");
|
||||
};
|
||||
|
||||
using AiPackage = MWMechanics::AiPackage;
|
||||
sol::usertype<AiPackage> aiPackage = context.mLua->sol().new_usertype<AiPackage>("AiPackage");
|
||||
|
|
|
@ -48,7 +48,7 @@ namespace MWLua
|
|||
{
|
||||
auto* lua = context.mLua;
|
||||
sol::table api(lua->sol(), sol::create);
|
||||
api["API_REVISION"] = 31;
|
||||
api["API_REVISION"] = 32;
|
||||
api["quit"] = [lua]() {
|
||||
Log(Debug::Warning) << "Quit requested by a Lua script.\n" << lua->debugTraceback();
|
||||
MWBase::Environment::get().getStateManager()->requestQuit();
|
||||
|
|
|
@ -56,6 +56,7 @@ namespace MWScript
|
|||
mFloats.resize(locals.get('f').size(), 0);
|
||||
}
|
||||
|
||||
mScriptId = script.mId;
|
||||
mInitialised = true;
|
||||
return true;
|
||||
}
|
||||
|
@ -74,84 +75,52 @@ namespace MWScript
|
|||
return (index != -1);
|
||||
}
|
||||
|
||||
int Locals::getIntVar(const ESM::RefId& script, std::string_view var)
|
||||
double Locals::getVarAsDouble(const ESM::RefId& script, std::string_view var)
|
||||
{
|
||||
ensure(script);
|
||||
|
||||
const Compiler::Locals& locals = MWBase::Environment::get().getScriptManager()->getLocals(script);
|
||||
int index = locals.getIndex(var);
|
||||
char type = locals.getType(var);
|
||||
if (index != -1)
|
||||
if (index == -1)
|
||||
return 0;
|
||||
switch (locals.getType(var))
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case 's':
|
||||
return mShorts.at(index);
|
||||
case 's':
|
||||
return mShorts.at(index);
|
||||
|
||||
case 'l':
|
||||
return mLongs.at(index);
|
||||
case 'l':
|
||||
return mLongs.at(index);
|
||||
|
||||
case 'f':
|
||||
return static_cast<int>(mFloats.at(index));
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
case 'f':
|
||||
return mFloats.at(index);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
float Locals::getFloatVar(ESM::RefId& script, std::string_view var)
|
||||
bool Locals::setVar(const ESM::RefId& script, std::string_view var, double val)
|
||||
{
|
||||
ensure(script);
|
||||
|
||||
const Compiler::Locals& locals = MWBase::Environment::get().getScriptManager()->getLocals(script);
|
||||
int index = locals.getIndex(var);
|
||||
char type = locals.getType(var);
|
||||
if (index != -1)
|
||||
if (index == -1)
|
||||
return false;
|
||||
switch (locals.getType(var))
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case 's':
|
||||
return mShorts.at(index);
|
||||
case 's':
|
||||
mShorts.at(index) = static_cast<Interpreter::Type_Short>(val);
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
return mLongs.at(index);
|
||||
case 'l':
|
||||
mLongs.at(index) = static_cast<Interpreter::Type_Integer>(val);
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
return mFloats.at(index);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
case 'f':
|
||||
mFloats.at(index) = static_cast<Interpreter::Type_Float>(val);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Locals::setVarByInt(const ESM::RefId& script, std::string_view var, int val)
|
||||
{
|
||||
ensure(script);
|
||||
|
||||
const Compiler::Locals& locals = MWBase::Environment::get().getScriptManager()->getLocals(script);
|
||||
int index = locals.getIndex(var);
|
||||
char type = locals.getType(var);
|
||||
if (index != -1)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case 's':
|
||||
mShorts.at(index) = val;
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
mLongs.at(index) = val;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
mFloats.at(index) = static_cast<float>(val);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Locals::write(ESM::Locals& locals, const ESM::RefId& script) const
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include <components/esm/refid.hpp>
|
||||
#include <components/interpreter/types.hpp>
|
||||
|
||||
namespace ESM
|
||||
|
@ -19,6 +20,7 @@ namespace MWScript
|
|||
class Locals
|
||||
{
|
||||
bool mInitialised;
|
||||
ESM::RefId mScriptId;
|
||||
|
||||
void ensure(const ESM::RefId& scriptName);
|
||||
|
||||
|
@ -29,6 +31,8 @@ namespace MWScript
|
|||
|
||||
Locals();
|
||||
|
||||
const ESM::RefId& getScriptId() const { return mScriptId; }
|
||||
|
||||
/// Are there any locals?
|
||||
///
|
||||
/// \note Will return false, if locals have not been configured yet.
|
||||
|
@ -40,7 +44,8 @@ namespace MWScript
|
|||
/// @note var needs to be in lowercase
|
||||
///
|
||||
/// \note Locals will be automatically configured first, if necessary
|
||||
bool setVarByInt(const ESM::RefId& script, std::string_view var, int val);
|
||||
bool setVarByInt(const ESM::RefId& script, std::string_view var, int val) { return setVar(script, var, val); }
|
||||
bool setVar(const ESM::RefId& script, std::string_view var, double val);
|
||||
|
||||
/// \note Locals will be automatically configured first, if necessary
|
||||
//
|
||||
|
@ -52,13 +57,15 @@ namespace MWScript
|
|||
/// @note var needs to be in lowercase
|
||||
///
|
||||
/// \note Locals will be automatically configured first, if necessary
|
||||
int getIntVar(const ESM::RefId& script, std::string_view var);
|
||||
|
||||
/// if var does not exist, returns 0
|
||||
/// @note var needs to be in lowercase
|
||||
///
|
||||
/// \note Locals will be automatically configured first, if necessary
|
||||
float getFloatVar(ESM::RefId& script, std::string_view var);
|
||||
double getVarAsDouble(const ESM::RefId& script, std::string_view var);
|
||||
int getIntVar(const ESM::RefId& script, std::string_view var)
|
||||
{
|
||||
return static_cast<int>(getVarAsDouble(script, var));
|
||||
}
|
||||
float getFloatVar(const ESM::RefId& script, std::string_view var)
|
||||
{
|
||||
return static_cast<float>(getVarAsDouble(script, var));
|
||||
}
|
||||
|
||||
/// \note If locals have not been configured yet, no data is written.
|
||||
///
|
||||
|
|
|
@ -25,6 +25,16 @@
|
|||
-- Movement controls (only for actors)
|
||||
-- @field [parent=#self] #ActorControls controls
|
||||
|
||||
---
|
||||
-- Local variables of an mwscript on this object (nil if there is no mwscript)
|
||||
-- @usage if self.mwscript then ... end -- check if there is an mwscript on this object
|
||||
-- @usage tostring(self.mwscript) -- name of the script
|
||||
-- @usage -- print value of local variable 'something' (0 if there is no such variable)
|
||||
-- print(self.mwscript.something)
|
||||
-- @usage -- set local variable 'something' (raises an error if there is no such variable)
|
||||
-- self.mwscript.something = 5
|
||||
-- @field [parent=#self] #MWScriptVariables mwscript
|
||||
|
||||
---
|
||||
-- Allows to view and/or modify controls of an actor. All fields are mutable.
|
||||
-- @type ActorControls
|
||||
|
|
Loading…
Reference in a new issue