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.
Getting it running
- 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. - Open http://127.0.0.1:27117/guide (this page, served by Hyperion). The dot at the top turns green when it is connected.
- 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.
{"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
| field | meaning |
|---|---|
state | "front end" (Hyperion's menus), "game", or "menus" (the original's own screens, passed through while a map starts) |
frame | the game's frame, about 24 a second at the fastest speed; 0 out of a game |
map | in a game, its size in map pixels: {"width": 4096, "height": 4096} for 128 by 128 tiles |
view | in 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_error | set 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, paused | whether 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.
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..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
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.
{"do": "camera", "x": 2048, "y": 1500, "zoom": 1.4, "ms": 3000, "ease": "in_out"}The eases
How a move covers its distance over its time. The dot under each curve moves as the camera would.
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.
| step | fields | what it does |
|---|---|---|
fade | to, ms, scale, ease | to 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 |
bars | on, size, hud, ms | cinema bars top and bottom, size a share of the height each (0.12); the console leaves with them unless hud is true |
hud | show, ms | the console dropped and faded out, or back |
depart | ms | the picture goes out as a map switch takes it out |
arrive | the picture comes in as a skirmish's start brings it (1.6 s) |
Words and sound
| step | fields | what it does |
|---|---|---|
caption | text, ms, at | words over the picture, in the bottom bar when the bars are in; at is bottom, middle or top; \n breaks a line |
text | text, ms | a line among the game's messages, as Display Text Message puts it |
transmission | unit, portrait, text, sound, ms | as 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 |
sound | path | a 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.
| step | fields | what it does |
|---|---|---|
spawn | unit, x, y, player, count, as, attack or move | units made as Create Unit makes them; as labels them for later steps; attack or move, an [x, y], sends them on at once |
order | units, to, order | move, attack or patrol to [x, y] |
kill, remove | units | killed, 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.
| step | takes, when ms is left out |
|---|---|
camera | 1 s |
follow, fade | 0.8 s |
bars, hud | 0.6 s |
depart / arrive | 1.2 s / 1.6 s |
caption, transmission | 1.5 s and 0.06 s a letter |
wait | 1 s |
spawn, order, kill, remove, text, sound | no time: the next step starts at once |
| cutscene_play field | default | meaning |
|---|---|---|
hold | true | the player's keys, clicks and the game's cursor are held while it plays |
skip | true | Escape ends it |
rest | true | at 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,yof a camera step directly (map pixels are the editor's tile × 32 + 16 for a tile's middle); its zoom giveszoom. A list of saved views with a time each is a camera path. - Places from locations. A location's middle is a good
x,yfor a spawn, an order or a camera step:(left + right) / 2,(top + bottom) / 2of its rectangle. - Units by label. Give each spawn an
asnamed 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": truerun 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 awaitbetween 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: falseanswers 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_errormeans the map did not start; Hyperion's logs in itsHyperionfolder say more (hyperion_hxm.logfor an.hxm,hyperion_canvas.logfor 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).
| cmd | fields | answers / does |
|---|---|---|
status | where the game is (above) | |
map_push | tileset, width, height, tiles | tiles_b64 | fill, rects, or from; ms, scene | tileset, size, state; the switch goes on |
map_load | path, ums, ms, scene | path (as found), state |
cutscene_play | steps, hold, skip, rest | plays the steps; ends one playing first |
cutscene_stop | ends it, as Escape | |
cutscene_status | playing, step, steps, do, units | |
reveal | the fog off for every player | |
camera | x, y | the view's middle there at once (no scene) |
units | player, type | the units on the map with their ids, places and hit points |
spawn | unit, x, y, player, count, attack | units made outside a scene; their ids |
pause, resume, step | frames | the game paused, on again, or a few frames on |
snapshot | name | the 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
.hxmmap 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_pushwith units, locations and triggers, and past 256 tiles through.hxm.