How to use this cheat sheet#
Identify the language first. XPath, MD and Lua express similar intentions differently. This is a selection useful for reading these examples and project code, not a statistical ranking or complete language reference. Start with how X4 code works if the terms are unfamiliar. New snippets are learning examples, not claimed in-game tests.
Four basic concepts#
A variable stores a value. A condition chooses whether to do something. A function receives arguments and performs work, sometimes returning a result. An event handler is a function or MD node run for a particular event. Distinguish defining getName, calling getName() and storing its returned value.
XML elements, attributes and selectors#
| Form | Meaning |
|---|---|
<hull max="1800" /> |
An element with an attribute and no child content |
<actions> ... </actions> |
A container's start and end |
<!-- comment --> |
XML comment |
replace, add, remove |
Diff operations to replace, add or remove selected content |
/properties/hull/@max |
XPath to an attribute |
[@name='example'] |
XPath attribute filter |
Inside an XML attribute, escape ampersands as & and less-than as <. XML is parsed before MD expressions, which is why lt/le/gt/ge are convenient comparisons. A diff selector and a do_if expression use different grammars.
MD: one small action at a time#
| Construct | Purpose |
|---|---|
set_value |
Assign or update a value |
do_if, do_elseif, do_else |
Select a branch |
do_for_each |
Process list elements |
append_to_list |
Append an element |
remove_value |
Remove a variable or record |
debug_text |
Write diagnostics |
run_actions |
Run an appropriate action library |
event_ui_triggered |
Receive a UI event in cue conditions |
raise_lua_event |
Send an event to Lua |
These are MD element names, not standard XML functions. The engine defines attributes and valid context. The actions example below creates its own list and ends with Count equal to 2. operation=add exact=1 increments it; Item denotes the current element.
<set_value name="$Items" exact="['Корпус', 'Двигатель']" />
<set_value name="$Count" exact="0" />
<do_for_each name="$Item" in="$Items">
<set_value name="$Count" operation="add" exact="1" />
</do_for_each>
<do_if value="$Count == 2">
<debug_text text="'Обработано два элемента'" />
</do_if>MD expressions#
| Form | Meaning |
|---|---|
$Count, Init.$States |
A variable, or a variable in an explicit cue context |
==, != |
Equal, not equal |
lt, le, gt, ge |
Less, less-or-equal, greater, greater-or-equal |
and, or, not |
Logical operations |
+, -, *, /, % |
Arithmetic; percent is remainder |
'Name: ' + $Label |
String concatenation |
$Value?, $Object.exists |
Variable/property resolution versus object existence |
typeof $D == datatype.list |
Value type test |
$D.{1}, $D.count |
First list element and element count |
table[], [] |
Empty table and empty list |
if $Ready then 'yes' else 'no' |
A conditional value expression |
The shown MD lists start at 1. A resolvable variable may contain false; existence and truth are different. See variable context, especially with instantiated cues.
Lua: reading a regular function#
The standalone example below uses no X4 functions. Its result is 8, assuming every item has a numeric amount field. {} creates a table, used for both sequences and named records. item.amount means item["amount"]. In for _, item, the first variable receives the index; underscore is an ordinary name conventionally marking an unused value.
local function total(items)
if type(items) ~= "table" then
return 0
end
local result = 0
for _, item in ipairs(items) do
result = result + item.amount
end
return result
end
local amount = total({{amount = 3}, {amount = 5}})Lua operators#
| Form | Meaning |
|---|---|
= |
Assignment |
==, ~= |
Equal, not equal |
<, <=, >, >= |
Comparisons |
and, or, not |
Logical operations |
+, -, *, /, % |
Arithmetic |
.. |
String concatenation |
#value |
String byte length or sequence boundary |
object.field |
Table field access |
object:method(x) |
Equivalent to object.method(object, x) |
#table is not a count of arbitrary keys. Holes and string keys do not form a dense sequence. String lengths count bytes, which matters for UTF-8. Only false and nil are false in Lua; 0 and an empty string are true. value or fallback also replaces false. Logical and/or return a selected value, not necessarily a boolean.
Standard Lua functions#
type reports a value type; tostring formats a value; tonumber attempts conversion and may return nil. ipairs walks dense indices from 1 until a missing item; pairs has no order guarantee. table.insert, table.remove and table.concat manipulate sequences. string.format builds formatted text; match/gsub use Lua patterns. math.min and math.max select numeric bounds. pcall catches Lua errors; require loads modules under environment rules.
Not every module is available in game UI. Do not assume debug or file access. Check the pcall flag and error rather than silently hiding a failure. A protected Lua call does not make an invalid native call safe. See the Lua 5.1 and LuaJIT primary references below.
X4 functions versus mod functions#
Resolve object IDs in the correct representation. A random number, ship name, network ID, UI handle and UniverseID are not interchangeable: ID precision.
Five mistakes you can spot while reading#
- Lua uses
~=, while MD uses!=for inequality. - Lua joins strings with
..; MD uses+in the shown forms. - Lua assignment is
=, comparison is==. - Changing window text does not prove changing the world object.
- A handler definition still needs a loaded file, a received event and validated input.
Read Lua ↔ MD and explain each line before installing the example in a test profile.