@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 +370 -25
- package/dist/combat/WeaponSelector.d.ts.map +1 -1
- package/dist/combat/WeaponSelector.js +0 -1
- package/dist/combat/WeaponSelector.js.map +1 -1
- package/dist/states/handlers/TakeCoverState.js +1 -1
- package/dist/states/handlers/TakeCoverState.js.map +1 -1
- package/package.json +3 -3
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.
|
|
82
|
+
const state = driver.currentStateId; // e.g. 'COMBAT'
|
|
82
83
|
|
|
83
|
-
// 7. Force a state transition (e.g. on NPC death)
|
|
84
|
-
|
|
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` |
|
|
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.
|
|
172
|
-
|
|
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
|
-
|
|
246
|
-
|
|
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.
|
|
264
|
-
4. **Loopholes** — each cover point has 1–
|
|
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
|
-
|
|
282
|
-
sequences. Replanning happens
|
|
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
|
-
|
|
286
|
-
|
|
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
|
-
|
|
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.
|
|
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,
|
|
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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"}
|
|
@@ -1 +1 @@
|
|
|
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;
|
|
1
|
+
{"version":3,"file":"TakeCoverState.js","sourceRoot":"","sources":["../../../src/states/handlers/TakeCoverState.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alife-sdk/ai",
|
|
3
|
-
"version": "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.
|
|
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.
|
|
115
|
+
"@alife-sdk/hazards": "0.3.0"
|
|
116
116
|
},
|
|
117
117
|
"scripts": {
|
|
118
118
|
"build": "tsc",
|