You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
openmw/apps/openmw/mwlua
Zackhasacat c63c1e69cf Lua: Add missing light flags, allow creating light record via world.createRecord 4 days ago
..
types Lua: Add missing light flags, allow creating light record via world.createRecord 4 days ago
README.md Add a bit of high-level developer documentation about the Lua system 1 year ago
animationbindings.cpp Cleanup includes 2 months ago
animationbindings.hpp Cleanup includes 2 months ago
birthsignbindings.cpp Cleanup includes 2 months ago
birthsignbindings.hpp Remove Core from functions that aren't in openmw.core 3 months ago
camerabindings.cpp Cleanup includes 2 months ago
camerabindings.hpp Add headers for all `.cpp` files in mwlua; move packages initilaization from LuaManager to luabindings.cpp 1 year ago
cellbindings.cpp Place ESM4 static collections to the scene 1 week ago
cellbindings.hpp Add headers for all `.cpp` files in mwlua; move packages initilaization from LuaManager to luabindings.cpp 1 year ago
classbindings.cpp Cleanup includes 2 months ago
classbindings.hpp Remove Core from functions that aren't in openmw.core 3 months ago
context.hpp Don't clear menu UI on game load 4 months ago
corebindings.cpp ESM::Dialogue Lua bindings 2 1 month ago
corebindings.hpp Draft: add new type of Lua scripts - menu scripts 7 months ago
debugbindings.cpp Cleanup includes 2 months ago
debugbindings.hpp Support rendering for navmesh update frequency as a heatmap 2 years ago
dialoguebindings.cpp ESM::Dialogue Lua bindings: filterActorGender returns string 2 weeks ago
dialoguebindings.hpp ESM::Dialogue Lua bindings 1 1 month ago
engineevents.cpp rebase errors 4 months ago
engineevents.hpp rebase errors 4 months ago
factionbindings.cpp Take in account faction reaction changes 4 weeks ago
factionbindings.hpp Lua: Standardize record stores 2 months ago
globalscripts.hpp Draft: add new type of Lua scripts - menu scripts 7 months ago
idcollectionbindings.hpp Unify the creation of RefId tables 3 months ago
inputbindings.cpp Remove hidden functions 1 month ago
inputbindings.hpp Add headers for all `.cpp` files in mwlua; move packages initilaization from LuaManager to luabindings.cpp 1 year ago
inputprocessor.hpp Mouse input engine handlers 3 months ago
itemdata.cpp Cleanup includes 2 months ago
itemdata.hpp take2 8 months ago
localscripts.cpp Expose Wander option values to the Lua API (#7916) 2 weeks ago
localscripts.hpp Add engine handler for skill levelup, to dehardcode the book/trainer case. 4 months ago
luabindings.cpp Load YAML files via Lua (feature 7590) 2 months ago
luabindings.hpp Draft: add new type of Lua scripts - menu scripts 7 months ago
luaevents.cpp Add types.Player.sendMenuEvent 7 months ago
luaevents.hpp Add types.Player.sendMenuEvent 7 months ago
luamanagerimp.cpp Add a storage mode to drop section on game exit 3 months ago
luamanagerimp.hpp Merge branch 'dehardcode-skillprogression' into 'master' 3 months ago
magicbindings.cpp Merge branch 'spellcast-refactor' into 'master' 2 months ago
magicbindings.hpp Lua bindings for magic. Based on the work made by @bharbich in !2765. 1 year ago
markupbindings.cpp Do not use an inner namespace 2 months ago
markupbindings.hpp Load YAML files via Lua (feature 7590) 2 months ago
menuscripts.cpp creationTime field in save info 4 months ago
menuscripts.hpp Avoid making engine handler methods public 4 months ago
mwscriptbindings.cpp Add back new_index 2 months ago
mwscriptbindings.hpp Change MWScript Lua bindings (#7142) 11 months ago
nearbybindings.cpp Move local variables 3 months ago
nearbybindings.hpp Add headers for all `.cpp` files in mwlua; move packages initilaization from LuaManager to luabindings.cpp 1 year ago
object.hpp Group owner bindings into a table 3 months ago
objectbindings.cpp Group owner bindings into a table 3 months ago
objectbindings.hpp Add headers for all `.cpp` files in mwlua; move packages initilaization from LuaManager to luabindings.cpp 1 year ago
objectlists.cpp Cleanup includes 2 months ago
objectlists.hpp Rename MWLua::WorldView -> MWLua::ObjectLists 9 months ago
objectvariant.hpp Add missing type validation in mwlua/objectvariant.hpp 1 year ago
playerscripts.hpp Avoid making engine handler methods public 4 months ago
postprocessingbindings.cpp Address Coverity Scan complaints left 3 months ago
postprocessingbindings.hpp Add headers for all `.cpp` files in mwlua; move packages initilaization from LuaManager to luabindings.cpp 1 year ago
racebindings.cpp Cleanup includes 2 months ago
racebindings.hpp Expose races to Lua 3 months ago
recordstore.hpp Lua: Standardize record stores 2 months ago
soundbindings.cpp Use normalized path for SoundManager::streamMusic 4 weeks ago
soundbindings.hpp Implement Lua bindings for sound system 9 months ago
stats.cpp Expose AI stats to Lua 2 months ago
stats.hpp Revert redundant changes 6 months ago
uibindings.cpp Fix child UI Elements created in the same frame as parent 2 months ago
uibindings.hpp Add headers for all `.cpp` files in mwlua; move packages initilaization from LuaManager to luabindings.cpp 1 year ago
userdataserializer.cpp Replace `const ESM::RefNum&` -> `ESM::RefNum` 8 months ago
userdataserializer.hpp Merge MWLua::ObjectRegistry and MWWorld::WorldModel 1 year ago
vfsbindings.cpp Cleanup includes 2 months ago
vfsbindings.hpp Implement Lua API for VFS 9 months ago
worker.cpp Use correct frame and stats for lua worker 3 weeks ago
worker.hpp Use correct frame and stats for lua worker 3 weeks ago
worldbindings.cpp Lua: Add missing light flags, allow creating light record via world.createRecord 4 days ago
worldbindings.hpp Draft: add new type of Lua scripts - menu scripts 7 months ago

README.md

MWLua

This folder contains the C++ implementation of the Lua scripting system.

For user-facing documentation, see OpenMW Lua scripting. The documentation is generated from /docs/source/reference/lua-scripting. You can find instructions for generating the documentation at the root of the docs folder.

The Lua API reference is generated from the specifications in /files/lua_api. They are written in the Lua Development Tool Documentation Language, and also enable autocompletion for (LDT) users. Please update them to reflect any changes you make.

MWLua::LuaManager

The Lua manager is the central interface through which information flows from the engine to the scripts and back.

Lua is executed in a separate thread by default. This thread executes update() in parallel with rendering logic (specifically with OSG Cull traversal). Because of this, Lua must not synchronously mutate anything that can directly or indirectly affect the scene graph. Instead such changes are queued to mActionQueue. They are then processed by synchronizedUpdate(), which is executed by the main thread. The Lua thread is paused while other updates of the game state take place, which means that state that doesn't affect the scene graph can be mutated immediately. There is no easy way to characterize which things affect the graph, you'll need to inspect the code.

Bindings

The bulk of the code in this folder consists of bindings that expose C++ data to Lua.

As explained in the scripting overview, there are Global and Local scripts, and they have different capabilities. A Local script has read-only access to objects other the one it is attached to. The bindings use the types MWLua::GObject, MWLua::LObject, MWLua::SelfObject to enforce this behaviour.

  • MWLua::GObject is used in global scripts
  • MWLua::LObject is used in local scripts (readonly),
  • MWLua::SelfObject is the object the local script is attached to.
  • MWLua::Object is the common base of all 3.

Functions that don't change objects are usually available in both local and global scripts so they accept MWLua::Object. Some (for example setEquipment in actor.cpp) should work only on self and because of this have argument of type SelfObject. There are also cases where a function is available in both local and global scripts, but has different effects in different cases. For example see the binding actor["inventory"] in 'MWLua::addActorBindings` in actor.cpp:

actor["inventory"] = sol::overload([](const LObject& o) { return Inventory<LObject>{ o }; },
    [](const GObject& o) { return Inventory<GObject>{ o }; });

The difference is that Inventory<LObject> is readonly and Inventory<GObject> is mutable. The read-only bindings are defined for both, but some functions are exclusive for Inventory<GObject>.

Mutations that affect the scene graph

Because of the threading issues mentioned under MWLua::LuaManager, bindings that mutate things that affect the scene graph must be implemented by queuing an action with LuaManager::addAction.

Here is an example that illustrates action queuing, along with the differences between GObject and LObject:

// We can always read the value because OSG Cull doesn't modify `RefData`.
auto isEnabled = [](const Object& o) { return o.ptr().getRefData().isEnabled(); };

// Changing the value must be queued because `World::enable`/`World::disable` aside of
// changing `RefData` also adds/removes the object to the scene graph.
auto setEnabled = [context](const Object& object, bool enable) {
    // It is important that the lambda state stores `object` and not the result of
    // `object.ptr()` because when delayed will be executed the old Ptr can potentially
    // be already invalidated.
    context.mLuaManager->addAction([object, enable] {
        if (enable)
            MWBase::Environment::get().getWorld()->enable(object.ptr());
        else
            MWBase::Environment::get().getWorld()->disable(object.ptr());
    });
};

// Local scripts can only view the value (because in multiplayer local scripts
// will be client-side and we want to avoid synchronization issues).
LObjectMetatable["enabled"] = sol::readonly_property(isEnabled);

// Global scripts can both read and modify the value.
GObjectMetatable["enabled"] = sol::property(isEnabled, setEnabled);

Please note that queueing means changes scripts make won't be visible to other scripts before the next frame. If you want to avoid that, you can implement a cache in the bindings. The first write will create the cache and queue the value to be synchronized from the cache to the engine in the next synchronization. Later writes will update the cache. Reads will read the cache if it exists. See LocalScripts::SelfObject::mStatsCache for an example.