Format String
Halo: Reach's scripting engine supports the display of "format strings." A format string can be a simple piece of text, but it can also include little placeholders that will automatically be replaced with other values (the format string "parameters") when the string is displayed. Up to two additional parameters can be provided after the format string itself.
A percentage sign (%
) marks the start of a placeholder; the
content after it determines the type of placeholder to use, and in some
cases, the options to use for the placeholder. If you want to write an
actual percentage sign in text, you must type %%
. Using a
placeholder symbol incorrectly (including by writing just one %
symbol) will cause Halo: Reach to refuse to display your string.
Examples
Here's an example of how to use format strings: this code, taken from Slayer, displays the number of points needed to win if the game variant has a score limit.
for each player do if game.score_to_win != 0 and game.teams_enabled == 1 then current_player.set_objective_text("Kill players on the enemy team.\r\n%n points to win.", game.score_to_win) end if game.score_to_win != 0 and game.teams_enabled == 0 then current_player.set_objective_text("Score points by killing other players.\r\n%n points to win.", game.score_to_win) end if game.score_to_win == 0 and game.teams_enabled == 1 then current_player.set_objective_text("Kill players on the enemy team.") end if game.score_to_win == 0 and game.teams_enabled == 0 then current_player.set_objective_text("Score points by killing other players.") end end
Persistent strings
Some functions treat format strings as persistent. This means that those particular strings can't be used to display "transient" variables — that is, any variable whose value will likely be reset before the frame is over, like the current_player or killer_player variables.
The game.show_message_to function is an example of a non-persistent string:
for each player do if current_player.number[0] == 1 then game.show_message_to(all_players, "%s won the game!", current_player) current_player.number[0] = 0 end end
When that function runs, it will immediately substitute your format string parameters into the format string, and it will pass the resulting text to the kill feed, which remembers that text. This means that for the case above, your kill feed message will always display whatever player was current_player at the time the function was called.
The widget.set_text function is an example of a persistent string:
script_widget[0].set_text("%s won the game!", global.player[0])
When that function runs, it doesn't immediately substitute out your
placeholders. Instead, it remembers the format string, and it remembers which
variables you passed as format string parameters — not the variables'
values, but the variables themselves. Every frame, the HUD widget
will take the format string and substitute out %s
for the name
of whatever player happens to be the one referred to by global.player[0]
on that frame. If that variable's value is changed, the HUD widget will update
in real time.
This is why transient variables can't be used with persistent strings: their values don't last through a whole frame, so when the HUD widget (or object waypoint or similar UI) redoes the format string substitution, the variables won't have the values you intended.
If you want players to see their own names (or variables) in a persistent string, then use variables like local_player.
Placeholder codes by type
Different placeholder codes are intended to format different kinds of information. If you pass a value of the wrong type (e.g. passing a player variable for a placeholder meant for numbers), then you'll see a default value which varies depending on the placeholder code.
If you don't pass any value at all, then the placeholder will be cut out of the string, but the string should still display as long as the placeholder itself was valid.
Integer number
- %n
- %o
- %p
- %s
- %t
-
All of these codes print the number normally, as you would expect.
Default result:
0
Object
- %n
- %o
- %p
- %s
- %t
- Displays the name of the object as defined in the map file. Note
that most objects don't have actual names defined, and will instead
display
unknown
.
Player
- %n
- %o
- %p
- %s
- %t
- Displays the player's Xbox LIVE gamertag.
Timer
- %n
- %o
- %p
- %s
- %t
- Displays minutes and seconds, separated with a colon and with
the seconds padded to two digits, e.g.
0:05
.
Unknown
- %c
- Sometimes, this fails as an error and prevents the string from being displayed. Other times, it produces a line break followed by the number 25. Notably, in ASCII, the number 25 is used to encode the percentage sign.
- %d
- %i
- %u
- %x
- %X
-
Seems to always produce
1
, no matter what you pass in.In the C and C++ programming languages, these codes are used to format integers. You can put additional settings between the percentage sign and the number, in order to pad the number to a certain length using spaces or zeroes. Those settings work here, but they always act as if you passed in the number 1;
%03d
, for example, always produces001
. - %S
- %Z
- Crashes the game instantly, when displayed.
Decimal number
Format codes exist for decimal numbers, but it's not clear why. None of the variable types available to Megalo are decimal numbers, and these codes don't work for timers (except when timers have special meanings for them).
These codes seem to be meant for double-precision floating-point values.
- %a
-
Prints the number in hexadecimal (base-16) format.
Default result:
0x0.0000000000001p-1022
- %A
-
Same as
%a
, but the result uses all-caps.Default result:0X0.0000000000001P-1022
- %e
-
Prints the number using scientific notation.
Default result:
0.000000e+00
- %f
-
Prints the number out to six significant figures.
Default result:
0.000000
- %g
-
Prints the number out to exactly as many decimal points as is
necessary if the number has fewer than six significant digits
before the decimal point and fewer than four after; otherwise,
uses scientific notation like
%e
does.Default result:0