feat(server): add pickup system for NPC stockpile material retrieval
NPCs can now retrieve crafting materials from stockpiles instead of always gathering raw resources. The industry system checks if a stockpile has needed materials before falling back to gathering. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -7,6 +7,7 @@ import type { GameMap } from '../map/GameMap.js';
|
||||
import type { GatheringState } from './gatheringSystem.js';
|
||||
import type { CraftingState } from './craftingSystem.js';
|
||||
import type { BuildingState, StructureData } from './buildingSystem.js';
|
||||
import type { PickupState } from './pickupSystem.js';
|
||||
import { RecipeRegistry } from '../industry/recipeRegistry.js';
|
||||
import { getEffectiveStat } from './statHelpers.js';
|
||||
import { industryConfig } from '../config/industryConfig.js';
|
||||
@@ -56,6 +57,7 @@ export function industrySystem(world: World, map: GameMap): void {
|
||||
if (brain.currentGoal === 'gather' && world.getComponent<GatheringState>(entity, 'gatheringState')) continue;
|
||||
if (brain.currentGoal === 'gather' || brain.currentGoal === 'eat' || brain.currentGoal === 'rest') continue;
|
||||
if (brain.currentGoal === 'dropoff') continue;
|
||||
if (brain.currentGoal === 'pickup') continue;
|
||||
|
||||
const inv = world.getComponent<Map<string, number>>(entity, 'inventory')!;
|
||||
const pos = world.getComponent<Position>(entity, 'position')!;
|
||||
@@ -114,6 +116,46 @@ export function industrySystem(world: World, map: GameMap): void {
|
||||
}
|
||||
if (didBuild) continue;
|
||||
|
||||
// Try pickup from stockpile for crafting
|
||||
let didPickup = false;
|
||||
const allCraftRecipes = registry.getAll().filter(r => !r.id.startsWith('build_'));
|
||||
for (const recipe of allCraftRecipes) {
|
||||
const neededItems: { itemId: string; quantity: number }[] = [];
|
||||
|
||||
for (const input of recipe.inputs) {
|
||||
const haveInInv = inv.get(input.itemId) ?? 0;
|
||||
const stillNeed = input.quantity - haveInInv;
|
||||
if (stillNeed > 0) {
|
||||
neededItems.push({ itemId: input.itemId, quantity: stillNeed });
|
||||
}
|
||||
}
|
||||
|
||||
if (neededItems.length === 0) continue; // NPC can already craft — handled above
|
||||
|
||||
// Find a stockpile that has all needed items
|
||||
let stockpileEntity: number | null = null;
|
||||
for (const sEntity of world.query('structure', 'position')) {
|
||||
const sData = world.getComponent<StructureData>(sEntity, 'structure')!;
|
||||
if (sData.type !== 'stockpile' || sData.buildProgress !== undefined) continue;
|
||||
const hasAll = neededItems.every(n => (sData.inventory.get(n.itemId) ?? 0) >= n.quantity);
|
||||
if (hasAll) {
|
||||
stockpileEntity = sEntity;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (stockpileEntity !== null) {
|
||||
brain.currentGoal = 'pickup';
|
||||
world.addComponent<PickupState>(entity, 'pickupState', {
|
||||
stockpileEntityId: stockpileEntity,
|
||||
items: neededItems,
|
||||
});
|
||||
didPickup = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (didPickup) continue;
|
||||
|
||||
// Fallback: gather
|
||||
brain.currentGoal = 'gather';
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user