Stormworks: Build and Rescue

Stormworks: Build and Rescue

60 ratings
Lua - Ultimate Beginner's Guide
By Griz
Using Lua in Stormworks

Greetings!
Welcome to the Lua "Ultimate Beginner's Guide". Whether you're a seasoned programmer or a newcomer to coding, Lua opens up a new dimension of possibilities in the realm of Stormworks creations.

Lua is a lightweight and flexible scripting language that empowers you to control and automate various aspects of your vehicles and machines. It's like the hidden toolbox that lets you fine-tune and optimize your builds, adding a touch of intelligence and efficiency to your designs.

In this guide, i'll take you through the fundamentals of Lua scripting, from understanding variables and functions to mastering loops and conditional statements. The guide has been handcrafted for over a year to ensure both high quality and accuracy.

Note: Images full-scale if you click them.

Originally posted by Griz:
Last update: 24/05/2024
3
   
Award
Favorite
Favorited
Unfavorite
Welcome!
Guide's content
Although basic understanding of Stormworks, logic and game components is recommended (and needed), no previous Lua experience is needed. This is a crash-course guide intended for absolute beginners!

Learn important concepts
  • Fundamental terms
  • Syntax
  • Input/Output
  • Data types (NIL, Bool, Number, String, Table)
  • Tables
  • Variables
  • Operators
  • Statements (if, then, else, elseif, while, do, end)
  • Functions (onTick, custom functions, onDraw)

Become fluent in Lua
The most important thing this guide will teach you, and the purpose of it in the first place, is to learn the fundamentals of the Lua language, allowing you to form a fluency like in any real languages such as Spanish or English. This fluency will let you convert ideas and creativity into working Lua code that serves a purpose.
Lua


Think of Lua as the universal language of communication between you and your creations. With Lua scripting, you can interact with your vessels and systems at a granular level, enabling you to craft intricate automation and create immersive experiences.

The potential of Lua in Stormworks is immense. Whether you want to build autonomous drones, intelligent navigation systems, or complex mission scenarios, Lua will be your indispensable companion on this journey.

Want to create your own Stormworks matrix world? With Lua you can! (I think). "Do you think that's air you're breathing now?"
Microcontrollers
To learn Lua, you will need to create a Lua script that you can write code in. In Stormworks, you do this within a microcontroller.

In the images below, you will be given information on the options you have. Keep in mind that you don't need any logic inputs or outputs to the microcontroller to create a Lua script within it. If we need logic anywhere in the guide, you will be given instructions on what to input and/or output as you get there!

View full image[ibb.co]

View full image[ibb.co]
Fundamental terms
Here are some commonly used words when Lua scripting (and some within coding in general):




  • Variable: A named container for storing data. It can hold numbers, strings, tables, or other values.

  • Function: A block of code that performs a specific task. Functions can take input (arguments) and may return a value.

  • Table: A versatile data structure that holds collections of data using key-value pairs. Tables act like arrays, dictionaries, or objects.

  • Object: In Lua, an object is often represented as a table with properties and methods. It's an instance of a class.

  • Method: A function that is associated with an object or a class. Methods can modify the object's data or perform actions related to the object.

  • Class: A blueprint or template for creating objects. It defines the structure and behavior of objects that belong to it.

  • Variable Scope: The region of the code where a variable is accessible. Variables can have local scope (accessible only within a specific block) or global scope (accessible from anywhere in the script).

  • Conditional Statements: Statements that allow the script to make decisions based on conditions. Common conditionals are if, else, and elseif.

  • Loop: A structure that repeats a block of code multiple times. Common loops are for, while, and repeat.

  • Operator: Symbols that perform operations on variables or values. Examples include + (addition), - (subtraction), * (multiplication), / (division), == (equal to), ~= (not equal to), > (greater than), < (less than), and more.

  • Comment: Lines of text in the code that are not executed but serve as notes for the programmer. Comments start with --.

  • Concatenation: Combining strings together using the .. operator.

  • Indexing: Accessing elements in a table using their keys (for associative arrays) or numerical indices (for arrays).

These are some of the fundamental terms you'll encounter in Lua scripting. Remember, Lua is a versatile and beginner-friendly language, so with practice and exploration, you'll become more comfortable using these concepts to create exciting scripts and programs.
Syntax
Syntax is the way we write the code in order for the computer to understand us. Languages like Java have a very complex and difficult syntax and can often be hard on the eye, whilst Lua on the other hand, is very simple and easy on the eye.

Comments
Comments are used to annotate code and are ignored by the interpreter. In Lua, you can add comments with a double hyphen (--).
-- This is a comment

You can also add multi-line comments in Lua. It starts with two hyphens (--) followed by a set of double square brackets ([[). The comment text is then added on the subsequent lines, and the comment is closed with another set of double square brackets (]]) followed by two hyphens (--).
--[[ This is a multi-line comment. It can span multiple lines and is ignored by the interpreter. You can use it to add documentation or notes to your code. ]]--

Variables
Variables are used to store values. In Lua, you don't need to specify a variable's type - the interpreter will figure it out based on the value you assign to it.
Example:
-- This is how you define a variable myVariable = 42

Functions
Functions are blocks of code that perform a specific task. In Lua, you define a function using the function keyword, and you call a function using its name, followed by parentheses.
Example:
-- This is how you define a function function sayHello() print("Hello, world!") end -- This is how you call a function sayHello()

Conditionals
Conditionals are used to make decisions based on the value of a variable or expression. In Lua, you use the keywords if, elseif, and else to create conditionals.
Example:
-- This is how you use a conditional if myVariable == 42 then print("The answer to the ultimate question of life, the universe, and everything.") elseif myVariable == 24 then print("Reverse the numbers and try again.") else print("I'm sorry, I don't know what you're talking about.") end

Loops
Loops are used to repeat a block of code multiple times. In Lua, you can use a while loop or a for loop.
Example of while loop:
-- This is how you use a while loop i = 1 while i <= 10 do print(i) i = i + 1 end
Example of for loop:
-- This is how you use a for loop for i = 1, 10 do print(i) end

Note!
You don't need to understand what loops, variables etc. are yet, and i don't expect you to, but the syntax is still nice to know as it will give you an understanding of how to structure your code. Feel free to come back to this section when you start writing actual code, as it will come in handy!
Input/Output
The Logic Input and Output system is a way for Lua scripts to interact with the game's logical systems. The Logic Input system allows you to read the state of logical inputs in the game (like switches or buttons), while the Logic Output system allows you to set the state of logical outputs (like lights or motors).
How to use it:
-- Read the state of a Logic Input local inputState = input.getBool(1) -- Set the state of a Logic Output output.setBool(1, true)

In this example, we're using two built-in functions to interact with the game's logical systems.

input.getBool(1) reads the state of the logical input connected to input number 1 and returns a boolean value (true or false) indicating whether the input is active or not.

output.setBool(1, true) sets the state of the logical output connected to output number 1 to true. You can replace true with false to turn the output off instead.

You can use these functions in combination with other Lua code to create complex logic circuits and systems within your StormWorks creations. For example, you might use the input.getBool function to check the state of a switch, and then use an if statement to run different code depending on whether the switch is on or off. Or you might use the output.setBool function to turn on or off a set of lights depending on some other condition in your script.
Data Types
Lua has several data types used to represent data to use in your script. By understanding the basics of the 5 data types explained below, you will be able to use them when learning about more advanced Lua functionality.

Important!
These examples are simply to show how these data types look and are written. We will dig more into how to USE data types as variables in functions later.

Before we start, at the top of your Lua script, type "function onTick()". With this function, you can freely test Lua functionality. If you put code outside this function, you might run into errors. Remember to put an "end" statement at the bottom of all your code that you want within your onTick function.

Example to get started:
function onTick() -- Code inside here. -- And here! -- You get the point... end




NIL
NIL is nothing. The value of the NIL data type will always be nil.

Bool
Bools represent one of two values: True or False. If something is True, something in Stormworks is on, if something is False, something in Stormworks is off.

Number
Numbers are floats, meaning they always have decimals. You can define a number as 10, but it will still be interpreted by Lua as having decimals, sort of like 10,000...

String
Strings of characters forming as text.

  • Let's define a string with the text hello:
String "hello"
  • Or with the number 10:
String 10
Strings can be True/False (booleans), numbers, text, etc. It's important to remember that text needs to have quotation marks before and after it, while numbers, booleans, etc. do not.

Table
Tables are the only data structure available in Lua that helps us create different types like arrays and dictionaries. Lua uses associative arrays and which can be indexed with not only numbers but also with strings except nil. Tables have no fixed size and can grow based on our need.

This can be useful in creating loops, etc. Note: Remember to use curly brackets, not square brackets!

Example of a table:
Table {1,2,3,4,5}




Using data types
Here is a simple example to show how to use data types. We will use a function called print, more on functions later in the guide! For now, focus on the data types.

Let's print some values. We use the type() function within the print() function. The output will be what data type the value within the type() function is. For example, type(true) when within the print function will print boolean. Here is how it looks:
print(type(nil)) -> nil print(type(true)) -> boolean print(type(10*2)) -> number print(type("Hello, World!")) -> string print(type({1,5,8})) -> table

Let's use variables to print. The data type here will be number, since dailyApples is defined with the value of 13 without quotation marks. If it was "13", it would be a string. Here is how it looks:
dailyApples = 13 weeklyApples = dailyApples*7 print(weeklyApples) -> 91
As you can see, we define the variable "dailyApples" as 13, then we use it within the variable "weeklyApples" where we multiply dailyApples by 7. dailyApples is already defined as 13, so it's the same as writing 13*7 since the data type of dailyApples is number.

After defining the weeklyApples variable, we then print it with the print() function. Since weeklyApples is defined as dailyApples, which is 13, times 7, the output to console will be 91.
Tables
You now have a grasp over the basics of the different data types, including tables, but due to the complexity of them a further explanation is required.

Tables are a fundamental data structure that allow you to organize and store collections of data. Think of them as containers or boxes that can hold various items, and each item has a unique label (key) for easy identification.




Examples

Example 1: Creating and Accessing Table Elements
Imagine you have a toolbox with different tools inside. Each tool has its name written on it. In Lua, you can represent this toolbox with a table:
-- Creating a table representing the toolbox local toolbox = { hammer = "red hammer", screwdriver = "blue screwdriver", wrench = "yellow wrench" } -- Accessing elements in the table print(toolbox["hammer"]) -- Output: red hammer print(toolbox["screwdriver"]) -- Output: blue screwdriver
In this example, 'toolbox' is a table with three items (tools). We use the tool names as keys to access the corresponding tools' descriptions.

Example 2: Adding and Modifying Table Elements
Let's say you want to add more tools to your toolbox or change the description of a tool. You can do it like this:
-- Adding a new tool and modifying an existing tool toolbox["saw"] = "sharp saw" toolbox["hammer"] = "steel hammer" -- Modifying the description of the hammer -- Accessing the updated elements print(toolbox["saw"]) -- Output: sharp saw print(toolbox["hammer"]) -- Output: steel hammer
In this example, we added a "saw" to the toolbox and updated the description of the "hammer."

Example 3: Iterating Through a Table
Let's say you want to go through each tool in the toolbox and do something with them. You can use a loop to iterate through the table:
-- Iterating through the table for key, value in pairs(toolbox) do print("Tool:", key, "Description:", value) end
The 'pairs' function allows us to loop through all the elements in the table. The 'key' variable represents the tool name (e.g., "hammer"), and the 'value' variable represents the description (e.g., "steel hammer").

Example 4: Tables with Mixed Data Types
Tables can hold various data types, not just strings. Let's create a table with numbers and strings:
local mixedTable = { name = "Alice", age = 30, scores = {90, 85, 95} } print(mixedTable["name"]) -- Output: Alice print(mixedTable["age"]) -- Output: 30 print(mixedTable["scores"][2]) -- Output: 85 (accessing the second score)
In this example, 'mixedTable' contains a string, a number, and another table holding scores.




Using classes with tables
In Lua, classes can be implemented using tables to represent objects and functions as methods. Here's a short example of how you can create a simple class using tables:
-- Define the class table local MyClass = {} -- Constructor function (similar to __init__ in other languages) function MyClass.new(name, age) local self = {} -- Create a new object (instance) self.name = name self.age = age return self end -- Method to print the object's details function MyClass:printDetails() print("Name:", self.name) print("Age:", self.age) end -- Create an object instance using the constructor local obj1 = MyClass.new("Alice", 30) local obj2 = MyClass.new("Bob", 25) -- Call the method on each object obj1:printDetails() obj2:printDetails()
In this example, we create a simple class 'MyClass' using a table. The class has a constructor function 'new', which creates a new instance of the class and sets its properties. We also have a method 'printDetails' that prints the object's name and age.

When we call the constructor 'MyClass.new()', it returns a new instance of the class (represented by the 'self' table). We can then call the method 'printDetails()' on each object to display their details.

Output:
Name: Alice Age: 30 Name: Bob Age: 25
Variables
In the example at the bottom of the data types section, you could see that we used variables to define a value to print to console. Let's actually understand what a variable is, and how we can use it!

What are variables?
Variables are a way to store and manipulate data in your scripts. You can use variables to hold numbers, strings, booleans, and other types of data, and then use them in your code to perform calculations, make decisions, or output information.
Example:
-- Define some variables local x = 10 local y = 5 -- Do some calculations with the variables local z = x + y local w = x * y -- Output the results print("The sum of x and y is " .. z) print("The product of x and y is " .. w)
In this example, we're using variables to hold the values of x and y, which are both set to integers (10 and 5, respectively). We then perform some calculations using these variables and store the results in two new variables, z and w. Finally, we output the results of these calculations using the print function, which writes text to the game's console.

Variables can also be used to store more complex data types, like tables (which are similar to arrays or dictionaries in other programming languages). Here's an example of how to create and use a table variable:
-- Define a table variable local myTable = { "apple", "banana", "orange" } -- Access elements of the table print("The first element of the table is " .. myTable[1]) print("The second element of the table is " .. myTable[2]) print("The third element of the table is " .. myTable[3])
In this example, we're creating a table variable called myTable and initializing it with three string values ("apple", "banana", and "orange"). We can then access elements of the table using the [ ] operator, which takes an index (starting from 1 for the first element) and returns the corresponding value.

By using variables effectively, you can create more complex and flexible scripts for your creations.
Operators
Now that you know what variables are, we will use operators to perform modifications to the variables.

What are operators?
Operators are symbols or keywords that you can use to perform operations on variables and other data types. There are several types of operators in Lua, including arithmetic operators, comparison operators, and logical operators.
Example:
-- Define some variables local x = 10 local y = 5 -- Perform arithmetic operations with the variables local sum = x + y local difference = x - y local product = x * y local quotient = x / y -- Use comparison operators to compare the variables local isEqual = x == y local isNotEqual = x ~= y local isGreaterThan = x > y local isLessThan = x < y -- Use logical operators to combine boolean values local andResult = true and false local orResult = true or false local notResult = not true
In this example, we're using several different types of operators to perform different operations.

Arithmetic operators (+, -, *, and /) are used to perform basic arithmetic operations on numeric variables. We're using these operators to add, subtract, multiply, and divide the x and y variables and store the results in new variables.

Comparison operators (==, ~=, >, and <) are used to compare the values of two variables and return a boolean value indicating whether the comparison is true or false. In this example, we're using comparison operators to compare the values of x and y and store the results in new boolean variables.

Logical operators (and, or, and not) are used to combine boolean values and return a new boolean value. In this example, we're using logical operators to combine boolean values and store the results in new boolean variables.
Statements
Great! You now know the basics of operators. Operators can be used in statements, and here's, in simple terms, how statements work!

What are statements?
Statements are commands or instructions that perform a specific action. Statements in Lua scripting are often used to control the flow of execution of a program based on certain conditions.

Examples:

if...then...else
The if...then...else statement allows you to execute one block of code if a condition is true, and another block of code if the condition is false. Here's an example:
if speed > 50 then print("Speed is greater than 50") else print("Speed is less than or equal to 50") end

elseif
The elseif statement allows you to test multiple conditions and execute different blocks of code based on the result. Here's an example:
if speed > 50 then print("Speed is greater than 50") elseif speed > 30 then print("Speed is greater than 30") else print("Speed is less than or equal to 30") end
In this example, if the speed is greater than 50, the first block of code is executed. If the speed is greater than 30 but less than or equal to 50, the second block of code is executed. Otherwise, the third block of code is executed.

while...do...end
The while...do...end statement allows you to repeat a block of code while a certain condition is true. Here's an example:
while speed < 100 do speed = speed + 10 print("Speed increased to " .. speed) end
In this example, the code inside the while loop will be executed repeatedly as long as the speed is less than 100. The code inside the loop increases the speed by 10 and prints a message to the console.

These are just a few examples of the conditional statements available in Lua scripting in Stormworks. These statements are used to control the flow of execution of a program based on certain conditions and make the program more dynamic and responsive to changes in the environment or user input.
Functions
onTick
The onTick function is a built-in function in StormWorks that gets called every game tick (which is a tiny unit of time in the game). You can use this function to run code that you want to execute repeatedly, like checking the status of a sensor or updating the position of an object.
Example:
function onTick() local sensorValue = input.getNumber(1) if sensorValue > 50 then output.setNumber(1, 100) else output.setNumber(1, 0) end end
In this example, the onTick function is used to check the value of a sensor connected to input number 1, and then set the output number 1 to either 100 or 0 depending on the sensor value.

onDraw
The onDraw function is another built-in function in StormWorks that gets called every time the game needs to draw something to the screen (like a text label or an image). You can use this function to draw custom graphics or text on the screen based on the current state of your game.
Example:
function onDraw() drawText("Current Score: " .. score, 100, 100) end
In this example, the onDraw function is used to draw text on the screen displaying the current score of the game. The drawText function is a built-in function in StormWorks that takes in a string of text and two numbers (representing the x and y coordinates of where to draw the text on the screen).

Custom functions
Custom functions, on the other hand, are functions that you create yourself to perform specific tasks. You can define these functions using the function keyword and then call them later in your code whenever you need them. For example, you might create a function called calculateSpeed that takes in the current velocity and acceleration of an object and returns its speed.
Example:
function calculateSpeed(velocity, acceleration) local speed = velocity + acceleration return speed end -- Call the function local currentVelocity = 10 local currentAcceleration = 5 local currentSpeed = calculateSpeed(currentVelocity, currentAcceleration)
In this example, we define a custom function called calculateSpeed that takes in two arguments (velocity and acceleration) and returns their sum as the calculated speed. We then call this function and pass in some example values for velocity and acceleration.
Footnote
Hope you found this guide helpful. Lots of good luck on your journey with Lua in Stormworks! I really appreciate any comments, likes, favorites and awards you may leave, but this is up to you! Keep in mind that feedback and suggestions are more than welcome in the comment section.

- Griz
28 Comments
Sergeant Polar Bear 23 Aug @ 9:17am 
:) np
Griz  [author] 23 Aug @ 5:50am 
@Sergeant Polar Bear - Thanks!
Sergeant Polar Bear 20 Aug @ 2:08pm 
dude i love you for this, this is amazing
towerscripter_1386 15 Aug, 2023 @ 2:46pm 
Hi again, I would like to clear up some stuff about tables, especially "keyword" self.

Lua "self" doesn't work like "this" in any other class languages, it just works as a pre-made pointer in a special-call function to a table that it belongs to, basically:

MyClass:SomeFunction(number)

end

is similar to this:

MyClass.SomeFunction(self,number)

end




If you will do something like that

local t1 = {}
local t2 = t1

It will not create a new table; you have to manually copy table contents into a new table,lua tables are stored as pointers and not new instances. To copy, you can do something like that:

for i,v in t1 do
   t2 = v
end

I don't remember if SW has a table.copy(); if it does, then use it instead of for loops
Griz  [author] 6 Aug, 2023 @ 3:36pm 
@superosh - No worries, i'll be sure to help you may you run into other issues. Appreciate it.
superosh 6 Aug, 2023 @ 1:17pm 
Many thanks for your quick reply.
However, I find it a bit strange, that "print" is a recocnized command/function within SW's LUA editor, but throws out a complete missleading error.(interpreting a function as a non-initialized variable).

Anyway...I used 30 memory-registers and plenty of function-blocks to emulate a 10-byte, 3 bits wide data register to use this as a LUA-table replacement.

The good thing is, all this mem-content-datasets are surviving a save/reload-game.
This, I believe is not possible in SW's LUA.

However...many thanks again.
Griz  [author] 6 Aug, 2023 @ 11:22am 
@superosh - "print" is for the console only. If you want to draw something (text) to a screen you will need to use "screen.drawText()". Remember to set color first.

Example with white text saying Hello:
function onDraw()
screen.setColor(255,255,255)
screen.drawText(0, 0, "Hello")
end

The "0, 0," are x, y coordinates to determine where to place the text on the screen. 0,0 means the text will be in the upper left corner. Hope this helped!
superosh 6 Aug, 2023 @ 10:44am 
Even the "hello World"(function) example does not work.
I just want to write "hello world" on the attached screen using "print".
But the lua-interpreter allways handles "print" as an undefined global variable (error 38).
This happens when: 1, I try to access the function...or 2. when using no function...just print("hello world")

Just traingf to learn teh basics because all I want is:

.....to store 3 values per variable/dataset...so tables comes to mind.
(X-xoordinate,y-coordinate, action to perform)
next data-set..etc

I guess, I limit to 10 datasets and use memory registers then (so 3*10 memory registers).
This lua-stuff is too strange for me.
towerscripter_1386 3 Aug, 2023 @ 11:13am 
I'm not sure if it's also good for this guide, but there is a way to optimize the code so much that you can turn 1000+ character code into ~250 one; basically, lua variables can contain data as well as pointers (by pointers I mean pointers to tables or functions). Basically, you can do something like:

function onDraw()
sc = screen.setColor
sc(0,0,0)
end

This example can REALLY help optimize the code; this can be applied to any function that the Stormworks Lua API provides. If you are using some function more than once, then you definitely need to make a pointer for that function.
Griz  [author] 25 Jul, 2023 @ 5:33am 
@Kerosene - ;)