Ground of Aces Scripting API
Loading...
Searching...
No Matches
Ground of Aces Scripting

The game uses Python for scripting. The current supported version of Python is 3.4.

Scripts location

The script are located in the game folder, under the directory GroundOfAces_Data/StreamingAssets/Scripts. They are grouped into directories that can be loaded individually.

Loading scripts

By default, only the scripts located inside the Default directory are loaded on game startup.

In order to load scripts from other directory, use the command load_scripts <name> in the cheats console.

Writing scripts

Inside of the directory, scripts are contained inside .py files, where each one can contain one or more event handlers.

Creating your first script

For the first script, let's create an event that is triggered every time a day phase changes and boosts the whole crew morale by 10 when it happens.

To do this, we will subscribe to the DAY_PHASE_CHANGE event. This is just one of the events you can use - the full list is available here.

Go to the scripts location (GroundOfAces_Data/StreamingAssets/Scripts/Default) and create a new file named morale_boost.py. Paste the following code into it:

# Import MinorEvent to have access to built-in event names
from Blindflug.MinorEvents import MinorEvent
# Import MoraleCategory to have access to morale type constants
from Blindflug.Game.Characters.Morale import MoraleCategory
# Define a localization term that can be displayed in the game.
# This term contains a single placeholder value named "MOOD".
# Since this is located outside the function, it will be called when the script is loaded.
localization.SetTerm("en", "morale_up", f"New day phase, [morale:{MoraleCategory.Mood}] improves by {{[MOOD]}}!")
# Use a decorator to mark the function `on_day_phase` as an event handler.
# Then, define a function to be called when the event happens.
# The arguments are specific to the day phase change event,
# and contain the previous and the current phase.
@event_handler(MinorEvent.DAY_PHASE_CHANGE)
def on_day_phase(previous_phase, current_phase):
# Define the value of mood to add
mood_boost = 10
# Modify the mood of all characters
characters_api.ModifyMorale(MoraleCategory.Mood, mood_boost)
# Create an event log entry, using the localization term defined previously
# The "MOOD" placeholder will be replaced with the value of `str(mood_boost)`
event_log.Create("morale_up", {'MOOD': str(mood_boost)})
Definition CharacterMoraleEffectPresenter.cs:6
Definition EventLogItemFactory.cs:5

Now, launch the game and wait until a day phase changes. You should see the message in the event log, and the mood of the whole crew should go up by 10. Congratulations - you've created your first script!

Note
The event_handler is a function that implements a Python concept called decorator (signified by the @ sign in front of it). If you're unfamiliar with Python, the general idea is that it can be used to modify the function that comes after it - in this case, by marking it as one that needs to be called when an event happens. See here for some further explanation.

Adding more logic

While everyone at the base certainly likes their work, even they probably enjoy a well-deserved break. Let's change the morale effect and make it dependent on which day phase has just started.

First, import DayPhase to have access to day phase constants:

from Blindflug.DayPhases import DayPhase
Definition DayPhase.cs:2

Inside the on_day_phase function, modify the value assigned to mood_boost variable:

mood_boost = 10 if current_phase == DayPhase.Leisure else 5 if current_phase == DayPhase.Sleep else 0

Since if the day phase is neither leisure nor sleep we don't really want to do anything, add an early return:

if mood_boost == 0:
return False

The returned value is actually significant - if it's True, this execution will be counted towards the max occurrences limit. However, when False is returned, this execution will not be counted.

Tweaking chance and maximum occurrences count

When not explicitly configured, the handler will execute every time the event happens, with no limitation of how many times this can happen. This is great for testing, but for actual usage, some randomness might be a good idea. This will give the function 10% chance to be called when the game day phase changes, up to 4 times during a single game:

@event_handler(MinorEvent.DAY_PHASE_CHANGE, chance=0.1, max_occurrences=4)

Adding localizations

If you want your script to support multiple languages, you can define localization terms for each of them. Let's translate our message into Polish:

localization.SetTerm("pl", "morale_up", f"Nowa faza dnia, [morale:{MoraleCategory.Mood}] wzrasta o {{[MOOD]}}!")

Now, when you change the game language between English and Polish, the message in the event log should also be translated correctly.

Note
If the term is not defined for the chosen game language, it will default to English, so it's probably a good idea to always provide at least an English version of the string.

Final script

After all the above changes, the final script should look something like this:

from Blindflug.MinorEvents import MinorEvent
from Blindflug.Game.Characters.Morale import MoraleCategory
from Blindflug.DayPhases import DayPhase
localization.SetTerm("en", "morale_up", f"New day phase, [morale:{MoraleCategory.Mood}] improves by {{[MOOD]}}!")
localization.SetTerm("pl", "morale_up", f"Nowa faza dnia, [morale:{MoraleCategory.Mood}] wzrasta o {{[MOOD]}}!")
@event_handler(MinorEvent.DAY_PHASE_CHANGE, chance=0.1, max_occurrences=4)
def on_day_phase(previous_phase, current_phase):
mood_boost = 10 if current_phase == DayPhase.Leisure else 5 if current_phase == DayPhase.Sleep else 0
if mood_boost == 0:
return False
characters_api.ModifyMorale(MoraleCategory.Mood, mood_boost)
event_log.Create("morale_up", {'MOOD': str(mood_boost)})

Next steps

A good way to get a feeling of what's possible using the scripting API is to look through the built-in scripts located in the random_events.py file in the scripts directory.

Global variables

Each script has access to some predefined global variables that provide functionality to interact which the game. They are:

Events

The list of default events and their arguments can be found here.

Event handler functions

Event handler functions are normal Python functions, decorated with the event_handler decorator. The name of the function can be any valid Python function name, and will be used together with the containing module name to identify the function internally when calculating how many times a function was called (in order to implement max occurrences limit). The function arguments depend on the particular event (see here).

The handler function can optionally return False - this will cause the execution not to be counted towards the max_occurrences limit. This is useful if particular handler should be invoked limited number of times, but only under certain conditions. Not returning anything (or explicitly returning True) causes the execution to be counted normally.

@event_handler(event_name, chance=1.0, max_occurrences=-1)
def handler_function(arg1, arg2):
  • event_name - Name of the event to handle. This can be any string that corresponds to an existing event, but for built-in events the easier way is to from Blindflug.MinorEvents import MinorEvent and the use the constants defined there.
  • chance - A chance of the event handler being called when the event happens, from 0.0 to 1.0. E.g. setting chance to 0.5 would give the handler 50% chance to be called when the event happens. This default to 1.0 (always call the handler on event).
  • max_occurrences - Maximum number of times the handler can be called during a single playthrough. Negative value means "no limit". The default in -1.

String formatting

  • [character:<id>]

    This can be used to create a clickable link to the character defined by the <id>.

  • [resource:<name>]

    This will add an icon and color to a resource.

    Use the following to get access to the ResourceType enum:

    from Blindflug.GameResources import ResourceType
  • [morale:<name>]

    This will add an icon and color to a morale category.

    Use the following to get access to the MoraleCategory enum:

    from Blindflug.Game.Characters.Morale import MoraleCategory