@jgengine/core 0.26.0 → 0.27.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.
Files changed (55) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/dist/game/playableGame.d.ts +19 -2
  3. package/dist/gameplay.d.ts +5 -0
  4. package/dist/gameplay.js +5 -0
  5. package/dist/inventory/carryLoad.d.ts +48 -0
  6. package/dist/inventory/carryLoad.js +44 -0
  7. package/dist/inventory/equipment.d.ts +95 -0
  8. package/dist/inventory/equipment.js +169 -0
  9. package/dist/inventory/inventoryModel.d.ts +15 -6
  10. package/dist/inventory/inventoryModel.js +54 -5
  11. package/dist/inventory/shapedGrid.d.ts +26 -0
  12. package/dist/inventory/shapedGrid.js +47 -0
  13. package/dist/loot/lootGen.d.ts +186 -0
  14. package/dist/loot/lootGen.js +437 -0
  15. package/dist/loot/lootWeapon.d.ts +35 -0
  16. package/dist/loot/lootWeapon.js +70 -0
  17. package/dist/meta/changelog.d.ts +1 -1
  18. package/dist/meta/changelog.js +37 -1
  19. package/dist/nav/laneGraph.d.ts +178 -0
  20. package/dist/nav/laneGraph.js +671 -0
  21. package/dist/nav/traffic.d.ts +223 -0
  22. package/dist/nav/traffic.js +919 -0
  23. package/dist/physics/kinematicVehicle.d.ts +36 -0
  24. package/dist/physics/kinematicVehicle.js +15 -1
  25. package/dist/physics/vehicleDamage.d.ts +136 -0
  26. package/dist/physics/vehicleDamage.js +214 -0
  27. package/dist/physics/vehicleParts.d.ts +62 -0
  28. package/dist/physics/vehicleParts.js +65 -0
  29. package/dist/progression/gearScore.d.ts +56 -0
  30. package/dist/progression/gearScore.js +59 -0
  31. package/dist/progression/skillTree.d.ts +129 -0
  32. package/dist/progression/skillTree.js +265 -0
  33. package/dist/progression/xpCurve.d.ts +60 -0
  34. package/dist/progression/xpCurve.js +141 -0
  35. package/dist/scene/builtinSceneKinds.js +2 -0
  36. package/dist/world/decalKind.d.ts +48 -0
  37. package/dist/world/decalKind.js +86 -0
  38. package/dist/world/features.d.ts +3 -1
  39. package/dist/world/features.js +1 -0
  40. package/dist/world/grassKind.d.ts +5 -0
  41. package/dist/world/grassKind.js +3 -0
  42. package/dist/world/terraform.d.ts +8 -0
  43. package/dist/world.d.ts +5 -1
  44. package/dist/world.js +4 -0
  45. package/package.json +1 -1
  46. package/skills/jgengine/api.md +2 -2
  47. package/skills/jgengine-combat/SKILL.md +3 -1
  48. package/skills/jgengine-gameplay/SKILL.md +31 -0
  49. package/skills/jgengine-gameplay/api.md +150 -6
  50. package/skills/jgengine-gameplay/capabilities.md +48 -3
  51. package/skills/jgengine-gameplay/reference-systems.md +118 -0
  52. package/skills/jgengine-world/SKILL.md +4 -0
  53. package/skills/jgengine-world/api.md +115 -5
  54. package/skills/jgengine-world/capabilities.md +20 -0
  55. package/skills/jgengine-world/recipes/vehicle-feel.md +5 -0
@@ -0,0 +1,48 @@
1
+ /**
2
+ * `decal` marker: a surface-grime decal authored as a placed marker (dirt, cracks, paint, blood).
3
+ * Its position, facing (`rotationY`), tilt (0 lies on the ground, 90 stands on a wall), size, opacity
4
+ * and seed live in the scene document, so decals are placed in the editor like any other authored
5
+ * content and a game never hardcodes a stain. Pure config here; the procedural texture and the
6
+ * draped/standing quad live in the `shell` renderer.
7
+ *
8
+ * @capability decal editor-authored surface decal
9
+ */
10
+ import { type ParamSchema, type SceneKindObject } from "../scene/sceneKinds.js";
11
+ /** The editor marker kind marking a surface decal. */
12
+ export declare const DECAL_KIND = "decal";
13
+ /** The four authored decal looks; each has its own deterministic procedural texture. */
14
+ export declare const DECAL_STYLES: readonly ["dirt", "cracks", "paint", "blood"];
15
+ /** One of the four authored decal looks. */
16
+ export type DecalStyle = (typeof DECAL_STYLES)[number];
17
+ /** Fully-defaulted decal params parsed from a marker's `meta`. */
18
+ export interface DecalRules {
19
+ style: DecalStyle;
20
+ /** Decal width/height in metres. */
21
+ size: number;
22
+ /** 0 lies flat on the ground, 90 stands on a wall; 45 leans. */
23
+ tilt: number;
24
+ /** Vertical offset of the decal centre above the placed point, in metres. */
25
+ lift: number;
26
+ /** Push along the decal's own normal, so a wall decal clears the wall it sits on. */
27
+ offset: number;
28
+ /** 0..1 overall alpha. */
29
+ opacity: number;
30
+ /** Deterministic shape seed. */
31
+ seed: string;
32
+ }
33
+ /** Default decal rules: a small dirt smudge lying on the ground. */
34
+ export declare const DECAL_DEFAULTS: DecalRules;
35
+ /** The decal parameter schema — drives the inspector and the `meta` parse. */
36
+ export declare const DECAL_SCHEMA: ParamSchema;
37
+ /** Parse a marker's `meta` into fully-defaulted decal rules. @internal */
38
+ export declare function readDecalRules(meta: Record<string, unknown> | undefined): DecalRules;
39
+ /** A resolved decal: its placed point/facing plus fully-defaulted rules. */
40
+ export interface ResolvedDecal {
41
+ position: readonly [number, number, number];
42
+ rotationY: number;
43
+ rules: DecalRules;
44
+ }
45
+ /** Resolve a decal marker into a placed, fully-defaulted decal; null without a position. @internal */
46
+ export declare function resolveDecalObject(object: SceneKindObject): ResolvedDecal | null;
47
+ /** Registers the `decal` scene kind. Called by {@link registerBuiltinSceneKinds}. @internal */
48
+ export declare function registerDecalKind(): void;
@@ -0,0 +1,86 @@
1
+ /**
2
+ * `decal` marker: a surface-grime decal authored as a placed marker (dirt, cracks, paint, blood).
3
+ * Its position, facing (`rotationY`), tilt (0 lies on the ground, 90 stands on a wall), size, opacity
4
+ * and seed live in the scene document, so decals are placed in the editor like any other authored
5
+ * content and a game never hardcodes a stain. Pure config here; the procedural texture and the
6
+ * draped/standing quad live in the `shell` renderer.
7
+ *
8
+ * @capability decal editor-authored surface decal
9
+ */
10
+ import { registerSceneKind } from "../scene/sceneKinds.js";
11
+ /** The editor marker kind marking a surface decal. */
12
+ export const DECAL_KIND = "decal";
13
+ /** The four authored decal looks; each has its own deterministic procedural texture. */
14
+ export const DECAL_STYLES = ["dirt", "cracks", "paint", "blood"];
15
+ /** Default decal rules: a small dirt smudge lying on the ground. */
16
+ export const DECAL_DEFAULTS = {
17
+ style: "dirt",
18
+ size: 2.4,
19
+ tilt: 0,
20
+ lift: 0.02,
21
+ offset: 0.04,
22
+ opacity: 0.9,
23
+ seed: "",
24
+ };
25
+ /** The decal parameter schema — drives the inspector and the `meta` parse. */
26
+ export const DECAL_SCHEMA = {
27
+ fields: [
28
+ { type: "select", key: "style", label: "style", options: DECAL_STYLES.map((value) => ({ value })), default: DECAL_DEFAULTS.style },
29
+ { type: "range", key: "size", label: "size", min: 0.3, max: 24, step: 0.1, default: DECAL_DEFAULTS.size, unit: "m" },
30
+ { type: "range", key: "tilt", label: "tilt", min: 0, max: 90, step: 1, default: DECAL_DEFAULTS.tilt, unit: "°" },
31
+ { type: "range", key: "lift", label: "height", min: 0, max: 30, step: 0.05, default: DECAL_DEFAULTS.lift, unit: "m" },
32
+ { type: "range", key: "offset", label: "surface offset", min: 0, max: 2, step: 0.01, default: DECAL_DEFAULTS.offset, unit: "m" },
33
+ { type: "range", key: "opacity", label: "opacity", min: 0.05, max: 1, step: 0.01, default: DECAL_DEFAULTS.opacity },
34
+ { type: "seed", key: "seed", label: "seed", default: DECAL_DEFAULTS.seed },
35
+ ],
36
+ };
37
+ function number(meta, key, fallback) {
38
+ const value = meta?.[key];
39
+ return typeof value === "number" && Number.isFinite(value) ? value : fallback;
40
+ }
41
+ function text(meta, key, fallback) {
42
+ const value = meta?.[key];
43
+ return typeof value === "string" ? value : fallback;
44
+ }
45
+ /** Parse a marker's `meta` into fully-defaulted decal rules. @internal */
46
+ export function readDecalRules(meta) {
47
+ const style = text(meta, "style", DECAL_DEFAULTS.style);
48
+ return {
49
+ style: DECAL_STYLES.includes(style) ? style : DECAL_DEFAULTS.style,
50
+ size: Math.min(24, Math.max(0.3, number(meta, "size", DECAL_DEFAULTS.size))),
51
+ tilt: Math.min(90, Math.max(0, number(meta, "tilt", DECAL_DEFAULTS.tilt))),
52
+ lift: Math.max(0, number(meta, "lift", DECAL_DEFAULTS.lift)),
53
+ offset: Math.max(0, number(meta, "offset", DECAL_DEFAULTS.offset)),
54
+ opacity: Math.min(1, Math.max(0.05, number(meta, "opacity", DECAL_DEFAULTS.opacity))),
55
+ seed: text(meta, "seed", DECAL_DEFAULTS.seed),
56
+ };
57
+ }
58
+ /** Resolve a decal marker into a placed, fully-defaulted decal; null without a position. @internal */
59
+ export function resolveDecalObject(object) {
60
+ const position = object.position ?? object.center;
61
+ if (position === undefined)
62
+ return null;
63
+ return {
64
+ position: [position.x, position.y, position.z],
65
+ rotationY: object.rotationY ?? 0,
66
+ rules: readDecalRules(object.meta),
67
+ };
68
+ }
69
+ /** Registers the `decal` scene kind. Called by {@link registerBuiltinSceneKinds}. @internal */
70
+ export function registerDecalKind() {
71
+ registerSceneKind({
72
+ kind: DECAL_KIND,
73
+ target: "marker",
74
+ label: "Decal",
75
+ addCategory: "Studios",
76
+ accent: "#b5793c",
77
+ schema: DECAL_SCHEMA,
78
+ resolve: (object) => resolveDecalObject(object),
79
+ note: (object) => {
80
+ const resolved = resolveDecalObject(object);
81
+ if (resolved === null)
82
+ return "Place the marker on a surface.";
83
+ return `${resolved.rules.style} · ${resolved.rules.size.toFixed(1)} m ${resolved.rules.tilt >= 45 ? "wall" : "ground"} decal`;
84
+ },
85
+ });
86
+ }
@@ -288,6 +288,8 @@ export interface GrassEnvironmentConfig {
288
288
  colorVariation?: number;
289
289
  /** 0..1 blend of blade normals toward straight-up (shell default 0.6). Low values light each blade plane individually and go dark when side-lit; high values light the field like a soft carpet. */
290
290
  normalLift?: number;
291
+ /** 0..1 strength of the turf ground-cover mat painted under the blades (shell default 0.9); 0 leaves the ground bare. */
292
+ groundCover?: number;
291
293
  }
292
294
  export interface OceanEnvironmentConfig {
293
295
  bounds?: WorldBounds;
@@ -459,7 +461,7 @@ export type SnowEnvironmentDescriptor = {
459
461
  } & Required<Pick<SnowEnvironmentConfig, "area" | "density" | "speed" | "flakeSize" | "drift" | "wind" | "color" | "opacity">>;
460
462
  export type GrassEnvironmentDescriptor = {
461
463
  kind: "grass";
462
- } & Required<Pick<GrassEnvironmentConfig, "area" | "density" | "bladeHeight" | "bladeWidth" | "windStrength" | "colors">> & Pick<GrassEnvironmentConfig, "seed" | "bladeBend" | "tuftRadius" | "colorVariation" | "normalLift">;
464
+ } & Required<Pick<GrassEnvironmentConfig, "area" | "density" | "bladeHeight" | "bladeWidth" | "windStrength" | "colors">> & Pick<GrassEnvironmentConfig, "seed" | "bladeBend" | "tuftRadius" | "colorVariation" | "normalLift" | "groundCover">;
463
465
  export type OceanEnvironmentDescriptor = {
464
466
  kind: "ocean";
465
467
  } & Required<Pick<OceanEnvironmentConfig, "bounds" | "level" | "waveHeight" | "waveScale" | "waveSpeed" | "color">> & Pick<OceanEnvironmentConfig, "position" | "levelAt">;
@@ -201,6 +201,7 @@ export function grass(config = {}) {
201
201
  ...(config.tuftRadius === undefined ? {} : { tuftRadius: config.tuftRadius }),
202
202
  ...(config.colorVariation === undefined ? {} : { colorVariation: config.colorVariation }),
203
203
  ...(config.normalLift === undefined ? {} : { normalLift: config.normalLift }),
204
+ ...(config.groundCover === undefined ? {} : { groundCover: config.groundCover }),
204
205
  };
205
206
  }
206
207
  /** Declares an ocean water body for `environment()` — bounds, level, and wave tuning. */
@@ -40,6 +40,11 @@ export interface GrassRules {
40
40
  windGust: number;
41
41
  /** Blade material roughness, 0..1. */
42
42
  roughness: number;
43
+ /**
44
+ * Ground-cover mat strength, 0..1: the patch paints a turf surface over its footprint instead of
45
+ * leaving the ground beneath the blades bare. 0 keeps blades only.
46
+ */
47
+ groundCover: number;
43
48
  /** Seed string; same seed reproduces the same blade layout. */
44
49
  seed: string;
45
50
  }
@@ -28,6 +28,7 @@ export const GRASS_DEFAULTS = {
28
28
  windSpeed: 1.6,
29
29
  windGust: 0.16,
30
30
  roughness: 0.85,
31
+ groundCover: 0.9,
31
32
  seed: "",
32
33
  };
33
34
  /** The grass parameter schema — drives the inspector and `meta` parse via the studio seam. */
@@ -48,6 +49,7 @@ export const GRASS_SCHEMA = {
48
49
  { type: "range", key: "windSpeed", label: "wind speed", min: 0, max: 4, step: 0.05, default: GRASS_DEFAULTS.windSpeed },
49
50
  { type: "range", key: "windGust", label: "gust scale", min: 0, max: 1, step: 0.02, default: GRASS_DEFAULTS.windGust },
50
51
  { type: "range", key: "roughness", label: "roughness", min: 0, max: 1, step: 0.02, default: GRASS_DEFAULTS.roughness },
52
+ { type: "range", key: "groundCover", label: "ground cover", min: 0, max: 1, step: 0.02, default: GRASS_DEFAULTS.groundCover },
51
53
  { type: "seed", key: "seed", label: "seed", default: "" },
52
54
  ],
53
55
  };
@@ -81,6 +83,7 @@ export function readGrassRules(meta) {
81
83
  windSpeed: metaNumber(meta, "windSpeed", GRASS_DEFAULTS.windSpeed),
82
84
  windGust: metaNumber(meta, "windGust", GRASS_DEFAULTS.windGust),
83
85
  roughness: metaNumber(meta, "roughness", GRASS_DEFAULTS.roughness),
86
+ groundCover: Math.max(0, Math.min(1, metaNumber(meta, "groundCover", GRASS_DEFAULTS.groundCover))),
84
87
  seed: metaString(meta, "seed", GRASS_DEFAULTS.seed),
85
88
  };
86
89
  }
@@ -57,6 +57,14 @@ export interface TerrainMaterialLayer {
57
57
  tint?: string;
58
58
  /** Layer master opacity 0..1 — scales this layer's blend weight everywhere. */
59
59
  opacity?: number;
60
+ /**
61
+ * Material library name (e.g. `"foliage/grass"`) whose scanned PBR color map paints this layer,
62
+ * as authored. The editor resolves it into {@link TerrainMaterialLayer.materialUrl} so the runtime
63
+ * needs no asset-library lookup.
64
+ */
65
+ material?: string;
66
+ /** Resolved URL of the layer's scanned color map, written by the editor from {@link TerrainMaterialLayer.material}. */
67
+ materialUrl?: string;
60
68
  }
61
69
  export interface TerraformSnapshot {
62
70
  bounds: Aabb;
package/dist/world.d.ts CHANGED
@@ -31,6 +31,7 @@ export { MOVEMENT_TUNING, type CollisionObstacle } from "./movement/movementMode
31
31
  export { resolvePlayerMovementTuning, stepPlayerMovement } from "./movement/playerMovement.js";
32
32
  export { POSE_HITBOX, createPoseState, type MovementPose } from "./movement/poseState.js";
33
33
  export { steerYaw } from "./movement/steering.js";
34
+ export { createLaneGraph, laneGraphFromDocument, type LaneEdgeConfig, type LaneGraph, type LaneGraphConfig, type LaneGraphDocumentOptions, type LaneIntersection, type LaneIntersectionConfig, type LaneNode, type LanePose, type LaneRightOfWay, type LaneSignalProgram, type LaneSpan, type LaneSpot, } from "./nav/laneGraph.js";
34
35
  export { constrainToNavGrid } from "./nav/navConstrain.js";
35
36
  export { createNavCrowd, type NavCrowd, type NavCrowdAgentSpec, type NavCrowdAgentView, type NavCrowdOptions, type NavCrowdRevalidate, type NavCrowdSnapshot, type NavCrowdStats, } from "./nav/navCrowd.js";
36
37
  export { populateNavGridFromEnvironment } from "./nav/navFromEnvironment.js";
@@ -38,6 +39,7 @@ export { createNavGrid, findPath, slopeStepCost, type NavGrid, type NavPoint } f
38
39
  export { buildNavAdjacency, closestPoint, createNavMeshQuery, raycastNav, type NavMeshAdjacency, type NavMeshData, type NavMeshLink, type NavMeshPath, type NavMeshQuery, type NavMeshQueryOptions, type NavMeshQuerySnapshot, } from "./nav/navMesh.js";
39
40
  export { createNavRuntime, navMeshFromBake, type AuthoredNavLink, type NavLinkKind, type NavRebuildStats, type NavRegion, type NavRuntime, type NavRuntimeOptions, type NavRuntimeSnapshot, type SceneBake, } from "./nav/navRuntime.js";
40
41
  export { advancePathFollow, createPathFollow, pathFollowProgress, pathFollowSeek, pathFromNav, pathLength, type PathFollowConfig, type PathFollowProgress, type PathFollowState, type PathProgress, type Waypoint, } from "./nav/pathFollow.js";
42
+ export { createTraffic, type Traffic, type TrafficCarView, type TrafficOptions, type TrafficRoutePolicy, type TrafficSignalState, type TrafficSnapshot, type TrafficStats, type TrafficTuning, } from "./nav/traffic.js";
41
43
  export { defineAttackMoveOrder, defineHoldOrder, defineMoveOrder, definePatrolOrder, defineStopOrder, defineTargetedOrder, type AttackMoveOrderPayload, type EmptyOrderPayload, type EngagementKindConfig, type EngagementOrderState, type MoveOrderPayload, type OrderKindConfig, type OrderMoveResult, type OrderMover, type OrderTargeting, type PatrolOrderPayload, type PatrolOrderState, type TargetedOrderPayload, } from "./orders/orderKinds.js";
42
44
  export { createOrderQueue, createOrderRegistry, type Order, type OrderCancelReason, type OrderEvent, type OrderIssueResult, type OrderKind, type OrderOutcome, type OrderPhase, type OrderProgress, type OrderQueue, type OrderQueueOptions, type OrderQueuePolicy, type OrderQueueState, type OrderRegistry, type OrderRejection, type OrderRequest, type OrderStartResult, type OrderTickReport, type OrderVec3, } from "./orders/orderQueue.js";
43
45
  export { createBallisticSweep, type BallisticSweep, type BallisticSweepHit } from "./physics/ballisticSweep.js";
@@ -48,14 +50,16 @@ export { tickDrivableVehicle } from "./physics/drivableVehicle.js";
48
50
  export { createAircraftDynamics, type AircraftAxis, type AircraftDynamics, type AircraftKind, type AircraftOptions, type AircraftStep, type AircraftTuning, type FlightControlInput, type FlightControlRates, type FlightVector, } from "./physics/flightDynamics.js";
49
51
  export { ForceVolume, PlatformCarry } from "./physics/forceVolume.js";
50
52
  export { combineGravity, pointGravity, uniformGravity, type GravityField, type GravityVector, type PointGravityOptions, } from "./physics/gravityField.js";
51
- export { createKinematicVehicle, type KinematicChassisTuning, type KinematicDynamicsTuning, type KinematicPowertrainTuning, type KinematicSteeringTuning, type KinematicVehicle, type KinematicVehicleStep, type KinematicVehicleTuning, } from "./physics/kinematicVehicle.js";
53
+ export { createKinematicVehicle, type KinematicChassisTuning, type KinematicDynamicsTuning, type KinematicPowertrainTuning, type KinematicSteeringTuning, type KinematicVehicle, type KinematicVehicleStep, type KinematicVehicleTuning, type KinematicWeightTransferTuning, } from "./physics/kinematicVehicle.js";
52
54
  export { PhysicsWorld, SHAPE_BOX, SHAPE_SPHERE, type AddBodyOptions, type CollisionEvent, type PhysicsStats, } from "./physics/physicsWorld.js";
53
55
  export { createRagdoll } from "./physics/ragdoll.js";
54
56
  export { SpatialGrid } from "./physics/spatialGrid.js";
55
57
  export { StructureGraph, type CollapseEvent, type StructureMaterial } from "./physics/structure.js";
56
58
  export { Glide, Grapple } from "./physics/traversal.js";
57
59
  export { DEFAULT_GRIP_CURVE, createVehicleBody, sampleGripCurve, type GripCurve } from "./physics/vehicleBody.js";
60
+ export { createVehicleDamage, damagedAxis, damagedTuning, type VehicleDamage, type VehicleDamageConfig, type VehicleDamageEffect, type VehicleDamageEffectResolved, type VehicleDamageState, type VehicleDamageTransition, type VehicleDamageZone, type VehicleDamageZoneState, type VehicleDeformation, } from "./physics/vehicleDamage.js";
58
61
  export { createVehicleObstacleClamp, type VehicleImpact, type VehicleObstacleClamp, } from "./physics/vehicleObstacles.js";
62
+ export { applyVehicleParts, feelOf, withPart, type VehicleFeel, type VehiclePart, type VehiclePartEffect, type VehicleSetup, type VehicleStat, } from "./physics/vehicleParts.js";
59
63
  export { type ObjectSlotRejection, type ObjectSlotResult, type ObjectSlotTransfer, type SceneObjectSlots, } from "./runtime/context/objectSlots.js";
60
64
  export { createAssetCatalog, type AssetCatalog, type ModelAssetRef, type ModelDims } from "./scene/assetCatalog.js";
61
65
  export { partsBounds, registerAssetGenerator, type GeneratedAsset, type GeneratedPart } from "./scene/assetGenerator.js";
package/dist/world.js CHANGED
@@ -31,6 +31,7 @@ export { MOVEMENT_TUNING } from "./movement/movementModel.js";
31
31
  export { resolvePlayerMovementTuning, stepPlayerMovement } from "./movement/playerMovement.js";
32
32
  export { POSE_HITBOX, createPoseState } from "./movement/poseState.js";
33
33
  export { steerYaw } from "./movement/steering.js";
34
+ export { createLaneGraph, laneGraphFromDocument, } from "./nav/laneGraph.js";
34
35
  export { constrainToNavGrid } from "./nav/navConstrain.js";
35
36
  export { createNavCrowd, } from "./nav/navCrowd.js";
36
37
  export { populateNavGridFromEnvironment } from "./nav/navFromEnvironment.js";
@@ -38,6 +39,7 @@ export { createNavGrid, findPath, slopeStepCost } from "./nav/navGrid.js";
38
39
  export { buildNavAdjacency, closestPoint, createNavMeshQuery, raycastNav, } from "./nav/navMesh.js";
39
40
  export { createNavRuntime, navMeshFromBake, } from "./nav/navRuntime.js";
40
41
  export { advancePathFollow, createPathFollow, pathFollowProgress, pathFollowSeek, pathFromNav, pathLength, } from "./nav/pathFollow.js";
42
+ export { createTraffic, } from "./nav/traffic.js";
41
43
  export { defineAttackMoveOrder, defineHoldOrder, defineMoveOrder, definePatrolOrder, defineStopOrder, defineTargetedOrder, } from "./orders/orderKinds.js";
42
44
  export { createOrderQueue, createOrderRegistry, } from "./orders/orderQueue.js";
43
45
  export { createBallisticSweep } from "./physics/ballisticSweep.js";
@@ -55,7 +57,9 @@ export { SpatialGrid } from "./physics/spatialGrid.js";
55
57
  export { StructureGraph } from "./physics/structure.js";
56
58
  export { Glide, Grapple } from "./physics/traversal.js";
57
59
  export { DEFAULT_GRIP_CURVE, createVehicleBody, sampleGripCurve } from "./physics/vehicleBody.js";
60
+ export { createVehicleDamage, damagedAxis, damagedTuning, } from "./physics/vehicleDamage.js";
58
61
  export { createVehicleObstacleClamp, } from "./physics/vehicleObstacles.js";
62
+ export { applyVehicleParts, feelOf, withPart, } from "./physics/vehicleParts.js";
59
63
  export {} from "./runtime/context/objectSlots.js";
60
64
  export { createAssetCatalog } from "./scene/assetCatalog.js";
61
65
  export { partsBounds, registerAssetGenerator } from "./scene/assetGenerator.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jgengine/core",
3
- "version": "0.26.0",
3
+ "version": "0.27.0",
4
4
  "description": "jgengine core — pure-TypeScript game framework SDK (npm @jgengine/core). Entity stores, commands, combat, inventory, multiplayer seams. Zero dependencies. Not an ECS. Agent skills ship in the tarball. https://jgengine.com",
5
5
  "keywords": [
6
6
  "jgengine",
@@ -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.26.0" — Installed `@jgengine/core` semver — compare against {@link CHANGELOG} keys when migrating.
9
+ - `VERSION` (const): const VERSION: "0.27.0" — Installed `@jgengine/core` semver — compare against {@link CHANGELOG} keys when migrating.
10
10
 
11
11
  ## @jgengine/core/authoring
12
12
 
@@ -285,7 +285,7 @@
285
285
 
286
286
  - `CHANGELOG` (const): const CHANGELOG: Record<string, ChangelogEntry> — Per-version engine changelog keyed by semver string (e.g. `"0.10.0"`).
287
287
  - `ChangelogEntry` (interface): interface ChangelogEntry — One release's migrate steps plus added/changed/removed notes (typed mirror of CHANGELOG.md).
288
- - `VERSION` (const): const VERSION: "0.26.0" — Installed `@jgengine/core` semver — compare against {@link CHANGELOG} keys when migrating.
288
+ - `VERSION` (const): const VERSION: "0.27.0" — Installed `@jgengine/core` semver — compare against {@link CHANGELOG} keys when migrating.
289
289
 
290
290
  ## @jgengine/core/runtime/adapter
291
291
 
@@ -24,7 +24,9 @@ spread, damage — hand the definition to `createWeaponSystem`
24
24
  (`combat/weaponSystem`): it runs single/auto/burst, hitscan or ballistic
25
25
  projectiles, interrupted reloads and a readable ammo economy, and resolves both
26
26
  deliveries through `createDamageRuntime`. Generated guns (rolled parts) are the
27
- same `WeaponDefinition`; see
27
+ same `WeaponDefinition`: `loot/lootGen` rolls the item and `loot/lootWeapon`'s
28
+ `lootWeaponDefinition` maps its stats onto one, so no second weapon type exists;
29
+ see
28
30
  [reference.md](reference.md#weapons-as-data).
29
31
  For scene-backed `createProjectileSystem`, inject authoritative `rng`; spread
30
32
  samples independent pellet rays and prediction stays on the center ray. The
@@ -38,6 +38,37 @@ Pins consume no choice RNG and must satisfy the same pool and constraints;
38
38
  incompatible pins backtrack earlier unpinned choices or return `unsatisfiable`
39
39
  within the configured attempt and pick budgets.
40
40
 
41
+ Roll whole named gear from an authored catalog with `rollLoot`
42
+ (`loot/lootGen`): bases with mount slots, parts, affix pools, weighted rarity
43
+ tiers, manufacturer stat personalities and a level curve, all caller data.
44
+ `validateLootItem` names each defect, `compareLootItems` returns per-stat deltas
45
+ and a weighted score, and `lootWeaponDefinition` (`loot/lootWeapon`) projects a
46
+ rolled item onto a `WeaponDefinition` for `createWeaponSystem`. `createLootRoller`
47
+ counts drops per rarity for a debug probe and snapshots its counters. Sample
48
+ catalog, distribution check and generated-weapon proof are in
49
+ [reference-systems.md](reference-systems.md#procedural-gear).
50
+
51
+ Resolve an authored XP curve with `defineXpCurve` (`progression/xpCurve`): one growth rule
52
+ (`flat`, `linear`, `power`, `geometric`, `table`), a `maxLevel` cap and a stated `rule` string;
53
+ `table()` and `totalXpFor()` read the same data, and `track()` hands those thresholds to
54
+ `leveling`. Spend a character's points in `createSkillTree` (`progression/skillTree`): nodes carry
55
+ a point `cost`, `requires`, `excludes`, `passives` and `actives`, `synergies` pay off two or more
56
+ ranked nodes together, `respec()` refunds exactly the points spent, and `resolved()` returns the
57
+ `StatModifierSet` plus ability-slot-shaped actives to feed `createStats` / `createAbilityKit`.
58
+ Score a whole loadout with `gearScore` (`progression/gearScore`) on the same weight policy as
59
+ `compareLootItems`. [reference-systems.md](reference-systems.md#progression-and-gear-score) shows
60
+ the data shapes and a two-build comparison.
61
+
62
+ Wear gear with `createEquipment` (`inventory/equipment`): slot defs own accepted kinds and the slots
63
+ they block, item defs own the slots an item may occupy, a filled slot swaps and hands back the
64
+ replaced item, and `state()` / `restore()` round-trip the worn set. Weigh a character with
65
+ `characterLoad` (`inventory/carryLoad`), which turns carried inventories plus worn gear into the
66
+ shared encumbrance bands (`moveMultiplier`, sprint/jump gates, `remaining`), so `canCarry` gates a
67
+ pickup. Declare a stash as its own inventory (`tier: "banked"`) and move items with
68
+ `InventorySet.move`; `snapshot()` / `restore()` save both as detached data. The bag and stash render
69
+ through `<InventoryGrid>` with `<EquipmentSlots>` above it. See
70
+ [inventory, equipment and weight](reference-systems.md#inventory-equipment-and-weight).
71
+
41
72
  Validate generated quest catalogs with `validateQuestCatalog` (`game/questCatalog`).
42
73
  Follow the [quest authoring recipe](recipes/quest-authoring.md) for bounded batches,
43
74
  canonical facts, external unlock declarations, and precise repair diagnostics.