@jgengine/core 0.30.0 → 0.31.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.
@@ -1297,6 +1297,7 @@
1297
1297
  - `DEFAULT_ESCAPE_MULTIPLE` (const): const DEFAULT_ESCAPE_MULTIPLE: 3 — A pursuit escapes at this multiple of its keep-close distance when none is declared.
1298
1298
  - `DEFAULT_FIXED_STAGES` (const): const DEFAULT_FIXED_STAGES: readonly ["input", "movement", "combat", "ai", "activities", "cleanup"] — Default fixed-sim stage order — systems pick a stage; most need only this.
1299
1299
  - `DEFAULT_FRAME_STAGES` (const): const DEFAULT_FRAME_STAGES: readonly ["input", "movement", "combat", "ai", "activities", "cleanup", "animation", "camera", "effects"] — Default frame stage order. Gameplay stages mirror the fixed table so once-per-frame systems (`type: "frame"`) can pick `combat`/`ai`/… without falling into the unknown-stage bucket; presentation stages follow.
1300
+ - `DEFAULT_MARKER_TOLERANCE` (const): const DEFAULT_MARKER_TOLERANCE: 8 — Default vertical allowance (m) for a horizontal marker proximity test.
1300
1301
  - `DEFAULT_PICKUP_RADIUS` (const): const DEFAULT_PICKUP_RADIUS: 2 — ⚠ undocumented
1301
1302
  - `DEFAULT_PING_CATEGORIES` (const): const DEFAULT_PING_CATEGORIES: Record<PingCategory, PingCategoryDef> — Content-agnostic default ping wheel: enemy / loot / location / danger.
1302
1303
  - `DEFAULT_PURSUE_DISTANCE` (const): const DEFAULT_PURSUE_DISTANCE: 3 — Default keep-close distance (m) for a `pursue` objective.
@@ -1445,7 +1446,7 @@
1445
1446
  - `LootDropProvenance` (interface): interface LootDropProvenance — Why one drop is in the result: the stage/table/entry that produced it, its weights, and the modifiers that shaped it.
1446
1447
  - `LootFilterRule` (interface): interface LootFilterRule { id: string; when: LootFilterCondition; hide?: boolean; color?: string; beam?: boolean; label?: string } — ⚠ undocumented · used by `evaluateLootFilter`: First matching rule wins (PoE/Last Epoch block semantics) — later rules never override an earlier match.
1447
1448
  - `LootInstalledPart` (interface): interface LootInstalledPart — One part occupying one slot of a rolled item.
1448
- - `LootIssueCode` (type): type LootIssueCode = | "invalid-level" | "unknown-base" | "unknown-manufacturer" | "manufacturer-base" | "unknown-rarity" | "duplicate-slot" | "unknown-slot" | "missing-slot-part" | "unknown-part" | "part-category" | "unknown-affix" | "duplicate-affix" | "invalid-affix" | "non-finite-stat" | "empty-… — A defect found by {@link validateLootItem}.
1449
+ - `LootIssueCode` (type): type LootIssueCode = | "invalid-level" | "unknown-base" | "level-gated-base" | "unknown-manufacturer" | "manufacturer-base" | "unknown-rarity" | "duplicate-slot" | "unknown-slot" | "missing-slot-part" | "unknown-part" | "part-category" | "unknown-affix" | "duplicate-affix" | "invalid-affix" | "non-f… — A defect found by {@link validateLootItem}.
1449
1450
  - `LootItem` (interface): interface LootItem — One rolled item: the base, maker, rarity, level, composed name, chosen parts, rolled affixes and resolved stats. Plain JSON, so a save stores it and the instance registry can key it.
1450
1451
  - `LootManufacturerDef` (interface): interface LootManufacturerDef — A maker with a stat personality: its mark goes in the name, `bias` shifts stats additively, `scale` multiplies them, and favored affix pools weigh more when this maker rolls the item.
1451
1452
  - `LootModifier` (interface): interface LootModifier<TCtx = unknown> — A registered, id-tagged loot policy applied to one stage. `plan` transforms eligibility, weights, and roll counts before rolling (luck, difficulty, gating); `drops` post-processes the rolled drops (quantity multipliers, dedupe, caps). Neither hook mutates table definitions, and the id is recorded in provenance so a resolved drop can be traced back to the policies that shaped it.
@@ -1493,6 +1494,8 @@
1493
1494
  - `MissionFailCondition` (interface): interface MissionFailCondition — A condition that fails the mission while the objective is active. `to` names a {@link MissionFailDef}; with no `to` the mission fails with the generic `"failed"` state.
1494
1495
  - `MissionFailDef` (interface): interface MissionFailDef — A named fail state an objective, timer or branch can land in.
1495
1496
  - `MissionIssue` (interface): interface MissionIssue — A located mission-catalog problem; `path` is a JSON Pointer into the supplied catalog.
1497
+ - `MissionMarkerPlane` (type): type MissionMarkerPlane = "horizontal" | "spatial" — Which plane a marker proximity test compares in.
1498
+ - `MissionMarkerProximity` (interface): interface MissionMarkerProximity — How a positional objective compares an actor to its authored marker.
1496
1499
  - `MissionObjectiveDef` (interface): interface MissionObjectiveDef — One objective. Every field is content; the machine reads only these.
1497
1500
  - `MissionObjectiveKind` (type): type MissionObjectiveKind = "reach" | "interact" | "survive" | "pursue" | "kill" | "collect" — The primitive goals an objective can have. Escort, chase and defend are not kinds — they are compositions of these plus fail conditions and timers (see `compositions.ts`).
1498
1501
  - `MissionRewardAppliers` (interface): interface MissionRewardAppliers — Appliers a mission reward routes through — the same shape quests use, plus a loot-table hook.
@@ -2178,7 +2181,7 @@
2178
2181
 
2179
2182
  ## @jgengine/core/item/affix
2180
2183
 
2181
- - `AffixDef` (interface): interface AffixDef { id: string; stat: string; op?: AffixOp; roll: number | [number, number]; weight: number; namePart?: {position: "prefix" | "suffix"; text: string} } — ⚠ undocumented
2184
+ - `AffixDef` (interface): interface AffixDef { id: string; stat: string; op?: AffixOp; roll: number | [number, number]; weight: number; minLevel?: number; namePart?: {position: "prefix" | "suffix"; text: string} } — ⚠ undocumented
2182
2185
  - `AffixOp` (type): type AffixOp = "add" | "mul" — ⚠ undocumented
2183
2186
  - `AffixPool` (interface): interface AffixPool { id: string; affixes: readonly AffixDef[] } — ⚠ undocumented
2184
2187
  - `AffixRoller` (interface): interface AffixRoller { rollRarity(rng: () => number): RarityTier; roll(base: ItemBaseDef, rarityId: string, rng: () => number): RolledItem; rollRandom(base: ItemBaseDef, rng: () => number): RolledItem } — ⚠ undocumented · used by `createAffixRoller`: Rolls randomized gear from a base item: a weighted rarity tier scales base stats and picks prefix/suffix affixes that name and modify the it…
@@ -2309,6 +2312,25 @@
2309
2312
  - `createWeaponStats` (function): function createWeaponStats(resolveEntry: (itemId: string) => WeaponEntry | null | undefined): WeaponStats — Resolve per-weapon stat values — damage, fire rate, spread — for combat math.
2310
2313
  - `getWeaponStat` (function): function getWeaponStat(entry: WeaponEntry | null | undefined, stat: string): number | null — ⚠ undocumented
2311
2314
 
2315
+ ## @jgengine/core/loot/drop
2316
+
2317
+ - `EquippedComparison` (interface): interface EquippedComparison — What a HUD renders when a drop lands: per-stat deltas against the worn item and one verdict.
2318
+ - `EquippedStatDelta` (interface): interface EquippedStatDelta extends LootStatDelta — A per-stat delta from the equipped item to the candidate; positive `delta` means the candidate is larger.
2319
+ - `ItemDrop` (interface): interface ItemDrop extends LootItem — A rolled item with a stable instance id, so a stash, ledger and vendor stock can name it.
2320
+ - `RollDropOptions` (interface): interface RollDropOptions extends LootRollOptions — {@link rollDrop} options: the loot roll plus the instance id (defaults to `drop:<seed>`).
2321
+ - `compareToEquipped` (function): function compareToEquipped(candidate: ItemDrop, equipped: ItemDrop | null, options: LootComparisonOptions = {}): EquippedComparison — Compare a dropped item against what is equipped, with one delta per stat and a weighted verdict. The delta is `candidate - equipped`; `better` flips for stats the caller lists in `lowerIsBetter`, so reload time improving does not read as worse. A missing equipped item compares against zeros.
2322
+ - `itemMass` (function): function itemMass(item: Pick<LootItem, "mass">): number — Carried mass of a rolled item. Older saves may predate `mass`; those default to `1`.
2323
+ - `rollDrop` (function): function rollDrop(catalog: LootCatalog, seed: string | number, options: RollDropOptions = {}): ItemDrop — Roll one item from a seed. Same seed, catalog and options produce the same id, name, affixes, stats and mass on every run; level gates which bases and affixes are in the pool.
2324
+
2325
+ ## @jgengine/core/loot/haul
2326
+
2327
+ - `CarryOutcome` (type): type CarryOutcome = | { ok: true; mass: number; remaining: number } | { ok: false; reason: "over-capacity" | "no-space" | "invalid-count"; mass: number; remaining: number } — What a carry attempt returns: the new load, or the rule that refused it.
2328
+ - `HaulTransfer` (interface): interface HaulTransfer — Stacks moved between a run and its stash, or lost when the run fails.
2329
+ - `RunHaul` (interface): interface RunHaul — A run's carried loot and the stash that outlives it.
2330
+ - `RunHaulConfig` (interface): interface RunHaulConfig<TId extends string> — What a run haul needs: two inventories, a weight rule and an optional save cell.
2331
+ - `RunHaulState` (interface): interface RunHaulState — Detached run and stash contents, for a save or a debug readout.
2332
+ - `createRunHaul` (function): function createRunHaul<TId extends string>(config: RunHaulConfig<TId>): RunHaul — A run's haul beside a persistent stash. Carrying is gated by the shared encumbrance rules; `bank` moves what the stash fits and saves; `fail` throws the run's haul away and leaves the stash as it was. The game decides when a run succeeds or fails and calls one of them.
2333
+
2312
2334
  ## @jgengine/core/loot/lootGen
2313
2335
 
2314
2336
  - `LootBaseDef` (interface): interface LootBaseDef extends ItemBaseDef — A base family (frame, housing, chassis — caller nouns) with its slots, stats and affix pools.
@@ -2316,7 +2338,7 @@
2316
2338
  - `LootComparison` (interface): interface LootComparison — How two items compare: every stat delta plus one weighted score for each.
2317
2339
  - `LootComparisonOptions` (interface): interface LootComparisonOptions — Caller policy for the comparison score.
2318
2340
  - `LootInstalledPart` (interface): interface LootInstalledPart — One part occupying one slot of a rolled item.
2319
- - `LootIssueCode` (type): type LootIssueCode = | "invalid-level" | "unknown-base" | "unknown-manufacturer" | "manufacturer-base" | "unknown-rarity" | "duplicate-slot" | "unknown-slot" | "missing-slot-part" | "unknown-part" | "part-category" | "unknown-affix" | "duplicate-affix" | "invalid-affix" | "non-finite-stat" | "empty-… — A defect found by {@link validateLootItem}.
2341
+ - `LootIssueCode` (type): type LootIssueCode = | "invalid-level" | "unknown-base" | "level-gated-base" | "unknown-manufacturer" | "manufacturer-base" | "unknown-rarity" | "duplicate-slot" | "unknown-slot" | "missing-slot-part" | "unknown-part" | "part-category" | "unknown-affix" | "duplicate-affix" | "invalid-affix" | "non-f… — A defect found by {@link validateLootItem}.
2320
2342
  - `LootItem` (interface): interface LootItem — One rolled item: the base, maker, rarity, level, composed name, chosen parts, rolled affixes and resolved stats. Plain JSON, so a save stores it and the instance registry can key it.
2321
2343
  - `LootManufacturerDef` (interface): interface LootManufacturerDef — A maker with a stat personality: its mark goes in the name, `bias` shifts stats additively, `scale` multiplies them, and favored affix pools weigh more when this maker rolls the item.
2322
2344
  - `LootPartDef` (interface): interface LootPartDef extends PartDef — A part a base can mount: its stats, a pick weight, and an optional word for the item name.
@@ -2342,6 +2364,30 @@
2342
2364
  - `LootWeaponStatMap` (interface): interface LootWeaponStatMap — Which rolled stat feeds which part of a {@link WeaponDefinition}. Every field is a stat id from the item; an omitted field keeps the template's value, so a catalog only maps what it rolls.
2343
2365
  - `lootWeaponDefinition` (function): function lootWeaponDefinition(item: LootItem, projection: LootWeaponProjection): WeaponDefinition — Project a rolled item onto a plain weapon definition: copy the template, then write the mapped stats into rate, damage, magazine, spread, range and projectile speed. The result is a {@link WeaponDefinition}, so `assertWeaponDefinition` and `createWeaponSystem` accept it unchanged.
2344
2366
 
2367
+ ## @jgengine/core/loot/salvage
2368
+
2369
+ - `ItemDropLike` (interface): interface ItemDropLike — The fields salvage reads; an `ItemDrop` from `./drop` satisfies it.
2370
+ - `ItemLedger` (interface): interface ItemLedger — One record of what happened to rolled item instances. Every path that removes an item - salvage, sale, granting a duplicate - claims it here first, so a second claim returns false and the item cannot be equipped, sold or broken down twice.
2371
+ - `ItemLedgerState` (type): type ItemLedgerState = Readonly<Record<string, Exclude<ItemLifecycle, "owned">>> — Items that have left play, keyed by instance id; anything absent is still `owned`.
2372
+ - `ItemLifecycle` (type): type ItemLifecycle = "owned" | "salvaged" | "sold" — Where an item instance stands: still usable, broken down, or sold.
2373
+ - `SalvageResult` (type): type SalvageResult = | { ok: true; id: string; yield: SalvageYield } | { ok: false; reason: "already-spent" | "invalid-item" } — Salvage outcome: the yield, or the reason the instance could not be broken down.
2374
+ - `SalvageTable` (interface): interface SalvageTable — What a broken-down item is worth: a game-authored currency, rate and per-rarity multiplier.
2375
+ - `SalvageYield` (interface): interface SalvageYield — The currency and amount one salvage yields. `currency` is the game's key, never interpreted.
2376
+ - `createItemLedger` (function): function createItemLedger(initial: ItemLedgerState = {}): ItemLedger — Build an item ledger. Ids are consumed once: the first successful {@link ItemLedger.spend} wins, every later call fails, which is what makes salvage and sale mutually exclusive.
2377
+ - `salvageItem` (function): function salvageItem(item: ItemDropLike, table: SalvageTable, ledger: ItemLedger): SalvageResult — Break one item down through its ledger. The ledger is claimed before the yield is computed, so a salvaged item cannot be salvaged, equipped or sold again; pass the game's own wallet update from `yield`.
2378
+ - `salvageValue` (function): function salvageValue(item: Pick<ItemDropLike, "level" | "rarity">, table: SalvageTable): SalvageYield — The yield an item of this level and rarity breaks down into. The formula is `round(perLevel x level x rarityMultiplier)`, floored by `minimum`, so the same item always yields the same amount and a higher level never yields less.
2379
+
2380
+ ## @jgengine/core/loot/vendor
2381
+
2382
+ - `StockVendorOptions` (interface): interface StockVendorOptions — What stocking a vendor reads: the roll catalog, a seeded rng and the pricing policy.
2383
+ - `VendorOffer` (interface): interface VendorOffer — One stocked item and the shop entry that prices it.
2384
+ - `VendorPriceRule` (interface): interface VendorPriceRule — How a vendor price is derived from an item: a base, a per-level rate and a rarity multiplier.
2385
+ - `VendorRotation` (interface): interface VendorRotation — A run-count refresh rule; the game owns how many runs between restocks.
2386
+ - `VendorRotationState` (interface): interface VendorRotationState — Where a vendor shelf stands: the run number it was last stocked on.
2387
+ - `createVendorRotation` (function): function createVendorRotation(everyRuns: number, start = 0): VendorRotation — A restock rule the game authors as "every N runs". It only answers when a refresh is due; the game calls {@link stockVendor} and then `mark`. No timer, so a paused or reloaded save keeps the same shelf until the run count moves.
2388
+ - `itemPrice` (function): function itemPrice(item: Pick<LootItem, "level" | "rarity">, rule: VendorPriceRule): { buy: number; sell: number | null } — The price of one item under a `VendorPriceRule`: `round(base + perLevel x level)` times the rarity multiplier, never below 1. Sell-back is `floor(price x sellFactor)` when the rule sets one.
2389
+ - `stockVendor` (function): function stockVendor(shop: ShopStock, options: StockVendorOptions): VendorOffer[] — Roll a vendor's shelf and add it to an existing {@link ShopStock}. Entries added by a previous call with the same `idPrefix` are removed first, so a refresh replaces the shelf instead of throwing on duplicate ids. Buying, selling and wallet charging stay in the economy owner.
2390
+
2345
2391
  ## @jgengine/core/mission/compositions
2346
2392
 
2347
2393
  - `ChaseMissionOptions` (interface): interface ChaseMissionOptions extends ComposedMissionOptions — Options for {@link chaseMission}: a target kept close until it is caught.
@@ -2355,6 +2401,7 @@
2355
2401
  ## @jgengine/core/mission/mission
2356
2402
 
2357
2403
  - `DEFAULT_ESCAPE_MULTIPLE` (const): const DEFAULT_ESCAPE_MULTIPLE: 3 — A pursuit escapes at this multiple of its keep-close distance when none is declared.
2404
+ - `DEFAULT_MARKER_TOLERANCE` (const): const DEFAULT_MARKER_TOLERANCE: 8 — Default vertical allowance (m) for a horizontal marker proximity test.
2358
2405
  - `DEFAULT_PURSUE_DISTANCE` (const): const DEFAULT_PURSUE_DISTANCE: 3 — Default keep-close distance (m) for a `pursue` objective.
2359
2406
  - `DEFAULT_REACH_RADIUS` (const): const DEFAULT_REACH_RADIUS: 2.5 — Default proximity radius (m) for a `reach` / `interact` objective.
2360
2407
  - `MISSION_COUNTER_KINDS` (const): const MISSION_COUNTER_KINDS: readonly MissionObjectiveKind[] — Objective kinds that are satisfied only by a counter — a mission made of these alone is a lint error.
@@ -2367,6 +2414,8 @@
2367
2414
  - `MissionFailCondition` (interface): interface MissionFailCondition — A condition that fails the mission while the objective is active. `to` names a {@link MissionFailDef}; with no `to` the mission fails with the generic `"failed"` state.
2368
2415
  - `MissionFailDef` (interface): interface MissionFailDef — A named fail state an objective, timer or branch can land in.
2369
2416
  - `MissionIssue` (interface): interface MissionIssue — A located mission-catalog problem; `path` is a JSON Pointer into the supplied catalog.
2417
+ - `MissionMarkerPlane` (type): type MissionMarkerPlane = "horizontal" | "spatial" — Which plane a marker proximity test compares in.
2418
+ - `MissionMarkerProximity` (interface): interface MissionMarkerProximity — How a positional objective compares an actor to its authored marker.
2370
2419
  - `MissionObjectiveDef` (interface): interface MissionObjectiveDef — One objective. Every field is content; the machine reads only these.
2371
2420
  - `MissionObjectiveKind` (type): type MissionObjectiveKind = "reach" | "interact" | "survive" | "pursue" | "kill" | "collect" — The primitive goals an objective can have. Escort, chase and defend are not kinds — they are compositions of these plus fail conditions and timers (see `compositions.ts`).
2372
2421
  - `MissionRewardAppliers` (interface): interface MissionRewardAppliers — Appliers a mission reward routes through — the same shape quests use, plus a loot-table hook.
@@ -244,6 +244,10 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
244
244
 
245
245
  - `splitStack` (function) · `import { splitStack } from "@jgengine/core/inventory/inventoryModel"`
246
246
 
247
+ ## item-comparison — show per-stat deltas and a weighted verdict for a drop against equipped gear
248
+
249
+ - `compareToEquipped` (function) · `import { compareToEquipped } from "@jgengine/core/loot/drop"`
250
+
247
251
  ## item-generation — compose constraints, weighted pools, transforms, and provenance into a deterministic generated item
248
252
 
249
253
  - `generate` (function) · `import { generate } from "@jgengine/core/gameplay"`
@@ -265,10 +269,46 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
265
269
  - `createItemInstanceRegistry` (function) · `import { createItemInstanceRegistry } from "@jgengine/core/gameplay"`
266
270
  - `proceduralLootEntry` (function) · `import { proceduralLootEntry } from "@jgengine/core/gameplay"`
267
271
 
272
+ ## item-ledger — track which rolled item instances are still owned, salvaged or sold
273
+
274
+ - `createItemLedger` (function) · `import { createItemLedger } from "@jgengine/core/loot/salvage"`
275
+
276
+ ## item-roll — roll one deterministic, level-gated item from a seed
277
+
278
+ - `rollDrop` (function) · `import { rollDrop } from "@jgengine/core/loot/drop"`
279
+
280
+ ## item-run-haul — carry loot with a weight gate, bank it into a persistent stash, or lose it when the run fails
281
+
282
+ - `createRunHaul` (function) · `import { createRunHaul } from "@jgengine/core/loot/haul"`
283
+
284
+ ## item-salvage — break an item down for the currency its level and rarity say, once
285
+
286
+ - `salvageItem` (function) · `import { salvageItem } from "@jgengine/core/loot/salvage"`
287
+
288
+ ## item-salvage-value — compute the currency an item of a level and rarity breaks down into
289
+
290
+ - `salvageValue` (function) · `import { salvageValue } from "@jgengine/core/loot/salvage"`
291
+
268
292
  ## item-use-composition — compose pluggable, ordered item use-behaviors from serializable references
269
293
 
270
294
  - `createUseBehaviorRegistry` (function) · `import { createUseBehaviorRegistry } from "@jgengine/core/gameplay"`
271
295
 
296
+ ## item-vendor — stock a vendor with rolled items priced through the shared economy
297
+
298
+ - `stockVendor` (function) · `import { stockVendor } from "@jgengine/core/loot/vendor"`
299
+
300
+ ## item-vendor-price — price an item from its level and rarity through the economy's currency
301
+
302
+ - `itemPrice` (function) · `import { itemPrice } from "@jgengine/core/loot/vendor"`
303
+
304
+ ## item-vendor-rotation — decide when a vendor's shelf is due for a restock
305
+
306
+ - `createVendorRotation` (function) · `import { createVendorRotation } from "@jgengine/core/loot/vendor"`
307
+
308
+ ## item-weight — read a rolled item's mass for a carry check
309
+
310
+ - `itemMass` (function) · `import { itemMass } from "@jgengine/core/loot/drop"`
311
+
272
312
  ## key-rebinding — conflict-aware key-remap session over the action-binding model — capture/reassign, conflict detection, reset-to-defaults, persist overrides, snapshot/restore
273
313
 
274
314
  - `createRebindSession` (function) · `import { createRebindSession } from "@jgengine/core/gameplay"`