diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..6c879e4 Binary files /dev/null and b/.DS_Store differ diff --git a/.github/.DS_Store b/.github/.DS_Store new file mode 100644 index 0000000..ce30d05 Binary files /dev/null and b/.github/.DS_Store differ diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml new file mode 100644 index 0000000..ef93b96 --- /dev/null +++ b/.github/workflows/docs.yaml @@ -0,0 +1,63 @@ +name: docs + +on: + push: + branches: + - main + paths: + - "docs/**" + - "mkdocs.yml" + - ".github/workflows/docs.yaml" + pull_request: + paths: + - "docs/**" + - "mkdocs.yml" + - ".github/workflows/docs.yaml" + workflow_dispatch: + +permissions: + contents: read + pages: write + id-token: write + +concurrency: + group: pages + cancel-in-progress: false + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - uses: actions/setup-python@v5 + with: + python-version: "3.12" + cache: pip + cache-dependency-path: docs/requirements.txt + + - name: Install MkDocs and plugins + run: pip install -r docs/requirements.txt + + - name: Build site + run: mkdocs build + + - name: Upload Pages artifact + if: github.event_name != 'pull_request' + uses: actions/upload-pages-artifact@v3 + with: + path: site + + deploy: + if: github.event_name != 'pull_request' + needs: build + runs-on: ubuntu-latest + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/docs/en/engine/arithmetic.md b/docs/en/engine/arithmetic.md new file mode 100644 index 0000000..3148357 --- /dev/null +++ b/docs/en/engine/arithmetic.md @@ -0,0 +1,180 @@ +# Arithmetic + +The Piklib/BlooMoo engine performs computations exclusively inside **arithmetic expressions** enclosed in square brackets. Round parentheses are reserved for method-call argument lists and do not act as grouping inside expressions. This chapter describes the available operators, the typing rules, and the conversions between primitive types. + +## Syntax + +An arithmetic expression is written between square brackets. It may appear anywhere a value is expected — including as a method argument or as the value assigned to a field: + +``` +VARIABLE_NAME^SET([VAL1+VAL2]); +*["ANIMO_"+_I_]^PLAY(); +``` + +Expressions can be nested using additional pairs of square brackets: + +``` +[[VAL1+VAL2]*VAL3] +``` + +## Typing rule + +All binary operations in expressions follow a single rule: + +> **The result's type and the right operand's type are both determined by the type of the left operand.** + +The right operand is cast to the left operand's type before the operation is performed, and the result also has that type. Examples: + +``` +"Value" + 2.5 → "Value2.50000" # DOUBLE cast to STRING +2 + "3" → 5 # STRING cast to INTEGER +``` + +A consequence: operand order matters not only for non-commutative operators, but also for the type of the result. + +## Type conversions + +Within the typing rule, the right operand is cast according to the rules below. + +### From `STRING` + +| Target | Rule | +|---|---| +| [`INTEGER`](../reference/INTEGER.md) | An integer is extracted from the start of the text (similar to `parseInt`). If the text does not start with a number, the result is `0`. | +| [`DOUBLE`](../reference/DOUBLE.md) | Same as `INTEGER`, but the fractional part is preserved. The decimal separator is a dot. | +| [`BOOL`](../reference/BOOL.md) | Text matching a truthful value (`TRUE` or a non-zero number) yields `TRUE`; otherwise `FALSE`. | + +``` +"5" → 5 +"Test" → 0 +``` + +### From `INTEGER` + +| Target | Rule | +|---|---| +| [`STRING`](../reference/STRING.md) | The decimal representation of the number. | +| [`DOUBLE`](../reference/DOUBLE.md) | The number with a zero fractional part (five zeros after the dot). | +| [`BOOL`](../reference/BOOL.md) | A non-zero value yields `TRUE`; `0` yields `FALSE`. | + +``` +5 → "5" +3 → 3.00000 +-2 → TRUE +0 → FALSE +``` + +### From `DOUBLE` + +| Target | Rule | +|---|---| +| [`STRING`](../reference/STRING.md) | Decimal representation with a dot and five fractional digits. For `0.0` the fractional part is omitted. | +| [`INTEGER`](../reference/INTEGER.md) | Rounded to the nearest integer; ties round up for positive values and down for negative values. | +| [`BOOL`](../reference/BOOL.md) | Indirect: first cast to `INTEGER` (with the rounding above), then to `BOOL`. Values in the open interval `(-0.5, 0.5)` give `FALSE`, all others `TRUE`. | + +``` +3.5 → "3.50000", 4, TRUE +0.0 → "0", 0, FALSE +0.45362 → "0.45362", 0, FALSE +1.00001 → "1.00001", 1, TRUE +-0.5 → "-0.50000", -1, TRUE +``` + +### From `BOOL` + +| Target | Rule | +|---|---| +| [`STRING`](../reference/STRING.md) | `TRUE` → `"TRUE"`, `FALSE` → `"FALSE"`. | +| [`INTEGER`](../reference/INTEGER.md) | `TRUE` → `1`, `FALSE` → `0`. | +| [`DOUBLE`](../reference/DOUBLE.md) | `TRUE` → `1.00000`, `FALSE` → `0.00000`. | + +## Arithmetic operators + +Expressions support the following binary operators: + +| Operator | Meaning | +|---|---| +| `+` | addition / concatenation | +| `-` | subtraction | +| `*` | multiplication | +| `@` | division | +| `%` | remainder | + +### Addition (`+`) + +| Left operand type | Behaviour | +|---|---| +| [`STRING`](../reference/STRING.md) | Concatenation of the right operand (after casting) onto the left. | +| [`INTEGER`](../reference/INTEGER.md) | Numeric sum. | +| [`DOUBLE`](../reference/DOUBLE.md) | Numeric sum. | +| [`BOOL`](../reference/BOOL.md) | Logical conjunction (`AND`). `TRUE + FALSE` yields `FALSE`. | + +### Subtraction (`-`) + +| Left operand type | Behaviour | +|---|---| +| [`STRING`](../reference/STRING.md) | No effect; the result is the left operand. | +| [`INTEGER`](../reference/INTEGER.md) | Numeric difference. | +| [`DOUBLE`](../reference/DOUBLE.md) | Numeric difference. | +| [`BOOL`](../reference/BOOL.md) | No effect; the result is the left operand. | + +### Multiplication (`*`) + +| Left operand type | Behaviour | +|---|---| +| [`STRING`](../reference/STRING.md) | No effect; the result is the left operand. | +| [`INTEGER`](../reference/INTEGER.md) | Numeric product. | +| [`DOUBLE`](../reference/DOUBLE.md) | Numeric product. | +| [`BOOL`](../reference/BOOL.md) | Logical disjunction (`OR`). `FALSE * TRUE` yields `TRUE`. | + +### Division (`@`) + +| Left operand type | Behaviour | +|---|---| +| [`STRING`](../reference/STRING.md) | No effect; the result is the left operand. | +| [`INTEGER`](../reference/INTEGER.md) | Integer quotient. | +| [`DOUBLE`](../reference/DOUBLE.md) | Floating-point quotient. | +| [`BOOL`](../reference/BOOL.md) | No effect; the result is the left operand. | + +Dividing a numeric type by `0` crashes the engine. + +### Remainder (`%`) + +| Left operand type | Behaviour | +|---|---| +| [`STRING`](../reference/STRING.md) | No effect; the result is the left operand. | +| [`INTEGER`](../reference/INTEGER.md) | Remainder. | +| [`DOUBLE`](../reference/DOUBLE.md) | Remainder truncated to an integer and then cast back to `DOUBLE`. The fractional part is lost — for example, `1.5 % 2` yields `1.00000`, not `1.50000`. | +| [`BOOL`](../reference/BOOL.md) | No effect; the result is the left operand. | + +Taking a remainder with `0` as the right operand crashes the engine. + +## Comparison operators + +Expressions support the standard comparisons: `==`, `!=`, `<`, `<=`, `>`, `>=`. The right operand is first cast to the left operand's type (per the [typing rule](#typing-rule)), and the comparison is then performed. + +### Equality and inequality + +`==` returns `TRUE` if both operands (after casting) are equal; `!=` returns the opposite. For [`STRING`](../reference/STRING.md) the comparison is character-by-character; for numeric types, it is value-based. + +### Less / greater + +| Left operand type | `<` returns `TRUE` if | +|---|---| +| [`STRING`](../reference/STRING.md) | The left operand is lexicographically smaller than the right (character-by-character in CP1250 encoding). | +| [`INTEGER`](../reference/INTEGER.md) | The left operand's value is smaller. | +| [`DOUBLE`](../reference/DOUBLE.md) | The left operand's value is smaller. | +| [`BOOL`](../reference/BOOL.md) | The left operand is `FALSE` and the right is `TRUE` (`FALSE < TRUE`). | + +`>` returns `TRUE` in the symmetric cases. `<=` and `>=` are equivalent to `<` or `==`, and `>` or `==`, respectively. + +## Logical operators + +`&&` (conjunction) and `||` (disjunction) accept only [`BOOL`](../reference/BOOL.md) operands. Passing an operand of another type (even one that could be cast) crashes the engine. + +| Operator | Result | +|---|---| +| `&&` | `TRUE` only if both operands are `TRUE`. | +| `||` | `TRUE` if at least one operand is `TRUE`. | + +Inside the [compound `@IF` condition](scripts.md#compound-condition), `&&` and `||` behave the same way, but they are part of the condition string rather than operators of an arithmetic expression. diff --git a/docs/en/engine/events.md b/docs/en/engine/events.md new file mode 100644 index 0000000..6f7d222 --- /dev/null +++ b/docs/en/engine/events.md @@ -0,0 +1,90 @@ +# Events and signals + +The Piklib/BlooMoo engine drives game logic with a reactive, signal-based model. Every object can emit named signals, and scripts can attach procedures or code blocks to react to them. This chapter describes how the mechanism works and lists the most common signals. + +## Attaching a signal handler + +A signal is attached like any other property of an object — the value is either a procedure name or a code block: + +``` +OBJECT_NAME:ONCHANGED=PROCEDURE_NAME +OBJECT_NAME:ONCHANGED={OTHER_OBJECT^PLAY("TADA");} +``` + +Each signal name can have at most one handler attached to it on a given object. + +## Parameterised signals + +Some signals — notably [`ONCHANGED`](#onchanged) and [`ONBRUTALCHANGED`](#onbrutalchanged) — are emitted together with a value. That value can be used to filter the handler: the engine first looks up a handler matching the pair `signal + value`, and only falls back to a generic handler for the signal name if no specific one is registered. + +The discriminator follows the signal name after a caret `^`: + +``` +OBJECT_NAME:ONBRUTALCHANGED^3=HANDLER_FOR_THREE +OBJECT_NAME:ONBRUTALCHANGED=GENERIC_HANDLER +``` + +In the example above, `OBJECT^SET(3)` runs `HANDLER_FOR_THREE`; any other value runs `GENERIC_HANDLER`. + +## Handler execution + +The signal system is synchronous and single-threaded. Emitting a signal immediately transfers control to its handler: the currently executing procedure is paused, the handler runs, and once it returns, control resumes where the signal was emitted. Signals are not queued. + +A chain of nested signal–procedure–signal–procedure invocations forms a call tree. The jump operators affect that tree as follows: + +- [`@ONEBREAK`](scripts.md#jump-operators) — aborts only the current procedure and returns to its caller. +- [`@BREAK`](scripts.md#jump-operators) — aborts the entire call tree started by the original signal emission. + +## Signal arguments + +Some signals are emitted with extra arguments. Inside a handler, those arguments are available exactly like procedure arguments — through `$1`, `$2`, … (numbered from `1`). This lets a handler react to the specific value that triggered the signal. + +## Universal signals + +### ONINIT + +Fired during the variable's initialisation as its file is loaded. The order in which `ONINIT` is fired across the variables of a single file is fixed and goes by type; the details are in [Variable initialisation](scripts.md#variable-initialisation). + +Typical uses: filling in [arrays](../reference/index.md), setting up the initial state of animations, loading data from external files. + +### ONSIGNAL + +A general-purpose signal, emitted by calling the global `SEND` method on an object: + +``` +OBJECT_NAME^SEND("MY_SIGNAL"); +``` + +The string passed in is available inside the handler as the first argument (`$1`). This mechanism allows custom events to be defined without relying on value changes or animation events. + +## Value-change signals + +Fired by [primitive types](../reference/index.md) (and any other type with a `VALUE` field) whenever the value is modified. + +### ONCHANGED + +Fired only when the new value differs from the previous one. The argument (`$1`) is the new value. + +### ONBRUTALCHANGED + +Fired on every modification, even if the new value is identical to the previous one. The argument (`$1`) is the new value. + +In practice, `ONBRUTALCHANGED` is useful for detecting that a value-setting method (`SET`, `INC`, `SWITCH`, …) was called at all, regardless of whether it actually changed the value. + +## Signals from graphical objects and sequences + +### ONSTARTED + +Fired when an animation or sequence starts playing. + +- For a **sequence** — fired once, with the current event name from the `.SEQ` file as its argument. +- For an **animation** — fired with the event name from the `.ANN` file. If the animation is driven by a sequence, this signal can fire multiple times as the animation loops. + +### ONFINISHED + +Fired when playback finishes: + +- for an **animation** — after the last frame is displayed and playback stops, +- for a **sequence** — after the last event finishes (or for each individual event played in turn, depending on configuration). + +In both cases the signal is also fired in response to a manual `STOP` call (with no argument or with `TRUE`). diff --git a/docs/en/engine/globals.md b/docs/en/engine/globals.md new file mode 100644 index 0000000..76dcfa7 --- /dev/null +++ b/docs/en/engine/globals.md @@ -0,0 +1,70 @@ +# Global and built-in variables + +The engine exposes a handful of variables and names that can be referenced from anywhere in the scripts, regardless of context depth. This chapter covers the built-in objects, the implicit variables, the special procedures, and the variable-lookup hierarchy. + +## Context hierarchy + +Each loaded script creates its own variable context. Contexts are nested: a scene's context inherits from its episode's context, which inherits from the application's context, which in turn inherits from the engine's global context. Variable lookup walks from the lowest context upwards — a variable in a lower context shadows one with the same name in a higher context, but higher-context variables remain visible from lower ones. + +## Built-in objects + +The following objects are created lazily by the engine on first access and are available from any context under fixed names: + +| Name | Type | Description | +|---|---|---| +| `MOUSE` | [`MOUSE`](../reference/index.md) | Mouse state (position, buttons). | +| `KEYBOARD` | [`KEYBOARD`](../reference/index.md) | Keyboard state. | +| `RAND` | [`RAND`](../reference/index.md) | Pseudo-random number generator. Also available under the alias `RANDOM`. | +| `SYSTEM` | [`SYSTEM`](../reference/index.md) | Interface to system functions (time, environment). | + +All four objects are singletons in the engine's global context — every script reference resolves to the same instance. + +## Objects from `Application.def` + +Objects defined in `Application.def` — of type [`APPLICATION`](../reference/index.md), [`EPISODE`](../reference/index.md), and [`SCENE`](../reference/index.md) — are loaded into the engine's global context and remain visible to every script in the game. Other types in that file are ignored (see [Entry point](scripts.md#entry-point)). + +## Implicit variables + +The engine injects a few variables that are not declared explicitly in scripts. + +### `_I_` + +The loop counter set up by the [`@LOOP`](scripts.md#loop) statement. It is an [`INTEGER`](../reference/INTEGER.md) variable created locally in the current iteration's context. Its value updates automatically as the loop progresses. + +Inside a `@LOOP`, `_I_` can be read in arithmetic expressions and passed as a method argument: + +``` +@LOOP({*["ANIMO_"+_I_]^PLAY();}, 0, 10, 1); +``` + +The [`@FOR`](scripts.md#for-bloomoo) loop allows a custom counter name to be supplied; in that case `_I_` is not set. + +### `THIS` + +A reference to the object that emitted the signal currently being handled. Only available inside a signal-handling block and procedures called from it. Its behaviour is detailed in [The THIS variable](scripts.md#the-this-variable). + +### `$1`, `$2`, … `$N` + +The arguments of a procedure or signal handler (numbered from `1`). Available only inside the body of a procedure or handler block: + +``` +PROCEDURE:CODE={VARIABLE_NAME^SET($1);} +``` + +This syntax is also covered in [Procedure arguments](scripts.md#procedure-arguments). + +## Special procedures + +Certain procedure names have conventional meaning — the engine invokes them automatically at fixed points in the lifecycle. + +### `__ONINIT__` + +Called once the initialisation of every variable in a loaded file has finished. See [Variable initialisation](scripts.md#variable-initialisation). A common use is to set the scene's initial state once all of its objects are available. + +### `__INIT__` + +Called after the scene has been loaded and variable initialisation has completed — just before control is handed off to the game's logic. Used to set scene-specific state that depends on the current episode or application. + +## Naming convention + +Names surrounded by double underscores (`__NAME__`) are reserved for the engine and for global conventional names (e.g. `__KEYB__`, `__INIT__`, `__ONINIT__`). AidemMedia scripts also use this format for their own globally significant variables to avoid being shadowed in local contexts. diff --git a/docs/en/engine/index.md b/docs/en/engine/index.md new file mode 100644 index 0000000..e69fbe4 --- /dev/null +++ b/docs/en/engine/index.md @@ -0,0 +1,38 @@ +# Engine + +**Piklib** (later **BlooMoo**) is a 32-bit graphical engine created by Aidem Media for a series of Polish adventure games released in the 2000s. This documentation describes the engine's internal logic and how it executes the games' scripts. + +## Scope + +This documentation focuses on the engine's **scripting language** and the **execution model** as seen from script-level code — that is, what a content programmer needs in order to read existing scripts or write new ones. + +It is not a documentation of the engine's source code, nor a complete specification of every internal data structure; those areas are being filled in gradually. + +## Structure + +The engine documentation is divided into five chapters: + +- [Scripts](scripts.md) — script syntax, the parser, loading order, and object initialisation. +- [Arithmetic](arithmetic.md) — computational expressions, operators, and conversion rules between primitive types. +- [Events and signals](events.md) — the engine's reactive model, attaching handlers, propagation through the call tree. +- [Global variables](globals.md) — built-in objects (`MOUSE`, `KEYBOARD`, `RAND`, `SYSTEM`), implicit variables (`_I_`, `THIS`, `$N`), and special procedures. +- [Engine quirks](quirks.md) — non-standard behaviours that are easy to miss. + +The full list of available data types is in the [Type reference](../reference/index.md). + +## Games using the engine + +The list is incomplete and will be extended as more titles are identified. + +| Game | Engine version | +|---|---| +| Reksio i Skarb Piratów | Piklib 8 | +| Reksio i Ufo | Piklib 7.1, Piklib 8 | +| Reksio i Czarodzieje | Piklib 8 | +| Reksio i Wehikuł Czasu | Piklib 8 | +| Reksio i Kapitan Nemo | BlooMoo | +| Reksio i Kretes w Akcji | BlooMoo | +| Poznaj Mity: Wyprawa po Złote Runo | Piklib 7.1 | +| Poznaj Mity: Wojna Trojańska | Piklib 7.2 | +| Poznaj Mity: Przygody Odyseusza | Piklib 8 | +| Poznaj Mity: Herkules | Piklib 8 | diff --git a/docs/en/engine/quirks.md b/docs/en/engine/quirks.md new file mode 100644 index 0000000..7e34b93 --- /dev/null +++ b/docs/en/engine/quirks.md @@ -0,0 +1,118 @@ +# Engine quirks + +The Piklib/BlooMoo engine has a number of non-standard behaviours that often surprise programmers used to mainstream scripting languages. This chapter collects the most common ones in a single place. + +## Expressions and operators + +### Only square brackets group computations + +Inside arithmetic expressions, grouping is done exclusively with `[ ]`. Round parentheses `( )` are reserved for method-call argument lists and have no grouping role (see [Arithmetic](arithmetic.md#syntax)). + +### `@` instead of `/` for division + +The division operator is the at-sign `@`, not `/`. Using `/` in an expression is not interpreted as division. + +### The result type follows the left operand + +All binary operations cast the right operand to the type of the left. The result also takes the left operand's type. The order of operands has non-trivial consequences (see [Typing rule](arithmetic.md#typing-rule)): + +``` +"Value" + 2.5 → "Value2.50000" +2 + "3" → 5 +``` + +### Operators on `BOOL` have inverted logic + +The `+` operator on [`BOOL`](../reference/BOOL.md) behaves as a logical conjunction (`AND`), and `*` as a disjunction (`OR`). The operators `-`, `@`, and `%` on `BOOL` have no effect (see [Arithmetic operators](arithmetic.md#arithmetic-operators)). + +### `%` on `DOUBLE` loses the fractional part + +The remainder operator on [`DOUBLE`](../reference/DOUBLE.md) first computes the result and then truncates it to an integer before casting it back to `DOUBLE`. As a result, `1.5 % 2` yields `1.00000`, not `1.50000`. + +### `&&` and `||` accept only `BOOL` + +The logical operators perform no implicit casting, even when the operand could be converted to `BOOL`. Passing an operand of any other type crashes the engine. + +### Division by `0` in expressions crashes + +Unlike the numeric-type methods (where `DIV` and `MOD` leave the value unchanged), the `@` and `%` operators in an arithmetic expression crash the engine when the right operand is `0`. + +## Script syntax + +### Code blocks must fit on one line + +The entire block between `{` and `}` must fit on a single line of the script file. Multi-line blocks are not supported. + +### Every statement must end with a semicolon + +Including the last statement in a code block. Omitting the final semicolon can cause that statement to be skipped. + +### Comments: `#` for lines, `!` for statements + +A line starting with `#` is skipped entirely. A single statement preceded by `!` is commented out up to the next semicolon. + +### The equality comparator changes in compound conditions + +In a [simple `@IF` condition](scripts.md#simple-condition), equality is written as `_`. In a [compound `@IF` condition](scripts.md#compound-condition), the same comparator is written as an apostrophe `'`. The remaining comparators (`<`, `>`, `<_`/`<'`, `>_`/`>'`) follow the same pattern. + +### Unquoted text is first looked up as a variable name + +A value written without quotes is first interpreted as a variable name. If a variable with that name exists, its value is used; otherwise the text is treated as a [`STRING`](../reference/STRING.md) literal. This can lead to hard-to-spot collisions when a literal accidentally matches a variable name. + +### Repeated object declarations merge properties + +A repeated `OBJECT=NAME` line in the same file does not overwrite the previous definition — the engine merges the new properties into the existing object and overrides entries with the same keys. + +### `Application.def` should end with an empty line + +Missing a trailing empty line in `Application.def` can leave the last scene incorrectly parsed, which manifests as a black screen at startup. + +## Numbers + +### `DOUBLE` accepts `d` as the exponent marker + +In scientific notation, both `e` and `d` are recognised as exponent separators: `1.23e4` and `1.23d4` are equivalent. + +### `DOUBLE → INTEGER` rounds, it does not truncate + +When casting [`DOUBLE`](../reference/DOUBLE.md) to [`INTEGER`](../reference/INTEGER.md), the value is rounded to the nearest integer rather than truncated. For positive values, `.5` rounds up; for negative values, it rounds down — so `-0.5 → -1` and `0.5 → 1`. + +### `STRING → INTEGER` returns `0` instead of erroring + +Casting a non-numeric string to [`INTEGER`](../reference/INTEGER.md) (or [`DOUBLE`](../reference/DOUBLE.md)) returns `0` (`0.00000`) silently. This can mask bugs in expressions mixing textual literals with numeric ones. + +## Type methods + +### `DOUBLE.MOD` drops the fractional part + +Like the `%` operator, [`MOD`](../reference/DOUBLE.md#mod) on `DOUBLE` returns the integer part of the remainder. + +### `DOUBLE.SGN` returns `INTEGER`, not `DOUBLE` + +The [`SGN`](../reference/DOUBLE.md#sgn) method is the only `DOUBLE` method that does not modify the variable, and its return value is an [`INTEGER`](../reference/INTEGER.md). + +### `INTEGER.RANDOM(min, max)` is inclusive on both ends + +The two-argument form of [`RANDOM`](../reference/INTEGER.md#random) returns a value from `[min, max]`, including both endpoints. The one-argument form returns `[0, bound)`. + +### `INTEGER.DIV` and `INTEGER.MOD` with `0` leave the value unchanged + +Unlike division with the `@`/`%` operators in an expression, the [`DIV`](../reference/INTEGER.md#div) and [`MOD`](../reference/INTEGER.md#mod) methods on `INTEGER` return the unchanged current value when given a `0` divisor instead of crashing. The same applies to the `DOUBLE` variants. + +### `STRING.COPYFILE` ignores its receiver + +The [`COPYFILE`](../reference/STRING.md#copyfile) method on [`STRING`](../reference/STRING.md) does not use the value of the variable on which it is called — it operates purely on its two path arguments. + +### `STRING.CHANGEAT` always replaces exactly one character + +Regardless of the length of the replacement string, [`CHANGEAT`](../reference/STRING.md#changeat) removes a single character from the current value at the given position and inserts the entire replacement string in its place. The string length after the operation may differ from before. + +## `THIS` in signal handlers + +### `THIS.GETNAME` returns `"temp"` + +Even though `THIS` references the object that emitted the signal, retrieving its name with `GETNAME` returns the string `"temp"`, hinting at an internal temporary-wrapper representation. + +### Not every type-specific method works on `THIS` + +Calling `GET`/`SET` (for primitive types) or `SHOW`/`HIDE`/`PLAY`/`PAUSE`/`STOP`/`RESUME` (for graphical objects) works reliably. Calling a type-specific method such as [`GETCFRAMEINEVENT`](../reference/index.md) on `ANIMO` typically crashes the engine. See [The THIS variable](scripts.md#the-this-variable) for details. diff --git a/docs/en/engine/scripts.md b/docs/en/engine/scripts.md new file mode 100644 index 0000000..9740c01 --- /dev/null +++ b/docs/en/engine/scripts.md @@ -0,0 +1,280 @@ +# Scripts + +The Piklib/BlooMoo engine drives game logic by interpreting text-based scripts. This chapter describes the syntax of those scripts, how the engine loads them, and the order in which objects are initialised. + +## File formats + +Scripts are stored in files with the `.CNV`, `.DEF`, `.CLASS`, and `.SEQ` extensions. They all share the same basic textual structure and differ only in their intended use. + +The engine treats all script content as uppercase and is case-insensitive. By convention, scripts are written in uppercase. + +### Encryption + +Files shipped with the game are encrypted by default using a transposition cipher with a variable offset. An encrypted file begins with a header of the form: + +``` +{} +``` + +where `X` is a letter indicating the direction of the offset (`D` means a negative offset) and `N` is the offset value. The engine detects this header automatically and decrypts the rest of the file before parsing. Files without this header are read as plain text. + +## Object declaration + +An object begins with a line containing the `OBJECT` keyword: + +``` +OBJECT=OBJECT_NAME +``` + +Lines between consecutive `OBJECT=` lines define properties of the current object. The definition lasts until the end of the file or the next `OBJECT=` line. + +If the same object is declared more than once in a single file, its properties are merged — later entries override earlier ones. + +## Object properties + +Properties are written as `objectName:property=value`: + +``` +OBJECT_NAME:PROPERTY=VALUE +``` + +Signals can take an additional parameter after a caret (`^`): + +``` +OBJECT_NAME:ONBRUTALCHANGED^3=PROCEDURE_NAME +``` + +In both cases, the engine accepts both `KEY=VALUE` and `KEY = VALUE` (with spaces around the equals sign). + +## Variable type + +The type is essential — without it, the engine does not know how to handle the object, and the result is usually a hard crash. The type is declared with the `TYPE` property: + +``` +OBJECT_NAME:TYPE=STRING +``` + +The full list of available types is in the [Type reference](../reference/index.md). + +## Literals and strings + +How a literal is interpreted depends on its context: + +- Text in double quotes (`"..."`) is always treated as a [`STRING`](../reference/STRING.md). +- Unquoted text is first checked against the names of existing variables — if a variable with that name exists, its value is used. Otherwise the text is taken literally. + +Floating-point numbers accept both standard notation (`1.234`) and scientific notation with the letter `e` or `d` (`1.23e4`, `1.23d4`). + +## Code blocks + +Code blocks — used as the value of a signal or as the body of a procedure — are written inside curly braces. Statements are separated by semicolons; the final statement must also end with a semicolon, otherwise it may not be executed. + +``` +OBJECT_NAME:ONCHANGED={VARIABLE2^PLAY("TADA");} +``` + +The entire code block must fit on a single line — the engine does not support multi-line blocks directly inside a script file. + +## Comments + +The engine recognises two forms of comments: + +- **Line comment** — a line starting with `#` is skipped entirely. +- **Statement comment** — a single statement preceded by `!` is treated as commented out, up to the next semicolon. + +## Method calls + +Methods are called using the caret (`^`): + +``` +OBJECT_NAME^METHOD(arg1, arg2); +``` + +## Arithmetic expressions + +Computational expressions are written inside square brackets: + +``` +VARIABLE_NAME^SET([VARIABLE_NAME^GET()+"2"]); +``` + +Operators and typing rules are described in the [Arithmetic](arithmetic.md) chapter. + +## String pointers + +A `*` before a variable name or an expression means that the value is to be used as the name of another variable. This allows dynamic references built from text: + +``` +*VARIABLE_NAME^PLAY(); +*["ANIMO_"+_I_]^PLAY(); +``` + +In the first form, `VARIABLE_NAME` should be a [`STRING`](../reference/STRING.md) containing the actual object's name. In the second, the object name is constructed from an arithmetic expression. + +## Procedure arguments + +Inside the body of a procedure, arguments are accessed with a dollar sign followed by a number (numbered from `1`): + +``` +PROCEDURE:CODE={VARIABLE_NAME^SET($1);} +``` + +## The THIS variable + +Inside a block that handles a signal, an implicit `THIS` variable is available, set to a reference to the object that fired the signal. `THIS` is also accessible from procedures called from within such a block. + +`THIS` behaves unusually: calling `GETNAME` on it returns the string `"temp"`, suggesting that under the hood it is a temporary wrapper. The following work reliably on `THIS`: + +- `GET` and `SET` for primitive types, +- `SHOW`, `HIDE`, `PLAY`, `PAUSE`, `STOP`, and `RESUME` for graphical objects ([`ANIMO`](../reference/index.md)). + +Calling another type-specific method (e.g. `GETCFRAMEINEVENT` on [`ANIMO`](../reference/index.md)) usually crashes the engine. To work around this, AidemMedia scripts use the following pattern: store the object's name in a [`STRING`](../reference/STRING.md) variable first, then call `^RUN(string_variable, method_name)`, which internally resolves the string pointer to the actual object. + +## Loops + +### @LOOP + +``` +@LOOP(BEHAVIOUR code, INTEGER start, INTEGER delta, INTEGER increment) +``` + +Executes `code` for counter values `_I_` in the range `[start, start + delta)` with step `increment`. In pseudocode: + +``` +for (int _I_ = start; _I_ < start + delta; _I_ += increment) { + code; +} +``` + +### @FOR (BlooMoo) + +``` +@FOR(INTEGER counter, BEHAVIOUR code, INTEGER start, INTEGER delta, INTEGER increment) +``` + +Identical to `@LOOP`, except that the first argument selects a custom variable to act as the counter instead of the default `_I_`. + +### @WHILE + +``` +@WHILE(mixed value1, STRING comparator, mixed value2, BEHAVIOUR code) +``` + +Executes `code` as long as the condition `value1 comparator value2` holds. The list of comparators is described below in [Conditional](#conditional). + +## Conditional + +The engine provides two forms of `@IF`. + +### Simple condition + +``` +@IF(mixed value1, STRING comparator, mixed value2, BEHAVIOUR codeTrue, BEHAVIOUR codeFalse) +``` + +Available comparators: + +| Comparator | Meaning | +|---|---| +| `_` | equal to | +| `!_` | not equal to | +| `<` | less than | +| `<_` | less than or equal | +| `>` | greater than | +| `>_` | greater than or equal | + +### Compound condition + +``` +@IF(STRING condition, BEHAVIOUR codeTrue, BEHAVIOUR codeFalse) +``` + +Compound conditions add logical operators: + +- `&&` — conjunction (and) +- `||` — disjunction (or) + +In a compound condition, the equals sign is written as an apostrophe (`'`) rather than an underscore (`_`): + +| Comparator | Meaning | +|---|---| +| `'` | equal to | +| `!'` | not equal to | +| `<` | less than | +| `<'` | less than or equal | +| `>` | greater than | +| `>'` | greater than or equal | + +## Dynamic variable creation + +Variables can be created on the fly inside a code block: + +``` +@INT(STRING name, INTEGER value) +@DOUBLE(STRING name, DOUBLE value) +@STRING(STRING name, STRING value) +@BOOL(STRING name, BOOL value) +``` + +Each statement creates a variable of the matching type with the given name and initial value. + +## Jump operators + +Inside loops and procedures, control flow can be redirected with: + +- `@CONTINUE()` — skips the remaining statements in the current loop iteration and moves to the next one. +- `@BREAK()` — aborts the entire call tree started by the current signal or invocation. +- `@ONEBREAK()` — aborts the current procedure only. +- `@RETURN(mixed value)` — sets the value returned by the procedure but does not stop it from executing. + +## Script loading order + +Scripts in the engine are organised hierarchically: scripts at lower levels can see variables from their own scope and from all ancestors, but not the other way around. + +### Entry point + +The engine starts from `Application.def` in the `dane` subdirectory. This file defines objects of types [`APPLICATION`](../reference/index.md), [`EPISODE`](../reference/index.md), and [`SCENE`](../reference/index.md) — other types in this file are ignored. + +Example contents: + +``` +OBJECT=GAME +GAME:TYPE=APPLICATION +GAME:PATH=GAME +GAME:EPISODES=PRZYGODA +GAME:STARTWITH=PRZYGODA + +OBJECT=PRZYGODA +PRZYGODA:TYPE=EPISODE +PRZYGODA:PATH=GAME\PRZYGODA +PRZYGODA:SCENES=START,CREDITS,LEBIODKA +PRZYGODA:STARTWITH=START + +OBJECT=START +START:TYPE=SCENE +START:PATH=GAME\PRZYGODA\START +``` + +### Loading subsequent files + +After `Application.def` is read, the engine loads a `.CNV` file for each defined object. The file path is built from the object's `PATH` attribute (relative to the `dane` directory), the object's name, and the `.CNV` extension. If the file does not exist, loading is silently skipped. + +The loading order is: + +1. The file bound to the `APPLICATION` object. +2. The file of the first episode (`STARTWITH` attribute of `APPLICATION`). +3. The file of the first scene of that episode (`STARTWITH` attribute of `EPISODE`). + +When locating files, the engine also takes the currently selected language into account (see [`APPLICATION.SETLANGUAGE`](../reference/APPLICATION.md#setlanguage)) — the chosen language identifier points to a subfolder of localised assets that is consulted while loading game files. + +### Variable initialisation + +Within each file, variables are created and initialised in a fixed order by type: + +1. Procedures. +2. Primitive types ([`STRING`](../reference/STRING.md), [`DOUBLE`](../reference/DOUBLE.md), [`INTEGER`](../reference/INTEGER.md), [`BOOL`](../reference/BOOL.md)). +3. Arrays and conditions. +4. Animations, images, sounds, and fonts. +5. Buttons, text fields, sequences, mouse, keyboard, canvas observer. + +For each variable in this phase the `ONINIT` signal is fired. Once all variables are initialised, the engine calls the `__ONINIT__` procedure if one is defined. diff --git a/docs/en/index.md b/docs/en/index.md new file mode 100644 index 0000000..f1733a5 --- /dev/null +++ b/docs/en/index.md @@ -0,0 +1,19 @@ +# Rex-EMoolator + +Unofficial documentation of the **Piklib** and **BlooMoo** scripting engines used by the *Reksio's Adventures* game series, and of the **Rex-EMoolator** emulator. + +## What you'll find here + +- the structure of the engine's scripting language, +- the data types and objects available to scripts, +- the methods, fields, and signals exposed by each type, +- how the engine interprets files, the loading order, and the data formats. + +## Navigation + +- [Engine](engine/index.md) — the scripting language, execution model, events, globals, and non-standard behaviours. +- [Type reference](reference/index.md) — alphabetical list of types available in scripts. + +## Status + +This documentation is a work in progress. Much of it is derived from analysis of the original scripts and engine reverse-engineering; behaviour that has not yet been confirmed is annotated accordingly. diff --git a/docs/en/reference/ANIMO.md b/docs/en/reference/ANIMO.md new file mode 100644 index 0000000..22302aa --- /dev/null +++ b/docs/en/reference/ANIMO.md @@ -0,0 +1,875 @@ +# ANIMO + +An animation loaded from an `.ANN` file. The most complex visual type in the engine — supports multiple events (frame sequences), variable FPS, an anchor point, opacity, collision monitoring, and a button mode. + +An animation is made up of **events**, each of which is a sequence of **frames**. The frame index inside an event starts at `0`, and the global frame index across the whole animation is also tracked separately from `0`. + +## Fields + +### ASBUTTON + +``` +BOOL ASBUTTON +``` + +Treats the animation as a clickable button. Modified through [`SETASBUTTON`](#setasbutton). + +### FILENAME + +``` +STRING FILENAME +``` + +Name of the `.ANN` file with the animation. Read at variable initialisation; can be overwritten via [`LOAD`](#load). + +### FPS + +``` +INTEGER FPS +``` + +Number of animation frames per second. Modified through [`SETFPS`](#setfps). + +### MONITORCOLLISION + +``` +BOOL MONITORCOLLISION +``` + +Whether the animation participates in collision detection. Modified through [`MONITORCOLLISION`](#monitorcollision-1) and [`REMOVEMONITORCOLLISION`](#removemonitorcollision). + +### MONITORCOLLISIONALPHA + +``` +BOOL MONITORCOLLISIONALPHA +``` + +Whether collision detection takes the alpha channel into account. + +### PRELOAD + +``` +BOOL PRELOAD +``` + +Whether the animation data is loaded eagerly at initialisation. + +### PRIORITY + +``` +INTEGER PRIORITY +``` + +Rendering priority (`Z`) relative to other scene objects. + +### TOCANVAS + +``` +BOOL TOCANVAS +``` + +Whether the animation is drawn on the scene's main canvas. Setting this to `FALSE` hides the animation visually, but the engine keeps playing it and firing the associated events. + +### VISIBLE + +``` +BOOL VISIBLE +``` + +Animation visibility. Modified through [`SHOW`](#show) and [`HIDE`](#hide). + +## Methods + +### GETANCHOR + +``` +STRING GETANCHOR() +``` + +Returns the currently configured anchor, in the form passed to [`SETANCHOR`](#setanchor). + +**Returns**: the anchor name or its coordinates. + +### GETCENTERX + +``` +INTEGER GETCENTERX() +``` + +Returns the X coordinate of the centre of the current frame's bounding box. + +**Returns**: centre X. + +**Examples** + +``` +ANNREX^GETCENTERX(); +``` + +### GETCENTERY + +``` +INTEGER GETCENTERY() +``` + +Returns the Y coordinate of the centre of the current frame's bounding box. + +**Returns**: centre Y. + +### GETCFRAMEINEVENT + +``` +INTEGER GETCFRAMEINEVENT() +``` + +Returns the index of the current frame inside the currently playing event (counted from `0`). + +**Returns**: the frame's index in the event. + +**Examples** + +``` +ANNREX^GETCFRAMEINEVENT(); +``` + +### GETCURRFRAMEPOSX + +``` +INTEGER GETCURRFRAMEPOSX() +``` + +Returns the X offset of the currently displayed frame image (per-frame, defined in the animation file). + +**Returns**: frame X offset. + +### GETCURRFRAMEPOSY + +``` +INTEGER GETCURRFRAMEPOSY() +``` + +Returns the Y offset of the currently displayed frame image. + +**Returns**: frame Y offset. + +### GETENDX + +``` +INTEGER GETENDX() +``` + +Returns the right edge of the current frame's bounding box. + +**Returns**: right edge X. + +### GETENDY + +``` +INTEGER GETENDY() +``` + +Returns the bottom edge of the current frame's bounding box. + +**Returns**: bottom edge Y. + +### GETEVENTNAME + +``` +STRING GETEVENTNAME() +``` + +Returns the name of the currently playing event. + +**Returns**: event name. + +**Examples** + +``` +ANNREX^GETEVENTNAME(); +``` + +### GETFRAME + +``` +INTEGER GETFRAME() +``` + +Returns the global index of the currently displayed frame (independent of the event subdivision). + +**Returns**: the global frame index. + +### GETFRAMENAME + +``` +STRING GETFRAMENAME() +``` + +Returns the name of the currently displayed frame (the frame image file name). + +**Returns**: the frame name. + +### GETHEIGHT + +``` +INTEGER GETHEIGHT() +``` + +Returns the height of the current animation frame. + +**Returns**: height in pixels. + +### GETMAXHEIGHT + +``` +INTEGER GETMAXHEIGHT() +``` + +Returns the maximum height across all of the animation's frames. + +**Returns**: the largest height in pixels. + +### GETMAXWIDTH + +``` +INTEGER GETMAXWIDTH() +``` + +Returns the maximum width across all of the animation's frames. + +**Returns**: the largest width in pixels. + +**Examples** + +``` +ANN_STATEK^GETMAXWIDTH(); +``` + +### GETNAME + +``` +STRING GETNAME() +``` + +Returns the animation variable's name. + +**Returns**: the variable's name. + +### GETNOE + +``` +INTEGER GETNOE() +``` + +Returns the number of events in the animation (short for *Number Of Events*). + +**Returns**: event count. + +**Examples** + +``` +ANNLISCIESLOTY^GETNOE(); +ANNBTN^GETNOE(); +``` + +### GETNOF + +``` +INTEGER GETNOF() +``` + +Returns the total number of frames in the animation (short for *Number Of Frames*). + +**Returns**: frame count. + +### GETNOFINEVENT + +``` +INTEGER GETNOFINEVENT(INTEGER eventId) +INTEGER GETNOFINEVENT(STRING eventName) +``` + +Returns the number of frames in the given event. The event can be identified by its number (from `0`) or by its name (case-insensitive). For a non-existent event, `0` is returned. + +**Parameters** + +- `eventId` / `eventName` — event identifier. + +**Returns**: frame count in the event. + +**Examples** + +``` +ANNREX^GETNOFINEVENT(VARSTEMP0); +ANNUKLAD^GETNOFINEVENT(0); +ANNPLANNAK^GETNOFINEVENT("IDLE"); +``` + +### GETPOSITIONX + +``` +INTEGER GETPOSITIONX([BOOL absolute]) +``` + +Returns the X coordinate of the current frame's top-left corner on the canvas. The variant with a `BOOL` argument returns the absolute position, ignoring per-frame offsets defined in the animation file. + +**Parameters** + +- `absolute` — (optional) `TRUE` to skip per-frame offsets. + +**Returns**: position X. + +### GETPOSITIONY + +``` +INTEGER GETPOSITIONY([BOOL absolute]) +``` + +Returns the Y coordinate of the current frame's top-left corner on the canvas. The variant with a `BOOL` argument returns the absolute position. + +**Parameters** + +- `absolute` — (optional) `TRUE` to skip per-frame offsets. + +**Returns**: position Y. + +### GETPRIORITY + +``` +INTEGER GETPRIORITY() +``` + +Returns the animation's rendering priority (`Z`). + +**Returns**: the value of the [`PRIORITY`](#priority) field. + +### GETWIDTH + +``` +INTEGER GETWIDTH() +``` + +Returns the width of the current animation frame. + +**Returns**: width in pixels. + +### HIDE + +``` +void HIDE() +``` + +Hides the animation visually without stopping its playback. Calling [`PLAY`](#play) automatically restores visibility. + +### ISAT + +``` +BOOL ISAT(INTEGER posX, INTEGER posY) +``` + +Checks whether the point at the given coordinates lies inside the current frame's bounding box. + +**Parameters** + +- `posX` — point X coordinate. +- `posY` — point Y coordinate. + +**Returns**: [`BOOL`](BOOL.md) — `TRUE` if the point is inside the bounding box. + +### ISNEAR + +``` +BOOL ISNEAR(STRING animoName, INTEGER iouThresholdPercent) +``` + +Checks whether this animation is close to another animation. Internally, the Jaccard index (*Intersection over Union*, IoU) of the two animations' bounding boxes is computed; if the IoU exceeds the given threshold (in percent), `TRUE` is returned. + +**Parameters** + +- `animoName` — name of the other animation. +- `iouThresholdPercent` — IoU threshold in percent. + +**Returns**: [`BOOL`](BOOL.md) — `TRUE` if the IoU exceeds the threshold. + +**Examples** + +``` +ENEMY^ISNEAR("HERO", 1); +ANNORKA^ISNEAR("ANNLODKA", 12); +``` + +### ISPLAYING + +``` +BOOL ISPLAYING() +BOOL ISPLAYING(STRING eventName) +``` + +Checks whether the animation is currently playing. The no-argument variant returns whether any event is currently playing; with a name, the check is limited to that specific event. + +**Parameters** + +- `eventName` — (optional) name of the event to check. + +**Returns**: [`BOOL`](BOOL.md) — `TRUE` if the animation (or the specific event) is playing. + +**Examples** + +``` +ANNREX^ISPLAYING(); +ANNREXGLOWA^ISPLAYING("SPI"); +``` + +### ISVISIBLE + +``` +BOOL ISVISIBLE() +``` + +Checks whether the animation is visible ([`VISIBLE`](#visible) = `TRUE` and [`TOCANVAS`](#tocanvas) = `TRUE`). + +**Returns**: [`BOOL`](BOOL.md) — `TRUE` if the animation is visible. + +### LOAD + +``` +void LOAD(STRING path) +``` + +Loads an animation from an `.ANN` file, replacing the previous contents. + +**Parameters** + +- `path` — `.ANN` file path in the game's VFS. + +**Examples** + +``` +ANNBKG^LOAD(SOBJECT|NAME); +ANNCHARACTER^LOAD("PIXEL.ANN"); +ANNMINIMAPA^LOAD([""+ILEVEL+"_MINIMAPA.ANN"]); +``` + +### MONITORCOLLISION {#monitorcollision-1} + +``` +void MONITORCOLLISION() +``` + +Enables collision monitoring between this animation and other objects. + +### MONITORCOLLISIONALPHA {#monitorcollisionalpha-1} + +``` +void MONITORCOLLISIONALPHA() +``` + +Enables alpha-channel awareness in collision detection. + +### MOVE + +``` +void MOVE(INTEGER offsetX, INTEGER offsetY) +``` + +Moves the animation by the given offsets relative to its current position. + +**Parameters** + +- `offsetX` — X offset. +- `offsetY` — Y offset. + +**Examples** + +``` +ANNELEMENT^MOVE(-200, 0); +ANNPLAYER^MOVE(VARDX, VARDY); +ANNITEMDRAGGING^MOVE([IMOUSEX-IMOUSELASTX], [IMOUSEY-IMOUSELASTY]); +``` + +### NEXTFRAME + +``` +void NEXTFRAME() +``` + +Advances the animation to the next frame of the current event. + +### NPLAY + +``` +void NPLAY(INTEGER eventId) +``` + +Starts playing the event with the given index (counted from `0`). + +**Parameters** + +- `eventId` — event index. + +**Examples** + +``` +ANNDARK0^NPLAY(VARITEMP2); +CZAS^NPLAY(0); +``` + +### PAUSE + +``` +void PAUSE() +``` + +Pauses the animation on the current frame. + +### PLAY + +``` +void PLAY([STRING eventName]) +``` + +Starts playing an event. The no-argument variant restarts the previously played event from the beginning. + +**Parameters** + +- `eventName` — (optional) name of the event to play (case-insensitive). + +**Examples** + +``` +G_STLPAGE^PLAY("ELAPSE"); +ANNREX^PLAY(VARITEMP0); +ANNKRET^PLAY(["IDLE_"+ANNKRET^GETEVENTNAME()]); +ANIMOREKSIO^PLAY($1); +``` + +### PREVFRAME + +``` +void PREVFRAME() +``` + +Moves the animation to the previous frame of the current event. + +### REMOVEMONITORCOLLISION + +``` +void REMOVEMONITORCOLLISION() +``` + +Disables collision monitoring previously enabled by [`MONITORCOLLISION`](#monitorcollision-1). + +### REMOVEMONITORCOLLISIONALPHA + +``` +void REMOVEMONITORCOLLISIONALPHA() +``` + +Disables alpha-channel awareness in collision detection, previously enabled by [`MONITORCOLLISIONALPHA`](#monitorcollisionalpha-1). + +### RESUME + +``` +void RESUME() +``` + +Resumes playback paused with [`PAUSE`](#pause). + +### SETANCHOR + +``` +void SETANCHOR(STRING anchor) +void SETANCHOR(INTEGER offsetX, INTEGER offsetY) +``` + +Sets the animation's anchor — the offset that is subtracted from coordinates passed to [`SETPOSITION`](#setposition). + +The `STRING` variant accepts a named position derived from the bounding box: `CENTER`, `LEFTUPPER`, `RIGHTUPPER`, `LEFTLOWER`, `RIGHTLOWER`, `LEFT`, `RIGHT`, `TOP`, `BOTTOM`. + +The two-`INTEGER` variant accepts the anchor coordinates directly. + +**Parameters** + +- `anchor` — bounding-box position name. +- `offsetX, offsetY` — anchor coordinates. + +**Examples** + +``` +ANNSELECT^SETANCHOR("CENTER"); +ANNREX^SETANCHOR("LEFTLOWER"); +ANNREX^SETANCHOR(0, -100); +``` + +### SETASBUTTON + +``` +void SETASBUTTON(BOOL enabled, BOOL changeCursor) +``` + +Configures the animation as a clickable button. Regardless of the argument values, the call makes the animation visible. + +**Parameters** + +- `enabled` — `TRUE` to activate click handling. +- `changeCursor` — `TRUE` for the cursor to change on hover. + +**Examples** + +``` +ANNEXIT^SETASBUTTON(TRUE, TRUE); +ANIMOPOWROT^SETASBUTTON(FALSE, FALSE); +``` + +### SETBACKWARD + +``` +void SETBACKWARD() +``` + +Sets the playback direction to backwards. + +### SETFORWARD + +``` +void SETFORWARD() +``` + +Sets the playback direction to forward (the natural direction). + +### SETFPS + +``` +void SETFPS(INTEGER fps) +``` + +Changes the animation's playback speed. + +**Parameters** + +- `fps` — frames per second. + +**Examples** + +``` +STLMAGIC^SETFPS(5); +ANNMUCHA1^SETFPS(30); +ANNKON^SETFPS([IKONFPS*8]); +``` + +### SETFRAME + +``` +void SETFRAME(INTEGER frameNumber) +void SETFRAME(STRING eventName, INTEGER frameNumber) +void SETFRAME(STRING eventName, STRING frameName) +``` + +Sets the animation to a specific frame. The one-argument variant selects a frame by its global index. The two-argument variant selects an event and then a position in it (by frame number or frame name). + +**Parameters** + +- `eventName` — event name. +- `frameNumber` — frame index within an event (from `0`) or a global frame index. +- `frameName` — specific frame name within the event. + +**Examples** + +``` +ANNREX^SETFRAME(VARSTEMP0, [VARITEMP2-1]); +ANNSCIAGA^SETFRAME("PLAY", VARIREPEATSPELL); +OFERTA^SETFRAME(3); +ANN_H_PIECYK^SETFRAME("ROT", "PIECYK4"); +``` + +### SETFRAMENAME + +``` +void SETFRAMENAME(INTEGER eventId, INTEGER frameNumber, STRING name) +``` + +Changes the name of a specific frame inside the given event. + +**Parameters** + +- `eventId` — event index (from `0`). +- `frameNumber` — frame index within the event (from `0`). +- `name` — the new frame name. + +**Examples** + +``` +ANNKALAREPA^SETFRAMENAME(0, 0, "200"); +ANNKALAREPA^SETFRAMENAME(1, 0, "300"); +``` + +### SETOPACITY + +``` +void SETOPACITY(INTEGER opacity) +``` + +Sets the animation's opacity in the `0–255` scale (`0` — fully transparent, `255` — fully opaque). + +**Parameters** + +- `opacity` — alpha-channel value. + +**Examples** + +``` +ANNPLAYER0^SETOPACITY(255); +ANNPLAYER^SETOPACITY(100); +``` + +### SETPOSITION + +``` +void SETPOSITION(INTEGER posX, INTEGER posY) +``` + +Sets the animation's absolute position. If an anchor has been set via [`SETANCHOR`](#setanchor), its coordinates are subtracted from the arguments. + +**Parameters** + +- `posX` — X coordinate. +- `posY` — Y coordinate. + +**Examples** + +``` +ANNREX^SETPOSITION(400, 300); +ANNEXIT^SETPOSITION(-700, -450); +ANNBKG^SETPOSITION([VARIBKGOFFSETX-VARDTEMP0], [VARIBKGOFFSETY-VARDTEMP1]); +``` + +### SETPRIORITY + +``` +void SETPRIORITY(INTEGER priority) +``` + +Sets the rendering priority. + +**Parameters** + +- `priority` — the new value of the [`PRIORITY`](#priority) field. + +**Examples** + +``` +ANNREX^SETPRIORITY(VARIPRIORITY); +ANNHEAD1^SETPRIORITY(15); +``` + +### SHOW + +``` +void SHOW() +``` + +Shows the animation (sets [`VISIBLE`](#visible) to `TRUE`). + +### STOP + +``` +void STOP([BOOL emitSignal]) +``` + +Stops the animation's playback. + +**Parameters** + +- `emitSignal` — (optional) if `FALSE`, the [`ONFINISHED`](#onfinished) signal is suppressed. By default, the signal is fired. + +**Examples** + +``` +G_STLPAGE^STOP(FALSE); +ANNREX^STOP(FALSE); +ANNBLANK^STOP(); +``` + +### TOP + +``` +void TOP([BOOL flag]) +``` + +Modifies how the animation is rendered relative to the scene's top layer. The exact behaviour depends on the current scene composition. + +**Parameters** + +- `flag` — (optional) a flag changing the rendering mode. + +**Examples** + +``` +ANNWAND0^TOP(FALSE); +ANNHEAD0^TOP(FALSE); +``` + +## Signals + +### ONCLICK + +Fired when the animation is clicked, provided it is configured as a button via [`SETASBUTTON`](#setasbutton). + +### ONCOLLISION + +Fired when a collision is detected. + +### ONCOLLISIONFINISHED + +Fired when an ongoing collision ends. + +### ONDONE + +Fired after all of the animation's events have finished. + +### ONFINISHED + +Fired when an event finishes playing. The signal is [parameterised](../engine/events.md#parameterised-signals) by the event name, so a handler can target a specific event: + +``` +ANIMATION:ONFINISHED^IDLE=BEHAFTERIDLE +``` + +### ONFIRSTFRAME + +Fired when the event's first frame is displayed. + +### ONFOCUSON + +Fired when the cursor moves onto the animation, provided it is configured as a button. + +### ONFOCUSOFF + +Fired when the cursor moves off the animation, provided it is configured as a button. + +### ONFRAMECHANGED + +Fired when the animation's frame changes. + +### ONINIT + +Fired when the object is initialised. + +### ONPAUSED + +Fired when the animation is paused via [`PAUSE`](#pause). + +### ONRELEASE + +Fired when a mouse button is released over an animation configured as a button. + +### ONRESUMED + +Fired when the animation is resumed via [`RESUME`](#resume). + +### ONSIGNAL + +Fired when a signal arrives (see [Events and signals](../engine/events.md#onsignal)). + +### ONSTARTED + +Fired when an event starts playing. Note: this signal arrives after [`ONFRAMECHANGED`](#onframechanged) for the event's first frame. diff --git a/docs/en/reference/APPLICATION.md b/docs/en/reference/APPLICATION.md new file mode 100644 index 0000000..ca0e2aa --- /dev/null +++ b/docs/en/reference/APPLICATION.md @@ -0,0 +1,154 @@ +# APPLICATION + +The application object — the top of the script hierarchy. Declared in [`Application.def`](../engine/scripts.md#entry-point) as the first object; lists the episodes and points to the one to start with. + +## Fields + +### EPISODES + +``` +STRING EPISODES +``` + +The list of episode names ([`EPISODE`](EPISODE.md)) that make up the application, separated by commas. The analysed games typically contain a single entry. + +### PATH + +``` +STRING PATH +``` + +Path relative to the `dane` directory where the application's files live. Used by the engine when locating the `.CNV` file bound to the application (see [Loading subsequent files](../engine/scripts.md#loading-subsequent-files)). + +### STARTWITH + +``` +STRING STARTWITH +``` + +Name of the episode the engine will start the game with. + +### Metadata + +The following fields are stored in the script as metadata and do not directly affect engine behaviour: + +- `AUTHOR` — file author. +- `BLOOMOO_VERSION` — BlooMoo engine version. +- `CREATIONTIME` — file creation date. +- `DESCRIPTION` — application description. +- `LASTMODIFYTIME` — file last-modification date. +- `VERSION` — application version. + +## Methods + +### EXIT + +``` +void EXIT() +``` + +Terminates the application. + +**Examples** + +``` +GAME^EXIT(); +``` + +### GETLANGUAGE + +``` +STRING GETLANGUAGE() +``` + +Returns the application's currently selected language. Defaults to `"POL"`. + +**Returns**: the language code. + +**Examples** + +``` +UFO^GETLANGUAGE(); +``` + +### RUN + +``` +mixed RUN(STRING varName, STRING methodName, [mixed param1, ..., mixed paramN]) +``` + +Invokes the method `methodName` on the variable `varName`, forwarding the remaining arguments. The return value is whatever the called method returns. This is the engine's dynamic-dispatch mechanism — both the target variable and the method can be selected at runtime. + +**Parameters** + +- `varName` — name of the target variable. +- `methodName` — name of the method to invoke. +- `param1, …, paramN` — (optional) arguments forwarded to the call. + +**Returns**: the value returned by the invoked method. + +**Examples** + +``` +UFO^RUN(VARSTRINGTEMP, "SETASBUTTON", FALSE, FALSE); +UFO^RUN(VARSTRINGTEMP, "HIDE"); +UFO^RUN(["ANIMO"+$1], "HIDE"); +UFO^RUN($1, "PLAY", $2); +UFO^RUN(ARRCARS^GET(VARPLAYER), "SETPRIORITY", ARRPRIORITY^GET(VARPLAYER)); +``` + +### RUNENV + +``` +mixed RUNENV(STRING sceneName, STRING behaviourName) +``` + +Calls the procedure `behaviourName`, but only when the currently active scene has the name `sceneName`. Otherwise the method has no effect. Useful for procedures that only make sense in a particular scene context. + +**Parameters** + +- `sceneName` — name of the scene in which the procedure must run. +- `behaviourName` — name of the procedure to call. + +**Returns**: the value returned by the procedure, or `NULL` if the scene guard was not satisfied. + +**Examples** + +``` +GAME^RUNENV(SCENENAME, "__HELPSTART__"); +GAME^RUNENV(SCENENAME, "B_PAUSE_START"); +GAME^RUNENV(SCENENAME, "__CUTINIT__"); +``` + +### SETLANGUAGE + +``` +void SETLANGUAGE(STRING languageCode) +``` + +Sets the application's language code. The engine maps the passed Windows LCID code to an internal language identifier per the table below: + +| LCID | Language | Internal ID | Subfolder | +|---|---|---|---| +| `0415` | Polish | `1` | `POL` | +| `0405` | Czech | `2` | `CZE` | +| `0402` | Bulgarian | `3` | `BUL` | +| `0418` | Romanian | `4` | `ROM` | +| `0419` | Russian | `5` | `RUS` | +| `040E` | Hungarian | `6` | `HUN` | +| `041B` | Slovak | `7` | `SLO` | +| `0422` | Ukrainian | `8` | `UKR` | + +The selected identifier determines the localised-assets subfolder the engine consults when loading game files (see [Loading subsequent files](../engine/scripts.md#loading-subsequent-files)). Identifiers `9`, `10`, and `11` (set through paths other than `SETLANGUAGE`) all map to the `NIEM` subfolder — the German-language build. Any identifier outside the listed range yields an empty subfolder. Setting the language also re-initialises the keyboard layout. + +**Parameters** + +- `languageCode` — the LCID as a four-digit hexadecimal number. + +**Examples** + +``` +UFO^SETLANGUAGE("0415"); +UFO^SETLANGUAGE("040E"); +UFO^SETLANGUAGE("0419"); +``` diff --git a/docs/en/reference/ARRAY.md b/docs/en/reference/ARRAY.md new file mode 100644 index 0000000..112db55 --- /dev/null +++ b/docs/en/reference/ARRAY.md @@ -0,0 +1,475 @@ +# ARRAY + +Zero-indexed array that stores values of any type. Full support for serialisation and arithmetic operations is provided for the four primitive types: [`INTEGER`](INTEGER.md), [`DOUBLE`](DOUBLE.md), [`STRING`](STRING.md), and [`BOOL`](BOOL.md). Mixed-type arrays are allowed, but some methods interpret elements in non-obvious ways (see the notes on [`FIND`](#find), [`CONTAINS`](#contains), and [`GETSUMVALUE`](#getsumvalue)). + +## Fields + +### TOINI + +``` +BOOL TOINI +``` + +Controls whether the array's contents are serialised to an INI file and restored on the next run. + +## Methods + +### ADD + +``` +void ADD(mixed value1, [mixed value2, ..., mixed valueN]) +``` + +Appends the given values to the end of the array. The argument types do not have to match. + +**Parameters** + +- `value1, …, valueN` — values to append. + +**Examples** + +``` +G_ARRSETTINGS^ADD(0, 600); +G_ARRDATAS^ADD("PODWIECZOREK1", "PODWIECZOREK2", "PODWIECZOREK3"); +ARRFLAMESDIR^ADD("R", "R", "R", "L", "L"); +ARR_JOINTS^ADD(FALSE, 6, "B", 10, "A", 4); +``` + +### ADDAT + +``` +void ADDAT(INTEGER index, mixed value) +``` + +Adds the argument to the element at position `index`. Internally, the element and the argument are converted to `DOUBLE`, summed, and stored as [`DOUBLE`](DOUBLE.md) — after this call the element at that position is always of type `DOUBLE`. Calling with `index` out of range leaves the array unchanged. + +**Parameters** + +- `index` — element position (`0`-based). +- `value` — value to add. + +**Examples** + +``` +ARRIDLETIME^ADDAT(0, 1); +ARRENEMYY^ADDAT(VARITMPINDEX, VARITMP1); +ARRSPEED^ADDAT(0, 2.0); +``` + +### CHANGEAT + +``` +void CHANGEAT(INTEGER index, mixed value) +``` + +Replaces the element at position `index` with the given value. The type of the new element is preserved exactly as passed. Calling with `index` out of range leaves the array unchanged. + +**Parameters** + +- `index` — element position (`0`-based). +- `value` — the new value. + +**Examples** + +``` +ARRIDLETIME^CHANGEAT(0, 0); +G_ARRREXSPELLS^CHANGEAT(VARIREPEATSPELL, 1); +ARRAYPLAYERSSTATE^CHANGEAT([VARCLONE-1], "NULL"); +``` + +### CLAMPAT + +``` +void CLAMPAT(INTEGER index, mixed rangeMin, mixed rangeMax) +``` + +Clamps the value at position `index` to the inclusive range `[rangeMin, rangeMax]`. The element's type is preserved — `INTEGER` stays `INTEGER`, `DOUBLE` stays `DOUBLE`. For elements of any other type (and for `index` out of range) the call leaves the array unchanged. + +**Parameters** + +- `index` — element position (`0`-based). +- `rangeMin` — lower bound (inclusive). +- `rangeMax` — upper bound (inclusive). + +**Examples** + +``` +ARRSPEED^CLAMPAT(VARPLAYER, 0.0, 100.0); +ARRSPEED^CLAMPAT(0, 0.0, 17.0); +``` + +### CONTAINS + +``` +BOOL CONTAINS(mixed needle) +``` + +Checks whether the array contains an element matching the given value. The comparison is done on the textual representation — `needle` is cast to [`STRING`](STRING.md) and compared with the `toDisplayString` result of each element. This differs from `FIND`, which compares values according to the [engine's typing rules](../engine/arithmetic.md#typing-rule). + +**Parameters** + +- `needle` — the value to search for. + +**Returns**: [`BOOL`](BOOL.md) — `TRUE` if a matching element was found. + +**Examples** + +``` +ART0^CONTAINS(ICIK); +ARRAYWARSZTATPRZEDMIOTY^CONTAINS(ARRAYTEMP^GET($1)); +``` + +### COPYTO + +``` +void COPYTO(STRING arrayVarName) +``` + +Appends the contents of this array to the end of the array named in the argument. The target array must already exist and be of type `ARRAY`. The target array is **not** cleared before copying. + +**Parameters** + +- `arrayVarName` — the name of the destination array variable. + +**Examples** + +``` +ARAG^COPYTO("ARTMP"); +``` + +### FIND + +``` +INTEGER FIND(mixed needle) +``` + +Searches the array for the first element equal to the given value. The comparison follows the [engine's typing rules](../engine/arithmetic.md#typing-rule) — the type of the array element in each iteration determines what type `needle` is cast to. This yields counterintuitive results in mixed-type arrays: for example, searching for `240` in an array containing `TRUE` will return the index of `TRUE`, because `240` is cast to `BOOL` (a non-zero value, which becomes `TRUE`). + +**Parameters** + +- `needle` — the value to search for. + +**Returns**: the index of the first matching element, or `-1` if no match was found. + +**Examples** + +``` +G_ARRCUTSCENES^FIND(G_SCUTSCENE); +ARRSTARTNAME0^FIND("NULL"); +ARRCLONES^FIND(-1); +``` + +### GET + +``` +mixed GET(INTEGER index) +``` + +Returns the element at position `index`. For `index` out of range, returns `NULL`. + +**Parameters** + +- `index` — element position (`0`-based). + +**Returns**: the element's value or `NULL`. + +**Examples** + +``` +ARRIDLETIME^GET(0); +ARRACTIVESPELLS^GET(_I_); +ARRAYPLAYERSSTATE^GET([VARCLONE-1]); +``` + +### GETSIZE + +``` +INTEGER GETSIZE() +``` + +Returns the number of elements in the array. + +**Returns**: the array's size. + +**Examples** + +``` +G_ARRSETTINGS^GETSIZE(); +ARRENEMYROUTEX^GETSIZE(); +``` + +### GETSUMVALUE + +``` +DOUBLE GETSUMVALUE() +``` + +Returns the sum of all element values. Each element is cast to `DOUBLE` per the [conversion rules](../engine/arithmetic.md#type-conversions); non-numeric elements can contribute unexpected values (`BOOL` → `1.0` or `0.0`, a non-numeric [`STRING`](STRING.md) → `0.0`). + +**Returns**: the sum as a [`DOUBLE`](DOUBLE.md). + +**Examples** + +``` +ARCONTAINER^GETSUMVALUE(); +``` + +### INSERTAT + +``` +void INSERTAT(INTEGER index, mixed value) +``` + +Inserts the value at position `index`, shifting existing elements to the right. Valid values of `index` are in `[0, size]` — inserting at the array's size appends the element at the end. Calling outside this range leaves the array unchanged. + +**Parameters** + +- `index` — insertion position. +- `value` — the value to insert. + +**Examples** + +``` +ARRTURNIEJ^INSERTAT(I3, I1); +ARRTURNIEJ^INSERTAT(4, I1); +``` + +### LOAD + +``` +void LOAD(STRING path) +``` + +Replaces the array's contents with data read from a binary `.ARR` file. The file is little-endian: a 4-byte element count, followed by, for each element, a 4-byte type tag (`1`=`INTEGER`, `2`=`STRING`, `3`=`BOOL`, `4`=`DOUBLE`) and the corresponding value representation. + +**Parameters** + +- `path` — the `.ARR` file path in the game's VFS. + +**Examples** + +``` +G_ARRSETTINGS^LOAD("$COMMON\SETTINGS.ARR"); +ARRPATH^LOAD(["MAPA"+ILEVEL+".ARR"]); +``` + +### LOADINI + +``` +void LOADINI() +``` + +Replaces the array's contents with data deserialised from the game's INI file under the key matching this variable's name. The INI format is a comma-separated list of values: + +``` +ARRAY_NAME=value1,value2,value3,... +``` + +Each element is interpreted in order as [`INTEGER`](INTEGER.md), [`DOUBLE`](DOUBLE.md), [`BOOL`](BOOL.md), or [`STRING`](STRING.md) — the first matching type is used. + +**Examples** + +``` +ARRAYWARSZTATMENUPRZEDMIOTY^LOADINI(); +``` + +### MODAT + +``` +void MODAT(INTEGER index, mixed divisor) +``` + +Stores the remainder of dividing the element at position `index` by the argument. Internally, the element and the argument are converted to `DOUBLE`, modulo is computed, and the result is stored as [`DOUBLE`](DOUBLE.md). Division by zero, or calling with `index` out of range, leaves the array unchanged. + +**Parameters** + +- `index` — element position. +- `divisor` — the divisor. + +**Examples** + +``` +ARRANGLE^MODAT(VARPLAYER, 360); +``` + +### MULAT + +``` +void MULAT(INTEGER index, mixed multiplier) +``` + +Multiplies the element at position `index` by the argument. Internally, the element and the argument are converted to `DOUBLE`, multiplied, and the result is stored as [`DOUBLE`](DOUBLE.md). Calling with `index` out of range leaves the array unchanged. + +**Parameters** + +- `index` — element position. +- `multiplier` — the multiplier. + +**Examples** + +``` +ARRDIRY^MULAT(VARPLAYER, -1.0); +ARRDIRX^MULAT(VARPLAYER, -1); +``` + +### REMOVEALL + +``` +void REMOVEALL() +``` + +Removes all elements from the array. + +**Examples** + +``` +G_ARRSETTINGS^REMOVEALL(); +ARRTEMP^REMOVEALL(); +``` + +### REMOVEAT + +``` +void REMOVEAT(INTEGER index) +``` + +Removes the element at position `index`, shifting the remaining elements to the left. Calling with `index` out of range leaves the array unchanged. + +**Parameters** + +- `index` — position of the element to remove. + +**Examples** + +``` +ARRTEMP^REMOVEAT(VARITEMP2); +ARRENEMYROUTEX^REMOVEAT(0); +``` + +### REVERSEFIND + +``` +INTEGER REVERSEFIND(mixed needle) +``` + +Works like [`FIND`](#find), but scans the array from the end. The same type-dependent comparison rules apply. + +**Parameters** + +- `needle` — the value to search for. + +**Returns**: the index of the last matching element, or `-1` if no match was found. + +**Examples** + +``` +ARRAYKURNIKFREESLOTS^REVERSEFIND(0); +``` + +### SAVE + +``` +void SAVE(STRING path) +``` + +Writes the array's contents to a binary `.ARR` file in the format described in [`LOAD`](#load). + +**Parameters** + +- `path` — the destination `.ARR` file path in the game's VFS. + +**Examples** + +``` +G_ARRSETTINGS^SAVE("$COMMON\SETTINGS.ARR"); +ARRPATH^SAVE(["MAPA"+ILEVEL+".ARR"]); +``` + +### SAVEINI + +``` +void SAVEINI() +``` + +Serialises the array's contents to the game's INI file under the key matching this variable's name, as a comma-separated list of values (the format described in [`LOADINI`](#loadini)). + +**Examples** + +``` +ARRAYPLATFORMOWKAPRZEDMIOTY^SAVEINI(); +``` + +### SUB + +``` +void SUB(mixed value) +``` + +Subtracts the argument from every element of the array. Each element is converted to `DOUBLE` before the subtraction; all elements after the call are of type `DOUBLE`. + +**Parameters** + +- `value` — the value to subtract. + +**Examples** + +``` +ARRAYBKGA^SUB([0-VARINT2]); +``` + +### SUBAT + +``` +void SUBAT(INTEGER index, mixed value) +``` + +Subtracts the argument from the element at position `index`. Internally, the element and the argument are converted to `DOUBLE`, subtracted, and the result is stored as [`DOUBLE`](DOUBLE.md). Calling with `index` out of range leaves the array unchanged. + +**Parameters** + +- `index` — element position. +- `value` — the value to subtract. + +**Examples** + +``` +ARRBUTTONPRESSED^SUBAT(IBUTTONNR, 1); +ARRSPEED^SUBAT(VARPLAYER, 0.15); +``` + +### SUM + +``` +void SUM(mixed value) +``` + +Adds the argument to every element of the array. Each element is converted to `DOUBLE` before the addition; all elements after the call are of type `DOUBLE`. + +**Parameters** + +- `value` — the value to add. + +**Examples** + +``` +ARRCHICKENX^SUM(-60); +ARRCHICKENY^SUM(-110); +``` + +## Signals + +### ONCHANGE + +Fired after a modification has been made to the array. + +### ONINIT + +Fired when the variable is initialised. + +### ONDONE + +Fired when leaving the scene that owns the variable. + +### ONSIGNAL + +Fired when a signal arrives (sent via the `SEND` method — see [Events and signals](../engine/events.md#onsignal)). diff --git a/docs/en/reference/BEHAVIOUR.md b/docs/en/reference/BEHAVIOUR.md new file mode 100644 index 0000000..875c6f6 --- /dev/null +++ b/docs/en/reference/BEHAVIOUR.md @@ -0,0 +1,122 @@ +# BEHAVIOUR + +A procedure. Executes the code stored in the `CODE` field, optionally guarded by the condition named in the `CONDITION` field. Call-site arguments are available inside the code as `$1`, `$2`, …; see [Procedure arguments](../engine/scripts.md#procedure-arguments) for details. + +## Fields + +### CODE + +``` +STRING CODE +``` + +The body of the procedure — a code block in curly braces following the syntax described in [Scripts](../engine/scripts.md#code-blocks). + +Example: + +``` +BEHGOTOTITLE:CODE={BEHSETSCENE^RUN();G_SARCADESCENE^SET("EGIPTLEJ");BEHCSSTART^RUN();} +``` + +### CONDITION + +``` +STRING CONDITION +``` + +The name of a [`CONDITION`](CONDITION.md) or [`COMPLEXCONDITION`](COMPLEXCONDITION.md) variable, used by [`RUNC`](#runc) as a gate and by [`RUNLOOPED`](#runlooped) as a per-iteration loop guard. If the field is not set, the methods run unconditionally. + +## Methods + +### RUN + +``` +mixed RUN([mixed param1, ..., mixed paramN]) +``` + +Executes the procedure's code. The arguments are exposed inside the body as `$1`, `$2`, …. The return value is whatever [`@RETURN`](../engine/scripts.md#jump-operators) sets in the body, or `NULL` if `@RETURN` is not invoked. + +**Parameters** + +- `param1, …, paramN` — procedure arguments (optional, of any type). + +**Returns**: the value returned by the procedure or `NULL`. + +**Examples** + +``` +__LOAD_SETTINGS__^RUN(); +BEHSELECTOBJ^RUN(VARITER); +BEHADDITEM^RUN(SOBJECT|SPARAM0, VARITER); +BEHENTERRABBIT^RUN("ANNHILL0", -1); +``` + +### RUNC + +``` +mixed RUNC([mixed param1, ..., mixed paramN]) +``` + +Calls the procedure only when the condition named in `CONDITION` is satisfied. If `CONDITION` is not set, behaves like [`RUN`](#run). Arguments and return value are the same as in `RUN`. + +**Parameters** + +- `param1, …, paramN` — procedure arguments. + +**Returns**: the value returned by the procedure, or `NULL` (including the case when the condition was not satisfied). + +**Examples** + +``` +BEHREMOVEMENUITEM^RUNC("CHOMIK"); +BEHREMOVEMENUITEM^RUNC(VARSTRINGTEMP); +BEH_HERO_FINISHED_0^RUNC(); +``` + +### RUNLOOPED + +``` +void RUNLOOPED(INTEGER start, INTEGER length) +void RUNLOOPED(INTEGER start, INTEGER length, INTEGER step, [mixed extraArg1, ..., mixed extraArgN]) +``` + +Runs the procedure in a `for` loop with the counter passed as `$1`. Extra arguments (from the fourth argument onwards) are forwarded to the procedure as `$2`, `$3`, … . If the `CONDITION` field is set, its condition is checked before every iteration — when it is not satisfied, the loop ends. + +The loop is equivalent to the following pseudocode: + +``` +for (int i = start; i < start + length; i += step) { + // call procedure with $1 = i, $2..$N = extraArgs +} +``` + +If `step` is omitted or passed as `0`, the value `1` is used. The [`@BREAK`](../engine/scripts.md#jump-operators) operator inside the procedure terminates the `RUNLOOPED` loop (but not the calling procedure). + +**Parameters** + +- `start` — initial counter value. +- `length` — number of iterations (`startVal < endVal` equals `startVal + length`). +- `step` — (optional) counter step. Defaults to `1`. +- `extraArg1, …, extraArgN` — (optional) extra arguments forwarded to the procedure. + +**Examples** + +``` +BEHSHOWMENU^RUNLOOPED(0, ARRAYWARSZTATMENUPRZEDMIOTY^GETSIZE()); +BEHSHOWPIONEK^RUNLOOPED(1, 9); +BEHINITZASLONAX^RUNLOOPED(0, 7, 1, "[80*$1]"); +``` + +## Signals + +### ONINIT + +Fired when the procedure is initialised. + +### ONDONE + +Fired after a procedure invocation completes. + +### ONSIGNAL + +Fired when a signal arrives (see [Events and signals](../engine/events.md#onsignal)). diff --git a/docs/en/reference/BOOL.md b/docs/en/reference/BOOL.md new file mode 100644 index 0000000..224bfa2 --- /dev/null +++ b/docs/en/reference/BOOL.md @@ -0,0 +1,92 @@ +# BOOL + +Boolean type. Stores one of two values: `TRUE` or `FALSE`. + +## Fields + +### TOINI + +``` +BOOL TOINI +``` + +Controls whether the field's value is persisted to an INI file and restored on the next run. + +### VALUE + +``` +BOOL VALUE +``` + +The current value of the variable. + +## Methods + +### GET + +``` +BOOL GET() +``` + +Returns the current value of the variable. + +**Returns** + +- `BOOL` — the current value of the `VALUE` field. + +### RESETINI + +``` +void RESETINI() +``` + +Resets the variable's value to the reset value defined in the object's script attributes. The engine looks up the value in the following order: `DEFAULT` → `INIT_VALUE` → `VALUE`; the first one found is used. + +### SET + +``` +void SET(BOOL value) +``` + +Sets the variable's value. + +**Parameters** + +- `value` — the new `BOOL` value. + +**Examples** + +``` +VARBLOCKSCENE^SET(FALSE); +__KEYB__^SET(KEYBOARD^ISENABLED()); +VARBTEMP1^SET($2); +``` + +### SWITCH + +``` +void SWITCH(BOOL value1, BOOL value2) +``` + +Toggles the variable's value between the two values passed as arguments. The method accepts two parameters in order to keep its signature consistent with `SWITCH` on the [`INTEGER`](INTEGER.md) and [`DOUBLE`](DOUBLE.md) types, even though for `BOOL` the full information could be expressed with a single argument. + +**Parameters** + +- `value1` — the first value. +- `value2` — the second value. + +**Examples** + +``` +B_0^SWITCH(TRUE, FALSE); +``` + +## Signals + +### ONCHANGED + +Fired when the variable's value is changed to one different from the previous one. + +### ONBRUTALCHANGED + +Fired on every call that sets the value, regardless of whether the new value differs from the previous one. diff --git a/docs/en/reference/CLASS.md b/docs/en/reference/CLASS.md new file mode 100644 index 0000000..097fa2b --- /dev/null +++ b/docs/en/reference/CLASS.md @@ -0,0 +1,70 @@ +# CLASS + +A class definition. The definition file has the `.class` extension and uses syntax similar to `.CNV` files. Instances (`INSTANCE`) are created from a class definition with [`NEW`](#new) and removed with [`DELETE`](#delete). + +## Fields + +### DEF + +``` +STRING DEF +``` + +Path to the class definition file. If the path does not start with `$`, it is prefixed with `$COMMON/classes/`. + +### BASE + +``` +STRING BASE +``` + +The base class for inheritance. In the current emulator implementation the field is read but not used. + +## Methods + +### NEW + +``` +mixed NEW(STRING varName, [mixed param1, ..., mixed paramN]) +``` + +Creates a new instance of the class with the name `varName`. The new variable is registered in the context where the class is declared (not in the caller's context) — the instance therefore survives scene changes when the class is declared at the application level. + +After the instance is created, if the class definition file contains a procedure called `CONSTRUCTOR`, it is invoked with the arguments passed to `NEW` (with `varName` as `$1`). + +**Parameters** + +- `varName` — name of the new instance variable. +- `param1, …, paramN` — (optional) arguments forwarded to the `CONSTRUCTOR` procedure. + +**Returns**: the value returned by `CONSTRUCTOR` or `NULL`. + +**Examples** + +``` +MM^NEW("G_MENU"); +CLSLOGOBJ^NEW("LOG", FALSE); +CLSEIFELENEMYOBJ^NEW("ENEMY0", "1_ENEMY0.ANN", 2, 5, 16, 4, 0, 2, 18); +CLSBDENEMYOBJ^NEW(["BDENEMY"+I2], _I_, I1, I2, IBDKRAINA); +``` + +### DELETE + +``` +mixed DELETE(STRING varName, [mixed param1, ..., mixed paramN]) +``` + +Deletes the instance named `varName`. If the class definition contains a procedure called `DESTRUCTOR`, it is invoked with the arguments passed to `DELETE` (with `varName` as `$1`) before the variable is removed from its context. + +**Parameters** + +- `varName` — name of the instance to delete. +- `param1, …, paramN` — (optional) arguments forwarded to the `DESTRUCTOR` procedure. + +**Returns**: the value returned by `DESTRUCTOR` or `NULL`. + +## Signals + +### ONINIT + +Fired when the class variable is initialised. diff --git a/docs/en/reference/COMPLEXCONDITION.md b/docs/en/reference/COMPLEXCONDITION.md new file mode 100644 index 0000000..8bb2898 --- /dev/null +++ b/docs/en/reference/COMPLEXCONDITION.md @@ -0,0 +1,104 @@ +# COMPLEXCONDITION + +An object that combines two conditions ([`CONDITION`](CONDITION.md) or nested `COMPLEXCONDITION`) with a logical `AND` or `OR` operator. Configured by three fields in the script and invoked similarly to a `CONDITION`. + +## Fields + +### CONDITION1 + +``` +STRING CONDITION1 +``` + +The name of the variable holding the left-hand sub-condition. The referenced variable should be of type [`CONDITION`](CONDITION.md) or `COMPLEXCONDITION` — in either case it is evaluated recursively. + +### CONDITION2 + +``` +STRING CONDITION2 +``` + +The name of the variable holding the right-hand sub-condition; the rules are identical to those of `CONDITION1`. + +### OPERATOR + +``` +STRING OPERATOR +``` + +The logical operator joining the two sub-conditions. Defaults to `AND`. Accepted values: + +| Value | Meaning | +|---|---| +| `AND` | conjunction — the whole is true when both sub-conditions are true | +| `OR` | disjunction — the whole is true when at least one sub-condition is true | + +## Methods + +### BREAK + +``` +void BREAK([BOOL emitSignals]) +``` + +Evaluates the compound condition. If the result is `TRUE`, aborts the entire current call tree (the same effect as [`@BREAK`](../engine/scripts.md#jump-operators)). + +**Parameters** + +- `emitSignals` — (optional) if `TRUE`, [`ONRUNTIMESUCCESS`](#onruntimesuccess)/[`ONRUNTIMEFAILED`](#onruntimefailed) signals are fired by both this object and each sub-condition. Defaults to `FALSE`. + +**Examples** + +``` +COC_END^BREAK(TRUE); +CCONDISATPOS^BREAK(TRUE); +``` + +### CHECK + +``` +BOOL CHECK([BOOL emitSignals]) +``` + +Evaluates the compound condition and returns the result. + +**Parameters** + +- `emitSignals` — (optional) same as for [`BREAK`](#break). + +**Returns**: [`BOOL`](BOOL.md) — the combined result. + +**Examples** + +``` +CCONDTESTEND^CHECK(TRUE); +``` + +### ONE_BREAK + +``` +void ONE_BREAK([BOOL emitSignals]) +``` + +Evaluates the compound condition. If the result is `TRUE`, aborts only the current procedure (the same effect as [`@ONEBREAK`](../engine/scripts.md#jump-operators)). + +**Parameters** + +- `emitSignals` — (optional) same as for [`BREAK`](#break). + +**Examples** + +``` +COC_END^ONE_BREAK(TRUE); +CCONDISATPOS^ONE_BREAK(TRUE); +``` + +## Signals + +### ONRUNTIMESUCCESS + +Fired when the compound condition evaluated to `TRUE` and `emitSignals` was `TRUE`. + +### ONRUNTIMEFAILED + +Fired when the compound condition evaluated to `FALSE` and `emitSignals` was `TRUE`. diff --git a/docs/en/reference/CONDITION.md b/docs/en/reference/CONDITION.md new file mode 100644 index 0000000..f26aa2f --- /dev/null +++ b/docs/en/reference/CONDITION.md @@ -0,0 +1,115 @@ +# CONDITION + +An object that describes a comparison of two operands. Configured by three fields in the script and invoked through [`CHECK`](#check) or one of the control-flow methods ([`BREAK`](#break), [`ONE_BREAK`](#one_break)). + +## Fields + +### OPERAND1 + +``` +STRING OPERAND1 +``` + +The left-hand operand of the comparison. The field holds the operand's textual form, which is parsed on every evaluation. Accepted forms: + +- a quoted string literal (`"..."` or `'...'`), +- a boolean literal (`TRUE`, `FALSE`), +- a numeric literal (`5`, `-3.14`), +- a variable name (its value is fetched; for variables of type [`EXPRESSION`](index.md), `CONDITION`, or [`COMPLEXCONDITION`](COMPLEXCONDITION.md), the variable is recursively evaluated), +- a script fragment — text starting with `[`, `*`, or containing the `^` or `|` operators. + +### OPERAND2 + +``` +STRING OPERAND2 +``` + +The right-hand operand of the comparison. The interpretation rules are identical to those of `OPERAND1`. + +### OPERATOR + +``` +STRING OPERATOR +``` + +The comparison operator. Defaults to `EQUAL`. Accepted values: + +| Value | Meaning | +|---|---| +| `EQUAL` | equal to | +| `NOTEQUAL` | not equal to | +| `LESS` | less than | +| `GREATER` | greater than | +| `LESSEQUAL` | less than or equal | +| `GREATEREQUAL` | greater than or equal | + +## Methods + +### BREAK + +``` +void BREAK([BOOL emitSignals]) +``` + +Evaluates the condition. If the result is `TRUE`, aborts the entire current call tree (the same effect as [`@BREAK`](../engine/scripts.md#jump-operators)). If the result is `FALSE`, the method has no effect. + +**Parameters** + +- `emitSignals` — (optional) if `TRUE`, also fires [`ONRUNTIMESUCCESS`](#onruntimesuccess) or [`ONRUNTIMEFAILED`](#onruntimefailed) depending on the result. Defaults to `FALSE`. + +**Examples** + +``` +COND1^BREAK(TRUE); +CONDKONTROLA^BREAK(TRUE); +``` + +### CHECK + +``` +BOOL CHECK([BOOL emitSignals]) +``` + +Evaluates the condition and returns the comparison result. + +**Parameters** + +- `emitSignals` — (optional) if `TRUE`, also fires [`ONRUNTIMESUCCESS`](#onruntimesuccess) or [`ONRUNTIMEFAILED`](#onruntimefailed) depending on the result. Defaults to `FALSE`. + +**Returns**: [`BOOL`](BOOL.md) — the comparison result. + +**Examples** + +``` +CONPR1^CHECK(TRUE); +CONPR2^CHECK(TRUE); +``` + +### ONE_BREAK + +``` +void ONE_BREAK([BOOL emitSignals]) +``` + +Evaluates the condition. If the result is `TRUE`, aborts only the current procedure (the same effect as [`@ONEBREAK`](../engine/scripts.md#jump-operators)). If the result is `FALSE`, the method has no effect. + +**Parameters** + +- `emitSignals` — (optional) same as for [`BREAK`](#break). + +**Examples** + +``` +COND1^ONE_BREAK(TRUE); +CONDREMOVEMENUITEM^ONE_BREAK(TRUE); +``` + +## Signals + +### ONRUNTIMESUCCESS + +Fired when the condition evaluated to `TRUE` and `emitSignals` was `TRUE`. + +### ONRUNTIMEFAILED + +Fired when the condition evaluated to `FALSE` and `emitSignals` was `TRUE`. diff --git a/docs/en/reference/DOUBLE.md b/docs/en/reference/DOUBLE.md new file mode 100644 index 0000000..b399db2 --- /dev/null +++ b/docs/en/reference/DOUBLE.md @@ -0,0 +1,458 @@ +# DOUBLE + +Double-precision floating-point number. + +## Fields + +### TOINI + +``` +BOOL TOINI +``` + +Controls whether the field's value is persisted to an INI file and restored on the next run. + +### VALUE + +``` +DOUBLE VALUE +``` + +The current value of the variable. Accepted notations include standard decimal (e.g. `1.234`) and scientific with the letter `e` or `d` (e.g. `1.23e4`, `1.23d4`). + +## Methods + +### ABS + +``` +DOUBLE ABS(DOUBLE value) +``` + +Stores the absolute value of the argument in the variable and returns it. + +**Parameters** + +- `value` — the number whose absolute value will be stored. + +**Returns**: the new value of the variable. + +**Examples** + +``` +VARDTMP2^ABS(VARDTMP2); +DKIERUNEKY^ABS(DKIERUNEKY); +``` + +### ADD + +``` +DOUBLE ADD(DOUBLE addend) +``` + +Adds the argument to the variable's current value, stores the result, and returns it. + +**Parameters** + +- `addend` — the value to add. + +**Returns**: the new value of the variable. + +**Examples** + +``` +VARDMENUOPACITY^ADD([42.5*VARIMENUVISIBLE]); +VARDTIME^ADD(1.0); +STREX|DPOSX^ADD(STREX|FORCEX); +``` + +### ARCTAN + +``` +DOUBLE ARCTAN(DOUBLE value) +``` + +Stores the arctangent of the argument, expressed in degrees, in the variable and returns it. The argument is treated as a number (a tangent value), not as an angle. + +**Parameters** + +- `value` — the number whose arctangent is computed. + +**Returns**: the new value of the variable (in degrees). + +**Examples** + +``` +VARDTMP1^ARCTAN(VARDTMP1); +``` + +### ARCTANEX + +``` +DOUBLE ARCTANEX(DOUBLE y, DOUBLE x) +``` + +Stores the value of `atan2(y, x)` expressed in degrees in the variable and returns it. This is the angle of the vector `(x, y)` measured from the positive `OX` axis. + +**Parameters** + +- `y` — the first vector component. +- `x` — the second vector component. + +**Returns**: the new value of the variable (in degrees). + +**Examples** + +``` +VARDTEMP1^ARCTANEX(VARIDIRY, VARIDIRX); +VARDTEMP2^ARCTANEX(VREFLECT^GET(1), VREFLECT^GET(0)); +``` + +### CLAMP + +``` +DOUBLE CLAMP(DOUBLE rangeMin, DOUBLE rangeMax) +``` + +Clamps the variable's current value to the inclusive range `[rangeMin, rangeMax]`. Values outside the range are pinned to its bounds. + +**Parameters** + +- `rangeMin` — lower bound of the range (inclusive). +- `rangeMax` — upper bound of the range (inclusive). + +**Returns**: the new value of the variable. + +**Examples** + +``` +D3^CLAMP(0.5, 2.5); +VARDTMP1^CLAMP(-15.0, 15.0); +DKONSPEED^CLAMP(0.0, DKONSPEEDMAX); +``` + +### CLEAR + +``` +DOUBLE CLEAR() +``` + +Sets the variable's value to `0.0` and returns it. + +**Returns**: `0.0`. + +### COSINUS + +``` +DOUBLE COSINUS(DOUBLE angle) +``` + +Stores the cosine of the given angle in the variable and returns it. The angle is given in degrees. + +**Parameters** + +- `angle` — the angle in degrees. + +**Returns**: the new value of the variable. + +**Examples** + +``` +VARDTEMP0^COSINUS(VARDANGLE); +VARDTEMP1^COSINUS(ARRANGLE^GET(VARPLAYER)); +``` + +### DEC + +``` +DOUBLE DEC() +``` + +Decrements the variable's value by `1.0`. + +**Returns**: the new value of the variable. + +### DIV + +``` +DOUBLE DIV(DOUBLE divisor) +``` + +Divides the variable's current value by the argument, stores the result, and returns it. Division by zero leaves the variable unchanged. + +**Parameters** + +- `divisor` — the divisor. + +**Returns**: the new value of the variable (or the unchanged value if `divisor` was `0.0`). + +**Examples** + +``` +VARDTEMP0^DIV(ARRSPEEDFACTOR^GET(0)); +DKONSPEED^DIV(6.0); +VARDTMP2^DIV(15); +``` + +### GET + +``` +DOUBLE GET() +``` + +Returns the current value of the variable. + +**Returns**: the current value of the `VALUE` field. + +### INC + +``` +DOUBLE INC() +``` + +Increments the variable's value by `1.0`. + +**Returns**: the new value of the variable. + +### LENGTH + +``` +DOUBLE LENGTH(DOUBLE x, DOUBLE y) +``` + +Computes the length of the vector `(x, y)` as `sqrt(x² + y²)`, stores it, and returns it. + +**Parameters** + +- `x` — the first vector component. +- `y` — the second vector component. + +**Returns**: the vector length. + +**Examples** + +``` +VARDTEMP0^LENGTH(VARIDIRX, VARIDIRY); +``` + +### LOG + +``` +DOUBLE LOG(DOUBLE value) +``` + +Stores the natural logarithm of the argument in the variable and returns it. + +**Parameters** + +- `value` — the number whose logarithm is computed. + +**Returns**: the new value of the variable. + +### MAXA + +``` +DOUBLE MAXA(DOUBLE value1, [DOUBLE value2, ..., DOUBLE valueN]) +``` + +Picks the maximum of the given arguments, stores it, and returns it. Requires at least one argument. + +**Parameters** + +- `value1, …, valueN` — the values to choose from. + +**Returns**: the largest of the given values. + +**Examples** + +``` +VARDPOWER^MAXA(0.0, VARDPOWER); +``` + +### MINA + +``` +DOUBLE MINA(DOUBLE value1, [DOUBLE value2, ..., DOUBLE valueN]) +``` + +Picks the minimum of the given arguments, stores it, and returns it. Requires at least one argument. + +**Parameters** + +- `value1, …, valueN` — the values to choose from. + +**Returns**: the smallest of the given values. + +**Examples** + +``` +VARDPOWER^MINA(VARDPOWER, 9.0); +``` + +### MOD + +``` +DOUBLE MOD(DOUBLE divisor) +``` + +Computes the remainder of dividing the variable's current value by the argument, truncates the fractional part to an integer, stores it, and returns it. Division by zero leaves the variable unchanged. + +**Parameters** + +- `divisor` — the divisor. + +**Returns**: the new value of the variable (or the unchanged value if `divisor` was `0.0`). + +### MUL + +``` +DOUBLE MUL(DOUBLE multiplier) +``` + +Multiplies the variable's current value by the argument, stores the result, and returns it. + +**Parameters** + +- `multiplier` — the multiplier. + +**Returns**: the new value of the variable. + +**Examples** + +``` +STPLAYER|FORCEX^MUL(0.75); +VARCATFORCEX^MUL(1000000); +STREX|FORCEX^MUL(STREX|DEFIANCE); +``` + +### RESETINI + +``` +DOUBLE RESETINI() +``` + +Resets the variable's value to the reset value defined in the object's script attributes. The engine looks up the value in the following order: `DEFAULT` → `INIT_VALUE` → `VALUE`; the first one found is used. If none of them is set, the value is reset to `0.0`. + +**Returns**: the new value of the variable. + +### SET + +``` +DOUBLE SET(DOUBLE value) +``` + +Sets the variable's value. + +**Parameters** + +- `value` — the new value. + +**Returns**: the new value of the variable. + +**Examples** + +``` +VARDMAXVEL^SET(300.0); +VARDMAXVELKRET^SET([0.6*VARDMAXVEL]); +VARD_KRETSPEED^SET($1); +``` + +### SGN + +``` +INTEGER SGN() +``` + +Returns the sign of the variable's current value: `-1` for negative values, `1` for positive, `0` for zero. This method does not modify the variable, and is the only method on this type that returns an [`INTEGER`](INTEGER.md) rather than a `DOUBLE`. + +**Returns**: the sign of the variable's value (`-1`, `0`, or `1`). + +### SINUS + +``` +DOUBLE SINUS(DOUBLE angle) +``` + +Stores the sine of the given angle in the variable and returns it. The angle is given in degrees. + +**Parameters** + +- `angle` — the angle in degrees. + +**Returns**: the new value of the variable. + +**Examples** + +``` +VARDTEMP1^SINUS(VARDANGLE); +VARDTEMP2^SINUS(ARRANGLE^GET(VARPLAYER)); +``` + +### SQRT + +``` +DOUBLE SQRT() +DOUBLE SQRT(DOUBLE value) +``` + +Stores the square root in the variable and returns it. + +- Without an argument, the square root of the variable's current value is taken. +- With an argument, the square root of the argument is taken. + +**Parameters** + +- `value` — (optional) the number whose square root is computed. + +**Returns**: the new value of the variable. + +**Examples** + +``` +VARDODLEGLOSC^SQRT(VARDODLEGLOSC); +``` + +### SUB + +``` +DOUBLE SUB(DOUBLE subtrahend) +``` + +Subtracts the argument from the variable's current value, stores the result, and returns it. + +**Parameters** + +- `subtrahend` — the value to subtract. + +**Returns**: the new value of the variable. + +**Examples** + +``` +VARDANGLE^SUB(VARDTEMP2); +DKONSPEED^SUB([DKONACCELERATION*D3]); +``` + +### SWITCH + +``` +DOUBLE SWITCH(DOUBLE valueA, DOUBLE valueB) +``` + +If the variable's current value equals `valueA`, assigns `valueB` to it; otherwise assigns `valueA`. Useful for alternating between two values. + +**Parameters** + +- `valueA` — the first value. +- `valueB` — the second value. + +**Returns**: the new value of the variable. + +## Signals + +### ONCHANGED + +Fired when the variable's value is changed to one different from the previous one. + +### ONBRUTALCHANGED + +Fired on every call that sets the value, regardless of whether the new value differs from the previous one. diff --git a/docs/en/reference/EPISODE.md b/docs/en/reference/EPISODE.md new file mode 100644 index 0000000..62422fa --- /dev/null +++ b/docs/en/reference/EPISODE.md @@ -0,0 +1,102 @@ +# EPISODE + +A logical segment of the game — a container of scenes ([`SCENE`](SCENE.md)) inside an [`APPLICATION`](APPLICATION.md). In practice, AidemMedia games used a single episode for the whole game. + +## Fields + +### SCENES + +``` +STRING SCENES +``` + +The list of scene names that make up the episode, separated by commas. + +### PATH + +``` +STRING PATH +``` + +Path relative to the `dane` directory containing the episode's files. Used by the engine when locating the scenes' `.CNV` files. + +### STARTWITH + +``` +STRING STARTWITH +``` + +The name of the scene that starts the episode. + +### Metadata + +The following fields are stored as metadata and do not directly affect engine behaviour: + +- `AUTHOR` — file author. +- `CREATIONTIME` — file creation date. +- `DESCRIPTION` — episode description. +- `LASTMODIFYTIME` — file last-modification date. +- `VERSION` — episode version. + +## Methods + +### BACK + +``` +void BACK() +``` + +Returns to the scene that was active immediately before the current one. + +**Examples** + +``` +PRZYGODA^BACK(); +``` + +### GETCURRENTSCENE + +``` +STRING GETCURRENTSCENE() +``` + +Returns the name of the currently active scene. + +**Returns**: the scene name. + +**Examples** + +``` +PRZYGODA^GETCURRENTSCENE(); +``` + +### GETLATESTSCENE + +``` +STRING GETLATESTSCENE() +``` + +Returns the name of the scene that was active immediately before the current one — the scene that [`BACK`](#back) would return to. + +**Returns**: the previous scene's name. + +### GOTO + +``` +void GOTO(STRING sceneName) +``` + +Switches the game to the given scene. + +**Parameters** + +- `sceneName` — target scene name. + +**Examples** + +``` +PRZYGODA^GOTO("CREDITS"); +PRZYGODA^GOTO("MAGIC"); +PRZYGODA^GOTO(G_SARCADEOBJECTS); +PRZYGODA^GOTO(UFO^RUN(["VARLEVEL"+VARNR], "GET")); +``` diff --git a/docs/en/reference/FONT.md b/docs/en/reference/FONT.md new file mode 100644 index 0000000..40dac8b --- /dev/null +++ b/docs/en/reference/FONT.md @@ -0,0 +1,25 @@ +# FONT + +A bitmap font definition. The object exposes no script-callable methods or signals — it is used by the [`TEXT`](TEXT.md) type as a source of character textures. + +## Fields + +### DEF + +``` +STRING DEF__