Difference between revisions of "LevelScripts"

From Wolfire Games Wiki
Jump to: navigation, search
(One script per-level (some_dir/something.as, defined by Edit -> Set Level Script...): clarified writing)
(Script Tiers: Simplified headings and clarified text)
Line 11: Line 11:
 
The order that the engine calls into level scripts is as follows:
 
The order that the engine calls into level scripts is as follows:
  
==== level.as (in the file <code>Data/Scripts/level.as</code>) ====
+
==== Global level script ====
 +
This script file is located in <code>../Overgrowth/Data/Scripts/level.as</code>.
  
 
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.
 
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.
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.
  
==== One script per-level (<code><script>some_dir/something.as</script></code>, defined by '''Edit -> Set Level Script...''') ====
+
==== 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.
 
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.
  
Line 25: Line 25:
 
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.
 
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.
  
==== One script per-mod (<code><LevelHookFile>some_dir/something.as</LevelHookFile></code>, inside each mod's mod.xml file ====
+
==== Per-mod Script ====
 +
Many of these scripts can be active at the same time, but each mod can only have one.
  
Many of these scripts can be active at the same time, though only one such script can be defined for each mod that you have active.
+
To use this script file you have to manually add the following XML tag the mod.xml that you make for your mod: <code><LevelHookFile>some_dir/something.as</LevelHookFile></code>
  
You have to manually add this XML tag the mod.xml that you make for your mod. Functions in this script are run for every level in the game, and every mod can add their own level hook script.
+
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.
 
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.

Revision as of 10:44, 25 July 2017

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 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. Data/Scripts/level.as

If you're doing a per-mod level script, then you have the most flexibility of where you put your files. Still, it is best to follow a standard convention so that it is easier to find said script in other people's mods. Merlyn recommends:

  • your_mod_name/Data/Scripts/your_mod_name/level_hook.as

If you're trying to alter existing files, then you're more stuck.

For an override for (<script>some_dir/something.as</script> (a per-level script) you must put your script file here:

  • your_mod_dir/Data/Scripts/some_dir/something.as, with the specific directory dictated by the path defined in the level's XML file.

For an override for Data/Scripts/level.as (replacing the base level script) you must put your script file here:

  • your_mod_dir/Data/Scripts/level.as

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:

  1. On Windows: My Documents\Wolfire\Overgrowth\aslevel_docs.h
  2. On Mac: ~/Library/Application Support/Overgrowth/aslevel_docs.h
  3. On Linux: ~/.local/share/Overgrowth/aslevel_docs.h

The list of available functions, classes, and object instances 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.

List of Data/Scripts/level.as hook functions

Required in Data/Scripts/level.as

These functions are required, and must be present in level.as. If you override that file in your mod, you must include all of these functions.

 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.
 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.
 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.
 void HotspotExit(string str, MovementObject @mo) { }
 // Triggered when any hotspot is exited by a movement object
 void HotspotEnter(string str, MovementObject @mo) { }
 // Triggered when any hotspot is entered by a movement object
 void DrawGUI() { }
 // Serves as an update function for script-defined GUIs
 void SetWindowDimensions(int width, int height) { }
 // Allows a script-defined GUI to resize itself when the window gets resized
 void SaveHistoryState(SavedChunk@ chunk) { }
 // Allows the level script to save extra undo state
 void ReadChunk(SavedChunk@ chunk) { }
 // Allows the level script to retrieve extra redo state
 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

Optional in Data/Scripts/level.as

These functions are optional, but will be called if they are present in level.as.

 void IncomingTCPData(uint socket, array<uint8>@ data) { }
 // Optional - Networking hook for when network data comes in over a socket you've created
 void DrawGUI2() { }
 // Optional - A second pass for updating script-defined GUIs, in case you need to do something with two passes (e.g. layout)

List of per_level_script.as 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.

Required in per_level_script.as

These functions are required, and must be present in <script>some_dir/per_level_script.as</script>. If you override that script file in your mod, or override the level file, you must include all of these functions.

 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.
 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.
 void DrawGUI() { }
 // Serves as an update function for script-defined GUIs
 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

Optional in per_level_script.as

These functions are optional, but will be called if they are present in <script>some_dir/per_level_script.as</script>.

 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.
 void IncomingTCPData(uint socket, array<uint8>@ data) { }
 // Optional - Networking hook for when network data comes in over a socket you've created
 void DrawGUI2() { }
 // Optional - A second pass for updating script-defined GUIs, in case you need to do something with two passes (e.g. layout)

List of per_mod_script.as 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.

Required in per_mod_script.as

These functions are required, and must be present in <LevelHookFile>some_dir/something.as</LevelHookFile>. If you add this level hook script in your mod, you must include all of these functions.

 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.
 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.
 void DrawGUI() { }
 // Serves as an update function for script-defined GUIs
 void SetWindowDimensions(int width, int height) { }
 // Allows a script-defined GUI to resize itself when the window gets resized

Optional in per_mod_script.as

These functions are optional, but will be called if they are present in <LevelHookFile>some_dir/something.as</LevelHookFile>.

 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.
 void IncomingTCPData(uint socket, array<uint8>@ data) { }
 // Optional - Networking hook for when network data comes in over a socket you've created
 void DrawGUI2() { }
 // Optional - A second pass for updating script-defined GUIs, in case you need to do something with two passes (e.g. layout)