diff --git a/server/src/game/GameLoop.ts b/server/src/game/GameLoop.ts index ebbf084..c75dd27 100644 --- a/server/src/game/GameLoop.ts +++ b/server/src/game/GameLoop.ts @@ -5,6 +5,7 @@ import { needsDecaySystem } from '../systems/needsDecaySystem.js'; import { npcBrainSystem } from '../systems/npcBrainSystem.js'; import { movementSystem } from '../systems/movementSystem.js'; import { socialSystem } from '../systems/socialSystem.js'; +import { statModifierSystem } from '../systems/statModifierSystem.js'; import { spawnNPC } from './spawner.js'; export class GameLoop { @@ -61,6 +62,7 @@ export class GameLoop { this.tick++; // Run systems in order + statModifierSystem(this.world); needsDecaySystem(this.world); npcBrainSystem(this.world, this.map); socialSystem(this.world); diff --git a/server/src/game/__tests__/spawner.test.ts b/server/src/game/__tests__/spawner.test.ts index 9c7b092..1b3e942 100644 --- a/server/src/game/__tests__/spawner.test.ts +++ b/server/src/game/__tests__/spawner.test.ts @@ -2,7 +2,7 @@ import { describe, it, expect } from 'vitest'; import { World } from '../../ecs/World.js'; import { GameMap } from '../../map/GameMap.js'; import { spawnNPC } from '../spawner.js'; -import type { Position } from '@dflike/shared'; +import type { Position, Stats } from '@dflike/shared'; describe('spawnNPC', () => { it('spawns at random position when no hint given', () => { @@ -44,5 +44,18 @@ describe('spawnNPC', () => { expect(world.getComponent(entity, 'appearance')).toBeDefined(); expect(world.getComponent(entity, 'name')).toBeDefined(); expect(world.getComponent(entity, 'socialState')).toBeDefined(); + expect(world.getComponent(entity, 'stats')).toBeDefined(); + expect(world.getComponent(entity, 'statModifiers')).toBeDefined(); + }); + + it('generates stats in 3-18 range', () => { + const world = new World(); + const map = new GameMap(); + const entity = spawnNPC(world, map); + const stats = world.getComponent(entity, 'stats')!; + for (const key of Object.keys(stats) as (keyof Stats)[]) { + expect(stats[key]).toBeGreaterThanOrEqual(3); + expect(stats[key]).toBeLessThanOrEqual(18); + } }); }); diff --git a/server/src/game/spawner.ts b/server/src/game/spawner.ts index ef0350f..bf110ca 100644 --- a/server/src/game/spawner.ts +++ b/server/src/game/spawner.ts @@ -2,7 +2,8 @@ import type { World } from '../ecs/World.js'; import type { GameMap } from '../map/GameMap.js'; import { generateRandomAppearance } from '../spawner/appearanceGenerator.js'; import { generateName } from '../spawner/nameGenerator.js'; -import type { EntityId, Position, Needs, Movement, NPCBrain, Appearance, SocialState } from '@dflike/shared'; +import { generateStats } from '../spawner/statGenerator.js'; +import type { EntityId, Position, Needs, Movement, NPCBrain, Appearance, SocialState, Stats, StatModifiers } from '@dflike/shared'; export function spawnNPC(world: World, map: GameMap, positionHint?: Position): EntityId { const entity = world.createEntity(); @@ -36,6 +37,8 @@ export function spawnNPC(world: World, map: GameMap, positionHint?: Position): E globalCooldown: 0, pairCooldowns: new Map(), }); + world.addComponent(entity, 'stats', generateStats()); + world.addComponent(entity, 'statModifiers', { modifiers: [] }); return entity; }