@alife-sdk/ai 0.1.0 → 0.3.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/README.md CHANGED
@@ -18,6 +18,7 @@ view and must behave in real-time.
18
18
 
19
19
  - **State machine driver** — `OnlineAIDriver` + `StateHandlerMap` runs a per-NPC FSM
20
20
  over 18 built-in states (idle, patrol, combat, flee, wounded, monster abilities, …)
21
+ - **Optional state handlers** — opt-in handlers for investigation, helping wounded allies, and combat transitions (`InvestigateState`, `HelpWoundedState`, `KillWoundedState`, `CombatTransitionHandler`)
21
22
  - **Cover system** — 6 evaluators, loophole peek/fire cycles, TTL-based cover locking
22
23
  - **Perception** — FOV queries, hearing radius, intel freshness filters
23
24
  - **GOAP** — elite NPC goal-oriented planning over a 16-property world state bitmask
@@ -78,10 +79,12 @@ function update(deltaMs: number): void {
78
79
  }
79
80
 
80
81
  // 6. Read current state
81
- const state = driver.currentState; // e.g. 'COMBAT'
82
+ const state = driver.currentStateId; // e.g. 'COMBAT'
82
83
 
83
- // 7. Force a state transition (e.g. on NPC death)
84
- driver.transitionTo(ONLINE_STATE.DEAD);
84
+ // 7. Force a state transition from within a state handler (e.g. on NPC death)
85
+ // Transitions happen via ctx.transition(), called from inside a state handler:
86
+ // ctx.transition(ONLINE_STATE.DEAD);
87
+ // To force a transition externally, call driver.update() after mutating ctx.state.
85
88
  ```
86
89
 
87
90
  ---
@@ -96,15 +99,15 @@ Each module has its own import path for optimal tree-shaking:
96
99
  | `@alife-sdk/ai/plugin` | `AIPlugin`, `IAIPluginConfig` | [plugin/](src/plugin/) |
97
100
  | `@alife-sdk/ai/states` | `OnlineAIDriver`, `StateHandlerMap`, `ONLINE_STATE`, all handlers, builder functions | [states/](src/states/) |
98
101
  | `@alife-sdk/ai/cover` | `CoverRegistry`, `CoverLockRegistry`, 6 evaluators, `LoopholeGenerator` | [cover/](src/cover/) |
99
- | `@alife-sdk/ai/perception` | `NPCSensors`, `isInFOV`, `filterVisibleEntities`, `filterFreshIntel` | [perception/](src/perception/) |
102
+ | `@alife-sdk/ai/perception` | `NPCSensors`, `isInFOV`, `filterVisibleEntities`, `filterHearingEntities`, `filterHostileEntities`, `filterFriendlyEntities`, `filterFreshIntel`, `distanceSq`, `findClosest`, `scanForEnemies` | [perception/](src/perception/) |
100
103
  | `@alife-sdk/ai/goap` | `GOAPController`, `buildWorldState`, `selectGoal`, `EvadeHazardAction` | [goap/](src/goap/) |
101
104
  | `@alife-sdk/ai/navigation` | `smoothPath`, `smoothPathWithTurning`, `SmoothPathFollower`, `RestrictedZoneManager`, `SteeringBehaviors` | [navigation/](src/navigation/) |
102
105
  | `@alife-sdk/ai/squad` | `evaluateSituation`, `SquadCommand`, `SquadSharedTargetTable` | [squad/](src/squad/) |
103
- | `@alife-sdk/ai/animation` | `getAnimationKey`, `AnimationController`, `DirectionCache` | [animation/](src/animation/) |
106
+ | `@alife-sdk/ai/animation` | `getDirection`, `getAnimationKey`, `getAnimationRequest`, `AnimationController`, `DirectionCache`, `CompassIndex`, `AnimLayer`, `DEFAULT_STATE_ANIM_MAP`, `DEFAULT_WEAPON_SUFFIXES` | [animation/](src/animation/) |
104
107
  | `@alife-sdk/ai/sound` | `VocalizationType`, `VocalizationTracker` | [sound/](src/sound/) |
105
108
  | `@alife-sdk/ai/suspicion` | `SuspicionAccumulator`, `SuspicionStimuli` | [suspicion/](src/suspicion/) |
106
109
  | `@alife-sdk/ai/conditions` | `ConditionBank`, `ConditionChannels` | [conditions/](src/conditions/) |
107
- | `@alife-sdk/ai/combat` | Combat helpers for online NPC state handlers | [combat/](src/combat/) |
110
+ | `@alife-sdk/ai/combat` | `selectBestWeapon`, `shouldThrowGrenade`, `shouldUseMedkit`, `LoadoutBuilder`, `createLoadout`, `FactionWeaponPreference`, `evaluateTransitions`, `DEFAULT_COMBAT_RULES`, `WoundedRule`, `NoAmmoRule`, `EvadeDangerRule`, `MoraleRule`, `GrenadeOpportunityRule`, `MonsterAbility`, `selectMonsterAbility` | [combat/](src/combat/) |
108
111
  | `@alife-sdk/ai/types` | Shared interfaces (`INPCContext`, `INPCOnlineState`, …) | [types/](src/types/) |
109
112
  | `@alife-sdk/ai/config` | `IStateConfig`, default config helpers | [config/](src/config/) |
110
113
  | `@alife-sdk/ai/ports` | AI-specific port interfaces | [ports/](src/ports/) |
@@ -168,8 +171,9 @@ per frame: `enter → update (every frame) → exit`.
168
171
  const driver = new OnlineAIDriver(ctx, handlers, ONLINE_STATE.IDLE);
169
172
 
170
173
  driver.update(deltaMs); // call every frame
171
- driver.currentState; // current state ID string
172
- driver.transitionTo('PATROL'); // force transition
174
+ driver.currentStateId; // current state ID string
175
+ // Transitions happen via ctx.transition() from inside a state handler:
176
+ // ctx.transition('PATROL');
173
177
  ```
174
178
 
175
179
  Each state handler is a stateless object — all per-NPC runtime data lives in
@@ -235,18 +239,25 @@ interfaces. You implement each interface once and compose them per NPC:
235
239
  const ctx: INPCContext = {
236
240
  npcId: npc.id,
237
241
  faction: npc.faction,
238
- perception: new MyPerception(npc), // INPCPerception
239
- health: new MyHealth(npc), // INPCHealth
240
- cover: coverAccess, // ICoverAccess (from AIPlugin)
241
- danger: dangerAdapter, // IDangerAccess
242
- squad: squadAccess, // ISquadAccess
243
- suspicion: suspicionAccess, // ISuspicionAccess
244
- conditions: conditionAccess, // IConditionAccess
245
- shoot: (payload) => fireWeapon(npc, payload),
246
- meleeHit: (payload) => applyMelee(npc, payload),
242
+ perception: new MyPerception(npc), // INPCPerception | null
243
+ health: new MyHealth(npc), // INPCHealth | null
244
+ cover: coverAccess, // ICoverAccess | null (from AIPlugin)
245
+ danger: dangerAdapter, // IDangerAccess | null
246
+ squad: squadAccess, // ISquadAccess | null
247
+ suspicion: suspicionAccess, // ISuspicionAccess | null
248
+ conditions: conditionAccess, // IConditionAccess | null
249
+ // pack, restrictedZones also nullable — omit if not used
250
+ emitShoot: (payload) => fireWeapon(npc, payload),
251
+ emitMeleeHit:(payload) => applyMelee(npc, payload),
247
252
  };
248
253
  ```
249
254
 
255
+ > **Important:** Many subsystems are nullable (`T | null`). State handlers
256
+ > must null-check before use — always access optional subsystems with optional
257
+ > chaining: `ctx.cover?.findCover(...)`, `ctx.health?.hp`, `ctx.perception?.hasVisibleEnemy()`.
258
+ > Omitting a subsystem (setting it to `null`) silently disables the
259
+ > features that depend on it, with no code changes required in the handlers.
260
+
250
261
  ### Cover system
251
262
 
252
263
  The cover module provides a full pipeline from raw cover points to per-NPC
@@ -260,8 +271,99 @@ peek/fire cycles:
260
271
  - `BestCoverEvaluator` — best angle + distance combined
261
272
  - `AmbushCoverEvaluator` — optimal ambush position
262
273
  - `SafeCoverEvaluator` — maximum distance from all threats
263
- 3. **Lock** — `CoverLockRegistry.lock(npcId, coverId, ttlMs)` so no two NPCs share a point
264
- 4. **Loopholes** — each cover point has 1–3 loophole offsets; `TakeCoverState` cycles `WAIT → PEEK → FIRE → RETURN`
274
+ 3. **Lock** — `CoverLockRegistry.tryLock(coverId, npcId, { ttlMs })` so no two NPCs share a point
275
+ 4. **Loopholes** — each cover point has 1–N loophole offsets (count randomized, cached per point); `TakeCoverState` cycles `WAIT → PEEK → FIRE → RETURN`
276
+
277
+ #### Cover workflow inside a state handler
278
+
279
+ The typical cover workflow in a custom state handler mirrors what `TakeCoverState`
280
+ does internally:
281
+
282
+ ```ts
283
+ // In your state handler's enter():
284
+ enter(ctx: INPCContext): void {
285
+ const enemies = ctx.perception?.getVisibleEnemies() ?? [];
286
+ const enemy = enemies[0] ?? null;
287
+
288
+ // 1. findCover() — searches CoverRegistry for the best available point.
289
+ // Returns { x, y } or null. Internally stores the found point's ID.
290
+ let coverPt: { x: number; y: number } | null = null;
291
+ if (ctx.cover !== null && enemy !== null) {
292
+ coverPt = ctx.cover.findCover(ctx.x, ctx.y, enemy.x, enemy.y);
293
+ }
294
+
295
+ if (coverPt !== null) {
296
+ // 2. lockLastFound() — acquires a TTL lock on the point just returned
297
+ // by findCover(). Returns false if already locked by another NPC.
298
+ const locked = ctx.cover?.lockLastFound?.(ctx.npcId, 8000) ?? true;
299
+ if (locked) {
300
+ ctx.state.coverPointX = coverPt.x;
301
+ ctx.state.coverPointY = coverPt.y;
302
+ } else {
303
+ coverPt = null; // contested — do not move to this point
304
+ }
305
+ }
306
+
307
+ // 3. Initialise the loophole phase cycle.
308
+ ctx.state.loophole = { phase: 'WAIT', phaseStartMs: ctx.now() };
309
+ }
310
+
311
+ // In your state handler's update(), cycle WAIT → PEEK → FIRE → RETURN:
312
+ update(ctx: INPCContext, deltaMs: number): void {
313
+ const loophole = ctx.state.loophole;
314
+ const now = ctx.now();
315
+ const enemies = ctx.perception?.getVisibleEnemies() ?? [];
316
+ const enemy = enemies[0] ?? null;
317
+
318
+ switch (loophole?.phase) {
319
+ case 'WAIT':
320
+ ctx.halt();
321
+ if (now >= ctx.state.lastGrenadeMs) {
322
+ loophole.phase = 'PEEK';
323
+ loophole.phaseStartMs = now;
324
+ }
325
+ break;
326
+
327
+ case 'PEEK':
328
+ // Move slightly toward enemy to simulate peeking out.
329
+ if (enemy) moveToward(ctx, enemy.x, enemy.y, speed * 0.5);
330
+ if (now - loophole.phaseStartMs >= cfg.loopholePeekDurationMs) {
331
+ loophole.phase = 'FIRE';
332
+ loophole.phaseStartMs = now;
333
+ }
334
+ break;
335
+
336
+ case 'FIRE':
337
+ ctx.halt();
338
+ if (enemy) {
339
+ ctx.emitShoot({ npcId: ctx.npcId, x: ctx.x, y: ctx.y,
340
+ targetX: enemy.x, targetY: enemy.y,
341
+ weaponType: ctx.state.primaryWeapon ?? 'rifle' });
342
+ }
343
+ if (now - loophole.phaseStartMs >= cfg.loopholeFireDurationMs) {
344
+ loophole.phase = 'RETURN';
345
+ loophole.phaseStartMs = now;
346
+ }
347
+ break;
348
+
349
+ case 'RETURN':
350
+ // Move back to cover centre, then restart WAIT.
351
+ moveToward(ctx, ctx.state.coverPointX, ctx.state.coverPointY, speed);
352
+ if (now - loophole.phaseStartMs >= cfg.loopholeReturnDurationMs) {
353
+ loophole.phase = 'WAIT';
354
+ ctx.state.lastGrenadeMs = now + waitDuration;
355
+ }
356
+ break;
357
+ }
358
+ }
359
+
360
+ // In exit(): release the lock so other NPCs can take the point.
361
+ exit(ctx: INPCContext): void {
362
+ ctx.state.hasTakenCover = false;
363
+ ctx.state.loophole = null;
364
+ ctx.cover?.unlockAll?.(ctx.npcId);
365
+ }
366
+ ```
265
367
 
266
368
  ```ts
267
369
  import { recommendCoverType } from '@alife-sdk/ai/cover';
@@ -278,18 +380,192 @@ const evaluatorType = recommendCoverType({
278
380
  ### GOAP — elite NPC planning
279
381
 
280
382
  For NPCs with rank ≥ 5, `GOAPController` wraps a `GOAPPlanner` (A* on a
281
- 16-property `WorldState` bitmask) to select and execute goal-oriented action
282
- sequences. Replanning happens every 5 s or on a forced trigger.
383
+ 17-property `WorldState`) to select and execute goal-oriented action
384
+ sequences. Replanning happens automatically on a configurable interval or
385
+ immediately when `invalidatePlan()` is called.
386
+
387
+ #### World state properties
388
+
389
+ `buildWorldState(snapshot)` maps an `INPCWorldSnapshot` to 17 boolean
390
+ properties. All property keys come from the `WorldProperty` constant:
391
+
392
+ | Property key | Source field | What it means |
393
+ |---|---|---|
394
+ | `alive` | `snapshot.isAlive` | NPC is alive |
395
+ | `criticallyWounded` | `hpRatio <= 0.3` | HP at or below 30 % |
396
+ | `hasWeapon` | `snapshot.hasWeapon` | Has a usable weapon |
397
+ | `hasAmmo` | `snapshot.hasAmmo` | Has ammunition |
398
+ | `inCover` | `snapshot.inCover` | Currently at a cover point |
399
+ | `seeEnemy` | `snapshot.seeEnemy` | Enemy visible in FOV |
400
+ | `enemyPresent` | `snapshot.enemyPresent` | Enemy known (seen or heard) |
401
+ | `enemyInRange` | `snapshot.enemyInRange` | Enemy within weapon range |
402
+ | `danger` | `snapshot.hasDanger` | General danger signal active |
403
+ | `dangerGrenade` | `snapshot.hasDangerGrenade` | Grenade danger signal active |
404
+ | `enemyWounded` | `snapshot.enemyWounded` | Last known enemy is wounded |
405
+ | `anomalyNear` | `snapshot.nearAnomalyZone` | Anomaly zone inside proximity |
406
+ | `enemySeeMe` | `snapshot.seeEnemy` | (derived) enemy has line of sight |
407
+ | `readyToKill` | `hasWeapon && hasAmmo && seeEnemy && enemyInRange` | Can fire immediately |
408
+ | `positionHeld` | `inCover && !seeEnemy` | Holding cover without exposure |
409
+ | `lookedOut` | always `false` | One-shot peek flag (actions set it) |
410
+ | `atTarget` | `!enemyPresent && !hasDanger` | Safe at destination |
411
+
412
+ #### Goal selection
413
+
414
+ Goals are chosen by evaluating `DEFAULT_GOAL_RULES` in priority order (lowest
415
+ number wins):
416
+
417
+ | Priority | Goal | Trigger |
418
+ |---|---|---|
419
+ | 0 `CRITICALLY_WOUNDED` | Heal + disengage | `hpRatio <= healHpThreshold` |
420
+ | 1 `ENEMY_PRESENT` | Eliminate enemy | `snapshot.enemyPresent` |
421
+ | 2 `DANGER` | Evade danger | `snapshot.hasDanger` |
422
+ | 3 `ANOMALY_AVOID` | Exit anomaly zone | `snapshot.nearAnomalyZone` |
423
+ | 4 `DEFAULT` | Patrol / idle | always (fallback) |
424
+
425
+ #### Integration example
283
426
 
284
427
  ```ts
285
- const goap = new GOAPController(ctx, goapConfig);
286
- goap.update(deltaMs); // ticks current action or replans if needed
428
+ import { GOAPController } from '@alife-sdk/ai/goap';
429
+ import { GOAPPlanner } from '@alife-sdk/core';
430
+ import type { IGOAPConfig } from '@alife-sdk/ai/types';
431
+ import type { INPCWorldSnapshot } from '@alife-sdk/ai/types';
432
+
433
+ // 1. Create a planner and register actions once (shared across NPCs of same type).
434
+ const planner = new GOAPPlanner();
435
+ planner.registerAction(new PatrolAction());
436
+ planner.registerAction(new TakeCoverAction());
437
+ planner.registerAction(new EngageEnemyAction());
438
+
439
+ // 2. Build config — replanIntervalMs drives periodic replanning.
440
+ const goapConfig: IGOAPConfig = {
441
+ replanIntervalMs: 5000, // replan every 5 s at minimum
442
+ eliteRankThreshold: 5,
443
+ healHpThreshold: 0.3,
444
+ maxPlanDepth: 6,
445
+ dangerMemoryMaxAge: 10000,
446
+ };
447
+
448
+ // 3. Create one GOAPController per NPC (in your per-NPC setup / state handler).
449
+ const goap = new GOAPController(planner, goapConfig);
450
+
451
+ // 4. Inside a state handler's update(), build a snapshot and tick GOAP.
452
+ update(ctx: INPCContext, deltaMs: number): void {
453
+ const snapshot: INPCWorldSnapshot = {
454
+ isAlive: ctx.health?.isAlive() ?? true,
455
+ hpRatio: ctx.health?.hpRatio() ?? 1,
456
+ hasWeapon: ctx.state.primaryWeapon !== null,
457
+ hasAmmo: ctx.state.hasAmmo,
458
+ inCover: ctx.state.hasTakenCover,
459
+ seeEnemy: (ctx.perception?.getVisibleEnemies().length ?? 0) > 0,
460
+ enemyPresent: ctx.state.lastKnownEnemyX !== 0,
461
+ enemyInRange: ctx.state.enemyInRange,
462
+ hasDanger: (ctx.danger?.getActiveZones().length ?? 0) > 0,
463
+ hasDangerGrenade: ctx.state.dangerGrenade,
464
+ enemyWounded: ctx.state.enemyWounded,
465
+ nearAnomalyZone: ctx.state.nearAnomaly,
466
+ };
467
+
468
+ const entity = ctx.entity; // IEntity — your game object adapter
469
+ const result = goap.update(deltaMs, entity, snapshot);
470
+
471
+ if (!result.handled) {
472
+ // GOAP has no plan — fall back to FSM transition
473
+ ctx.transition('IDLE');
474
+ }
475
+
476
+ // Force immediate replan when significant world change occurs:
477
+ // goap.invalidatePlan();
478
+ }
287
479
 
288
480
  // Custom world property builders and goal rules are opt-in:
289
481
  import { DEFAULT_WORLD_PROPERTY_BUILDERS,
290
482
  DEFAULT_GOAL_RULES } from '@alife-sdk/ai/goap';
291
483
  ```
292
484
 
485
+ ### Animation integration
486
+
487
+ `AnimationController` is a stateful per-NPC controller with debounce and
488
+ layer priority. It sits in front of your engine's animation API and
489
+ prevents redundant `play()` calls.
490
+
491
+ #### Layers
492
+
493
+ Animations are tagged with one of three `AnimLayer` values (defined as numeric
494
+ constants for priority comparison):
495
+
496
+ | Layer | Value | Typical use |
497
+ |---|---|---|
498
+ | `LEGS` | `0` | Walking, running, crouching, idle |
499
+ | `TORSO` | `1` | Combat stance, throw, fire |
500
+ | `HEAD` | `2` | (reserved — for facial rigs etc.) |
501
+
502
+ A higher numeric value wins when two layers compete. For example, a `TORSO`
503
+ animation (value `1`) overrides a `LEGS` animation (value `0`). The priority
504
+ mapping can be overridden via `ILayerPriorityMap`.
505
+
506
+ #### Debouncing
507
+
508
+ `request()` is a no-op if the same `key + layer` is already playing. This
509
+ means you can call it every frame without spamming the engine renderer.
510
+ `force()` bypasses both the debounce and the priority check — use it for
511
+ one-shot events such as death animations or ability effects.
512
+
513
+ #### Creating and using AnimationController
514
+
515
+ ```ts
516
+ import { AnimationController } from '@alife-sdk/ai/animation';
517
+ import { getAnimationRequest } from '@alife-sdk/ai/animation';
518
+ import type { IAnimationDriver } from '@alife-sdk/ai/animation';
519
+
520
+ // 1. Implement IAnimationDriver once for your engine.
521
+ // Phaser example:
522
+ class PhaserAnimDriver implements IAnimationDriver {
523
+ constructor(private readonly sprite: Phaser.GameObjects.Sprite) {}
524
+ play(key: string, opts: { loop: boolean; frameRate: number }): void {
525
+ this.sprite.anims.play({ key, loop: opts.loop, frameRate: opts.frameRate }, true);
526
+ }
527
+ hasAnimation(key: string): boolean {
528
+ return this.sprite.anims.exists(key);
529
+ }
530
+ }
531
+
532
+ // 2. Create one AnimationController per NPC.
533
+ const animController = new AnimationController({
534
+ driver: new PhaserAnimDriver(sprite),
535
+ // layerPriority: { [AnimLayer.TORSO]: 10 } — optional override
536
+ });
537
+
538
+ // 3. Inside a state handler's update(), resolve and request the animation.
539
+ update(ctx: INPCContext, deltaMs: number): void {
540
+ const req = getAnimationRequest({
541
+ state: ctx.driver.currentStateId, // e.g. 'COMBAT'
542
+ weaponCategory: ctx.state.primaryWeaponType, // e.g. 2 → 'rifle'
543
+ velocity: { x: ctx.vx, y: ctx.vy },
544
+ directionCache: this.dirCache, // DirectionCache — avoids atan2 every frame
545
+ });
546
+
547
+ // request() skips play() if the same key+layer is already active (debounce).
548
+ animController.request(req);
549
+
550
+ // For one-shot events — bypasses debounce and priority:
551
+ // animController.force({ key: 'death_rifle', loop: false, frameRate: 8,
552
+ // layer: AnimLayer.LEGS });
553
+ }
554
+
555
+ // 4. On respawn or object-pool recycle:
556
+ animController.reset();
557
+ ```
558
+
559
+ Key points:
560
+ - `getAnimationRequest()` builds the animation key from `state + weaponCategory + direction`.
561
+ Default key format: `{base}_{weapon}_{direction}`, e.g. `combat_rifle_SE`.
562
+ States with `omitDirection: true` (e.g. `DEAD`, `GRENADE`, `SLEEP`) use
563
+ `{base}_{weapon}` only.
564
+ - `DirectionCache.resolve(vx, vy)` caches the last 8-way compass direction and
565
+ only re-runs `atan2` when velocity changes by more than ~2 px/s.
566
+ - The controller is stateless in terms of NPC data — one instance per NPC,
567
+ but one `StateHandlerMap` can carry a shared `AnimationController` factory.
568
+
293
569
  ---
294
570
 
295
571
  ## Lifecycle
@@ -336,10 +612,12 @@ import { buildDefaultHandlerMap, OnlineAIDriver, ONLINE_STATE } from '@alife-sdk
336
612
  const ctx = buildStubContext({ hp: 100, targetId: 'enemy1' });
337
613
  const driver = new OnlineAIDriver(ctx, buildDefaultHandlerMap(), ONLINE_STATE.IDLE);
338
614
 
339
- driver.transitionTo(ONLINE_STATE.COMBAT);
615
+ // Transitions happen via ctx.transition() inside a state handler.
616
+ // To test a forced transition, put it inside a stub handler's enter/update:
617
+ // enter: (ctx) => ctx.transition(ONLINE_STATE.COMBAT)
340
618
  driver.update(16);
341
619
 
342
- expect(driver.currentState).toBe(ONLINE_STATE.COMBAT);
620
+ expect(driver.currentStateId).toBe(ONLINE_STATE.COMBAT);
343
621
  ```
344
622
 
345
623
  Tips:
@@ -383,3 +661,70 @@ src/
383
661
  ├── config/ IStateConfig, IStateTransitionMap, createDefaultStateConfig
384
662
  └── ports/ AI-specific port interfaces (IRestrictedZoneAccess, IHazardZoneAccess)
385
663
  ```
664
+
665
+ ---
666
+
667
+ ## Common pitfalls
668
+
669
+ **NPC stuck in a state — update() is called but the state never changes**
670
+
671
+ State transitions are only triggered by `ctx.transition()` being called from
672
+ inside a state handler's `enter()` or `update()`. If your state never calls
673
+ `ctx.transition()`, the driver stays in that state indefinitely.
674
+ Check the transition conditions in your handler: perception null-checks, timer
675
+ comparisons, and morale/health thresholds are the most common culprits.
676
+
677
+ **Transitions not firing — `ctx.transition()` is called externally but ignored**
678
+
679
+ `ctx.transition()` must be called from within a state handler's `enter()` or
680
+ `update()` method. Calling it from outside (e.g. from your game's event
681
+ handler directly) does nothing because the driver only processes transitions
682
+ during its own `update()` call. To force a state change from outside,
683
+ mutate `ctx.state` to put the NPC in the correct pre-condition, then let
684
+ the next `driver.update()` frame evaluate the transition naturally.
685
+
686
+ **Cover system returns null — NPC never finds a cover point**
687
+
688
+ Work through this checklist:
689
+ 1. `CoverRegistry` populated? Call `registry.getSize()` — if it returns `0`,
690
+ no points have been registered. Call `registry.addPoints([...])` during
691
+ scene setup.
692
+ 2. Cover points within search radius? The default `searchRadius` from `ICoverConfig`
693
+ must be larger than the distance between the NPC and the nearest point.
694
+ 3. All points locked? If `CoverLockRegistry` is in use, points expire
695
+ automatically after their TTL. Check that `ttlMs` is not set so high
696
+ that points remain locked indefinitely.
697
+ 4. Score threshold too strict? `minScoreThreshold` in `ICoverConfig` filters
698
+ out low-quality candidates. Lower it for sparse maps.
699
+
700
+ **Subsystem returning null — calls like `ctx.cover.findCover()` crash**
701
+
702
+ All subsystems on `INPCContext` are typed `T | null`. You must access them
703
+ with optional chaining:
704
+
705
+ ```ts
706
+ // Safe — no-op if cover is null:
707
+ const pt = ctx.cover?.findCover(ctx.x, ctx.y, ex, ey) ?? null;
708
+
709
+ // Safe — defaults to empty array:
710
+ const enemies = ctx.perception?.getVisibleEnemies() ?? [];
711
+
712
+ // Safe — defaults to 1 (full HP):
713
+ const hp = ctx.health?.hpRatio() ?? 1;
714
+ ```
715
+
716
+ Setting a subsystem to `null` on `INPCContext` silently disables the
717
+ features that depend on it — the built-in state handlers all guard with
718
+ optional chaining, so no code changes are needed in the handlers themselves.
719
+
720
+ **GOAP plan never advances — `result.handled` is always `false`**
721
+
722
+ The most common causes:
723
+ - No actions registered in `GOAPPlanner`. Call `planner.registerAction(...)` before
724
+ creating `GOAPController`.
725
+ - `INPCWorldSnapshot` already satisfies the selected goal. When the world state
726
+ already matches the goal, the planner returns an empty plan and the controller
727
+ yields `handled: false`. This is correct behaviour — GOAP is done.
728
+ - `action.isValid(entity)` returns `false` on every action. Each action
729
+ aborts immediately and the plan is marked invalid, triggering a replan loop.
730
+ Log `goap.getCurrentPlanIds()` and `goap.getLastGoalResult()` to diagnose.
@@ -1 +1 @@
1
- {"version":3,"file":"WeaponSelector.d.ts","sourceRoot":"","sources":["../../src/combat/WeaponSelector.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACtE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAEvE;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CAC7B;AAuID;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,sBAAsB,GAC7B,WAAW,GAAG,IAAI,CAqBpB;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,sBAAsB,GAC7B,OAAO,CAQT;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,sBAAsB,GAC7B,OAAO,CAMT"}
1
+ {"version":3,"file":"WeaponSelector.d.ts","sourceRoot":"","sources":["../../src/combat/WeaponSelector.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACtE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAEvE;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CAC7B;AAuID;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,sBAAsB,GAC7B,WAAW,GAAG,IAAI,CAoBpB;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,sBAAsB,GAC7B,OAAO,CAQT;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,sBAAsB,GAC7B,OAAO,CAMT"}
@@ -137,7 +137,6 @@ export function selectBestWeapon(ctx, config) {
137
137
  if (loadout.secondary && loadout.secondary.ammo > 0) {
138
138
  const secScore = weaponScore(loadout.secondary.category, distanceToEnemy, enemyCount, hpRatio, config);
139
139
  if (secScore > bestScore) {
140
- bestScore = secScore;
141
140
  bestSlot = loadout.secondary;
142
141
  }
143
142
  }
@@ -1 +1 @@
1
- {"version":3,"file":"WeaponSelector.js","sourceRoot":"","sources":["../../src/combat/WeaponSelector.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"WeaponSelector.js","sourceRoot":"","sources":["../../src/combat/WeaponSelector.ts"],"names":[],"mappings":"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"}
@@ -47,7 +47,7 @@ export class TakeCoverState {
47
47
  ctx.state.coverPointY = coverPt.y;
48
48
  }
49
49
  else {
50
- coverPt = null;
50
+ coverPt = null; // eslint-disable-line no-useless-assignment
51
51
  }
52
52
  }
53
53
  // If no cover found, we still enter — the NPC will try to move to last
@@ -1 +1 @@
1
- {"version":3,"file":"TakeCoverState.js","sourceRoot":"","sources":["../../../src/states/handlers/TakeCoverState.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"TakeCoverState.js","sourceRoot":"","sources":["../../../src/states/handlers/TakeCoverState.ts"],"names":[],"mappings":"AAAA,oCAAoC;AACpC,qEAAqE;AACrE,EAAE;AACF,wBAAwB;AACxB,8FAA8F;AAC9F,6EAA6E;AAC7E,gFAAgF;AAChF,mFAAmF;AACnF,EAAE;AACF,mBAAmB;AACnB,gCAAgC;AAChC,8BAA8B;AAC9B,iCAAiC;AACjC,EAAE;AACF,4DAA4D;AAC5D,wCAAwC;AAKxC,OAAO,EAAE,0BAA0B,EAAE,MAAM,wBAAwB,CAAC;AAEpE,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEtC;;;;GAIG;AACH,MAAM,OAAO,cAAc;IAIzB,YAAY,GAAiB,EAAE,EAAiC;QAC9D,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,EAAE,GAAG,0BAA0B,CAAC,EAAE,CAAC,CAAC;IAC3C,CAAC;IAED,KAAK,CAAC,GAAgB;QACpB,2DAA2D;QAC3D,MAAM,OAAO,GAAG,GAAG,CAAC,UAAU,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAAC;QAC1D,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;QAEjC,IAAI,OAAO,GAAoC,IAAI,CAAC;QAEpD,IAAI,GAAG,CAAC,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YACzC,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;QAChE,CAAC;aAAM,IAAI,GAAG,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC;YAC9B,2CAA2C;YAC3C,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;QAC5D,CAAC;QAED,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;YACrB,qEAAqE;YACrE,+DAA+D;YAC/D,MAAM,MAAM,GAAG,GAAG,CAAC,KAAK,EAAE,aAAa,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC;YAC7D,IAAI,MAAM,EAAE,CAAC;gBACX,GAAG,CAAC,KAAK,CAAC,WAAW,GAAG,OAAO,CAAC,CAAC,CAAC;gBAClC,GAAG,CAAC,KAAK,CAAC,WAAW,GAAG,OAAO,CAAC,CAAC,CAAC;YACpC,CAAC;iBAAM,CAAC;gBACN,OAAO,GAAG,IAAI,CAAC,CAAC,4CAA4C;YAC9D,CAAC;QACH,CAAC;QACD,uEAAuE;QACvE,sDAAsD;QAEtD,GAAG,CAAC,KAAK,CAAC,aAAa,GAAG,KAAK,CAAC;QAEhC,wDAAwD;QACxD,MAAM,YAAY,GAChB,IAAI,CAAC,GAAG,CAAC,iBAAiB;YAC1B,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,iBAAiB,GAAG,IAAI,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;QAE3E,GAAG,CAAC,KAAK,CAAC,QAAQ,GAAG;YACnB,KAAK,EAAE,MAAM;YACb,YAAY,EAAE,GAAG,CAAC,GAAG,EAAE;SACxB,CAAC;QAEF,iEAAiE;QACjE,mEAAmE;QACnE,mEAAmE;QACnE,2EAA2E;QAC3E,qEAAqE;QACrE,4EAA4E;QAC5E,GAAG,CAAC,KAAK,CAAC,aAAa,GAAG,GAAG,CAAC,GAAG,EAAE,GAAG,YAAY,CAAC;IACrD,CAAC;IAED,MAAM,CAAC,GAAgB,EAAE,QAAgB;QACvC,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,EAAE,CAAC;QAEtB,4EAA4E;QAC5E,kCAAkC;QAClC,4EAA4E;QAC5E,IAAI,GAAG,CAAC,KAAK,CAAC,WAAW,KAAK,UAAU,EAAE,CAAC;YACzC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,mBAAmB,CAAC,CAAC;YAC5C,OAAO;QACT,CAAC;QAED,IAAI,GAAG,CAAC,KAAK,CAAC,WAAW,KAAK,QAAQ,EAAE,CAAC;YACvC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,iBAAiB,CAAC,CAAC;YAC1C,OAAO;QACT,CAAC;QAED,MAAM,OAAO,GAAG,GAAG,CAAC,UAAU,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAAC;QAC1D,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;QAEpC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,kBAAkB,CAAC,CAAC;YAC3C,OAAO;QACT,CAAC;QAED,oCAAoC;QACpC,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QACzB,GAAG,CAAC,KAAK,CAAC,eAAe,GAAG,KAAK,CAAC,CAAC,CAAC;QACpC,GAAG,CAAC,KAAK,CAAC,eAAe,GAAG,KAAK,CAAC,CAAC,CAAC;QAEpC,4EAA4E;QAC5E,uDAAuD;QACvD,4EAA4E;QAC5E,IAAI,GAAG,CAAC,KAAK,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;YAChC,MAAM,YAAY,GAChB,IAAI,CAAC,GAAG,CAAC,iBAAiB;gBAC1B,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,iBAAiB,GAAG,IAAI,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;YAC3E,GAAG,CAAC,KAAK,CAAC,QAAQ,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,GAAG,EAAE,CAAC;YAC1D,GAAG,CAAC,KAAK,CAAC,aAAa,GAAG,GAAG,GAAG,YAAY,CAAC;QAC/C,CAAC;QAED,4EAA4E;QAC5E,wCAAwC;QACxC,4EAA4E;QAC5E,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,aAAa,EAAE,CAAC;YAC7B,MAAM,EAAE,GAAG,GAAG,CAAC,KAAK,CAAC,WAAW,GAAG,GAAG,CAAC,CAAC,CAAC;YACzC,MAAM,EAAE,GAAG,GAAG,CAAC,KAAK,CAAC,WAAW,GAAG,GAAG,CAAC,CAAC,CAAC;YACzC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;YAE1C,IAAI,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,eAAe,EAAE,CAAC;gBACpC,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,KAAK,CAAC,WAAW,EAAE,GAAG,CAAC,KAAK,CAAC,WAAW,EAAE,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;gBACtF,OAAO;YACT,CAAC;YACD,GAAG,CAAC,KAAK,CAAC,aAAa,GAAG,IAAI,CAAC;YAC/B,GAAG,CAAC,IAAI,EAAE,CAAC;QACb,CAAC;QAED,4EAA4E;QAC5E,gCAAgC;QAChC,4EAA4E;QAC5E,MAAM,QAAQ,GAAG,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC;QAEpC,QAAQ,QAAQ,CAAC,KAAK,EAAE,CAAC;YAEvB,0EAA0E;YAC1E,mCAAmC;YACnC,0EAA0E;YAC1E,KAAK,MAAM,CAAC,CAAC,CAAC;gBACZ,GAAG,CAAC,IAAI,EAAE,CAAC;gBACX,yDAAyD;gBACzD,IAAI,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,aAAa,EAAE,CAAC;oBACnC,QAAQ,CAAC,KAAK,GAAG,MAAM,CAAC;oBACxB,QAAQ,CAAC,YAAY,GAAG,GAAG,CAAC;gBAC9B,CAAC;gBACD,MAAM;YACR,CAAC;YAED,0EAA0E;YAC1E,2EAA2E;YAC3E,0EAA0E;YAC1E,KAAK,MAAM,CAAC,CAAC,CAAC;gBACZ,MAAM,OAAO,GAAG,GAAG,GAAG,QAAQ,CAAC,YAAY,CAAC;gBAC5C,IAAI,OAAO,IAAI,IAAI,CAAC,GAAG,CAAC,sBAAsB,EAAE,CAAC;oBAC/C,GAAG,CAAC,IAAI,EAAE,CAAC;oBACX,QAAQ,CAAC,KAAK,GAAG,MAAM,CAAC;oBACxB,QAAQ,CAAC,YAAY,GAAG,GAAG,CAAC;gBAC9B,CAAC;qBAAM,CAAC;oBACN,8DAA8D;oBAC9D,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,aAAa,GAAG,GAAG,CAAC,CAAC;gBAClE,CAAC;gBACD,MAAM;YACR,CAAC;YAED,0EAA0E;YAC1E,sCAAsC;YACtC,0EAA0E;YAC1E,KAAK,MAAM,CAAC,CAAC,CAAC;gBACZ,MAAM,OAAO,GAAG,GAAG,GAAG,QAAQ,CAAC,YAAY,CAAC;gBAC5C,GAAG,CAAC,IAAI,EAAE,CAAC;gBAEX,kBAAkB;gBAClB,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;gBAC3B,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;gBAC3B,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC;oBACzB,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;gBACtC,CAAC;gBAED,qBAAqB;gBACrB,IAAI,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,WAAW,IAAI,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC;oBACvD,GAAG,CAAC,KAAK,CAAC,WAAW,GAAG,GAAG,CAAC;oBAC5B,GAAG,CAAC,SAAS,CAAC;wBACZ,KAAK,EAAE,GAAG,CAAC,KAAK;wBAChB,CAAC,EAAE,GAAG,CAAC,CAAC;wBACR,CAAC,EAAE,GAAG,CAAC,CAAC;wBACR,OAAO,EAAE,KAAK,CAAC,CAAC;wBAChB,OAAO,EAAE,KAAK,CAAC,CAAC;wBAChB,UAAU,EAAE,GAAG,CAAC,KAAK,CAAC,aAAa,IAAI,OAAO;qBAC/C,CAAC,CAAC;gBACL,CAAC;gBAED,IAAI,OAAO,IAAI,IAAI,CAAC,GAAG,CAAC,sBAAsB,EAAE,CAAC;oBAC/C,QAAQ,CAAC,KAAK,GAAG,QAAQ,CAAC;oBAC1B,QAAQ,CAAC,YAAY,GAAG,GAAG,CAAC;gBAC9B,CAAC;gBACD,MAAM;YACR,CAAC;YAED,0EAA0E;YAC1E,0CAA0C;YAC1C,0EAA0E;YAC1E,KAAK,QAAQ,CAAC,CAAC,CAAC;gBACd,MAAM,OAAO,GAAG,GAAG,GAAG,QAAQ,CAAC,YAAY,CAAC;gBAE5C,IAAI,OAAO,IAAI,IAAI,CAAC,GAAG,CAAC,wBAAwB,EAAE,CAAC;oBACjD,GAAG,CAAC,IAAI,EAAE,CAAC;oBACX,yBAAyB;oBACzB,MAAM,YAAY,GAChB,IAAI,CAAC,GAAG,CAAC,iBAAiB;wBAC1B,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,iBAAiB,GAAG,IAAI,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;oBAC3E,QAAQ,CAAC,KAAK,GAAG,MAAM,CAAC;oBACxB,QAAQ,CAAC,YAAY,GAAG,GAAG,CAAC;oBAC5B,GAAG,CAAC,KAAK,CAAC,aAAa,GAAG,GAAG,GAAG,YAAY,CAAC;gBAC/C,CAAC;qBAAM,CAAC;oBACN,gCAAgC;oBAChC,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,KAAK,CAAC,WAAW,EAAE,GAAG,CAAC,KAAK,CAAC,WAAW,EAAE,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;gBACxF,CAAC;gBACD,MAAM;YACR,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,CAAC,GAAgB;QACnB,GAAG,CAAC,KAAK,CAAC,aAAa,GAAG,KAAK,CAAC;QAChC,GAAG,CAAC,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC;QAC1B,GAAG,CAAC,KAAK,EAAE,SAAS,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACpC,CAAC;CACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alife-sdk/ai",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "description": "Online frame-based NPC behavior system",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -107,12 +107,12 @@
107
107
  "access": "public"
108
108
  },
109
109
  "dependencies": {
110
- "@alife-sdk/core": "0.1.0"
110
+ "@alife-sdk/core": "0.3.0"
111
111
  },
112
112
  "devDependencies": {
113
113
  "typescript": "^5.9.3",
114
114
  "vitest": "^4.0.18",
115
- "@alife-sdk/hazards": "0.1.0"
115
+ "@alife-sdk/hazards": "0.3.0"
116
116
  },
117
117
  "scripts": {
118
118
  "build": "tsc",