Scripting Gameplay Elements

Jun 14, 2021
Scripting Gameplay Elements
  • This information was compiled for your use as a reference and learning resource. Please keep in mind that Halo 5 Forge updates over the years, including but not limited to the huge Monitor's Bounty update, means you may find information that is no longer relevant or was modified in an update. We're working to get this info up-to-date. Feel free to contact staff if you find deprecated information, when they can forward your concern to the appropriate team for correction.

    Don't forget to check out the Scripter's Resources page for more gameplay and gametype help.


    In Halo 5 Traits are included in gametype options. To use these traits in custom games you have to apply them to players using the Trait:Apply Action with scripting. You do not have to clear one trait before applying a different one, because they do not stack. However, know that traits alpha-delta run based off whatever you've chosen in the base traits section, so any percentages you use in alpha-delta will be percentages of those base traits that you have defined.

    It is important to realize that you cannot use any settings in your alpha-delta traits that you have not defined as usable in your base trait, meaning Default settings set to OFF or 0% are not usable. For example, if you have not turned ON "Deathless" in the Default trait, it will not work in your alpha-delta traits. If you only want one player to sometimes have Deathless, you will have to use one of your alpha-delta traits as your "default" trait and turn it OFF there, then give that trait to all your other players.

    Traits are extremely unreliable when used repeatedly (with Timer Check or other loops), and will stop working completely if they are changed too often. This is a bug in Halo 5. It has been discovered that the best way to apply traits is to change a player number with a boundary or whatever, then have a Number Check script run the Trait:Apply when that number triggers it.

    Here is a Google doc you can use that is set up to look like the traits section of the Halo 5 Custom Games menu. It has all the default settings logged in, so all you have to do is record your changes.
    Gametype Traits Settings Template

    Scripting Objective Objects (Flag, Ball, Skull, Strongholds(top)

    General Game Modes Information(top)

    You can enter scripts into the Ball [only] and Flag [only] objects. You can prevent players from picking them up by using Traits in minigame with no weapon pickup. but applying the trait once players have picked them up won't make them drop these objects. You can also set some objects and players as objective spawns or returns using mods.

    The generated ball and flag that spawn on the sportsball:spawn and flag:spawn plates only in those modes in custom games can still be affected by some scripts using the sportsball: object and flag: object mods. These "generated" objects will also take on the team property of whichever team is carrying them, so Team mods will apply when carried (Team[include]1/2 etc, TeamTHIS[include], etc). Strongholds also get the team property of whichever team has control of them. Keep in mind attempts to add or remove navs from these objects can result in ALL navs breaking in these game modes.

    See a detailed breakdown of game mode options in the Halo 5 Scripting Reference Game Mode tab:

    Ball General Information(top)

    • Players don’t drop the ball when interacting with objects like switches
    • The ball has a whopping 1,000,000 health at 100%, which only seems affected by Damage Ratio scripts, not player damage such as shooting it, Fire FX, or explosions. (thanks SirScoundrel!)
    • When a ball is not held, it receives damage from Damage Ratio and is destroyed when its health reaches zero
      • Any damage done with the Damage Ratio action (even 0.10, which is 1,000 health) while the ball is held seems to kill the player, but the ball remains, seemingly undamaged
    • The built-in ball scoring explosion FX occurs where the ball is when it's destroyed or despawned (the Assault mode area damage does not occur)
    • Currently there is no known way to remove the ball from a player's hands other than them dropping it, scoring it, or by killing the player

    Game-Generated Ball - sportsball:spawn(top)

    • Will not display scripted navs
    • Like the Ball [only] object, this ball can be selected using the sportsball:surprise:bject label in mods, for TRACKING, changing spawn order, labels, etc. even before it's picked up off spawn plate
    • In the Assault game mode, this ball takes on the Team property of the carrier who holds it, selectable in mods (not so with Ball [only] object)
    • Does not respond to "Despawn" (Ball [only] object does)
    • Instantly respawns (no explosion) when dropped in a Kill Zone or Timed Kill Zone (this doesn't work for Ball [only])
    • Kill Zone also despawns the "Ghost Ball" on spawn plate, but doesn't stop "Incoming" nav
    • When thrown point settings are on (as in Ricochet settings), the "Ghost Ball" over a Ball Spawn Plate will arm if it's placed in a Ball Return score zone but not explode. Then it will crash the game!
    • You can script the game-generated ball to Phased, but it returns to its Normal behavior after a few ticks. If you script it to Phased repeatedly, you can keep it in a Phased condition. You can still pick it up.
    • The game-generated Ball can be removed from a player & despawned by teleporting the carrier to an out-of-bounds region of a map. Some maps have out-of-bounds regions that cause players to respawn instead of killing them. This forced player respawn technique (affectionately named the YEET technique) can be used to despawn a game-generated ball without killing the carrier.
      • This solves the GOTCHA for multi-round ball game modes (especially Grifball) by despawning the ball just before time runs out so that the current ball doesn't interfere with the next round's ball spawning process

    Ball/Skull [only] Forge Objects(top)

    • Automatically has the sportsball:surprise:bject label in object properties when added in Forge (the generated ball responds to this label, as well)
    • Will despawn remotely when this label is used (the game-generated ball will not)
    • Unlike the generated ball, this one does NOT get a team property when picked up
    • This one will stay Phased when you script it, until it's picked up, then it acts like normal physics
    • A standard Ball Return (with the sportsball:include & sportsball:return labels) doesn’t score the Ball/Skull [only] or any built-in game mode events when a player carries the ball into its zone
    • Explodes when you despawn it with scripts
    • If a Ball/Skull [only] object is despawned during a ball mode match, it will respawn whenever a game-generated ball spawns in, even if you've removed its sportsball:surprise:bject label
    • Damage Ratio scripts destroy the ball, but if a player is holding it this kills the player, even at the lowest setting. If carrier has Deathless trait (invincible), Damage Ratio does nothing to the ball and player.

    Skull [only] Specifics(top)

    Skull ball seems to move slower than other objects, regardless of set Move:Offset time, and can fail to reach end destination, stopping partway there. Therefore, longer move times will probably be necessary on longer moves. Keep this in mind also if they keep getting stuck under ground in normal physics, when moving them into a position through landscapes.

    In Forge, Skull Ball successfully reverts back to original label and physics property when despawned then spawned. Keep in mind once physics are made normal, wherever it is at that point becomes it's new "default position", and it will respawn there instead of back at it's original spawn location. A workaround is to create a TARGET at the original spawn and just use a terminal with Message Send to trigger it to return to it's default position while building your map.

    Additional Ball Information(top)

    Any objects set to be ball returns are defended by the team they're assigned to & all enemies can arm + score. Anyone can score on a neutral ball return. Ball return objects won't spawn if no members of its team are there to defend it. (Some lights from a scorpion welded group did spawn without the rest of it and I collided with stuff there, so that could be checked out.) Only tested for teams 1 & 2. Guessing if more teams are allowed, then players can score on any goal that's not their own.

    There's only one ball at a time, so it's always a neutral element. If there are multiple objects set to spawn balls (add sportsball:include and sportsball:spawn to the object's Game Mode Labels), the ball spawn location will cycle thru the spawn objects starting with the oldest one (verify). Ball Spawn object Team colors change to white when the ball spawns on them, as if they become neutral.

    Kill zones are made visible (including symbols) by making them a ball return. They have a "Defend" or "Attack" waypoint. The ball resets when thrown into it (timed kill zones were used), which could be an interesting dynamic as throwing scores wouldn't work and drops in the enemy zone would cause an instant reset which usually would be a disaster. Other zones might work as well. They can be used as waypoints or interesting decorations.

    Scorpion didn't seem to work as ball return zone. Vehicles display a waypoint, and the ball spawns below the vehicle, but the boundaries don't seem to show up on the map. Vehicles do seem to act as ball spawns. They tend to carry the ball placeholder under them.

    When the Mantis is a ball spawn, it protects the ball between its feet like a male penguin. Players can't reach the ball while the Mantis squats over it. If players from opposite teams got to the Mantis at the same time, they'd have to choose between getting in the Mantis, or waiting for another player take the Mantis and either grabbing the ball as it stands up or attacking it.
    Penguin Daddy Mantis video on waypoint

    If a weapon is given the sportsball:spawn label it will spawn the ball in ball modes. If a player is holding the weapon and the ball is spawned at the weapon but not picked up, the ball (placeholder) spawns over the player's head and stays there if the player moves (it then keeps bouncing down to the ground, likely an example of local xbox showing gravity then resetting the position after an update from the server, after the Xbox checks in with server when collision with ground happens). Doesn't matter if the player holds the weapon-ball-spawn or if it's swapped. If the ball spawn is a weapon a player is holding while in a vehicle and the ball spawns, the ball placeholder spawns at the player's position and stays there (and bounces!). This hasn't been tested much.

    Looks like if the placeholder is inside any return zone, it repeatedly acts as though it fills the timer then scores & explodes. It resets to the same current spawn object. Could provide for some startling amusement. Player holding weapon that's the current ball spawn while in his own return zone - waypoint video

    Scripting Players(top)

    Detecting Players(top)

    Spartans have a location that acts similarly to the point of origin on objects, which must pass a boundary to be detected. You can make tiny boundaries on weapons and some vehicles that are very unlikely to be triggered by anyone unless they are using them. Following is the player Spartan location detection point/height to 2 decimal places:

    Standing: 3.62
    Crouched: 2.50

    Accessing Player Channel Numbers and Game Values(top)

    The ONLY place to retrieve PLAYER CHANNEL NUMBERS & GAME VALUES is from Number Change, Score Change, or Spawn Order Change, but only if the condition defines ACTIVATOR so the option Object=ACTIVATOR appears

    Learn more and see examples here.

    Game Settings Options List(top)

    • Shield/Health Percentage
    • Shield/Health Recharge Speed
    • Shield/Health Recharge Wait Time
    • Shield/Health Vampirism
    • Damage Resistance
    • Deathless keeps players from dying but doesn't stop them from taking damage until they have no shields or health
    • Sheild HUD Visibility, Shield Effects, Damage Indicators

    Shields and Health(top)

    • The Damage Ratio script damages health not shields
    • The Damage Ratio script action does reset both the player shields and health regen wait timers (confirmed for Forge, need to confirm for Customs)
    • There doesn't seem to be a way to add shields or health back using scripting
    • There doesn't seem to be a way to keep health level using only Damage Ratio without reset the regen timers
    • To read player shields and health (also number values), use a condition that has ACTIVATOR or EXTRA mods (Number Check, Boundary Check, Interacted, Message Send, Power Set) and read the values from the Number or Game Value options of Number/Score/Spawn-Order Check

    Scripts on Players Leaving, Joining(top)

    • Player numbers are retained if you exit a match and return before it ends.
    • This can be cleaned up in the first 4sec of quitting the match, but that is hard to detect specifically.
    • First() of a player is seemingly retained if you leave and rejoin as well.
    • The second player in the mod list would be considered "first" until the original first shows back up in the mods list, at which time they appear to always win.
    • BUT if both players die and original "first" has no bodies on the map, the second player will be considered first until their bodies are cleared from the map, even if the original "first" has respawned.

    Scripts and Spartan Dead Bodies(top)

    • Conditions like Boundary Check and Number Check generally treat dead Spartans the same as live ones
    • Actions such as Move:Offset can use the Dead[exclude/include] mod filters to either target the live or dead copy of a Spartan after filtering the Spartan by using a unique label added to the player or a unique value assigned to their alpha channel number (using the Number mods)
    • Living Spartans and bodies/ragdolls are separate objects on the map. A player can have 0-1 Spartan and 0-3 bodies on the map at one time, so their player object count can total 0-4.
      • The Players [add] mod will add all Spartans and bodies
      • The Dead [exclude] mod filters out bodies and can reliably tell us which players are currently alive/spawned
      • The Dead [include] mod filters out living Spartans and can reliably select only bodies... However, it can't tell us which players are still dead since bodies can still be on the map after players respawn.
      • A simple technique to mark players that are dead and haven't respawned is to use a label or player number channel to: 1️⃣ mark bodies using Players[add], Dead[include] then 2️⃣ remove that label or number from respawned players using Players[add], Dead[exclude]. This works because labels & numbers are shared between a player's Spartan and bodies.
    • Scripts with a Number Check condition for Player Numbers define/populate the EXTRA mod, but EXTRA will not return dead bodies, only live ones (Player Numbers can be changed by selecting bodies & the Number Check condition does trigger, but EXTRA doesn't select players who aren't currently spawned)

    Traits Using Percentages(top)

    • The settings that are represented with percentages seem to be multiplied with each other when applied to players, default settings x more specific category or trait
    • Toastman found a glitch where some of the % settings were multiplied repeatedly when using Trait: Add with a repeating Timer Check condition
    • Damage % changes seem to apply to the weapon so they affect the damage done to players and objects

    Learn more about reading player info here.

    Scripting Initial & Respawn Locations(top)

    Spawn Order
    • Spawn order does not reset on rounds.
    • Spawn order prioritizes the lowest spawn order first. This will even over write spawn zone influence
    • If there are no valid spawns of an order the next order is then looked for.
    • Any valid spawn is a spawn that does not have something physically blocking the spawn. This does not include line of sight
    • For a spawn to be used during a match it must be valid when the map loads. If it is blocked before the match starts then becomes unblocked it will still remain invalid
    • Testing has not been able to force players to spawn by changing their spawn order. Instead try changing the game label of spawns and the player to try and trigger it that way.
    • With players, it seems only the default player SpOrder of 0 has the "choose lowest available SpOrder" behavior. Once player SpOrder is set, they only respawn at plates with that specific SpOrder. Default behavior won't return once SpOrder is set. In Forge, player SpOrder gets reset to default when they can't respawn to a specific SpOrder. That makes it hard to properly test how it'll really work in customs.
    • The default player SpOrder reads "255", but changing it to 255 doesn't bring back the default behavior. We can write signed 16-bit values (-32768 to 32767) to a SpOrder, but they get interpreted as unsigned 8-bit (0 to 255) values... -1 becomes 255 (not the default though) and 256 becomes 0.

    Spawned and Despawned List
    • Can't add scripts directly to them
    • Can't use Action Targeting on them (add a label, use Label [add])
    • Except when they're part of a group, then using Group Siblings [add] works
    • Can manipulate them some in Forge (Navpoints, Move Offset, Rotate Offset, Spawn Order Change)
    • Postition/Rotation Reset didn't work at all
    • In Customs, they can be Action Targeted enough to add to the Object Count of objects in the group. I could use Spawn Order Change to change one to Order 64 and then the Object Count got lower by one since I added Order [exclude] 64. But since Navpoints didn't work on them, I couldn't tell if Move or Rotate worked.
    • Should try having something visible Move-Target one of them to see if they're there and movin

    Scripting Inventory Objects: Weapons, Grenades(top)

    You can use scripts to add labels and change the spawn order of weapons that players spawn with. When a player is holding a weapon, that weapons Team property is automatically changed to the team that player is on, and the weapon can be filtered using Action mods (Team[include]/[exclude] etc).

    When you pick up a map weapon that is part of a group, just the weapon becomes part of the player inventory (it gets detached from a group). This is why "Inventory" could be a potential column for the Scripting Options Sheet. It would include items that disappear and reappear when used by the player, but the objects are different representations (part of the player animations instead of free objects). For weapons, the game doesn't erase its internal object and scripts still apply to it unless another copy gets respawned & then the new one inherits the scripts. The (Destroyed) condition doesn't fire when the player picks it up, though it does trigger if all its ammo gets picked up.

    Grenades, on the other hand, do immediately trigger (Destroyed) when picked up. The programming is a bit different possibly due to player inventories being able to have multiple grenades of the same type. It's much simpler to represent grenade inventory with an integer variable for each type of grenade rather than have a container that holds multiple grenade objects.

    When a player dies and drops their grenades, they are new copies of the grenades they picked up and will not have any scripting that was added to the original grenades.

    Despawning Held Weapons(top)

    The last update disabled despawning weapons held by players, so here's a workaround:

    Spawn 2 items, preferably invisible/collisionless. Weld them together.
    Select the 2 items you just welded and the weapon you wish to force-despawn. Tap up on the D-pad (or G on PC). This adds the weapon to the welded group. Make sure one of the 2 original welded items is set as the parent.

    When a player is holding the weapon, you can remove it by despawning the parent object.

    Notes, Observations, Suggestions(top)

    Vehicles or turrets might not qualify as "inventory" items since they can't disappear into the player inventory. Maybe those plus inventory items would qualify as "Possessions" or something. Not sure what would happen to a turret that's in a welded group that gets picked up. For fixed turrets, there's the stand and the weapon so it's much like it's already a weapon welded to a stand object. Would objects welded to one would be stuck to the stand? Does a detached turret act just like a normal weapon except we can't swap it into our inventories?

    Weapons that are welded to a group (not the parent) can be picked up and moved around by the player. When dropped, they are added back to the group at the location where dropped. (Do we need to verify this?)
    Inventory "Keys"

    It might be possible to use individual weapons as some kind of "key" that can be added to a player's inventory and carried around and used to unlock something.

    Weapons that instantly deal large damage could be used on an object with big health and (Health) scripts that can tell the difference between large and small damage.

    A Gungoose can be driven right up against a destructible and fired to damage both the goose and destructible at the same time.

    Scripting FX(top)

    To control when an FX appears, you can use the following method:

    Use Script 1 to activate the FX when you want it to show up
    Script 1: Condition: Message {activate}
    A1: Spawn ON
    A2: Number Change: Object (THIS) Set Constant 1
    Use Script 2 to make sure the FX shows up only when you activate it with Script 1
    Script 2: Condition: Spawned
    A1: Despawn (THIS, Number [exclude] 1)
    A2: Number Change: Object (THIS) Set Constant 0
    A3: Wait {2.00}
    A4: Despawn (THIS)


    All the Powerups are scriptable using Interacted or Despawned, not just the ones that say "Scriptable". The regular ones have the default Powerup effects, but the "Scriptable" ones don't. You can stop the Powerup pickup animation by using the Despawn Action with the Interacted Condition. This will cancel the animation of the player putting it to his/her chest. Add a Wait action to delay cancelling the animation.

    Scripting and Match Rounds Gotchas and Fixes(top)

    Starting in round two, some Conditions will not work or will not work correctly at the beginning of rounds. The reason seems to be that objects don't truly respawn once a game has loaded. For example, after a match starts the When Spawned Condition doesn't work correctly at the beginning of successive rounds. And, when using the trick below to get objects to despawn after a round ends, the object remains despawned after the next round starts.

    A workaround for scripts that won't work at Round Event:End that I found is to use an Action that sends a message, then trigger your script when that message is received. This seems to bypass the interruption that Round End causes to scripts. It works for information scripts, like number changes and spawn/despawn, but has not been tested on move scripts yet.

    Round and Condition interrupt must be off on both the message send and the script receiving it, and since objects don't truly respawn on rounds, if you use this trick to despawn an object at the end of a round it won't be there on the next round. You can get it to spawn in by using the Round Event:Start Condition.

    Switching to Round Event:Start is another way to get around the Spawned Condition weirdness on rounds. But there is a weird bug with Global numbers when working on Static Weapons where they might not work. The fix for this is to turn Force Dirty ON, even if they've already been dirtied by a number change. Though they don't truly respawn on rounds it's possible objects "load" twice during the transition for rounds, and this is why Force Dirty must be on. For some reason, this doesn't happen with object numbers. It hasn't been tested with Team numbers.

    Round weirdness doesn't just affect our scripts. When using the ball spawn object, the sportsball spawns in fine first round, but in successive rounds can glitch, repeating the ball incoming over and over. During testing to see if we could find a workaround, Yumudas noticed that it only happens if the ball is on the field when round ends. Making sure the sportsball is destroyed or despawned before the round ends prevents this from happening every time.
Yumudas Beegbut likes this.