feat: add getEffectiveStat helper for computed stat values
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { World } from '../../ecs/World.js';
|
||||
import { getEffectiveStat } from '../statHelpers.js';
|
||||
import type { Stats, StatModifiers } from '@dflike/shared';
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
describe('getEffectiveStat', () => {
|
||||
it('returns base stat when no modifiers', () => {
|
||||
const world = new World();
|
||||
const e = world.createEntity();
|
||||
addStats(world, e, { strength: 14 });
|
||||
expect(getEffectiveStat(world, e, 'strength')).toBe(14);
|
||||
});
|
||||
|
||||
it('adds positive modifier', () => {
|
||||
const world = new World();
|
||||
const e = world.createEntity();
|
||||
addStats(world, e, { empathy: 12 });
|
||||
world.addComponent<StatModifiers>(e, 'statModifiers', {
|
||||
modifiers: [{ stat: 'empathy', value: 2, remaining: 50 }],
|
||||
});
|
||||
expect(getEffectiveStat(world, e, 'empathy')).toBe(14);
|
||||
});
|
||||
|
||||
it('adds negative modifier', () => {
|
||||
const world = new World();
|
||||
const e = world.createEntity();
|
||||
addStats(world, e, { intelligence: 10 });
|
||||
world.addComponent<StatModifiers>(e, 'statModifiers', {
|
||||
modifiers: [{ stat: 'intelligence', value: -2, remaining: 50 }],
|
||||
});
|
||||
expect(getEffectiveStat(world, e, 'intelligence')).toBe(8);
|
||||
});
|
||||
|
||||
it('clamps to minimum 3', () => {
|
||||
const world = new World();
|
||||
const e = world.createEntity();
|
||||
addStats(world, e, { dexterity: 4 });
|
||||
world.addComponent<StatModifiers>(e, 'statModifiers', {
|
||||
modifiers: [{ stat: 'dexterity', value: -5, remaining: 50 }],
|
||||
});
|
||||
expect(getEffectiveStat(world, e, 'dexterity')).toBe(3);
|
||||
});
|
||||
|
||||
it('clamps to maximum 18', () => {
|
||||
const world = new World();
|
||||
const e = world.createEntity();
|
||||
addStats(world, e, { strength: 17 });
|
||||
world.addComponent<StatModifiers>(e, 'statModifiers', {
|
||||
modifiers: [{ stat: 'strength', value: 5, remaining: 50 }],
|
||||
});
|
||||
expect(getEffectiveStat(world, e, 'strength')).toBe(18);
|
||||
});
|
||||
|
||||
it('sums multiple modifiers for same stat', () => {
|
||||
const world = new World();
|
||||
const e = world.createEntity();
|
||||
addStats(world, e, { sociability: 10 });
|
||||
world.addComponent<StatModifiers>(e, 'statModifiers', {
|
||||
modifiers: [
|
||||
{ stat: 'sociability', value: 2, remaining: 50 },
|
||||
{ stat: 'sociability', value: -1, remaining: 30 },
|
||||
],
|
||||
});
|
||||
expect(getEffectiveStat(world, e, 'sociability')).toBe(11);
|
||||
});
|
||||
|
||||
it('floors float base stats to integer', () => {
|
||||
const world = new World();
|
||||
const e = world.createEntity();
|
||||
addStats(world, e, { courage: 10.7 });
|
||||
expect(getEffectiveStat(world, e, 'courage')).toBe(10);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,15 @@
|
||||
import type { Stats, StatName, StatModifiers } from '@dflike/shared';
|
||||
import type { World } from '../ecs/World.js';
|
||||
|
||||
export function getEffectiveStat(world: World, entity: number, stat: StatName): number {
|
||||
const base = world.getComponent<Stats>(entity, 'stats');
|
||||
if (!base) return 10; // fallback for entities without stats
|
||||
let value = base[stat];
|
||||
const mods = world.getComponent<StatModifiers>(entity, 'statModifiers');
|
||||
if (mods) {
|
||||
for (const m of mods.modifiers) {
|
||||
if (m.stat === stat) value += m.value;
|
||||
}
|
||||
}
|
||||
return Math.max(3, Math.min(18, Math.floor(value)));
|
||||
}
|
||||
Reference in New Issue
Block a user