Device Scripting

From Off Grid Wiki
Jump to navigation Jump to search
An example of a hackable device

Introduction

Device scripting is core to creating an Off Grid Mission, they are incredibly extensible and are useful for a multitude of tasks including forwarding your missions plot and world building. Each device that the player can hack into will have a device script, devices can share scripts if they're similar enough or have their own bespoke scripts.

Script Example

Let's start with a quick device example and build up from there. One of the Off Grid story missions finds the player needing to hack into the office hand dryers.

Here's a basic example that we'll build upon: It's not as bad as it looks!

Visual representation of the example device script
device = {
    -- The game calls this function when the player tries to interact with the device,
    -- It determines if the player has permission to view the devices GUI
    canAccess = function()
     return true
    end,
    -- This determines how often the update function gets called
    -- In this example, we'll call it once a second
    updateRate = 1.0,
    update = function()
        print("Updating!")
    end,
    -- The gui table controls the user interface for the device
    gui = {
        -- For the moment, this can only be ncurses, but will eventually allow different styles for your gui
		type = "ncurses",
		-- The text in the title bar of the gui
		header = [[Our test hand dryer]],
		-- The RGB value of the background
		backgroundColour = {0.95, 0.65, 0.19},
		-- The RGB value of the button highlights
		highlightColour = {0.21, 0.48, 0.74},
		-- Here we set up the list of buttons the user can click on
		buttons = {
			{
				-- The name of the first button
				name = "Test button",
				-- Code to execute when it's clicked
				onClick = function()
                    print("test button clicked!")
				end,
				-- The list of sub buttons, these appear as options when the main button is clicked
                subButtons = {
                    {
						-- Name of the sub button
                        name = "Test subbutton",
						-- Sub button logic when clicked
                        onClick = function()
                            print("test subbutton clicked!")
                        end,
                    },
                }
			}
		},
	},
}


Device Access

You can restrict access to a device in few ways. First, setting an owner for the device in the mission script means the player needs to collect some metadata about the owner to be able to guess the device's password and gain access. By default the amount of required data is 5, but you can configure this in your device script if you want to. And secondly, you can sue the canAccess() function in the device script for more customized checks, for example to check if player's data inventory contains certain file, or social inventory contains some exact piece of metadata. Or do checks on mission progress data using something like Mission.GetBool(), or even overall game progress data to see if player has done some specific thing in a previous level.

The rules for access are these:

  1. If canAccess() returns true, player gets access
  2. Otherwise, if player's collected metadata about the owner is more or equal to the accessLimit value in device script, the player will be able to use password cracker app to gain access to the device.
  3. If the player has 75% or more of the required data, there's a 25% chance to guess the password. After trying this once, the result is remembered, so following tries would yield the same result. The player can try again after collecting at least one more piece of metadata.
  4. if all those fail, the device can't be accessed.

So, the minimum setup for a restricted device is defining the owner in your mission script, and setting the canAccess() to always return false so the device can only be accessed through collecting enough character metadata.

device = {
	...,
	accessLimit = 5,
	canAccess = function()
 		if Player.HasDataFile("Guard1PGPKey") or Player.SocialProfileContainsTagData(owner, "NickName", "Beardman") then
			return true
		else
			return false
		end
	end,
	...,
}

Receiving Data

Devices can set up a callback for when they receive data, this is done by adding the following to the devices Lua table:

device = {
	...,
 	OnReceiveData = function(dataTable)
 		-- Your code here!
	end,
	...,
}

The OnReceiveData callback will be triggered when the device is the recipient of the Mission.SendData function.

What do I do now?

Now you've read through and got an idea of how to build up what your interface looks like you might be looking at ways to expand what your device does.

What's important to remember is all Lua Apis are available in device scripts meaning they can:

  • Trigger sounds
  • Start and stop particle effects
  • Complete and start new objectives
  • Send data to the player and other devices

Suggested next topic to read up on: Lua Apis