Creating Apps: Difference between revisions

From Off Grid Wiki
Jump to navigation Jump to search
No edit summary
No edit summary
Line 64: Line 64:
The first section of the app script is used to define some default settings and basic information about what the app is and how it works.
The first section of the app script is used to define some default settings and basic information about what the app is and how it works.


{|
{| class="wikitable"
!width="5%"| Name
! Name
!align="center" width="8%"| Required/Optional
! Required/Optional
!width="5%"| Description
! Description
|-
|-
| name
| name

Revision as of 14:47, 9 November 2018

Introduction

Example Lua script

app = {
    name = "Example App",
    description = "How to make your first app for Off Grid.",
    cost = 2.0,
    targets = {TargetType.Data},
    showInRadial = AppMenuState.target,
    showInAppWheel = AppMenuState.byDefault,
    state = AppState.off,
    icon = "ExampleApp.png",
    iconColor = Color.Blue,
    statusIcons = { "option1.png", "option2.png"},

    actions = {
        {
            name = "DefaultAction",
            run = function(target)
                -- In 3rd person mode executing app will always trigger first action
            end,
        },
        {
            name = "ExtraAction",
            cost = 2.0,
            run = function(target)
                -- In radial menu mode if there's more than one action, triggering the app opens a popup menu to select which action to take.
            end,
        },
    },

    options = {
        someOption = {
            name = "Some option",
            enabled = true,
        },
        anotherOption = {
            name = "Some other option",
            enabled = false,
            OnOptionChange = function()
                -- This runs when the option is toggled.
            end
        },
    },

    OnStateChange = function(state)
        -- This runs when something on game side asks the app to change it's state
        app.state = state
        SetState(app.state)
    end,

    UpdateActions = function(target)
        -- If you want to change available actions based on the target player has selected, do it here.
    end,

    Update = function(time)
        -- Update will run continuosly.
    end,

}

App configuration

The first section of the app script is used to define some default settings and basic information about what the app is and how it works.

Name Required/Optional Description
name required Name of the app
description required Short description of what the app does
cost optional How many seconds the tracking progress increases when using this app
targets optional List of what target types the app can have
showInRadial optional How the app should be displayed in Radial menu. See menu options.
showInAppWheel optional How the app should be displayed in the AppWheel. See menu options.
state required Current state of the app.
icon required Path to icon image
iconColor optional background color for the app icon
statusIcons optional List of icon images to use for status window

name

description

cost

targets

showInRadial

showInAppWheel

state

icon

iconColor

statusIcons

Actions & Options

Actions table

Options table

Functions

There are a few functions that the game tries to call in different situations, so depending on the app you are making you might want to include some of these in your script.

OnStateChange()

OnStateChange function handles the game requesting the app to change it's state, to turn the app on, or off, and so on, either becuase the player pressed a buytton to do so, or some other Lua script or game system asked for it. Ultimately, the app itself get's to decide how to handle the request, although usually you would want the app to comply. When the game calls this function, it will pass the requested app state to the function.

The minimun you should do is to se tthe app's state to the requested one, and then trigger the built-in API function to tell the game to change state there as well:

OnStateChange = function(state)
    app.state = state
    SetState(app.state)
end,

If the app script doesn't include OnStateChange function, the game assumes this is all you want to do and a sa fallback solution handles it for you automatically.

You can also add additional things the app should do when changing the state, for example to show or hide a status window as the app is toggled on and off:

OnStateChange = function(state)
    if state == AppState.on then
        CreateStatusWindow()
        SetStatusIcon(1)
        SetStatusIconColor(Color.LightGrey)
        DisplayStatusWindow(true)
    elseif state == AppState.off then
        RemoveStatusWindow()
    end
    app.state = state
    SetState(app.state)
end,

UpdateActions()

If the app has UpdateActions function, it's called when the player has selected a target and presses a button to trigger the app. It let's you rewrite the app's action table to change what the app does, or what kind of actiosn the player can take. The game passes the app target information when calling this function.

One option would be to just rewrite the whole actiosn table based on target type:

UpdateActions = function(target)

        if target.type == TargetType.Hackable then
            app.actions = {
                {
                    name = ""
                },
                {

                },
            }
        else if target.type == TargetType.Character then
            app.actions = {
                {

                },
            }
        else
            app.actions = {}
        end

    end,

You can also use this to dynamically create a list of actions. The following code checks if the target is either a hackablke device or a character (so, a target type that you can receive data), and then uses the Player API to get a list of files in player's inventory and adds a new action each file:

UpdateActions = function(target)

        if target.type == TargetType.Hackable or target.type == TargetType.Character then
            app.actions = {
                {
                    name = "Select file to send:",
                }
            }
            playerFiles = Player.GetAllDataFiles()
            for _, file in ipairs(playerFiles) do
                newAction = {}
                newAction.name = file.name
                newAction.cost = 1
                newAction.run = function(target)
                    message = string.format("Sending file %s to %s", file.name, target.name)
                    UI.ShowPopUp(PopupType.progress, "FileShare", message, 3)
                    Scheduler.CallInSecsReal(function()
                        Player.SendData(file.internalName, target.name)
                    end, 3)
                end
                table.insert(app.actions, newAction)
            end
        else
            app.actions = {}
        end

    end,

Update()

If the app script has Update() function, it will be called regularly by the game. This allows your apps to do things continuously in the background. The update rate is once every 0.2 seconds, and the game will pass current time as the parameter.

The Update function is called regarlessof the app's current state, so it's up to you to choose if the app should only do things when it's switched on (which would be the usual case) or if you want the app to continue running in the background.

If the app table includes a cost value (in contrary to the cost defined in actions), this will get applied every tick the update runs.

A good example of app using the Update function would be the light monitor app, which checks the light level continuously and then updates that to a status window:

Update = function()
    if state == AppState.on then
        lightLevel = Player.GetLightLevel()
        if lightLevel < 0.06 then
            SetStatusIconColor(Color.Green)
        elseif lightLevel < 0.15 then
            SetStatusIconColor(Color.Blue)
        else
            SetStatusIconColor(Color.LightGrey)
        end
        statusText = string.format("%.1f %%", lightLevel * 100)
        UpdateStatusWindow(statusText)
    end
end,

Data types

Target types

These are the types of targets available from the game's targeting system. Using TargetType.None allows the app to work without requiring a target at all. The values are used in the game internally for bitmasking multiple target types at the same time, and in general won't be needed for anyhting in Lua side, you can just use the more conveninent text version in your script.

Type Value Description
TargetType.None 0 No target. Use for apps which don't require any target at all.
TargetType.Data 1 Any data points currently visible to the player
TargetType.Interaction 2 Physical interactions in the levels
TargetType.Hackable 4 Hackable devices in player's current networks
TargetType.Character 8 People

Menu options

Name Description
AppMenuState.always App is always displayed in this menu.
AppMenuState.never App will never be shown in this menu
AppMenuState.byDefault App will be set as favourite for this menu by default (but can be removed by player)
AppMenuState.target App will always display in Radial menu if current target matches one of the target types for the app.

App states

Name Description
AppState.unavailable The player doesn't have this app yet
AppState.disabled App can't be used at the moment, for example no network connection
AppState.off App is not doing anything
AppState.on App is switched on and running in the background
AppState.alert App displays alert to notify the player about something

time

The game will pass a time value to the Update function. This is just counting seconds from when the game was started. (Equal to Unity's Time.time)

target

When the game runs the UpdateActions function, or triggers an action, it will pass target table to the app script. This contains some information about the current target:

Data Description
target.name the internalName of the current target object
target.type TargetType of the current target
target.missionObject Set if the target is a MissionObject.(Check the missionObject table for more details)
target.data Set for data targets. Contain s a table with more infromation (see data table for details)
target.interactionType Set on interaction targets, this will contain the interactionType
target.macAddress Set on device targets. Contains the device's MAC address as a string.

If the app's targets list includes TargetType.None, and there is no target selected when UpdateAction or some actio s triggered, the target.name will be an empty string, and target.type is set to TargetType.None.

Built-in functions

Status window

CreateStatusWindow()

DisplayStatusWindow()

RemoveStatusWindow()

SetStatusIcon()

SetStatusIconColor()

App state

SetState()

Apps in your mission and other scripts

Apps API