scmJS docs

Text

Texts with values#

displayText and print take a template literal, or texts joined with +, with the program's numbers in it, name(p) and color(p):

program(() => {
  let wave = 3;
  displayText(`${color(P2)}${name(P2)}\x01 has ${minerals(P2)} ore — wave ${wave + 1}`);
  print(`Wave ${wave}`, { to: AllPlayers, position: "center" });
});

name(p) is the player's name and color(p) the colour code of their colour, both filled in by the game; the ordinary colour codes work as ever. displayText shows the text to the current player. print(text, { to, position }) shows it to someone else (a player, AllPlayers or a force), or, with position: "center", on the line in the middle of the screen where the game's own messages appear. A boolean in a text is true or false. A program's texts never take a string of the map you edit: the build gives them strings of their own.

A text is a value#

string is a type of a program as number is. A variable holds one, a function takes and returns one, a record has one as a field, and there is no length to declare.

program(() => {
  let wave = 3, left = 12, shown = "";
  let title = wave > 10 ? "Late game" : "Early game";   // texts written in the script
  let line = `Wave ${wave}: ${left} left`;                // a text made in the game
  line += "!";
  if (line != shown) { print(line); shown = line; }
  setMissionObjectives(`${title} - ${line}`);
});

The editor keeps a text one of two ways and says which at the end of its line. A variable that only ever receives texts written in the script ("Boss", titles[level] out of a list the script has) holds the number of a string, and costs what a number does. A text that is made (a template with values in it, a + b, a method's result) keeps its characters in the pool the growing arrays share, and holds up to 1 023 bytes. Past that it is cut off, and the game says so once in red.

Texts take +, +=, templates, the comparisons, if (s) (not empty), switch (s), length, s[i], at(), charAt(), charCodeAt(), codePointAt(), slice(), substring(), indexOf(), includes(), startsWith(), endsWith(), padStart(), padEnd(), repeat(), concat(), trim(), trimStart(), trimEnd(), toUpperCase() and toLowerCase() (A to Z only), replace() and replaceAll() of a text, split() at a text, parseInt(), isNaN(), String(n), n.toString() and for (const ch of s).

program(() => {
  let wave = 3;
  const line = ` Wave ${wave}: zerglings, hydras `;
  const parts = line.trim().split(": ");
  print(parts[1].toUpperCase().replaceAll(", ", " + "));       // ZERGLINGS + HYDRAS
  print(`${parseInt("12 ore") + wave} ${line.includes("hydra")} ${"A".charCodeAt(0)}`);   // 15 true 65
});

Characters#

A character counts as one, as JavaScript counts it, so "저글링".length is 3 and "저글링"[1] is 글. The one difference is a character past U+FFFF, such as an emoji: a program counts one where JavaScript counts two, and the game draws a dark square in its place. s[i] and slice() walk the text from its start, so over a long text, for (const ch of s) is quicker. That loop runs within the frame and cannot sleep. A loop over the places can, which is how a text is typed out one character at a time:

program(() => {
  let wave = 3;
  let line = `Wave ${wave} is here`;
  let typed = "";
  for (let i = 0; i < line.length; i++) { typed += line[i]; print(typed); sleep(frames(2)); }
});

The game's font is proportional and a colour code has no width, so padStart does not line columns up.

Texts outside the chat area#

The objectives, a leaderboard's label, a transmission's line and a unit type's name (stats(units.TerranMarine).name = …) take a made text, up to 255 bytes. The game shows the text as it was when the action ran, so when the text changes, run the action again. In a program of every player, each player sees their own. Any other action's text, such as setNextScenario or a sound's path, has to be written in the script.

Lines of JSX#

In a .tsx file, <line>…</line> is a line of text that may hold the program's values, <bar value={hp} max={100} width={10} /> is a bar of squares, and <cell color={c} /> is a square of one of the game's text colours. print takes a line, and ui.lines(player, () => …) keeps the lines in a player's text area and draws them again when the values in them change. The trigscript/ui library builds panels, meters, menus and dialogs from them.

program(async () => {
  let hp = 0;
  ui.lines(P1, () => (
    <line>
      Base <bar value={hp} max={100} width={10} /> {hp}
    </line>
  ));
  while (hp < 100) {
    hp += 25;
    await sleep(seconds(1));
  }
  print(<line>Wave {hp / 25}</line>);
});

scmJS 0.8.5 · Generated from the repository. The source is under the MIT license, which does not cover what ATTRIBUTION.md lists. StarCraft and Brood War are trademarks of Blizzard Entertainment; this project ships none of their data.