@jgengine/core 0.14.0 → 0.15.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 +500 -1
- package/dist/ai/difficulty.d.ts +154 -0
- package/dist/ai/difficulty.js +194 -0
- package/dist/ai/driver.d.ts +107 -0
- package/dist/ai/driver.js +175 -0
- package/dist/ai/flock.js +13 -23
- package/dist/ai/laneSelect.js +2 -1
- package/dist/ai/mobBrain.js +2 -1
- package/dist/ai/waveRunner.d.ts +81 -0
- package/dist/ai/waveRunner.js +104 -0
- package/dist/audio/musicState.d.ts +47 -0
- package/dist/audio/musicState.js +38 -0
- package/dist/audio/stepCadence.d.ts +47 -0
- package/dist/audio/stepCadence.js +29 -0
- package/dist/audio/synth.d.ts +12 -0
- package/dist/authoring.d.ts +6 -4
- package/dist/authoring.js +6 -4
- package/dist/combat/castRunner.d.ts +13 -1
- package/dist/combat/castRunner.js +5 -1
- package/dist/combat/comboMeter.d.ts +140 -0
- package/dist/combat/comboMeter.js +215 -0
- package/dist/combat/comboPoints.d.ts +11 -0
- package/dist/combat/comboPoints.js +11 -2
- package/dist/combat/damageResolution.d.ts +1 -1
- package/dist/combat/defensiveWindow.d.ts +5 -0
- package/dist/combat/effects.d.ts +24 -0
- package/dist/combat/effects.js +6 -1
- package/dist/combat/projectiles.d.ts +6 -0
- package/dist/combat/projectiles.js +2 -2
- package/dist/combat/regenShield.d.ts +40 -2
- package/dist/combat/regenShield.js +66 -18
- package/dist/combat/resourcePool.d.ts +19 -0
- package/dist/combat/resourcePool.js +20 -2
- package/dist/combat/shotOrigin.d.ts +5 -0
- package/dist/combat/statusApplication.d.ts +1 -1
- package/dist/combat/statusApplication.js +2 -1
- package/dist/combat/statusEffectView.d.ts +56 -0
- package/dist/combat/statusEffectView.js +52 -0
- package/dist/combat.d.ts +4 -2
- package/dist/combat.js +2 -0
- package/dist/devtools/fallbackSeams.d.ts +3 -2
- package/dist/devtools/fallbackSeams.js +1 -1
- package/dist/devtools/textureErrors.d.ts +40 -0
- package/dist/devtools/textureErrors.js +68 -0
- package/dist/economy/shopStock.d.ts +110 -0
- package/dist/economy/shopStock.js +157 -0
- package/dist/economy/wallet.d.ts +6 -0
- package/dist/economy/wallet.js +1 -0
- package/dist/game/achievements.d.ts +80 -0
- package/dist/game/achievements.js +124 -0
- package/dist/game/cameraConfig.d.ts +7 -0
- package/dist/game/codex.d.ts +60 -0
- package/dist/game/codex.js +89 -0
- package/dist/game/credits.d.ts +36 -0
- package/dist/game/credits.js +0 -0
- package/dist/game/defineGame.d.ts +28 -3
- package/dist/game/defineGame.js +5 -0
- package/dist/game/dialogueGraph.d.ts +116 -0
- package/dist/game/dialogueGraph.js +103 -0
- package/dist/game/eventTicker.d.ts +95 -0
- package/dist/game/eventTicker.js +91 -0
- package/dist/game/events.d.ts +24 -5
- package/dist/game/events.js +18 -0
- package/dist/game/gamePhase.d.ts +1 -1
- package/dist/game/gamePhase.js +1 -1
- package/dist/game/leaderboardRank.d.ts +71 -0
- package/dist/game/leaderboardRank.js +76 -0
- package/dist/game/lootTable.d.ts +10 -1
- package/dist/game/lootTable.js +4 -2
- package/dist/game/notifications.d.ts +57 -0
- package/dist/game/notifications.js +107 -0
- package/dist/game/playableGame.d.ts +39 -2
- package/dist/game/quest.d.ts +26 -0
- package/dist/game/quest.js +31 -0
- package/dist/game/runDraft.js +2 -1
- package/dist/game/saveSlots.d.ts +102 -0
- package/dist/game/saveSlots.js +136 -0
- package/dist/game/talentTreeView.d.ts +106 -0
- package/dist/game/talentTreeView.js +114 -0
- package/dist/game/worldItem.js +2 -1
- package/dist/gameplay.d.ts +15 -4
- package/dist/gameplay.js +13 -2
- package/dist/i18n/i18n.d.ts +51 -0
- package/dist/i18n/i18n.js +82 -0
- package/dist/input/axisInput.d.ts +1 -1
- package/dist/input/axisInput.js +18 -2
- package/dist/input/rebindSession.d.ts +141 -0
- package/dist/input/rebindSession.js +235 -0
- package/dist/input/touchControlsMode.d.ts +16 -0
- package/dist/input/touchControlsMode.js +23 -0
- package/dist/input/touchScheme.d.ts +30 -1
- package/dist/input/touchScheme.js +31 -1
- package/dist/interaction/promptRegistry.d.ts +78 -0
- package/dist/interaction/promptRegistry.js +130 -0
- package/dist/inventory/storageTier.js +3 -2
- package/dist/meta/changelog.d.ts +1 -1
- package/dist/meta/changelog.js +145 -1
- package/dist/movement/movementModel.d.ts +26 -3
- package/dist/movement/movementModel.js +121 -15
- package/dist/movement/playerMovement.js +161 -25
- package/dist/physics/drivableVehicle.js +3 -1
- package/dist/physics/kinematicVehicle.d.ts +56 -1
- package/dist/physics/kinematicVehicle.js +99 -10
- package/dist/physics/vehicleObstacles.js +19 -0
- package/dist/random/resolveRng.d.ts +14 -0
- package/dist/random/resolveRng.js +31 -0
- package/dist/render/postProcessing.d.ts +12 -1
- package/dist/runtime/cameraDirector.d.ts +2 -2
- package/dist/runtime/context/combat.js +8 -0
- package/dist/runtime/gameContext.js +6 -1
- package/dist/runtime/gameContextTypes.d.ts +18 -0
- package/dist/runtime/inputSnapshot.d.ts +10 -1
- package/dist/runtime/inputSnapshot.js +13 -1
- package/dist/runtime/runtimeSave.d.ts +3 -3
- package/dist/runtime/runtimeSave.js +11 -2
- package/dist/scene/assetDiagnostics.js +2 -2
- package/dist/scene/autoTarget.js +2 -1
- package/dist/scene/captureCheck.js +3 -2
- package/dist/scene/entityStore.d.ts +4 -1
- package/dist/scene/entityStore.js +3 -0
- package/dist/scene/objectStore.d.ts +10 -0
- package/dist/scene/objectStore.js +29 -6
- package/dist/scene/sceneKinds.d.ts +18 -0
- package/dist/scene/sceneKinds.js +19 -0
- package/dist/scene/sequenceDirector.d.ts +110 -0
- package/dist/scene/sequenceDirector.js +146 -0
- package/dist/session/roles.js +3 -2
- package/dist/settings/settingsModel.d.ts +1 -0
- package/dist/settings/settingsModel.js +1 -0
- package/dist/stats/rollCheck.js +4 -2
- package/dist/time/dayNightCycle.d.ts +114 -0
- package/dist/time/dayNightCycle.js +208 -0
- package/dist/time/timerSet.d.ts +132 -0
- package/dist/time/timerSet.js +243 -0
- package/dist/ui/accessibility.d.ts +51 -0
- package/dist/ui/accessibility.js +83 -0
- package/dist/ui/coachMarks.d.ts +99 -0
- package/dist/ui/coachMarks.js +126 -0
- package/dist/ui/floatingText.d.ts +114 -0
- package/dist/ui/floatingText.js +203 -0
- package/dist/ui/modalStack.d.ts +143 -0
- package/dist/ui/modalStack.js +160 -0
- package/dist/ui/objectiveBanner.d.ts +123 -0
- package/dist/ui/objectiveBanner.js +162 -0
- package/dist/ui/photoMode.d.ts +32 -0
- package/dist/ui/photoMode.js +51 -0
- package/dist/ui/radialMenu.d.ts +47 -0
- package/dist/ui/radialMenu.js +74 -0
- package/dist/ui/screenMarkers.d.ts +128 -0
- package/dist/ui/screenMarkers.js +118 -0
- package/dist/ui.d.ts +8 -0
- package/dist/ui.js +8 -0
- package/dist/vfx/cameraShake.d.ts +97 -0
- package/dist/vfx/cameraShake.js +136 -0
- package/dist/vfx/damageDirection.d.ts +102 -0
- package/dist/vfx/damageDirection.js +188 -0
- package/dist/vfx/particles.d.ts +103 -0
- package/dist/vfx/particles.js +256 -0
- package/dist/vfx/screenEffects.d.ts +149 -0
- package/dist/vfx/screenEffects.js +191 -0
- package/dist/world/authoredObjects.d.ts +18 -0
- package/dist/world/authoredObjects.js +21 -0
- package/dist/world/authoredSpawn.js +19 -0
- package/dist/world/buildingLots.d.ts +54 -11
- package/dist/world/buildingLots.js +116 -30
- package/dist/world/cityBlocks.d.ts +45 -0
- package/dist/world/cityBlocks.js +159 -0
- package/dist/world/cityContent.d.ts +46 -2
- package/dist/world/cityContent.js +160 -2
- package/dist/world/cityGenerator.d.ts +261 -23
- package/dist/world/cityGenerator.js +643 -33
- package/dist/world/cityGeometry.d.ts +20 -0
- package/dist/world/cityGeometry.js +91 -0
- package/dist/world/cityKind.js +1 -44
- package/dist/world/fastTravel.d.ts +64 -0
- package/dist/world/fastTravel.js +108 -0
- package/dist/world/features.d.ts +16 -0
- package/dist/world/features.js +2 -0
- package/dist/world/grounded.d.ts +11 -0
- package/dist/world/grounded.js +12 -0
- package/dist/world/mapAnnotations.d.ts +75 -0
- package/dist/world/mapAnnotations.js +139 -0
- package/dist/world/markers.js +1 -0
- package/dist/world/resourceNode.d.ts +1 -1
- package/dist/world/resourceNode.js +2 -1
- package/dist/world/roads.d.ts +294 -5
- package/dist/world/roads.js +1262 -21
- package/dist/world/sharedAnnotations.d.ts +84 -0
- package/dist/world/sharedAnnotations.js +76 -0
- package/dist/world/spawnOverride.d.ts +37 -0
- package/dist/world/spawnOverride.js +50 -0
- package/dist/world/streetGenerator.d.ts +60 -11
- package/dist/world/streetGenerator.js +1786 -129
- package/dist/world/terrain.d.ts +1 -0
- package/dist/world/terrain.js +2 -0
- package/dist/world/waypoints.d.ts +63 -0
- package/dist/world/waypoints.js +137 -0
- package/dist/world.d.ts +17 -2
- package/dist/world.js +17 -2
- package/package.json +1 -1
- package/skills/ce-handoff/SKILL.md +149 -0
- package/skills/game-design/SKILL.md +2 -0
- package/skills/jgengine/SKILL.md +3 -1
- package/skills/jgengine/api.md +17 -7
- package/skills/jgengine/capabilities.md +12 -0
- package/skills/jgengine/recipes/minimal-game.md +7 -4
- package/skills/jgengine-combat/api.md +40 -4
- package/skills/jgengine-combat/capabilities.md +12 -0
- package/skills/jgengine-combat/reference.md +2 -0
- package/skills/jgengine-gameplay/api.md +212 -11
- package/skills/jgengine-gameplay/capabilities.md +66 -1
- package/skills/jgengine-world/api.md +397 -11
- package/skills/jgengine-world/capabilities.md +123 -2
- package/skills/jgengine-world/reference.md +15 -1
package/skills/jgengine/api.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
- `CHANGELOG` (const): const CHANGELOG: Record<string, ChangelogEntry> — Per-version engine changelog keyed by semver string (e.g. `"0.10.0"`).
|
|
8
8
|
- `ChangelogEntry` (interface): interface ChangelogEntry — One release's migrate steps plus added/changed/removed notes (typed mirror of CHANGELOG.md).
|
|
9
|
-
- `VERSION` (const): const VERSION: "0.
|
|
9
|
+
- `VERSION` (const): const VERSION: "0.15.0" — Installed `@jgengine/core` semver — compare against {@link CHANGELOG} keys when migrating.
|
|
10
10
|
|
|
11
11
|
## @jgengine/core/authoring
|
|
12
12
|
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
- `AuthoredProvenance` (interface): interface AuthoredProvenance — A first-class entry in the scene document — the editor fully owns and persists it.
|
|
15
15
|
- `Drop` (interface): interface Drop — A resolved loot outcome — one item or currency grant with its rolled count.
|
|
16
16
|
- `GameDefinition` (interface): interface GameDefinition<TAssetRef extends ModelAssetRef = ModelAssetRef, TMultiplayer = unknown> — Fully-resolved game description produced by {@link defineGameDefinition} — assets, scene, and opted-in subsystems.
|
|
17
|
-
- `GameDefinitionConfig` (type): type GameDefinitionConfig<TAssetRef extends ModelAssetRef = ModelAssetRef, TMultiplayer = unknown> = Omit<GameDefinition<TAssetRef, TMultiplayer>, "scene" | "assets"> & { assets?: AssetCatalog<TAssetRef>; } — Input to {@link defineGameDefinition} — a `GameDefinition` with `scene` derived and `assets` optional.
|
|
17
|
+
- `GameDefinitionConfig` (type): type GameDefinitionConfig<TAssetRef extends ModelAssetRef = ModelAssetRef, TMultiplayer = unknown> = Omit<GameDefinition<TAssetRef, TMultiplayer>, "scene" | "assets" | "lifecycle"> & { assets?: AssetCatalog<TAssetRef>; /** * The game's run-phase story — a {@link LifecycleConfig} or the `"always-live… — Input to {@link defineGameDefinition} — a `GameDefinition` with `scene` derived and `assets` optional.
|
|
18
18
|
- `GameLoop` (interface): interface GameLoop<TContext = unknown> — Lifecycle hooks a game implements to drive init, per-tick simulation, and player join/leave.
|
|
19
19
|
- `GameServerConfig` (type): type GameServerConfig = "persistent" | { mode: string; [key: string]: unknown } — Hosting mode for a game's multiplayer server: `"persistent"`, or a custom mode with its own options.
|
|
20
20
|
- `GeneratedProvenance` (interface): interface GeneratedProvenance — An object derived from an authored document object — instances scattered from a painted layer, walls extruded from an authored footprint. Edits belong on the source object, not the generated instance.
|
|
@@ -125,7 +125,7 @@
|
|
|
125
125
|
|
|
126
126
|
## @jgengine/core/devtools/fallbackSeams
|
|
127
127
|
|
|
128
|
-
- `FallbackCause` (type): type FallbackCause = "omittedMapping" | "unpulledPack" | "noScene" — Why a seam fell back: `omittedMapping` (no mapping supplied — often intended), `unpulledPack` (a mapping was supplied but its asset pack is not pulled/indexed), `noScene` (nothing authored — e.g. no environment component).
|
|
128
|
+
- `FallbackCause` (type): type FallbackCause = "omittedMapping" | "unpulledPack" | "noScene" | "renderError" — Why a seam fell back: `omittedMapping` (no mapping supplied — often intended), `unpulledPack` (a mapping was supplied but its asset pack is not pulled/indexed), `noScene` (nothing authored — e.g. no environment component), `renderError` (authored content was found but threw while rendering — always a defect).
|
|
129
129
|
- `FallbackSeam` (type): type FallbackSeam = "ground" | "entity" | "object" | "scatter" — Render seams that can resolve to a placeholder FALLBACK instead of authored content: `ground` (default green terrain), `entity`/`object` (primitive capsule/box actors), `scatter` (stylized proxy foliage).
|
|
130
130
|
- `FallbackSeamCounts` (type): type FallbackSeamCounts = Record<FallbackSeam, Record<FallbackCause, number>> — A per-seam, per-cause count table. Serializable, allocation-stable (keys never change).
|
|
131
131
|
- `FallbackSeamsReport` (type): type FallbackSeamsReport = Partial<Record<FallbackSeam, Partial<Record<FallbackCause, number>>>> — Non-zero-only view of {@link FallbackSeamCounts} returned by {@link fallbackSeamsSnapshot}.
|
|
@@ -163,6 +163,14 @@
|
|
|
163
163
|
- `SaveEndpointRequest` (type): type SaveEndpointRequest = | { kind: "editor-document"; gameId: string; json: string } | { kind: "tunables"; gameId: string; deltas: readonly { table: string; key: string; value: unknown }[]; } — One write request the dev save endpoint accepts: a scene document or tunable deltas.
|
|
164
164
|
- `SaveEndpointResponse` (interface): interface SaveEndpointResponse — Result envelope the dev save endpoint returns for every write request.
|
|
165
165
|
|
|
166
|
+
## @jgengine/core/devtools/textureErrors
|
|
167
|
+
|
|
168
|
+
- `TextureLoadError` (interface): interface TextureLoadError — One texture (or other GLB sub-resource) that failed to load, plus how many times a load for that URL errored. Serializable so it flows through the `debug_snapshot` RPC exactly like {@link import("./fallbackSeams").FallbackSeamsReport}.
|
|
169
|
+
- `armTextureErrors` (function): function armTextureErrors(on: boolean): void — Arm or disarm the texture-load-error diagnostic. Off by default; the shell arms it only when devtools is enabled (dev builds), so production is a pure no-op. Toggling clears the tally so a fresh observation starts empty and the opt-out path reports nothing.
|
|
170
|
+
- `reportTextureLoadError` (function): function reportTextureLoadError(url: string): void — Record that a sub-resource load ERRORED for `url` (called from the shared GLB loading manager's `onError`, which fires for GLTF textures/images whose fetch 404s or otherwise fails — the failure the whole-model fallback probe never sees because the model itself still resolves). A pure, allocation-free no-op when disarmed. On the armed path it also emits ONE deduped devtools warn line per newly-seen failure set so a texture-404'd scene is loud, not silent.
|
|
171
|
+
- `resetTextureErrors` (function): function resetTextureErrors(): void — Clear the texture-error tally without changing the armed state. Used to bracket a fresh observation (e.g. between scenes or in tests). No-op when disarmed.
|
|
172
|
+
- `textureErrorsSnapshot` (function): function textureErrorsSnapshot(): TextureLoadError[] — Snapshot the current texture-load-error tally as a compact, serializable list (empty when nothing failed). Flows into the devtools `textureErrors` probe and the `debug_snapshot` RPC so `jgengine-verify` can treat a non-empty set exactly like a model fallback: content that resolved but is visibly broken.
|
|
173
|
+
|
|
166
174
|
## @jgengine/core/devtools/transformTunables
|
|
167
175
|
|
|
168
176
|
- `TunableTransformResult` (interface): interface TunableTransformResult — ⚠ undocumented
|
|
@@ -220,7 +228,7 @@
|
|
|
220
228
|
|
|
221
229
|
- `CHANGELOG` (const): const CHANGELOG: Record<string, ChangelogEntry> — Per-version engine changelog keyed by semver string (e.g. `"0.10.0"`).
|
|
222
230
|
- `ChangelogEntry` (interface): interface ChangelogEntry — One release's migrate steps plus added/changed/removed notes (typed mirror of CHANGELOG.md).
|
|
223
|
-
- `VERSION` (const): const VERSION: "0.
|
|
231
|
+
- `VERSION` (const): const VERSION: "0.15.0" — Installed `@jgengine/core` semver — compare against {@link CHANGELOG} keys when migrating.
|
|
224
232
|
|
|
225
233
|
## @jgengine/core/runtime/adapter
|
|
226
234
|
|
|
@@ -248,7 +256,7 @@
|
|
|
248
256
|
## @jgengine/core/runtime/cameraDirector
|
|
249
257
|
|
|
250
258
|
- `CameraDirector` (interface): interface CameraDirector — ⚠ undocumented
|
|
251
|
-
- `ChaseCameraTuning` (type): type ChaseCameraTuning = Partial< Pick<ChaseCameraConfig, "distance" | "height" | "lookHeight" | "springDamping" | "fov" | "lead" | "bank"> > — Runtime patch over the static `camera.chase` config — distance/height/fov retuning from gameplay events (#286.11).
|
|
259
|
+
- `ChaseCameraTuning` (type): type ChaseCameraTuning = Partial< Pick<ChaseCameraConfig, "distance" | "height" | "lookHeight" | "springDamping" | "fov" | "lead" | "bank" | "shakePerSpeed" | "velocityYaw" | "yawResponse"> > — Runtime patch over the static `camera.chase` config — distance/height/fov retuning from gameplay events (#286.11), or a whole driving-feel overlay (speed→FOV, lead, bank, speed shake, drift-lag) applied only while a vehicle is piloted (#1299).
|
|
252
260
|
|
|
253
261
|
## @jgengine/core/runtime/commandRunner
|
|
254
262
|
|
|
@@ -414,9 +422,9 @@
|
|
|
414
422
|
|
|
415
423
|
## @jgengine/core/runtime/runtimeSave
|
|
416
424
|
|
|
417
|
-
- `RuntimeSave` (interface): interface RuntimeSave — Whole-world save/load bound to a live world and a pluggable backend. `save()` captures `target.snapshot()` and writes it; `load()` reads it back and `target.hydrate()`s the whole world. In `autosave` mode it also writes on a
|
|
425
|
+
- `RuntimeSave` (interface): interface RuntimeSave — Whole-world save/load bound to a live world and a pluggable backend. `save()` captures `target.snapshot()` and writes it; `load()` reads it back and `target.hydrate()`s the whole world. In `autosave` mode it also writes on a trailing timer while the world keeps changing. Named slots, versioned migration, and offline↔cloud (backend swap) all come for free from the underlying save store.
|
|
418
426
|
- `RuntimeSaveConfig` (interface): interface RuntimeSaveConfig — How {@link createRuntimeSave} is wired — the live world `target`, the `backend` it persists through, and optional mode/slot/versioning/cadence knobs.
|
|
419
|
-
- `RuntimeSaveMode` (type): type RuntimeSaveMode = "autosave" | "manual" — `"autosave"` writes a fresh capture on a
|
|
427
|
+
- `RuntimeSaveMode` (type): type RuntimeSaveMode = "autosave" | "manual" — `"autosave"` writes a fresh capture on a trailing timer while the world changes (at most once per `autosaveMs`, so a never-idle world still persists); `"manual"` writes only on an explicit `save()`/`checkpoint()` — the save-point / quest-trigger model.
|
|
420
428
|
- `RuntimeSaveOptions` (type): type RuntimeSaveOptions = Omit<RuntimeSaveConfig, "target"> — {@link RuntimeSaveConfig} without `target` — what a host (`createGameContext`) accepts to build `ctx.game.save` and bind it to the context itself.
|
|
421
429
|
- `RuntimeSaveTarget` (interface): interface RuntimeSaveTarget — The narrow slice of a live `GameContext` a runtime save reads and writes — a `GameContext` satisfies it directly (`ctx.snapshot`/`ctx.hydrate`/`ctx.subscribe`). Depending on this instead of the full context keeps the save controller a deep, decoupled module: it captures and restores the *whole* opted-in world without knowing any subsystem.
|
|
422
430
|
- `createRuntimeSave` (function): function createRuntimeSave(config: RuntimeSaveConfig): RuntimeSave — Bridge a live world to a pluggable save backend: whole-state capture/restore with autosave, save points, named slots, and versioned migration — the same call for offline (localStorage) and cloud (Convex), only the `backend` differs. The game keeps control of *when* it saves (the `mode` plus explicit `checkpoint()` calls from quests/areas) and *when* it restores (`load()` on boot), so any save mechanic — continuous autosave, manual save points, checkpoint triggers — is expressible without new engine code.
|
|
@@ -506,6 +514,7 @@
|
|
|
506
514
|
|
|
507
515
|
- `Clock` (function): function Clock({ format, showDay, controls, style, className, }: { format?: "24h" | "12h"; showDay?: boolean; controls?: boolean; style?: CSSProperties; className?: string; }): JSX.Element — A time-of-day clock reading the sim calendar — `Day N · HH:MM`, 24h or 12h. `controls` adds pause + the game's speed multipliers as clickable pills (the "fast-forward" bar), off by default so a game opts into letting the player scrub time.
|
|
508
516
|
- `Coins` (function): function Coins({ currencyId, icon, style, className, }: { currencyId: string; icon?: ReactNode; style?: CSSProperties; className?: string; }): JSX.Element — A currency counter — an icon (emoji/char, default a coin) plus the live amount for `currencyId`. *
|
|
517
|
+
- `DEFAULT_WALK_CODES` (const): const DEFAULT_WALK_CODES: { readonly moveForward: readonly ["KeyW"]; readonly moveBack: readonly ["KeyS"]; readonly moveLeft: readonly ["KeyA"]; readonly moveRight: readonly ["KeyD"]; readonly jump: readonly ["Space"]; } — Default keyboard codes for the shell walk controller (WASD + Space). Use as the base of `defineGame({ input: { ...DEFAULT_WALK_CODES, interact: ["KeyE"] } })` instead of re-typing the same five bindings in every game.
|
|
509
518
|
- `EditorCatalogDefinition` (interface): interface EditorCatalogDefinition — Game-exported catalog definition: a `ParamSchema` plus default entries. Schemas stay in code; entry values merge into `document.catalogs` and are what the editor/RPC edits and saves.
|
|
510
519
|
- `EditorDocument` (interface): interface EditorDocument — The full authored scene: every marker, volume, path, note, and sculpted terrain for a game.
|
|
511
520
|
- `EditorSummonModule` (interface): interface EditorSummonModule — Structural shape of the module `GameHost`'s `editor` loader resolves — `import("@jgengine/editor")` satisfies it.
|
|
@@ -530,6 +539,7 @@
|
|
|
530
539
|
- `defineSystem` (function): function defineSystem(definition: SystemDefinition): SystemDefinition — Declare a composable game system. Pure data + hooks — the engine compiles the schedule and installs lifecycle when the game boots.
|
|
531
540
|
- `environment` (function): function environment(config?: EnvironmentWorldConfig): EnvironmentWorldFeature — Composes an `environment()` feature from terrain, sky, weather, vegetation, water, structures, roads, and pads.
|
|
532
541
|
- `environmentContentFromDocument` (function): function environmentContentFromDocument(doc: EditorDocument, options?: EnvironmentContentOptions): EnvironmentContent — Derives the coordinate/placement content of an `environment()` world from its scene document: terrain footprint (via {@link terrainBoundsFromDocument}), ground clearings under authored spawns/POIs (via `clearanceZonesFrom`), and the document's sculpt snapshot. This is the seam that lets a game author its world footprint and flatten regions in the editor instead of hardcoding them — the `world.ts` that consumes it carries only engine tuning.
|
|
542
|
+
- `grounded` (function): function grounded(ctx: Pick<GameContext, "world">, x: number, z: number): readonly [number, number, number] — Ground an XZ point onto the live world surface as `[x, groundY, z]`.
|
|
533
543
|
- `offline` (function): function offline(): MultiplayerAdapterConfig — Explicit single-player adapter. Solo games never need this — omitting `multiplayer` in the shell `defineGame` already defaults to offline; pass it only where an adapter value is structurally required.
|
|
534
544
|
- `seededRng` (function): function seededRng(seed: string | number): () => number — Deterministic pseudo-random generator seeded from a string or number — same seed, same sequence.
|
|
535
545
|
- `useHudLayout` (function): function useHudLayout(options?: { storageKey?: string; snap?: number; locked?: boolean; /** * Scene-document `ui` section — source of truth for panel placement/size. * When provided, hydrates the layout store (and wins over legacy localStorage). */ documentUi?: EditorUiDocument; /** * When true (def… — Layout state for `HudCanvas` — panel placements, edit-mode drag/resize, and per-game persistence.
|
|
@@ -16,6 +16,10 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
|
|
|
16
16
|
|
|
17
17
|
- `GameContextModels` (interface) · `import { GameContextModels } from "@jgengine/core/runtime/gameContext"`
|
|
18
18
|
|
|
19
|
+
## default-walk-codes — stock WASD + jump key codes for the shell walk controller
|
|
20
|
+
|
|
21
|
+
- `DEFAULT_WALK_CODES` (const) · `import { DEFAULT_WALK_CODES } from "@jgengine/shell/gameKit"`
|
|
22
|
+
|
|
19
23
|
## define-game — single public game-authoring path — compose systems, world, presentation, and authored scene in one definition
|
|
20
24
|
|
|
21
25
|
- `defineGame` (function) · `import { defineGame } from "@jgengine/shell/gameKit"`
|
|
@@ -32,6 +36,10 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
|
|
|
32
36
|
|
|
33
37
|
- `SystemDefinition` (interface) · `import { SystemDefinition } from "@jgengine/shell/gameKit"`
|
|
34
38
|
|
|
39
|
+
## grounded — ground an XZ point onto the world surface as a pose triple
|
|
40
|
+
|
|
41
|
+
- `grounded` (function) · `import { grounded } from "@jgengine/shell/gameKit"`
|
|
42
|
+
|
|
35
43
|
## headless-runner — play a real game loop with no renderer — tick, feed input, read the world snapshot
|
|
36
44
|
|
|
37
45
|
- `HeadlessRunner` (interface) · `import { HeadlessRunner } from "@jgengine/core/runtime/headlessRunner"`
|
|
@@ -95,8 +103,12 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
|
|
|
95
103
|
## render-fallback-diagnostics — Enable/disable the dev-only placeholder-fallback probe.
|
|
96
104
|
|
|
97
105
|
- `armFallbackSeams` (function) · `import { armFallbackSeams } from "@jgengine/core/devtools/fallbackSeams"`
|
|
106
|
+
- `armTextureErrors` (function) · `import { armTextureErrors } from "@jgengine/core/devtools/textureErrors"`
|
|
98
107
|
- `fallbackSeamsSnapshot` (function) · `import { fallbackSeamsSnapshot } from "@jgengine/core/devtools/fallbackSeams"`
|
|
99
108
|
- `reportFallbackSeam` (function) · `import { reportFallbackSeam } from "@jgengine/core/devtools/fallbackSeams"`
|
|
109
|
+
- `reportTextureLoadError` (function) · `import { reportTextureLoadError } from "@jgengine/core/devtools/textureErrors"`
|
|
110
|
+
- `resetTextureErrors` (function) · `import { resetTextureErrors } from "@jgengine/core/devtools/textureErrors"`
|
|
111
|
+
- `textureErrorsSnapshot` (function) · `import { textureErrorsSnapshot } from "@jgengine/core/devtools/textureErrors"`
|
|
100
112
|
|
|
101
113
|
## runtime-save — save/load the whole game world through a pluggable backend, autosave or save points
|
|
102
114
|
|
|
@@ -72,10 +72,13 @@ export function onNewPlayer(ctx: GameContext): void {
|
|
|
72
72
|
```
|
|
73
73
|
|
|
74
74
|
`GameUI` starts as an empty `HudCanvas` (`useHudLayout` + `HudCanvas` from the kit). That is
|
|
75
|
-
intentional: **every game owns its UI
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
75
|
+
intentional: **every game owns its UI composition** — layout, terminology, placement, and art
|
|
76
|
+
direction. Compose the shipped building blocks the moment you need them (`StatBar`, `Hotbar`,
|
|
77
|
+
`Coins`, `InventoryGrid`, `CharacterSheet`, window shells from `jgengine-ui`), then reskin via
|
|
78
|
+
`HudTheme` tokens. Reaching for those is using the engine correctly, not incomplete work. What
|
|
79
|
+
the engine does not ship is a whole finished game *face* or genre theme preset — do not leave an
|
|
80
|
+
unarranged, unskinned generic dashboard as the product. Hand-roll markup only where no building
|
|
81
|
+
block fits (see `jgengine-ui`).
|
|
79
82
|
|
|
80
83
|
## 3. Author, play, win
|
|
81
84
|
|
|
@@ -19,7 +19,12 @@
|
|
|
19
19
|
- `CheckResult` (interface): interface CheckResult — ⚠ undocumented
|
|
20
20
|
- `ClaimOutcome` (interface): interface ClaimOutcome — The outcome of a claim attempt — the updated pool and the grants owed (empty when the claim is refused).
|
|
21
21
|
- `ClaimablePool` (interface): interface ClaimablePool — A serializable pool of results left open for later claiming — first-come contested drops or a `reservedFor` personal reward. Tracks `eligible` claimants, optional `expiresAtMs`, and the authoritative `claimedBy` winner so reconnect and duplicate-claim attempts resolve idempotently.
|
|
22
|
+
- `ComboMeter` (interface): interface ComboMeter — A live, observable combo/multiplier meter — an integer hit chain with a decay window, free-string tier thresholds, a derived multiplier, and peak tracking.
|
|
23
|
+
- `ComboMeterConfig` (interface): interface ComboMeterConfig — Options for {@link createComboMeter}.
|
|
24
|
+
- `ComboMeterSnapshot` (interface): interface ComboMeterSnapshot — Serializable state for save/restore — clock-agnostic (stores time left, not an absolute deadline).
|
|
25
|
+
- `ComboMeterView` (interface): interface ComboMeterView — A pooled, read-only snapshot of the live meter for a renderer to draw each frame. Reused across {@link ComboMeter.view} calls and overwritten on the next one — read it, do not retain it. For a save, use {@link ComboMeter.snapshot}.
|
|
22
26
|
- `ComboStep` (interface): interface ComboStep — ⚠ undocumented
|
|
27
|
+
- `ComboTier` (interface): interface ComboTier — One tier threshold in a {@link ComboMeter}. Tiers gate on the integer combo `count` (not a filled fraction), and `id` is a free string the game owns and styles ("good", "great", "savage", …) — the model never interprets it.
|
|
23
28
|
- `CompletionPredicate` (type): type CompletionPredicate = ( params: Readonly<Record<string, unknown>>, ctx: PredicateContext, ) => boolean — A completion predicate: pure and deterministic, returns true when the node it gates is finished. Registered under a `kind` and reused across phases with different `params`.
|
|
24
29
|
- `CrossingDirection` (type): type CrossingDirection = "falling" | "rising" — The direction a crossing moved: `falling` = value decreased past the mark, `rising` = increased past it.
|
|
25
30
|
- `CrossingPolicy` (type): type CrossingPolicy = "once" | "repeat" — Whether a threshold may fire repeatedly (`repeat`) or at most once per direction (`once`).
|
|
@@ -40,6 +45,7 @@
|
|
|
40
45
|
- `DamagePredicate` (interface): interface DamagePredicate — A typed predicate over a {@link DamageContext}. Every listed facet must match (AND); a facet matches when the context value is in the list (channels/sources) or shares any member (targetStatuses/tags). An empty predicate matches every hit.
|
|
41
46
|
- `DamageResolution` (interface): interface DamageResolution — The outcome of running a pending application through the pipeline: what to apply, what was deferred, and why each value changed.
|
|
42
47
|
- `DeathReason` (type): type DeathReason = | { kind: "player_kill"; killerUserId: string; via?: { item?: string } } | { kind: "environment"; source: string } | { kind: "self"; source: string } — Why an entity died — who or what gets credit, for drop/command rules and the `entity.died` event.
|
|
48
|
+
- `DefenseResolution` (interface): interface DefenseResolution — Result of resolving an incoming hit against a defensive window: `outcome` is the graded defense (`"parry"`/`"block"`/`"iframe"`/`"hit"`) and `perfect` is true when the input landed inside the tight just-frame at the window's start rather than its wider active span.
|
|
43
49
|
- `EncounterConfig` (interface): interface EncounterConfig<TData = unknown> — Non-serializable configuration for an encounter: the authored phase tree plus predicate and spawn-provider registries. Re-supplied alongside a loaded {@link EncounterState}, the way `advanceSpawnDirector` pairs config with state, so the state itself stays pure data.
|
|
44
50
|
- `EncounterContext` (interface): interface EncounterContext — Context passed to {@link startEncounter} / {@link updateEncounter}: the caller signals predicates evaluate against, plus named `spawnPoints` catalogs (authored in the scene, referenced by key) that spawn providers place against. Never holds coordinates the sequence itself owns.
|
|
45
51
|
- `EncounterEvent` (type): type EncounterEvent = | { type: "enter"; phaseId: string; iteration: number } | { type: "spawn"; phaseId: string; provider: string; requests: readonly EncounterSpawnRequest[] } | { type: "complete"; phaseId: string; iteration: number; reason: string } | { type: "done" } — A lifecycle event emitted while stepping an encounter, carrying provenance.
|
|
@@ -83,6 +89,7 @@
|
|
|
83
89
|
- `ReceivedPolicy` (type): type ReceivedPolicy = | { kind: "scale"; factor: number } | { kind: "flat"; delta: number } | { kind: "cap"; max: number } | { kind: "floor"; min: number } | { kind: "convert"; toChannel: DamageChannelId; portion?: number } | { kind: "redirect"; toTarget: string; portion?: number } | { kind: "immune… — What a matched modifier does to the incoming amount. Amplification is one policy beside reduction — both are `scale` (factor `> 1` amplifies, `< 1` reduces). `cap`/`floor` clamp, `flat` adds/subtracts, `convert` moves a portion to another channel on the same target, `redirect` moves a portion to another target, and `immune` zeroes the hit outright.
|
|
84
90
|
- `RenderCueTuning` (interface): interface RenderCueTuning — Tuning knobs for `advanceMotionCues` / `useEntityRenderCues`; every field has a default, override only what a weapon/rig's feel needs to differ.
|
|
85
91
|
- `ResolvedMatchup` (interface): interface ResolvedMatchup — Fully-resolved matchup outputs (every axis populated) plus the contributions that produced them.
|
|
92
|
+
- `ResolvedShot` (interface): interface ResolvedShot — A shot's resolved firing geometry in world space: `origin` is the point the projectile/ray starts from and `direction` is its normalized aim vector, both computed by {@link resolveShot} from the shooter's position, facing, and the chosen origin policy.
|
|
86
93
|
- `ResourcePool` (interface): interface ResourcePool — ⚠ undocumented
|
|
87
94
|
- `RewardClaimSpec` (interface): interface RewardClaimSpec — How a `claimed` allocation exposes its pool: open first-come (`first`) or `reserved` to one recipient.
|
|
88
95
|
- `RewardGrant` (interface): interface RewardGrant — An authoritative, serializable award of one result stack to one recipient — carries `via` (the policy that produced it) and `private` (replication scope) so provenance and visibility survive save/load and viewer projection. Applying a grant twice with the same identity is the caller's idempotency contract; this seam only decides who is owed what.
|
|
@@ -103,6 +110,8 @@
|
|
|
103
110
|
- `StatsSnapshot` (interface): interface StatsSnapshot<TStat extends string> — Complete plain-data state for a {@link Stats} runtime.
|
|
104
111
|
- `StatusApplicationOutcome` (interface): interface StatusApplicationOutcome — The result of one status application: the outcome, the resulting instance (if any), and the roll.
|
|
105
112
|
- `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.
|
|
113
|
+
- `StatusEffectView` (interface): interface StatusEffectView — A serializable, presentation-ready snapshot of one active status for a timeline HUD row: a stable list `id`, the free-string `kind` the game styles (color / label / icon), the countdown-ring inputs `remainingMs` / `durationMs`, the `stacks` badge count, and the optional `magnitude` in force. Derived from a live {@link StatusInstance} via {@link toStatusEffectView}. The engine never interprets `kind` — it is a reference the game skins, not a built-in condition.
|
|
114
|
+
- `StatusEffectViewOptions` (interface): interface StatusEffectViewOptions — Options for {@link toStatusEffectView} / {@link toStatusEffectViews}.
|
|
106
115
|
- `StatusImmunity` (interface): interface StatusImmunity — Statuses a target cannot receive at all — the immunity half of application policy.
|
|
107
116
|
- `StatusInstance` (interface): interface StatusInstance — A live status carried by a target — the serializable, replicable state a status application mutates.
|
|
108
117
|
- `StatusStackPolicy` (type): type StatusStackPolicy = | { kind: "refresh" } | { kind: "stack"; max?: number; add?: number } | { kind: "replace" } | { kind: "ignore" } — How a fresh application behaves when the target already carries the status. - `refresh` — reset duration, hold the existing stack count. - `stack` — add `add` stacks (default 1) up to `max`, and refresh duration. - `replace` — overwrite duration and magnitude, stacks reset to 1. - `ignore` — leave the existing instance untouched (first application wins).
|
|
@@ -137,6 +146,7 @@
|
|
|
137
146
|
- `createAntiOneShotPolicy` (function): function createAntiOneShotPolicy(config: AntiOneShotConfig): AntiOneShotPolicy — Compose a reusable anti-one-shot / chip-guard clamp from caller data: while above `guardAboveFraction` a hit cannot drop the target below `leaveFraction`, and after such a save the target gets `recoverMs` of immunity. Below the guard fraction, lethal hits pass unchanged.
|
|
138
147
|
- `createBuildupMeter` (function): function createBuildupMeter(config: BuildupMeterConfig): BuildupMeter — Accumulate an ailment buildup — bleed, freeze, poison — that procs a status once it fills, then decays.
|
|
139
148
|
- `createCastRunner` (function): function createCastRunner(): CastRunner — Run a channeled cast/charge timer that movement or damage can interrupt — the spell cast bar.
|
|
149
|
+
- `createComboMeter` (function): function createComboMeter(config: ComboMeterConfig): ComboMeter — A count-based combo / multiplier meter: an integer hit chain that climbs with every `hit()` and drops when a decay window elapses, crossing free-string tier thresholds ("good" → "great" → "savage") that derive a score multiplier, while tracking the peak reached. Time is injected (`now`, default `Date.now`) and/or driven by `update(dt)`; `view()` returns a pooled draw-state and `snapshot`/`restore` round-trips the chain through a save.
|
|
140
150
|
- `createComboPoints` (function): function createComboPoints(config: ComboPointsConfig): ComboPoints — Build and spend finisher points — the combo-point economy behind rogue-style builders and spenders.
|
|
141
151
|
- `createComboRunner` (function): function createComboRunner(combo: ComboString, anim: AnimationState): ComboRunner — Advance a chained melee string from timed inputs, tracking the current step and its cancel/continue windows.
|
|
142
152
|
- `createDamageClamp` (function): function createDamageClamp(config: DamageClampConfig): DamageInterceptor — A stateless interceptor that caps any single application at `maxPerHit`.
|
|
@@ -182,9 +192,12 @@
|
|
|
182
192
|
- `resolveShot` (function): function resolveShot(deps: ShotOriginDeps, from: string, aim: Aim, policy: ShotOriginPolicy = { kind: "eye" }): ResolvedShot | null — ⚠ undocumented
|
|
183
193
|
- `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
194
|
- `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).
|
|
185
|
-
- `rollCheck` (function): function rollCheck(input: CheckInput, rng
|
|
195
|
+
- `rollCheck` (function): function rollCheck(input: CheckInput, rng?: () => number): CheckResult — Resolve a tabletop-style pass/fail roll against a target number with modifiers and crit/fumble bands.
|
|
186
196
|
- `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`.
|
|
197
|
+
- `statusEffectRemainingFraction` (function): function statusEffectRemainingFraction(view: StatusEffectView): number — Fraction of the countdown still remaining, clamped to `[0,1]` — the value a countdown ring fills to. Returns `0` when the duration is non-positive. Pure; safe to call every frame.
|
|
187
198
|
- `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`.
|
|
199
|
+
- `toStatusEffectView` (function): function toStatusEffectView(instance: StatusInstance, options?: StatusEffectViewOptions): StatusEffectView — Map one live {@link StatusInstance} to a serializable {@link StatusEffectView} for a HUD row. Pure: no clock, no allocation beyond the returned view. The `durationMs` option supplies the ring denominator the instance does not carry; without it the ring reads full.
|
|
200
|
+
- `toStatusEffectViews` (function): function toStatusEffectViews(instances: readonly StatusInstance[], options?: StatusEffectViewOptions): StatusEffectView[] — Map a list of live statuses (a target's carried {@link StatusInstance}s) to ordered HUD views. Pure and allocation-bounded — one pass, one view per input — so a status bar can render straight off the existing status model's snapshot without re-deriving ring math or timers.
|
|
188
201
|
- `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
202
|
- `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.
|
|
190
203
|
|
|
@@ -245,10 +258,20 @@
|
|
|
245
258
|
- `CastRunner` (interface): interface CastRunner — Per-entity cast-time state machine — begin, tick with game-time `dt` plus how far the caster moved, and act on the returned event. The runner owns timing and move-interruption only; the caller spends resources, starts cooldowns, and executes the ability when `completed` fires (compose with `abilityKit` — check readiness before `begin`, `cast` on completion).
|
|
246
259
|
- `createCastRunner` (function): function createCastRunner(): CastRunner — Run a channeled cast/charge timer that movement or damage can interrupt — the spell cast bar.
|
|
247
260
|
|
|
261
|
+
## @jgengine/core/combat/comboMeter
|
|
262
|
+
|
|
263
|
+
- `ComboMeter` (interface): interface ComboMeter — A live, observable combo/multiplier meter — an integer hit chain with a decay window, free-string tier thresholds, a derived multiplier, and peak tracking.
|
|
264
|
+
- `ComboMeterConfig` (interface): interface ComboMeterConfig — Options for {@link createComboMeter}.
|
|
265
|
+
- `ComboMeterSnapshot` (interface): interface ComboMeterSnapshot — Serializable state for save/restore — clock-agnostic (stores time left, not an absolute deadline).
|
|
266
|
+
- `ComboMeterView` (interface): interface ComboMeterView — A pooled, read-only snapshot of the live meter for a renderer to draw each frame. Reused across {@link ComboMeter.view} calls and overwritten on the next one — read it, do not retain it. For a save, use {@link ComboMeter.snapshot}.
|
|
267
|
+
- `ComboTier` (interface): interface ComboTier — One tier threshold in a {@link ComboMeter}. Tiers gate on the integer combo `count` (not a filled fraction), and `id` is a free string the game owns and styles ("good", "great", "savage", …) — the model never interprets it.
|
|
268
|
+
- `createComboMeter` (function): function createComboMeter(config: ComboMeterConfig): ComboMeter — A count-based combo / multiplier meter: an integer hit chain that climbs with every `hit()` and drops when a decay window elapses, crossing free-string tier thresholds ("good" → "great" → "savage") that derive a score multiplier, while tracking the peak reached. Time is injected (`now`, default `Date.now`) and/or driven by `update(dt)`; `view()` returns a pooled draw-state and `snapshot`/`restore` round-trips the chain through a save.
|
|
269
|
+
|
|
248
270
|
## @jgengine/core/combat/comboPoints
|
|
249
271
|
|
|
250
272
|
- `ComboPoints` (interface): interface ComboPoints — ⚠ undocumented
|
|
251
273
|
- `ComboPointsConfig` (interface): interface ComboPointsConfig — ⚠ undocumented
|
|
274
|
+
- `ComboPointsSnapshot` (interface): interface ComboPointsSnapshot — Complete serializable state for {@link ComboPoints}; `remaining: null` means no expiry is running.
|
|
252
275
|
- `createComboPoints` (function): function createComboPoints(config: ComboPointsConfig): ComboPoints — Build and spend finisher points — the combo-point economy behind rogue-style builders and spenders.
|
|
253
276
|
|
|
254
277
|
## @jgengine/core/combat/comboString
|
|
@@ -323,7 +346,7 @@
|
|
|
323
346
|
|
|
324
347
|
- `DefenseKind` (type): type DefenseKind = "parry" | "block" | "dodge" — ⚠ undocumented
|
|
325
348
|
- `DefenseOutcome` (type): type DefenseOutcome = "parry" | "block" | "iframe" | "hit" — ⚠ undocumented
|
|
326
|
-
- `DefenseResolution` (interface): interface DefenseResolution —
|
|
349
|
+
- `DefenseResolution` (interface): interface DefenseResolution — Result of resolving an incoming hit against a defensive window: `outcome` is the graded defense (`"parry"`/`"block"`/`"iframe"`/`"hit"`) and `perfect` is true when the input landed inside the tight just-frame at the window's start rather than its wider active span.
|
|
327
350
|
- `DefensiveWindow` (interface): interface DefensiveWindow — ⚠ undocumented
|
|
328
351
|
- `DefensiveWindowConfig` (interface): interface DefensiveWindowConfig — ⚠ undocumented
|
|
329
352
|
- `ResolveDefenseInput` (interface): interface ResolveDefenseInput — ⚠ undocumented
|
|
@@ -366,6 +389,7 @@
|
|
|
366
389
|
- `ReceiveMap` (type): type ReceiveMap = Record<string, ReceiveRule> — ⚠ undocumented
|
|
367
390
|
- `ReceiveRule` (interface): interface ReceiveRule — ⚠ undocumented
|
|
368
391
|
- `SingleTargetEffectInput` (interface): interface SingleTargetEffectInput — ⚠ undocumented
|
|
392
|
+
- `SlainIdentity` (interface): interface SlainIdentity — Identity of an entity slain by a lethal effect, captured before the death system despawns it. Serializable and genre-agnostic: `catalogId` is the slain entity's spawn kind/name (the same value the `entity.died` event carries), `name` an optional human-readable label for kill feeds, and `userId` the owning player when the slain unit was player-controlled. The slain entity's instance id is already {@link EffectResult.instanceId}.
|
|
369
393
|
- `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.
|
|
370
394
|
- `resolveAreaTargets` (function): function resolveAreaTargets(spatial: CombatSpatialDeps, input: AreaTargetInput, accept?: (instanceId: string) => boolean): AreaTarget[] — ⚠ undocumented
|
|
371
395
|
|
|
@@ -451,6 +475,8 @@
|
|
|
451
475
|
|
|
452
476
|
- `RegenShield` (interface): interface RegenShield — A shield pool that stops regenerating for `regenDelayMs` after every hit, then refills at `regenPerSecond` — the delayed-regen primitive that replaces snapshot-comparing stat values per tick to detect "damage taken" (#536.3). `damage` resets the grace timer; `tick` counts it down and regenerates once it elapses.
|
|
453
477
|
- `RegenShieldConfig` (interface): interface RegenShieldConfig — Tuning for `createRegenShield`: pool size, refill rate, and the post-damage grace period.
|
|
478
|
+
- `RegenShieldPool` (interface): interface RegenShieldPool — External storage a {@link RegenShield} reads and writes instead of keeping the value itself — an entity stat, a replicated store, a save record. This is the same port `Magazine` exposes as `MagazineReserve`, and it exists for the same reason: in most games the shield value is already owned by the stat system that damage, the HUD, and replication all read, so a primitive that insists on owning the number privately cannot be adopted without creating a second source of truth.
|
|
479
|
+
- `RegenShieldRates` (interface): interface RegenShieldRates — Per-tick rate overrides, for games that derive regen from live state — a talent tree, a buff, an equipped mod — rather than a constant fixed when the shield was built. Omit to use the configured values; the grace period in effect is whichever `regenDelayMs` was last passed to `tick`.
|
|
454
480
|
- `createRegenShield` (function): function createRegenShield(config: RegenShieldConfig): RegenShield — Builds a {@link RegenShield} that suppresses regen for `regenDelayMs` after each hit.
|
|
455
481
|
|
|
456
482
|
## @jgengine/core/combat/renderCues
|
|
@@ -481,6 +507,8 @@
|
|
|
481
507
|
|
|
482
508
|
- `ResourcePool` (interface): interface ResourcePool — ⚠ undocumented
|
|
483
509
|
- `ResourcePoolConfig` (interface): interface ResourcePoolConfig — ⚠ undocumented
|
|
510
|
+
- `ResourcePoolRetune` (interface): interface ResourcePoolRetune — Runtime tuning patch for {@link ResourcePool.retune} — omitted fields keep their current value.
|
|
511
|
+
- `ResourcePoolSnapshot` (interface): interface ResourcePoolSnapshot — Complete serializable state for a {@link ResourcePool}.
|
|
484
512
|
- `createResourcePool` (function): function createResourcePool(config: ResourcePoolConfig): ResourcePool — A regenerating resource pool — mana, stamina, energy — that actions spend from and that refills over time.
|
|
485
513
|
|
|
486
514
|
## @jgengine/core/combat/rewardAllocation
|
|
@@ -502,7 +530,7 @@
|
|
|
502
530
|
## @jgengine/core/combat/shotOrigin
|
|
503
531
|
|
|
504
532
|
- `DEFAULT_EYE_HEIGHT` (const): const DEFAULT_EYE_HEIGHT: number — Shot-origin and first-person camera eye height above an entity's position: 90% of the default 1.8m hitbox top.
|
|
505
|
-
- `ResolvedShot` (interface): interface ResolvedShot —
|
|
533
|
+
- `ResolvedShot` (interface): interface ResolvedShot — A shot's resolved firing geometry in world space: `origin` is the point the projectile/ray starts from and `direction` is its normalized aim vector, both computed by {@link resolveShot} from the shooter's position, facing, and the chosen origin policy.
|
|
506
534
|
- `ShotOriginDeps` (interface): interface ShotOriginDeps — ⚠ undocumented
|
|
507
535
|
- `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.
|
|
508
536
|
- `aimDirection` (function): function aimDirection(aim: Aim): EntityPosition | null — ⚠ undocumented
|
|
@@ -523,6 +551,14 @@
|
|
|
523
551
|
- `StatusStackPolicy` (type): type StatusStackPolicy = | { kind: "refresh" } | { kind: "stack"; max?: number; add?: number } | { kind: "replace" } | { kind: "ignore" } — How a fresh application behaves when the target already carries the status. - `refresh` — reset duration, hold the existing stack count. - `stack` — add `add` stacks (default 1) up to `max`, and refresh duration. - `replace` — overwrite duration and magnitude, stacks reset to 1. - `ignore` — leave the existing instance untouched (first application wins).
|
|
524
552
|
- `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`.
|
|
525
553
|
|
|
554
|
+
## @jgengine/core/combat/statusEffectView
|
|
555
|
+
|
|
556
|
+
- `StatusEffectView` (interface): interface StatusEffectView — A serializable, presentation-ready snapshot of one active status for a timeline HUD row: a stable list `id`, the free-string `kind` the game styles (color / label / icon), the countdown-ring inputs `remainingMs` / `durationMs`, the `stacks` badge count, and the optional `magnitude` in force. Derived from a live {@link StatusInstance} via {@link toStatusEffectView}. The engine never interprets `kind` — it is a reference the game skins, not a built-in condition.
|
|
557
|
+
- `StatusEffectViewOptions` (interface): interface StatusEffectViewOptions — Options for {@link toStatusEffectView} / {@link toStatusEffectViews}.
|
|
558
|
+
- `statusEffectRemainingFraction` (function): function statusEffectRemainingFraction(view: StatusEffectView): number — Fraction of the countdown still remaining, clamped to `[0,1]` — the value a countdown ring fills to. Returns `0` when the duration is non-positive. Pure; safe to call every frame.
|
|
559
|
+
- `toStatusEffectView` (function): function toStatusEffectView(instance: StatusInstance, options?: StatusEffectViewOptions): StatusEffectView — Map one live {@link StatusInstance} to a serializable {@link StatusEffectView} for a HUD row. Pure: no clock, no allocation beyond the returned view. The `durationMs` option supplies the ring denominator the instance does not carry; without it the ring reads full.
|
|
560
|
+
- `toStatusEffectViews` (function): function toStatusEffectViews(instances: readonly StatusInstance[], options?: StatusEffectViewOptions): StatusEffectView[] — Map a list of live statuses (a target's carried {@link StatusInstance}s) to ordered HUD views. Pure and allocation-bounded — one pass, one view per input — so a status bar can render straight off the existing status model's snapshot without re-deriving ring math or timers.
|
|
561
|
+
|
|
526
562
|
## @jgengine/core/combat/telegraph
|
|
527
563
|
|
|
528
564
|
- `HazardCycleConfig` (interface): interface HazardCycleConfig — ⚠ undocumented
|
|
@@ -584,7 +620,7 @@
|
|
|
584
620
|
- `CheckAdvantage` (type): type CheckAdvantage = "advantage" | "disadvantage" | "normal" — ⚠ undocumented
|
|
585
621
|
- `CheckInput` (interface): interface CheckInput — ⚠ undocumented
|
|
586
622
|
- `CheckResult` (interface): interface CheckResult — ⚠ undocumented
|
|
587
|
-
- `rollCheck` (function): function rollCheck(input: CheckInput, rng
|
|
623
|
+
- `rollCheck` (function): function rollCheck(input: CheckInput, rng?: () => number): CheckResult — Resolve a tabletop-style pass/fail roll against a target number with modifiers and crit/fumble bands.
|
|
588
624
|
|
|
589
625
|
## @jgengine/core/stats/spawnLevelStats
|
|
590
626
|
|
|
@@ -32,6 +32,10 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
|
|
|
32
32
|
|
|
33
33
|
- `createComboRunner` (function) · `import { createComboRunner } from "@jgengine/core/combat"`
|
|
34
34
|
|
|
35
|
+
## combo-meter — count-based combo/multiplier meter with a decay window, free-string tier thresholds, derived multiplier, peak tracking and snapshot/restore
|
|
36
|
+
|
|
37
|
+
- `createComboMeter` (function) · `import { createComboMeter } from "@jgengine/core/combat"`
|
|
38
|
+
|
|
35
39
|
## combo-points — build up and spend finisher/combo points
|
|
36
40
|
|
|
37
41
|
- `createComboPoints` (function) · `import { createComboPoints } from "@jgengine/core/combat"`
|
|
@@ -208,6 +212,14 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
|
|
|
208
212
|
|
|
209
213
|
- `resolveStatusApplication` (function) · `import { resolveStatusApplication } from "@jgengine/core/combat"`
|
|
210
214
|
|
|
215
|
+
## status-effect-timeline — adapt live status instances into serializable timeline-HUD views (id, kind, remaining/duration, stacks) for a countdown-ring effect bar
|
|
216
|
+
|
|
217
|
+
- `toStatusEffectViews` (function) · `import { toStatusEffectViews } from "@jgengine/core/combat"`
|
|
218
|
+
|
|
219
|
+
## status-effect-view — adapt one live status instance into a serializable timeline-HUD view (id, kind, remaining/duration, stacks)
|
|
220
|
+
|
|
221
|
+
- `toStatusEffectView` (function) · `import { toStatusEffectView } from "@jgengine/core/combat"`
|
|
222
|
+
|
|
211
223
|
## status-effects — commit direct or area effects through caller-owned stat pools with ordered spillover and lethal results
|
|
212
224
|
|
|
213
225
|
- `createEffectSystem` (function) · `import { createEffectSystem } from "@jgengine/core/combat"`
|
|
@@ -45,6 +45,8 @@ ctx.scene.entity.effect({ from, effect, via, at, radius, falloff?, los? }) // A
|
|
|
45
45
|
|
|
46
46
|
AoE: `inRadius(at, radius)` → LoS filter (default on) → `canReceive` per target → absorption; `falloff: "linear" | "none"`. `via` = `{ item }` (magnitude from weapon stats) or `{ amount }`. `canReceive`'s `pools-depleted` reason checks headroom in the effect's direction: a positive (draining) magnitude needs a stat above its min, a negative (restorative) magnitude needs a stat below its max — so a heal can still raise a stat sitting at its minimum. Omitting `magnitude` assumes the draining direction.
|
|
47
47
|
|
|
48
|
+
Each per-target `EffectResult` carries `{ instanceId, effect, applied, lethal }`. On a **lethal** hit it additionally carries `slain: { catalogId, name?, userId? }` — the victim's identity captured **before** the death system despawns it, so kill credit / XP reads the slain kind straight off the call result without a spawn-time id→kind registry (a non-lethal hit omits `slain`). This is the synchronous complement to the `entity.died` event: use `slain` when the code awarding the kill is the same code that fired the effect; use `entity.died` for decoupled listeners (quests, feeds, leaderboards).
|
|
49
|
+
|
|
48
50
|
`canReceive`'s optional signed `magnitude` makes the check direction-aware: positive (or omitted) keeps the standard `"pools-depleted"` check; negative checks the opposite direction and returns `"pools-full"` only when every stat in the receive order is already at max — so a heal (`via: { amount: -n }`) correctly reaches a fully-depleted target and is rejected only when there's nothing left to restore.
|
|
49
51
|
|
|
50
52
|
**Projectiles** (aim-based — no target ids):
|