Script Types

Overview
When you create scripts in halo, they have one of at least four different types (More in Halo 2+). These types are the primary determinant of when scripts execute.

Startup
These scripts execute once, when the map has finished loading. Common uses are setting items up in a map, and for linear single player maps.

Example 1 - Spawning Additional Items in Multiplayer
(script startup detect_host (if (!= (unit_get_health random_vehicle) -1) (object_create_containing vehicle)) ;;If a named vehicle exists, this proves they are the host. If they are the host, ;;create every other object that has the word 'vehicle' in their name. )

Example 2 - Linear Single Player Mission
(script startup mission_assault (cinematic_start) ;;Cutscene (camera_set_dead enemy_commander) ;;Camera 3p around enemy character (camera_control 1) ;;Allows the camera to do that (sleep 120) ;;Displays for 4 seconds (cinematic_stop) ;;End cutscene (camera_control 0) ;;Return camera to normal (fade_in 0 0 0 60) ;;Fade in from black, 2 seconds. (sleep 60) ;; Wait 2 seconds before continuing. (ai_place enemy_squad) ;;Place enemy encounter (ai_attach enemy_commander enemy_squad) ;;Make that enemy character part of the AI (sleep_until (< (ai_living_count enemy_squad) 3) 150) ;;Wait until less than 3 of that AI are alive. ;;Checks every 5 seconds. (ai_place backup_squad) ;;Spawns more AI of a different group. (object_create_anew dropship) ;;Creates the dropship (vehicle_load_magic dropship "" (ai_actors backup_squad)) ;;Loads them into a dropship (recording_play_and_hover dropship entry_recorded_animation) ;;Plays a recorded animation. ;;When the animation ends, the ship hovers in place. (sleep (max 1 (recording_time dropship))) ;;Wait for the duration of the dropship animation. ;;If there was an error, wait at least 1/30th of a second, to prevent the script from breaking. (vehicle_unload dropship "") ;;Get the AI out of the ship. (sleep 150) ;;Wait 5 seconds. (vehicle_hover dropship false) ;;Stop floating idle (recording_play_and_delete dropship exit_recorded_animation) ;;Fly away and remove the dropship. (sleep_until (= (ai_living_count backup_squad) 0) 300) ;;Wait until AI are all dead. ;;checks every 10 seconds (game_won) ;;Tells the map that you have won. If the map name is one of the default ones, ;; it will progress to the next level. Otherwise... nothing. )

Continuous
These scripts will rerun themselves over and over again, until the end of the map. These are used for things you expect to happen more than once. You can, however, stop their execution if you so choose; this can be done with sleep commands, with a sleep of -1 to pospone indefinitely.

Example 1 - Basic Vehicle Teleporter
(script continuous basic_vehicle_teleporter (if (volume_test_object trigger_volume_a vehicle_01) (object_teleport vehicle_01 flag_b) (if (volume_test_object trigger_volume_b vehicle_01) (object_teleport vehicle_01 flag_a)) ) ;;This script checks if they are in volume a, if they are, teleport to cutscene flag b. ;;If they are not (and only if they are not), check if they are in B, and if so, teleport to A. ;;(if  ) ;;The way this script is, you cannot place flag_b inside trigger_volume_b, same with A. )

Example 2 - Randomized Background Fireworks
(global long run_count 0) ;;See Global Variables (script continuous run_500000_times (begin_random ;;Execute the following in a random order. (effect_new "effects\custom\firework" flag_01) ;;creates that effect tag, at flag_01 (effect_new "effects\custom\firework" flag_02) (effect_new "effects\custom\firework" flag_03) (effect_new "effects\custom\firework" flag_04) (effect_new "effects\custom\firework" flag_05) (effect_new "effects\custom\firework" flag_06) (sleep 60) ;;Wait 2 seconds. (sleep 60) (sleep 60) (sleep 60) (sleep 60) (sleep 60) ) (if (> 500000 run_count) (set run_count (+ run_count 1)) (sleep -1)) ;;If the run_count is less than 500,000, increase run_count by 1. ;;Otherwise, stop execution of this script. )

Dormant
These scripts will not run directly by themselves. They are executed, when called on by either tags, or other scripts using the wake command.

In UI_Widget_Definition tags, there is a slot labeled script under event handlers. Simply write the name of a script, and select the flag 'run scenario script'.

When dormant scripts are ran through other scripts, they can only run a single time, however if you only run the script through a Widget, you can run them infinite times. When using a widget, the script will only run on the PC who triggers it. Unless it is something that clients only use for their own personal preferences that do not effect others, it should be restricted so only host can click it. Setting the function "mp game options open" is an effective way of making it disabled on clients.

Example 1 - Device Power for Widget (Matches Picture)
(script dormant powerbutton (device_set_power my_device 1);;Set a device's power on. )

Example 2 - Waking Dormants from Scripts
(global boolean cliff_wave false) ;;See Global Variables (global boolean river_wave false) (script dormant cliff_waves (ai_place cliff_wave_1) ;;Spawn AI (sleep_until (< (ai_living_count cliff_wave_1) 3) 150) ;;Wait until less than 3 are left alive. (ai_place cliff_wave_2) ;;Spawn AI (sleep_until (< (ai_living_count cliff_wave_2) 3) 150) ;;Wait until less than 3 are left alive. (set cliff_wave true) ;;Set global variable to True. ) (script dormant river_waves (ai_place river_wave_1) ;;Spawn AI. (sleep_until (< (ai_living_count river_wave_1) 3) 150) ;;Wait until less than 3 are left alive. (ai_place river_wave_2) ;;Spawn AI. (sleep_until (< (ai_living_count river_wave_2) 3) 150) ;;Wait until less than 3 are left alive. (set river_wave true) ;;Set global variable to true ) (script startup missions (ai_place first_enemies) ;;Spawn AI. (sleep_until (= (ai_living_count first_enemies) 0) 150) ;;Wait until 0 are left alive. (wake cliff_waves) ;;Begin execution of dormant script, cliff_waves ;;This does not effect this scripts execution, it continues while cliff_waves executes. (wake river_waves) ;;Begin execution of formant script, river_waves. (sleep_until (and cliff_wave river_wave) 150) ;;Waits until global variables, ;; cliff_wave and river_wave, are both true. (game_won) )

Static
If you've done other programming before, you can think of these as functions, or methods. Otherwise, you can treat these like shortcuts; if you need to do something a number of times, or get the results of a compilation from multiple places, it is easier to have it performed in one place. This means, that if you ever decide to change anything, you only need to change it in one place, instead of multiple places.

Since this script type can return results, it requires you give it a Data Type. If you are not expecting any data to be returned, just leave it as Void.

Example 1 - Shortcut to Player 0
(script static unit player0 (unit (list_get (players) 0)) ;;Returns the first player. ;;The play can now just type (player0) instead of the above. ) (script startup idk (sleep_until (< (unit_get_shield (player0)) 1) 5) ;;Wait until P0's shields aren't full (sv_say "Player 0's shields are damaged!") ;;Have the server declare it in the chat. )

Example 2 - Performing a Calculation
(global short var1 0) ;;Global Variable ;;Input 1 (global short var2 0) ;;Global Variable ;;Input 2 (global real result1 0) ;;Global Variable ;;Result as a decimal number (global short result2 0) ;;Global Variable ;;Correct result. (script static short modulus ;;Returns a 'Short' (Non-decimal number, within 2^16) (set result1 (/ var1 var2)) ;;Get decimal of input1 / input2 (set result2 (/ var1 var2)) ;;Get non-decimal copy of input1 / input2 (set result1 (- result1 result2)) ;;Difference between decimal and non-decimal (less than 1) (set result2 (* result1 var2)) ;;Difference * input 2, without decimals (set result1 (* result1 var2)) ;;Difference * input 2, with decimals (if (!= result1 result2) (set result2 (+ result2 1))) ;;If data was lost in decimals, restore rounding. (+ result2 0) ;;Return result2 variable. ) (script startup idk (set var1 16) ;;set input1 as 16. (set var2 (list_count (players))) ;;Input2 as the number of players (Counting from 1) (fade_in 0 0 0 (modulus)) ;;Fade in from black, at the speed of '16 mod (player count)' )

Stub
Stubs are made to be overwritten by other scripts. If you've done C programming, you can recognize these as method headers that we predeclare. These follow the exact format of Static scripts.

The benifit these scripts give us, is primarly the pre-declaring scripts, but mostly the ability to perform recursion with scripts.

Example - Modulus Recursive
(global short in0 0) (global short in1 0) (script stub short modulus ;;This here is garbage, it's just to let sapien know ;;that a script called modulus that returns a short, exists. ;;Without this, the static script would have an error that 'modulus' is undefined. (+ 0 0) ;;Returns a number. This'll always return 0. ) (script static short modulus (if (< in0 in1) (+ 0 in0) ;;If in0 is smaller than in1, return in0. (begin (set in0 (- in0 in1)) ;;Otherwise, reduce in0 by in1. (modulus) ;;Then repeat this. )) )

Command_Script (Halo 2+ Only)
In halo 2 onwards, Command Lists where removed from the scenario tag. These are their replacements. They define set actions that an AI will take, without referencing the AI itself. Then, either through the Scenario tag, or another script, it will be applied to an AI.