Files
dflike/server/src/systems/gatheringSystem.ts
T
2026-03-08 22:49:47 +00:00

69 lines
2.5 KiB
TypeScript

import {
PRODUCTIVITY_RECOVERY_RATE, PRODUCTIVITY_THRESHOLD,
type Needs, type Movement, type NPCBrain, type Position,
} from '@dflike/shared';
import type { World } from '../ecs/World.js';
import type { GameMap } from '../map/GameMap.js';
import { getEffectiveStat } from './statHelpers.js';
import { addItem } from '../industry/inventoryHelpers.js';
import { industryConfig } from '../config/industryConfig.js';
export interface GatheringState {
resourceType: string;
ticksRemaining: number;
}
export function gatheringSystem(world: World, map: GameMap): void {
for (const entity of world.query('npcBrain', 'position', 'needs', 'movement')) {
const brain = world.getComponent<NPCBrain>(entity, 'npcBrain')!;
if (brain.currentGoal !== 'gather') continue;
const pos = world.getComponent<Position>(entity, 'position')!;
const needs = world.getComponent<Needs>(entity, 'needs')!;
const movement = world.getComponent<Movement>(entity, 'movement')!;
const gs = world.getComponent<GatheringState>(entity, 'gatheringState');
// Already gathering — tick down
if (gs) {
gs.ticksRemaining--;
needs.productivity = Math.min(100, needs.productivity + PRODUCTIVITY_RECOVERY_RATE);
if (gs.ticksRemaining <= 0) {
// Complete: add resource to inventory
const inv = world.getComponent<Map<string, number>>(entity, 'inventory');
if (inv) {
addItem(inv, gs.resourceType, industryConfig.gatherYield);
}
world.removeComponent(entity, 'gatheringState');
// Decide next action
if (needs.productivity >= PRODUCTIVITY_THRESHOLD) {
brain.currentGoal = 'wander';
}
// else brain stays on 'gather', npcBrain will pick new target next tick
}
continue;
}
// Not yet gathering — check if at resource tile and idle
if (movement.state !== 'idle') continue;
const resourceTile = map.resourceTiles.find(r => r.x === pos.x && r.y === pos.y);
if (!resourceTile) continue;
// Start gathering
const str = getEffectiveStat(world, entity, 'strength');
const baseTicks = industryConfig.gatherBaseTicks;
const ticks = Math.max(1, Math.round(baseTicks * (1 - (str - 10) * industryConfig.gatherStrengthModifier)));
world.addComponent<GatheringState>(entity, 'gatheringState', {
resourceType: resourceTile.resourceType,
ticksRemaining: ticks,
});
// Recover productivity on first tick too
needs.productivity = Math.min(100, needs.productivity + PRODUCTIVITY_RECOVERY_RATE);
}
}