A level describes the starting conditions and objectives for a single mission. It can be a solo level, in which a human player attempts to beat a CPU player, or a net level, where two human players go head-to-head.
Yes. A plugin with no levels won’t have anything to play. A plugin can be all solo levels, all net levels, or a mixture.
Levels are in the levels directory and have a .pn extension.
The recommended convention for naming levels is:
A level is a procyon file with the following fields, plus any fields appropriate to its type:
Field | Req? | Type |
---|---|---|
type | yes | “solo”, “net”, or “demo” |
chapter | no | integer |
title | yes | string |
initial | no | array of initials |
conditions | no | array of conditions |
briefings | no | array of briefings |
starmap | no | rect |
song | no | name of a music track |
status | no | array of status lines |
start_time | no | duration |
angle | no | angle |
Determines the order that the level appears in on the “Select Level” screen. If null, the level won’t appear at all. All chapter numbers must be unique. If the plugin has solo levels, then there must be a chapter 1, which is initially unlocked.
Chapter numbers are also used by the unlocking level cheat. On the “Select Level” screen, type *03 to unlock the level with chapter number 3 (the number of digits must match the highest-numbered level in the plugin).
The title of the level. Level titles are normally two lines. Solo level titles normally look like this:
\i Chapter 1 \iIn Case of Emergency, Break Glass
Net level titles normally look like this:
\i Sundown Showdown \i
Note the space after the \i in the first line. The \i tells Antares to invert the text’s foreground and background (and back again in the second line).
A rect to highlight on the plugin’s starmap during mission briefings. In the factory scenario, these rects are 32×24, but any size appropriate to the plugin’s starmap can be used.
If null, the starmap page in the mission briefing will be skipped.
The name of a music track to play during the level. Any of the following is appropriate:
An array of status lines. Status lines are shown in the “Mission Status” screen of the computer. There are three general kinds of status lines:
Any of the three types of status lines can include underline: true to underline that line.
The computer screen is 25 characters wide. Status lines that exceed this length will be truncated before display.
Field | Req? | Type |
---|---|---|
text | yes | string |
underline | no | boolean |
Displays text verbatim, optionally with an underline.
For example, the following status lines:
* text: "Capture Vulpecula Beta" * text: " and Gamma" underline: true
will display unconditionally as:
Capture Vulpecula Beta and Gamma
Field | Req? | Type |
---|---|---|
prefix | no | string |
condition | yes | index of a condition |
true | no | string |
false | no | string |
suffix | no | string |
underline | no | boolean |
If the condition numbered condition has triggered, displays the true string, otherwise the false string. In either case, the text is preceded by prefix, followed by suffix, and optionally underlined.
condition must not reference a persistent condition. Any of true, false, prefix, or suffix may be null. If null, they are assumed to be empty.
For example, the following status line watches condition 0:
* prefix: "Battleship destroyed: " condition: 0 true: "Y" false: "N"
Before condition 0 triggers, it displays as:
Battleship destroyed: N
After condition 0 triggers, it displays as:
Battleship destroyed: Y
Field | Req? | Type |
---|---|---|
prefix | no | string |
minuend | no | number |
counter | yes | counter |
fixed | no | boolean |
suffix | no | string |
underline | no | boolean |
Displays a player’s numbered counter. The text is preceded by prefix, followed by suffix, and optionally underlined.
If fixed is true, divides the counter by 256 and displays it as a fractional value. If minuend is non-null, subtracts the counter from the minuend before displaying it.
For example, the following status lines watch the counters of the two players:
* prefix: "Player 1: " minuend: 3 counter: {player: 1, which: 0} suffix: " lives" * prefix: "Player 2: " minuend: 3 counter: {player: 0, which: 0} suffix: " lives"
If the counters count each player’s kills, and the first player has two kills and the second none, this displays as:
Player 1: 3 lives Player 2: 1 lives
Specifies a duration of time to run the level before before gameplay starts. In the factory scenario, this is typically used together with an asteroid generator. The level generates asteroids for a couple of minutes, so that when the player starts playing the level, it is filled with a random asteroid field.
Objects can still move before gameplay starts, and cpu players can act. For this reason, in levels with a start_time, it’s best to keep ships initially hidden, and planets initially without an owner. A time condition can reveal the ships and capture the planets just prior to the start of gameplay (duration: "-0.1s").
Specifies an angle to rotate the map to. Normally, this is either 0 (no rotation) or null (random rotation).
Solo levels have a single human player who (usually) plays against a CPU player.
Field | Req? | Type |
---|---|---|
players | yes | array of solo players |
par | yes | par |
skip | no | name of a level |
no_ships | no | string |
prologue | no | string |
epilogue | no | string |
Field | Req? | Type |
---|---|---|
type | yes | “human” or “cpu” |
name | yes | string |
race | yes | name of a race |
hue | no | hue |
earning_power | no | number |
In a solo level, the first player must be type: "human" and all other players must be type: "cpu".
name is used in messages about changes of ownership.
race determines the ships available to the player, as described in the documentation for initials’ base and build fields.
If hue is non-null, ships owned by the player will be recolored accordingly. This makes it possible to distinguish two players if they have the same race.
earning_power is a multiplier on the earning values of initials that a player owns, as well as the money paid out to all players at the start of the level (normally ¤25). If null, the player earns no cash.
For being 22 seconds (19%) over the par, 40 points (50 - 19%) are awarded. For losses being under half par, 60 points (the maximum) are awarded. For being 3 kills (30%) over par, 26 points (20 + 30%) are awarded.
The total score is 40 + 60 + 26 = 126 points.
Field | Req? | Type |
---|---|---|
time | yes | duration |
kills | yes | integer |
losses | yes | integer |
Sets target values for completing a level well. At the end of the level, 100 points are awarded to players that meet par, and points may be doubled for even better performance. Points for par are awarded as in the following proportions:
For time and losses, additional points may be awarded if under par, up to 2× for ½ par, and points may be deducted if over, down to 0 points for 2× par.
For kills, additional points may be awarded if over par, up to 2× for 2× par, and points may be deducted if under, down to 0 points for ½ par.
Note
if losses is 0, then it’s impossible to get fewer losses than par, so the maximum score is 170.
If provided, the player may press ESC during the game and skip the level. The level named skip will be unlocked, and play will continue with that level. Mainly used for tutorials, where victory is not important, and the player may want to skip to a real level.
If a human player loses all of their ships, they lose the level. This is the message that will be displayed if that happens.
A text crawl that will be displayed before playing the level (prologue) or after winning the level (epilogue). There are special codes supported for controlling formatting and displaying images:
Example | Meaning |
---|---|
\\ | Display a single backslash. |
\t | Tab to the middle of the screen. |
\r | Restore original foreground and background colors. |
\i Inverted \i | Swap foreground and background colors. |
\f8eIn yellow\r | Set the foreground color to $8e from the Ares CLUT. |
\b8eOn yellow\r | Set the background color to $8e from the Ares CLUT. |
#+ | Start a new line and reset foreground and background colors. |
#+gai/race | Display the picture with name gai/race in the foreground. |
#+Blog/starfield/a | From here on, use the picture with name log/starfield/a as the background. |
Field | Req? | Type |
---|---|---|
players | yes | array of net players |
description | no | string |
own_no_ships | no | string |
foe_no_ships | no | string |
Field | Req? | Type |
---|---|---|
type | yes | “human” or “cpu” |
races | yes | array of names of races |
earning_power | no | number |
In a net level, at least two players must be type: "human". Additional players may be type: "cpu".
race lists the races that a player may select in the level. The races will be offered in the given order, with the first option selected by default.
earning_power is a multiplier on the earning values of initials that a player owns. If null, the player earns no cash.
Net players have names and possibly hues, but these are determined by the players. Players choose their own names freely, and, if multiple players choose the same race, their hues as well.
A description of the level, used during level selection in a net game.
If a human player loses all of their ships, they lose the level. These are the messages that will be displayed if that happens to them (own_no_ships) or their opponent (foe_no_ships).
Demo levels are not properly supported yet. They have no human players, so they demonstrate CPU players playing against each other.
Field | Req? | Type |
---|---|---|
players | yes | array of demo players |