First part of the ingame LUA Codex

All about coding and Lua scripts
Site Admin
Site Admin
Posts: 136
Joined: Sun Jul 26, 2020 3:49 am
Location: Sosua

Has thanked: 7 times
Been thanked: 5 times

North Industries

First part of the ingame LUA Codex

Post by scheissegalo »


In Dual Universe, you can script interactions between Elements using Lua. The principle is the following: you can plug Elements into a Control Unit "CONTROL" slots, and each of the plugged Element will present itself as a Lua object capable to emit events and execute functions. The name of the slot is simply the name of the Lua object. The Control Unit has a dedicated "Edit Lua" window where you can then associate a piece of Lua code to any event emitted by one of your plugged Element. This code will be executed when the event occurs. Inside the Lua script, you can use the functions offered by the plugged Elements to generate any behavior you like. These functions are simply methods of the Lua object that represents the slot where your Element is plugged into.


To script Elements in Lua, here are the necessary steps:

Identify the Control Unit that you want to host your Lua scripting. You Lua code will run when you activate this Control Unit.
Plug all the Elements that you want to script together inside the Control Unit, using CONTROL links. You can simply click the Control Unit and then the desired plugged Element, this will pick the first free CONTROL plug in your Control Unit. You may want to selectively pick a particular plug, in that case you need to right-click on the Control Unit first and select the desired plug in the menu.
Once all the Elements are plugged, open the "Edit Lua" window from the context menu of the Control Unit. This will open the "Control Unit Editor".
The Control Unit Editor is composed of three columns. The first column lists all the slots available, with the corresponding Element plugged inside them. Each Slot correspond to one of the CONTROL plug of the Control Unit.
Note that there are some predefined slots:

System: the System DPU, to access things like keystrokes, updates, timers. See the doc below.
Unit: this is the Control Unit itself
Library: contains useful functions that are implemented in C++ for performance reasons
The rest of the slots are the slots you used to plug your Elements. You can rename them to help you remember who is what.

Select one slot, for example the System slot.
In the middle column (which is initially empty), you can define event handlers to react to events associated to the slot you have selected.
Add an event, for example "actionStart", and select the "forward" action in the dropdown menu that appears when you try to edit the event argument.
When you click on an event handler, the third column will display the associated Lua code that must be run when this event occurs.
The Lua code can use any of the functions of any slot, using the syntax: slotname.function(...)
The documentation below details all the functions and events available for all the type of Element in the game

Physics scripting, how is your ship flying?

Piloting a ship is a complex topic, a bit like... rocket science actually! We tried to simplify it to a few core concepts. The ship will move because it has some engines attached to it, and engines are capable to exert a force on the body of the ship. To be more precise, there are two things an engine can generate:

Forces: they actually push your ship and make it move in a given direction
Torques: they make your ship rotate on itself
To simplify the control problem, we made a first move by defining engines that can do "torque" only, called the "Adjustors", vs engines that can do "force" only, basically the other engines. Hovercraft engines are the only engines capable to produce force and torque at the same time.

You can control the thrust of each individual engine in your ship by plugging them in the Control Unit and using the setThrust method. However, this can become tedious as the number of engines grow, and it is quite difficult to calculate exactly what thrust to apply to which engine if you want to control the overall global cumulative effect. So, we introduce a cool notion to simplify the process of controlling your engines: grouping.

Grouping engines is done via a tagging mechanism, that you can access by right-clicking an engine and setting its associated tags. By default, all engines are tagged with "all" and some other tags indicating their typical role in the ship control. The default tagging is the following:

Code: Select all

Adjustors: all, torque
Hovercraft: all, vertical, torque
Vertical Boosters: all, vertical
Air brake or Retro Engines: all, brake
All the others: all, horizontal
These are the default, and you can freely modify them and add you custom groups.

Once you have a group of engines, you have a facility within your Control Unit to address them as a whole, just as if they were one single engine, and assign them a given linear and angular acceleration. The system will then calculate the corresponding force and torque that are needed to produce these accelerations, and figure out a thrust assignment for all the engines in the group, so that the end result will be equal or as close as possible to the requested command. This is the "setEngineCommand" method, available in the Control Unit slot (called "unit").

Using this facility, the auto configurator that generates a Lua script for you the first time you enter into a cockpit will typically produce Lua code of this form:

Code: Select all

control.setEngineCommand("vertical,torque", acceleration, angularAcceleration) 
control.setEngineCommand("horizontal", forwardAcceleration, nullvector) 
control.setEngineCommand("brake", brake, nullvector)
The linear acceleration in the horizontal or vertical direction, as well as the angular acceleration, are the result of a computation that is done in the Navigator Lua code, which you may freely modify (it's the ControlCommand.lua file, which is loaded whenever you start a Control Unit), and which defines how controlling of your ship by pressing keys will affect the desired acceleration requested.

All these calculation and the final call to the setEngineCommand method are done in the "flush" event of the System slot. Flush is called several times per frame to calculate the physics simulation. You should never put anything else but physics-related calculation in flush. Anything else this is gameplay related, like connecting buttons or displaying things on screens, should be done in the "update" event, which is called at each frame rendering.

System events and methods
The System DPU, available in the "system" slot is a crucial part of your Lua programming. This virtual element (it is always plugged and always there) will send various events that you can catch to orchestrate your Lua scripting.

There are three fundamental ways to get events are regular intervals from System:

update: this event is triggered at each frame (its frequency will depend on the framerate)
flush: this event is triggered at each step of the physics calculation, usually more than once per frame. Be careful to limit its use to setting engine thrusts, for example with the setEngineCommand method.
tick(n): this event is repeatedly triggered whenever the timer 'n' is reaching its duration. You can create a timer with index "n" and with a given duration using the setTimer(n, duration) method in System. The duration is expressed in seconds, and the event will tick at quasi-regular intervals, independently of the framerate if the duration is larger that the typical frame duration.
The other important event type that System is managing are keystroke events. We call these "actions" to make it independent on the particular key binding that will be associated to it. System then defines three types of events associated to an action:

Code: Select all

actionStart(action): this event is triggered when the action starts (key pressed down)
actionStop(action): this event is triggered when the action stops (key released)
actionLoop(action): this event is triggered at each frame as long as the key is presse
(think of it as a filter on the "update" event)
Actions are referred to by their name, and the Control Unit Editor will pop a list of available actions to choose from whenever you click on the argument of an action event.

Lua code associated to an event filter
Inside the code window that is associated to an event filter on a given slot, you can type in any Lua code you like. There are limits in memory and CPU usage however, as well as in the total size of the code (currently 10Ko compressed).

Note that the Lua interpreter that runs the Lua code is specific to each Control Unit, so there is not automatic sharing of the memory between two running Control Units. You may however exchange variable between different event handlers, simply define them without the "local" keyword and they will become global variables.

The Lua code will typically refer to some of the slots in the Control Unit to call methods associated to the elements that are plugged in these slots. Suppose you have a "screen" slot where you have plugged a Screen Unit, you may write code of the form:

Code: Select all

screen.setCenteredText("Hello World")
To know what methods and what events are available for all the different Elements in the game, simply refer to the documentation below.

How to expose some values outside of Lua editor
You can edit Lua variable values without opening the Lua editor. This can be handy to expose some configuration variables. They only have to be declared with the "export" keyword:

Code: Select all

rotationSpeed = 2 --export 
local rotationSpeed = 2 --export: rotation speed in rad/s
Then, you can right click on your ControlUnit and select the "Edit Lua Parameters" action to modify those exported values.]
TeamSpeak3: LINK | Steam: LINK | Facebook: LINK | Say NO to Corona's witnesses


Post Reply

Who is online

Users browsing this forum: No registered users and 0 guests