feat(golemancy): Phase 1 - Component-based construction system data definitions
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 1m18s
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 1m18s
- Add new golem component types (Core, Frame, MindCircuit, Enchantment) - Create 4 Core tiers, 7 Frames, 4 Mind Circuits, 8 Enchantments - Rewrite golem utils for component-based stat computation - Update GolemancyState with new fields (golemDesigns, golemLoadout, activeGolems) - Update combat store, actions, and pipelines for new golem system - Rewrite GolemancyTab with component selection UI - Update fabricator discipline perks for new system - Add comprehensive tests for component registries and utilities - All files under 400 lines, all 743 tests passing
This commit is contained in:
@@ -1,19 +1,26 @@
|
||||
// ─── Golem Combat Pipeline ─────────────────────────────────────────────────────
|
||||
// Extracts golem combat setup from gameStore.ts tick()
|
||||
// to keep the coordinator under the 400-line file limit.
|
||||
// ─── Golem Combat Pipeline (Component-Based) ─────────────────────────────────
|
||||
// Pipeline integration for the component-based golem combat system.
|
||||
// Extracts golem combat setup from gameStore.ts tick() to keep the coordinator
|
||||
// under the 400-line file limit.
|
||||
|
||||
import { useCombatStore } from '../combatStore';
|
||||
import { useManaStore } from '../manaStore';
|
||||
import { processGolemRoomDuration } from '../golem-combat-actions';
|
||||
import { lowestHPEnemy } from '../combat-damage';
|
||||
import type { ActiveGolem, EnemyState } from '../../types';
|
||||
import {
|
||||
summonGolemsOnRoomEntry,
|
||||
processGolemMaintenance,
|
||||
processGolemManaRegen,
|
||||
processGolemAttacks,
|
||||
countdownGolemRoomDuration,
|
||||
} from '../golem-combat-actions';
|
||||
import { useAttunementStore } from '../attunementStore';
|
||||
import type { RuntimeActiveGolem } from '../../types';
|
||||
|
||||
export interface GolemCombatContext {
|
||||
addLog: (msg: string) => void;
|
||||
ctx: {
|
||||
combat: {
|
||||
currentFloor: number;
|
||||
currentRoom: { roomType: string; unknown: Array<{ name: string }> };
|
||||
currentRoom: { roomType: string; enemies: Array<{ name: string; hp: number; maxHP: number; armor: number }> };
|
||||
};
|
||||
prestige: { signedPacts: number[] };
|
||||
};
|
||||
@@ -22,20 +29,29 @@ export interface GolemCombatContext {
|
||||
maxMana: number;
|
||||
}
|
||||
|
||||
export interface GolemCombatResult {
|
||||
export interface GolemCombatPipelineResult {
|
||||
rawMana: number;
|
||||
elements: Record<string, { current: number; max: number; unlocked: boolean }>;
|
||||
activeGolems: RuntimeActiveGolem[];
|
||||
logMessages: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the golem combat pipeline for the current tick.
|
||||
* Returns golem state needed by processCombatTick.
|
||||
*/
|
||||
export function buildGolemCombatPipeline(_addLog: (msg: string) => void): {
|
||||
activeGolems: ActiveGolem[];
|
||||
activeGolems: RuntimeActiveGolem[];
|
||||
golemDesigns: Record<string, { id: string; name: string; coreId: string; frameId: string; mindCircuitId: string; enchantmentIds: string[]; selectedManaTypes: string[]; selectedSpells: string[] }>;
|
||||
golemApplyDamageToRoom: (dmg: number) => { floorHP: number; floorMaxHP: number; roomCleared: boolean };
|
||||
} {
|
||||
const activeGolems = useCombatStore.getState().golemancy?.activeGolems ?? [];
|
||||
const combatState = useCombatStore.getState();
|
||||
const golemancy = combatState.golemancy;
|
||||
|
||||
// New component-based active golems
|
||||
const activeGolems = golemancy?.activeGolems ?? [];
|
||||
|
||||
// Reconstruct golem designs from store
|
||||
const golemDesigns = golemancy?.golemDesigns ?? {};
|
||||
|
||||
const golemApplyDamageToRoom = (dmg: number) => {
|
||||
const cs = useCombatStore.getState();
|
||||
@@ -44,14 +60,19 @@ export function buildGolemCombatPipeline(_addLog: (msg: string) => void): {
|
||||
return { floorHP: cs.floorHP, floorMaxHP: cs.floorMaxHP, roomCleared: false };
|
||||
}
|
||||
|
||||
// Golems use focus-fire targeting (spec §9.4) — target lowest HP enemy
|
||||
const target = lowestHPEnemy(room.enemies);
|
||||
if (!target) {
|
||||
// Focus-fire targeting: target lowest HP enemy
|
||||
let target = room.enemies[0];
|
||||
for (const e of room.enemies) {
|
||||
if (e.hp > 0 && e.hp < (target?.hp ?? Infinity)) {
|
||||
target = e;
|
||||
}
|
||||
}
|
||||
if (!target || target.hp <= 0) {
|
||||
return { floorHP: cs.floorHP, floorMaxHP: cs.floorMaxHP, roomCleared: false };
|
||||
}
|
||||
|
||||
const updatedEnemies = room.enemies.map((enemy) => {
|
||||
if (enemy.id === target.id && enemy.hp > 0) {
|
||||
if (enemy.id === target!.id && enemy.hp > 0) {
|
||||
return { ...enemy, hp: Math.max(0, enemy.hp - dmg) };
|
||||
}
|
||||
return enemy;
|
||||
@@ -68,5 +89,32 @@ export function buildGolemCombatPipeline(_addLog: (msg: string) => void): {
|
||||
return { floorHP: newFloorHP, floorMaxHP: cs.floorMaxHP, roomCleared: allDead };
|
||||
};
|
||||
|
||||
return { activeGolems, golemApplyDamageToRoom };
|
||||
return { activeGolems, golemDesigns, golemApplyDamageToRoom };
|
||||
}
|
||||
|
||||
/**
|
||||
* Process golem summoning on room entry.
|
||||
*/
|
||||
export function processGolemRoomEntry(
|
||||
loadout: { enabled: boolean; designId: string; design: { name: string } }[],
|
||||
currentFloor: number,
|
||||
): {
|
||||
rawMana: number;
|
||||
elements: Record<string, { current: number; max: number; unlocked: boolean }>;
|
||||
activeGolems: RuntimeActiveGolem[];
|
||||
logMessages: string[];
|
||||
} {
|
||||
const cs = useCombatStore.getState();
|
||||
const attStore = useAttunementStore.getState();
|
||||
const fabLevel = attStore.attunements?.fabricator?.level ?? 0;
|
||||
const discBonus = 0; // TODO: compute from discipline
|
||||
|
||||
return summonGolemsOnRoomEntry(
|
||||
loadout as any,
|
||||
useManaStore.getState().rawMana,
|
||||
useManaStore.getState().elements as any,
|
||||
currentFloor,
|
||||
cs.golemancy.activeGolems as any[],
|
||||
discBonus,
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user