Difference between revisions of "Mission Scripting"
(Fix Device Scripting Link) |
(Link/fix) |
||
Line 247: | Line 247: | ||
| ''internalName'' || The name of the device. Must be unique and match the MissionObject in the scene | | ''internalName'' || The name of the device. Must be unique and match the MissionObject in the scene | ||
|- | |- | ||
− | | ''script'' || The script that defines the gui and the behaviour of the device ( See [[ | + | | ''script'' || The script that defines the gui and the behaviour of the device ( See [[Device Scripting | device scripts]] for more information ) |
|} | |} | ||
Revision as of 09:52, 8 September 2017
Intro
This article will describe everything you need to know in order to understand how to write and modify missions scripts in Off Grid! Mission scripts can get a little bit large but don't let that overwhelm you, they're deceptively simple, we promise!
Pre-requisites
All modding scripts for Off Grid are written in Lua, it's a lovely little language which is simple ( don't tell it I said that ) and extensible thanks to the marvellous MoonSharp.
Lua is quite easy to pick up, even people with no programming experience should be able to get hacking in next to no time!
You'll need the following tools for editing and writing new mission scripts:
IDE
Firstly you'll need an IDE, we recommend the Atom with the following extensions:
language-lua | Syntax highlighting for Lua |
autocomplete-lua | Auto-complete support for Lua, we recommend enabling the "Override lower priority providers" in the plugin settings |
LevelKit & Game
Both of these are needed in order to run and test and scripts you create
TO DO
The Mission Script Structure
As mentioned above, mission scripts can get rather large so this article will attempt to break down all the little sub elements, it can be helpful to try and think of the mission script in the same way you might think of a film script. The vast majority of the script is simply defining what is in the world of the mission you've created. Enough talking, lets jump into an example! Rather than posting an entire example script, we'll go from top to bottom exploring what each element does.
Initial Mission State
mission = { -- Mission info startTime = {2009, 04, 27, 21, 13, 00},
In this first code block we create the mission Lua table and define its first value.
Name | Description |
---|---|
startTime | The start time of the mission in the game world (Year, Month, Day, Hour, Mins, Secs) |
startTime doesn't have to be the current date, you can set your mission in any time you desire.
Characters
-- Character definitions: characters = { joe = { displayName = "Joe Harman", internalName = "Joe", characterType = "player", prefab = "player", spawnpoint = "PlayerSpawn", }, },
This is the first example of us creating a sub table in the mission table, the characters table contains all the information about the characters in your mission! In this example we've added Joe, the protagonist of Off Grid. Here's a break down of what the value of Joe's table means:
Character Table | |
---|---|
Name | Description |
displayName | The name that will be used any game UI referencing the character |
internalName | The internalName can be thought of as the id for the character, you'll reference the character by this value in a few places including conversations (Must be unique!) |
characterType | The 'type' of the character, see Character Types and Prefabs for more information on possible values |
'prefab' | The prefab for the character, see Character Types and Prefabs for more information on possible values |
spawnpoint | The name of the spawn mission object, the position of this object will be where the character is spawned |
The characters table can hold information on as many characters as you'd like to fill the mission with, they won't be spawned into the mission until you decide (more on that later)
Physical Items
-- Inventory items: items = { usbkey = { internalName = "USBDongle", displayName = "USB dongle", description = "Modified USB Bluetooth dongle given to you by the hackers", uiSpriteName = "usbdongle.png", }, },
The items table contains information about physical items that the player will be able to add to their inventory over the course of the mission, in this example we're marking up a USB dongle that the player can plug into computers
Item Table | |
---|---|
Name | Description |
internalName | The internalName we'll use to identify this item (Must be unique!) |
displayName | The display name of the item, this is what will be displayed in the games UI |
description | The description of the item, this will be displayed to users in the players inventory UI |
uiSpriteName | The path to the items sprite, this is the image that will be used in the games UI |
Data
--[[ Data files: Available data types: generic, text, SMS, encrypted, audio, video, location, key, UUID ]]-- data = { PlayerPGPKey = { internalName = "PlayerPGPKey", name = "Personal PGP encryption key", immutable = true, dataType = 7, creatorName = "Player", dataString = "PGP Fingerprint: 1d7d ef54 7a63 5756 63a7 cf14 fbd8 775c c39d 4e51", description = "AES 256-bit", dataColor = {0.0, 0.6, 1.0, 0.3}, }, },
The data table contains data that's specific to your mission, in this example we're defining the players PGP encryption key
Data Table | |
---|---|
Name | Description |
internalName | The internalName we'll use to identify this data (Must be unique!) |
name | The display name of the data, this is what will be displayed in the games UI |
immutable | Is the data immutable? If true the player won't be able to delete it, this is useful for data items that are part of mission objectives |
dataType | The type of the data, this is used for displaying the data correctly |
creatorName | The name of the data's creator (displayed in the UI) |
dataString | The contents of the data file |
description | A description of the data file |
dataColor | RGBA value that's used as the colour of the data point when visible in the players data view |
Networks
-- Networks: --[[ types: 0 = mobile, 1 = WiFi, 2 = mesh ]]-- networks = { Semaeopus4G = { name = "Semaeopus4G", networkType = 0, allowPlayerDisconnect = false, userAccessKey = "user", adminAccessKey = "admin", rootAccessKey = "root", }, },
The networks table contains all the information about the possible networks in your game, networks can be of different types such as mobile networks, WiFi, and mesh
Network Table | |
---|---|
Name | Description |
name | The name of the network (Must be unique!) |
networkType | The type of the network (mobile - 0, WiFi - 1, mesh - 2) |
allowPlayerDisconnect | Is the player allowed to disconnect from the network? |
userAccessKey | The password for user access to the network |
adminAccessKey | The password for admin access to the network |
rootAccessKey | The password for root access to the network |
Data sent at higher access levels across a network won't be visible to devices that are connected at a lower access level.
Objectives
-- Mission objectives: objectives = { enterTheBuilding = { name = "Enter the building", onStart = function() print("Player must now enter the building") end, onCompleted = function() print("The player is now in the building!") end, }, },
The objectives table contains all the tasks that the player should complete before your mission is finished.
Objective Table | |
---|---|
Name | Description |
name | The name of the objective (should be unique) |
onStart | A callback function that's triggered when the objective is started |
onCompleted | A callback function that's triggered when the objective is completed |
Devices
devices = { laptop = { internalName = "laptop", script = "Scripts/Devices/laptop.lua", }, },
Device Table | |
---|---|
Name | Description |
internalName | The name of the device. Must be unique and match the MissionObject in the scene |
script | The script that defines the gui and the behaviour of the device ( See device scripts for more information ) |
Mission Setup
function SetupMission() -- add player and guards: Mission.AddCharacter(mission.characters.joe) -- these two below add in the guards which you might not have created yet! Mission.AddCharacter(mission.characters.jack) Mission.AddCharacter(mission.characters.john) -- set up hackable devices Mission.AddHackableDevice(mission.devices.laptop) -- set up networks: Mission.AddNetwork(mission.networks.Semaeopus4G) Mission.ConnectToNetwork(mission.devices.laptop, mission.networks.Semaeopus4G.name, mission.networks.Semaeopus4G.userAccessKey) Doors.SetNetwork(mission.networks.Semaeopus4G) Doors.SetZoneKeys("admin", {"adminkey"}) -- misc. -- Player.SetInvisible(true) Mission.MissionStarted() end
This will add in all of your created elements into your level, below you will see what the function of each part of this code will do.
Adding in Characters
-- add player and guards: Mission.AddCharacter(mission.characters.joe) -- these two below add in the guards which you might not have created yet! Mission.AddCharacter(mission.characters.jack) Mission.AddCharacter(mission.characters.john)
This part of the code shows the format of adding in characters - this includes the player and any NPCs like the guards, which you will have created further up in your Mission Script. If the title of your character table for your player was called jenson
, you would simply change Mission.AddCharacter(mission.characters.joe)
to Mission.AddCharacter(mission.characters.jenson)
, this would now let your player spawn in.
Adding in Hackable Devices
-- set up hackable devices Mission.AddHackableDevice(mission.devices.laptop)
Once you have set up some hackable devices, by adding this to your SetupMission() the hackable devices will now be added into your level. Similarly to adding in the characters as seen above, to customise this for your own devices, you only need to change the last part inside the brackets. So if the title of one of your devices tables was vendingmachine
, you could just change Mission.AddHackableDevice(mission.devices.laptop)
to Mission.AddHackableDevice(mission.devices.vendingmachine)
.
Adding in Networks
-- set up networks: Mission.AddNetwork(mission.networks.Semaeopus4G) Mission.ConnectToNetwork(mission.devices.laptop, mission.networks.Semaeopus4G.name, mission.networks.Semaeopus4G.userAccessKey) Doors.SetNetwork(mission.networks.Semaeopus4G) Doors.SetZoneKeys("admin", {"adminkey"})
You will have already created a network in your networks table. Now to add it into the game you need to just add in Mission.AddNetwork(mission.networks.NETWORKNAME)
where NETWORKNAME
is the title of the table you created in your networks table, in this tutorial it was defined as Semaeopus4G
. To then connect your hackable devices to your network you just need to add in what you see on line 86, where laptop
can be replaced with the hackable devices table name, though in our example the table of our hackable device is called laptop
, so we'll keep it as it is.
Once you have created doors you can then also add them to a network. By adding them to a network you can make it so that the player cannot open the door unless they have a key. Firstly you add the door to a network, then you can set the door's zone to require a specific key to open it. In our example where we set the zone's required key: Doors.SetZoneKeys("admin", {"adminkey"})
, "admin"
is the name of the zone the door is assigned to, and "adminkey"
is the name of the key that will allow the player to unlock the doors of the zone "admin"
.
Adding in Other Changes
-- misc. -- Player.SetInvisible(true)
Whilst modding you might get to a point in development where you need to test features like the patrol routes of guards, so a useful line of code you can add to your MissionSetup() is Player.SetInvisible(true)
, this will make your player invisible to the Guards which can certainly be handy for testing your level without being spotted!