@origingame/engine 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/web/origin-engine.d.ts +8 -5
- package/dist/web/origin-engine.js +39 -19
- package/dist/web/origin-engine_bg.wasm +0 -0
- package/dist/web/origin-engine_bg.wasm.d.ts +6 -5
- package/dist/web-publish/origin-engine-lanes.js +49 -29
- package/dist/web-publish/origin-engine-lanes_bg.wasm +0 -0
- package/dist/web-publish/origin-engine.d.ts +8 -5
- package/dist/web-publish/origin-engine.js +39 -19
- package/dist/web-publish/origin-engine_bg.wasm +0 -0
- package/dist/web-publish/origin-engine_bg.wasm.d.ts +6 -5
- package/dist/web-publish-2d/origin-engine-lanes.js +49 -29
- package/dist/web-publish-2d/origin-engine-lanes_bg.wasm +0 -0
- package/dist/web-publish-2d/origin-engine.d.ts +8 -5
- package/dist/web-publish-2d/origin-engine.js +39 -19
- package/dist/web-publish-2d/origin-engine_bg.wasm +0 -0
- package/dist/web-publish-2d/origin-engine_bg.wasm.d.ts +6 -5
- package/knowledge/looks/catalogue.json +123 -2
- package/knowledge/package.json +1 -1
- package/knowledge/scaffold/origin-engine.json +2 -2
- package/knowledge/scaffold/template/package.json +1 -1
- package/knowledge/scaffold/template/project.ogt +1 -1
- package/knowledge/scripts/validate.ts +69 -6
- package/knowledge/skills/og-audio/SKILL.md +31 -5
- package/knowledge/skills/og-build/SKILL.md +44 -4
- package/knowledge/skills/og-core/SKILL.md +4 -3
- package/knowledge/skills/og-feel/SKILL.md +9 -1
- package/knowledge/skills/og-game/SKILL.md +199 -16
- package/knowledge/skills/og-platform-sdk/SKILL.md +6 -0
- package/knowledge/skills/og-taste/SKILL.md +7 -0
- package/knowledge/skills/og-ui/SKILL.md +24 -0
- package/knowledge/wiki/ai.md +20 -20
- package/knowledge/wiki/anim.md +526 -60
- package/knowledge/wiki/atmosphere.md +13 -13
- package/knowledge/wiki/audio.md +160 -20
- package/knowledge/wiki/camera.md +13 -13
- package/knowledge/wiki/commands.md +11 -11
- package/knowledge/wiki/debug.md +13 -13
- package/knowledge/wiki/game.md +8 -8
- package/knowledge/wiki/i18n.md +7 -7
- package/knowledge/wiki/index.md +25 -1
- package/knowledge/wiki/input.md +47 -47
- package/knowledge/wiki/load.md +76 -50
- package/knowledge/wiki/math.md +102 -102
- package/knowledge/wiki/nav.md +34 -34
- package/knowledge/wiki/net.md +10 -10
- package/knowledge/wiki/path.md +14 -14
- package/knowledge/wiki/physics.md +111 -100
- package/knowledge/wiki/platform.md +44 -44
- package/knowledge/wiki/probe.md +86 -86
- package/knowledge/wiki/reflect.md +17 -17
- package/knowledge/wiki/render.md +245 -176
- package/knowledge/wiki/rng.md +14 -14
- package/knowledge/wiki/shapes.md +26 -26
- package/knowledge/wiki/stream.md +15 -15
- package/knowledge/wiki/system.md +8 -8
- package/knowledge/wiki/systems.md +2 -2
- package/knowledge/wiki/terrain.md +19 -19
- package/knowledge/wiki/tilemap.md +13 -13
- package/knowledge/wiki/time.md +4 -4
- package/knowledge/wiki/timeline.md +14 -14
- package/knowledge/wiki/transform.md +8 -8
- package/knowledge/wiki/tween.md +17 -17
- package/knowledge/wiki/ui.md +243 -243
- package/knowledge/wiki/video.md +5 -5
- package/knowledge/wiki/world.md +36 -36
- package/package.json +4 -4
- package/schema/api.schema.json +639 -11
- package/shell/page.ts +4 -0
- package/src/generated/abi.ts +3 -0
- package/src/index.ts +11 -0
- package/src/node/device.ts +5 -2
- package/src/node/polish.ts +34 -15
- package/src/node/run.ts +23 -6
- package/src/runtime.ts +1 -0
- package/src/web/gl-state.ts +907 -0
- package/src/web/worker.ts +6 -0
- package/types/bindings.json +823 -349
- package/types/index.d.ts +650 -15
|
@@ -53,8 +53,9 @@ a number and a sound (taste 98, feel 79).
|
|
|
53
53
|
`get:<Resource>[.<field>]` or `get:<entity>[.<Component>[.<field>]]`
|
|
54
54
|
(logs the value as game code sees it, og.Time whole and a light og.DayNight
|
|
55
55
|
drives as it is drawn, and writes `get-<tick>.json`, then
|
|
56
|
-
`get-<tick>-2.json`, ... for more on one tick;
|
|
57
|
-
resources by name only, so `get:`
|
|
56
|
+
`get-<tick>-2.json`, ... for more on one tick; `get:Game:game.json`
|
|
57
|
+
names the file; a world dump lists resources by name only, so `get:`
|
|
58
|
+
is how to read one),
|
|
58
59
|
`set:<entity>.<Component>.<field>=<value>` or
|
|
59
60
|
`set:<Resource>.<field>=<value>` (`set:og.Camera.trauma=0.5`,
|
|
60
61
|
`set:Game.coins=10`, `set:og.Stylise.ink=false`: a number, `true` or
|
|
@@ -98,7 +99,46 @@ each its argument form and one sentence in `GameDesc.commandHelp`
|
|
|
98
99
|
(`{ spawn_wave: { usage: "<count>", doc: "Spawns a wave now." } }`)
|
|
99
100
|
so `help` explains it (it lists `spawn_wave:<count>`: the name, then the
|
|
100
101
|
usage). An entry naming no action is logged when the game
|
|
101
|
-
starts.
|
|
102
|
+
starts. A step's arguments are its colon-delimited fields after the
|
|
103
|
+
action, never shell words: `0.5:records:12:34.5` hands the handler
|
|
104
|
+
`args[0]` `"12"` and `args[1]` `"34.5"`, and its usage is written the same
|
|
105
|
+
way, `usage: "<berries>:<seconds>"` (a space stays inside its field:
|
|
106
|
+
`records:12 34.5` is one argument). A game may not take a core action's
|
|
107
|
+
name; og-game §3 lists them, with `open_pause` beside the engine's `pause`.
|
|
108
|
+
|
|
109
|
+
**File names.** Every output of one script has its own file. An unnamed
|
|
110
|
+
output takes the action and the tick (`get-000030.json`), and a second on
|
|
111
|
+
the same tick is suffixed quietly (`get-000030-2.json`). A named one that
|
|
112
|
+
an earlier step of the script already wrote, at any time (a copy-pasted
|
|
113
|
+
`0.5:get:Game:met.json`), is written as `met-2.json`, then `met-3.json`,
|
|
114
|
+
never over the first, and logs a WARN naming both steps ("'met.json' was
|
|
115
|
+
already written by the 0.5s get step, so this one is 'met-2.json'"). The
|
|
116
|
+
WARN is in `run.warnings`, so a playtest that asserts a clean run
|
|
117
|
+
(`t.equal(run.warnings.length, 0, ...)`) fails on the clash, and
|
|
118
|
+
`run.json("met.json")` reads the first step's: give each named step its
|
|
119
|
+
own file.
|
|
120
|
+
|
|
121
|
+
**Values in the JSON.** A dump and a `get` answer write a vector as an
|
|
122
|
+
array in lane order (`Vector3` `[x, y, z]`, `Quaternion` `[x, y, z, w]`,
|
|
123
|
+
`Color` `[r, g, b]`), where the API's values are objects
|
|
124
|
+
(`{ x, y, z }`); `set:` takes the lanes comma-separated, without spaces
|
|
125
|
+
(`set:box.og.Transform.position=4,5,6`). Read a dump by index:
|
|
126
|
+
|
|
127
|
+
```ts
|
|
128
|
+
// 0.3:get:box.og.Transform:t.json writes {"kind":"get","target":"box.og.Transform","tick":18,"value":{"position":[1,2.5,-3],...}}
|
|
129
|
+
const [x, y, z] = run.json<{ value: { position: [number, number, number] } }>("t.json").value.position;
|
|
130
|
+
t.near(y, 2.5, 1e-4, "the box stands on the ledge");
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
An `f32` field is IEEE-754 single precision. Game code reads it as the
|
|
134
|
+
f32's exact value promoted to a JavaScript number, so `2.7` written to an
|
|
135
|
+
f32 reads back as `2.700000047683716`, and what game code sends carries
|
|
136
|
+
that number as JSON (the facts, an og.platform payload, so
|
|
137
|
+
`dump_platform`); `get` and the dumps print the f32's shortest form,
|
|
138
|
+
`2.7`. Compare numbers with a tolerance in a test (`t.near(a, b, 1e-4,
|
|
139
|
+
...)`), round only to display one (`toFixed(1)` on the label), and keep a
|
|
140
|
+
value that must round-trip exactly (a payload a test compares with `===`)
|
|
141
|
+
in an `f64` field.
|
|
102
142
|
|
|
103
143
|
## 2. Live sessions: the probe and hot reload
|
|
104
144
|
|
|
@@ -205,7 +245,7 @@ every screen that matters.
|
|
|
205
245
|
| taste | UI sounds | a press that changed the UI and started a voice on the ui bus within 8 ticks | every press | og-taste §6, og-audio §3 |
|
|
206
246
|
| taste | Locale keys | `og cook`'s warnings | none | og-i18n §1 |
|
|
207
247
|
| feel | Input latency | ticks from the tick an input lands to the first thing seen or heard to change (a named entity accelerating or changing clip, the UI, a sound, a tween, a floating text, shake, hit stop, a particle burst); a press answered on its release counts from the release | 0–1 ticks | og-feel §1 |
|
|
208
|
-
| feel | Hit feedback | each damage moment (a fact named `hp`, `health`, `lives`… falling, or `hits`, `damage`, `kills`… rising): hit stop, shake, floating text and a sound within 8 ticks | three of the four | og-feel §3, §4, §7, og-audio §1 |
|
|
248
|
+
| feel | Hit feedback | each damage moment (a fact named `hp`, `health`, `lives`… falling, or `hits`, `damage`, `kills`… rising): hit stop, shake, floating text and a sound within 8 ticks | three of the four, per moment (a moment with three owes no fourth: a bump that holds, shakes and sounds is not asked for a number) | og-feel §3, §4, §7, og-audio §1 |
|
|
209
249
|
| feel | Idle frames | ticks after the first ten where nothing moves or animates, no UI moves, no sound starts or plays, no tween, text or particle runs | at most 10 % | og-feel §9, og-taste §5 |
|
|
210
250
|
| feel | Sound on input | inputs answered by a sound within 6 ticks | every action | og-audio §1 |
|
|
211
251
|
| feel | Frame time | step + render, p95, on the tier it ran on (`metal` on a Mac, `vulkan` on a GPU); the probe's own screenshots (render, read back, PNG) are not the game's step and are left out. Without a renderer the row says `n/a (no renderer)`, as do contrast, text size and HUD occupancy, which read frames | 8.3 ms (half the frame) | og-game §14 |
|
|
@@ -240,9 +240,10 @@ export const Move = defineSystem("Move", { reads: [Velocity], writes: [og.Transf
|
|
|
240
240
|
entity each.
|
|
241
241
|
- A handle is a 64-bit number (an `og.load` answer, a texture, a sound,
|
|
242
242
|
a geometry, a material, an entity): keep it in a field of its own kind,
|
|
243
|
-
`Asset()`, `Texture()`, `Sound()`, `
|
|
244
|
-
`Entity()` (each handle type of the API
|
|
245
|
-
|
|
243
|
+
`Asset()`, `Texture()`, `Sound()`, `Font()`, `Style()`, `Look()`,
|
|
244
|
+
`Geometry()`, `Material()` or `Entity()` (each handle type of the API
|
|
245
|
+
has its factory, named as the type: a font is a `Font()`, never an
|
|
246
|
+
`Asset()` cast), in a component or a resource. A `u32` field refuses one (`4294967298 is not
|
|
246
247
|
a u32`).
|
|
247
248
|
- Per-entity calls (`world.get`, `world.set`) are for commands, setup and
|
|
248
249
|
the few named entities a system touches (a camera, a listener, the
|
|
@@ -169,7 +169,10 @@ it is a cutscene or a reward.
|
|
|
169
169
|
## 7. Floating text
|
|
170
170
|
|
|
171
171
|
`og.render.floatingText(world, { text, position, ... })` pops a text that
|
|
172
|
-
rises, drifts and fades by itself (world state, deterministic).
|
|
172
|
+
rises, drifts and fades by itself (world state, deterministic). A label
|
|
173
|
+
that stays with a character (a name tag, a player's number) is not
|
|
174
|
+
floating text: it is screen text where the og.Camera resource's
|
|
175
|
+
`worldToScreen` puts the point, og-ui §3 (Text over a world point).
|
|
173
176
|
|
|
174
177
|
- Damage and score numbers above the hit point, not on the HUD: the eye is
|
|
175
178
|
already there. Pickups: what was gained (`+1`, `key`), short.
|
|
@@ -180,6 +183,11 @@ rises, drifts and fades by itself (world state, deterministic).
|
|
|
180
183
|
biggest number on screen should be the most important.
|
|
181
184
|
- Lifetime 0.6–1.0 s, rise 0.8–1.5 units, spread 0.2–0.4 so stacked hits do
|
|
182
185
|
not overlap. At most 6–8 on screen: sum rapid hits into one number.
|
|
186
|
+
- Not every impact wants a number. An impact is held by three of four
|
|
187
|
+
signals (hit stop §3, shake §4, floating text, a sound): `og polish`
|
|
188
|
+
counts them per damage moment and asks for the missing ones only of a
|
|
189
|
+
moment with fewer than three, so a party game's bump that holds, shakes
|
|
190
|
+
and sounds owes no floating text.
|
|
183
191
|
|
|
184
192
|
## 8. Camera: look-ahead, dead zones, zones, rails
|
|
185
193
|
|
|
@@ -213,6 +213,36 @@ export default og.game({
|
|
|
213
213
|
channel and playtests can call (`0.5:spawn_wave:3`), with their usage in
|
|
214
214
|
`GameDesc.commandHelp` for `help` (og-build §1). Add one for each state a
|
|
215
215
|
test needs to reach quickly, instead of playing there.
|
|
216
|
+
- **Arguments are colon-delimited**, the fields after the name, each a
|
|
217
|
+
string (`Number(args[0])` to read a number); a space is part of its
|
|
218
|
+
field, not a separator, and `\:` writes a colon inside one. Two
|
|
219
|
+
arguments, and the usage that says so:
|
|
220
|
+
|
|
221
|
+
```ts
|
|
222
|
+
commands: { records: (world, args) => setRecords(world, Number(args[0]), Number(args[1])) },
|
|
223
|
+
commandHelp: { records: { usage: "<berries>:<seconds>", doc: "Sets the isle's records." } },
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
`0.5:records:12:34.5` hands `args` `["12", "34.5"]`; `records:12 34.5`
|
|
227
|
+
would hand one argument, `"12 34.5"`.
|
|
228
|
+
- **Reserved names.** The channel's core actions are not a game's to
|
|
229
|
+
take, and the game refuses to start on one (`'pause' is a core action;
|
|
230
|
+
register under another name`): `screenshot`, `listen`, `touch_move_to`,
|
|
231
|
+
`touch_move`, `touch_start`, `touch_end`, `touch`, `scroll`, `gamepad`,
|
|
232
|
+
`key_down`, `key_up`, `type`, `compose`, `commit`, `move_to_text`,
|
|
233
|
+
`teleport`, `frame_entity`, `dump_world`, `dump_entity`, `dump_ui`,
|
|
234
|
+
`get`, `set`, `seed`, `pause`, `resume`, `advance`, `describe`,
|
|
235
|
+
`expect`, `save_scene`, `quit` and `help`. The actions the engine's
|
|
236
|
+
modules register are refused the same way (`'view' is a registered
|
|
237
|
+
engine action; register under another name`), in every build:
|
|
238
|
+
`bake_probes`, `cover`, `debug`, `dump_ai`, `dump_desync`,
|
|
239
|
+
`dump_lanes`, `dump_nav`, `dump_platform`, `dump_pulse`,
|
|
240
|
+
`dump_render`, `dump_room`, `dump_stream`, `lanes`, `locale`,
|
|
241
|
+
`terrain_stream`, `timeline`, `turntable` and `view` (`help` marks
|
|
242
|
+
them `(registered)`). The engine's `pause`
|
|
243
|
+
freezes the tick from outside the game; the game's own pause (its menu
|
|
244
|
+
open, `Game.paused` set) is a game action under its own name,
|
|
245
|
+
`open_pause`.
|
|
216
246
|
- **Facts** (`GameDesc.facts`) return a small JSON object for the probe's
|
|
217
247
|
`state()`: score, phase, lives. Tests assert on facts and dumps.
|
|
218
248
|
|
|
@@ -255,7 +285,19 @@ registered schema and refuses a model path that does not exist.
|
|
|
255
285
|
(ETC1S for colour, UASTC for normal and linear maps), WAV into QOA, fonts
|
|
256
286
|
into MSDF atlases, scenes into component tables. Import settings live next
|
|
257
287
|
to the source as `<file>.ogt` (`texture { kind normal }`,
|
|
258
|
-
`font { charset latin chars "开始游戏" }`).
|
|
288
|
+
`font { charset latin chars "开始游戏" }`). The prose here writes a
|
|
289
|
+
block on one line for short; in a file, as in every `.ogt`, a `{` ends
|
|
290
|
+
its key's line and a `}` stands alone on its own (the parser refuses
|
|
291
|
+
`'{' must end its line`):
|
|
292
|
+
|
|
293
|
+
```text
|
|
294
|
+
type import
|
|
295
|
+
version 1
|
|
296
|
+
---
|
|
297
|
+
texture {
|
|
298
|
+
kind normal
|
|
299
|
+
}
|
|
300
|
+
```
|
|
259
301
|
- At load a cooked texture reaches the GPU block-compressed in the device's
|
|
260
302
|
format with its mips (BC7, and BC5 for normal maps, on desktop GPUs; ASTC
|
|
261
303
|
on Apple and most Android; ETC2 and EAC elsewhere), a quarter of RGBA8's
|
|
@@ -411,6 +453,22 @@ else ignores it. The stamp is world state, so a replay reproduces it.
|
|
|
411
453
|
```ts
|
|
412
454
|
world.insert(hero, og.Sprite, { texture: tex, width: 1, height: 1.5, anchor: { x: 0.5, y: 0 }, dropShadow: 0.5, shadow: 0.3 });
|
|
413
455
|
```
|
|
456
|
+
- **Billboards** (three.js `Sprite`): `og.Sprite.facing` (or
|
|
457
|
+
`SpriteDesc.facing`) turns a world sprite to the camera that draws it.
|
|
458
|
+
`"cameraY"` stands it upright and turns it about y (trees, characters,
|
|
459
|
+
props a looking-down camera must not tip back); `"camera"` lays it in
|
|
460
|
+
the view plane (smoke, glints, signs); `"none"`, the default, keeps the
|
|
461
|
+
xy plane. Every camera turns it to itself (og.CameraView, og.Mirror, reflection
|
|
462
|
+
probes), the turn is render-only (never read by systems or snapshots),
|
|
463
|
+
faced sprites in one layer draw back to front from the camera and are
|
|
464
|
+
culled off screen, and a faced sprite's `dropShadow` is its whole shape
|
|
465
|
+
from any angle. It is still a sprite: flash, glow, blend, 2D lighting,
|
|
466
|
+
arrays, flipbooks and `toneMapped` all apply. A billboard behind a
|
|
467
|
+
transparent mesh still draws over it (sprites draw after the 3D scene).
|
|
468
|
+
|
|
469
|
+
```ts
|
|
470
|
+
world.insert(tree, og.Sprite, { texture: treeTex, width: 2, height: 2.6, anchor: { x: 0.5, y: 0 }, facing: "cameraY", dropShadow: 0.6 });
|
|
471
|
+
```
|
|
414
472
|
- **World UI that must not change with the light** (speech bubbles, name
|
|
415
473
|
tags, markers) takes `og.Sprite.toneMapped: false` (or
|
|
416
474
|
`SpriteDesc.toneMapped`), three.js's `Material.toneMapped`: still placed
|
|
@@ -717,6 +775,65 @@ strike, a bite or a fall at weight 1, back to 0 when `finished`.
|
|
|
717
775
|
Transform by the root joint's xz travel and yaw, `full` by all of it,
|
|
718
776
|
`off` (the default) leaves the hips travelling inside the model; switch it
|
|
719
777
|
to `planar` for a lunge's clip and back to `off` after.
|
|
778
|
+
**Look-at and joint limits.** `og.LookAt { skeleton, joint, target }`
|
|
779
|
+
on its own entity turns a joint (a head, an eye, a turret's barrel) so its
|
|
780
|
+
`axis` (default +Z, as three.js `lookAt`) points at `target` after the
|
|
781
|
+
clips and IK, its `upAxis` (+Y) rolling towards `up` (world +Y; zero
|
|
782
|
+
keeps the animated roll). `maxYaw` and `maxPitch` (radians from the
|
|
783
|
+
animated forward) hold a head from turning round, `clamped` reads back
|
|
784
|
+
when they did; `bones: 3` spreads the turn over neck, chest and spine;
|
|
785
|
+
`weight` fades it in and out. `og.JointLimit { skeleton, joint, axis,
|
|
786
|
+
swing, twistMin, twistMax }` (radians from the rest pose) limits what
|
|
787
|
+
`og.IkChain` and `og.LookAt` may turn a joint to: a knee is a hinge,
|
|
788
|
+
`axis` +X, `swing: 0.15`, `twistMin: 0`, `twistMax: 2.6`, so a
|
|
789
|
+
foot IK target never bends it backwards; a shoulder is a cone (`swing`).
|
|
790
|
+
The defaults limit nothing, and the clip's own pose is never clamped.
|
|
791
|
+
|
|
792
|
+
```ts
|
|
793
|
+
const look = must(world.spawn({ name: "hero-look" }));
|
|
794
|
+
must(world.insert(look, og.LookAt, { skeleton: body, joint: HEAD, bones: 2, maxYaw: 1.2, maxPitch: 0.5 }));
|
|
795
|
+
const knee = must(world.spawn({ name: "hero-knee-l" }));
|
|
796
|
+
must(world.insert(knee, og.JointLimit, { skeleton: body, joint: SHIN_L, axis: { x: 1, y: 0, z: 0 }, swing: 0.15, twistMin: 0, twistMax: 2.6 }));
|
|
797
|
+
// each tick, from a system that writes og.LookAt: world.set(look, og.LookAt, { target: playerPosition })
|
|
798
|
+
```
|
|
799
|
+
|
|
800
|
+
**Foot locking.** `og.FootLock { skeleton, foot }` on its own entity, one
|
|
801
|
+
per foot, keeps a foot the clips plant (within 5 mm of its lowest in the
|
|
802
|
+
clip, the same test retargeting uses) where it touched the ground while
|
|
803
|
+
root motion carries the body on and clips cross-fade, bending the leg
|
|
804
|
+
(two-bone IK, `og.JointLimit`s respected); when the clips lift it the
|
|
805
|
+
foot rejoins its animation over `release` (0.15 s). `planted` and
|
|
806
|
+
`locked` read back each tick; `maxDistance` (0.5 m) lets go before a leg
|
|
807
|
+
would stretch. It needs clips whose feet actually rest: a foot that only
|
|
808
|
+
grazes its lowest for a frame is held for that frame only.
|
|
809
|
+
|
|
810
|
+
**Spring bones.** `og.SpringBone { skeleton, joint, bones }` on its own
|
|
811
|
+
entity, one per chain (a tail, ears, a ponytail, a single jiggling node),
|
|
812
|
+
swings `joint` and its `bones` − 1 parents after their parents' motion:
|
|
813
|
+
each joint's tail is a damped spring (`frequency` 3 Hz, `damping` 0.3;
|
|
814
|
+
1 settles without overshoot) towards where the animation puts it, under
|
|
815
|
+
`gravity` (`{ x: 0, y: -9.8, z: 0 }` droops it), held at the bone's
|
|
816
|
+
length. `space` world (default) lags behind the entity's motion; model
|
|
817
|
+
ignores it (a teleport does not whip the tail). Applied last, after IK
|
|
818
|
+
and look-at; `lag` reads back how far the chain trails. Deterministic and
|
|
819
|
+
saved with the world. `tipFrequency` and `tipDamping` (1) scale the last
|
|
820
|
+
joint's frequency and damping, the joints between in proportion: 0.25 is
|
|
821
|
+
a strand soft at its tip on a stiff root.
|
|
822
|
+
|
|
823
|
+
Keep hair out of the head with `og.SpringCollider { skeleton, joint,
|
|
824
|
+
shape, offset, tail, radius }` on its own entity, a sphere about `offset`
|
|
825
|
+
or a capsule from `offset` to `tail` in the joint's frame: every tail of
|
|
826
|
+
that skeleton's springs is pushed out of it to its `radius` plus the
|
|
827
|
+
spring's `radius`, keeping its bone's length. A collider's `layers` (1)
|
|
828
|
+
must meet the spring's `colliders` (all) to count.
|
|
829
|
+
|
|
830
|
+
```ts
|
|
831
|
+
const tail = must(world.spawn({ name: "hero-tail" }));
|
|
832
|
+
must(world.insert(tail, og.SpringBone, { skeleton: body, joint: TAIL_TIP, bones: 3, gravity: { x: 0, y: -4, z: 0 }, tipFrequency: 0.5, radius: 0.02 }));
|
|
833
|
+
const hips = must(world.spawn({ name: "hero-hips-collider" }));
|
|
834
|
+
must(world.insert(hips, og.SpringCollider, { skeleton: body, joint: HIPS, shape: "capsule", offset: { x: -0.15, y: 0, z: 0 }, tail: { x: 0.15, y: 0, z: 0 }, radius: 0.12 }));
|
|
835
|
+
```
|
|
836
|
+
|
|
720
837
|
`templates/archetypes/third-person` (`src/anim.ts`: a 1D blend by speed,
|
|
721
838
|
a hero retargeted at cook time and sentinels at run time) is the pattern,
|
|
722
839
|
and for a 3D action game as a whole: a CharacterController over a level,
|
|
@@ -770,6 +887,7 @@ animation {
|
|
|
770
887
|
library "anims/humanoid-clips.glb" # its clips land in this model's #anim, retargeted (repeatable)
|
|
771
888
|
rig "rigs/hero.ogt" # how this model's bones are named (`type rig`); default: detected from the node names
|
|
772
889
|
footIk true # retargeting solves the legs so planted feet stay planted (default true)
|
|
890
|
+
mirror "turnLeft" "turnRight" # also write a clip mirrored to the other side, under that name (default "<clip>.mirrored"; repeatable)
|
|
773
891
|
compress false # quantised samples and keyframe reduction (default false: f32)
|
|
774
892
|
tolerance 0.0001 # the most compression may move a sampled value (default 0.0001, at most 0.1)
|
|
775
893
|
}
|
|
@@ -789,6 +907,34 @@ stride), and its legs are solved so planted feet stay on the ground
|
|
|
789
907
|
(`footIk`, on by default). The fx-showcase `retarget` station is the
|
|
790
908
|
pattern.
|
|
791
909
|
|
|
910
|
+
Hands retarget too: the fingers are humanoid bones (VRM 1.0's
|
|
911
|
+
`leftThumbMetacarpal` … `leftLittleDistal`, read from Mixamo's
|
|
912
|
+
`LeftHandIndex1`, VRoid's `J_Bip_L_Index1`, Rigify's `DEF-f_index.01.L`,
|
|
913
|
+
Unreal's `index_01_l`, plain `index.01.L`; Unity's legacy `Left Thumb
|
|
914
|
+
Proximal` is the metacarpal), each turning from its hand as
|
|
915
|
+
the source's does, so a fist or a grip holds on an A-posed arm whatever
|
|
916
|
+
the arm does. The target's twist bones (unmapped nodes named `twist`, such
|
|
917
|
+
as Unreal's `lowerarm_twist_01_l`, or Rigify's `DEF-forearm.L.001`) take a
|
|
918
|
+
share of their segment's roll by where they sit along it: none at the
|
|
919
|
+
segment's head, the next bone's at its end, so a forearm does not
|
|
920
|
+
candy-wrap. A clip made for the rig itself that leaves its twist bones
|
|
921
|
+
still gets the same shares each tick (after IK); a clip that keys them
|
|
922
|
+
is played as keyed. A character whose rest pose does not stand on the ground (an
|
|
923
|
+
armature lifted off it, a crouched rest) says how high its ankles stand
|
|
924
|
+
in its `type rig` file, `footHeight 0.08` (or `footHeight <left>
|
|
925
|
+
<right>`); planted feet then land on that ground, not at the rest pose's
|
|
926
|
+
foot height.
|
|
927
|
+
|
|
928
|
+
**Mirroring.** `og.anim.mirror(world, { clip, skeleton })` answers a new
|
|
929
|
+
clip that plays `clip` on the other side (a left-handed swing, a limp on
|
|
930
|
+
the other leg, a turn the other way): left and right nodes are paired by
|
|
931
|
+
the side tokens every naming scheme writes (`LeftArm`/`RightArm`,
|
|
932
|
+
`thigh.L`/`thigh.R`, `J_Bip_L_`/`J_Bip_R_`, `calf_l`/`calf_r`), each
|
|
933
|
+
node takes its counterpart's motion reflected across the skeleton's
|
|
934
|
+
x = 0 plane, root motion's sideways travel and turns flip. It assumes a
|
|
935
|
+
symmetric rest pose; mirror a retargeted clip on the skeleton it was
|
|
936
|
+
retargeted for.
|
|
937
|
+
|
|
792
938
|
**Compression** shrinks a model's clips in the bundle (not in memory: they
|
|
793
939
|
are rebuilt at load). In the same `animation` block, `compress true`
|
|
794
940
|
quantises rotations to 48 bits and the rest to 16 and drops the keyframes
|
|
@@ -818,6 +964,9 @@ clip walk "walk" {
|
|
|
818
964
|
speed 1 # duration multiplier, above 0 (default 1)
|
|
819
965
|
loop true # false: holds its last frame (default true)
|
|
820
966
|
}
|
|
967
|
+
clip walkOther "walk" {
|
|
968
|
+
mirror true # plays the clip on the other side of the skeleton (default false): no og.anim.mirror needed
|
|
969
|
+
}
|
|
821
970
|
clip run "run"
|
|
822
971
|
clip waving "wave"
|
|
823
972
|
blend1d move speed { # blend1d <motion> <param>: the two children around the value blend linearly, clamped at the ends
|
|
@@ -833,12 +982,14 @@ layer base { # the first layer is the base: root motion and og.An
|
|
|
833
982
|
state still idle # state <name> <motion>
|
|
834
983
|
state move move {
|
|
835
984
|
speed 1 # playback rate, 0 or more (default 1)
|
|
985
|
+
sync gait # a sync group: states of one group play in step across layers (default none)
|
|
836
986
|
}
|
|
837
987
|
entry still # the state it starts in (default: the first)
|
|
838
988
|
transition still move { # transition <from | any> <to>; in file order, the first that holds fires
|
|
839
989
|
when speed gt 0.2 # when <param> gt | ge | lt | le | eq | ne <number>; every `when` must hold
|
|
840
990
|
exit 0.9 # and the source has played this many cycles (a `when` or an `exit` is required)
|
|
841
991
|
fade 0.25 # cross-fade seconds (default 0.2)
|
|
992
|
+
interrupt any # what may cut this fade: any (default) | none (it completes first) | source (only the state being left) | next (only the new state's own)
|
|
842
993
|
}
|
|
843
994
|
transition any still { # any: from every state but the target
|
|
844
995
|
when speed le 0.2
|
|
@@ -847,7 +998,11 @@ layer base { # the first layer is the base: root motion and og.An
|
|
|
847
998
|
layer upper {
|
|
848
999
|
mode additive # override (default): replaces the pose below | additive: adds each clip's difference from its first frame
|
|
849
1000
|
weight wave # a number 0 to 1, or a parameter clamped to it (default 1)
|
|
850
|
-
|
|
1001
|
+
mask "spine" 0.5 # mask "<node>" [weight 0 to 1, default 1]: that node and every node under it (default: no mask, all 1)
|
|
1002
|
+
mask "arm.L" # a deeper line wins for its branch; nodes under no line take 0
|
|
1003
|
+
state wave waving {
|
|
1004
|
+
sync gait
|
|
1005
|
+
}
|
|
851
1006
|
}
|
|
852
1007
|
```
|
|
853
1008
|
|
|
@@ -855,7 +1010,16 @@ Each state advances one phase by `dt × AnimationGraph.speed × state speed
|
|
|
855
1010
|
/ duration`, the duration weighted across a blend's clips, so blended
|
|
856
1011
|
clips stay in step. Per tick and layer the transitions are checked first,
|
|
857
1012
|
then the phases advance, then the poses blend; a transition during a fade
|
|
858
|
-
replaces it
|
|
1013
|
+
replaces it unless its `interrupt` says otherwise (`none` for a
|
|
1014
|
+
committed attack or landing, `source` to let an idle re-target a start
|
|
1015
|
+
that has just begun). A layer's `mask` lines confine it to branches of the
|
|
1016
|
+
skeleton (by node name, the nearest named ancestor's weight; an upper-body
|
|
1017
|
+
layer is `mask "spine"`), so a wave or an aim plays over a walk without
|
|
1018
|
+
freezing the legs. In a sync group the first layer (file order) whose
|
|
1019
|
+
current state is in it leads: every later layer's state of that group
|
|
1020
|
+
plays at the leader's phase, whatever its clip's length, and a transition
|
|
1021
|
+
between two states of one group keeps the phase (a walk-to-run blend
|
|
1022
|
+
keeps the feet in step). `og.anim.graph` refuses a parse error naming the line, a
|
|
859
1023
|
clip name `clips` lacks, a parameter not declared and a motion that
|
|
860
1024
|
contains itself. Write the parameters from a system every tick
|
|
861
1025
|
(`world.set(body, og.AnimationGraph, { p0: speed })`); `state` and
|
|
@@ -1671,16 +1835,24 @@ there. `world.set(e, og.Velocity, ...)` refuses on
|
|
|
1671
1835
|
an entity without one (a body in `start`, before its first step):
|
|
1672
1836
|
`world.insert` it there, which adds and sets it.
|
|
1673
1837
|
|
|
1674
|
-
`og.CollisionStarted` is read on the tick after the physics step
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1838
|
+
`og.CollisionStarted` is read on the tick after the physics step, when
|
|
1839
|
+
the bodies' `og.Velocity` already holds the solver's answer (they may
|
|
1840
|
+
already be parting), so never weigh a hit from og.Velocity. The event
|
|
1841
|
+
carries the hit itself, taken in the step that made the contact. `a` is
|
|
1842
|
+
the lower id, and `normal` points from `a` to `b`. `point` is the deepest
|
|
1843
|
+
contact point.
|
|
1844
|
+
`relativeVelocity` (m/s) is `a`'s velocity relative to `b` at `point` as
|
|
1845
|
+
that step began: each body's linear velocity plus its spin crossed with
|
|
1846
|
+
the point's offset from its centre of mass. A static collider counts as
|
|
1847
|
+
still, and a kinematic body moves at its velocity. Its part along
|
|
1848
|
+
`normal` is the closing speed:
|
|
1849
|
+
`Math.max(0, rv.x * n.x + rv.y * n.y + rv.z * n.z)`, which is positive
|
|
1850
|
+
while they approach. `impulse` (N·s, at least 0) is the normal impulse the
|
|
1851
|
+
solver gave the pair in that step, summed over substeps and contact points:
|
|
1852
|
+
`b` took `impulse` along `normal` and `a` the same against it, so heavier
|
|
1853
|
+
bodies hitting give more. Scale feedback on the closing speed (how fast)
|
|
1854
|
+
or the impulse (how hard, mass included), as
|
|
1855
|
+
`examples/rumpus-isle/src/critters.ts` does for its bumps.
|
|
1684
1856
|
|
|
1685
1857
|
```ts
|
|
1686
1858
|
const hit = og.physics.raycast(world, { origin: eye, direction: { x: 0, y: 0, z: -1 }, maxDistance: 30, filter: { mask: 0b10, exclude: player } });
|
|
@@ -2821,11 +2993,22 @@ door. Mark the scene's unmoving models `static true` and put an
|
|
|
2821
2993
|
entity "hall" {
|
|
2822
2994
|
model "models/hall.glb"
|
|
2823
2995
|
static true
|
|
2824
|
-
Transform {
|
|
2996
|
+
Transform {
|
|
2997
|
+
position 0 0 0
|
|
2998
|
+
quaternion 0 0 0 1
|
|
2999
|
+
scale 1 1 1
|
|
3000
|
+
}
|
|
2825
3001
|
}
|
|
2826
3002
|
entity "hall-probes" {
|
|
2827
|
-
Transform {
|
|
2828
|
-
|
|
3003
|
+
Transform {
|
|
3004
|
+
position 0 2 0
|
|
3005
|
+
quaternion 0 0 0 1
|
|
3006
|
+
scale 1 1 1
|
|
3007
|
+
}
|
|
3008
|
+
LightVolume {
|
|
3009
|
+
size 12 4 12
|
|
3010
|
+
spacing 1
|
|
3011
|
+
}
|
|
2829
3012
|
}
|
|
2830
3013
|
```
|
|
2831
3014
|
|
|
@@ -88,6 +88,12 @@ if (answer.ok && typeof answer.data.value === "number") run.best[i] = Math.max(r
|
|
|
88
88
|
| AI-generated content shown | `aiMark(world, { kind, label })` | disclosure, not permission |
|
|
89
89
|
| Play with others in one room | `roomCreate(world, { name })`, `roomJoin(world, room)`, `roomLeave`, `roomSend(world, data, to?)`, `roomPeers`, `roomInfo`; the answers as `og.RoomJoined`, `og.RoomPeerJoined`, `og.RoomPeerLeft`, `og.RoomMessage` (read one with `roomMessage`) | natively `og relay` with `og run --room ws://127.0.0.1:P/<room>`; on the web the Player's rooms, when its hello lists `room.join` (`roomInfo(world).host` is `none` otherwise and joins are refused). A message is this peer's host input only: for a game both peers simulate, use og.net's lockstep (`og.Lockstep`, `og.PlayerInput`, og-game §20) and send nothing yourself |
|
|
90
90
|
|
|
91
|
+
A payload keeps the number it was given: an `f32` field's value is single
|
|
92
|
+
precision promoted to a JSON number (`f32(2.7)` sends `2.700000047683716`),
|
|
93
|
+
and the store neither rounds nor widens it. Compare with a tolerance in
|
|
94
|
+
a playtest, round only for display, or keep a value that must compare
|
|
95
|
+
exactly in an `f64` (og-build §1, Values in the JSON).
|
|
96
|
+
|
|
91
97
|
`og.platform.info(world)` says what answers here (`player`, `local` or
|
|
92
98
|
`none`) and the methods it answers (`capabilities`): check it rather than
|
|
93
99
|
trying.
|
|
@@ -342,6 +342,13 @@ the look lives in authored art (painted backdrops, frame-by-frame
|
|
|
342
342
|
animation, hand-placed pixels); the engine frames it with the look, but
|
|
343
343
|
the assets carry it, so budget for them.
|
|
344
344
|
|
|
345
|
+
**Read `look.profiles` before matching.** It names the project profiles a
|
|
346
|
+
style draws for: `["2d"]` for flipbooks, hand-placed pixels and paper
|
|
347
|
+
cut-outs, `["3d"]` for lit meshes, toon materials and voxels, both for a
|
|
348
|
+
post treatment that frames either. `create --premise` matches only among the
|
|
349
|
+
styles of the game's profile (`--profile`, else the premise's, else 3D);
|
|
350
|
+
`--look` names any style and wins.
|
|
351
|
+
|
|
345
352
|
**Write the look.** Start from the style's preset and change only what the
|
|
346
353
|
game needs; your file wins field by field. A style whose `look.presetReady`
|
|
347
354
|
is false has no preset in this engine yet: leave out `extends` and set the
|
|
@@ -105,6 +105,30 @@ layers (`anchor` for HUD corners, `modal` for dialogs,
|
|
|
105
105
|
playtest can `touch_move_to` it (`Shop/Panel/Detail/Buy` resolves as
|
|
106
106
|
`Detail/Buy`).
|
|
107
107
|
|
|
108
|
+
**Text over a world point** (a name tag over a critter, a marker over a
|
|
109
|
+
door): project the point each tick with the og.Camera resource's
|
|
110
|
+
`worldToScreen` (null behind the camera: draw nothing) and draw screen
|
|
111
|
+
text there, not world text. World text (`og.render.text` without `screen`) faces +z, rides
|
|
112
|
+
the tone curve and is blurred by depth of field at the frame's edge;
|
|
113
|
+
screen text is never tone mapped, blurred or depth tested, so the tag
|
|
114
|
+
stays crisp and in its colour, and at a `layer` up to `UI_LAYER` (1000) it
|
|
115
|
+
draws under every UI element (the HUD and the dialogs cover it):
|
|
116
|
+
|
|
117
|
+
```ts
|
|
118
|
+
const Tags = defineSystem("Tags", { reads: [Game, og.Camera] }, (_q, _t, world) => {
|
|
119
|
+
const cam = must(world.resource(og.Camera));
|
|
120
|
+
for (const c of critters(world)) {
|
|
121
|
+
const at = cam.worldToScreen({ x: c.x, y: c.y + 1.25, z: c.z }); // CSS pixels, y down
|
|
122
|
+
if (at === null) continue;
|
|
123
|
+
og.render.text(world, { font, text: c.name, position: { x: at.x, y: at.y, z: 0 }, size: 18, align: "center", outline: 0.7, screen: true, layer: 10 });
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Keep the font in a `Font()` field. Two tags within a tag's width of each
|
|
129
|
+
other overlap into one label: lift the later one by its height, or hide
|
|
130
|
+
the farther one's.
|
|
131
|
+
|
|
108
132
|
Mixed styles in one paragraph are `richText(id, markup)`: `[b]`,
|
|
109
133
|
`[color=danger]` (a token, or `#rrggbb`), `[size=lg]`, `[font=mono]`,
|
|
110
134
|
`[icon=coin]`, `[link=shop]…[/link]` and the per-glyph `[wave]`, `[shake]`,
|
package/knowledge/wiki/ai.md
CHANGED
|
@@ -18,7 +18,7 @@ module ai {
|
|
|
18
18
|
# declarations follow, each quoted below
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
-
<sub>`api.ogt` line
|
|
21
|
+
<sub>`api.ogt` line 9869</sub>
|
|
22
22
|
|
|
23
23
|
## Contents
|
|
24
24
|
|
|
@@ -74,7 +74,7 @@ fn load {
|
|
|
74
74
|
}
|
|
75
75
|
```
|
|
76
76
|
|
|
77
|
-
<sub>`api.ogt` line
|
|
77
|
+
<sub>`api.ogt` line 10041</sub>
|
|
78
78
|
|
|
79
79
|
<a id="fn-parse"></a>
|
|
80
80
|
|
|
@@ -104,7 +104,7 @@ fn parse {
|
|
|
104
104
|
}
|
|
105
105
|
```
|
|
106
106
|
|
|
107
|
-
<sub>`api.ogt` line
|
|
107
|
+
<sub>`api.ogt` line 10048</sub>
|
|
108
108
|
|
|
109
109
|
<a id="fn-get"></a>
|
|
110
110
|
|
|
@@ -136,7 +136,7 @@ fn get {
|
|
|
136
136
|
}
|
|
137
137
|
```
|
|
138
138
|
|
|
139
|
-
<sub>`api.ogt` line
|
|
139
|
+
<sub>`api.ogt` line 10055</sub>
|
|
140
140
|
|
|
141
141
|
<a id="fn-set"></a>
|
|
142
142
|
|
|
@@ -170,7 +170,7 @@ fn set {
|
|
|
170
170
|
}
|
|
171
171
|
```
|
|
172
172
|
|
|
173
|
-
<sub>`api.ogt` line
|
|
173
|
+
<sub>`api.ogt` line 10063</sub>
|
|
174
174
|
|
|
175
175
|
<a id="fn-restart"></a>
|
|
176
176
|
|
|
@@ -200,7 +200,7 @@ fn restart {
|
|
|
200
200
|
}
|
|
201
201
|
```
|
|
202
202
|
|
|
203
|
-
<sub>`api.ogt` line
|
|
203
|
+
<sub>`api.ogt` line 10072</sub>
|
|
204
204
|
|
|
205
205
|
<a id="fn-noise"></a>
|
|
206
206
|
|
|
@@ -230,7 +230,7 @@ fn noise {
|
|
|
230
230
|
}
|
|
231
231
|
```
|
|
232
232
|
|
|
233
|
-
<sub>`api.ogt` line
|
|
233
|
+
<sub>`api.ogt` line 10079</sub>
|
|
234
234
|
|
|
235
235
|
<a id="fn-describe"></a>
|
|
236
236
|
|
|
@@ -260,7 +260,7 @@ fn describe {
|
|
|
260
260
|
}
|
|
261
261
|
```
|
|
262
262
|
|
|
263
|
-
<sub>`api.ogt` line
|
|
263
|
+
<sub>`api.ogt` line 10086</sub>
|
|
264
264
|
|
|
265
265
|
## Components, resources and events
|
|
266
266
|
|
|
@@ -310,7 +310,7 @@ component AiAgent {
|
|
|
310
310
|
}
|
|
311
311
|
```
|
|
312
312
|
|
|
313
|
-
<sub>`api.ogt` line
|
|
313
|
+
<sub>`api.ogt` line 9888</sub>
|
|
314
314
|
|
|
315
315
|
<a id="record-Perception"></a>
|
|
316
316
|
|
|
@@ -411,7 +411,7 @@ component Perception {
|
|
|
411
411
|
}
|
|
412
412
|
```
|
|
413
413
|
|
|
414
|
-
<sub>`api.ogt` line
|
|
414
|
+
<sub>`api.ogt` line 9914</sub>
|
|
415
415
|
|
|
416
416
|
<a id="record-Perceivable"></a>
|
|
417
417
|
|
|
@@ -440,7 +440,7 @@ component Perceivable {
|
|
|
440
440
|
}
|
|
441
441
|
```
|
|
442
442
|
|
|
443
|
-
<sub>`api.ogt` line
|
|
443
|
+
<sub>`api.ogt` line 9984</sub>
|
|
444
444
|
|
|
445
445
|
<a id="record-AiChanged"></a>
|
|
446
446
|
|
|
@@ -467,7 +467,7 @@ event AiChanged {
|
|
|
467
467
|
}
|
|
468
468
|
```
|
|
469
469
|
|
|
470
|
-
<sub>`api.ogt` line
|
|
470
|
+
<sub>`api.ogt` line 9996</sub>
|
|
471
471
|
|
|
472
472
|
## Types
|
|
473
473
|
|
|
@@ -483,7 +483,7 @@ A generational handle: a number the engine hands out. A dead handle is an error
|
|
|
483
483
|
handle Behaviour "A loaded behaviour tree or state machine."
|
|
484
484
|
```
|
|
485
485
|
|
|
486
|
-
<sub>`api.ogt` line
|
|
486
|
+
<sub>`api.ogt` line 9875</sub>
|
|
487
487
|
|
|
488
488
|
<a id="type-BehaviourInfo"></a>
|
|
489
489
|
|
|
@@ -512,7 +512,7 @@ struct BehaviourInfo {
|
|
|
512
512
|
}
|
|
513
513
|
```
|
|
514
514
|
|
|
515
|
-
<sub>`api.ogt` line
|
|
515
|
+
<sub>`api.ogt` line 10004</sub>
|
|
516
516
|
|
|
517
517
|
<a id="type-NoiseDesc"></a>
|
|
518
518
|
|
|
@@ -544,7 +544,7 @@ struct NoiseDesc {
|
|
|
544
544
|
}
|
|
545
545
|
```
|
|
546
546
|
|
|
547
|
-
<sub>`api.ogt` line
|
|
547
|
+
<sub>`api.ogt` line 10014</sub>
|
|
548
548
|
|
|
549
549
|
<a id="type-AiDescription"></a>
|
|
550
550
|
|
|
@@ -579,7 +579,7 @@ struct AiDescription {
|
|
|
579
579
|
}
|
|
580
580
|
```
|
|
581
581
|
|
|
582
|
-
<sub>`api.ogt` line
|
|
582
|
+
<sub>`api.ogt` line 10028</sub>
|
|
583
583
|
|
|
584
584
|
## Column kinds
|
|
585
585
|
|
|
@@ -598,7 +598,7 @@ column Behaviour {
|
|
|
598
598
|
}
|
|
599
599
|
```
|
|
600
600
|
|
|
601
|
-
<sub>`api.ogt` line
|
|
601
|
+
<sub>`api.ogt` line 9877</sub>
|
|
602
602
|
|
|
603
603
|
## Constants
|
|
604
604
|
|
|
@@ -612,16 +612,16 @@ column Behaviour {
|
|
|
612
612
|
const AI_RUNNING u32 1 "AiAgent.status: the tree or state is still running."
|
|
613
613
|
```
|
|
614
614
|
|
|
615
|
-
<sub>`api.ogt` line
|
|
615
|
+
<sub>`api.ogt` line 9884</sub>
|
|
616
616
|
|
|
617
617
|
```ogt
|
|
618
618
|
const AI_SUCCESS u32 2 "AiAgent.status: the tree succeeded on the last think."
|
|
619
619
|
```
|
|
620
620
|
|
|
621
|
-
<sub>`api.ogt` line
|
|
621
|
+
<sub>`api.ogt` line 9885</sub>
|
|
622
622
|
|
|
623
623
|
```ogt
|
|
624
624
|
const AI_FAILURE u32 3 "AiAgent.status: the tree failed on the last think."
|
|
625
625
|
```
|
|
626
626
|
|
|
627
|
-
<sub>`api.ogt` line
|
|
627
|
+
<sub>`api.ogt` line 9886</sub>
|