Lua guide
This is both a simplistic introduction to Lua scripting in Hedgewars and a guide for more advanced control over the game. With Lua scripting, one can define own missions (both in training and campaign menu), mission maps (like Knockball) and styles (like Highlander).
What is a Lua script
A Lua script is used to make the game behave different by giving the Hedgewars engine different commands. The script gets called by the engine on different events and the script tells the engine what to do.
Lua is a programming language, and you must first learn some basics about the Lua programming language to get started. See http://www.lua.org/ to learn more.
Lua in Hedgewars
Version 0.9.13 of Hedgewars introduced the ability to use Lua scripts to modify Hedgewars behaviour for different maps. The till then used triggers (only appeared in training maps) were removed.
The use of Lua scripts has been extended since then.
Now, Lua scripts are used for:
- Missions, one of three types:
- Training: Easy missions which explain the game, like a tutorial
- Challenge: Missions in which the goal is to reach a high score
- Scenario: Missions with a pre-set goal, like collecting a crate or killing all enemies
- Mission maps (e.g. TrophyRace)
- Styles (e.g. Highlander, Balanced Random Weapon)
- Campaigns
The basic structure
Dependent on what type of script you want to write the requirements are a bit different, but before we go into that we must first create the
.lua
file. The location of the file depends on the script type.
- If you want to make a mission for singleplayer then you create a new
.lua
in one of three directories, depending on the type:
- Training:
Data/Missions/Training
- Challenge:
Data/Missions/Challenge
- Scenario:
Data/Missions/Scenario
- If you want to make a mission for multi player (also called a “mission map”) you create a map and create a new file
map.lua
in the map's folder.
- If you want to make a custom game style, create a new
.lua
file in
Data/Scripts/Multiplayer
.
- Campaign missions go into
Data/Missions/Campaign/<CAMPAIGN NAME>
.
To get started, a
.lua
file should generally be structured like this:
function onGameInit()
end
function onAmmoStoreInit()
end
function onGameStart()
end
function onGameTick()
end
function onGearAdd(gear)
end
function onGearDelete(gear)
end
These are event handlers and are called on different events by the engine. Now lets look at the initiation events.
The initiation events
The two most important event handlers are
onGameInit
and
onAmmoStoreInit
. They are used instead of loading a game scheme and weapon scheme and in campaign missions or standalone missions
onGameInit
is also used to add teams and hogs.
First we have
onGameInit
. On this event we should add all game modifiers and team setup. If you are making a mission you only need to specify the things you want to change on this event, everything not changed will be set to default. The available game modifiers can be found here: LuaEvents#onGameInit()
An example of setting up Barrel Mayhem in a style:
function onGameInit()
GameFlags = gfRandomOrder + gfSharedAmmo
TurnTime = 30000
CaseFreq = 0
MinesNum = 0
MinesTime = 0
Explosives = 40
end
If you are doing a training or campaign mission you should also set
Seed
,
Map
and
Theme
. But you must also add teams and hogs on this event. This is done by using
AddTeam
and
AddHog
. An example of adding one team with one hog (these functions may only be used here):
AddTeam("Team", 0xFF0002, "Simple", "Island", "Default", "hedgewars")
AddHog("Hedgehog", 0, 1, "NoHat")
To be able to play you must add another team and hog that should have another team color (this team has
0xFF0002
) or if you only want one team add the game flag
gfOneClanMode
. Look into LuaGameplay and LuaGears to see what the other parameters of
AddTeam
and
AddHog
are.
In
onAmmoStoreInit
you set what weapons is available in the game. For every weapon, run
SetAmmo
(see LuaGameplay).
This is used to set both starting weapons and weapons found in crates.
Here is an example of the initiation of a training mission:
function onGameInit()
Seed = 0
GameFlags = gfMultiWeapon + gfOneClanMode
TurnTime = 25000
CaseFreq = 0
MinesNum = 0
Explosives = 0
Delay = 0
Map = "Mushrooms"
Theme = "Nature"
AddTeam("Team", 0xFF00002, "Simple", "Island", "Default", "hedgewars")
AddHog("Hedgehog", 0, 1, "NoHat")
end
function onAmmoStoreInit()
SetAmmo(amShotgun, 9, 0, 0, 0)
end
Gears everywhere
Mostly everything in Hedgewars are made out of gears: grenades, bazooka shells, and cakes just to name a few. But these are just the visible gears, the whip's effect and rising water are also gears. But for now we will focus on the more visible ones.
The hogs are gears, too and when you shoot with bazooka the bazooka shell will be created and explode when it hits the ground. When the shell is created the
onGearAdd
event is called and the
gear
parameter will be the bazooka.
And when it hits the ground, before the gear has been deleted,
onGearDelete
is invoked with the shell as parameter, after that it is removed.
Each gear has a gear type, for instance, a bazooka shell has the gear type of
gtShell
, a grenade has a gear type of
gtGrenade
, and so on. You will almost always need to check for the gear type with
GetGearType
in the
onGearAdd
function in order to do anything meaningful.
Gears also have a lot of various values to track their position, state, etc. These can be accessed and written to with several “getter” and “setter” functions like
GetPos
,
GetHealth
,
SetTag
, etc. See LuaGears for a full list. In Hedgewars, the gear values and some variable names do not always really mean what they seem to be, their concrete meaning often depends on the actual gear type. For instance, using
GetHealth(h)
on a hedgehog gear (gear type:
gtHedgehog
) will return its health (obviously). Less obviously, using
GetHealth
on a flying saucer gear (gear type:
gtJetpack
) will return its amount of fuel.
To learn all the gory detaily about gears, see GearTypes.
Other important event handlers
The last important event handlers are
onGameTick
and
onGameTick20
.
onGameTick
is called every game tick, that is every millisecond which is a thousand times a second.
onGameTick20
is called every 20 game ticks, that is, every 20 milliseconds.
These functions are very important for specifying actions which need to happen regularily. It is important to know when to use
onGameTick
, and when to use
onGameTick20
. You can usually get away with just using
onGameTick
but must make sure any code inserted here must be efficient and fast, as this function is called very often. Complex code which takes more time to execute should go into
onGameTick20
instead.
If you need a different interval other than 1 or 20 milliseconds, you can use modulo on the
GameTicks
variable which holds the total number of game ticks since the beginning of the game.
Getting started … for real
This was just a simplistic introduction which didn't cover everything.
A good way to learn Lua scripting in Hedgewars is to read existing scripts. We recommend to take a look into
Data/Missions/Training/Basic_Training_-_Sniper_Rifle.lua
which is the Lua script for the Sniper Rifle target practice training mission. It should give you a rough “feeling” of how a script is supposed to look and is heavily commented.
Continue with the following pages to learn more:
- LuaAPI is the central landing page for everything about the Lua API
- Missions for a more in-depth guide on how to create missions
- LuaLibraries contains information about “libraries”, that is, extra scripts you can include for even more functions. One common library is
Locale
for making a mission translatable
- GearTypes contains the list of all gear types, along with an explanation of how the gears and their values work