mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-21 11:39:44 +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 "localscripts.hpp"
|
||||||
|
|
||||||
#include <components/esm3/loadcell.hpp>
|
#include <components/esm3/loadcell.hpp>
|
||||||
|
#include <components/misc/strings/lower.hpp>
|
||||||
|
|
||||||
#include "../mwmechanics/aicombat.hpp"
|
#include "../mwmechanics/aicombat.hpp"
|
||||||
#include "../mwmechanics/aiescort.hpp"
|
#include "../mwmechanics/aiescort.hpp"
|
||||||
|
@ -17,6 +18,14 @@
|
||||||
#include "context.hpp"
|
#include "context.hpp"
|
||||||
#include "worldview.hpp"
|
#include "worldview.hpp"
|
||||||
|
|
||||||
|
namespace MWLua
|
||||||
|
{
|
||||||
|
struct LocalMWScript
|
||||||
|
{
|
||||||
|
LObject mSelf;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
namespace sol
|
namespace sol
|
||||||
{
|
{
|
||||||
template <>
|
template <>
|
||||||
|
@ -27,6 +36,10 @@ namespace sol
|
||||||
struct is_automagical<MWLua::LocalScripts::SelfObject> : std::false_type
|
struct is_automagical<MWLua::LocalScripts::SelfObject> : std::false_type
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
template <>
|
||||||
|
struct is_automagical<MWLua::LocalMWScript> : std::false_type
|
||||||
|
{
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace MWLua
|
namespace MWLua
|
||||||
|
@ -61,6 +74,27 @@ namespace MWLua
|
||||||
selfAPI["controls"] = sol::readonly_property([](SelfObject& self) { return &self.mControls; });
|
selfAPI["controls"] = sol::readonly_property([](SelfObject& self) { return &self.mControls; });
|
||||||
selfAPI["isActive"] = [](SelfObject& self) { return &self.mIsActive; };
|
selfAPI["isActive"] = [](SelfObject& self) { return &self.mIsActive; };
|
||||||
selfAPI["enableAI"] = [](SelfObject& self, bool v) { self.mControls.mDisableAI = !v; };
|
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;
|
using AiPackage = MWMechanics::AiPackage;
|
||||||
sol::usertype<AiPackage> aiPackage = context.mLua->sol().new_usertype<AiPackage>("AiPackage");
|
sol::usertype<AiPackage> aiPackage = context.mLua->sol().new_usertype<AiPackage>("AiPackage");
|
||||||
|
|
|
@ -48,7 +48,7 @@ namespace MWLua
|
||||||
{
|
{
|
||||||
auto* lua = context.mLua;
|
auto* lua = context.mLua;
|
||||||
sol::table api(lua->sol(), sol::create);
|
sol::table api(lua->sol(), sol::create);
|
||||||
api["API_REVISION"] = 31;
|
api["API_REVISION"] = 32;
|
||||||
api["quit"] = [lua]() {
|
api["quit"] = [lua]() {
|
||||||
Log(Debug::Warning) << "Quit requested by a Lua script.\n" << lua->debugTraceback();
|
Log(Debug::Warning) << "Quit requested by a Lua script.\n" << lua->debugTraceback();
|
||||||
MWBase::Environment::get().getStateManager()->requestQuit();
|
MWBase::Environment::get().getStateManager()->requestQuit();
|
||||||
|
|
|
@ -56,6 +56,7 @@ namespace MWScript
|
||||||
mFloats.resize(locals.get('f').size(), 0);
|
mFloats.resize(locals.get('f').size(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mScriptId = script.mId;
|
||||||
mInitialised = true;
|
mInitialised = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -74,84 +75,52 @@ namespace MWScript
|
||||||
return (index != -1);
|
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);
|
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);
|
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':
|
case 'l':
|
||||||
return mLongs.at(index);
|
return mLongs.at(index);
|
||||||
|
|
||||||
case 'f':
|
case 'f':
|
||||||
return static_cast<int>(mFloats.at(index));
|
return mFloats.at(index);
|
||||||
default:
|
default:
|
||||||
return 0;
|
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);
|
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);
|
if (index == -1)
|
||||||
if (index != -1)
|
return false;
|
||||||
|
switch (locals.getType(var))
|
||||||
{
|
{
|
||||||
switch (type)
|
case 's':
|
||||||
{
|
mShorts.at(index) = static_cast<Interpreter::Type_Short>(val);
|
||||||
case 's':
|
break;
|
||||||
return mShorts.at(index);
|
|
||||||
|
|
||||||
case 'l':
|
case 'l':
|
||||||
return mLongs.at(index);
|
mLongs.at(index) = static_cast<Interpreter::Type_Integer>(val);
|
||||||
|
break;
|
||||||
|
|
||||||
case 'f':
|
case 'f':
|
||||||
return mFloats.at(index);
|
mFloats.at(index) = static_cast<Interpreter::Type_Float>(val);
|
||||||
default:
|
break;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return 0;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Locals::write(ESM::Locals& locals, const ESM::RefId& script) const
|
bool Locals::write(ESM::Locals& locals, const ESM::RefId& script) const
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include <components/esm/refid.hpp>
|
||||||
#include <components/interpreter/types.hpp>
|
#include <components/interpreter/types.hpp>
|
||||||
|
|
||||||
namespace ESM
|
namespace ESM
|
||||||
|
@ -19,6 +20,7 @@ namespace MWScript
|
||||||
class Locals
|
class Locals
|
||||||
{
|
{
|
||||||
bool mInitialised;
|
bool mInitialised;
|
||||||
|
ESM::RefId mScriptId;
|
||||||
|
|
||||||
void ensure(const ESM::RefId& scriptName);
|
void ensure(const ESM::RefId& scriptName);
|
||||||
|
|
||||||
|
@ -29,6 +31,8 @@ namespace MWScript
|
||||||
|
|
||||||
Locals();
|
Locals();
|
||||||
|
|
||||||
|
const ESM::RefId& getScriptId() const { return mScriptId; }
|
||||||
|
|
||||||
/// Are there any locals?
|
/// Are there any locals?
|
||||||
///
|
///
|
||||||
/// \note Will return false, if locals have not been configured yet.
|
/// \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 var needs to be in lowercase
|
||||||
///
|
///
|
||||||
/// \note Locals will be automatically configured first, if necessary
|
/// \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
|
/// \note Locals will be automatically configured first, if necessary
|
||||||
//
|
//
|
||||||
|
@ -52,13 +57,15 @@ namespace MWScript
|
||||||
/// @note var needs to be in lowercase
|
/// @note var needs to be in lowercase
|
||||||
///
|
///
|
||||||
/// \note Locals will be automatically configured first, if necessary
|
/// \note Locals will be automatically configured first, if necessary
|
||||||
int getIntVar(const 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)
|
||||||
/// if var does not exist, returns 0
|
{
|
||||||
/// @note var needs to be in lowercase
|
return static_cast<int>(getVarAsDouble(script, var));
|
||||||
///
|
}
|
||||||
/// \note Locals will be automatically configured first, if necessary
|
float getFloatVar(const ESM::RefId& script, std::string_view var)
|
||||||
float getFloatVar(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.
|
/// \note If locals have not been configured yet, no data is written.
|
||||||
///
|
///
|
||||||
|
|
|
@ -25,6 +25,16 @@
|
||||||
-- Movement controls (only for actors)
|
-- Movement controls (only for actors)
|
||||||
-- @field [parent=#self] #ActorControls controls
|
-- @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.
|
-- Allows to view and/or modify controls of an actor. All fields are mutable.
|
||||||
-- @type ActorControls
|
-- @type ActorControls
|
||||||
|
|
Loading…
Reference in a new issue