@idosgames/game-kit 0.0.0-stage → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +31 -2
- package/dist/chunk-NBIYNARI.js +2 -0
- package/dist/index.cjs +3 -0
- package/dist/index.d.cts +2032 -0
- package/dist/index.d.ts +2032 -0
- package/dist/index.js +2 -0
- package/dist/phaser/index.cjs +2 -0
- package/dist/phaser/index.d.cts +82 -0
- package/dist/phaser/index.d.ts +82 -0
- package/dist/phaser/index.js +1 -0
- package/dist/view-CS-ixOId.d.cts +309 -0
- package/dist/view-CS-ixOId.d.ts +309 -0
- package/package.json +70 -6
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,2032 @@
|
|
|
1
|
+
import { W as World, C as CastDef, A as ArtLook, E as Entity, a as ActorAct, F as FxEvent, b as ActorPose, c as ComponentType } from './view-CS-ixOId.js';
|
|
2
|
+
export { D as DEFAULT_CAST, d as DEFAULT_LOOK, e as DEFAULT_PALETTE, f as EventHandler, g as FX_TOPIC, I as INPUT_TOPIC, h as InputEvent, R as Rng, S as System, i as Transform, T as TransformData, j as VIEW_RESIZED_TOPIC, k as Visual, V as VisualData, l as WorldOptions, m as WorldVar, n as createFixedStepper, o as createRng, p as defineComponent, q as mergePalette, r as resolveColor } from './view-CS-ixOId.js';
|
|
3
|
+
|
|
4
|
+
/** Every entry has a stable id and a version (bumped on an incompatible change of the entry). */
|
|
5
|
+
interface RegistryEntry {
|
|
6
|
+
readonly id: string;
|
|
7
|
+
readonly version: number;
|
|
8
|
+
}
|
|
9
|
+
/** A typed kind token. */
|
|
10
|
+
interface RegistryKind<T extends RegistryEntry> {
|
|
11
|
+
readonly name: string;
|
|
12
|
+
/** Phantom: carries the entry type, never set at runtime. */
|
|
13
|
+
readonly __entry?: T;
|
|
14
|
+
}
|
|
15
|
+
/** A kind token for entries of type T. Kind names are lower-kebab ("asset-pack"). */
|
|
16
|
+
declare function defineKind<T extends RegistryEntry>(name: string): RegistryKind<T>;
|
|
17
|
+
/** Entry ids: lower-kebab, optionally namespaced by dots ("runner", "acme.lava-runner"). */
|
|
18
|
+
declare const ENTRY_ID_RE: RegExp;
|
|
19
|
+
interface DefineOptions {
|
|
20
|
+
/**
|
|
21
|
+
* Replace an entry with the same id. Off by default: two packages that both define "runner" is a
|
|
22
|
+
* bug, and silently keeping the last one would hide it. A project overrides deliberately.
|
|
23
|
+
*/
|
|
24
|
+
readonly override?: boolean;
|
|
25
|
+
}
|
|
26
|
+
interface Registry {
|
|
27
|
+
define<T extends RegistryEntry>(kind: RegistryKind<T>, entry: T, options?: DefineOptions): T;
|
|
28
|
+
get<T extends RegistryEntry>(kind: RegistryKind<T>, id: string): T | undefined;
|
|
29
|
+
/** Like get, but throws a readable error when the entry is missing. */
|
|
30
|
+
require<T extends RegistryEntry>(kind: RegistryKind<T>, id: string): T;
|
|
31
|
+
has<T extends RegistryEntry>(kind: RegistryKind<T>, id: string): boolean;
|
|
32
|
+
/** Every entry of a kind, in id order (stable, independent of registration order). */
|
|
33
|
+
list<T extends RegistryEntry>(kind: RegistryKind<T>): T[];
|
|
34
|
+
/** A child registry: sees every entry of this one, defines its own on top (a project over the platform). */
|
|
35
|
+
extend(): Registry;
|
|
36
|
+
}
|
|
37
|
+
declare function createRegistry(parent?: Registry): Registry;
|
|
38
|
+
|
|
39
|
+
type ExprValue = number | boolean | string;
|
|
40
|
+
/** What a formula reads: nested plain objects, numbers, strings and booleans. */
|
|
41
|
+
interface ExprScope {
|
|
42
|
+
readonly [name: string]: unknown;
|
|
43
|
+
}
|
|
44
|
+
/** A parsed formula. */
|
|
45
|
+
interface Expr {
|
|
46
|
+
readonly source: string;
|
|
47
|
+
/** Evaluate against a scope. */
|
|
48
|
+
eval(scope?: ExprScope): ExprValue;
|
|
49
|
+
/** Evaluate and coerce to a finite number (NaN / Infinity → 0). */
|
|
50
|
+
num(scope?: ExprScope): number;
|
|
51
|
+
/** Evaluate and coerce to a boolean. */
|
|
52
|
+
bool(scope?: ExprScope): boolean;
|
|
53
|
+
/** Every variable path the formula reads, e.g. ["event.damage", "vars.level"]. */
|
|
54
|
+
readonly reads: readonly string[];
|
|
55
|
+
}
|
|
56
|
+
declare class ExprError extends Error {
|
|
57
|
+
readonly source: string;
|
|
58
|
+
readonly at: number;
|
|
59
|
+
constructor(message: string, source: string, at: number);
|
|
60
|
+
}
|
|
61
|
+
/** The only functions a formula may call. Each takes numbers. */
|
|
62
|
+
declare const FUNCTIONS: Readonly<Record<string, (...args: number[]) => number>>;
|
|
63
|
+
/** Parse a formula. Throws ExprError on a syntax error. Parsed formulas are shared by source text. */
|
|
64
|
+
declare function compileExpr(source: string): Expr;
|
|
65
|
+
/** A syntax check without throwing: null when the formula parses, else the error text. */
|
|
66
|
+
declare function checkExpr(source: string): string | null;
|
|
67
|
+
/** A number field of the spec: a plain number, or a formula string evaluated against the scope. */
|
|
68
|
+
type NumberOrFormula = number | string;
|
|
69
|
+
/** Evaluate a number-or-formula field. */
|
|
70
|
+
declare function evalNumber(value: NumberOrFormula | undefined, scope?: ExprScope, fallback?: number): number;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* A finding of spec validation. `error` makes the spec unusable (the game would not run or would
|
|
74
|
+
* run wrong); `warning` was repaired on the way (a clamped number, a dropped unknown parameter).
|
|
75
|
+
*/
|
|
76
|
+
interface Issue {
|
|
77
|
+
readonly level: "error" | "warning";
|
|
78
|
+
/** Where, as a dotted path into the spec: "modes.0.params.speed". */
|
|
79
|
+
readonly path: string;
|
|
80
|
+
/** A stable code for programs (the config agent, the dashboard): "MODE_PRESET_UNKNOWN". */
|
|
81
|
+
readonly code: string;
|
|
82
|
+
/** Plain English for logs and the agent. */
|
|
83
|
+
readonly message: string;
|
|
84
|
+
}
|
|
85
|
+
declare const hasErrors: (issues: readonly Issue[]) => boolean;
|
|
86
|
+
|
|
87
|
+
/** One effect of a rule: its type names an EFFECTS entry, the rest are its parameters. */
|
|
88
|
+
interface EffectSpec {
|
|
89
|
+
readonly type: string;
|
|
90
|
+
readonly [param: string]: unknown;
|
|
91
|
+
}
|
|
92
|
+
interface RuleDef {
|
|
93
|
+
readonly id: string;
|
|
94
|
+
/** Event topic that triggers the rule ("enemy-killed", "level-cleared", "tick"). */
|
|
95
|
+
readonly on: string;
|
|
96
|
+
/** Formula; the rule runs only when it is true. Reads `event.*`, `vars.*`, `tick`, `time`. */
|
|
97
|
+
readonly when?: string;
|
|
98
|
+
readonly do: readonly EffectSpec[];
|
|
99
|
+
/** Run at most once per world. */
|
|
100
|
+
readonly once?: boolean;
|
|
101
|
+
/** Run on every N-th matching event only (every 3rd hit). */
|
|
102
|
+
readonly every?: number;
|
|
103
|
+
/** Minimum seconds of world time between two runs. */
|
|
104
|
+
readonly cooldown?: number;
|
|
105
|
+
}
|
|
106
|
+
/** What an effect receives. */
|
|
107
|
+
interface EffectContext {
|
|
108
|
+
readonly world: World;
|
|
109
|
+
readonly rule: RuleDef;
|
|
110
|
+
readonly event: Readonly<Record<string, unknown>>;
|
|
111
|
+
/** The scope formulas of this run evaluate against. */
|
|
112
|
+
readonly scope: ExprScope;
|
|
113
|
+
/** Evaluate a number-or-formula parameter of the effect. */
|
|
114
|
+
num(value: unknown, fallback?: number): number;
|
|
115
|
+
}
|
|
116
|
+
interface EffectDef extends RegistryEntry {
|
|
117
|
+
/** Parameters that are formulas (checked when the spec is validated). */
|
|
118
|
+
readonly formulas?: readonly string[];
|
|
119
|
+
/** Required parameters. */
|
|
120
|
+
readonly required?: readonly string[];
|
|
121
|
+
run(ctx: EffectContext, params: EffectSpec): void;
|
|
122
|
+
}
|
|
123
|
+
declare const EFFECTS: RegistryKind<EffectDef>;
|
|
124
|
+
/** The generic effects every game has. Blocks add their own. */
|
|
125
|
+
declare const CORE_EFFECTS: readonly EffectDef[];
|
|
126
|
+
/** Registers CORE_EFFECTS (once per registry). */
|
|
127
|
+
declare function registerCoreEffects(registry: Registry): void;
|
|
128
|
+
/** Check rules without running them (used by spec validation). */
|
|
129
|
+
declare function checkRules(rules: readonly RuleDef[], registry: Registry, path: string, issues: Issue[]): void;
|
|
130
|
+
/**
|
|
131
|
+
* Attach rules to a world. Rules run when their event is delivered (after the step's systems).
|
|
132
|
+
* An effect that throws is skipped and reported through `onError`: one bad rule must not stop the game.
|
|
133
|
+
* Returns a detach function.
|
|
134
|
+
*/
|
|
135
|
+
declare function attachRules(world: World, rules: readonly RuleDef[], registry: Registry, options?: {
|
|
136
|
+
onError?: (rule: RuleDef, error: unknown) => void;
|
|
137
|
+
}): () => void;
|
|
138
|
+
|
|
139
|
+
type ParamValue = number | string | boolean;
|
|
140
|
+
type ParamDef = {
|
|
141
|
+
readonly type: "number";
|
|
142
|
+
readonly default: number;
|
|
143
|
+
readonly min?: number;
|
|
144
|
+
readonly max?: number;
|
|
145
|
+
/** Round to an integer. */
|
|
146
|
+
readonly integer?: boolean;
|
|
147
|
+
/** Text key describing the parameter (for the config agent and the editor). */
|
|
148
|
+
readonly label?: string;
|
|
149
|
+
} | {
|
|
150
|
+
readonly type: "enum";
|
|
151
|
+
readonly default: string;
|
|
152
|
+
readonly values: readonly string[];
|
|
153
|
+
readonly label?: string;
|
|
154
|
+
} | {
|
|
155
|
+
readonly type: "boolean";
|
|
156
|
+
readonly default: boolean;
|
|
157
|
+
readonly label?: string;
|
|
158
|
+
} | {
|
|
159
|
+
readonly type: "string";
|
|
160
|
+
readonly default: string;
|
|
161
|
+
readonly maxLength?: number;
|
|
162
|
+
readonly label?: string;
|
|
163
|
+
};
|
|
164
|
+
type ParamDefs = Readonly<Record<string, ParamDef>>;
|
|
165
|
+
/**
|
|
166
|
+
* Defaults merged with the given values. Unknown names are dropped with a warning (a typo must not
|
|
167
|
+
* silently do nothing AND must not break the game); bad types fall back to the default.
|
|
168
|
+
*/
|
|
169
|
+
declare function resolveParams(defs: ParamDefs, given: Readonly<Record<string, unknown>> | undefined, path: string, issues: Issue[]): Record<string, ParamValue>;
|
|
170
|
+
|
|
171
|
+
declare const SPEC_VERSION = 1;
|
|
172
|
+
interface ModeSpec {
|
|
173
|
+
/** Snake-case id, unique in the spec ("main", "city"). */
|
|
174
|
+
readonly id: string;
|
|
175
|
+
/** PRESETS entry id. */
|
|
176
|
+
readonly preset: string;
|
|
177
|
+
/** core: what the player plays; meta: what they come back for; embedded: called from another mode. */
|
|
178
|
+
readonly role?: "core" | "meta" | "embedded";
|
|
179
|
+
readonly params?: Readonly<Record<string, unknown>>;
|
|
180
|
+
/** Overrides of block parameters: `{ "waves": { "count": 12 } }`. */
|
|
181
|
+
readonly blockParams?: Readonly<Record<string, Readonly<Record<string, unknown>>>>;
|
|
182
|
+
/** Rules of this mode, after the preset's own. */
|
|
183
|
+
readonly rules?: readonly RuleDef[];
|
|
184
|
+
/**
|
|
185
|
+
* Which rows of the genre's own lists this game leaves out (tuning knobs, 08.11.2026): `{ "powers":
|
|
186
|
+
* { "without": ["flight"] } }`. The kinds are the genre's (runner: powers, obstacles; survivors:
|
|
187
|
+
* foes). A block never ends up with nothing: leaving out every row of a kind keeps them all.
|
|
188
|
+
*/
|
|
189
|
+
readonly content?: Readonly<Record<string, Readonly<{
|
|
190
|
+
without?: readonly string[];
|
|
191
|
+
}>>>;
|
|
192
|
+
}
|
|
193
|
+
interface ResourceSpec {
|
|
194
|
+
/** Snake-case id, readable in formulas as `res.<id>`. */
|
|
195
|
+
readonly id: string;
|
|
196
|
+
/**
|
|
197
|
+
* currency / item: kept on the server (an engine currency or item: `ref` is its id), need a source
|
|
198
|
+
* and a sink; score: a round's result (goes to a leaderboard); local: lives inside a round.
|
|
199
|
+
*/
|
|
200
|
+
readonly kind: "currency" | "item" | "score" | "local";
|
|
201
|
+
readonly ref?: string;
|
|
202
|
+
/** Text key of the name. */
|
|
203
|
+
readonly name?: string;
|
|
204
|
+
}
|
|
205
|
+
interface FlowSpec {
|
|
206
|
+
readonly resource: string;
|
|
207
|
+
/** A mode id of the spec, or "system:<id>" (store, quests, reward-window, idle…). */
|
|
208
|
+
readonly by: string;
|
|
209
|
+
readonly kind: "source" | "sink";
|
|
210
|
+
/** How much, as a number or a formula ("10 + vars.level * 2"). */
|
|
211
|
+
readonly amount?: NumberOrFormula;
|
|
212
|
+
}
|
|
213
|
+
interface RewardsSpec {
|
|
214
|
+
/**
|
|
215
|
+
* The server's reward window (`Reward.Windows[window]` of the title config) the round's coins are
|
|
216
|
+
* claimed through. The server owns the real multipliers and caps; the two below are what the
|
|
217
|
+
* creation path writes into that window.
|
|
218
|
+
*/
|
|
219
|
+
readonly window?: string;
|
|
220
|
+
/** "x3 for an ad". Ads exist only in the mobile app; elsewhere the button is not drawn. */
|
|
221
|
+
readonly adMultiplier?: number;
|
|
222
|
+
/** "x5 for VIP", no ad. */
|
|
223
|
+
readonly vipMultiplier?: number;
|
|
224
|
+
}
|
|
225
|
+
interface GameSpec {
|
|
226
|
+
readonly v: number;
|
|
227
|
+
readonly engine: Engine;
|
|
228
|
+
readonly seed?: string;
|
|
229
|
+
readonly modes: readonly ModeSpec[];
|
|
230
|
+
readonly resources?: readonly ResourceSpec[];
|
|
231
|
+
readonly flows?: readonly FlowSpec[];
|
|
232
|
+
/** Game-wide rules (links between modes, quests of the run). */
|
|
233
|
+
readonly rules?: readonly RuleDef[];
|
|
234
|
+
readonly vars?: Readonly<Record<string, number | string | boolean>>;
|
|
235
|
+
/** Taxonomy ids. */
|
|
236
|
+
readonly setting?: string;
|
|
237
|
+
readonly style?: string;
|
|
238
|
+
/** Asset pack id. */
|
|
239
|
+
readonly assets?: string;
|
|
240
|
+
/** Role → colour: `{ "primary": "#ff8800" }`. */
|
|
241
|
+
readonly palette?: Readonly<Record<string, string>>;
|
|
242
|
+
/** Text key → language → text: `{ "title": { "en": "Lava Run", "ru": "Лавовый забег" } }`. */
|
|
243
|
+
readonly texts?: Readonly<Record<string, Readonly<Record<string, string>>>>;
|
|
244
|
+
/** Who the actors are, over the asset pack's cast, role by role: `{ "hero": { "preset": "viking", "races": ["dwarf"] } }`. */
|
|
245
|
+
readonly cast?: Readonly<Record<string, Partial<CastDef>>>;
|
|
246
|
+
readonly rewards?: RewardsSpec;
|
|
247
|
+
readonly multiplayer?: "none" | "async" | "coop" | "pvp";
|
|
248
|
+
/** Unknown fields are kept. */
|
|
249
|
+
readonly [extra: string]: unknown;
|
|
250
|
+
}
|
|
251
|
+
interface ResolvedMode {
|
|
252
|
+
readonly id: string;
|
|
253
|
+
readonly role: "core" | "meta" | "embedded";
|
|
254
|
+
readonly preset: PresetDef;
|
|
255
|
+
readonly params: Readonly<Record<string, ParamValue>>;
|
|
256
|
+
/** Block id → its resolved parameters. */
|
|
257
|
+
readonly blockParams: Readonly<Record<string, Readonly<Record<string, ParamValue>>>>;
|
|
258
|
+
/** Preset rules, then the mode's own. */
|
|
259
|
+
readonly rules: readonly RuleDef[];
|
|
260
|
+
/** Kind → the row ids this game leaves out (see ModeSpec.content); read through `contentOf`. */
|
|
261
|
+
readonly content: Readonly<Record<string, readonly string[]>>;
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* The rows of a genre list this mode plays with: `all` without the ones the spec leaves out. Never
|
|
265
|
+
* empty: a spec that leaves out every row keeps them all (a game must stay playable).
|
|
266
|
+
*/
|
|
267
|
+
declare function contentOf<T extends string>(mode: Pick<ResolvedMode, "content"> | undefined, kind: string, all: readonly T[]): readonly T[];
|
|
268
|
+
interface ResolvedSpec {
|
|
269
|
+
readonly spec: GameSpec;
|
|
270
|
+
readonly engine: Engine;
|
|
271
|
+
readonly seed: string;
|
|
272
|
+
readonly modes: readonly ResolvedMode[];
|
|
273
|
+
readonly resources: readonly ResourceSpec[];
|
|
274
|
+
readonly flows: readonly FlowSpec[];
|
|
275
|
+
readonly rules: readonly RuleDef[];
|
|
276
|
+
readonly vars: Readonly<Record<string, number | string | boolean>>;
|
|
277
|
+
readonly rewards: Required<RewardsSpec>;
|
|
278
|
+
readonly multiplayer: "none" | "async" | "coop" | "pvp";
|
|
279
|
+
/** Every palette role: the defaults ← the asset pack's ← the spec's own. */
|
|
280
|
+
readonly palette: Readonly<Record<string, string>>;
|
|
281
|
+
/** Texts: the asset pack's defaults ← the spec's own, key by key and language by language. */
|
|
282
|
+
readonly texts: Readonly<Record<string, Readonly<Record<string, string>>>>;
|
|
283
|
+
/** The art style and the cast: the asset pack's over the kit's defaults. */
|
|
284
|
+
readonly look: ArtLook;
|
|
285
|
+
}
|
|
286
|
+
declare const DEFAULT_REWARDS: Required<RewardsSpec>;
|
|
287
|
+
/** Bring a spec to SPEC_VERSION. A spec without `v` is treated as version 1. */
|
|
288
|
+
declare function migrateSpec(raw: Record<string, unknown>, issues: Issue[]): Record<string, unknown> | null;
|
|
289
|
+
interface SpecResult {
|
|
290
|
+
/** No errors (warnings are allowed: they were repaired). */
|
|
291
|
+
readonly ok: boolean;
|
|
292
|
+
readonly issues: readonly Issue[];
|
|
293
|
+
/** The migrated spec, unknown fields kept. Present when the shape could be read. */
|
|
294
|
+
readonly spec?: GameSpec;
|
|
295
|
+
/** Everything resolved against the registry. Present only when ok. */
|
|
296
|
+
readonly resolved?: ResolvedSpec;
|
|
297
|
+
}
|
|
298
|
+
/** Validate a spec from any source (JSON from the title's config, an AI, a remix). Never throws. */
|
|
299
|
+
declare function validateSpec(input: unknown, registry: Registry): SpecResult;
|
|
300
|
+
|
|
301
|
+
/** Rendering family. The kit's logic is engine-free; a preset says which adapter draws it. */
|
|
302
|
+
type Engine = "phaser" | "three" | "dom";
|
|
303
|
+
declare const ENGINES: readonly Engine[];
|
|
304
|
+
/** What a block's setup receives for one mode of a game. */
|
|
305
|
+
interface BlockContext {
|
|
306
|
+
readonly world: World;
|
|
307
|
+
readonly spec: ResolvedSpec;
|
|
308
|
+
readonly mode: ResolvedMode;
|
|
309
|
+
/** This block's own parameters (block defaults ← preset values ← spec values). */
|
|
310
|
+
readonly params: Readonly<Record<string, ParamValue>>;
|
|
311
|
+
readonly registry: Registry;
|
|
312
|
+
}
|
|
313
|
+
interface BlockDef extends RegistryEntry {
|
|
314
|
+
/** Engines the block's logic is drawn by; omitted = any (pure logic). */
|
|
315
|
+
readonly engines?: readonly Engine[];
|
|
316
|
+
readonly params?: ParamDefs;
|
|
317
|
+
/** Blocks that must be in the same mode (a "waves" block needs "combat"). */
|
|
318
|
+
readonly requires?: readonly string[];
|
|
319
|
+
/** Add systems, entities and event handlers to the world. */
|
|
320
|
+
setup?(ctx: BlockContext): void;
|
|
321
|
+
}
|
|
322
|
+
/** A rewarded-ad spot a preset offers (shown only where ads exist: the mobile app). */
|
|
323
|
+
interface RewardedPlacementDef {
|
|
324
|
+
/** Placement id, written into the title's Advertising section on creation. */
|
|
325
|
+
readonly id: string;
|
|
326
|
+
readonly kind: "reward-window" | "revive" | "chest" | "energy" | "timer" | "retry";
|
|
327
|
+
/** Views per player per day; omitted = the title's default. */
|
|
328
|
+
readonly dailyLimit?: number;
|
|
329
|
+
}
|
|
330
|
+
interface PresetDef extends RegistryEntry {
|
|
331
|
+
readonly engine: Engine;
|
|
332
|
+
/** Genre id (the constructor's genre list: "runner", "match3", "tower-defense", …). */
|
|
333
|
+
readonly genre: string;
|
|
334
|
+
/** Text key of the preset's name. */
|
|
335
|
+
readonly name?: string;
|
|
336
|
+
/** Block ids in setup order. */
|
|
337
|
+
readonly blocks: readonly string[];
|
|
338
|
+
/** The preset's own parameters (what the decision model's score questions and the config agent set). */
|
|
339
|
+
readonly params?: ParamDefs;
|
|
340
|
+
/**
|
|
341
|
+
* Values the preset gives its blocks' parameters: `{ "waves": { "count": 10 } }`. For a number or
|
|
342
|
+
* true/false parameter a string is a formula over the preset's own `params.*`
|
|
343
|
+
* (`"count": "6 + params.difficulty * 8"`). The spec's own blockParams win over these.
|
|
344
|
+
*/
|
|
345
|
+
readonly blockParams?: Readonly<Record<string, Readonly<Record<string, ParamValue>>>>;
|
|
346
|
+
/** Default rules of the genre (a spec's mode rules come after them). */
|
|
347
|
+
readonly rules?: readonly RuleDef[];
|
|
348
|
+
/** Resource roles the genre produces / consumes ("soft", "score", "stars"), for links. */
|
|
349
|
+
readonly produces?: readonly string[];
|
|
350
|
+
readonly consumes?: readonly string[];
|
|
351
|
+
readonly placements?: readonly RewardedPlacementDef[];
|
|
352
|
+
}
|
|
353
|
+
declare const BLOCKS: RegistryKind<BlockDef>;
|
|
354
|
+
declare const PRESETS: RegistryKind<PresetDef>;
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* Who may produce or consume besides the spec's own modes: the platform's systems ("system:store",
|
|
358
|
+
* "system:quests"…) and the kit's shared blocks. An unknown system is a warning, not an error: a
|
|
359
|
+
* project may add its own.
|
|
360
|
+
*/
|
|
361
|
+
declare const KNOWN_SYSTEMS: readonly string[];
|
|
362
|
+
declare function checkEconomy(modes: readonly ModeSpec[], resources: readonly ResourceSpec[], flows: readonly FlowSpec[], issues: Issue[]): void;
|
|
363
|
+
|
|
364
|
+
/** A registry with the kit's generic effects in it: the base every platform or project registry extends. */
|
|
365
|
+
declare function createKitRegistry(): Registry;
|
|
366
|
+
interface RunningMode {
|
|
367
|
+
readonly world: World;
|
|
368
|
+
readonly mode: ResolvedMode;
|
|
369
|
+
/** Detach rules and drop the world's handlers. */
|
|
370
|
+
stop(): void;
|
|
371
|
+
}
|
|
372
|
+
interface StartModeOptions {
|
|
373
|
+
/**
|
|
374
|
+
* Extra seed material (a run number, a daily seed, the opponent's id in async PvP). The same spec,
|
|
375
|
+
* mode and salt give the same run.
|
|
376
|
+
*/
|
|
377
|
+
readonly salt?: string;
|
|
378
|
+
/** A rule effect threw: the rule is skipped, the game goes on. */
|
|
379
|
+
readonly onRuleError?: (rule: RuleDef, error: unknown) => void;
|
|
380
|
+
}
|
|
381
|
+
declare function startMode(resolved: ResolvedSpec, modeId: string, registry: Registry, options?: StartModeOptions): RunningMode;
|
|
382
|
+
|
|
383
|
+
type Hex = string;
|
|
384
|
+
|
|
385
|
+
interface ArtContext {
|
|
386
|
+
readonly style: string;
|
|
387
|
+
/** A palette role or #hex → #rrggbb. */
|
|
388
|
+
readonly c: (role: string) => Hex;
|
|
389
|
+
/** The visual's colour (resolved), or the entry's default role. */
|
|
390
|
+
readonly main: Hex;
|
|
391
|
+
/** The outline colour of the style. */
|
|
392
|
+
readonly ink: Hex;
|
|
393
|
+
/** The box asked for, logical px ("exact" art draws at it). */
|
|
394
|
+
readonly w: number;
|
|
395
|
+
readonly h: number;
|
|
396
|
+
}
|
|
397
|
+
interface ArtDef {
|
|
398
|
+
/** The viewBox (ignored for exact art). */
|
|
399
|
+
readonly w: number;
|
|
400
|
+
readonly h: number;
|
|
401
|
+
/** Drawn at the asked box itself, not stretched. */
|
|
402
|
+
readonly exact?: boolean;
|
|
403
|
+
/** A band that repeats only sideways (a backdrop layer): its texture gets an empty row under it, so
|
|
404
|
+
* the GPU's wrap never pulls the bottom edge over the top one (a thin line across the sky). */
|
|
405
|
+
readonly band?: boolean;
|
|
406
|
+
/** The colour role used when the visual names none. */
|
|
407
|
+
readonly main?: string;
|
|
408
|
+
draw(c: ArtContext): string;
|
|
409
|
+
}
|
|
410
|
+
/** Every picture of the kit, by id. */
|
|
411
|
+
declare const ART: Readonly<Record<string, ArtDef>>;
|
|
412
|
+
declare const hasArt: (id: string) => boolean;
|
|
413
|
+
/** The art's own aspect (w / h) — exact art has the box's. */
|
|
414
|
+
declare function artAspect(id: string, box: {
|
|
415
|
+
w: number;
|
|
416
|
+
h: number;
|
|
417
|
+
}): number;
|
|
418
|
+
/**
|
|
419
|
+
* A whole SVG document of a picture, `px` pixels big (the adapter's raster size). Null for an unknown id.
|
|
420
|
+
* `box` is the logical box the visual asked for (exact art draws at it).
|
|
421
|
+
*/
|
|
422
|
+
declare function artDocument(id: string, options: {
|
|
423
|
+
style: string;
|
|
424
|
+
palette: Readonly<Record<string, string>>;
|
|
425
|
+
color?: string;
|
|
426
|
+
box: {
|
|
427
|
+
w: number;
|
|
428
|
+
h: number;
|
|
429
|
+
};
|
|
430
|
+
px: {
|
|
431
|
+
w: number;
|
|
432
|
+
h: number;
|
|
433
|
+
};
|
|
434
|
+
/** Empty px added under the picture (bands). */
|
|
435
|
+
padBottom?: number;
|
|
436
|
+
}): string | null;
|
|
437
|
+
|
|
438
|
+
interface ViewSize {
|
|
439
|
+
readonly w: number;
|
|
440
|
+
readonly h: number;
|
|
441
|
+
}
|
|
442
|
+
/** The logical view the adapter keeps in vars (720 × 1280 before the first resize). */
|
|
443
|
+
declare const viewOf: (world: World) => ViewSize;
|
|
444
|
+
/** What the player holds now: arrows / WASD and the pointer (pressed + where). */
|
|
445
|
+
interface Controls {
|
|
446
|
+
readonly keys: ReadonlySet<string>;
|
|
447
|
+
readonly pointer: {
|
|
448
|
+
readonly down: boolean;
|
|
449
|
+
readonly x: number;
|
|
450
|
+
readonly y: number;
|
|
451
|
+
};
|
|
452
|
+
/** -1..1 per axis from the held keys. */
|
|
453
|
+
axis(): {
|
|
454
|
+
x: number;
|
|
455
|
+
y: number;
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
/** Tracks held keys and the pointer from the input topic (the adapter sends press / move / release / key / key-up). */
|
|
459
|
+
declare function trackControls(world: World): Controls;
|
|
460
|
+
/** A square board centred in the view: cell size and the top-left corner. */
|
|
461
|
+
interface Board {
|
|
462
|
+
readonly cols: number;
|
|
463
|
+
readonly rows: number;
|
|
464
|
+
readonly cell: number;
|
|
465
|
+
readonly left: number;
|
|
466
|
+
readonly top: number;
|
|
467
|
+
}
|
|
468
|
+
declare function boardOf(view: ViewSize, cols: number, rows: number, area: {
|
|
469
|
+
top: number;
|
|
470
|
+
bottom: number;
|
|
471
|
+
widthShare?: number;
|
|
472
|
+
}): Board;
|
|
473
|
+
declare const cellCenter: (b: Board, col: number, row: number) => {
|
|
474
|
+
x: number;
|
|
475
|
+
y: number;
|
|
476
|
+
};
|
|
477
|
+
/** The cell under a point, or null outside the board. */
|
|
478
|
+
declare function cellAt(b: Board, x: number, y: number): {
|
|
479
|
+
col: number;
|
|
480
|
+
row: number;
|
|
481
|
+
} | null;
|
|
482
|
+
/** The board's piece colours (palette roles piece1..piece6). */
|
|
483
|
+
declare const PIECE_COLORS: readonly ["piece1", "piece2", "piece3", "piece4", "piece5", "piece6"];
|
|
484
|
+
/** Asks the adapter for an effect (sparks, a rising number, a shake). Logic never depends on it. */
|
|
485
|
+
declare const fx: (world: World, ev: FxEvent) => void;
|
|
486
|
+
/**
|
|
487
|
+
* Puts the backdrop behind the play: "side" — the sky, the sun, the far and near layers standing on
|
|
488
|
+
* `horizon` (a y in the view), "top" — the floor seen from above with scattered decor, "board" — a
|
|
489
|
+
* side backdrop dimmed behind a board. Called again on a resize: it replaces what it put.
|
|
490
|
+
*/
|
|
491
|
+
declare function placeBackdrop(world: World, kind: "side" | "top" | "board", horizon?: number, options?: {
|
|
492
|
+
pan?: boolean;
|
|
493
|
+
}): void;
|
|
494
|
+
/** The world scrolled by `dx` logical px (positive: the ground moved left): the layers follow at their speeds. */
|
|
495
|
+
declare function scrollBackdrop(world: World, dx: number): void;
|
|
496
|
+
/** Sets an actor's pose (and keeps the rest of its Visual). */
|
|
497
|
+
declare function setPose(world: World, e: Entity, pose: ActorPose): void;
|
|
498
|
+
/** Plays a one-shot on an actor (attack, hit, jump...). */
|
|
499
|
+
declare function act(world: World, e: Entity, a: ActorAct): void;
|
|
500
|
+
|
|
501
|
+
/** A stat bought between rounds. */
|
|
502
|
+
interface MetaStatDef {
|
|
503
|
+
/** The Character stat id (`StatID`). */
|
|
504
|
+
readonly id: string;
|
|
505
|
+
/** The world var the block reads (`meta:…`). */
|
|
506
|
+
readonly var: string;
|
|
507
|
+
readonly art: string;
|
|
508
|
+
readonly color: string;
|
|
509
|
+
/** Value per level (percent stats in percent, seconds stats in seconds). */
|
|
510
|
+
readonly perLevel: number;
|
|
511
|
+
/** "%" — a percent (the var gets value / 100); "s" — seconds; "" — a plain number. */
|
|
512
|
+
readonly unit: "%" | "s" | "";
|
|
513
|
+
readonly maxLevel: number;
|
|
514
|
+
/** Price of level 1 in the soft currency; each level costs `growth` more (geometric). */
|
|
515
|
+
readonly price: number;
|
|
516
|
+
readonly growth: number;
|
|
517
|
+
}
|
|
518
|
+
/** A hero of the game: who plays (a cast role of the pack) and the gems to open it (0 — everyone's). */
|
|
519
|
+
interface MetaHeroDef {
|
|
520
|
+
readonly id: string;
|
|
521
|
+
readonly cast: string;
|
|
522
|
+
readonly gems: number;
|
|
523
|
+
}
|
|
524
|
+
interface MetaGameDef {
|
|
525
|
+
/** The preset id it belongs to ("survivors", "runner"). */
|
|
526
|
+
readonly game: string;
|
|
527
|
+
/** The Character id of the stats; the progress key and the heroes' Character ids are made from it. */
|
|
528
|
+
readonly character: string;
|
|
529
|
+
readonly stats: readonly MetaStatDef[];
|
|
530
|
+
readonly heroes: readonly MetaHeroDef[];
|
|
531
|
+
/** How many levels (chapters) there are. */
|
|
532
|
+
readonly levels: number;
|
|
533
|
+
/** The soft coins the first finish of a level pays. */
|
|
534
|
+
firstClearGold(level: number): number;
|
|
535
|
+
/** Stars a level can give (0 — the game has none). */
|
|
536
|
+
readonly stars: number;
|
|
537
|
+
/** Stars (of all levels together) needed to play a level: a world's gate. None — only the level before. */
|
|
538
|
+
starsToEnter?(level: number): number;
|
|
539
|
+
}
|
|
540
|
+
/** The Character id of a hero that has to be opened (the first hero is everyone's and has none). */
|
|
541
|
+
declare const heroCharacterOf: (def: MetaGameDef, heroID: string) => string;
|
|
542
|
+
|
|
543
|
+
/**
|
|
544
|
+
* What stands on the road, and the one answer to each:
|
|
545
|
+
* wall — tall: only another lane gets you past;
|
|
546
|
+
* barrier — low: jump it or take another lane;
|
|
547
|
+
* pit — a hole in the lane: only a jump gets you over;
|
|
548
|
+
* mover — a foe running at you; it switches lane once, blinking first;
|
|
549
|
+
* train — a long wagon over several rows; its ramp takes you up onto the roof (coins up there),
|
|
550
|
+
* a wagon without a ramp is a long wall;
|
|
551
|
+
* rock — falls from above: its shadow runs on the lane first, then it lands and stays like a wall.
|
|
552
|
+
*/
|
|
553
|
+
type ObstacleKind = "wall" | "barrier" | "pit" | "mover" | "train" | "rock";
|
|
554
|
+
declare const OBSTACLE_KINDS: readonly ObstacleKind[];
|
|
555
|
+
type PowerId = "magnet" | "shield" | "double" | "dash" | "flight";
|
|
556
|
+
declare const POWER_IDS: readonly PowerId[];
|
|
557
|
+
interface PowerDef {
|
|
558
|
+
readonly art: string;
|
|
559
|
+
readonly color: string;
|
|
560
|
+
/** Seconds it lasts before the meta's upgrades. */
|
|
561
|
+
readonly seconds: number;
|
|
562
|
+
/** The meta var that adds seconds to it. */
|
|
563
|
+
readonly var: string;
|
|
564
|
+
/** How often it turns up among the power-ups of the road. */
|
|
565
|
+
readonly weight: number;
|
|
566
|
+
}
|
|
567
|
+
declare const POWERS: Readonly<Record<PowerId, PowerDef>>;
|
|
568
|
+
/** Levels of the game: each opens when the one before is finished. */
|
|
569
|
+
declare const RUNNER_LEVELS = 20;
|
|
570
|
+
interface RunnerLevel {
|
|
571
|
+
readonly level: number;
|
|
572
|
+
/** The road's length to the finish, px. */
|
|
573
|
+
readonly length: number;
|
|
574
|
+
/** Starting speed and the speed it reaches at the finish, px / s. */
|
|
575
|
+
readonly speed: number;
|
|
576
|
+
readonly topSpeed: number;
|
|
577
|
+
/** How busy the rows are (0..1). */
|
|
578
|
+
readonly density: number;
|
|
579
|
+
/** The kinds on this level. */
|
|
580
|
+
readonly kinds: readonly ObstacleKind[];
|
|
581
|
+
/** The newest kind (the level teaches it first). */
|
|
582
|
+
readonly fresh: ObstacleKind | null;
|
|
583
|
+
/** Share of the coins of the level that gives the second star. */
|
|
584
|
+
readonly coinStar: number;
|
|
585
|
+
/** Soft coins its first finish pays. */
|
|
586
|
+
readonly firstClearGold: number;
|
|
587
|
+
}
|
|
588
|
+
/**
|
|
589
|
+
* A level by its number (1-based, clamped). `difficulty` (0..1, the preset's knob) moves the speed and the
|
|
590
|
+
* density of all levels together; the level number moves them along the map.
|
|
591
|
+
*/
|
|
592
|
+
declare function levelOf$5(level: number, difficulty?: number): RunnerLevel;
|
|
593
|
+
/** The meters a distance shows (px of the road / 30). */
|
|
594
|
+
declare const metersOf: (px: number) => number;
|
|
595
|
+
/** A hero's own bonus in a run. */
|
|
596
|
+
type RunnerPerk = "none" | "heart" | "power";
|
|
597
|
+
interface RunnerHeroDef {
|
|
598
|
+
readonly id: string;
|
|
599
|
+
readonly cast: string;
|
|
600
|
+
readonly gems: number;
|
|
601
|
+
/** heart — one more heart; power — every power-up lasts a quarter longer. */
|
|
602
|
+
readonly perk: RunnerPerk;
|
|
603
|
+
}
|
|
604
|
+
declare const RUNNER_HEROES: readonly RunnerHeroDef[];
|
|
605
|
+
/** The Character id of the runner's stats (the seed of kit-game; the heroes are `kit-runner-hero2/3`). */
|
|
606
|
+
declare const RUNNER_CHARACTER = "kit-runner";
|
|
607
|
+
/**
|
|
608
|
+
* Stats bought between runs with the soft currency (the server's Character system). ⚠ The seed mirrors these
|
|
609
|
+
* numbers (`KitGameStarterFixtures` of the engine): the constructor's page draws by them without a server.
|
|
610
|
+
*/
|
|
611
|
+
declare const RUNNER_META_STATS: readonly MetaStatDef[];
|
|
612
|
+
declare const RUNNER_META: MetaGameDef;
|
|
613
|
+
|
|
614
|
+
type ItemKind = ObstacleKind | "ramp" | "coin" | "power" | "finish";
|
|
615
|
+
/** A thing on the road: its lane, what touching it does, how far it reaches along the road. */
|
|
616
|
+
declare const RoadItem: ComponentType<{
|
|
617
|
+
lane: number;
|
|
618
|
+
kind: ItemKind;
|
|
619
|
+
/** Width of its body along the road (a train, a pit: long). */
|
|
620
|
+
size: number;
|
|
621
|
+
/** Height above the road a coin floats at (a power-up too). */
|
|
622
|
+
alt: number;
|
|
623
|
+
power?: PowerId;
|
|
624
|
+
/** A mover: the lane it is heading to, the seconds of its warning. */
|
|
625
|
+
to?: number;
|
|
626
|
+
warn?: number;
|
|
627
|
+
/** A rock: landed. */
|
|
628
|
+
landed?: boolean;
|
|
629
|
+
/** A coin pulled by the magnet. */
|
|
630
|
+
pulled?: boolean;
|
|
631
|
+
}>;
|
|
632
|
+
/** The hero: its lane, its height over the road and its vertical speed. */
|
|
633
|
+
declare const Runner: ComponentType<{
|
|
634
|
+
lane: number;
|
|
635
|
+
size: number;
|
|
636
|
+
alt: number;
|
|
637
|
+
vy: number;
|
|
638
|
+
}>;
|
|
639
|
+
declare const laneRunnerBlock: BlockDef;
|
|
640
|
+
|
|
641
|
+
/** Weapons the hero carries (up to `MAX_WEAPONS`), each fires by itself. */
|
|
642
|
+
type WeaponId = "blaster" | "blades" | "aura" | "boomerang" | "lightning" | "drone";
|
|
643
|
+
/** Passives (up to `MAX_PASSIVES`): every level adds to one number of the hero. */
|
|
644
|
+
type PassiveId = "might" | "haste" | "area" | "swift" | "vigor" | "armor" | "magnet" | "luck" | "growth";
|
|
645
|
+
declare const MAX_LEVEL = 5;
|
|
646
|
+
declare const MAX_WEAPONS = 6;
|
|
647
|
+
declare const MAX_PASSIVES = 6;
|
|
648
|
+
/** Per level (index 0 = level 1). Level 5 is the weapon's strong form (a card says so). */
|
|
649
|
+
interface WeaponDef {
|
|
650
|
+
readonly id: WeaponId;
|
|
651
|
+
/** The kit's art drawn on its card and on the HUD. */
|
|
652
|
+
readonly art: string;
|
|
653
|
+
readonly color: string;
|
|
654
|
+
readonly damage: readonly number[];
|
|
655
|
+
/** Seconds between uses (blades and aura: the time a foe waits before the same blade or aura hurts it again). */
|
|
656
|
+
readonly cooldown: readonly number[];
|
|
657
|
+
/** Bullets, blades, boomerangs, chain jumps or drones. */
|
|
658
|
+
readonly count: readonly number[];
|
|
659
|
+
/** Foes one bullet goes through (blaster). */
|
|
660
|
+
readonly pierce?: readonly number[];
|
|
661
|
+
/** Reach, in units of the view's short side (blades' circle, aura's radius, boomerang's throw, chain's jump). */
|
|
662
|
+
readonly reach?: readonly number[];
|
|
663
|
+
}
|
|
664
|
+
declare const WEAPONS: Readonly<Record<WeaponId, WeaponDef>>;
|
|
665
|
+
declare const WEAPON_IDS: WeaponId[];
|
|
666
|
+
interface PassiveDef {
|
|
667
|
+
readonly id: PassiveId;
|
|
668
|
+
readonly art: string;
|
|
669
|
+
readonly color: string;
|
|
670
|
+
/** What one level adds (a share for percents, a number for hit points and armour). */
|
|
671
|
+
readonly step: number;
|
|
672
|
+
}
|
|
673
|
+
declare const PASSIVES: Readonly<Record<PassiveId, PassiveDef>>;
|
|
674
|
+
declare const PASSIVE_IDS: PassiveId[];
|
|
675
|
+
/** One choice of a level-up (or a chest): a new weapon / passive, or its next level; `heal` and `gold` when all is full. */
|
|
676
|
+
interface UpgradeOption {
|
|
677
|
+
readonly kind: "weapon" | "passive" | "heal" | "gold";
|
|
678
|
+
readonly id: string;
|
|
679
|
+
/** The level it brings (1 = new). */
|
|
680
|
+
readonly level: number;
|
|
681
|
+
}
|
|
682
|
+
type FoeKind = "swarm" | "grunt" | "archer" | "brute" | "charger" | "bomber" | "miniboss" | "boss";
|
|
683
|
+
interface FoeDef {
|
|
684
|
+
readonly kind: FoeKind;
|
|
685
|
+
/** The asset pack's cast role that plays it. */
|
|
686
|
+
readonly cast: string;
|
|
687
|
+
/** Hit points in units of the chapter's base foe. */
|
|
688
|
+
readonly hp: number;
|
|
689
|
+
/** Speed, px a second at 720. */
|
|
690
|
+
readonly speed: number;
|
|
691
|
+
/** Body size, share of the view's short side. */
|
|
692
|
+
readonly size: number;
|
|
693
|
+
/** Damage of a touch (archer: of its arrow). */
|
|
694
|
+
readonly damage: number;
|
|
695
|
+
/** Crystals of experience it drops. */
|
|
696
|
+
readonly xp: number;
|
|
697
|
+
/** Minutes (with the chapter's head start) before it joins the stream. */
|
|
698
|
+
readonly from: number;
|
|
699
|
+
/** Weight in the stream once it has joined. */
|
|
700
|
+
readonly weight: number;
|
|
701
|
+
}
|
|
702
|
+
declare const FOES: Readonly<Record<FoeKind, FoeDef>>;
|
|
703
|
+
declare const CHAPTERS = 10;
|
|
704
|
+
/** A chapter's numbers: later chapters are longer, their foes tougher, the stream starts further in. */
|
|
705
|
+
declare function chapterOf(chapter: number, baseSeconds: number): {
|
|
706
|
+
chapter: number;
|
|
707
|
+
/** Seconds to the final boss. */
|
|
708
|
+
duration: number;
|
|
709
|
+
/** Foe hit points ×. */
|
|
710
|
+
hp: number;
|
|
711
|
+
/** Foe damage ×. */
|
|
712
|
+
damage: number;
|
|
713
|
+
/** Minutes the stream is ahead (late kinds come sooner). */
|
|
714
|
+
headStart: number;
|
|
715
|
+
/** Gold of the first clear. */
|
|
716
|
+
firstClearGold: number;
|
|
717
|
+
};
|
|
718
|
+
/** Heroes: who plays (a cast role of the pack), the weapon they start with, their own bonus. */
|
|
719
|
+
interface HeroDef {
|
|
720
|
+
readonly id: string;
|
|
721
|
+
readonly cast: string;
|
|
722
|
+
readonly weapon: WeaponId;
|
|
723
|
+
/** One passive at level 1 from the start (null — none). */
|
|
724
|
+
readonly passive: PassiveId | null;
|
|
725
|
+
/** Price to open it in gems (0 — open from the start). */
|
|
726
|
+
readonly gems: number;
|
|
727
|
+
}
|
|
728
|
+
declare const HEROES: readonly HeroDef[];
|
|
729
|
+
|
|
730
|
+
declare const META_STATS: readonly MetaStatDef[];
|
|
731
|
+
/** The Character id of the survivors' meta stats (one for every hero: the upgrades are the player's). */
|
|
732
|
+
declare const META_CHARACTER = "kit-survivors";
|
|
733
|
+
/** Gems a revive / a reroll of the cards cost on the test page; a title charges the price of its spends (`Currency.Spends`). */
|
|
734
|
+
declare const REVIVE_GEMS = 30;
|
|
735
|
+
declare const REROLL_GEMS = 10;
|
|
736
|
+
/** The survivors' meta as the host shows it (chapters, upgrades, heroes). */
|
|
737
|
+
declare const SURVIVORS_META: MetaGameDef;
|
|
738
|
+
|
|
739
|
+
declare const ROUND_STARTED = "round-started";
|
|
740
|
+
declare const ROUND_OVER = "round-over";
|
|
741
|
+
declare const ROUND_ENDED = "round-ended";
|
|
742
|
+
declare const START_ROUND = "start-round";
|
|
743
|
+
/** The UI goes back to the game's home after a result (the start button again, the meta around it). */
|
|
744
|
+
declare const SHOW_START = "show-start";
|
|
745
|
+
/** A run's hero fell and may come back once: the host offers a revive (gems or an ad) and answers below. */
|
|
746
|
+
declare const REVIVE_OFFER = "revive-offer";
|
|
747
|
+
/** The host paid for the revive: the run goes on. */
|
|
748
|
+
declare const REVIVE = "revive";
|
|
749
|
+
/** The player said no to the revive: the run ends. */
|
|
750
|
+
declare const GIVE_UP = "give-up";
|
|
751
|
+
type RoundState = "ready" | "playing" | "ended";
|
|
752
|
+
declare const roundBlock: BlockDef;
|
|
753
|
+
|
|
754
|
+
declare const LEVEL_CLEARED = "level-cleared";
|
|
755
|
+
type ThingKind = "walker" | "spiky" | "hopper" | "flyer" | "gunner" | "boss" | "bullet" | "wave" | "coin" | "star" | "heart" | "key" | "chest" | "spring" | "mover" | "checkpoint" | "flag";
|
|
756
|
+
/** A body in the level, in tiles: x is its middle, y its bottom (feet). */
|
|
757
|
+
declare const Body: ComponentType<{
|
|
758
|
+
x: number;
|
|
759
|
+
y: number;
|
|
760
|
+
w: number;
|
|
761
|
+
h: number;
|
|
762
|
+
}>;
|
|
763
|
+
/** Something of the level that is not a tile: an enemy, a pickup, a spring, a moving platform… */
|
|
764
|
+
declare const Thing: ComponentType<{
|
|
765
|
+
kind: ThingKind;
|
|
766
|
+
vx: number;
|
|
767
|
+
vy: number;
|
|
768
|
+
dir: number;
|
|
769
|
+
t: number;
|
|
770
|
+
baseX: number;
|
|
771
|
+
baseY: number;
|
|
772
|
+
hp: number;
|
|
773
|
+
/** A star's index (0..2), a boss's attack. */
|
|
774
|
+
tag: string;
|
|
775
|
+
/** Seconds it cannot be hurt (a boss after a stomp). */
|
|
776
|
+
safe: number;
|
|
777
|
+
}>;
|
|
778
|
+
/** The hero. */
|
|
779
|
+
declare const Jumper: ComponentType<{
|
|
780
|
+
vx: number;
|
|
781
|
+
vy: number;
|
|
782
|
+
grounded: boolean;
|
|
783
|
+
facing: number;
|
|
784
|
+
jumps: number;
|
|
785
|
+
coyote: number;
|
|
786
|
+
buffer: number;
|
|
787
|
+
dash: number;
|
|
788
|
+
dashCd: number;
|
|
789
|
+
/** -1 / 1 — touching a wall on that side in the air. */
|
|
790
|
+
wall: number;
|
|
791
|
+
/** Seconds left of a sword swing, and before the next one. */
|
|
792
|
+
swing: number;
|
|
793
|
+
swingCd: number;
|
|
794
|
+
}>;
|
|
795
|
+
declare const platformerBlock: BlockDef;
|
|
796
|
+
|
|
797
|
+
/**
|
|
798
|
+
* A room of a level: rows of tiles, row 0 at the top, ROOM_ROWS rows.
|
|
799
|
+
* # ground (solid) = a platform (stand on it, jump through it from below)
|
|
800
|
+
* _ a crumbling platform ^ spikes
|
|
801
|
+
* M a moving platform T a spring
|
|
802
|
+
* o a coin H a heart * a big star's spot (the level keeps three)
|
|
803
|
+
* K a key B a chest (opens with the key)
|
|
804
|
+
* W walker (stomp it) S spiky walker (never stomp: go round or dash)
|
|
805
|
+
* J hopper (jumps in place) F flyer (flies a wave) G gunner (shoots along the ground)
|
|
806
|
+
* P the start C a checkpoint E the exit flag
|
|
807
|
+
*/
|
|
808
|
+
declare const ROOM_ROWS = 10;
|
|
809
|
+
/** What a room shows the player (a level opens them in order: the first levels teach one thing each). */
|
|
810
|
+
type RoomFeature = "walker" | "gaps" | "spikes" | "stairs" | "pits" | "spring" | "hopper" | "crumble" | "spiky" | "moving" | "flyer" | "key" | "gunner";
|
|
811
|
+
interface RoomDef {
|
|
812
|
+
readonly id: string;
|
|
813
|
+
readonly needs: readonly RoomFeature[];
|
|
814
|
+
readonly rows: readonly string[];
|
|
815
|
+
}
|
|
816
|
+
declare const ROOMS: readonly RoomDef[];
|
|
817
|
+
/** Worlds and their levels: the last level of a world is its boss. */
|
|
818
|
+
declare const WORLDS = 4;
|
|
819
|
+
declare const LEVELS_PER_WORLD = 5;
|
|
820
|
+
declare const PLATFORMER_LEVELS: number;
|
|
821
|
+
/** Stars needed to enter each world (all stars of the game: 3 a level, 60 in all). */
|
|
822
|
+
declare const WORLD_STARS: readonly number[];
|
|
823
|
+
interface PlatformerLevel {
|
|
824
|
+
readonly level: number;
|
|
825
|
+
readonly world: number;
|
|
826
|
+
/** 1..LEVELS_PER_WORLD inside its world. */
|
|
827
|
+
readonly index: number;
|
|
828
|
+
readonly boss: boolean;
|
|
829
|
+
readonly features: readonly RoomFeature[];
|
|
830
|
+
/** The newest feature (its room goes first). */
|
|
831
|
+
readonly fresh: RoomFeature | null;
|
|
832
|
+
/** Rooms between the start and the end (the checkpoint in the middle). */
|
|
833
|
+
readonly rooms: number;
|
|
834
|
+
/** The enemies' speed ×. */
|
|
835
|
+
readonly pace: number;
|
|
836
|
+
/** The boss's hit points (boss levels). */
|
|
837
|
+
readonly bossHp: number;
|
|
838
|
+
readonly firstClearGold: number;
|
|
839
|
+
}
|
|
840
|
+
declare function levelOf$4(level: number, difficulty?: number): PlatformerLevel;
|
|
841
|
+
/** Stars needed to play a level (its world's gate). */
|
|
842
|
+
declare const starsToEnter: (level: number) => number;
|
|
843
|
+
/** Abilities opened by all the stars the player has (they also open the hidden stars of earlier levels). */
|
|
844
|
+
type AbilityId = "double" | "dash" | "wall";
|
|
845
|
+
declare const ABILITIES: readonly {
|
|
846
|
+
readonly id: AbilityId;
|
|
847
|
+
readonly stars: number;
|
|
848
|
+
}[];
|
|
849
|
+
declare const abilitiesFor: (stars: number) => AbilityId[];
|
|
850
|
+
type PlatformerPerk = "none" | "heart" | "jump";
|
|
851
|
+
interface PlatformerHeroDef {
|
|
852
|
+
readonly id: string;
|
|
853
|
+
readonly cast: string;
|
|
854
|
+
readonly gems: number;
|
|
855
|
+
/** heart — one more heart; jump — jumps 15% higher. */
|
|
856
|
+
readonly perk: PlatformerPerk;
|
|
857
|
+
}
|
|
858
|
+
declare const PLATFORMER_HEROES: readonly PlatformerHeroDef[];
|
|
859
|
+
declare const PLATFORMER_CHARACTER = "kit-platformer";
|
|
860
|
+
/**
|
|
861
|
+
* Stats bought between levels with the soft currency (the server's Character system). ⚠ The seed mirrors these
|
|
862
|
+
* numbers (`KitGameStarterFixtures` of the engine).
|
|
863
|
+
*/
|
|
864
|
+
declare const PLATFORMER_META_STATS: readonly MetaStatDef[];
|
|
865
|
+
declare const PLATFORMER_META: MetaGameDef;
|
|
866
|
+
|
|
867
|
+
declare const Survivor: ComponentType<{
|
|
868
|
+
size: number;
|
|
869
|
+
}>;
|
|
870
|
+
declare const Foe: ComponentType<{
|
|
871
|
+
kind: FoeKind;
|
|
872
|
+
hp: number;
|
|
873
|
+
maxHp: number;
|
|
874
|
+
speed: number;
|
|
875
|
+
size: number;
|
|
876
|
+
damage: number;
|
|
877
|
+
xp: number;
|
|
878
|
+
elite: boolean;
|
|
879
|
+
/** A timer of its own move (an archer's shot, a charger's dash, a boss's attack). */
|
|
880
|
+
t: number;
|
|
881
|
+
phase: "walk" | "wind" | "dash";
|
|
882
|
+
vx: number;
|
|
883
|
+
vy: number;
|
|
884
|
+
/** World time each weapon last hurt it (blades, aura: one hurt per their cooldown). */
|
|
885
|
+
hurtAt: Partial<Record<string, number>>;
|
|
886
|
+
/** Next attack of a boss. */
|
|
887
|
+
next: number;
|
|
888
|
+
}>;
|
|
889
|
+
/** The hero's bullet (blaster, drones): flies, goes through `pierce` foes. */
|
|
890
|
+
declare const Shot: ComponentType<{
|
|
891
|
+
vx: number;
|
|
892
|
+
vy: number;
|
|
893
|
+
life: number;
|
|
894
|
+
damage: number;
|
|
895
|
+
pierce: number;
|
|
896
|
+
hit: number[];
|
|
897
|
+
by: string;
|
|
898
|
+
}>;
|
|
899
|
+
/** A foe's bullet (archers, the boss's ring). */
|
|
900
|
+
declare const Bullet: ComponentType<{
|
|
901
|
+
vx: number;
|
|
902
|
+
vy: number;
|
|
903
|
+
life: number;
|
|
904
|
+
damage: number;
|
|
905
|
+
}>;
|
|
906
|
+
declare const Drop: ComponentType<{
|
|
907
|
+
kind: "xp" | "coin" | "food" | "magnet" | "bomb" | "chest";
|
|
908
|
+
value: number;
|
|
909
|
+
pulled: boolean;
|
|
910
|
+
}>;
|
|
911
|
+
declare const LEVEL_UP = "level-up";
|
|
912
|
+
declare const UPGRADE_PICKED = "upgrade-picked";
|
|
913
|
+
declare const UPGRADE_PICK = "upgrade-pick";
|
|
914
|
+
declare const UPGRADE_REROLL = "upgrade-reroll";
|
|
915
|
+
|
|
916
|
+
declare const BOSS_SPAWNED = "boss-spawned";
|
|
917
|
+
declare const BOSS_DEFEATED = "boss-defeated";
|
|
918
|
+
/** The hero's build: weapon / passive → level. */
|
|
919
|
+
interface SurvivorsBuild {
|
|
920
|
+
readonly weapons: Readonly<Partial<Record<WeaponId, number>>>;
|
|
921
|
+
readonly passives: Readonly<Partial<Record<PassiveId, number>>>;
|
|
922
|
+
}
|
|
923
|
+
/** A build written into a var ("w:blaster:2,p:might:1") — the host reads it after a remount. */
|
|
924
|
+
declare const buildToVar: (b: SurvivorsBuild) => string;
|
|
925
|
+
declare const buildFromVar: (s: unknown) => SurvivorsBuild;
|
|
926
|
+
declare const offerToVar: (o: readonly UpgradeOption[]) => string;
|
|
927
|
+
declare const offerFromVar: (s: unknown) => UpgradeOption[];
|
|
928
|
+
declare const survivorsBlock: BlockDef;
|
|
929
|
+
|
|
930
|
+
/** physical — cut by armour; magic — cut by resistance; true — cut by nothing. */
|
|
931
|
+
type DamageType = "physical" | "magic" | "true";
|
|
932
|
+
/** What a tower's shot does. Optional fields add an effect; a tower mixes as many as it needs. */
|
|
933
|
+
interface TowerStats {
|
|
934
|
+
readonly damage: number;
|
|
935
|
+
readonly type: DamageType;
|
|
936
|
+
/** Cells. */
|
|
937
|
+
readonly range: number;
|
|
938
|
+
/** Shots a second. */
|
|
939
|
+
readonly rate: number;
|
|
940
|
+
/** It hits flyers. */
|
|
941
|
+
readonly air: boolean;
|
|
942
|
+
/** It hits walkers. */
|
|
943
|
+
readonly ground: boolean;
|
|
944
|
+
/** The picture of the shot and its speed (cells a second). */
|
|
945
|
+
readonly shot: string;
|
|
946
|
+
readonly shotSpeed: number;
|
|
947
|
+
/** The shot flies in an arc (a shell). */
|
|
948
|
+
readonly lob?: boolean;
|
|
949
|
+
/** The hit is instant: a zap from the tower to the foe (and on along the chain). */
|
|
950
|
+
readonly beam?: boolean;
|
|
951
|
+
/** Damage around the hit, cells. */
|
|
952
|
+
readonly splash?: number;
|
|
953
|
+
/** Speed × (1 − slow) for slowTime seconds. */
|
|
954
|
+
readonly slow?: number;
|
|
955
|
+
readonly slowTime?: number;
|
|
956
|
+
/** The hit jumps on to this many more foes (each takes 70% of the one before). */
|
|
957
|
+
readonly chain?: number;
|
|
958
|
+
/** Damage a second for burnTime seconds (true damage). */
|
|
959
|
+
readonly burn?: number;
|
|
960
|
+
readonly burnTime?: number;
|
|
961
|
+
/** A chance to stop the foe for stunTime seconds. */
|
|
962
|
+
readonly stun?: number;
|
|
963
|
+
readonly stunTime?: number;
|
|
964
|
+
/** The share of armour it ignores (0..1). */
|
|
965
|
+
readonly pierce?: number;
|
|
966
|
+
/** A chance of a double hit. */
|
|
967
|
+
readonly crit?: number;
|
|
968
|
+
/** Foes shot at once (the furthest ones in range). */
|
|
969
|
+
readonly multishot?: number;
|
|
970
|
+
}
|
|
971
|
+
interface TowerTierDef {
|
|
972
|
+
/** Gold to reach this tier (the first: to build). */
|
|
973
|
+
readonly cost: number;
|
|
974
|
+
/** What changes from the tier below. */
|
|
975
|
+
readonly stats: Partial<TowerStats>;
|
|
976
|
+
readonly art: string;
|
|
977
|
+
}
|
|
978
|
+
interface TowerBranchDef {
|
|
979
|
+
readonly id: string;
|
|
980
|
+
readonly cost: number;
|
|
981
|
+
/** What changes from the last tier. */
|
|
982
|
+
readonly stats: Partial<TowerStats>;
|
|
983
|
+
readonly art: string;
|
|
984
|
+
}
|
|
985
|
+
interface TowerDef {
|
|
986
|
+
readonly id: string;
|
|
987
|
+
/** Tier 1's stats; tiers add to them. */
|
|
988
|
+
readonly base: TowerStats;
|
|
989
|
+
readonly tiers: readonly TowerTierDef[];
|
|
990
|
+
/** The fourth level: one of these (opened at BRANCH_LEVEL). */
|
|
991
|
+
readonly branches: readonly TowerBranchDef[];
|
|
992
|
+
/** The first level it can be built on. */
|
|
993
|
+
readonly unlockLevel: number;
|
|
994
|
+
/** The meta var that adds to its power (damage, slow time, burn), a share: 0.12 = +12%. */
|
|
995
|
+
readonly metaVar: string;
|
|
996
|
+
}
|
|
997
|
+
declare const TOWERS: readonly TowerDef[];
|
|
998
|
+
/** The level the fourth-level branches open on. */
|
|
999
|
+
declare const BRANCH_LEVEL = 6;
|
|
1000
|
+
/** The share of the gold spent on a tower that selling gives back. */
|
|
1001
|
+
declare const SELL_SHARE = 0.7;
|
|
1002
|
+
declare const towerOf: (id: string) => TowerDef | undefined;
|
|
1003
|
+
/** A tower's stats at `tier` (1..tiers), or its branch. */
|
|
1004
|
+
declare function towerStats(def: TowerDef, tier: number, branch?: string | null): TowerStats;
|
|
1005
|
+
/** The gold spent on a tower so far. */
|
|
1006
|
+
declare function towerSpent(def: TowerDef, tier: number, branch?: string | null): number;
|
|
1007
|
+
declare const towerArt: (def: TowerDef, tier: number, branch?: string | null) => string;
|
|
1008
|
+
interface EnemyDef$1 {
|
|
1009
|
+
readonly id: string;
|
|
1010
|
+
/** The asset pack's cast (its look). */
|
|
1011
|
+
readonly cast: string;
|
|
1012
|
+
readonly variant?: number;
|
|
1013
|
+
/** Hit points, × the level's base. */
|
|
1014
|
+
readonly hp: number;
|
|
1015
|
+
/** Cells a second. */
|
|
1016
|
+
readonly speed: number;
|
|
1017
|
+
/** Physical damage cut (0..0.9). */
|
|
1018
|
+
readonly armor: number;
|
|
1019
|
+
/** Magic damage cut (0..0.9). */
|
|
1020
|
+
readonly resist: number;
|
|
1021
|
+
/** Flies over the road: walls of soldiers and shells do not reach it. */
|
|
1022
|
+
readonly flying?: boolean;
|
|
1023
|
+
/** Gold for felling it. */
|
|
1024
|
+
readonly bounty: number;
|
|
1025
|
+
/** Lives it takes through the gate. */
|
|
1026
|
+
readonly leak: number;
|
|
1027
|
+
/** Its height, × a cell. */
|
|
1028
|
+
readonly size: number;
|
|
1029
|
+
/** Damage a second to a soldier holding it, × the level's base hp. */
|
|
1030
|
+
readonly hit: number;
|
|
1031
|
+
/** Heals the foes around it: `share` of their max hit points every `every` seconds. */
|
|
1032
|
+
readonly heals?: {
|
|
1033
|
+
readonly radius: number;
|
|
1034
|
+
readonly share: number;
|
|
1035
|
+
readonly every: number;
|
|
1036
|
+
};
|
|
1037
|
+
/** Falls apart into smaller foes. */
|
|
1038
|
+
readonly splits?: {
|
|
1039
|
+
readonly into: string;
|
|
1040
|
+
readonly count: number;
|
|
1041
|
+
};
|
|
1042
|
+
/** Calls foes onto the road behind it. */
|
|
1043
|
+
readonly summons?: {
|
|
1044
|
+
readonly id: string;
|
|
1045
|
+
readonly count: number;
|
|
1046
|
+
readonly every: number;
|
|
1047
|
+
};
|
|
1048
|
+
/** Below `below` of its hit points it runs `speed` × faster. */
|
|
1049
|
+
readonly enrage?: {
|
|
1050
|
+
readonly below: number;
|
|
1051
|
+
readonly speed: number;
|
|
1052
|
+
};
|
|
1053
|
+
/** A world's boss (the last wave of its last level). */
|
|
1054
|
+
readonly boss?: number;
|
|
1055
|
+
/** The first level it walks in waves (0: never by itself — a split, a summon, a boss). */
|
|
1056
|
+
readonly firstLevel: number;
|
|
1057
|
+
/** Wave budget it takes. */
|
|
1058
|
+
readonly cost: number;
|
|
1059
|
+
/** A small picture over its hit points (what it resists). */
|
|
1060
|
+
readonly badge?: string;
|
|
1061
|
+
}
|
|
1062
|
+
declare const ENEMIES$1: readonly EnemyDef$1[];
|
|
1063
|
+
declare const enemyOf$1: (id: string) => EnemyDef$1 | undefined;
|
|
1064
|
+
interface SpellDef {
|
|
1065
|
+
readonly id: string;
|
|
1066
|
+
readonly icon: string;
|
|
1067
|
+
/** strike — meteors on a spot; summon — soldiers on the road who hold the foes. */
|
|
1068
|
+
readonly kind: "strike" | "summon";
|
|
1069
|
+
/** Seconds. */
|
|
1070
|
+
readonly cooldown: number;
|
|
1071
|
+
readonly unlockLevel: number;
|
|
1072
|
+
/** strike: damage of one meteor (× the level's base hp), how many, their radius (cells). */
|
|
1073
|
+
readonly damage?: number;
|
|
1074
|
+
readonly count?: number;
|
|
1075
|
+
readonly radius?: number;
|
|
1076
|
+
readonly burn?: number;
|
|
1077
|
+
/** summon: the soldiers' look, hit points and damage a second (× the level's base hp), seconds they stay. */
|
|
1078
|
+
readonly cast?: string;
|
|
1079
|
+
readonly hp?: number;
|
|
1080
|
+
readonly dps?: number;
|
|
1081
|
+
readonly time?: number;
|
|
1082
|
+
}
|
|
1083
|
+
declare const SPELLS: readonly SpellDef[];
|
|
1084
|
+
/**
|
|
1085
|
+
* A map: MAP_ROWS rows of MAP_COLS cells, row 0 at the top.
|
|
1086
|
+
* . grass # road S an entry (foes come in here; on an edge they walk in from outside)
|
|
1087
|
+
* X the gate (a foe that reaches it takes lives) o a build spot (the only cells towers stand on)
|
|
1088
|
+
* t a tree r a rock ~ water * a bush
|
|
1089
|
+
* The road is traced from each entry to the gate (always the step nearer the gate), so two roads may merge.
|
|
1090
|
+
*/
|
|
1091
|
+
declare const MAP_COLS = 9;
|
|
1092
|
+
declare const MAP_ROWS = 13;
|
|
1093
|
+
interface MapDef {
|
|
1094
|
+
readonly id: string;
|
|
1095
|
+
readonly rows: readonly string[];
|
|
1096
|
+
}
|
|
1097
|
+
declare const MAPS: readonly MapDef[];
|
|
1098
|
+
type Mirror = "none" | "x" | "y";
|
|
1099
|
+
/** A map turned over (a level may play one the other way round). */
|
|
1100
|
+
declare function mirrored(map: MapDef, mirror: Mirror): readonly string[];
|
|
1101
|
+
interface Cell {
|
|
1102
|
+
readonly col: number;
|
|
1103
|
+
readonly row: number;
|
|
1104
|
+
}
|
|
1105
|
+
interface TracedMap {
|
|
1106
|
+
readonly rows: readonly string[];
|
|
1107
|
+
/** One road a entry, from the entry to the gate (cells). */
|
|
1108
|
+
readonly paths: readonly (readonly Cell[])[];
|
|
1109
|
+
readonly gate: Cell;
|
|
1110
|
+
readonly spots: readonly Cell[];
|
|
1111
|
+
}
|
|
1112
|
+
/** The roads of a map: from every entry, always the step nearer the gate. Throws on a broken map (tests run it). */
|
|
1113
|
+
declare function traceMap(rows: readonly string[]): TracedMap;
|
|
1114
|
+
declare const TD_WORLDS = 4;
|
|
1115
|
+
declare const TD_LEVELS_PER_WORLD = 5;
|
|
1116
|
+
declare const TD_LEVELS: number;
|
|
1117
|
+
/** Stars needed to enter each world (3 a level, 60 in all). */
|
|
1118
|
+
declare const TD_WORLD_STARS: readonly number[];
|
|
1119
|
+
/** The map of every level, in order (the fourth level of a world plays an earlier map turned over). */
|
|
1120
|
+
declare const LEVEL_MAPS: readonly {
|
|
1121
|
+
readonly map: string;
|
|
1122
|
+
readonly mirror: Mirror;
|
|
1123
|
+
}[];
|
|
1124
|
+
/** A group of one kind of foe in a wave: `count` of them, `gap` seconds apart, from `delay` into the wave. */
|
|
1125
|
+
interface WaveGroup {
|
|
1126
|
+
readonly enemy: string;
|
|
1127
|
+
readonly count: number;
|
|
1128
|
+
readonly gap: number;
|
|
1129
|
+
readonly delay: number;
|
|
1130
|
+
/** Which entry (an index into the map's entries; wraps). */
|
|
1131
|
+
readonly entry: number;
|
|
1132
|
+
}
|
|
1133
|
+
interface WaveDef {
|
|
1134
|
+
readonly groups: readonly WaveGroup[];
|
|
1135
|
+
}
|
|
1136
|
+
interface TdLevel {
|
|
1137
|
+
readonly level: number;
|
|
1138
|
+
readonly world: number;
|
|
1139
|
+
readonly index: number;
|
|
1140
|
+
readonly boss: boolean;
|
|
1141
|
+
readonly map: string;
|
|
1142
|
+
readonly mirror: Mirror;
|
|
1143
|
+
/** A foe's hit points at hp × 1 (grows a level, and wave by wave inside it). */
|
|
1144
|
+
readonly hp: number;
|
|
1145
|
+
readonly waves: readonly WaveDef[];
|
|
1146
|
+
readonly gold: number;
|
|
1147
|
+
/** Bounties × (later levels pay more). */
|
|
1148
|
+
readonly bounty: number;
|
|
1149
|
+
readonly towers: readonly string[];
|
|
1150
|
+
readonly spells: readonly string[];
|
|
1151
|
+
readonly branches: boolean;
|
|
1152
|
+
/** The foe new on this level, or null. */
|
|
1153
|
+
readonly fresh: string | null;
|
|
1154
|
+
readonly enemies: readonly string[];
|
|
1155
|
+
readonly firstClearGold: number;
|
|
1156
|
+
}
|
|
1157
|
+
/**
|
|
1158
|
+
* The waves of a level: a budget a wave, spent on the foes open by then; the new foe shows itself early.
|
|
1159
|
+
* `foes`: the wave foes this game plays with (GameSpec content), every one when omitted.
|
|
1160
|
+
*/
|
|
1161
|
+
declare function wavesOf(level: number, entries: number, foes?: readonly string[]): WaveDef[];
|
|
1162
|
+
declare function levelOf$3(level: number, difficulty?: number, foes?: readonly string[]): TdLevel;
|
|
1163
|
+
/** Stars needed to play a level (its world's gate). */
|
|
1164
|
+
declare const tdStarsToEnter: (level: number) => number;
|
|
1165
|
+
/** The stars a cleared level gives by the lives kept: all of them nearly — three. */
|
|
1166
|
+
declare const starsFor: (lives: number, start: number) => number;
|
|
1167
|
+
/** Lives a revive gives back. */
|
|
1168
|
+
declare const REVIVE_LIVES = 5;
|
|
1169
|
+
/** Lives at a level's start (before the meta's). */
|
|
1170
|
+
declare const TD_LIVES = 20;
|
|
1171
|
+
/** gold — 25% more gold at the start; spells — spells come back 30% sooner. */
|
|
1172
|
+
type TdPerk = "none" | "gold" | "spells";
|
|
1173
|
+
interface TdHeroDef {
|
|
1174
|
+
readonly id: string;
|
|
1175
|
+
readonly cast: string;
|
|
1176
|
+
readonly gems: number;
|
|
1177
|
+
readonly perk: TdPerk;
|
|
1178
|
+
}
|
|
1179
|
+
declare const TD_HEROES: readonly TdHeroDef[];
|
|
1180
|
+
declare const TD_CHARACTER = "kit-td";
|
|
1181
|
+
/**
|
|
1182
|
+
* Upgrades bought between levels with the soft currency (the server's Character system): one a tower (a new
|
|
1183
|
+
* tower gets its own row here and in the seed), the start gold, lives, spells. ⚠ The seed mirrors these numbers
|
|
1184
|
+
* (`KitGameStarterFixtures` of the engine).
|
|
1185
|
+
*/
|
|
1186
|
+
declare const TD_META_STATS: readonly MetaStatDef[];
|
|
1187
|
+
declare const TD_META: MetaGameDef;
|
|
1188
|
+
|
|
1189
|
+
declare const WAVE_STARTED = "wave-started";
|
|
1190
|
+
/** A build spot of the map. */
|
|
1191
|
+
declare const Spot: ComponentType<{
|
|
1192
|
+
index: number;
|
|
1193
|
+
col: number;
|
|
1194
|
+
row: number;
|
|
1195
|
+
}>;
|
|
1196
|
+
/** A tower on a spot: its kind (a TOWERS id), tier, branch ("" — none yet). */
|
|
1197
|
+
declare const Tower: ComponentType<{
|
|
1198
|
+
spot: number;
|
|
1199
|
+
kind: string;
|
|
1200
|
+
tier: number;
|
|
1201
|
+
branch: string;
|
|
1202
|
+
cooldown: number;
|
|
1203
|
+
}>;
|
|
1204
|
+
/** A foe on the road: its kind (an ENEMIES id), where it is on its route (cells walked), what is on it. */
|
|
1205
|
+
declare const Raider: ComponentType<{
|
|
1206
|
+
kind: string;
|
|
1207
|
+
hp: number;
|
|
1208
|
+
maxHp: number;
|
|
1209
|
+
route: number;
|
|
1210
|
+
progress: number;
|
|
1211
|
+
/** Cells, refreshed each frame. */
|
|
1212
|
+
x: number;
|
|
1213
|
+
y: number;
|
|
1214
|
+
slow: number;
|
|
1215
|
+
slowLeft: number;
|
|
1216
|
+
stun: number;
|
|
1217
|
+
burn: number;
|
|
1218
|
+
burnLeft: number;
|
|
1219
|
+
healCd: number;
|
|
1220
|
+
summonCd: number;
|
|
1221
|
+
/** The soldier holding it, or -1. */
|
|
1222
|
+
heldBy: number;
|
|
1223
|
+
enraged: boolean;
|
|
1224
|
+
/** The wave it came with (its hit points grow with it). */
|
|
1225
|
+
wave: number;
|
|
1226
|
+
}>;
|
|
1227
|
+
/** A shot in flight (px). */
|
|
1228
|
+
declare const Missile: ComponentType<{
|
|
1229
|
+
target: number;
|
|
1230
|
+
x: number;
|
|
1231
|
+
y: number;
|
|
1232
|
+
ax: number;
|
|
1233
|
+
ay: number;
|
|
1234
|
+
dist0: number;
|
|
1235
|
+
went: number;
|
|
1236
|
+
stats: TowerStats;
|
|
1237
|
+
power: number;
|
|
1238
|
+
crit: boolean;
|
|
1239
|
+
}>;
|
|
1240
|
+
/** A soldier of the reinforcement spell, on a route. */
|
|
1241
|
+
declare const Soldier: ComponentType<{
|
|
1242
|
+
hp: number;
|
|
1243
|
+
maxHp: number;
|
|
1244
|
+
dps: number;
|
|
1245
|
+
left: number;
|
|
1246
|
+
route: number;
|
|
1247
|
+
progress: number;
|
|
1248
|
+
swing: number;
|
|
1249
|
+
}>;
|
|
1250
|
+
declare const towerDefenseBlock: BlockDef;
|
|
1251
|
+
|
|
1252
|
+
/** A piece on the screen: its id in the board's logic and the cell it moves to. */
|
|
1253
|
+
declare const Gem: ComponentType<{
|
|
1254
|
+
id: number;
|
|
1255
|
+
col: number;
|
|
1256
|
+
row: number;
|
|
1257
|
+
kind: number;
|
|
1258
|
+
}>;
|
|
1259
|
+
declare const match3Block: BlockDef;
|
|
1260
|
+
|
|
1261
|
+
type SpecialKind = string;
|
|
1262
|
+
interface SpecialDef {
|
|
1263
|
+
readonly id: SpecialKind;
|
|
1264
|
+
/** The cells it clears when it fires: row, col, cross, cross:N, area:N, color, all. */
|
|
1265
|
+
readonly shape: string;
|
|
1266
|
+
/** Drawn over the piece (the rainbow is a piece of its own). */
|
|
1267
|
+
readonly art: string;
|
|
1268
|
+
/** Does a match group make it: its longest run, whether runs cross (L / T), the longest run's direction. */
|
|
1269
|
+
readonly make: ((longest: number, crossing: boolean, dir: "h" | "v") => boolean) | null;
|
|
1270
|
+
}
|
|
1271
|
+
/** The first row whose `make` fits wins (so five in a row is a rainbow before it is a bomb). */
|
|
1272
|
+
declare const SPECIALS: readonly SpecialDef[];
|
|
1273
|
+
interface ObstacleDef$1 {
|
|
1274
|
+
readonly id: string;
|
|
1275
|
+
/** under — under a piece (hit when it is cleared); over — over it (it cannot move; a clear breaks the layer);
|
|
1276
|
+
* block — instead of a piece (hit by a match next to it, `hitByNear`, or by an effect on it). */
|
|
1277
|
+
readonly layer: "under" | "over" | "block";
|
|
1278
|
+
/** Hit points it gets when an enemy puts it down. */
|
|
1279
|
+
readonly hp: number;
|
|
1280
|
+
readonly art: string;
|
|
1281
|
+
readonly hitByNear?: boolean;
|
|
1282
|
+
/** Grows to a neighbour after a move that cleared none of it. */
|
|
1283
|
+
readonly spreads?: boolean;
|
|
1284
|
+
/** At most this many on the board from enemies' spells (so a board never chokes). */
|
|
1285
|
+
readonly max?: number;
|
|
1286
|
+
}
|
|
1287
|
+
declare const OBSTACLES$1: Readonly<Record<string, ObstacleDef$1>>;
|
|
1288
|
+
type Element = "fire" | "water" | "nature" | "light" | "dark";
|
|
1289
|
+
/** What an element is strong against (×1.5 on it; the same element ×0.5). */
|
|
1290
|
+
declare const ELEMENTS: Readonly<Record<Element, {
|
|
1291
|
+
readonly beats: readonly Element[];
|
|
1292
|
+
readonly color: string;
|
|
1293
|
+
}>>;
|
|
1294
|
+
interface PieceDef {
|
|
1295
|
+
/** The colour index on the board. */
|
|
1296
|
+
readonly index: number;
|
|
1297
|
+
readonly art: string;
|
|
1298
|
+
readonly color: string;
|
|
1299
|
+
/** attack — hits the foe with its element; heal — heals the hero; shield — blocks the next blow. */
|
|
1300
|
+
readonly role: "attack" | "heal" | "shield";
|
|
1301
|
+
readonly element?: Element;
|
|
1302
|
+
}
|
|
1303
|
+
declare const PIECES: readonly PieceDef[];
|
|
1304
|
+
/** What a foe does on its turn after striking. */
|
|
1305
|
+
type EnemySkill = {
|
|
1306
|
+
readonly kind: "sow";
|
|
1307
|
+
readonly obstacle: string;
|
|
1308
|
+
readonly count: number;
|
|
1309
|
+
} | {
|
|
1310
|
+
readonly kind: "heal";
|
|
1311
|
+
readonly share: number;
|
|
1312
|
+
} | {
|
|
1313
|
+
readonly kind: "rage";
|
|
1314
|
+
readonly mult: number;
|
|
1315
|
+
};
|
|
1316
|
+
interface EnemyDef {
|
|
1317
|
+
readonly id: string;
|
|
1318
|
+
readonly cast: string;
|
|
1319
|
+
readonly variant?: number;
|
|
1320
|
+
readonly element: Element;
|
|
1321
|
+
/** Hit points and a blow, × the level's base. */
|
|
1322
|
+
readonly hp: number;
|
|
1323
|
+
readonly attack: number;
|
|
1324
|
+
/** Moves between its blows. */
|
|
1325
|
+
readonly every: number;
|
|
1326
|
+
readonly skill?: EnemySkill;
|
|
1327
|
+
readonly boss?: boolean;
|
|
1328
|
+
/** Below this share of its hit points it strikes every `every - 1` moves. */
|
|
1329
|
+
readonly enrage?: number;
|
|
1330
|
+
readonly size: number;
|
|
1331
|
+
}
|
|
1332
|
+
declare const ENEMIES: readonly EnemyDef[];
|
|
1333
|
+
declare const enemyOf: (id: string) => EnemyDef | undefined;
|
|
1334
|
+
interface SkillDef$2 {
|
|
1335
|
+
readonly id: string;
|
|
1336
|
+
readonly art: string;
|
|
1337
|
+
/** Mana to cast. */
|
|
1338
|
+
readonly mana: number;
|
|
1339
|
+
/** shape — clears a shape round the cell the player taps (bigger from `bigAt` skill power); storm — turns pieces
|
|
1340
|
+
* into specials and fires them (more with power). */
|
|
1341
|
+
readonly kind: "shape" | "storm";
|
|
1342
|
+
readonly shape?: string;
|
|
1343
|
+
readonly bigShape?: string;
|
|
1344
|
+
readonly bigAt?: number;
|
|
1345
|
+
readonly count?: number;
|
|
1346
|
+
/** Bonus damage to the foe, × the hero's attack. */
|
|
1347
|
+
readonly damage: number;
|
|
1348
|
+
}
|
|
1349
|
+
declare const SKILLS$2: readonly SkillDef$2[];
|
|
1350
|
+
declare const skillOf$2: (id: string) => SkillDef$2 | undefined;
|
|
1351
|
+
interface M3HeroDef {
|
|
1352
|
+
readonly id: string;
|
|
1353
|
+
readonly cast: string;
|
|
1354
|
+
readonly gems: number;
|
|
1355
|
+
readonly element: Element;
|
|
1356
|
+
readonly skill: string;
|
|
1357
|
+
}
|
|
1358
|
+
declare const M3_HEROES: readonly M3HeroDef[];
|
|
1359
|
+
type GoalDef$1 = {
|
|
1360
|
+
readonly kind: "color";
|
|
1361
|
+
readonly color: number;
|
|
1362
|
+
readonly count: number;
|
|
1363
|
+
} | {
|
|
1364
|
+
readonly kind: "clear";
|
|
1365
|
+
readonly obstacle: string;
|
|
1366
|
+
} | {
|
|
1367
|
+
readonly kind: "drops";
|
|
1368
|
+
readonly count: number;
|
|
1369
|
+
} | {
|
|
1370
|
+
readonly kind: "score";
|
|
1371
|
+
readonly value: number;
|
|
1372
|
+
};
|
|
1373
|
+
type LevelDef$2 = {
|
|
1374
|
+
readonly kind: "goal";
|
|
1375
|
+
readonly board: string;
|
|
1376
|
+
readonly moves: number;
|
|
1377
|
+
readonly colors: number;
|
|
1378
|
+
readonly goals: readonly GoalDef$1[];
|
|
1379
|
+
readonly drops?: number;
|
|
1380
|
+
} | {
|
|
1381
|
+
readonly kind: "battle";
|
|
1382
|
+
readonly board: string;
|
|
1383
|
+
readonly elements: number;
|
|
1384
|
+
readonly enemies: readonly string[];
|
|
1385
|
+
};
|
|
1386
|
+
/** 4 worlds × 10: two goal levels, a battle, … the tenth a boss. */
|
|
1387
|
+
declare const LEVELS$2: readonly LevelDef$2[];
|
|
1388
|
+
declare const M3_LEVELS_PER_WORLD = 10;
|
|
1389
|
+
declare const M3_WORLDS = 4;
|
|
1390
|
+
declare const M3_LEVELS: number;
|
|
1391
|
+
/** Stars needed to enter each world (3 a level, 120 in all). */
|
|
1392
|
+
declare const M3_WORLD_STARS: readonly number[];
|
|
1393
|
+
interface M3Level {
|
|
1394
|
+
readonly level: number;
|
|
1395
|
+
readonly world: number;
|
|
1396
|
+
readonly index: number;
|
|
1397
|
+
readonly def: LevelDef$2;
|
|
1398
|
+
readonly boss: boolean;
|
|
1399
|
+
/** The board's colour indices. */
|
|
1400
|
+
readonly colors: readonly number[];
|
|
1401
|
+
/** A foe's hit points and blow at × 1. */
|
|
1402
|
+
readonly enemyHp: number;
|
|
1403
|
+
readonly enemyAttack: number;
|
|
1404
|
+
readonly firstClearGold: number;
|
|
1405
|
+
}
|
|
1406
|
+
declare function levelOf$2(level: number, difficulty?: number): M3Level;
|
|
1407
|
+
declare const m3StarsToEnter: (level: number) => number;
|
|
1408
|
+
declare const M3_CHARACTER = "kit-match3";
|
|
1409
|
+
/**
|
|
1410
|
+
* The hero's upgrades bought between levels with the soft currency (the server's Character system). ⚠ The seed
|
|
1411
|
+
* mirrors these numbers (`KitGameStarterFixtures` of the engine).
|
|
1412
|
+
*/
|
|
1413
|
+
declare const M3_META_STATS: readonly MetaStatDef[];
|
|
1414
|
+
declare const M3_META: MetaGameDef;
|
|
1415
|
+
|
|
1416
|
+
/** Colours by [row][col]; null — no matchable piece. */
|
|
1417
|
+
type KindGrid = Array<Array<number | null>>;
|
|
1418
|
+
/** Every cell in a run of three or more of one colour, as "col,row". */
|
|
1419
|
+
declare function findMatches(grid: KindGrid): Set<string>;
|
|
1420
|
+
/** Is there a swap of neighbours that makes a match (on a plain grid). */
|
|
1421
|
+
declare function hasMove(grid: KindGrid): boolean;
|
|
1422
|
+
|
|
1423
|
+
/** A thing on the screen: its id in the board's logic and its cell. */
|
|
1424
|
+
declare const MergeItem: ComponentType<{
|
|
1425
|
+
id: number;
|
|
1426
|
+
col: number;
|
|
1427
|
+
row: number;
|
|
1428
|
+
}>;
|
|
1429
|
+
/** A waiting customer's order (its slot over the board). */
|
|
1430
|
+
declare const Order: ComponentType<{
|
|
1431
|
+
slot: number;
|
|
1432
|
+
}>;
|
|
1433
|
+
declare const mergeBlock: BlockDef;
|
|
1434
|
+
|
|
1435
|
+
interface ChainDef {
|
|
1436
|
+
readonly id: string;
|
|
1437
|
+
/** The art of level n is `${prefix}${n}`. */
|
|
1438
|
+
readonly prefix: string;
|
|
1439
|
+
readonly levels: number;
|
|
1440
|
+
/** The palette role of its rings and sparks. */
|
|
1441
|
+
readonly color: string;
|
|
1442
|
+
/** The generator's art (a tier badge is drawn over it). */
|
|
1443
|
+
readonly gen: string;
|
|
1444
|
+
}
|
|
1445
|
+
declare const CHAINS: readonly ChainDef[];
|
|
1446
|
+
declare const chainOf: (id: string) => ChainDef | undefined;
|
|
1447
|
+
interface ObstacleDef {
|
|
1448
|
+
readonly id: string;
|
|
1449
|
+
/** block — instead of an item (the cell is taken); cover — over an item (it cannot be moved). */
|
|
1450
|
+
readonly layer: "block" | "cover";
|
|
1451
|
+
/** The art by hit points left (index hp - 1; the last one for more). */
|
|
1452
|
+
readonly art: readonly string[];
|
|
1453
|
+
/** A merge in a cell next to it takes a hit point. */
|
|
1454
|
+
readonly neighbour: boolean;
|
|
1455
|
+
/** The item under it is hidden (fog). */
|
|
1456
|
+
readonly hides?: boolean;
|
|
1457
|
+
/** An item of the same chain and level may be merged into the covered one (the cover goes). */
|
|
1458
|
+
readonly mergeInto?: boolean;
|
|
1459
|
+
/** Generator taps until it bursts and takes its item with it (a bubble). */
|
|
1460
|
+
readonly ttl?: number;
|
|
1461
|
+
/** Coins it gives when it goes. */
|
|
1462
|
+
readonly coins?: number;
|
|
1463
|
+
}
|
|
1464
|
+
declare const OBSTACLES: Readonly<Record<string, ObstacleDef>>;
|
|
1465
|
+
interface SpecialItemDef {
|
|
1466
|
+
readonly id: string;
|
|
1467
|
+
readonly art: string;
|
|
1468
|
+
/** joker — dropped onto an item, makes it its next level; split — dropped onto an item of level 2+, makes it two of
|
|
1469
|
+
* the level below; chest — a tap: `amount` free items; energy — a tap: `amount` energy. */
|
|
1470
|
+
readonly effect: "joker" | "split" | "chest" | "energy";
|
|
1471
|
+
readonly amount?: number;
|
|
1472
|
+
}
|
|
1473
|
+
declare const SPECIAL_ITEMS: readonly SpecialItemDef[];
|
|
1474
|
+
declare const specialOf: (id: string) => SpecialItemDef | undefined;
|
|
1475
|
+
declare const MG_COLS = 7;
|
|
1476
|
+
declare const MG_ROWS = 8;
|
|
1477
|
+
declare const BOARDS: Readonly<Record<string, readonly string[]>>;
|
|
1478
|
+
interface SkillDef$1 {
|
|
1479
|
+
readonly id: string;
|
|
1480
|
+
readonly art: string;
|
|
1481
|
+
/** Merges to charge it. */
|
|
1482
|
+
readonly charge: number;
|
|
1483
|
+
/** upgrade — `count` items go a level up by themselves (those an order wants next first); free — the next `count`
|
|
1484
|
+
* generator taps cost no energy; joker — puts `count` jokers on the board for the player to use. */
|
|
1485
|
+
readonly effect: "upgrade" | "free" | "joker";
|
|
1486
|
+
readonly count: number;
|
|
1487
|
+
}
|
|
1488
|
+
declare const SKILLS$1: readonly SkillDef$1[];
|
|
1489
|
+
declare const skillOf$1: (id: string) => SkillDef$1 | undefined;
|
|
1490
|
+
interface MergeHeroDef extends MetaHeroDef {
|
|
1491
|
+
readonly skill: string;
|
|
1492
|
+
}
|
|
1493
|
+
declare const MG_HEROES: readonly MergeHeroDef[];
|
|
1494
|
+
interface LevelDef$1 {
|
|
1495
|
+
readonly board: string;
|
|
1496
|
+
/** The chains of the level (CHAINS ids): the board's A–D and a–d are these. */
|
|
1497
|
+
readonly chains: readonly string[];
|
|
1498
|
+
/** Customers in all, one after another. */
|
|
1499
|
+
readonly orders: number;
|
|
1500
|
+
/** The highest level an order asks. */
|
|
1501
|
+
readonly top: number;
|
|
1502
|
+
/** The share of orders that ask two things. */
|
|
1503
|
+
readonly double: number;
|
|
1504
|
+
/** Customers waiting at once. */
|
|
1505
|
+
readonly visible: number;
|
|
1506
|
+
/** The energy over what the orders cost (× 1 — just enough with no luck). */
|
|
1507
|
+
readonly slack?: number;
|
|
1508
|
+
/** × the energy the formula gives (a level the bot found too tight or too loose). */
|
|
1509
|
+
readonly extra?: number;
|
|
1510
|
+
/** The last customer of a world: asks the most and pays the most. */
|
|
1511
|
+
readonly vip?: boolean;
|
|
1512
|
+
}
|
|
1513
|
+
/** 4 worlds × 10 levels: world 1 — the garden and the bakery, boxes and fog; 2 — jewels, webs, scissors; 3 —
|
|
1514
|
+
* potions, bubbles, holes; 4 — everything. */
|
|
1515
|
+
declare const LEVELS$1: readonly LevelDef$1[];
|
|
1516
|
+
declare const MG_LEVELS_PER_WORLD = 10;
|
|
1517
|
+
declare const MG_WORLDS = 4;
|
|
1518
|
+
declare const MG_LEVELS: number;
|
|
1519
|
+
/** Stars needed to enter each world (3 a level, 120 in all). */
|
|
1520
|
+
declare const MG_WORLD_STARS: readonly number[];
|
|
1521
|
+
interface WantDef {
|
|
1522
|
+
readonly chain: string;
|
|
1523
|
+
readonly level: number;
|
|
1524
|
+
}
|
|
1525
|
+
interface OrderDef {
|
|
1526
|
+
readonly wants: readonly WantDef[];
|
|
1527
|
+
/** The VIP's order: pays three times. */
|
|
1528
|
+
readonly vip: boolean;
|
|
1529
|
+
}
|
|
1530
|
+
interface MergeLevel {
|
|
1531
|
+
readonly level: number;
|
|
1532
|
+
readonly world: number;
|
|
1533
|
+
readonly index: number;
|
|
1534
|
+
readonly def: LevelDef$1;
|
|
1535
|
+
readonly boss: boolean;
|
|
1536
|
+
readonly orders: readonly OrderDef[];
|
|
1537
|
+
/** The energy to start with (before the upgrades). */
|
|
1538
|
+
readonly energy: number;
|
|
1539
|
+
readonly firstClearGold: number;
|
|
1540
|
+
}
|
|
1541
|
+
declare function levelOf$1(level: number, difficulty?: number): MergeLevel;
|
|
1542
|
+
declare const mgStarsToEnter: (level: number) => number;
|
|
1543
|
+
/** Stars of a won level by the share of the energy left. */
|
|
1544
|
+
declare const mgStarsFor: (share: number) => number;
|
|
1545
|
+
/** A revive: this much energy and a joker on the board. */
|
|
1546
|
+
declare const MG_REVIVE_ENERGY = 15;
|
|
1547
|
+
declare const MG_CHARACTER = "kit-merge";
|
|
1548
|
+
/**
|
|
1549
|
+
* The upgrades bought between levels with the soft currency (the server's Character system). ⚠ The seed mirrors these
|
|
1550
|
+
* numbers (`KitGameStarterFixtures` of the engine).
|
|
1551
|
+
*/
|
|
1552
|
+
declare const MG_META_STATS: readonly MetaStatDef[];
|
|
1553
|
+
declare const MG_META: MetaGameDef;
|
|
1554
|
+
|
|
1555
|
+
interface BusinessDef {
|
|
1556
|
+
readonly id: string;
|
|
1557
|
+
readonly art: string;
|
|
1558
|
+
/** The palette role of its bar and sparks. */
|
|
1559
|
+
readonly color: string;
|
|
1560
|
+
/** The price to open it (level 1); level n+1 costs `cost × growth^n`. */
|
|
1561
|
+
readonly cost: number;
|
|
1562
|
+
/** What one cycle pays per level. */
|
|
1563
|
+
readonly income: number;
|
|
1564
|
+
/** Seconds of a cycle at level 1. */
|
|
1565
|
+
readonly cycle: number;
|
|
1566
|
+
readonly growth: number;
|
|
1567
|
+
/** The price of its manager (collects every cycle by itself). */
|
|
1568
|
+
readonly manager: number;
|
|
1569
|
+
}
|
|
1570
|
+
declare const BUSINESSES: readonly BusinessDef[];
|
|
1571
|
+
declare const businessOf: (id: string) => BusinessDef | undefined;
|
|
1572
|
+
interface MilestoneDef {
|
|
1573
|
+
/** The level of a business that reaches it. */
|
|
1574
|
+
readonly at: number;
|
|
1575
|
+
/** × the speed (a cycle is this many times shorter). */
|
|
1576
|
+
readonly speed?: number;
|
|
1577
|
+
/** × what a cycle pays. */
|
|
1578
|
+
readonly income?: number;
|
|
1579
|
+
}
|
|
1580
|
+
declare const MILESTONES: readonly MilestoneDef[];
|
|
1581
|
+
interface UpgradeDef {
|
|
1582
|
+
readonly id: string;
|
|
1583
|
+
/** one: every business of the city gets its own; all: one for the city. */
|
|
1584
|
+
readonly scope: "one" | "all";
|
|
1585
|
+
readonly art: string;
|
|
1586
|
+
/** × what a cycle pays. */
|
|
1587
|
+
readonly mult: number;
|
|
1588
|
+
/** × the business's opening price (scope all: of the city's dearest business). */
|
|
1589
|
+
readonly price: number;
|
|
1590
|
+
/** Shown when the business is at this level (scope all: the city's first business). */
|
|
1591
|
+
readonly after: number;
|
|
1592
|
+
}
|
|
1593
|
+
declare const UPGRADES: readonly UpgradeDef[];
|
|
1594
|
+
interface EventDef {
|
|
1595
|
+
readonly id: string;
|
|
1596
|
+
readonly art: string;
|
|
1597
|
+
/** rush: a business glows: a tap on it, ×`mult` for `seconds`; break: a business stops until `taps` taps;
|
|
1598
|
+
* invest: an investor: `now` seconds of the city's income at once, or ×`mult` for `seconds`; courier: a chest
|
|
1599
|
+
* goes by: a tap, `now` seconds of income and `coins` soft coins. */
|
|
1600
|
+
readonly effect: "rush" | "break" | "invest" | "courier";
|
|
1601
|
+
readonly weight: number;
|
|
1602
|
+
/** Seconds it waits for the player. */
|
|
1603
|
+
readonly ttl: number;
|
|
1604
|
+
readonly mult?: number;
|
|
1605
|
+
readonly seconds?: number;
|
|
1606
|
+
readonly taps?: number;
|
|
1607
|
+
readonly now?: number;
|
|
1608
|
+
readonly coins?: number;
|
|
1609
|
+
}
|
|
1610
|
+
declare const EVENTS: readonly EventDef[];
|
|
1611
|
+
declare const eventOf: (id: string) => EventDef | undefined;
|
|
1612
|
+
interface SkillDef {
|
|
1613
|
+
readonly id: string;
|
|
1614
|
+
readonly art: string;
|
|
1615
|
+
/** Seconds to charge it (taps and events add to it). */
|
|
1616
|
+
readonly charge: number;
|
|
1617
|
+
/** rush: every business ×`mult` for `seconds`; instant: every open business pays `cycles` cycles at once; sale :
|
|
1618
|
+
* prices × `mult` for `seconds`. The meta's skill power stretches the seconds and the cycles. */
|
|
1619
|
+
readonly effect: "rush" | "instant" | "sale";
|
|
1620
|
+
readonly mult?: number;
|
|
1621
|
+
readonly seconds?: number;
|
|
1622
|
+
readonly cycles?: number;
|
|
1623
|
+
}
|
|
1624
|
+
declare const SKILLS: readonly SkillDef[];
|
|
1625
|
+
declare const skillOf: (id: string) => SkillDef | undefined;
|
|
1626
|
+
interface TycoonHeroDef extends MetaHeroDef {
|
|
1627
|
+
readonly skill: string;
|
|
1628
|
+
}
|
|
1629
|
+
declare const TY_HEROES: readonly TycoonHeroDef[];
|
|
1630
|
+
interface GoalDef {
|
|
1631
|
+
/** cash: earn `n` in the day; level: the business `biz` to level `n`; managers: `n` managers hired. */
|
|
1632
|
+
readonly kind: "cash" | "level" | "managers";
|
|
1633
|
+
readonly n: number;
|
|
1634
|
+
readonly biz?: string;
|
|
1635
|
+
}
|
|
1636
|
+
interface LevelDef {
|
|
1637
|
+
/** The city's businesses, cheapest first (BUSINESSES ids); the first one is open at the start. */
|
|
1638
|
+
readonly businesses: readonly string[];
|
|
1639
|
+
readonly goals: readonly GoalDef[];
|
|
1640
|
+
/** Cash at the start (default: twice the second business's price). */
|
|
1641
|
+
readonly cash?: number;
|
|
1642
|
+
/** The events of the day (EVENTS ids). */
|
|
1643
|
+
readonly events: readonly string[];
|
|
1644
|
+
/** × the day's length the formula gives (a city the bot found too tight or too loose). */
|
|
1645
|
+
readonly extra?: number;
|
|
1646
|
+
/** The big city at the end of a world: more goals, more coins. */
|
|
1647
|
+
readonly vip?: boolean;
|
|
1648
|
+
}
|
|
1649
|
+
/** 4 worlds × 10 cities: 1: lemonade to the workshop, rushes and couriers; 2: the bakery to the cinema,
|
|
1650
|
+
* breakdowns; 3: the cafe to the hotel, investors; 4: the workshop to the spaceport, everything. */
|
|
1651
|
+
declare const LEVELS: readonly LevelDef[];
|
|
1652
|
+
declare const TY_LEVELS_PER_WORLD = 10;
|
|
1653
|
+
declare const TY_WORLDS = 4;
|
|
1654
|
+
declare const TY_LEVELS: number;
|
|
1655
|
+
/** Stars needed to enter each world (3 a city, 120 in all). */
|
|
1656
|
+
declare const TY_WORLD_STARS: readonly number[];
|
|
1657
|
+
declare const tyStarsToEnter: (level: number) => number;
|
|
1658
|
+
/** Stars of a won city by the share of the day left. */
|
|
1659
|
+
declare const tyStarsFor: (share: number) => number;
|
|
1660
|
+
/** A revive: this many seconds more of the day. */
|
|
1661
|
+
declare const TY_REVIVE_SECONDS = 30;
|
|
1662
|
+
declare const TY_CHARACTER = "kit-tycoon";
|
|
1663
|
+
/**
|
|
1664
|
+
* The upgrades bought between cities with the soft currency (the server's Character system). ⚠ The seed mirrors these
|
|
1665
|
+
* numbers (`KitGameStarterFixtures` of the engine).
|
|
1666
|
+
*/
|
|
1667
|
+
declare const TY_META_STATS: readonly MetaStatDef[];
|
|
1668
|
+
declare const TY_META: MetaGameDef;
|
|
1669
|
+
|
|
1670
|
+
interface Biz {
|
|
1671
|
+
readonly def: BusinessDef;
|
|
1672
|
+
level: number;
|
|
1673
|
+
/** 0..1 of the cycle. */
|
|
1674
|
+
progress: number;
|
|
1675
|
+
/** A finished cycle waits for a tap (no manager). */
|
|
1676
|
+
ready: boolean;
|
|
1677
|
+
manager: boolean;
|
|
1678
|
+
/** × what a cycle pays (the upgrades bought). */
|
|
1679
|
+
mult: number;
|
|
1680
|
+
/** Seconds of a rush left, and its ×. */
|
|
1681
|
+
rush: number;
|
|
1682
|
+
rushMult: number;
|
|
1683
|
+
/** Taps left to fix a breakdown (0: it works). */
|
|
1684
|
+
broken: number;
|
|
1685
|
+
}
|
|
1686
|
+
/** A timed effect on the whole city (a skill, an investor's share). */
|
|
1687
|
+
interface Timed {
|
|
1688
|
+
readonly id: string;
|
|
1689
|
+
left: number;
|
|
1690
|
+
readonly income: number;
|
|
1691
|
+
readonly price: number;
|
|
1692
|
+
}
|
|
1693
|
+
interface Mods {
|
|
1694
|
+
/** + share of what a cycle pays. */
|
|
1695
|
+
readonly income: number;
|
|
1696
|
+
/** + share of the speed. */
|
|
1697
|
+
readonly speed: number;
|
|
1698
|
+
/** − share of the prices (at most 0.9). */
|
|
1699
|
+
readonly discount: number;
|
|
1700
|
+
}
|
|
1701
|
+
interface TycoonState {
|
|
1702
|
+
readonly biz: Biz[];
|
|
1703
|
+
cash: number;
|
|
1704
|
+
earned: number;
|
|
1705
|
+
/** × of the "all" upgrades. */
|
|
1706
|
+
allMult: number;
|
|
1707
|
+
readonly bought: Set<string>;
|
|
1708
|
+
readonly timed: Timed[];
|
|
1709
|
+
readonly mods: Mods;
|
|
1710
|
+
}
|
|
1711
|
+
interface TycoonLevel {
|
|
1712
|
+
readonly level: number;
|
|
1713
|
+
readonly world: number;
|
|
1714
|
+
readonly index: number;
|
|
1715
|
+
readonly def: LevelDef;
|
|
1716
|
+
readonly boss: boolean;
|
|
1717
|
+
/** Seconds of the day. */
|
|
1718
|
+
readonly day: number;
|
|
1719
|
+
readonly cash: number;
|
|
1720
|
+
readonly coins: number;
|
|
1721
|
+
readonly firstClearGold: number;
|
|
1722
|
+
}
|
|
1723
|
+
/** The bot's time on a level (once per level). */
|
|
1724
|
+
declare function botTimeOf(n: number): number;
|
|
1725
|
+
declare function levelOf(level: number, difficulty?: number): TycoonLevel;
|
|
1726
|
+
|
|
1727
|
+
/** A manager standing by its building. */
|
|
1728
|
+
declare const Manager: ComponentType<{
|
|
1729
|
+
index: number;
|
|
1730
|
+
}>;
|
|
1731
|
+
/** 1234 → "1.2K". */
|
|
1732
|
+
declare const shortCash: (n: number) => string;
|
|
1733
|
+
declare const tycoonStateOf: (w: World) => {
|
|
1734
|
+
s: TycoonState;
|
|
1735
|
+
level: TycoonLevel;
|
|
1736
|
+
} | undefined;
|
|
1737
|
+
declare const tycoonBlock: BlockDef;
|
|
1738
|
+
|
|
1739
|
+
interface AssetPackDef extends RegistryEntry {
|
|
1740
|
+
/** Taxonomy setting id ("fantasy", "sci-fi", "cozy", "post-apocalypse"). */
|
|
1741
|
+
readonly setting: string;
|
|
1742
|
+
/** Its name per language ("en" is the fallback). */
|
|
1743
|
+
readonly names: Readonly<Record<string, string>>;
|
|
1744
|
+
/** Colours by role (view.ts DEFAULT_PALETTE has every role). */
|
|
1745
|
+
readonly palette: Readonly<Record<string, string>>;
|
|
1746
|
+
/** Default texts (`res.coins`…) per language, under the spec's own. */
|
|
1747
|
+
readonly texts?: Readonly<Record<string, Readonly<Record<string, string>>>>;
|
|
1748
|
+
/** Hero races (@idosgames/characters) that fit the setting, the first is the default. */
|
|
1749
|
+
readonly races?: readonly string[];
|
|
1750
|
+
/** The art style its pictures are drawn in (src/art); default: the pack's id. */
|
|
1751
|
+
readonly style?: string;
|
|
1752
|
+
/** Who plays the roles (hero, foe, foe2, boss, helper), over the kit's DEFAULT_CAST role by role. */
|
|
1753
|
+
readonly cast?: Readonly<Record<string, CastDef>>;
|
|
1754
|
+
}
|
|
1755
|
+
interface LinkDef extends RegistryEntry {
|
|
1756
|
+
/** Text key of its name. */
|
|
1757
|
+
readonly name: string;
|
|
1758
|
+
/** Genres of the core mode it fits. */
|
|
1759
|
+
readonly core: readonly string[];
|
|
1760
|
+
/** Platform systems the title must have (modules/<id>), installed by the creation path. */
|
|
1761
|
+
readonly systems: readonly string[];
|
|
1762
|
+
/** The spec with the link: resources, flows, maybe a mode. Pure: returns a new spec. */
|
|
1763
|
+
apply(spec: GameSpec): GameSpec;
|
|
1764
|
+
}
|
|
1765
|
+
declare const ASSET_PACKS: RegistryKind<AssetPackDef>;
|
|
1766
|
+
declare const LINKS: RegistryKind<LinkDef>;
|
|
1767
|
+
/** A pack's name in a language, English when it has none there. */
|
|
1768
|
+
declare const packName: (pack: AssetPackDef, language?: string) => string;
|
|
1769
|
+
/**
|
|
1770
|
+
* Applies a link to a spec: refused (issues, the spec unchanged) when the link is unknown or does not
|
|
1771
|
+
* fit the genre of the spec's core mode.
|
|
1772
|
+
*/
|
|
1773
|
+
declare function applyLink(spec: GameSpec, linkId: string, registry: Registry): {
|
|
1774
|
+
spec: GameSpec;
|
|
1775
|
+
systems: readonly string[];
|
|
1776
|
+
issues: Issue[];
|
|
1777
|
+
};
|
|
1778
|
+
|
|
1779
|
+
declare const fantasyPack: AssetPackDef;
|
|
1780
|
+
declare const sciFiPack: AssetPackDef;
|
|
1781
|
+
declare const cozyPack: AssetPackDef;
|
|
1782
|
+
declare const postApocalypsePack: AssetPackDef;
|
|
1783
|
+
declare const PLATFORM_PACKS: readonly AssetPackDef[];
|
|
1784
|
+
declare const heroUpgradeLink: LinkDef;
|
|
1785
|
+
declare const puzzleCityLink: LinkDef;
|
|
1786
|
+
declare const runnerCollectionLink: LinkDef;
|
|
1787
|
+
declare const defenseBoostsLink: LinkDef;
|
|
1788
|
+
declare const PLATFORM_LINKS: readonly LinkDef[];
|
|
1789
|
+
|
|
1790
|
+
/**
|
|
1791
|
+
* Lane runner with levels to a finish (owner, 08.11.2026): swipe for a lane, tap to jump; six kinds of
|
|
1792
|
+
* obstacles in patterns, power-ups, hearts, a revive, up to three stars a level; the meta (levels, upgrades,
|
|
1793
|
+
* heroes) is the host's (RUNNER_META).
|
|
1794
|
+
*/
|
|
1795
|
+
declare const runnerPreset: PresetDef;
|
|
1796
|
+
/**
|
|
1797
|
+
* Platformer with the player's own controls (owner, 08.11.2026): walk, jump (hold for higher), the abilities the
|
|
1798
|
+
* stars open; worlds of levels from hand-made rooms, enemies, traps, a checkpoint, three stars a level, a boss at
|
|
1799
|
+
* the end of a world; the meta (worlds, upgrades, heroes) is the host's (PLATFORMER_META).
|
|
1800
|
+
*/
|
|
1801
|
+
declare const platformerPreset: PresetDef;
|
|
1802
|
+
/**
|
|
1803
|
+
* Survivors-like: walk, the weapons fire by themselves (six weapons, six passives, five levels each), foes of
|
|
1804
|
+
* six kinds in a directed stream, elites with chests, mini-bosses, the chapter's boss; ten chapters and stats
|
|
1805
|
+
* bought between runs (the meta: the host sets meta:* vars before a round).
|
|
1806
|
+
*/
|
|
1807
|
+
declare const survivorsPreset: PresetDef;
|
|
1808
|
+
/**
|
|
1809
|
+
* Tower defense with ready-made build spots (owner, 08.11.2026): four towers of three tiers and a branch each, foes
|
|
1810
|
+
* that fly, resist, heal, split and call, two spells, a commander; worlds of hand-made maps, a boss at the end of a
|
|
1811
|
+
* world, three stars by the lives kept; the meta (worlds, upgrades, commanders) is the host's (TD_META). Towers,
|
|
1812
|
+
* foes, maps and spells are rows of registries (kit/towerDefense/content.ts).
|
|
1813
|
+
*/
|
|
1814
|
+
declare const towerDefensePreset: PresetDef;
|
|
1815
|
+
/**
|
|
1816
|
+
* Match-3 with a hero (owner, 08.11.2026): goal levels (colours, ice, stones, chains, cages, slime, drops) and battles
|
|
1817
|
+
* (the hero against foes: element pieces hit, hearts heal, shields block; foes strike and spoil the board) in turn;
|
|
1818
|
+
* specials and combos; the hero's skill from mana on every level; 4 worlds × 10 levels, a boss at the end of each;
|
|
1819
|
+
* the meta (worlds, the hero's upgrades, heroes) is the host's (M3_META). Content: kit/match3/content.ts.
|
|
1820
|
+
*/
|
|
1821
|
+
declare const match3Preset: PresetDef;
|
|
1822
|
+
/**
|
|
1823
|
+
* Merge with levels (owner, 08.11.2026): hand-made boards with generators of four chains (they merge too), boxes, fog,
|
|
1824
|
+
* webs, bubbles and special items (a joker, scissors, a chest, a battery); customers come one after another with
|
|
1825
|
+
* orders; all served → the level is won, three stars by the energy left; the hero's skill charged by merges; 4 worlds
|
|
1826
|
+
* × 10 levels, a VIP at the end of each; the meta (worlds, upgrades, heroes) is the host's (MG_META). Content:
|
|
1827
|
+
* kit/merge/content.ts.
|
|
1828
|
+
*/
|
|
1829
|
+
declare const mergePreset: PresetDef;
|
|
1830
|
+
/**
|
|
1831
|
+
* Tycoon with levels (owner, 08.11.2026): cities of 2–4 businesses (eight in the registry) with goals (earn so much, a
|
|
1832
|
+
* business to a level, managers hired) and a day of a few minutes (from a bot's play of the city); levels, milestones,
|
|
1833
|
+
* managers, upgrades for the day's cash; events (a rush, a breakdown, an investor, a courier); the hero's skill charged
|
|
1834
|
+
* by time and taps; all goals done → three stars by the time left; 4 worlds × 10 cities, a big city at the end of each;
|
|
1835
|
+
* the meta (worlds, upgrades, heroes) is the host's (TY_META). Content: kit/tycoon/content.ts.
|
|
1836
|
+
*/
|
|
1837
|
+
declare const tycoonPreset: PresetDef;
|
|
1838
|
+
declare const PLATFORM_PRESETS: readonly PresetDef[];
|
|
1839
|
+
/** Core effects + the platform's blocks and presets. Safe to call once per registry. */
|
|
1840
|
+
declare function registerPlatformKit(registry: Registry): void;
|
|
1841
|
+
/**
|
|
1842
|
+
* The spec a game runs when its title has none yet (a fresh title before the constructor wrote one,
|
|
1843
|
+
* the playground). A complete, valid game on its own.
|
|
1844
|
+
*/
|
|
1845
|
+
declare const DEMO_SPEC: GameSpec;
|
|
1846
|
+
/**
|
|
1847
|
+
* A complete, valid one-mode game of a preset: the base's coins (CO) from the round and spent in the
|
|
1848
|
+
* store, the round's score, the texts and palette given. The creation path starts from this and the
|
|
1849
|
+
* config agent edits it; links between modes are added on top (economy links).
|
|
1850
|
+
*/
|
|
1851
|
+
declare function specForPreset(presetId: string, options?: {
|
|
1852
|
+
seed?: string;
|
|
1853
|
+
params?: Readonly<Record<string, unknown>>;
|
|
1854
|
+
texts?: GameSpec["texts"];
|
|
1855
|
+
palette?: Readonly<Record<string, string>>;
|
|
1856
|
+
/** Asset pack id ("fantasy"…). */
|
|
1857
|
+
assets?: string;
|
|
1858
|
+
coinRef?: string;
|
|
1859
|
+
}): GameSpec;
|
|
1860
|
+
|
|
1861
|
+
/** Which part of the title a knob changes (the dashboard groups its cards by it). */
|
|
1862
|
+
type KnobGroup = "look" | "feel" | "economy" | "liveops" | "texts";
|
|
1863
|
+
/** When the decision model answers it: on creation (the one request that creates the title), on a later tune, or both. */
|
|
1864
|
+
type KnobStage = "create" | "tune";
|
|
1865
|
+
/** A text shown to the creator. English is required, other languages fall back to it. */
|
|
1866
|
+
type KnobText = Readonly<{
|
|
1867
|
+
en: string;
|
|
1868
|
+
ru?: string;
|
|
1869
|
+
} & Record<string, string | undefined>>;
|
|
1870
|
+
/**
|
|
1871
|
+
* One change of one config section.
|
|
1872
|
+
*
|
|
1873
|
+
* `path` is a dot path inside the section; a segment `name[field=value]` picks the element of the
|
|
1874
|
+
* array `name` whose `field` equals `value` (`modes[role=core].params.difficulty`); a key with a dot in
|
|
1875
|
+
* it is quoted (`texts.'res.coins'.en`). Plain segments
|
|
1876
|
+
* that are missing are created as objects; a missing array element is not created (the patch is
|
|
1877
|
+
* skipped). An empty path is the section itself.
|
|
1878
|
+
*
|
|
1879
|
+
* The `GameSpec` section is a JSON string in the config: patches address the parsed object, the
|
|
1880
|
+
* applier parses and serializes it.
|
|
1881
|
+
*/
|
|
1882
|
+
interface KnobPatch {
|
|
1883
|
+
/** Config section: a property of the title's public configuration ("Look", "GameSpec", "Reward"…). */
|
|
1884
|
+
readonly section: string;
|
|
1885
|
+
/**
|
|
1886
|
+
* set: put `value` (a level's value for a score knob); merge: deep-merge the object `value` (objects
|
|
1887
|
+
* merge key by key, everything else is replaced); unset: remove; add / remove: put into / take out
|
|
1888
|
+
* of the array at `path` each item of the array `value` (equal items once).
|
|
1889
|
+
*/
|
|
1890
|
+
readonly op: "set" | "merge" | "unset" | "add" | "remove";
|
|
1891
|
+
readonly path?: string;
|
|
1892
|
+
readonly value?: unknown;
|
|
1893
|
+
/**
|
|
1894
|
+
* Score knobs only: the value from the answered level (0 = the first level, 1 = the last):
|
|
1895
|
+
* `min + level × (max − min)`, rounded when `integer`, to `digits` places otherwise (default 2).
|
|
1896
|
+
*/
|
|
1897
|
+
readonly range?: Readonly<{
|
|
1898
|
+
min: number;
|
|
1899
|
+
max: number;
|
|
1900
|
+
integer?: boolean;
|
|
1901
|
+
digits?: number;
|
|
1902
|
+
}>;
|
|
1903
|
+
/**
|
|
1904
|
+
* Change only what the title already has: the patch is skipped when a key on its path (the last one
|
|
1905
|
+
* too) is missing. Without it `set` / `merge` / `add` create the plain objects on the way, which is
|
|
1906
|
+
* right for Look and GameSpec and wrong for content a seed brought (a quest, an event, a currency):
|
|
1907
|
+
* a title without it would get a broken stub. The catalog sets it on every such section by itself.
|
|
1908
|
+
*/
|
|
1909
|
+
readonly ifExists?: boolean;
|
|
1910
|
+
}
|
|
1911
|
+
/** An answer of a choice knob: what the decision model reads about it, what the creator sees, what it writes. */
|
|
1912
|
+
interface KnobOption {
|
|
1913
|
+
/** Snake/kebab-case id, unique in its knob or list. */
|
|
1914
|
+
readonly id: string;
|
|
1915
|
+
readonly title: KnobText;
|
|
1916
|
+
/** For the decision model: what this option is. */
|
|
1917
|
+
readonly what: string;
|
|
1918
|
+
/** For the decision model: what it is NOT for (keeps near options apart). */
|
|
1919
|
+
readonly notFor?: string;
|
|
1920
|
+
/** For the decision model: ideas it fits. */
|
|
1921
|
+
readonly examples?: readonly string[];
|
|
1922
|
+
/** Colour swatches or a preview hint for the dashboard card (#rrggbb). */
|
|
1923
|
+
readonly swatch?: readonly string[];
|
|
1924
|
+
readonly patches: readonly KnobPatch[];
|
|
1925
|
+
/**
|
|
1926
|
+
* Translations of the texts the patches write (`{ "ru": { "Gold": "Золото" } }`): the server puts them
|
|
1927
|
+
* into the title's translation tables (only missing keys), like a seed's `$localization`.
|
|
1928
|
+
*/
|
|
1929
|
+
readonly translations?: Readonly<Record<string, Readonly<Record<string, string>>>>;
|
|
1930
|
+
}
|
|
1931
|
+
/** Which titles a knob is for. Omitted = every title. */
|
|
1932
|
+
interface KnobScope {
|
|
1933
|
+
/** Any of these modules is in the title (a base or a system: "kit-game", "quests", "premium"). */
|
|
1934
|
+
readonly modules?: readonly string[];
|
|
1935
|
+
/** The title's constructor genre (the GameSpec core mode's preset): "runner", "tycoon"… */
|
|
1936
|
+
readonly presets?: readonly string[];
|
|
1937
|
+
/** Every one of these config sections has something in it (a knob of the daily calendar needs `Reward`). */
|
|
1938
|
+
readonly sections?: readonly string[];
|
|
1939
|
+
}
|
|
1940
|
+
interface KnobBase {
|
|
1941
|
+
/** Dotted id, unique in the catalog: "look.theme", "feel.runner.lanes". */
|
|
1942
|
+
readonly id: string;
|
|
1943
|
+
readonly group: KnobGroup;
|
|
1944
|
+
readonly title: KnobText;
|
|
1945
|
+
/** One line for the creator: what turning it changes. */
|
|
1946
|
+
readonly hint?: KnobText;
|
|
1947
|
+
readonly for?: KnobScope;
|
|
1948
|
+
/** Omitted = both. */
|
|
1949
|
+
readonly stages?: readonly KnobStage[];
|
|
1950
|
+
/** The question for the decision model, in English. */
|
|
1951
|
+
readonly question: string;
|
|
1952
|
+
}
|
|
1953
|
+
interface ChoiceKnob extends KnobBase {
|
|
1954
|
+
readonly kind: "choice";
|
|
1955
|
+
/** The options, or `list` (then the options are that list's items: a shared list, extendable in PlatformAdmin). */
|
|
1956
|
+
readonly options?: readonly KnobOption[];
|
|
1957
|
+
readonly list?: string;
|
|
1958
|
+
}
|
|
1959
|
+
interface ScoreKnob extends KnobBase {
|
|
1960
|
+
readonly kind: "score";
|
|
1961
|
+
/** 2..10 levels, from the first to the last; the decision model answers a fractional level. */
|
|
1962
|
+
readonly levels: readonly string[];
|
|
1963
|
+
/** What the creator sees on each level (short, per language), as many as `levels`: those are for the model. */
|
|
1964
|
+
readonly levelTitles?: readonly KnobText[];
|
|
1965
|
+
/** Applied with the answered level (their `range` gives the value). */
|
|
1966
|
+
readonly patches: readonly KnobPatch[];
|
|
1967
|
+
}
|
|
1968
|
+
interface NoulKnob extends KnobBase {
|
|
1969
|
+
readonly kind: "noul";
|
|
1970
|
+
/** What "yes" and "no" mean, for the decision model. */
|
|
1971
|
+
readonly yes: string;
|
|
1972
|
+
readonly no: string;
|
|
1973
|
+
readonly onYes: readonly KnobPatch[];
|
|
1974
|
+
readonly onNo?: readonly KnobPatch[];
|
|
1975
|
+
}
|
|
1976
|
+
type KnobDef = ChoiceKnob | ScoreKnob | NoulKnob;
|
|
1977
|
+
/** The exported catalog: every knob, and the shared lists choice knobs point at. */
|
|
1978
|
+
interface KnobCatalog {
|
|
1979
|
+
readonly version: number;
|
|
1980
|
+
readonly knobs: readonly KnobDef[];
|
|
1981
|
+
readonly lists: Readonly<Record<string, readonly KnobOption[]>>;
|
|
1982
|
+
}
|
|
1983
|
+
/** The decision model's limits (TypeSafe System One): options of a choice, levels of a score. */
|
|
1984
|
+
declare const DECISION_MAX_OPTIONS = 255;
|
|
1985
|
+
declare const DECISION_MAX_LEVELS = 10;
|
|
1986
|
+
|
|
1987
|
+
/** One path segment: a key, or `key[field=value]` (an array element picked by a field). */
|
|
1988
|
+
interface Segment {
|
|
1989
|
+
readonly key: string;
|
|
1990
|
+
readonly match?: {
|
|
1991
|
+
field: string;
|
|
1992
|
+
value: string;
|
|
1993
|
+
};
|
|
1994
|
+
}
|
|
1995
|
+
/** `modes[role=core].params.difficulty` → segments; `null` when a segment is malformed. */
|
|
1996
|
+
declare function parseKnobPath(path: string | undefined): Segment[] | null;
|
|
1997
|
+
/** A score answer (0..1) → the patch's value by its range; the patch's own value otherwise. */
|
|
1998
|
+
declare function patchValue(patch: KnobPatch, level?: number): unknown;
|
|
1999
|
+
/**
|
|
2000
|
+
* Applies the patches in order to a section's value (a parsed object; `undefined` = the section is empty).
|
|
2001
|
+
* Returns the new value and the indexes of the patches that could not be applied (a bad path, an array
|
|
2002
|
+
* element that is not there, `add` to something that is not an array): they are skipped, the rest
|
|
2003
|
+
* still applies. Never mutates the input.
|
|
2004
|
+
*/
|
|
2005
|
+
declare function applyPatches(section: unknown, patches: readonly KnobPatch[], level?: number): {
|
|
2006
|
+
value: unknown;
|
|
2007
|
+
skipped: number[];
|
|
2008
|
+
};
|
|
2009
|
+
/** Every (section, path) a list of patches writes: what a knob owns (pinning compares against it). */
|
|
2010
|
+
declare function patchTargets(patches: readonly KnobPatch[]): string[];
|
|
2011
|
+
|
|
2012
|
+
declare const KNOB_CATALOG_VERSION = 1;
|
|
2013
|
+
declare const KNOBS: readonly KnobDef[];
|
|
2014
|
+
declare const KNOB_CATALOG: KnobCatalog;
|
|
2015
|
+
|
|
2016
|
+
declare const UI_THEMES: readonly KnobOption[];
|
|
2017
|
+
declare const KIT_PALETTES: readonly KnobOption[];
|
|
2018
|
+
declare const HERO_LOOK_OPTIONS: readonly KnobOption[];
|
|
2019
|
+
declare const BACKGROUND_OPTIONS: readonly KnobOption[];
|
|
2020
|
+
declare const SOUND_SET_OPTIONS: readonly KnobOption[];
|
|
2021
|
+
/** Ids the UI kit must know how to draw / play (its own tests check them against these lists). */
|
|
2022
|
+
declare const LOOK_RUNTIME_IDS: {
|
|
2023
|
+
readonly backgrounds: string[];
|
|
2024
|
+
readonly soundSets: string[];
|
|
2025
|
+
};
|
|
2026
|
+
/** All shared lists by id. */
|
|
2027
|
+
declare const KNOB_LISTS: Readonly<Record<string, readonly KnobOption[]>>;
|
|
2028
|
+
|
|
2029
|
+
/** Errors of a catalog; empty = good. */
|
|
2030
|
+
declare function validateKnobCatalog(catalog: KnobCatalog): string[];
|
|
2031
|
+
|
|
2032
|
+
export { ABILITIES, ART, ASSET_PACKS, type AbilityId, ActorAct, ActorPose, type ArtContext, type ArtDef, ArtLook, type AssetPackDef, BACKGROUND_OPTIONS, BLOCKS, BOSS_DEFEATED, BOSS_SPAWNED, BRANCH_LEVEL, type BlockContext, type BlockDef, type Board, Body, Bullet, CHAPTERS, CORE_EFFECTS, CastDef, type ChoiceKnob, ComponentType, type Controls, DECISION_MAX_LEVELS, DECISION_MAX_OPTIONS, DEFAULT_REWARDS, DEMO_SPEC, type DamageType, type DefineOptions, Drop, EFFECTS, ENEMIES$1 as ENEMIES, ENGINES, ENTRY_ID_RE, type EffectContext, type EffectDef, type EffectSpec, type EnemyDef$1 as EnemyDef, type Engine, Entity, type Expr, ExprError, type ExprScope, type ExprValue, FOES, FUNCTIONS, type FlowSpec, Foe, type FoeKind, FxEvent, GIVE_UP, type GameSpec, Gem, HEROES, HERO_LOOK_OPTIONS, type HeroDef, type Issue, Jumper, KIT_PALETTES, KNOBS, KNOB_CATALOG, KNOB_CATALOG_VERSION, KNOB_LISTS, KNOWN_SYSTEMS, type KindGrid, type KnobCatalog, type KnobDef, type KnobGroup, type KnobOption, type KnobPatch, type KnobScope, type KnobStage, type KnobText, LEVELS_PER_WORLD, LEVEL_CLEARED, LEVEL_MAPS, LEVEL_UP, LINKS, LOOK_RUNTIME_IDS, type LinkDef, type EnemyDef as M3EnemyDef, type GoalDef$1 as M3GoalDef, type M3HeroDef, type M3Level, type LevelDef$2 as M3LevelDef, type SkillDef$2 as M3SkillDef, M3_CHARACTER, ELEMENTS as M3_ELEMENTS, ENEMIES as M3_ENEMIES, M3_HEROES, M3_LEVELS, M3_LEVELS_PER_WORLD, LEVELS$2 as M3_LEVEL_DEFS, M3_META, M3_META_STATS, OBSTACLES$1 as M3_OBSTACLES, PIECES as M3_PIECES, SKILLS$2 as M3_SKILLS, SPECIALS as M3_SPECIALS, M3_WORLDS, M3_WORLD_STARS, MAPS, MAP_COLS, MAP_ROWS, MAX_LEVEL, MAX_PASSIVES, MAX_WEAPONS, META_CHARACTER, META_STATS, BOARDS as MG_BOARDS, CHAINS as MG_CHAINS, MG_CHARACTER, MG_COLS, MG_HEROES, MG_LEVELS, MG_LEVELS_PER_WORLD, LEVELS$1 as MG_LEVEL_DEFS, MG_META, MG_META_STATS, OBSTACLES as MG_OBSTACLES, MG_REVIVE_ENERGY, MG_ROWS, SKILLS$1 as MG_SKILLS, SPECIAL_ITEMS as MG_SPECIAL_ITEMS, MG_WORLDS, MG_WORLD_STARS, type MapDef, type MergeHeroDef, MergeItem, type MergeLevel, type MetaGameDef, type MetaHeroDef, type MetaStatDef, type ChainDef as MgChainDef, type LevelDef$1 as MgLevelDef, type ObstacleDef as MgObstacleDef, type OrderDef as MgOrderDef, type SkillDef$1 as MgSkillDef, type SpecialItemDef as MgSpecialItemDef, type WantDef as MgWantDef, Missile, type ModeSpec, type NoulKnob, type NumberOrFormula, OBSTACLE_KINDS, type ObstacleKind, Order, PASSIVES, PASSIVE_IDS, PIECE_COLORS, PLATFORMER_CHARACTER, PLATFORMER_HEROES, PLATFORMER_LEVELS, PLATFORMER_META, PLATFORMER_META_STATS, PLATFORM_LINKS, PLATFORM_PACKS, PLATFORM_PRESETS, POWERS, POWER_IDS, PRESETS, type ParamDef, type ParamDefs, type ParamValue, type PassiveDef, type PassiveId, type PlatformerHeroDef, type PlatformerLevel, type PlatformerPerk, type PowerDef, type PowerId, type PresetDef, REROLL_GEMS, REVIVE, REVIVE_GEMS, REVIVE_OFFER, ROOMS, ROOM_ROWS, ROUND_ENDED, ROUND_OVER, ROUND_STARTED, RUNNER_CHARACTER, RUNNER_HEROES, RUNNER_LEVELS, RUNNER_META, RUNNER_META_STATS, Raider, type Registry, type RegistryEntry, type RegistryKind, type ResolvedMode, type ResolvedSpec, type ResourceSpec, type RewardedPlacementDef, type RewardsSpec, RoadItem, type RoomDef, type RoomFeature, type RoundState, type RuleDef, Runner, type RunnerHeroDef, type RunnerLevel, type RunnerPerk, type RunningMode, SELL_SHARE, SHOW_START, SOUND_SET_OPTIONS, SPEC_VERSION, SPELLS, START_ROUND, SURVIVORS_META, type ScoreKnob, Shot, Soldier, type SpecResult, type SpellDef, Spot, type StartModeOptions, Survivor, type SurvivorsBuild, TD_CHARACTER, TD_HEROES, TD_LEVELS, TD_LEVELS_PER_WORLD, TD_LIVES, TD_META, TD_META_STATS, REVIVE_LIVES as TD_REVIVE_LIVES, TD_WORLDS, TD_WORLD_STARS, TOWERS, BUSINESSES as TY_BUSINESSES, TY_CHARACTER, EVENTS as TY_EVENTS, TY_HEROES, TY_LEVELS, TY_LEVELS_PER_WORLD, LEVELS as TY_LEVEL_DEFS, TY_META, TY_META_STATS, MILESTONES as TY_MILESTONES, TY_REVIVE_SECONDS, SKILLS as TY_SKILLS, UPGRADES as TY_UPGRADES, TY_WORLDS, TY_WORLD_STARS, type TdHeroDef, type TdLevel, type TdPerk, Thing, Tower, type TowerBranchDef, type TowerDef, type TowerStats, type TowerTierDef, type TracedMap, type BusinessDef as TyBusinessDef, type EventDef as TyEventDef, type GoalDef as TyGoalDef, type LevelDef as TyLevelDef, Manager as TyManager, type SkillDef as TySkillDef, type UpgradeDef as TyUpgradeDef, type TycoonHeroDef, type TycoonLevel, UI_THEMES, UPGRADE_PICK, UPGRADE_PICKED, UPGRADE_REROLL, type UpgradeOption, type ViewSize, WAVE_STARTED, WEAPONS, WEAPON_IDS, WORLDS, WORLD_STARS, type WaveDef, type WaveGroup, type WeaponDef, type WeaponId, World, abilitiesFor, act, applyLink, applyPatches, artAspect, artDocument, attachRules, boardOf, buildFromVar, buildToVar, cellAt, cellCenter, chapterOf, checkEconomy, checkExpr, checkRules, compileExpr, contentOf, cozyPack, createKitRegistry, createRegistry, defenseBoostsLink, defineKind, enemyOf$1 as enemyOf, evalNumber, fantasyPack, findMatches, fx, hasArt, hasErrors, hasMove, heroCharacterOf, heroUpgradeLink, laneRunnerBlock, levelOf$5 as levelOf, enemyOf as m3EnemyOf, levelOf$2 as m3LevelOf, skillOf$2 as m3SkillOf, m3StarsToEnter, match3Block, match3Preset, mergeBlock, mergePreset, metersOf, chainOf as mgChainOf, levelOf$1 as mgLevelOf, skillOf$1 as mgSkillOf, specialOf as mgSpecialOf, mgStarsFor, mgStarsToEnter, migrateSpec, mirrored, offerFromVar, offerToVar, packName, parseKnobPath, patchTargets, patchValue, placeBackdrop, platformerBlock, levelOf$4 as platformerLevelOf, platformerPreset, postApocalypsePack, puzzleCityLink, registerCoreEffects, registerPlatformKit, resolveParams, roundBlock, runnerCollectionLink, runnerPreset, sciFiPack, scrollBackdrop, setPose, shortCash, specForPreset, starsToEnter, startMode, survivorsBlock, survivorsPreset, levelOf$3 as tdLevelOf, starsFor as tdStarsFor, tdStarsToEnter, wavesOf as tdWavesOf, towerArt, towerDefenseBlock, towerDefensePreset, towerOf, towerSpent, towerStats, traceMap, trackControls, botTimeOf as tyBotTimeOf, businessOf as tyBusinessOf, eventOf as tyEventOf, levelOf as tyLevelOf, skillOf as tySkillOf, tyStarsFor, tyStarsToEnter, tycoonBlock, tycoonPreset, tycoonStateOf, validateKnobCatalog, validateSpec, viewOf };
|