LevelScripts
Contents
- 1 Overview
- 2 Script Tiers
- 3 Which level scripts to use in mods, and where to put files
- 4 Documentation
- 5 List of global level script hook functions
- 6 List of per-level script hook functions
- 7 List of per-mod level script hook functions
- 8 Documentation for level script functions
- 8.1 Init function
- 8.2 Update function
- 8.3 ReceiveMessage function
- 8.4 HotspotExit function
- 8.5 HotspotEnter function
- 8.6 DrawGUI function
- 8.7 HasFocus function
- 8.8 SetWindowDimensions function
- 8.9 SaveHistoryState function
- 8.10 ReadChunk function
- 8.11 IncomingTCPData function
- 8.12 DrawGUI2 function
- 8.13 DrawGUI3 function
- 8.14 DialogueCameraControl function
Overview
Level scripts allow you to set up level-wide code that will get run, regardless of what characters, items, and hotspots exist in that level.
Generally you should prefer to put your script logic in hotspots or character controller scripts.
However, sometimes a level script is the right tool for the job. This is especially true when you need to intercept messages that are only passed to level scripts, and that are not (by default) sent to smaller objects in the scene.
Script Tiers
The order that the engine calls into level scripts is as follows:
Global level script
This script file is located in ../Overgrowth/Data/Scripts/level.as
.
Only one of these scripts is ever active at a time, since it is either defined by the base game, or by a mod, and only one mod is allowed to be active at the same time that changes this file. The game will tell you "File Collision" if you try to activate a second mod that overrides the file.
The engine will call into this script for every level in the game. You can override this script in mods, but it is best to only do this as a last resort, since this can make your mod incompatible with other script mods that also override the same file.
Per-level script
Only one of these scripts is ever active at a time, since it is defined per-level, and you cannot have more than one level running at the same time.
The specific path for this script is found in the <script>
XML tag inside each level XML file. This can be changed in the top bar in the editor under Edit -> Set Level Script....
You can override this script in your mods, but that requires you to override it for each individual level. Only one such script can be active for a given level, so this is another place where mod collisions might occur.
Per-mod Level Script
Many of these scripts can be active at the same time, but each mod can only have one.
To use this script file you have to manually add the following XML tag the mod.xml that you make for your mod: <LevelHookFile>some_dir/something.as</LevelHookFile>
Functions in this script are run for every level in the game, and every mod can add their own level hook script.
The disadvantage to it is that you can't as easily override default level script behavior. For the most part, changes in this file are limited to adding on additional behavior, rather than altering existing behavior in the base level script.
Which level scripts to use in mods, and where to put files
In mods, you should always strive to do the least impacting change possible. Prefer modifying level scripts in this order:
If you're creating a per-mod level script, then you have the most flexibility of where to put your script files. Still, it is best to follow a standard convention so that it is easier to find the scripts in other people's mods. The recommended location is <Overgrowth install folder>/Data/Mods/your_mod_name/Data/Scripts/your_mod_name/level_hook.as
.
If you're trying to alter existing script files, then you'll need to place your modified script files in more specific locations.
To override a per-level script you must put your script file in <Overgrowth install folder>/Data/Mods/your_mod_dir/Data/Scripts/
, as this is the root directory for the <script>
tag. To avoid accidentally overshadowing another mod's or one of the main game's script files, it is recommended that you create a directory in the Scripts
directory with the name of your mod, and then put the script file in there. WARNING: Right now there is a bug when setting a level script from the editor menu, if your script is in a .../Scripts/my_mod_name/
folder. You have to manually edit the your_level.xml
file to change the script tag to <Script>your_mod_name/your_script_name.as</Script>
To overshadow the Global level script, create your script file with the following directory and name: <Overgrowth install folder>/Data/Mods/your_mod_dir/Data/Scripts/level.as
.
Documentation
A list of functions, data, etc, is created automatically whenever you run the game, in a file on your hard drive. This lists what external code you get "for free" and can call from inside a custom level script.
- Windows:
My Documents\Wolfire\Overgrowth\aslevel_docs.h
- Mac:
~/Library/Application Support/Overgrowth/aslevel_docs.h
- Linux:
~/.local/share/Overgrowth/aslevel_docs.h
This list is can change with each version of the game, so keep checking back on this aslevel_docs.h
file to see the most up to date information.
There are also wiki pages which have more detailed documentation many of these functions. These pages have a danger of going out of date, but give more detailed documentation on some of the code:
List of global level script hook functions
These functions are required. If you override level.as
in your mod, you must include all of these functions:
-
void Init(string level_name) { }
-
void Update(int is_paused) { }
-
void ReceiveMessage(string message) { }
-
void HotspotExit(string str, MovementObject @mo) { }
-
void HotspotEnter(string str, MovementObject @mo) { }
-
void DrawGUI() { }
-
void SetWindowDimensions(int width, int height) { }
-
void SaveHistoryState(SavedChunk@ chunk) { }
-
void ReadChunk(SavedChunk@ chunk) { }
-
bool HasFocus() { return false; }
These functions are optional. These functions do not have to be added to your overridden level.as
level script, but will be called if they are present:
-
void IncomingTCPData(uint socket, array<uint8>@ data) { }
-
void DrawGUI2() { }
-
bool DialogueCameraControl() { return false; }
-
void DrawGUI3() { }
List of per-level script hook functions
Note that the specific path and filename of each of these scripts is defined in each level's XML file, and there can only be one such script defined per level.
These functions are required. If you override set a level script for your level, you must include all of these functions:
-
void Init(string level_name) { }
-
void Update() { }
-
void DrawGUI() { }
-
bool HasFocus() { return false; }
These functions are optional. These functions do not have to be added to a per-level level script, but will be called if they are present in that file:
-
void ReceiveMessage(string message) { }
-
void IncomingTCPData(uint socket, array<uint8>@ data) { }
-
void DrawGUI2() { }
-
bool DialogueCameraControl() { return false; }
-
void DrawGUI3() { }
List of per-mod level script hook functions
Note that the specific path and filename of each of these scripts is defined in each mod's mod.xml file, and there can only be one such script defined per mod.
These functions are required. If you add a level hook script in your mod, you must include all of these functions in that file:
-
void Init(string level_name) { }
-
void Update(int is_paused) { }
-
void DrawGUI() { }
-
void SetWindowDimensions(int width, int height) { }
-
void ReceiveMessage(string message) { }
These functions are optional. They do not have to be added to your per-mod level script, but will be called if they are present in that file:
Documentation for level script functions
Init function
void Init(string level_name) { }
Global | Per-Level | Per-Mod |
---|---|---|
Required | Required | Required |
TODO: Is level_name a filename, or a string description?
Called when the level is first loaded. TODO: Is it called at any other time?
Be careful, this may be (often is) called before some objects or script params are present in the level!
It is most useful for setting initial values for file-scope angelscript state. TODO: Good example of something that should be Init
instead of just defined with a file-scope initializer?
Update function
void Update(int is_paused) { }
Global | Per-Level | Per-Mod |
---|---|---|
Required | Required | Required |
Note: In per-level level scripts, the signature is void Update() { }
instead.
Called regularly by the engine so you can perform work, or detect that the game is paused. For per-level level scripts, the function is not called if the game is paused. TODO: Make example and add it here, or link to it.
It may be useful to do initialization once in this function, which is safer than doing it in Init if you need objects or level script params to be present. TODO: Make example and add it here, or link to it.
ReceiveMessage function
void ReceiveMessage(string message) { }
Global | Per-Level | Per-Mod |
---|---|---|
Required | Optional | Required |
Called when level-wide messages have been sent by the engine, or by objects in levels.
Objects in levels (such as characters or hotspots) can send this using level.SendMessage("some message string");.
Parameters can be sent by separating them with spaces, and putting quotes around parameters that might contain spaces, then using the TokenIterator object.
TODO: Make a good example and add it here, or link to it.
HotspotExit function
void HotspotExit(string str, MovementObject @mo) { }
Global | Per-Level | Per-Mod |
---|---|---|
Required | Not Called | Not Called |
Triggered when any hotspot is exited by a movement object (such as a character, but not items).
TODO: Make a good example and add it here, or link to it.
HotspotEnter function
void HotspotEnter(string str, MovementObject @mo) { }
Global | Per-Level | Per-Mod |
---|---|---|
Required | Not Called | Not Called |
Triggered when any hotspot is entered by a movement object (such as a character, but not items).
TODO: Make a good example and add it here, or link to it.
DrawGUI function
void DrawGUI() { }
Global | Per-Level | Per-Mod |
---|---|---|
Required | Required | Required |
An update function for script-defined GUIs and graphics/text overlays.
DrawGUI
is called after the main game scene is drawn. If you need to draw on top of other UIs that are drawn with DrawGUI
, then see the DrawGUI2
and DrawGUI3
functions.
All level scripts will have their DrawGUI
functions called before any level script's DrawGUI2
or DrawGUI3
function is called.
HasFocus function
bool HasFocus() { return false; }
Global | Per-Level | Per-Mod |
---|---|---|
Required | Required | Not Called |
Return true from this function if you are going to handle mouse input in this level script. This is particularly useful for menus that you draw yourself, such as the challenge level UI.
TODO: Is this necessary with all types of UIs? How about Dear ImGui?
SetWindowDimensions function
void SetWindowDimensions(int width, int height) { }
Global | Per-Level | Per-Mod |
---|---|---|
Required | Not Called | Required |
Allows a script-defined GUI to resize itself when the window gets resized.
SaveHistoryState function
void SaveHistoryState(SavedChunk@ chunk) { }
Global | Per-Level | Per-Mod |
---|---|---|
Required | Not Called | Not Called |
Allows the level script to save extra undo state.
TODO: Document how this works and why it is useful.
ReadChunk function
void ReadChunk(SavedChunk@ chunk) { }
Global | Per-Level | Per-Mod |
---|---|---|
Required | Not Called | Not Called |
Allows the level script to retrieve extra redo state.
TODO: Document how this works and why it is useful.
IncomingTCPData function
void IncomingTCPData(uint socket, array<uint8>@ data) { }
Global | Per-Level | Per-Mod |
---|---|---|
Optional | Optional | Optional |
Networking hook function, for when network data comes in over a socket you've created.
TODO: Add better documentation for this function, or link to another page with better documentation.
DrawGUI2 function
void DrawGUI2() { }
Global | Per-Level | Per-Mod |
---|---|---|
Optional | Optional | Optional |
A second pass for updating script-defined GUIs and graphics/text overlays, in case you need to do something with two passes (e.g. windows and text overlays that should always be on top of other windows/dialogues, etc).
DrawGUI2
is called after DrawGUI
, in case you need to draw on top of other UIs at those levels.
All level scripts will have their DrawGUI
functions called before any level script's DrawGUI2
function is called. All level script's DrawGUI2
functions will be called before any level script's DrawGUI3
gets called.
DrawGUI3 function
void DrawGUI3() { }
Global | Per-Level | Per-Mod |
---|---|---|
Optional | Optional | Optional |
A third pass for updating script-defined GUIs and graphics/text overlays, in case you need to do something with three passes (e.g. windows that are always top level, such as the pause menu).
DrawGUI3
is called after DrawGUI2
and DrawGUI
, in case you need to draw on top of other UIs at those levels.
All level scripts will have their DrawGUI
and DrawGUI2
functions called before any level script's DrawGUI3
function is called.
DialogueCameraControl function
bool DialogueCameraControl() { return false; }
Global | Per-Level | Per-Mod |
---|---|---|
Optional | Optional | Not Called |
Called from character scripts, in order to determine if a dialogue rendered in a level script has camera control. That way character control scripts can avoid conflicts while they manipulate the camera.