Hyperion live guide

connecting Debug Tools panel

Start here

Hyperion plays the original StarCraft with an engine of its own. While it runs, a map editor, a script or an AI can drive it over a live channel: switch the game to a map it is editing, and play a scene on that map with the camera, fades, words and units, without restarting anything. This page shows each of those, lets you try each on the game, and gives the code to do the same from your own program.

This copy is opened as a file, so its buttons cannot reach the game. Start Hyperion.exe --control and open http://127.0.0.1:27117/guide for the live one; the text is the same.

Getting it running

  1. Unpack Hyperion into a StarCraft 1.17 folder and start it with the channel open: Hyperion.exe --control. Started that way it goes straight to its menus, with no opening cinematic.
  2. Open http://127.0.0.1:27117/guide (this page, served by Hyperion). The dot at the top turns green when it is connected.
  3. Press Push a test map at the top, or any button marked with a map, and try the rest on it. Escape in the game ends a scene that plays.

Only programs on the same machine reach the channel: it listens on 127.0.0.1. A browser page may talk to it only when Hyperion served the page; a program that is not a browser may always.

The channel

A WebSocket on ws://127.0.0.1:27117/?t=<key> (another port with --control=<port>). Each message is one JSON object with a cmd; each answer carries the message's id and ok, and error, a sentence, when it is false.

The key is made each time Hyperion starts and written to a file only you can read: %LOCALAPPDATA%\Hyperion\control-27117.key on Windows, ~/.local/share/Hyperion/control-27117.key elsewhere (the number is the port). The C++ and Python clients read it themselves; a page Hyperion serves has it in the link Debug Tools' Copy link gives. A connection without it is refused, so no other program on the machine can drive the game.

message and answer
{"id": 7, "cmd": "map_push", "tileset": "jungle", "width": 128, "height": 128}
{"id": 7, "ok": true, "tileset": "jungle", "size": [128, 128], "state": "going out"}

{"id": 8, "cmd": "map_push", "tileset": "jungle", "width": 100}
{"id": 8, "ok": false, "error": "width and height are each 64, 96, 128, 192 or 256 tiles"}

Send one message and wait for its answer before the next. status is cheap; poll it a few times a second while waiting for something, and once a second or so to show where the game is.

What status says

fieldmeaning
state"front end" (Hyperion's menus), "game", or "menus" (the original's own screens, passed through while a map starts)
framethe game's frame, about 24 a second at the fastest speed; 0 out of a game
mapin a game, its size in map pixels: {"width": 4096, "height": 4096} for 128 by 128 tiles
viewin a game, where the camera looks: {"x", "y", "zoom"}, the same numbers a camera step takes
map_swap"none", "going out" or "loading" while a map switch is on its way
map_swap_errorset when the last switch could not start the map, saying why
cutscene{"playing", "step", "steps", "do", "units"}: the step that plays and the units its spawns made, by label
canvas, changed, pausedwhether the game is a pushed map, whether units were made or removed, whether it is paused

A client in a few lines

The C++ client is tools\hxlive_cpp\hxlive.h: one header, Windows' own WinHTTP, nothing else. The Python one is tools\hxlive.py, the standard library only. In a browser or Node, the WebSocket is built in.

Map switches

Two messages switch the game to another map. Both work from a single-player game and from Hyperion's menus. From a game the picture goes out over ms milliseconds, the old game is left as Quit Mission leaves it, the new map starts, and it comes in as a skirmish's start does.

map_pushMakes a map from what you send: a tileset, a size and the tiles (the MTXM section, as an editor holds it in memory), or the terrain of a map file with from. Player 1 starts on the west, player 2 (a computer with no AI) on the east, everything available. For a terrain test after every change.
map_loadPlays a saved map file: .scm, .scx or Hyperion's .hxm, as melee, or with "ums": true as Use Map Settings, with the map's own players, units, locations and triggers. For a test of the whole map.

The switch, step by step

map_swap: "going out" "loading" "none", state "game" out: console drops, themap shrinks to 86 % intoblack, over ms (1000) black: the game ends andthe map starts, a secondor a few for a big map in: out of black, 86 %to full size, consolelast, 1.6 s your scene plays,if one was sentwith the switch

Wait for the switch by polling status until map_swap is "none" and state is "game"; if map_swap_error appears instead, the map could not be started and it says why. Hyperion stays on its menus then. A pushed map starts explored but fogged: send {"cmd": "reveal"} once it runs to lift the fog, which a camera tour wants.

Push tiles

Left without tiles, the ground is the tileset's first plain buildable group, varied as a brush varies it. tiles is the MTXM values row by row (group × 16 + variation); tiles_b64 is the same as base64 of the little-endian 16-bit values, which is the MTXM section's own bytes and the better choice from a program; rects paints boxes over them. Sizes are those the original offers: 64, 96, 128, 192 or 256 tiles a side.

Push a map file's terrain

from takes a map file's tileset, size and tiles; Hyperion reads .scm, .scx and .hxm itself. A full path is used as it is; a name is looked for as the game looks for a map, in Hyperion's data folder, the StarCraft folder (so maps\(2)Volcanis.scm finds the install's), then each --maps folder, and failing that by the file's name alone in any folder under them, so (4)Lost Temple.scm finds the one in maps\ladder\. The units, locations and triggers stay behind: that is map_load's.

Load a map

As melee the player gets their race's start and the other starts get computers, as --map plays a map; as Use Map Settings the map's own slots, units and triggers decide. A map that cannot play (an .hxm that names a mod's unit while the mod is not on, for one) answers with map_swap_error, and hyperion_hxm.log in the Hyperion folder says why.

Find maps

maps lists every map file Hyperion finds: the data folder's maps, the StarCraft folder's and each --maps folder, with the folders in them, each with its name, folder, root and full path. filter keeps those whose folder and name hold it; the folders are read again after ten seconds, or at once with fresh: true. map_info {path} reads one map: its size, tileset, player slots, the title and description it shows in the game, its start locations in pixels with their player, whether map_push can take its terrain, and preview, its minimap with the starts marked, a picture served under /snapshots/. Debug Tools' panel lists the maps the same way.

Camera

Places are map pixels, 32 to a tile, from the map's top left: the middle of tile (40, 12) is (1296, 400). A camera step glides the middle of the view to x, y and the zoom to zoom over ms, with an ease; either part may be left out. zoom 1 is the game's own view, 2 shows twice the map across, and a scene may go as close as 0.5.

step
{"do": "camera", "x": 2048, "y": 1500, "zoom": 1.4, "ms": 3000, "ease": "in_out"}
Move the camera in the game, then capture it: the step goes into the builder.

The eases

How a move covers its distance over its time. The dot under each curve moves as the camera would.

in_outStarts and ends gently, quick in the middle. A camera step's own; the classic glide.
outFast first, settling at the end. Pushes in, reveals, a move that lands.
easeA soft start, a long settle. A fade's own; a gentle reframe.
evenThe same speed throughout. A drift, a dolly, an orbit's legs that must join without a bump.

Moves to try

Each plays around where the camera looks now, on whatever map runs.

Follow

{"do": "follow", "unit": "lings", "zoom": 1.2, "ms": 800} glides onto a unit and stays on it as it moves, until the next camera step. unit is a label a spawn gave, a unit's id, or a list of them (the first alive is followed). The tracking shot above uses it.

Picture transitions

Black over the picture, a zoom of the picture itself, cinema bars and the console, each on its own clock, so they combine: a fade can carry a zoom while the bars come in.

stepfieldswhat it does
fadeto, ms, scale, easeto is "black", "clear" or an amount 0 to 1; scale zooms the picture as it fades: 0.86 the skirmish's start, 1 as drawn, above 1 closer
barson, size, hud, mscinema bars top and bottom, size a share of the height each (0.12); the console leaves with them unless hud is true
hudshow, msthe console dropped and faded out, or back
departmsthe picture goes out as a map switch takes it out
arrivethe picture comes in as a skirmish's start brings it (1.6 s)

Words and sound

stepfieldswhat it does
captiontext, ms, atwords over the picture, in the bottom bar when the bars are in; at is bottom, middle or top; \n breaks a line
texttext, msa line among the game's messages, as Display Text Message puts it
transmissionunit, portrait, text, sound, msas the trigger Transmission: the portrait (a unit type, else the unit's own) talks, the unit flashes and pings the minimap, the text shows, the sound plays; with the console hidden the text comes as a caption
soundpatha sound from the game's files, as Play WAV plays it: sound\Misc\TPwrDown.wav

Left without ms, words stay for a reading time: a second and a half and 0.06 s a letter.

Units in a scene

Units made and ordered as the trigger actions do it, in a single-player game; the game is then marked as changed. A scene that only moves the camera, the picture and words also plays in a replay.

stepfieldswhat it does
spawnunit, x, y, player, count, as, attack or moveunits made as Create Unit makes them; as labels them for later steps; attack or move, an [x, y], sends them on at once
orderunits, to, ordermove, attack or patrol to [x, y]
kill, removeunitskilled, their deaths shown, or removed

A unit type is a name, as .hxm maps use (terran_marine, zerg_zergling, protoss_dragoon, terran_siege_tank_siege_mode), or the original's number. Players count from 0. The units a scene made are listed by label in cutscene_status and in status's cutscene.

Timing

Steps run in turn, each waiting for the one before. A step sent with "async": true lets the next start at once, under it: a caption stays up while the camera moves, a fade runs while a zoom eases.

steptakes, when ms is left out
camera1 s
follow, fade0.8 s
bars, hud0.6 s
depart / arrive1.2 s / 1.6 s
caption, transmission1.5 s and 0.06 s a letter
wait1 s
spawn, order, kill, remove, text, soundno time: the next step starts at once
cutscene_play fielddefaultmeaning
holdtruethe player's keys, clicks and the game's cursor are held while it plays
skiptrueEscape ends it
resttrueat its end the picture eases back to the game's in half a second; false leaves it as the last step left it, so a scene can end in black before a map_load

A new cutscene_play ends the one playing; cutscene_stop ends it as Escape does. The steps are checked before any runs, and the answer names the first wrong one.

Sample scenes

Five scenes made while the channel was built, each showing a different way to use it. Play switches to the map each was made for, then plays it. They are in tools\cutscenes\ to read and copy; each file names its map in map: push for a made map, or from for a map file with or as a stand-in when that file is not there.

Scene builder

Write or paste a scene, check it, play it on the game. Each button below adds a step of that kind with its fields filled in from where the camera looks now.

In your editor

What a Test in Hyperion button needs, in the order it happens. The C++ here uses tools\hxlive_cpp\hxlive.h; tools\hxlive_cpp\example.cpp is the same as a whole program.

1. Start Hyperion, or find it running

Try to connect first: a Hyperion the player already started answers. If nothing answers, start Hyperion.exe --control from the player's StarCraft 1.17 folder (the folder with StarCraft.exe, where Hyperion was unpacked), as its working directory, and connect again until it answers; it takes a few seconds. Keep it running between tests: every test after the first is a switch, a few seconds, not a start.

2. Send the map

For a terrain change, send the MTXM you hold in memory with map_push, no saving needed. For a test of units, locations and triggers, save the map and send its path with map_load (with "ums": true for a map made for Use Map Settings). Keep one connection and send one message at a time, from a worker thread so the editor stays responsive while it waits.

3. Wait for it, then the extras

Poll status until the switch has ended (above, under Map switches). Then reveal if the tester wants the whole map in view, and a scene if they asked for one; a scene can also ride along with the switch as its scene field, so it starts the moment the map comes in.

4. Scenes from the editor's own data

A scene is a list of steps, so an editor can make one from what it already has:

  • Camera keys from the viewport. The editor's view of the map gives the x, y of a camera step directly (map pixels are the editor's tile × 32 + 16 for a tile's middle); its zoom gives zoom. A list of saved views with a time each is a camera path.
  • Places from locations. A location's middle is a good x, y for a spawn, an order or a camera step: (left + right) / 2, (top + bottom) / 2 of its rectangle.
  • Units by label. Give each spawn an as named after what it is in the editor ("the convoy") and later steps can order or follow it by that name.
  • A timeline. Steps with "async": true run under the next, so a track per kind (camera, picture, words, units) on a timeline turns into a step list by sorting the starts and putting a wait between them.

The scene's format is the same one that will be kept in an .hxm and started by its triggers, when that comes: what an editor builds for live tests now carries over.

5. When something is wrong

  • ok: false answers say why in a sentence a tester can read: show it as it is.
  • A refused connection means Hyperion is not running with --control, or listens on another port.
  • map_swap_error means the map did not start; Hyperion's logs in its Hyperion folder say more (hyperion_hxm.log for an .hxm, hyperion_canvas.log for a push).
  • On a player's very first start without --control, the original's opening cinematic plays first; Escape skips it.

Message reference

The messages an editor uses. docs\live-channel-for-editors.md has the same with more detail; the channel has more, for Debug Tools (list, set, perf and others).

cmdfieldsanswers / does
statuswhere the game is (above)
map_pushtileset, width, height, tiles | tiles_b64 | fill, rects, or from; ms, scenetileset, size, state; the switch goes on
map_loadpath, ums, ms, scenepath (as found), state
cutscene_playsteps, hold, skip, restplays the steps; ends one playing first
cutscene_stopends it, as Escape
cutscene_statusplaying, step, steps, do, units
revealthe fog off for every player
camerax, ythe view's middle there at once (no scene)
unitsplayer, typethe units on the map with their ids, places and hit points
spawnunit, x, y, player, count, attackunits made outside a scene; their ids
pause, resume, stepframesthe game paused, on again, or a few frames on
snapshotnamethe frame as a PNG in Data\snapshots\; the answer gives its path

Tilesets

badlands, platform, install, ashworld, jungle, desert, ice, twilight, or "0" to "7" in that order (a map's ERA).

What is planned

  • Scenes kept in an .hxm map and started by its triggers, in this same step format.
  • Cutscene styles of Hyperion's own, beyond the classic look: other captions, bars and transitions.
  • map_push with units, locations and triggers, and past 256 tiles through .hxm.