feat: integrate constitution into needs decay rates
High constitution slows hunger/energy decay, low constitution speeds it. Uses getEffectiveStat helper which defaults to 10 for entities without stats, preserving backward compatibility. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -4,7 +4,7 @@ import { GameMap } from '../../map/GameMap.js';
|
||||
import { needsDecaySystem } from '../needsDecaySystem.js';
|
||||
import { npcBrainSystem } from '../npcBrainSystem.js';
|
||||
import { movementSystem } from '../movementSystem.js';
|
||||
import type { Needs, Movement, NPCBrain, Position, SocialState } from '@dflike/shared';
|
||||
import type { Needs, Movement, NPCBrain, Position, SocialState, Stats, StatModifiers } from '@dflike/shared';
|
||||
import { HUNGER_DECAY_PER_TICK, ENERGY_DECAY_PER_TICK, MOVE_SPEED } from '@dflike/shared';
|
||||
|
||||
function createNPC(world: World, x: number, y: number, hunger = 80, energy = 80) {
|
||||
@@ -16,6 +16,16 @@ function createNPC(world: World, x: number, y: number, hunger = 80, energy = 80)
|
||||
return e;
|
||||
}
|
||||
|
||||
function addStats(world: World, entity: number, overrides: Partial<Stats> = {}): void {
|
||||
const base: Stats = {
|
||||
strength: 10, dexterity: 10, constitution: 10, intelligence: 10, perception: 10,
|
||||
sociability: 10, courage: 10, curiosity: 10, empathy: 10, temperament: 10,
|
||||
...overrides,
|
||||
};
|
||||
world.addComponent<Stats>(entity, 'stats', base);
|
||||
world.addComponent<StatModifiers>(entity, 'statModifiers', { modifiers: [] });
|
||||
}
|
||||
|
||||
function addSocialState(world: World, entity: number, phase: SocialState['phase'] = 'none') {
|
||||
world.addComponent<SocialState>(entity, 'socialState', {
|
||||
phase,
|
||||
@@ -37,6 +47,34 @@ describe('needsDecaySystem', () => {
|
||||
expect(needs.energy).toBeCloseTo(50 - ENERGY_DECAY_PER_TICK);
|
||||
});
|
||||
|
||||
it('high constitution slows hunger decay', () => {
|
||||
const world = new World();
|
||||
const e = createNPC(world, 0, 0, 50, 50);
|
||||
addStats(world, e, { constitution: 14 });
|
||||
needsDecaySystem(world);
|
||||
const needs = world.getComponent<Needs>(e, 'needs')!;
|
||||
const expectedDecay = HUNGER_DECAY_PER_TICK * (1 - (14 - 10) * 0.03);
|
||||
expect(needs.hunger).toBeCloseTo(50 - expectedDecay);
|
||||
});
|
||||
|
||||
it('low constitution speeds hunger decay', () => {
|
||||
const world = new World();
|
||||
const e = createNPC(world, 0, 0, 50, 50);
|
||||
addStats(world, e, { constitution: 6 });
|
||||
needsDecaySystem(world);
|
||||
const needs = world.getComponent<Needs>(e, 'needs')!;
|
||||
const expectedDecay = HUNGER_DECAY_PER_TICK * (1 - (6 - 10) * 0.03);
|
||||
expect(needs.hunger).toBeCloseTo(50 - expectedDecay);
|
||||
});
|
||||
|
||||
it('uses default decay when entity has no stats', () => {
|
||||
const world = new World();
|
||||
const e = createNPC(world, 0, 0, 50, 50);
|
||||
needsDecaySystem(world);
|
||||
const needs = world.getComponent<Needs>(e, 'needs')!;
|
||||
expect(needs.hunger).toBeCloseTo(50 - HUNGER_DECAY_PER_TICK);
|
||||
});
|
||||
|
||||
it('clamps needs at 0', () => {
|
||||
const world = new World();
|
||||
const e = createNPC(world, 0, 0, 0.01, 0.01);
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
import { HUNGER_DECAY_PER_TICK, ENERGY_DECAY_PER_TICK, type Needs } from '@dflike/shared';
|
||||
import type { World } from '../ecs/World.js';
|
||||
import { getEffectiveStat } from './statHelpers.js';
|
||||
|
||||
export function needsDecaySystem(world: World): void {
|
||||
for (const entity of world.query('needs')) {
|
||||
const needs = world.getComponent<Needs>(entity, 'needs')!;
|
||||
needs.hunger = Math.max(0, needs.hunger - HUNGER_DECAY_PER_TICK);
|
||||
needs.energy = Math.max(0, needs.energy - ENERGY_DECAY_PER_TICK);
|
||||
const con = getEffectiveStat(world, entity, 'constitution');
|
||||
const conMultiplier = 1 - (con - 10) * 0.03;
|
||||
needs.hunger = Math.max(0, needs.hunger - HUNGER_DECAY_PER_TICK * conMultiplier);
|
||||
needs.energy = Math.max(0, needs.energy - ENERGY_DECAY_PER_TICK * conMultiplier);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user