Scripting Extension

Overview
These are notes and current status of extending openmw scripting through SWIG.

Current Status
Python and Lua scripting is fully functional. You can call from the console, or can attach to objects/global scripts with the command StartExternalScript, "scriptname.py" or StartExternalScript, "scriptname.lua" This way you get access to all the locals and globals as if your script is a normal script. The Python/Lua script has to be in the same directory that other morrowind data/addons are in (one of the data directories).

Install Prerequsites
Ubuntu Linux:

(Should also work in other Linuxes that use the apt package manager.) $ sudo apt-get update $ sudo apt-get install python3-dev swig liblua5.1-0-dev

Github
Command-line example for Unix-like operating systems: $ git clone https://github.com/maqifrnswa/openmw/tree/python-scripting $ cd openmw/ $ mkdir build && cd build $ make -j

Ubuntu PPA
A Utopic personal package archive (PPA) is available for Ubuntu (and related) Linux: $ sudo apt-add-repository ppa:showard314/openmw-scripting $ sudo apt-get install openmw

It will install the highest version of openmw in all the repositories you have enabled, so if you have the openmw PPA, the daily PPA, and this PPA turned on, it may download versions from unwanted PPAs as each gets updated. Therefore, to be safe, only enable one PPA in the Software Center Sources at a time. This version also comes with "testing.py" as seen in the Example below.

Script Testing
Make your Python or Lua script; see Python example below. The test the script in the console. A command-line example for most Unix-like operating systems: $ ./openmw --start="Seyda Neen" --skip-menu

Then in game, press  to get the Console, and run your script with the new command   or , or write a script/addon that calls.

Python Scripts
OpenMW will import your python script as a module and run the  method when you use the Morrowind command.

Example Script
Make sure you have a  method, that is what will be called by OpenMW: from openmw import *
 * 1) Example file: "testing.py"
 * 2) SomethingScript is a script in a .omwaddon file that you create that has a short variable named "hello" you can use for testing.
 * 3) It's just a demonstration of setting a local variable, you can comment it out if it causes problems.

def run: print("health: " + str((gethealth("player")))) print("hello i'm a criminal") setpccrimelevel(100000000) print("flying: " + str(getflying("player"))) setflying("player",1) print("flying: " + str(getflying("player"))) print("random100: " + str(omwget("random100"))) omwset("random100",42) print("random100: " + str(omwget("random100"))) print("SomethingScript.hello: " + str(omwget("SomethingScript.hello"))) omwset("SomethingScript.hello",42.0) print("SomethingScript.hello: " + str(omwget("SomethingScript.hello"))) omwcall("MessageBox, \"This is a simple message\"")

How to Write Python Scripts
All commands are lowercase and take the same arguments as before, even optional ones. Commands that can take a reference (commands with ) now have a first argument which is the reference. That first argument is required. If it is an implicit reference, use.

Example 1: player->AddItem, "Gold_001", 200 is now: additem("player","Gold_001",200)

Example 2: AIWander, 0, 0, 0 is now: aiwander("self",0,0,0)

Example 3: "urzul gra-agum"->AIWander, 128, 0, 0, 60, 30, 10, 0, 0, 0, 0, 0, 0 is now: aiwander("urzul gra-agum", 128, 0, 0, 60, 30, 10, 0, 0, 0, 0, 0, 0)

Getting and setting variables
omwset("localvariablename", value) omwset("globalvariablename", value) omwset("objectID.variablename", value) owmset("globalID.variablename", value)

omwget("localvariablename") [etc.] Use  and   instead of   and   to avoid name collisions with built-in functions in Python.

Non-extension Functions and Instructions
All extensions are directly available for use, but game interpreter commands (like ) can be accessed with  : omwcall("MessageBox, \"This is a simple message\"")

The argument to  will be parsed as if it were a normal Morrowind script.

Lua Scripts
OpenMW will import your Lua script as a module and run the  method when you use the Morrowind command

Example Script
Make sure you have a  method; that is what will be called by OpenMW:
 * 1) Example file: "testing.lua"
 * 2) SomethingScript is a script in a .omwaddon file that you create that has a short variable named "hello" you can use for testing.
 * 3) It's just a demonstration of setting a local variable; you can comment it out if it causes problems.

local testing = {}

function testing.run print("health: "..omw.gethealth("player")) print("hello i'm a criminal") omw.setpccrimelevel(100000000) print("flying: "..omw.getflying("player")) omw.setflying("player",1) print("flying: "..omw.getflying("player")) print("random100: "..omw.omwget("random100")) omw.omwset("random100",42) print("random100: "..omw.omwget("random100")) print("SomethingScript.hello: "..omw.omwget("SomethingScript.hello")) omw.omwset("SomethingScript.hello",42.0) print("SomethingScript.hello: "..omw.omwget("SomethingScript.hello")) omw.omwcall("MessageBox, \"This is a simple message\"") end

return testing

How to Write Lua Scripts
All commands are in the  namespace, are lowercase, and take the same arguments as before, even optional ones. Commands that can take a reference (commands with ) now have a first argument which is the reference. That first argument is required. If it is an implicit reference, use.

Example 1: player->AddItem, "Gold_001", 200 is now: omw.additem("player","Gold_001",200)

Example 2: AIWander, 0, 0, 0 is now: omw.aiwander("self",0,0,0)

Example 3: "urzul gra-agum"->AIWander, 128, 0, 0, 60, 30, 10, 0, 0, 0, 0, 0, 0 is now: omw.aiwander("urzul gra-agum", 128, 0, 0, 60, 30, 10, 0, 0, 0, 0, 0, 0)

Getting and Setting Variables
omw.omwset("localvariablename", value) omw.omwset("globalvariablename", value) omw.omwset("objectID.variablename", value) omw.owmset("globalID.variablename", value)

omw.omwget("localvariablename") [etc.] Use  and   instead of   and   (for syntax consistency with OpenMW Python scripts;   and   are built-in functions in Python).

Non-extension Functions and Instructions
All extensions are directly available for use, but interpreter commands (like ) can be accessed with  : omw.omwcall("MessageBox, \"This is a simple message\"") The argument to  will be parsed as if it was a normal Morrowind script.

Debugging output
There's still a bunch of normal Python or Lua debugging output that will go to the terminal; bear with it for the time being.

Security
Security will be an issue when it comes to running untrusted scripts, but it something people already deal with in the modding community (e.g, Blender Python Scripting Security. Concerns can be addressed to an extent by making users opt in to using Python or Lua, and could be extended to only allow running scripts signed by a trusted certificate (key).

To do
sandboxing Lua, options to enable/disable compile and runtime availabillity of scripts, code clean up, script signing/trust