@jgengine/core 0.11.0 → 0.13.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/CHANGELOG.md +52 -0
- package/dist/ai/populationDirector.d.ts +103 -0
- package/dist/ai/populationDirector.js +190 -0
- package/dist/ai/pursuit.d.ts +56 -0
- package/dist/ai/pursuit.js +53 -0
- package/dist/authoring.d.ts +1 -1
- package/dist/authoring.js +1 -1
- package/dist/combat/effects.d.ts +11 -4
- package/dist/combat/effects.js +24 -17
- package/dist/combat/magazine.d.ts +13 -0
- package/dist/combat/magazine.js +27 -0
- package/dist/combat/vfxPresets.d.ts +176 -0
- package/dist/combat/vfxPresets.js +74 -0
- package/dist/combat/weaponFire.d.ts +114 -0
- package/dist/combat/weaponFire.js +96 -0
- package/dist/combat.d.ts +5 -2
- package/dist/combat.js +4 -1
- package/dist/devtools/controls.d.ts +38 -0
- package/dist/devtools/controls.js +181 -0
- package/dist/devtools/devtools.d.ts +5 -197
- package/dist/devtools/devtools.js +38 -774
- package/dist/devtools/discover.d.ts +32 -0
- package/dist/devtools/discover.js +240 -0
- package/dist/devtools/fallbackSeams.d.ts +50 -0
- package/dist/devtools/fallbackSeams.js +111 -0
- package/dist/devtools/frame.d.ts +15 -0
- package/dist/devtools/frame.js +247 -0
- package/dist/devtools/logs.d.ts +15 -0
- package/dist/devtools/logs.js +86 -0
- package/dist/devtools/overrides.d.ts +16 -0
- package/dist/devtools/overrides.js +66 -0
- package/dist/devtools/types.d.ts +212 -0
- package/dist/devtools/types.js +1 -0
- package/dist/devtools/urlFlags.d.ts +22 -0
- package/dist/devtools/urlFlags.js +62 -0
- package/dist/economy/auctionBook.d.ts +122 -0
- package/dist/economy/auctionBook.js +213 -0
- package/dist/economy/priceHistory.d.ts +44 -0
- package/dist/economy/priceHistory.js +89 -0
- package/dist/economy/unlockPoints.d.ts +92 -0
- package/dist/economy/unlockPoints.js +103 -0
- package/dist/editor/commandApply.d.ts +5 -0
- package/dist/editor/commandApply.js +755 -0
- package/dist/editor/commands.d.ts +48 -3
- package/dist/editor/commands.js +40 -754
- package/dist/editor/directives.d.ts +94 -0
- package/dist/editor/directives.js +206 -0
- package/dist/editor/document.d.ts +37 -2
- package/dist/editor/document.js +422 -6
- package/dist/editor/entityCatalog.d.ts +42 -0
- package/dist/editor/entityCatalog.js +101 -0
- package/dist/editor/environment.d.ts +74 -0
- package/dist/editor/environment.js +169 -0
- package/dist/editor/index.d.ts +26 -1
- package/dist/editor/index.js +8 -1
- package/dist/editor/minimap.d.ts +31 -0
- package/dist/editor/minimap.js +73 -0
- package/dist/editor/streamer.d.ts +66 -0
- package/dist/editor/streamer.js +68 -0
- package/dist/editor/types.d.ts +143 -0
- package/dist/editor/world.d.ts +136 -0
- package/dist/editor/world.js +303 -0
- package/dist/game/breeding.d.ts +161 -0
- package/dist/game/breeding.js +181 -0
- package/dist/game/cameraConfig.d.ts +451 -0
- package/dist/game/cameraConfig.js +1 -0
- package/dist/game/clipRoles.d.ts +51 -0
- package/dist/game/clipRoles.js +142 -0
- package/dist/game/defineGame.d.ts +16 -9
- package/dist/game/defineGame.js +14 -6
- package/dist/game/defineSystem.d.ts +2 -0
- package/dist/game/defineSystem.js +2 -0
- package/dist/game/events.d.ts +28 -0
- package/dist/game/partAnimation.d.ts +78 -0
- package/dist/game/partAnimation.js +147 -0
- package/dist/game/playableGame.d.ts +72 -440
- package/dist/game/playableGame.js +1 -1
- package/dist/game/progression.d.ts +35 -0
- package/dist/game/progression.js +22 -1
- package/dist/game/quest.js +1 -3
- package/dist/game/tribe.d.ts +184 -0
- package/dist/game/tribe.js +432 -0
- package/dist/gameplay.d.ts +3 -1
- package/dist/gameplay.js +3 -1
- package/dist/inventory/encumbrance.d.ts +69 -0
- package/dist/inventory/encumbrance.js +68 -0
- package/dist/inventory/inventoryModel.d.ts +24 -8
- package/dist/inventory/inventoryModel.js +47 -8
- package/dist/item/durability.js +1 -3
- package/dist/meta/changelog.d.ts +1 -1
- package/dist/meta/changelog.js +48 -1
- package/dist/movement/movementModel.d.ts +15 -1
- package/dist/movement/movementModel.js +33 -15
- package/dist/movement/playerMovement.js +102 -2
- package/dist/multiplayer/combatSnapshot.js +13 -8
- package/dist/multiplayer/presenceModel.d.ts +2 -0
- package/dist/multiplayer/presenceModel.js +8 -0
- package/dist/physics/drivableVehicle.d.ts +2 -0
- package/dist/physics/drivableVehicle.js +1 -1
- package/dist/physics/flightDynamics.d.ts +82 -0
- package/dist/physics/flightDynamics.js +165 -0
- package/dist/physics/gravityField.d.ts +25 -0
- package/dist/physics/gravityField.js +41 -0
- package/dist/physics/kinematicVehicle.d.ts +87 -0
- package/dist/physics/kinematicVehicle.js +193 -11
- package/dist/physics/physicsWorld.d.ts +26 -0
- package/dist/physics/physicsWorld.js +109 -117
- package/dist/physics/vehicleObstacles.d.ts +44 -0
- package/dist/physics/vehicleObstacles.js +115 -0
- package/dist/random/rng.d.ts +4 -1
- package/dist/random/rng.js +4 -1
- package/dist/runtime/adapter.d.ts +13 -0
- package/dist/runtime/adapter.js +13 -0
- package/dist/runtime/context/combat.d.ts +51 -0
- package/dist/runtime/context/combat.js +131 -0
- package/dist/runtime/context/combatFx.js +15 -5
- package/dist/runtime/context/deathLoot.d.ts +30 -0
- package/dist/runtime/context/deathLoot.js +39 -0
- package/dist/runtime/context/player.d.ts +48 -0
- package/dist/runtime/context/player.js +125 -0
- package/dist/runtime/context/scene.d.ts +60 -0
- package/dist/runtime/context/scene.js +329 -0
- package/dist/runtime/context/snapshotCodecs.d.ts +12 -0
- package/dist/runtime/context/snapshotCodecs.js +26 -0
- package/dist/runtime/descriptors/baseline.js +26 -3
- package/dist/runtime/descriptors/features.d.ts +5 -0
- package/dist/runtime/descriptors/features.js +20 -2
- package/dist/runtime/gameContext.d.ts +2 -428
- package/dist/runtime/gameContext.js +133 -500
- package/dist/runtime/gameContextTypes.d.ts +500 -0
- package/dist/runtime/gameContextTypes.js +1 -0
- package/dist/runtime/headlessRunner.d.ts +17 -2
- package/dist/runtime/headlessRunner.js +15 -0
- package/dist/runtime/hostPolicy.d.ts +51 -0
- package/dist/runtime/hostPolicy.js +68 -0
- package/dist/runtime/hostedGameRunner.d.ts +3 -1
- package/dist/runtime/hostedGameRunner.js +1 -0
- package/dist/runtime/hostedWorldSession.d.ts +3 -1
- package/dist/runtime/hostedWorldSession.js +1 -0
- package/dist/runtime/worldSnapshot.d.ts +13 -1
- package/dist/runtime/worldSnapshot.js +15 -3
- package/dist/scene/assetCatalog.d.ts +7 -0
- package/dist/scene/assetSpace.js +1 -3
- package/dist/scene/authoredTriggers.d.ts +50 -0
- package/dist/scene/authoredTriggers.js +114 -0
- package/dist/scene/builtinSceneKinds.js +8 -3
- package/dist/scene/colliders.d.ts +79 -0
- package/dist/scene/colliders.js +170 -0
- package/dist/scene/collisionMesh.d.ts +94 -0
- package/dist/scene/collisionMesh.js +699 -0
- package/dist/scene/companion.d.ts +147 -0
- package/dist/scene/companion.js +193 -0
- package/dist/scene/entityStats.d.ts +7 -9
- package/dist/scene/entityStats.js +19 -15
- package/dist/scene/sceneKinds.d.ts +16 -0
- package/dist/scene/sceneKinds.js +4 -0
- package/dist/scene/sceneRaycast.js +15 -0
- package/dist/stats/spawnLevelStats.d.ts +110 -0
- package/dist/stats/spawnLevelStats.js +140 -0
- package/dist/stats/statModifiers.d.ts +16 -0
- package/dist/stats/statModifiers.js +30 -1
- package/dist/stats/statPool.d.ts +70 -0
- package/dist/stats/statPool.js +62 -0
- package/dist/store/changeSignal.d.ts +3 -0
- package/dist/store/changeSignal.js +2 -0
- package/dist/store/observableKeyedStore.d.ts +2 -0
- package/dist/store/observableKeyedStore.js +1 -0
- package/dist/survival/decayMeter.js +1 -3
- package/dist/survival/regionHealth.js +1 -3
- package/dist/ui/hudLayout.d.ts +5 -0
- package/dist/ui/hudLayout.js +17 -1
- package/dist/ui/panelModel.d.ts +120 -0
- package/dist/ui/panelModel.js +168 -0
- package/dist/ui.d.ts +1 -0
- package/dist/ui.js +1 -0
- package/dist/world/authoredEntities.d.ts +29 -0
- package/dist/world/authoredEntities.js +29 -0
- package/dist/world/authoredObjects.d.ts +15 -1
- package/dist/world/authoredObjects.js +13 -1
- package/dist/world/authoredSpawn.d.ts +39 -0
- package/dist/world/authoredSpawn.js +37 -0
- package/dist/world/buildSockets.d.ts +152 -0
- package/dist/world/buildSockets.js +188 -0
- package/dist/world/buildingLots.d.ts +84 -0
- package/dist/world/buildingLots.js +119 -0
- package/dist/world/buildings.d.ts +6 -0
- package/dist/world/cityBlocks.d.ts +152 -0
- package/dist/world/cityBlocks.js +670 -0
- package/dist/world/cityContent.d.ts +77 -0
- package/dist/world/cityContent.js +261 -0
- package/dist/world/cityGenerator.d.ts +41 -0
- package/dist/world/cityGenerator.js +58 -0
- package/dist/world/cityGeometry.d.ts +114 -0
- package/dist/world/cityGeometry.js +573 -0
- package/dist/world/cityKind.d.ts +314 -0
- package/dist/world/cityKind.js +1578 -0
- package/dist/world/environmentSummary.js +57 -1
- package/dist/world/features.d.ts +53 -5
- package/dist/world/features.js +15 -3
- package/dist/world/grassKind.js +2 -2
- package/dist/world/markers.d.ts +50 -4
- package/dist/world/markers.js +49 -0
- package/dist/world/massing.js +1 -1
- package/dist/world/minimapBake.d.ts +78 -0
- package/dist/world/minimapBake.js +208 -0
- package/dist/world/minimapTrack.d.ts +17 -0
- package/dist/world/minimapTrack.js +22 -0
- package/dist/world/place.d.ts +166 -0
- package/dist/world/place.js +96 -0
- package/dist/world/placeAsset.js +3 -1
- package/dist/world/poleLineKind.d.ts +40 -0
- package/dist/world/poleLineKind.js +97 -0
- package/dist/world/polyline.js +9 -2
- package/dist/world/resourceNode.d.ts +109 -0
- package/dist/world/resourceNode.js +140 -0
- package/dist/world/roads.d.ts +19 -2
- package/dist/world/roads.js +60 -3
- package/dist/world/scatter.js +2 -20
- package/dist/world/streetGenerator.d.ts +159 -0
- package/dist/world/streetGenerator.js +684 -0
- package/dist/world/streets.d.ts +103 -1
- package/dist/world/streets.js +273 -0
- package/dist/world/terraform.js +58 -88
- package/dist/world/terrain.d.ts +65 -1
- package/dist/world/terrain.js +119 -2
- package/dist/world.d.ts +14 -5
- package/dist/world.js +12 -3
- package/package.json +1 -1
- package/skills/game-design/SKILL.md +28 -0
- package/skills/game-design/agents/openai.yaml +4 -0
- package/skills/game-design/references/application-playbook.md +170 -0
- package/skills/game-design/references/field-guide.md +288 -0
- package/skills/jgengine/SKILL.md +8 -4
- package/skills/jgengine/api.md +182 -81
- package/skills/jgengine/capabilities.md +104 -2
- package/skills/jgengine/recipes/minimal-game.md +88 -0
- package/skills/jgengine-combat/SKILL.md +19 -1
- package/skills/jgengine-combat/api.md +75 -2
- package/skills/jgengine-combat/capabilities.md +61 -1
- package/skills/jgengine-combat/recipes/portable-damage-effects.md +197 -0
- package/skills/jgengine-combat/recipes/portable-runtime-state.md +154 -0
- package/skills/jgengine-combat/recipes/portable-stat-pools.md +122 -0
- package/skills/jgengine-combat/recipes/portable-weapon-plumbing.md +156 -0
- package/skills/jgengine-combat/recipes/visible-attacks.md +81 -0
- package/skills/jgengine-combat/reference.md +33 -4
- package/skills/jgengine-gameplay/SKILL.md +8 -0
- package/skills/jgengine-gameplay/api.md +182 -26
- package/skills/jgengine-gameplay/capabilities.md +96 -2
- package/skills/jgengine-gameplay/recipes/portable-xp-leveling.md +168 -0
- package/skills/jgengine-gameplay/reference-systems.md +10 -5
- package/skills/jgengine-world/SKILL.md +13 -0
- package/skills/jgengine-world/api.md +453 -21
- package/skills/jgengine-world/capabilities.md +112 -2
- package/skills/jgengine-world/recipes/commanding-entities.md +128 -0
- package/skills/jgengine-world/reference.md +43 -4
- package/skills/jgengine/reference-cartridge.md +0 -72
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# Recipe — minimal game (scaffold → authored scene → win)
|
|
2
|
+
|
|
3
|
+
**What this wires:** the default end-to-end path from nothing to a complete, genre-free
|
|
4
|
+
walk/interact/win game: a scaffold, one `defineGame` config off the happy-path kit, an
|
|
5
|
+
authored scene edited in the browser, one system, one store slot, an empty-canvas HUD,
|
|
6
|
+
and a win condition. Every new game starts here; add combat, multiplayer, or deeper
|
|
7
|
+
world features only after this loop plays.
|
|
8
|
+
|
|
9
|
+
## 1. Scaffold
|
|
10
|
+
|
|
11
|
+
`npx jgengine create <name>` (inside the engine monorepo: `bun run new:game "<id-or-title>"`).
|
|
12
|
+
The file set is thin and already runs:
|
|
13
|
+
|
|
14
|
+
- `src/main.tsx` — mounts `GameHost` with `editor={() => import("@jgengine/editor")}`; the
|
|
15
|
+
host owns the F2+E / `?mode=editor` editor summon and the dev save endpoint.
|
|
16
|
+
- `src/game.config.ts` — the whole game definition (below).
|
|
17
|
+
- `src/editor.scene.json` + `src/editorLayers.ts` — the authored scene document, normalized
|
|
18
|
+
with `normalizeEditorLayers`. All placement lives here, never as coordinates in code.
|
|
19
|
+
- `src/loop.ts` and `src/game/ui/GameUI.tsx` — systems and HUD.
|
|
20
|
+
|
|
21
|
+
## 2. Define the game — one import surface
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
// game.config.ts — everything below comes from the kit; deeper paths are for outgrowing it.
|
|
25
|
+
import { defineGame } from "@jgengine/shell/gameKit";
|
|
26
|
+
|
|
27
|
+
import { editorLayers } from "./editorLayers";
|
|
28
|
+
import { GameUI } from "./game/ui/GameUI";
|
|
29
|
+
import { onNewPlayer, systems } from "./loop";
|
|
30
|
+
|
|
31
|
+
export const game = defineGame({
|
|
32
|
+
name: "my-game",
|
|
33
|
+
// Binding movement actions makes the shell drive the walk controller — the game walks day one.
|
|
34
|
+
input: { moveForward: ["KeyW"], moveBack: ["KeyS"], moveLeft: ["KeyA"], moveRight: ["KeyD"], interact: ["KeyE"] },
|
|
35
|
+
systems,
|
|
36
|
+
loop: { onNewPlayer },
|
|
37
|
+
GameUI,
|
|
38
|
+
editorLayers, // the authored scene auto-mounts; the player spawns at its player_spawn marker
|
|
39
|
+
});
|
|
40
|
+
// Solo game: omit `multiplayer` entirely — offline is the shell default.
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**World is optional and thin.** Omitting `world` is valid — a pure UI/rules game is not a
|
|
44
|
+
spatial place. When the game *is* a place, declare only substrate + laws with `world()` from
|
|
45
|
+
`@jgengine/core/world/place` (e.g. `{ id, ground: { mode: "flat", size: { x: Infinity, z: Infinity } }, physics: { gravity: -24 } }`,
|
|
46
|
+
or `mode: "board"` for 2D). Never seed, sky, or vegetation in `world` — the engine renders its
|
|
47
|
+
default sky until you author one in the editor, and foliage is editor scatter over the ground.
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
// loop.ts — one store slot for run state, one system for the rules tick.
|
|
52
|
+
import { defineStore, defineSystem, authoredSpawnPosition, type GameContext } from "@jgengine/shell/gameKit";
|
|
53
|
+
|
|
54
|
+
import { editorLayers } from "./editorLayers";
|
|
55
|
+
|
|
56
|
+
export const run = defineStore("run", { collected: 0, won: false });
|
|
57
|
+
|
|
58
|
+
export const systems = [
|
|
59
|
+
defineSystem({
|
|
60
|
+
id: "rules",
|
|
61
|
+
tick: { type: "fixed" },
|
|
62
|
+
update(ctx: GameContext) {
|
|
63
|
+
// System-check win alternative: read/update `run` here (e.g. win at collected >= 3).
|
|
64
|
+
if (run.read(ctx).collected >= 3) run.update(ctx, (s) => ({ ...s, won: true }));
|
|
65
|
+
},
|
|
66
|
+
}),
|
|
67
|
+
];
|
|
68
|
+
|
|
69
|
+
export function onNewPlayer(ctx: GameContext): void {
|
|
70
|
+
ctx.scene.entity.spawn("player", { id: ctx.player.userId, position: authoredSpawnPosition(editorLayers) ?? [0, 0, 0] });
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
`GameUI` starts as an empty `HudCanvas` (`useHudLayout` + `HudCanvas` from the kit). That is
|
|
75
|
+
intentional: **every game owns its UI**. Write a short UI art direction, then build custom
|
|
76
|
+
panels for this pitch — do not ship stock drop-in widgets (`StatBar`, `Hotbar`, `Coins`, glass
|
|
77
|
+
frames) as the product face. Reach for engine pieces only as headless data, layout, or
|
|
78
|
+
interaction models under game-owned chrome (see `jgengine-ui`).
|
|
79
|
+
|
|
80
|
+
## 3. Author, play, win
|
|
81
|
+
|
|
82
|
+
1. `bun dev`, then F2+E opens the editor on `editor.scene.json` — move the spawn, place
|
|
83
|
+
props and trigger markers, Ctrl+S saves back to the document.
|
|
84
|
+
2. The starter scene ships a goal marker with `{ on: "enter", action: "win" }` — walking
|
|
85
|
+
into it wins with zero game code. Author more rules the same way (triggers in the
|
|
86
|
+
editor), or read volumes yourself via the kit's `collectAuthoredTriggers(editorLayers)`.
|
|
87
|
+
3. Prove it: `bun test` asserts the document (spawn, goal), and `jgengine-verify` covers
|
|
88
|
+
screenshot and gameplay evidence before any "it works" claim.
|
|
@@ -11,6 +11,25 @@ This skill owns combat resolution: target policy, combat stats, teams/factions a
|
|
|
11
11
|
|
|
12
12
|
Search [capabilities.md](capabilities.md), then use [api.md](api.md) for signatures and [reference.md](reference.md) for complete pipelines.
|
|
13
13
|
|
|
14
|
+
Existing projects keep their resource state and follow the
|
|
15
|
+
[portable stat-pool recipe](recipes/portable-stat-pools.md). Adapt the caller's
|
|
16
|
+
store through `StatPoolAccess`; do not require `StatValueMap`, `GameContext`, or
|
|
17
|
+
a parallel entity store. To bolt firing onto an existing game, compose
|
|
18
|
+
`createWeaponRuntime` (cadence + magazine + the caller's own raycast + portable
|
|
19
|
+
`resolveDamageHit`) per the
|
|
20
|
+
[portable weapon-plumbing recipe](recipes/portable-weapon-plumbing.md); never add
|
|
21
|
+
a default gun or FPS kit.
|
|
22
|
+
|
|
23
|
+
Damage commitment accepts the same structural pool adapter while the matchup,
|
|
24
|
+
receiver, interceptor, and status stages remain pure. Follow the
|
|
25
|
+
[portable damage/effects recipe](recipes/portable-damage-effects.md) to compose
|
|
26
|
+
them over an existing store, clock, RNG, spatial index, and death flow.
|
|
27
|
+
|
|
28
|
+
Closure-backed magazines and stat modifiers expose plain snapshot/restore
|
|
29
|
+
state for caller-owned saves, rollback, replay, and workers. Follow the
|
|
30
|
+
[portable runtime-state recipe](recipes/portable-runtime-state.md); the caller
|
|
31
|
+
keeps its clock, reserve state, schema, and authority.
|
|
32
|
+
|
|
14
33
|
## Canonical pipeline
|
|
15
34
|
|
|
16
35
|
1. Acquire eligible candidates from a bounded spatial source.
|
|
@@ -31,4 +50,3 @@ Compose stages through registration/policy seams; adding a damage type, effect,
|
|
|
31
50
|
- Reward generation and allocation are different operations, especially in multiplayer.
|
|
32
51
|
- Compose multiple loot pools with `createLootPipeline` (ordered stages, gates, fallbacks, roll modifiers, per-drop provenance) over `lootTable`; keep genre concepts (world/dedicated/boss/luck/pity) in game-space stages and modifiers, never in core.
|
|
33
52
|
- UI bars, reticles, and feedback route to `jgengine-ui`.
|
|
34
|
-
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
- `DEFAULT_FIRE_PULSE_SECONDS` (const): const DEFAULT_FIRE_PULSE_SECONDS: 0.12 — Default `RenderCueTuning.firePulseSeconds`.
|
|
29
29
|
- `DEFAULT_HIT_PULSE_SECONDS` (const): const DEFAULT_HIT_PULSE_SECONDS: 0.2 — Default `RenderCueTuning.hitPulseSeconds`.
|
|
30
30
|
- `DEFAULT_RENDER_CUES` (const): const DEFAULT_RENDER_CUES: Readonly<EntityRenderCues> — Neutral starting cue set: idle, unarmed, undamaged.
|
|
31
|
+
- `DEFAULT_VFX_PRESET` (const): const DEFAULT_VFX_PRESET: VfxPresetName — The fallback flavor used when a `vfx()` call names an unknown preset — so a typo still shows a spark instead of nothing.
|
|
31
32
|
- `DamageChannelId` (type): type DamageChannelId = string — Caller-owned id for a damage channel — `"fire"`, `"ballistic"`, `"physical"`, `"corrosive"`. The engine never branches on the value; a channel is whatever a game's data declares.
|
|
32
33
|
- `DamageClampConfig` (interface): interface DamageClampConfig — Caller data for a flat per-hit damage cap.
|
|
33
34
|
- `DamageContext` (interface): interface DamageContext — The facts a received-damage modifier predicates over: the incoming `channel`, who dealt it, the statuses the target currently carries, and any caller tags. All caller-owned strings; the engine never assigns meaning to a channel, source, status, or tag.
|
|
@@ -50,6 +51,8 @@
|
|
|
50
51
|
- `EntityRenderCues` (interface): interface EntityRenderCues — Per-entity render cues: the motion/animation signal a custom `renderEntity` or first-person viewmodel component needs to drive gait, muzzle flash, reload poses, and hit reactions — without diffing the parent group's position itself or reading a game-side module map for attack timing.
|
|
51
52
|
- `EventMeter` (interface): interface EventMeter — ⚠ undocumented
|
|
52
53
|
- `EventMeterFeedResult` (interface): interface EventMeterFeedResult — ⚠ undocumented
|
|
54
|
+
- `FireCadence` (interface): interface FireCadence — A minimal minimum-interval rate gate for a repeated action — weapon fire, ability spam, any "no faster than N per second" rule. Deterministic and serializable: its whole state is the elapsed time since the last action, exposed via {@link FireCadence.elapsedMs}.
|
|
55
|
+
- `FireCadenceConfig` (interface): interface FireCadenceConfig — Tuning for {@link createFireCadence}: the minimum interval between actions and whether it starts ready.
|
|
53
56
|
- `FrameRange` (interface): interface FrameRange — ⚠ undocumented
|
|
54
57
|
- `HitReactionConfig` (interface): interface HitReactionConfig — ⚠ undocumented
|
|
55
58
|
- `ImmunityWindow` (interface): interface ImmunityWindow — A per-target timed immunity policy: an interceptor plus grant/query/serialize controls, toggled by transitions.
|
|
@@ -58,7 +61,9 @@
|
|
|
58
61
|
- `InterceptRecord` (interface): interface InterceptRecord — One row of provenance: which interceptor acted, what it decided, and the amount before/after it acted.
|
|
59
62
|
- `MAX_INTERCEPT_STEPS` (const): const MAX_INTERCEPT_STEPS: 256 — Upper bound on interceptor evaluations for a single resolution; guards against runaway `split`/`redirect` loops.
|
|
60
63
|
- `Magazine` (interface): interface Magazine — A per-weapon magazine: discrete loaded rounds, a timed reload that refills from a reserve pool, and the reserve-pool interaction itself — the primitive that replaces hand-rolling mag size, reload delay, and reserve bookkeeping per game (#536.2).
|
|
64
|
+
- `MagazineConfig` (interface): interface MagazineConfig — Tuning for `createMagazine`: mag capacity, reload delay, and where reserve ammo is drawn from.
|
|
61
65
|
- `MagazineReserve` (interface): interface MagazineReserve — Draws ammo for a `Magazine`'s reload from wherever the reserve pool actually lives.
|
|
66
|
+
- `MagazineSnapshot` (interface): interface MagazineSnapshot — Complete serializable state for a {@link Magazine}; `reserve: null` means infinite reserve.
|
|
62
67
|
- `MatchupOutputs` (interface): interface MatchupOutputs — The independent, typed outputs a channel-vs-trait matchup can scale. Every field is an optional multiplier that defaults to `1` (identity), so a matchup entry names only the axes it bends. `impact` scales the direct hit, `applyChance` the odds a status lands, `magnitude` and `duration` the applied status itself, and `extra` carries any further caller-defined scalar (knockback, stagger, heat) the engine forwards without interpreting.
|
|
63
68
|
- `MeterAddResult` (interface): interface MeterAddResult — ⚠ undocumented
|
|
64
69
|
- `ObjectRaycastHit` (interface): interface ObjectRaycastHit — ⚠ undocumented
|
|
@@ -88,7 +93,14 @@
|
|
|
88
93
|
- `ShotOriginPolicy` (type): type ShotOriginPolicy = | { kind: "converge"; muzzle?: EntityPosition; height?: number } | { kind: "eye"; height?: number } | { kind: "legacy" } | { kind: "entity" } | { kind: "entityOffset"; offset: EntityPosition } | { kind: "muzzle"; offset?: EntityPosition } | { kind: "camera"; origin: EntityPos… — How a shot's world-space origin (and optional direction) is resolved before prediction/settlement. - `converge` — the shot leaves the gun `muzzle` yet still passes through whatever the shooter's sightline (crosshair) covers: origin is the muzzle offset, direction is bent from the muzzle to the eye ray's aim point. The projectile system's default for a free `{ yaw, pitch }` aim, so a bullet visibly comes from the barrel without missing the reticle. Needs a scene raycast to find the aim point (`convergeShot`); a bare `resolveShot` degrades to a straight muzzle ray. Passes an explicit `{ origin, direction }` aim through untouched. - `eye` — `aim.origin` when present, else the shooter's entity position raised to eye height; the shot traces the shooter's sightline, so what the crosshair covers is what gets hit. - `legacy` — `aim.origin` when present, else the shooter's raw entity position (feet). - `entity` — always the shooter's entity position. - `entityOffset` / `muzzle` — entity-local offset rotated by the shooter's yaw (muzzle on a weapon model). - `camera` — explicit camera/reticle world origin (and optional direction override). - `world` — absolute world origin.
|
|
89
94
|
- `SpawnProvider` (type): type SpawnProvider = ( params: Readonly<Record<string, unknown>>, ctx: SpawnProviderContext, ) => readonly EncounterSpawnRequest[] — A spawn provider: given the phase's `params` and context, returns the spawn requests to emit on enter. Deterministic; reads authored scene points from `ctx.spawnPoints` rather than embedding coordinates.
|
|
90
95
|
- `SpawnProviderContext` (interface): interface SpawnProviderContext — Evaluation context a spawn provider receives when its phase is entered.
|
|
96
|
+
- `StatPool` (interface): interface StatPool — Serializable state for any bounded named resource. The caller defines what the resource means.
|
|
97
|
+
- `StatPoolAccess` (interface): interface StatPoolAccess<TOwnerId extends string = string, TStatId extends string = string> — Structural bridge to caller-owned resource state. Implement it over an ECS, Redux/Zustand store, plain object, database-backed model, or JGengine's native entity stats without moving ownership into the SDK.
|
|
98
|
+
- `StatPoolAccessResult` (type): type StatPoolAccessResult = | ({ status: "ok" } & StatPoolChange) | { status: "rejected"; reason: string } — Outcome of changing a pool through {@link StatPoolAccess}.
|
|
99
|
+
- `StatPoolChange` (interface): interface StatPoolChange — Inspectable result of a bounded pool change.
|
|
100
|
+
- `StatPoolInput` (interface): interface StatPoolInput — Input used to create a normalized pool. `current` defaults to `max`; `min` defaults to zero.
|
|
101
|
+
- `StatPoolPatch` (interface): interface StatPoolPatch — Partial update applied without mutating the previous pool.
|
|
91
102
|
- `Stats` (interface): interface Stats<TStat extends string> — ⚠ undocumented
|
|
103
|
+
- `StatsSnapshot` (interface): interface StatsSnapshot<TStat extends string> — Complete plain-data state for a {@link Stats} runtime.
|
|
92
104
|
- `StatusApplicationOutcome` (interface): interface StatusApplicationOutcome — The result of one status application: the outcome, the resulting instance (if any), and the roll.
|
|
93
105
|
- `StatusApplicationSpec` (interface): interface StatusApplicationSpec — A serializable, effect-agnostic description of a status a hit tries to apply: an opaque `status` id the game routes to its own effect/DoT pipeline, a base landing `chance`, and the duration/ticks/magnitude/attribution/stacking data the resolver needs. The engine never interprets `status` — it is a reference, not a built-in condition.
|
|
94
106
|
- `StatusImmunity` (interface): interface StatusImmunity — Statuses a target cannot receive at all — the immunity half of application policy.
|
|
@@ -102,6 +114,12 @@
|
|
|
102
114
|
- `ThresholdMark` (interface): interface ThresholdMark — Generic numeric threshold-crossing tracker (#931).
|
|
103
115
|
- `ThresholdTracker` (interface): interface ThresholdTracker — A stateful crossing tracker over one numeric source.
|
|
104
116
|
- `ThresholdTrackerSnapshot` (interface): interface ThresholdTrackerSnapshot — Serializable tracker state for save/load.
|
|
117
|
+
- `VfxPreset` (interface): interface VfxPreset — A named visual flavor for a one-shot `combat.vfx` burst: the archetype (`kind`), a `0xRRGGBB` tint, and optional default `durationMs`/`radius`. Purely presentation — a preset never touches damage, range, or any authoritative value; it just answers "what does this attack look like" so a game does not hand-roll colors and archetypes.
|
|
118
|
+
- `VfxPresetName` (type): type VfxPresetName = keyof typeof vfxPresets — A named key into {@link vfxPresets} (`"arrow" | "fireball" | "lightning" | "web" | "slash" | "shield" | "heal" | ...`).
|
|
119
|
+
- `WeaponFireResult` (interface): interface WeaponFireResult<THit> — The result of a {@link WeaponRuntime.fire} attempt. On `"fired"`, `hits` is whatever the caller's raycast returned and `resolutions` holds the portable damage provenance for each hit that produced a {@link DamageHitInput}; on any blocked status both are empty and no round was spent.
|
|
120
|
+
- `WeaponFireStatus` (type): type WeaponFireStatus = "fired" | "cooling" | "empty" | "reloading" — Why a {@link WeaponRuntime.fire} attempt resolved the way it did.
|
|
121
|
+
- `WeaponRuntime` (interface): interface WeaponRuntime<TAim, THit> — A composed weapon fire controller: a {@link FireCadence} gate, an optional {@link Magazine}, the caller's raycast, and portable {@link resolveDamageHit} damage resolution wired together. The caller retains ownership of models, animations, muzzle flash, audio, input, camera, aiming, and the raycaster itself.
|
|
122
|
+
- `WeaponRuntimeConfig` (interface): interface WeaponRuntimeConfig<TAim, THit> — Configuration for {@link createWeaponRuntime}. Everything time/ammo-related is plain data; the two callbacks are where the caller keeps ownership of aiming, its own raycaster/projectile query, and how a hit maps to damage. There is deliberately no default weapon, projectile, or damage table here — those are game content.
|
|
105
123
|
- `activePhaseId` (function): function activePhaseId<TData>(state: EncounterState<TData>): string | null — The deepest active phase id — the completion cursor a HUD reads to label the current wave/phase — or null before start and once done.
|
|
106
124
|
- `advanceCombo` (function): function advanceCombo(input: AdvanceComboInput): AdvanceComboResult — ⚠ undocumented
|
|
107
125
|
- `advanceMotionCues` (function): function advanceMotionCues(cues: EntityRenderCues, speed: number, dt: number, tuning?: RenderCueTuning): EntityRenderCues — Advances `bobPhase` and decays `recoil` from a live `speed` sample (e.g. `groundSpeed(entity)`); leaves event-driven fields untouched.
|
|
@@ -109,7 +127,9 @@
|
|
|
109
127
|
- `applyRenderAnimationEvent` (function): function applyRenderAnimationEvent(cues: EntityRenderCues, event: string): EntityRenderCues — Applies a `entity.animation` event (`"fire"` / `"reload"` / `"reloadEnd"`, or any game-defined name) to the cue set. Unknown event names are a no-op.
|
|
110
128
|
- `applyRenderDeathEvent` (function): function applyRenderDeathEvent(cues: EntityRenderCues): EntityRenderCues — Marks the cue set dead after `entity.died`; sticky for the lifetime of the render component.
|
|
111
129
|
- `applyRenderHitEvent` (function): function applyRenderHitEvent(cues: EntityRenderCues): EntityRenderCues — Marks a `combat.hitReaction` pulse; the caller clears `hit` again after its own pulse window.
|
|
130
|
+
- `applyStatPoolDelta` (function): function applyStatPoolDelta<TOwnerId extends string, TStatId extends string>(access: StatPoolAccess<TOwnerId, TStatId>, ownerId: TOwnerId, statId: TStatId, amount: number): StatPoolAccessResult — Read, transition, and write a caller-owned pool through the structural adapter. Positive amounts increase the resource; negative amounts decrease it. The adapter receives a complete replacement value, never a hidden mutation.
|
|
112
131
|
- `attackMeta` (function): function attackMeta(tags: readonly AttackTag[], extra?: Omit<AttackMeta, "tags">): AttackMeta — ⚠ undocumented
|
|
132
|
+
- `changeStatPool` (function): function changeStatPool(pool: StatPool, amount: number): StatPoolChange — Pure bounded delta transition with the exact applied amount and boundary flags.
|
|
113
133
|
- `convergeShot` (function): function convergeShot(deps: ShotOriginDeps, from: string, aim: Aim, range: number, sightHit: (origin: EntityPosition, direction: EntityPosition) => EntityPosition | null, muzzleOffset?: EntityPosition): ResolvedShot | null — Resolves a `converge` shot with scene knowledge: fires from the gun muzzle but bends the direction so the shot passes through the aim point the shooter's eye ray covers. `sightHit` casts the eye ray and returns where it lands (first impact), or `null` to fall back to a point `range` metres down the sightline. A `{ origin, direction }` aim is passed through unchanged (nothing to converge).
|
|
114
134
|
- `counters` (function): function counters(meta: AttackMeta, move: CounterMove): boolean — ⚠ undocumented
|
|
115
135
|
- `createAbilityKit` (function): function createAbilityKit(configs: readonly AbilitySlotConfig[], options: AbilityKitOptions = {}): AbilityKit — A bar of cooldown-gated abilities the player fires by slot, tracking readiness and cooldown per ability.
|
|
@@ -125,17 +145,20 @@
|
|
|
125
145
|
- `createDefensiveWindow` (function): function createDefensiveWindow(config: DefensiveWindowConfig): DefensiveWindow — Open a timed defensive window — block, parry, or i-frames — and test incoming hits against it.
|
|
126
146
|
- `createDotField` (function): function createDotField(): DotField — Builds an empty {@link DotField}; `apply` DoTs onto it and drain damage each frame with `tick`.
|
|
127
147
|
- `createDownedState` (function): function createDownedState(config: DownedConfig): DownedState — A downed/bleed-out state that ticks toward death and that teammates can revive before the timer runs out.
|
|
128
|
-
- `createEffectSystem` (function): function createEffectSystem(deps: EffectSystemDeps): EffectSystem —
|
|
148
|
+
- `createEffectSystem` (function): function createEffectSystem(deps: EffectSystemDeps): EffectSystem — Resolve direct or area resource effects through caller-owned stat pools, including ordered absorption, restoration, modifiers, and lethal context.
|
|
129
149
|
- `createEncounterState` (function): function createEncounterState<TData>(config: EncounterConfig<TData>): EncounterState<TData> — Build the initial, serializable state for an encounter from its config. Deep-copies the authored phase tree (so later injection never mutates the config), verifies phase ids are unique, and leaves every node pending. Does not enter the first phase — call {@link startEncounter} for that.
|
|
130
150
|
- `createEventMeter` (function): function createEventMeter(config: EventMeterConfig): EventMeter — A heat/hype gauge that rises as tagged events land and cools between them, firing when it fills or breaks — the streak/overdrive meter shooters and fighters hand-roll.
|
|
151
|
+
- `createFireCadence` (function): function createFireCadence(config: FireCadenceConfig): FireCadence — Build a {@link FireCadence} rate gate. Reach for this instead of hand-tracking a `lastFiredAt` timestamp and comparing against a fire interval per game.
|
|
131
152
|
- `createImmunityWindow` (function): function createImmunityWindow(id = "immunity"): ImmunityWindow — A per-target immunity/invulnerability window as an ordinary damage policy — granted and cleared by state transitions (i-frames, phase invuln), rejecting damage while active. Deterministic (time is passed in) and serializable.
|
|
132
153
|
- `createMagazine` (function): function createMagazine(config: MagazineConfig): Magazine — Builds a {@link Magazine}: discrete loaded ammo, a timed reload, and reserve-pool interaction.
|
|
133
154
|
- `createProjectileSystem` (function): function createProjectileSystem(deps: ProjectileSystemDeps): ProjectileSystem — Spawn and advance projectiles each frame, resolving travel, lifetime, and hits.
|
|
134
155
|
- `createRegenShield` (function): function createRegenShield(config: RegenShieldConfig): RegenShield — Builds a {@link RegenShield} that suppresses regen for `regenDelayMs` after each hit.
|
|
135
156
|
- `createResourcePool` (function): function createResourcePool(config: ResourcePoolConfig): ResourcePool — A regenerating resource pool — mana, stamina, energy — that actions spend from and that refills over time.
|
|
136
157
|
- `createStaggerMeter` (function): function createStaggerMeter(config: StaggerMeterConfig): StaggerMeter — Build a stagger/poise gauge from landed hits toward a break threshold that staggers the target.
|
|
158
|
+
- `createStatPool` (function): function createStatPool(input: StatPoolInput): StatPool — Normalize caller data into a complete plain-data pool.
|
|
137
159
|
- `createStats` (function): function createStats<TStat extends string>(base: Record<TStat, number>, options?: CreateStatsOptions): Stats<TStat> — A stat block whose base values take stacking, timed buffs and debuffs, resolving the modified value on read.
|
|
138
160
|
- `createThresholdTracker` (function): function createThresholdTracker(config: ThresholdCrossingConfig): ThresholdTracker — Track a numeric source against named thresholds and emit ordered crossing events with direction, hysteresis, once/repeat policy, and skipped-threshold handling. Deterministic and serializable; drives phase transitions, armor breaks, resource warnings, and any other threshold consumer.
|
|
161
|
+
- `createWeaponRuntime` (function): function createWeaponRuntime<TAim, THit>(config: WeaponRuntimeConfig<TAim, THit>): WeaponRuntime<TAim, THit> — Compose a portable weapon fire controller from the existing generic primitives — a {@link FireCadence} gate, an optional {@link Magazine}, a caller-provided raycast, and portable {@link resolveDamageHit} damage resolution. No `GameContext`, entity store, renderer, or default weapon is involved; the caller owns aiming, its raycaster, and all presentation, and the result carries full damage provenance for authority to apply and replicate.
|
|
139
162
|
- `encounterProgress` (function): function encounterProgress<TData>(state: EncounterState<TData>): { completed: number; total: number; done: boolean; } — Progress across the whole tree: how many phases have completed out of the total node count, plus whether the encounter has finished. Counts injected phases.
|
|
140
163
|
- `eyeHeightFromColliders` (function): function eyeHeightFromColliders(set: EntityColliderSet | null | undefined): number — Eye height derived from a collider set: 90% of the tallest hitbox top, or the humanoid default when unknown.
|
|
141
164
|
- `filterOutcomeFor` (function): function filterOutcomeFor(outcome: AllocationOutcome, viewerId: string): AllocationOutcome — Project an allocation outcome for one viewer, enforcing replication authoritatively: private grants belonging to other recipients are dropped, and pools the viewer cannot claim (not eligible, or reserved for someone else) are hidden — so private rewards never leak across the wire while provenance on the viewer's own grants is preserved.
|
|
@@ -145,6 +168,7 @@
|
|
|
145
168
|
- `isBlockable` (function): function isBlockable(meta: AttackMeta): boolean — ⚠ undocumented
|
|
146
169
|
- `isDodgeable` (function): function isDodgeable(meta: AttackMeta): boolean — ⚠ undocumented
|
|
147
170
|
- `isParryable` (function): function isParryable(meta: AttackMeta): boolean — ⚠ undocumented
|
|
171
|
+
- `patchStatPool` (function): function patchStatPool(pool: StatPool, patch: StatPoolPatch): StatPool — Apply new bounds/current to a pool, clamping the result and leaving the input untouched.
|
|
148
172
|
- `phaseStatus` (function): function phaseStatus<TData>(state: EncounterState<TData>, id: string): PhaseStatus | null — The runtime status of a phase by id (pending/active/complete), or null if the id is unknown — for driving per-phase HUD ticks and objective checklists.
|
|
149
173
|
- `resistanceScale` (function): function resistanceScale<TCategory extends string = string, TProperty extends string = string>(matrix: ResistanceMatrix<TCategory, TProperty>, category: TCategory | string, targetProperties: readonly (TProperty | string)[]): number — ⚠ undocumented
|
|
150
174
|
- `resolveClaim` (function): function resolveClaim(pool: ClaimablePool, claimantId: string, options?: { nowMs?: number; private?: boolean }): ClaimOutcome — Resolve an authoritative claim against a pool. Idempotent: re-claiming an already-owned pool returns the same grants without re-awarding, a losing claimant gets no grants, and eligibility, reservation, and expiry are all enforced here — the authority, not UI hiding, decides ownership. Returns the updated (serializable) pool plus the grants owed.
|
|
@@ -157,10 +181,12 @@
|
|
|
157
181
|
- `resolveResistance` (function): function resolveResistance<TCategory extends string = string, TProperty extends string = string>(matrix: ResistanceMatrix<TCategory, TProperty>, category: TCategory | string, targetProperties: readonly (TProperty | string)[]): ResistanceResult — ⚠ undocumented
|
|
158
182
|
- `resolveShot` (function): function resolveShot(deps: ShotOriginDeps, from: string, aim: Aim, policy: ShotOriginPolicy = { kind: "eye" }): ResolvedShot | null — ⚠ undocumented
|
|
159
183
|
- `resolveStatusApplication` (function): function resolveStatusApplication(input: StatusApplicationInput): StatusApplicationOutcome — Resolve one status application: reject on immunity, roll landing chance against injected RNG, scale magnitude/duration by the matchup, then fold into any existing instance per the stacking policy. Deterministic given a seeded `rng`; pure over serializable data, so authority can run it and replicate only the returned `instance`.
|
|
184
|
+
- `resolveVfxPreset` (function): function resolveVfxPreset(name: string | undefined, overrides?: Partial<VfxPreset>): VfxPreset — Resolve a named visual flavor into a concrete `{ kind, color, durationMs?, radius? }`, with any provided `overrides` winning field by field. An unknown name resolves to {@link DEFAULT_VFX_PRESET} rather than throwing, so a flavor typo degrades to a visible spark. Used by `ctx.scene.entity.vfx({ preset })`; call it directly when you need the raw numbers (e.g. to seed a retained `vfxInstance` from the same vocabulary).
|
|
160
185
|
- `rollCheck` (function): function rollCheck(input: CheckInput, rng: () => number = Math.random): CheckResult — Resolve a tabletop-style pass/fail roll against a target number with modifiers and crit/fumble bands.
|
|
161
186
|
- `startEncounter` (function): function startEncounter<TData>(config: EncounterConfig<TData>, state: EncounterState<TData>, ctx: EncounterContext = {}): EncounterStep<TData> — Start a created encounter: enter the first root phase, descending to its first leaf, and return the initial enter/spawn events. A no-op (with no events) on an already-started or empty encounter. Mutates and returns `state`.
|
|
162
187
|
- `tierAt` (function): function tierAt(value: number, tiers: readonly MeterTier[]): string | null — The highest tier id whose `at` threshold `value` has reached, or `null` below every tier — the pure lookup `createAccumulatorMeter`/`createEventMeter` call on every `add`/`tick`.
|
|
163
188
|
- `updateEncounter` (function): function updateEncounter<TData>(config: EncounterConfig<TData>, state: EncounterState<TData>, dt: number, ctx: EncounterContext = {}): EncounterStep<TData> — Advance an encounter by `dt` seconds against the caller `ctx`. Accumulates time, then repeatedly: evaluates the cursor node's completion predicate; on completion, either re-runs its subtree (`repeat`) or marks it complete and advances to the next sibling — bubbling up to parent groups whose children are exhausted — entering the next chain and emitting enter/spawn/complete events. Emits a final `done` event when the last phase completes. Bounded per call by node count; mutates and returns `state`.
|
|
189
|
+
- `vfxPresets` (const): const vfxPresets: { readonly arrow: { readonly kind: "projectile"; readonly color: 14207392; }; readonly bolt: { readonly kind: "projectile"; readonly color: 16777215; }; readonly fireball: { readonly kind: "projectile"; readonly color: 16738842; readonly durationMs: 460; }; readonly firebolt: { rea… — Ready-made visual flavors for the things players actually shoot, swing, and cast — so `ctx.scene.entity.vfx({ preset: "arrow", from, to })` renders a visible bolt with zero tuning, and `"lightning"`, `"web"`, `"slash"`, `"shield"`, `"heal"`, `"explosion"` likewise just work. Each entry only picks a `kind` (`projectile | beam | nova | glow | spark`), a color, and a lifetime; it is visual vocabulary (like named CSS colors), not a gameplay archetype — combat numbers stay in the caller's own effect/ability data. Any field passed to `vfx()` overrides the preset, and unknown names fall back to `spark` so a flavor typo still shows *something* rather than nothing.
|
|
164
190
|
|
|
165
191
|
## @jgengine/core/combat/abilityKit
|
|
166
192
|
|
|
@@ -340,7 +366,7 @@
|
|
|
340
366
|
- `ReceiveMap` (type): type ReceiveMap = Record<string, ReceiveRule> — ⚠ undocumented
|
|
341
367
|
- `ReceiveRule` (interface): interface ReceiveRule — ⚠ undocumented
|
|
342
368
|
- `SingleTargetEffectInput` (interface): interface SingleTargetEffectInput — ⚠ undocumented
|
|
343
|
-
- `createEffectSystem` (function): function createEffectSystem(deps: EffectSystemDeps): EffectSystem —
|
|
369
|
+
- `createEffectSystem` (function): function createEffectSystem(deps: EffectSystemDeps): EffectSystem — Resolve direct or area resource effects through caller-owned stat pools, including ordered absorption, restoration, modifiers, and lethal context.
|
|
344
370
|
- `resolveAreaTargets` (function): function resolveAreaTargets(spatial: CombatSpatialDeps, input: AreaTargetInput, accept?: (instanceId: string) => boolean): AreaTarget[] — ⚠ undocumented
|
|
345
371
|
|
|
346
372
|
## @jgengine/core/combat/encounterSequence
|
|
@@ -390,6 +416,7 @@
|
|
|
390
416
|
- `Magazine` (interface): interface Magazine — A per-weapon magazine: discrete loaded rounds, a timed reload that refills from a reserve pool, and the reserve-pool interaction itself — the primitive that replaces hand-rolling mag size, reload delay, and reserve bookkeeping per game (#536.2).
|
|
391
417
|
- `MagazineConfig` (interface): interface MagazineConfig — Tuning for `createMagazine`: mag capacity, reload delay, and where reserve ammo is drawn from.
|
|
392
418
|
- `MagazineReserve` (interface): interface MagazineReserve — Draws ammo for a `Magazine`'s reload from wherever the reserve pool actually lives.
|
|
419
|
+
- `MagazineSnapshot` (interface): interface MagazineSnapshot — Complete serializable state for a {@link Magazine}; `reserve: null` means infinite reserve.
|
|
393
420
|
- `createMagazine` (function): function createMagazine(config: MagazineConfig): Magazine — Builds a {@link Magazine}: discrete loaded ammo, a timed reload, and reserve-pool interaction.
|
|
394
421
|
|
|
395
422
|
## @jgengine/core/combat/projectiles
|
|
@@ -516,6 +543,25 @@
|
|
|
516
543
|
- `ThresholdTrackerSnapshot` (interface): interface ThresholdTrackerSnapshot — Serializable tracker state for save/load.
|
|
517
544
|
- `createThresholdTracker` (function): function createThresholdTracker(config: ThresholdCrossingConfig): ThresholdTracker — Track a numeric source against named thresholds and emit ordered crossing events with direction, hysteresis, once/repeat policy, and skipped-threshold handling. Deterministic and serializable; drives phase transitions, armor breaks, resource warnings, and any other threshold consumer.
|
|
518
545
|
|
|
546
|
+
## @jgengine/core/combat/vfxPresets
|
|
547
|
+
|
|
548
|
+
- `DEFAULT_VFX_PRESET` (const): const DEFAULT_VFX_PRESET: VfxPresetName — The fallback flavor used when a `vfx()` call names an unknown preset — so a typo still shows a spark instead of nothing.
|
|
549
|
+
- `VfxPreset` (interface): interface VfxPreset — A named visual flavor for a one-shot `combat.vfx` burst: the archetype (`kind`), a `0xRRGGBB` tint, and optional default `durationMs`/`radius`. Purely presentation — a preset never touches damage, range, or any authoritative value; it just answers "what does this attack look like" so a game does not hand-roll colors and archetypes.
|
|
550
|
+
- `VfxPresetName` (type): type VfxPresetName = keyof typeof vfxPresets — A named key into {@link vfxPresets} (`"arrow" | "fireball" | "lightning" | "web" | "slash" | "shield" | "heal" | ...`).
|
|
551
|
+
- `resolveVfxPreset` (function): function resolveVfxPreset(name: string | undefined, overrides?: Partial<VfxPreset>): VfxPreset — Resolve a named visual flavor into a concrete `{ kind, color, durationMs?, radius? }`, with any provided `overrides` winning field by field. An unknown name resolves to {@link DEFAULT_VFX_PRESET} rather than throwing, so a flavor typo degrades to a visible spark. Used by `ctx.scene.entity.vfx({ preset })`; call it directly when you need the raw numbers (e.g. to seed a retained `vfxInstance` from the same vocabulary).
|
|
552
|
+
- `vfxPresets` (const): const vfxPresets: { readonly arrow: { readonly kind: "projectile"; readonly color: 14207392; }; readonly bolt: { readonly kind: "projectile"; readonly color: 16777215; }; readonly fireball: { readonly kind: "projectile"; readonly color: 16738842; readonly durationMs: 460; }; readonly firebolt: { rea… — Ready-made visual flavors for the things players actually shoot, swing, and cast — so `ctx.scene.entity.vfx({ preset: "arrow", from, to })` renders a visible bolt with zero tuning, and `"lightning"`, `"web"`, `"slash"`, `"shield"`, `"heal"`, `"explosion"` likewise just work. Each entry only picks a `kind` (`projectile | beam | nova | glow | spark`), a color, and a lifetime; it is visual vocabulary (like named CSS colors), not a gameplay archetype — combat numbers stay in the caller's own effect/ability data. Any field passed to `vfx()` overrides the preset, and unknown names fall back to `spark` so a flavor typo still shows *something* rather than nothing.
|
|
553
|
+
|
|
554
|
+
## @jgengine/core/combat/weaponFire
|
|
555
|
+
|
|
556
|
+
- `FireCadence` (interface): interface FireCadence — A minimal minimum-interval rate gate for a repeated action — weapon fire, ability spam, any "no faster than N per second" rule. Deterministic and serializable: its whole state is the elapsed time since the last action, exposed via {@link FireCadence.elapsedMs}.
|
|
557
|
+
- `FireCadenceConfig` (interface): interface FireCadenceConfig — Tuning for {@link createFireCadence}: the minimum interval between actions and whether it starts ready.
|
|
558
|
+
- `WeaponFireResult` (interface): interface WeaponFireResult<THit> — The result of a {@link WeaponRuntime.fire} attempt. On `"fired"`, `hits` is whatever the caller's raycast returned and `resolutions` holds the portable damage provenance for each hit that produced a {@link DamageHitInput}; on any blocked status both are empty and no round was spent.
|
|
559
|
+
- `WeaponFireStatus` (type): type WeaponFireStatus = "fired" | "cooling" | "empty" | "reloading" — Why a {@link WeaponRuntime.fire} attempt resolved the way it did.
|
|
560
|
+
- `WeaponRuntime` (interface): interface WeaponRuntime<TAim, THit> — A composed weapon fire controller: a {@link FireCadence} gate, an optional {@link Magazine}, the caller's raycast, and portable {@link resolveDamageHit} damage resolution wired together. The caller retains ownership of models, animations, muzzle flash, audio, input, camera, aiming, and the raycaster itself.
|
|
561
|
+
- `WeaponRuntimeConfig` (interface): interface WeaponRuntimeConfig<TAim, THit> — Configuration for {@link createWeaponRuntime}. Everything time/ammo-related is plain data; the two callbacks are where the caller keeps ownership of aiming, its own raycaster/projectile query, and how a hit maps to damage. There is deliberately no default weapon, projectile, or damage table here — those are game content.
|
|
562
|
+
- `createFireCadence` (function): function createFireCadence(config: FireCadenceConfig): FireCadence — Build a {@link FireCadence} rate gate. Reach for this instead of hand-tracking a `lastFiredAt` timestamp and comparing against a fire interval per game.
|
|
563
|
+
- `createWeaponRuntime` (function): function createWeaponRuntime<TAim, THit>(config: WeaponRuntimeConfig<TAim, THit>): WeaponRuntime<TAim, THit> — Compose a portable weapon fire controller from the existing generic primitives — a {@link FireCadence} gate, an optional {@link Magazine}, a caller-provided raycast, and portable {@link resolveDamageHit} damage resolution. No `GameContext`, entity store, renderer, or default weapon is involved; the caller owns aiming, its raycaster, and all presentation, and the result carries full damage provenance for authority to apply and replicate.
|
|
564
|
+
|
|
519
565
|
## @jgengine/core/stats/accumulatorMeter
|
|
520
566
|
|
|
521
567
|
- `AccumulatorMeter` (interface): interface AccumulatorMeter — ⚠ undocumented
|
|
@@ -540,10 +586,37 @@
|
|
|
540
586
|
- `CheckResult` (interface): interface CheckResult — ⚠ undocumented
|
|
541
587
|
- `rollCheck` (function): function rollCheck(input: CheckInput, rng: () => number = Math.random): CheckResult — Resolve a tabletop-style pass/fail roll against a target number with modifiers and crit/fumble bands.
|
|
542
588
|
|
|
589
|
+
## @jgengine/core/stats/spawnLevelStats
|
|
590
|
+
|
|
591
|
+
- `CreatureStatInstance` (interface): interface CreatureStatInstance<TStat extends string> — A single creature's serializable stat record — a reference to its species (`speciesId`), the current `level`, the per-stat count of distributed points, and how many post-capture domestic levels have been spent. Plain data: round-trips through JSON, save/load, and multiplayer sync. Resolve display values with {@link resolveSpawnStats}.
|
|
592
|
+
- `SpawnSpeciesDef` (type): type SpawnSpeciesDef<TStat extends string> = Record<TStat, SpawnStatDef> — A species' stat table: every stat the creature owns keyed to its {@link SpawnStatDef}. The key order is the deterministic order random points are distributed over, so a serialized species definition reproduces the same rolls under the same rng sequence.
|
|
593
|
+
- `SpawnStatDef` (interface): interface SpawnStatDef — Per-stat growth definition for one species. `base` is the level-1 value of the stat; `growth` is how much a single distributed point adds, expressed as a fraction of `base` — so a point on a `growth: 0.1` stat is worth +10% of base. The resolved value is `base * (1 + points * growth)`.
|
|
594
|
+
- `applyCaptureEffectiveness` (function): function applyCaptureEffectiveness<TStat extends string>(species: SpawnSpeciesDef<TStat>, instance: CreatureStatInstance<TStat>, effectiveness: number, rng: () => number): CaptureResult<TStat> — Apply a capture at the given effectiveness: compute bonus levels via {@link captureBonusLevels}, distribute those extra points randomly with the injected rng, and return the post-capture instance (level raised to the tamed total) alongside the granted bonus levels and tamed level. The input instance is not mutated.
|
|
595
|
+
- `captureBonusLevels` (function): function captureBonusLevels(level: number, effectiveness: number): number — Bonus levels granted by a capture at the given effectiveness: `floor(level * clamp01(effectiveness) / 2)`. A perfect (1.0) capture grants half the wild level; a botched (0) capture grants none. Effectiveness outside `[0,1]` clamps.
|
|
596
|
+
- `resolveSpawnStats` (function): function resolveSpawnStats<TStat extends string>(species: SpawnSpeciesDef<TStat>, instance: CreatureStatInstance<TStat>): Record<TStat, number> — Resolve an instance's live stat values from its distributed points: `value = base * (1 + points * growth)` per stat. Stats with zero points return their base.
|
|
597
|
+
- `restoreSpawnInstance` (function): function restoreSpawnInstance<TStat extends string>(data: CreatureStatInstance<TStat>): CreatureStatInstance<TStat> — Rehydrate a creature stat instance from decoded data (e.g. `JSON.parse` output), returning a fresh deep copy the caller owns. Inverse of {@link snapshotSpawnInstance}.
|
|
598
|
+
- `rollSpawnInstance` (function): function rollSpawnInstance<TStat extends string>(speciesId: string, species: SpawnSpeciesDef<TStat>, level: number, rng: () => number): CreatureStatInstance<TStat> — Roll a fresh wild creature at `level`: distribute `(level - 1)` points randomly across the species' stats using the injected rng and return a serializable {@link CreatureStatInstance}. Deterministic — the same rng sequence yields the same point spread. Levels below 1 clamp to 1 (no points). Use `seededRng` from `../random/rng` for a persisted, reproducible stream.
|
|
599
|
+
- `snapshotSpawnInstance` (function): function snapshotSpawnInstance<TStat extends string>(instance: CreatureStatInstance<TStat>): CreatureStatInstance<TStat> — Deep-copy an instance into a detached, serializable record — the transport/save counterpart of {@link restoreSpawnInstance}. Copies the points map so later edits don't leak into the snapshot.
|
|
600
|
+
- `spendDomesticLevel` (function): function spendDomesticLevel<TStat extends string>(instance: CreatureStatInstance<TStat>, stat: TStat, options?: SpendLevelOptions): SpendLevelResult<TStat> — Spend one earned post-capture level into `stat`, adding a single growth increment (one point) and raising both `level` and `domesticLevels`. When `maxDomesticLevels` is set and already reached, the spend is refused (`spent: false`) and the instance is returned untouched. Pure: returns a new instance rather than mutating the input.
|
|
601
|
+
|
|
543
602
|
## @jgengine/core/stats/statModifiers
|
|
544
603
|
|
|
545
604
|
- `CreateStatsOptions` (interface): interface CreateStatsOptions — ⚠ undocumented
|
|
546
605
|
- `StatModifier` (interface): interface StatModifier — ⚠ undocumented
|
|
547
606
|
- `StatModifierSet` (type): type StatModifierSet<TStat extends string> = Partial<Record<TStat, StatModifier>> — ⚠ undocumented
|
|
548
607
|
- `Stats` (interface): interface Stats<TStat extends string> — ⚠ undocumented
|
|
608
|
+
- `StatsSnapshot` (interface): interface StatsSnapshot<TStat extends string> — Complete plain-data state for a {@link Stats} runtime.
|
|
549
609
|
- `createStats` (function): function createStats<TStat extends string>(base: Record<TStat, number>, options?: CreateStatsOptions): Stats<TStat> — A stat block whose base values take stacking, timed buffs and debuffs, resolving the modified value on read.
|
|
610
|
+
|
|
611
|
+
## @jgengine/core/stats/statPool
|
|
612
|
+
|
|
613
|
+
- `StatPool` (interface): interface StatPool — Serializable state for any bounded named resource. The caller defines what the resource means.
|
|
614
|
+
- `StatPoolAccess` (interface): interface StatPoolAccess<TOwnerId extends string = string, TStatId extends string = string> — Structural bridge to caller-owned resource state. Implement it over an ECS, Redux/Zustand store, plain object, database-backed model, or JGengine's native entity stats without moving ownership into the SDK.
|
|
615
|
+
- `StatPoolAccessResult` (type): type StatPoolAccessResult = | ({ status: "ok" } & StatPoolChange) | { status: "rejected"; reason: string } — Outcome of changing a pool through {@link StatPoolAccess}.
|
|
616
|
+
- `StatPoolChange` (interface): interface StatPoolChange — Inspectable result of a bounded pool change.
|
|
617
|
+
- `StatPoolInput` (interface): interface StatPoolInput — Input used to create a normalized pool. `current` defaults to `max`; `min` defaults to zero.
|
|
618
|
+
- `StatPoolPatch` (interface): interface StatPoolPatch — Partial update applied without mutating the previous pool.
|
|
619
|
+
- `applyStatPoolDelta` (function): function applyStatPoolDelta<TOwnerId extends string, TStatId extends string>(access: StatPoolAccess<TOwnerId, TStatId>, ownerId: TOwnerId, statId: TStatId, amount: number): StatPoolAccessResult — Read, transition, and write a caller-owned pool through the structural adapter. Positive amounts increase the resource; negative amounts decrease it. The adapter receives a complete replacement value, never a hidden mutation.
|
|
620
|
+
- `changeStatPool` (function): function changeStatPool(pool: StatPool, amount: number): StatPoolChange — Pure bounded delta transition with the exact applied amount and boundary flags.
|
|
621
|
+
- `createStatPool` (function): function createStatPool(input: StatPoolInput): StatPool — Normalize caller data into a complete plain-data pool.
|
|
622
|
+
- `patchStatPool` (function): function patchStatPool(pool: StatPool, patch: StatPoolPatch): StatPool — Apply new bounds/current to a pool, clamping the result and leaving the input untouched.
|
|
@@ -12,6 +12,14 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
|
|
|
12
12
|
|
|
13
13
|
- `createAntiOneShotPolicy` (function) · `import { createAntiOneShotPolicy } from "@jgengine/core/combat"`
|
|
14
14
|
|
|
15
|
+
## capture-bonus-levels — convert wild level and capture effectiveness into bonus levels
|
|
16
|
+
|
|
17
|
+
- `captureBonusLevels` (function) · `import { captureBonusLevels } from "@jgengine/core/stats/spawnLevelStats"`
|
|
18
|
+
|
|
19
|
+
## capture-effectiveness-tame — apply capture effectiveness to grant and distribute bonus levels
|
|
20
|
+
|
|
21
|
+
- `applyCaptureEffectiveness` (function) · `import { applyCaptureEffectiveness } from "@jgengine/core/stats/spawnLevelStats"`
|
|
22
|
+
|
|
15
23
|
## cast-bar — run a channeled cast timer that movement or damage can interrupt
|
|
16
24
|
|
|
17
25
|
- `createCastRunner` (function) · `import { createCastRunner } from "@jgengine/core/combat"`
|
|
@@ -56,6 +64,10 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
|
|
|
56
64
|
|
|
57
65
|
- `rollCheck` (function) · `import { rollCheck } from "@jgengine/core/combat"`
|
|
58
66
|
|
|
67
|
+
## domestic-level-spend — spend an earned post-capture level into a chosen stat under a cap
|
|
68
|
+
|
|
69
|
+
- `spendDomesticLevel` (function) · `import { spendDomesticLevel } from "@jgengine/core/stats/spawnLevelStats"`
|
|
70
|
+
|
|
59
71
|
## dot-field — track stacking damage-over-time effects and drain damage each frame
|
|
60
72
|
|
|
61
73
|
- `createDotField` (function) · `import { createDotField } from "@jgengine/core/combat"`
|
|
@@ -108,6 +120,10 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
|
|
|
108
120
|
|
|
109
121
|
- `createEventMeter` (function) · `import { createEventMeter } from "@jgengine/core/combat"`
|
|
110
122
|
|
|
123
|
+
## fire-cadence — a serializable minimum-interval rate gate for repeated actions (weapon fire, ability spam)
|
|
124
|
+
|
|
125
|
+
- `createFireCadence` (function) · `import { createFireCadence } from "@jgengine/core/combat"`
|
|
126
|
+
|
|
111
127
|
## immunity-window — reject damage during a per-target invulnerability window installed by transitions
|
|
112
128
|
|
|
113
129
|
- `createImmunityWindow` (function) · `import { createImmunityWindow } from "@jgengine/core/combat"`
|
|
@@ -125,6 +141,10 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
|
|
|
125
141
|
|
|
126
142
|
- `createDefensiveWindow` (function) · `import { createDefensiveWindow } from "@jgengine/core/combat"`
|
|
127
143
|
|
|
144
|
+
## portable-stat-pool — apply deterministic bounded resource changes through a caller-owned stat adapter
|
|
145
|
+
|
|
146
|
+
- `applyStatPoolDelta` (function) · `import { applyStatPoolDelta } from "@jgengine/core/combat"`
|
|
147
|
+
|
|
128
148
|
## projectiles — spawn and advance projectiles with travel and hit resolution
|
|
129
149
|
|
|
130
150
|
- `createProjectileSystem` (function) · `import { createProjectileSystem } from "@jgengine/core/combat"`
|
|
@@ -147,6 +167,22 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
|
|
|
147
167
|
- `filterOutcomeFor` (function) · `import { filterOutcomeFor } from "@jgengine/core/combat"`
|
|
148
168
|
- `resolveClaim` (function) · `import { resolveClaim } from "@jgengine/core/combat"`
|
|
149
169
|
|
|
170
|
+
## spawn-instance-restore — rehydrate a creature stat instance from decoded snapshot data
|
|
171
|
+
|
|
172
|
+
- `restoreSpawnInstance` (function) · `import { restoreSpawnInstance } from "@jgengine/core/stats/spawnLevelStats"`
|
|
173
|
+
|
|
174
|
+
## spawn-instance-snapshot — deep-copy a creature stat instance into a serializable record
|
|
175
|
+
|
|
176
|
+
- `snapshotSpawnInstance` (function) · `import { snapshotSpawnInstance } from "@jgengine/core/stats/spawnLevelStats"`
|
|
177
|
+
|
|
178
|
+
## spawn-level-roll — distribute a wild creature's spawn level into random per-stat points
|
|
179
|
+
|
|
180
|
+
- `rollSpawnInstance` (function) · `import { rollSpawnInstance } from "@jgengine/core/stats/spawnLevelStats"`
|
|
181
|
+
|
|
182
|
+
## spawn-stat-values — resolve a creature's per-stat values from its distributed points
|
|
183
|
+
|
|
184
|
+
- `resolveSpawnStats` (function) · `import { resolveSpawnStats } from "@jgengine/core/stats/spawnLevelStats"`
|
|
185
|
+
|
|
150
186
|
## stagger-meter — accumulate an ailment buildup (bleed, freeze) until it procs
|
|
151
187
|
|
|
152
188
|
- `createBuildupMeter` (function) · `import { createBuildupMeter } from "@jgengine/core/combat"`
|
|
@@ -156,14 +192,38 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
|
|
|
156
192
|
|
|
157
193
|
- `createStats` (function) · `import { createStats } from "@jgengine/core/combat"`
|
|
158
194
|
|
|
195
|
+
## stat-pool — create a serializable current/min/max pool for any caller-named resource
|
|
196
|
+
|
|
197
|
+
- `createStatPool` (function) · `import { createStatPool } from "@jgengine/core/combat"`
|
|
198
|
+
|
|
199
|
+
## stat-pool-change — immutably increase or decrease any named bounded resource with clamp evidence
|
|
200
|
+
|
|
201
|
+
- `changeStatPool` (function) · `import { changeStatPool } from "@jgengine/core/combat"`
|
|
202
|
+
|
|
203
|
+
## stat-pool-patch — immutably retune a bounded resource's current value or bounds
|
|
204
|
+
|
|
205
|
+
- `patchStatPool` (function) · `import { patchStatPool } from "@jgengine/core/combat"`
|
|
206
|
+
|
|
159
207
|
## status-application — resolve a data-defined status application with chance, matchup scaling, and stacking policy
|
|
160
208
|
|
|
161
209
|
- `resolveStatusApplication` (function) · `import { resolveStatusApplication } from "@jgengine/core/combat"`
|
|
162
210
|
|
|
163
|
-
## status-effects —
|
|
211
|
+
## status-effects — commit direct or area effects through caller-owned stat pools with ordered spillover and lethal results
|
|
164
212
|
|
|
165
213
|
- `createEffectSystem` (function) · `import { createEffectSystem } from "@jgengine/core/combat"`
|
|
166
214
|
|
|
167
215
|
## threshold-crossings — emit ordered crossing events as a numeric source passes named thresholds with hysteresis and once/repeat policy
|
|
168
216
|
|
|
169
217
|
- `createThresholdTracker` (function) · `import { createThresholdTracker } from "@jgengine/core/combat"`
|
|
218
|
+
|
|
219
|
+
## vfx-preset-resolve — turn a named attack flavor into concrete vfx kind/color/duration with per-field overrides
|
|
220
|
+
|
|
221
|
+
- `resolveVfxPreset` (function) · `import { resolveVfxPreset } from "@jgengine/core/combat"`
|
|
222
|
+
|
|
223
|
+
## vfx-presets — render a named attack visual (arrow, fireball, lightning, web, slash, shield, heal, explosion) in one call
|
|
224
|
+
|
|
225
|
+
- `vfxPresets` (const) · `import { vfxPresets } from "@jgengine/core/combat"`
|
|
226
|
+
|
|
227
|
+
## weapon-runtime — compose cadence, magazine, a caller-owned raycast, and portable damage resolution into a fire controller
|
|
228
|
+
|
|
229
|
+
- `createWeaponRuntime` (function) · `import { createWeaponRuntime } from "@jgengine/core/combat"`
|