Skip to content

Lua in Dialogues⚓︎

It is possible to use lua inside the mwscript results pane in the dialogue menu of the Construction Set.

Additional functions are available to extend the usefulness of this feature, including tes3ui.choice and tes3.applyTextDefines.

Note

The execution order of the Results pane is not mixed. All lua commands will be executed before the mwscript is parsed and executed.

Tip

The keyboard shortcut Control+A does not work in the Construction Set. Right-clicking still allows selecting all text for quick replacement.

Environment⚓︎

All commands from the same results text share the same lua environment. This allows persistent values between lines. To do this however, the local keyword cannot be used. This does not pollute the normal global namespace.

Example: Multi Line Values

;lua playerName = tes3.player.object.name
;lua tes3.messageBox("Hello %s", playerName)

Additionally, some information has been provided in the environment. These values are reference, dialogue, and info for the specifics of what result is being executed, and on who.

Example: Print Results Context

;lua tes3.messageBox("Reference: %s; Dialogue/INFO: %s/%s;", reference, dialogue, info.id)

The environment can also be extended through the dialogueEnvironmentCreated event. This allows libraries to extend what functionality is available to dialogue scripters more easily.

Example: Extending the Dialogue Environment

In your library's main.lua file, create the event hook:

local function onDialogueEnvironmentCreated(e)
    -- Cache the environment variables outside the function for easier access.
    -- Dialogue scripters shouldn't have to constantly pass these to the functions anyway.
    local env = e.environment
    local reference = env.reference
    local dialogue = env.dialogue
    local info = env.info

    -- Define the "global" function.
    function env.DisplayDialogueContext()
        tes3.messageBox("Reference: %s; Dialogue/INFO: %s/%s;", reference, dialogue, info.id)
    end
end
event.register(tes3.event.dialogueEnvironmentCreated, onDialogueEnvironmentCreated)

Then, any dialogue scripts can make use of the new function:

;lua DisplayDialogueContext()

Usage⚓︎

Basics⚓︎

To write lines with lua, prefix them with a mwscript comment starting with ;lua. This allows the lua commands to be backwards-compatible for users that do not have MWSE, including users of OpenMW.

Example: Goodbye with a Message

; The next line will execute lua.
;lua tes3.messageBox("This will run as lua!")

; The next line will just be normal mwscript.
goodbye

Note

All lua logic is contained to a single line. This a limitation of the approach to keep things as compatible as possible.

Executing a Lua File⚓︎

It may be useful to move the majority of your script logic to an actual .lua file, and use dofile.

Example: Execute Lua File from Dialogue

;lua dofile("myMod.onSomeDialogueResult")

The environment variables are not inherited with dofile. To pass the data, it is best to make a call from a module.

Example: Passing Results Context to a Lua Module

Define your module with a function to be called:

local myDialogueModule = {}

--- A function designed to be called from a dialogue result.
--- @param reference tes3reference The reference the dialogue is running on.
--- @param dialogue tes3dialogue The parent dialogue for our info.
--- @param info tes3dialogueInfo The specific INFO object that is being executed.
function myDialogueModule.myFunction(reference, dialogue, info)
    tes3.messageBox("Reference: %s; Dialogue/INFO: %s/%s;", reference, dialogue, info.id)
end

return myDialogueModule

Call your module from the dialogue result:

;lua myDialogueModule = require("myMod.myDialogueModule")
;lua myDialogueModule.myFunction(reference, dialogue, info)

Preventing Default Scripts⚓︎

For better compatibility with OpenMW, it can be useful to prevent any vanilla result behavior from happening. This can be done by setting the environment variable noMorrowindScript.

Example: Preventing Morrowind Script

;lua noMorrowindScript = true

This will not prevent other associated events, but will prevent the mwscript from the result box from being executed. This can be done conditionally as well.

Example: Sometimes Preventing Morrowind Script

;lua myDialogueModule = require("myMod.myDialogueModule")
;lua myDialogueModule.myFunction(reference, dialogue, info)
;lua if (myDialogueModule.wasSuccessful()) then noMorrowindScript = true end