Data
Data your interface owns, such as a shop’s stock, is declared with listOf:
const WARES = listOf<Ware>([ { item: FarmingItems.RAKE, name: 'Rake', price: 12, category: Category.TOOLS, restock: 30 }, { item: FarmingItems.SEED_DIBBER, name: 'Seed dibber', price: 6, category: Category.TOOLS, restock: 30 }, … { item: FarmingItems.BOTTOMLESS_COMPOST_BUCKET, name: 'Bottomless bucket', price: 5_440, category: Category.SEEDS },]);A plain array literal and an enum work too, for a fixed list. listOf and
mapOf make a collection you can filter, look up and pass around.
Records
Section titled “Records”A record type gives each entry named fields:
type Ware = { item: Item; name: String; price: Int; category: Category; /** How many the stall restocks to. Absent on the one-off pieces. */ restock?: Int;};Fields read as properties, ware.name, and a record is a valid prop type. An
entry that leaves out an optional number field reads back -1:
{(ware.restock ?? 0) > 0 && ( <text x={44} y={25} w={116} h={12} text={`restocks ${ware.restock}`} font={Fonts.SMALL} valign="middle" shadow color={Colors.DIM} />)}A list or a map
Section titled “A list or a map”A list is positional, read with .at(i). A map is keyed: declare it with
mapOf and read it with .get(key):
const CategoryNames = mapOf<Category, String>([ [Category.TOOLS, 'Tools'], [Category.CARE, 'Plant care'],]);Entries are [key, value] pairs. A map iterates in the order its pairs were
written; see
Rendering lists.
A read that can miss
Section titled “A read that can miss”.at(i) and .get(k) return Value | null unless the index or key is a
literal. For a scalar, ?? gives the fallback:
const categoryLabel = (names: Map<Category, String>, ware: Ware): String => names.get(ware.category) ?? 'Sundries';For a record, compare against null:
const ware = WARES.at(i);if (ware === null) { return null;}A collection can be bound, passed and returned like any value.
The game’s dictionaries
Section titled “The game’s dictionaries”Every font, sprite, item, sound and animation the game ships has a generated
name. Your project carries one file per kind under src/game/:
sprites.ts2 items.ts2 varps.ts2 animations.ts2fonts.ts2 inventories.ts2 varbits.ts2 models.ts2enums.ts2 params.ts2 npcs.ts2 …import { Fonts } from './game/fonts';
<text text="Confirm" w="fill" h={16} font={Fonts.B12_FULL} color={0xff981f} />Naming the ones you use
Section titled “Naming the ones you use”An unnamed entry arrives as ENUM_4136 or PARAM_1448. Alias it with typeof
in a file of your own:
/** * The game's own table of skill icons: `enum_255`, keyed by skill. * … */export declare const SkillIcons: typeof GameEnums.ENUM_255;Reading a table
Section titled “Reading a table”.get() and .at() read the game’s tables exactly as they read yours, and
the value’s type comes from the table:
const icon = SkillIcons.get(Skills.WOODCUTTING);return ( <layer x={0} y={0} w="fill" h={26}> {icon !== null && <sprite x={0} y="center" w={25} h={25} sprite={icon} />}Reading an item’s parameters
Section titled “Reading an item’s parameters”Items, NPCs and world objects carry parameters. When your project names them, each one reads as a field of the item, typed by the parameter:
const needs: Int = axe.item.levelrequire!;The ! marks a field your project’s parameter types declare. A parameter read
is never null: an item that does not set it reads the default. param() reads
a parameter with no field, by its dictionary reference:
const runeNeeds: Int = param(rune, AxeParams.LEVEL_REQUIRED);paramText, paramSprite and inventory.param(slot, …) are its siblings; see
param. A row the game ships is read with
.int(), .text() and .sprite(); see
Collections.