Difference between revisions of "LevelScripts"

From Wolfire Games Wiki
Jump to: navigation, search
(Optional global functions)
(Global level script: Added todo for level messages)
 
(48 intermediate revisions by 2 users not shown)
Line 1: Line 1:
 
== Overview ==
 
== Overview ==
 
+
[[Category: Modding]]
 +
[[Category:Overgrowth]]
 
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.
 
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.
  
Line 17: Line 18:
  
 
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.
 
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.
 +
 +
'''TODO:''' These level messages are handled in this script, this should be documented somewhere:
 +
<pre>
 +
"clearhud"
 +
"cleartext"
 +
"disable_retry"
 +
"displaygui"
 +
"displayhud"
 +
"displaytext"
 +
"dispose_level"
 +
"go_to_main_menu"
 +
"loadlevel"
 +
"make_all_aware"
 +
"manual_reset"
 +
"open_menu"
 +
"reset"
 +
"screen_message"
 +
"start_dialogue"
 +
"start_dialogue_fade"
 +
"tutorial"
 +
</pre>
  
 
==== Per-level script ====
 
==== Per-level script ====
Line 41: Line 63:
 
# [[#Per-level script|Per-level script]]
 
# [[#Per-level script|Per-level script]]
 
# [[#Global level script|Global level script]]
 
# [[#Global level script|Global level script]]
If you're creating a [[#Per-mod_Level_Script|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 <code>../Overgrowth/Data/Mods/your_mod_name/Data/Scripts/your_mod_name/level_hook.as</code>.
+
If you're creating a [[#Per-mod_Level_Script|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 <code>../Data/Mods/your_mod_name/Data/Scripts/your_mod_name/level_hook.as</code>.
  
 
If you're trying to alter existing script files, then you'll need to place your modified script files in more specific locations.
 
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|per-level script]] you must put your script file in <code>../Overgrowth/Data/Mods/your_mod_dir/Data/Scripts/</code>, as this is the root directory for the <code><script></code> 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 <code>Scripts</code> directory with the name of your mod, and then put the script file in there.
+
To override a [[#Per-level script|per-level script]] you must put your script file in <code>../Data/Mods/your_mod_dir/Data/Scripts/</code>, as this is the root directory for the <code><script></code> 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 <code>Scripts</code> 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 <code>.../Data/Scripts/your_mod_name/</code> folder. You have to manually edit the <code>your_level.xml</code> file to change the script tag to <code><Script>your_mod_name/your_script_name.as</Script></code>
  
To overshadow the [[#Global level script|Global level script]], create your script file with the following directory and name: <code>../Overgrowth/Data/Mods/your_mod_dir/Data/Scripts/level.as</code>.
+
To overshadow the [[#Global level script|Global level script]], create your script file with the following directory and name: <code>../Data/Mods/your_mod_dir/Data/Scripts/level.as</code>.
  
 
== Documentation ==
 
== Documentation ==
  
Documentation of the functions, classes, and object instances that you can access inside a level script are available in an automatically generated file on your hard drive after starting the game for the first time. Find the location for your operating system just below.
+
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''': <code>My Documents\Wolfire\Overgrowth\aslevel_docs.h</code>
 
* '''Windows''': <code>My Documents\Wolfire\Overgrowth\aslevel_docs.h</code>
Line 57: Line 79:
 
* '''Linux''': <code>~/.local/share/Overgrowth/aslevel_docs.h</code>
 
* '''Linux''': <code>~/.local/share/Overgrowth/aslevel_docs.h</code>
  
The list of available functions, classes, and object instances can change with each version of the game, so keep checking back on this <code>aslevel_docs.h</code> file to see the most up to date information.
+
This list is can change with each version of the game, so keep checking back on this <code>aslevel_docs.h</code> 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:
 +
 
 +
* [[Level Script External Code|These functions are unique to level scripts]]
 +
* [[Common Script External Code|These functions are shared with other script types]]
 +
 
 +
== List of level script hook functions ==
 +
 
 +
These functions are '''required'''. You must include all of these functions in a level script:
 +
 
 +
* [[#Init function|<code>void Init(string level_name) { }</code>]]
 +
 
 +
These functions are '''optional'''. These functions do not have to be added to a level script, but will be called if they are present:
 +
 
 +
* [[#Update function|<code>void Update(int is_paused) { }</code>]]
 +
* [[#Update function|<code>void Update() { }  // Deprecated: Only called if previous function doesn't exist, and only when paused</code>]]
 +
* [[#ReceiveMessage function|<code>void ReceiveMessage(string message) { }</code>]]
 +
* [[#HotspotExit function|<code>void HotspotExit(string str, MovementObject @mo) { }</code>]]
 +
* [[#HotspotEnter function|<code>void HotspotEnter(string str, MovementObject @mo) { }</code>]]
 +
* [[#DrawGUI function|<code>void DrawGUI() { }</code>]]
 +
* [[#HasFocus function|<code>bool HasFocus() { return false; }</code>]]
 +
* [[#SetWindowDimensions function|<code>void SetWindowDimensions(int width, int height) { }</code>]]
 +
* [[#SaveHistoryState function|<code>void SaveHistoryState(SavedChunk@ chunk) { }</code>]]
 +
* [[#ReadChunk function|<code>void ReadChunk(SavedChunk@ chunk) { }</code>]]
 +
* [[#IncomingTCPData function|<code>void IncomingTCPData(uint socket, array<uint8>@ data) { }</code>]]
 +
* [[#DrawGUI2 function|<code>void DrawGUI2() { }</code>]]
 +
* [[#DrawGUI3 function|<code>void DrawGUI3() { }</code>]]
 +
* [[#DialogueCameraControl function|<code>bool DialogueCameraControl() { return false; }</code>]]
 +
 
 +
== Documentation for level script hook functions ==
 +
 
 +
=== Init function ===
 +
 
 +
<pre style="white-space: pre-wrap;">void Init(string level_name) { }</pre>
 +
 
 +
[[#List of level script hook functions|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 <code>Init</code> instead of just defined with a file-scope initializer?
 +
----
 +
 
 +
=== Update function ===
 +
 
 +
<pre style="white-space: pre-wrap;">void Update(int is_paused) { }</pre>
 +
 
 +
[[#List of level script hook functions|Optional]]
 +
 
 +
Called regularly by the engine so you can perform work, or detect that 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.
 +
 
 +
'''Note''': If <code>void Update(int is_paused) { }</code> is not present in the level script, then <code>void Update() { }</code> will be called instead (if present, but only if the game is paused). This is a deprecated fallback function, and it is recommended to always use the '''is_paused''' variant.
 +
----
 +
 
 +
=== ReceiveMessage function ===
 +
 
 +
<pre style="white-space: pre-wrap;">void ReceiveMessage(string message) { }</pre>
 +
 
 +
[[#List of level script hook functions|Optional]]
 +
 
 +
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 ===
 +
 
 +
<pre style="white-space: pre-wrap;">void HotspotExit(string str, MovementObject @mo) { }</pre>
 +
 
 +
[[#List of level script hook functions|Optional]]
 +
 
 +
Triggered when any hotspot is exited by a movement object (such as a character, but not items).
  
== List global level script hook functions ==
+
'''TODO''': Make a good example and add it here, or link to it.
 +
----
 +
=== HotspotEnter function ===
  
=== Required global functions ===
+
<pre style="white-space: pre-wrap;">void HotspotEnter(string str, MovementObject @mo) { }</pre>
  
These functions are required, and must be present in <code>level.as</code>. If you override that file in your mod, you must include all of these functions.
+
[[#List of level script hook functions|Optional]]
  
<pre style="white-space: pre-wrap;
+
Triggered when any hotspot is entered by a movement object (such as a character, but not items).
white-space: -moz-pre-wrap;
 
white-space: -pre-wrap;
 
white-space: -o-pre-wrap;
 
word-wrap: break-word;">void Init(string level_name) { }
 
// Called when the level is first loaded.
 
// Be careful, this may be 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.</pre>
 
  
<pre style="white-space: pre-wrap;
+
'''TODO''': Make a good example and add it here, or link to it.
white-space: -moz-pre-wrap;
+
----
white-space: -pre-wrap;
+
=== DrawGUI function ===
white-space: -o-pre-wrap;
 
word-wrap: break-word;">void Update(int is_paused) { }
 
// Called regularly by the engine so you can perform work, or detect that the game is paused.
 
// It may be useful to do initialization once in this function, if you need objects or level script params to be present.</pre>
 
  
<pre style="white-space: pre-wrap;
+
<pre style="white-space: pre-wrap;">void DrawGUI() { }</pre>
white-space: -moz-pre-wrap;
 
white-space: -pre-wrap;
 
white-space: -o-pre-wrap;
 
word-wrap: break-word;">void ReceiveMessage(string message) { }
 
// 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.</pre>
 
  
<pre style="white-space: pre-wrap;
+
[[#List of level script hook functions|Optional]]
white-space: -moz-pre-wrap;
 
white-space: -pre-wrap;
 
white-space: -o-pre-wrap;
 
word-wrap: break-word;">void HotspotExit(string str, MovementObject @mo) { }
 
// Triggered when any hotspot is exited by a movement object</pre>
 
  
<pre style="white-space: pre-wrap;
+
An update function for script-defined GUIs and graphics/text overlays.
white-space: -moz-pre-wrap;
 
white-space: -pre-wrap;
 
white-space: -o-pre-wrap;
 
word-wrap: break-word;">void HotspotEnter(string str, MovementObject @mo) { }
 
// Triggered when any hotspot is entered by a movement object</pre>
 
  
<pre style="white-space: pre-wrap;
+
<code>DrawGUI</code> is called after the main game scene is drawn. If you need to draw on top of other UIs that are drawn with <code>DrawGUI</code>, then see the <code>DrawGUI2</code> and <code>DrawGUI3</code> functions.
white-space: -moz-pre-wrap;
 
white-space: -pre-wrap;
 
white-space: -o-pre-wrap;
 
word-wrap: break-word;">void DrawGUI() { }
 
// Serves as an update function for script-defined GUIs</pre>
 
  
<pre style="white-space: pre-wrap;
+
All level scripts will have their <code>DrawGUI</code> functions called before any level script's <code>DrawGUI2</code> or <code>DrawGUI3</code> function is called.
white-space: -moz-pre-wrap;
+
----
white-space: -pre-wrap;
+
=== HasFocus function ===
white-space: -o-pre-wrap;
 
word-wrap: break-word;">void SetWindowDimensions(int width, int height) { }
 
// Allows a script-defined GUI to resize itself when the window gets resized</pre>
 
  
<pre style="white-space: pre-wrap;
+
<pre style="white-space: pre-wrap;">bool HasFocus() { return false; }</pre>
white-space: -moz-pre-wrap;
 
white-space: -pre-wrap;
 
white-space: -o-pre-wrap;
 
word-wrap: break-word;">void SaveHistoryState(SavedChunk@ chunk) { }
 
// Allows the level script to save extra undo state</pre>
 
  
<pre style="white-space: pre-wrap;
+
[[#List of level script hook functions|Optional]]
white-space: -moz-pre-wrap;
 
white-space: -pre-wrap;
 
white-space: -o-pre-wrap;
 
word-wrap: break-word;">void ReadChunk(SavedChunk@ chunk) { }
 
// Allows the level script to retrieve extra redo state</pre>
 
  
<pre style="white-space: pre-wrap;
+
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.
white-space: -moz-pre-wrap;
 
white-space: -pre-wrap;
 
white-space: -o-pre-wrap;
 
word-wrap: break-word;">bool HasFocus() { return false; }
 
// Old unused function.
 
// Reserved, though, so be careful to just make this function return false, and not use it for anything</pre>
 
  
=== Optional global functions ===
+
'''TODO''': Is this necessary with all types of UIs? How about Dear ImGui?
 +
----
 +
=== SetWindowDimensions function ===
  
These functions are optional, but will be called if they are present in <code>level.as</code>.
+
<pre style="white-space: pre-wrap;">void SetWindowDimensions(int width, int height) { }</pre>
  
<pre style="white-space: pre-wrap;
+
[[#List of level script hook functions|Optional]]
white-space: -moz-pre-wrap;
 
white-space: -pre-wrap;
 
white-space: -o-pre-wrap;
 
word-wrap: break-word;">void IncomingTCPData(uint socket, array<uint8>@ data) { }
 
// Optional - Networking hook for when network data comes in over a socket you've created</pre>
 
  
<pre style="white-space: pre-wrap;
+
Allows a script-defined GUI to resize itself when the window gets resized.
white-space: -moz-pre-wrap;
+
----
white-space: -pre-wrap;
+
=== SaveHistoryState function ===
white-space: -o-pre-wrap;
 
word-wrap: break-word;">void DrawGUI2() { }
 
// Optional - A second pass for updating script-defined GUIs, in case you need to do something with two passes
 
//  (e.g. transparent overlays, or layout)</pre>
 
  
== List of per-level script hook functions ==
+
<pre style="white-space: pre-wrap;">void SaveHistoryState(SavedChunk@ chunk) { }</pre>
  
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.
+
[[#List of level script hook functions|Optional]]
  
=== Required per-level functions ===
+
Allows the level script to save extra undo state.
  
These functions are required, and must be present in a per-level script file. If you have that script file in your mod you must include all of the following functions.
+
'''TODO''': Document how this works and why it is useful.
 +
----
 +
=== ReadChunk function ===
  
<pre style="white-space: pre-wrap;
+
<pre style="white-space: pre-wrap;">void ReadChunk(SavedChunk@ chunk) { }</pre>
white-space: -moz-pre-wrap;
 
white-space: -pre-wrap;
 
white-space: -o-pre-wrap;
 
word-wrap: break-word;">void Init(string level_name) { }
 
// Called when the level is first loaded.
 
// Be careful, this may be 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.</pre>
 
  
<pre style="white-space: pre-wrap;
+
[[#List of level script hook functions|Optional]]
white-space: -moz-pre-wrap;
 
white-space: -pre-wrap;
 
white-space: -o-pre-wrap;
 
word-wrap: break-word;">void Update() { }
 
// Called regularly by the engine so you can perform work.
 
// This function '''will not be called''' if the game is paused.
 
// It may be useful to do initialization once in this function, if you need objects or level script params to be present.</pre>
 
  
<pre style="white-space: pre-wrap;
+
Allows the level script to retrieve extra redo state.
white-space: -moz-pre-wrap;
 
white-space: -pre-wrap;
 
white-space: -o-pre-wrap;
 
word-wrap: break-word;">void DrawGUI() { }
 
// Serves as an update function for script-defined GUIs</pre>
 
  
<pre style="white-space: pre-wrap;
+
'''TODO''': Document how this works and why it is useful.
white-space: -moz-pre-wrap;
+
----
white-space: -pre-wrap;
+
=== IncomingTCPData function ===
white-space: -o-pre-wrap;
 
word-wrap: break-word;">bool HasFocus() { return false; }
 
// Old unused function.
 
// Reserved, though, so be careful to just make this function return false, and not use it for anything</pre>
 
  
=== Optional per-level functions ===
+
<pre style="white-space: pre-wrap;">void IncomingTCPData(uint socket, array<uint8>@ data) { }</pre>
  
These functions are optional, but will be called if they are present in a per-level script file.
+
[[#List of level script hook functions|Optional]]
  
<pre style="white-space: pre-wrap;
+
Networking hook function, for when network data comes in over a socket you've created.
white-space: -moz-pre-wrap;
 
white-space: -pre-wrap;
 
white-space: -o-pre-wrap;
 
word-wrap: break-word;">void ReceiveMessage(string message) { }
 
// 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.</pre>
 
  
<pre style="white-space: pre-wrap;
+
'''TODO''': Add better documentation for this function, or link to another page with better documentation.
white-space: -moz-pre-wrap;
+
----
white-space: -pre-wrap;
 
white-space: -o-pre-wrap;
 
word-wrap: break-word;">void IncomingTCPData(uint socket, array<uint8>@ data) { }
 
// Optional - Networking hook for when network data comes in over a socket you've created</pre>
 
  
<pre style="white-space: pre-wrap;
+
=== DrawGUI2 function ===
white-space: -moz-pre-wrap;
 
white-space: -pre-wrap;
 
white-space: -o-pre-wrap;
 
word-wrap: break-word;">void DrawGUI2() { }
 
// Optional - A second pass for updating script-defined GUIs, in case you need to do something with two passes
 
//  (e.g. transparent overlays, or layout)</pre>
 
  
== List of per-mod level script hook functions ==
+
<pre style="white-space: pre-wrap;">void DrawGUI2() { }</pre>
  
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.
+
[[#List of level script hook functions|Optional]]
  
=== Required per-mod functions ===
+
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).
  
These functions are required, and must be present in a per-mod script file. If you add this level hook script in your mod, you must include all of these functions.
+
<code>DrawGUI2</code> is called after <code>DrawGUI</code>, in case you need to draw on top of other UIs at those levels.
  
<pre style="white-space: pre-wrap;
+
All level scripts will have their <code>DrawGUI</code> functions called before any level script's <code>DrawGUI2</code> function is called. All level script's <code>DrawGUI2</code> functions will be called before any level script's <code>DrawGUI3</code> gets called.
white-space: -moz-pre-wrap;
+
----
white-space: -pre-wrap;
+
=== DrawGUI3 function ===
white-space: -o-pre-wrap;
 
word-wrap: break-word;">void Init(string level_name) { }
 
// Called when the level is first loaded.
 
// Be careful, this may be 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.</pre>
 
  
<pre style="white-space: pre-wrap;
+
<pre style="white-space: pre-wrap;">void DrawGUI3() { }</pre>
white-space: -moz-pre-wrap;
 
white-space: -pre-wrap;
 
white-space: -o-pre-wrap;
 
word-wrap: break-word;">void Update(int is_paused) { }
 
// Called regularly by the engine so you can perform work, or detect that the game is paused.
 
// It may be useful to do initialization once in this function, if you need objects or level script params to be present.</pre>
 
  
<pre style="white-space: pre-wrap;
+
[[#List of level script hook functions|Optional]]
white-space: -moz-pre-wrap;
 
white-space: -pre-wrap;
 
white-space: -o-pre-wrap;
 
word-wrap: break-word;">void DrawGUI() { }
 
// Serves as an update function for script-defined GUIs</pre>
 
  
<pre style="white-space: pre-wrap;
+
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).
white-space: -moz-pre-wrap;
 
white-space: -pre-wrap;
 
white-space: -o-pre-wrap;
 
word-wrap: break-word;">void SetWindowDimensions(int width, int height) { }
 
// Allows a script-defined GUI to resize itself when the window gets resized</pre>
 
  
=== Optional per-mod functions ===
+
<code>DrawGUI3</code> is called after <code>DrawGUI2</code> and <code>DrawGUI</code>, in case you need to draw on top of other UIs at those levels.
  
These functions are optional, but will be called if they are present in a per-mod level script hook file.
+
All level scripts will have their <code>DrawGUI</code> and <code>DrawGUI2</code> functions called before any level script's <code>DrawGUI3</code> function is called.
 +
----
 +
=== DialogueCameraControl function ===
  
<pre style="white-space: pre-wrap;
+
<pre style="white-space: pre-wrap;">bool DialogueCameraControl() { return false; }</pre>
white-space: -moz-pre-wrap;
 
white-space: -pre-wrap;
 
white-space: -o-pre-wrap;
 
word-wrap: break-word;">void ReceiveMessage(string message) { }
 
// 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.</pre>
 
  
<pre style="white-space: pre-wrap;
+
[[#List of level script hook functions|Optional]]
white-space: -moz-pre-wrap;
 
white-space: -pre-wrap;
 
white-space: -o-pre-wrap;
 
word-wrap: break-word;">void IncomingTCPData(uint socket, array<uint8>@ data) { }
 
// Optional - Networking hook for when network data comes in over a socket you've created</pre>
 
  
<pre style="white-space: pre-wrap;
+
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.
white-space: -moz-pre-wrap;
 
white-space: -pre-wrap;
 
white-space: -o-pre-wrap;
 
word-wrap: break-word;">void DrawGUI2() { }
 
// Optional - A second pass for updating script-defined GUIs, in case you need to do something with two passes
 
//  (e.g. transparent overlays, or layout)</pre>
 

Latest revision as of 07:31, 7 April 2018

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.

TODO: These level messages are handled in this script, this should be documented somewhere:

"clearhud"
"cleartext"
"disable_retry"
"displaygui"
"displayhud"
"displaytext"
"dispose_level"
"go_to_main_menu"
"loadlevel"
"make_all_aware"
"manual_reset"
"open_menu"
"reset"
"screen_message"
"start_dialogue"
"start_dialogue_fade"
"tutorial"

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:

  1. Per-mod level script
  2. Per-level script
  3. Global level script

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 ../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 ../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 .../Data/Scripts/your_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: ../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 level script hook functions

These functions are required. You must include all of these functions in a level script:

These functions are optional. These functions do not have to be added to a level script, but will be called if they are present:

Documentation for level script hook functions

Init function

void Init(string level_name) { }

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) { }

Optional

Called regularly by the engine so you can perform work, or detect that 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.

Note: If void Update(int is_paused) { } is not present in the level script, then void Update() { } will be called instead (if present, but only if the game is paused). This is a deprecated fallback function, and it is recommended to always use the is_paused variant.


ReceiveMessage function

void ReceiveMessage(string message) { }

Optional

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) { }

Optional

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) { }

Optional

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() { }

Optional

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; }

Optional

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) { }

Optional

Allows a script-defined GUI to resize itself when the window gets resized.


SaveHistoryState function

void SaveHistoryState(SavedChunk@ chunk) { }

Optional

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) { }

Optional

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) { }

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() { }

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() { }

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; }

Optional

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.