chore: golemancy redesign cleanup — remove orphaned legacy code and update docs
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 1m19s
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 1m19s
This commit is contained in:
@@ -21,6 +21,7 @@ export function LeftPanel() {
|
||||
const rawMana = useManaStore((s) => s.rawMana);
|
||||
const elements = useManaStore((s) => s.elements);
|
||||
const meditateTicks = useManaStore((s) => s.meditateTicks);
|
||||
const elementRegen = useManaStore((s) => s.elementRegen);
|
||||
const prestigeUpgrades = usePrestigeStore((s) => s.prestigeUpgrades);
|
||||
const equippedInstances = useCraftingStore((s) => s.equippedInstances);
|
||||
const equipmentInstances = useCraftingStore((s) => s.equipmentInstances);
|
||||
@@ -77,6 +78,7 @@ export function LeftPanel() {
|
||||
onGatherStart={handleGatherStart}
|
||||
onGatherEnd={handleGatherEnd}
|
||||
elements={elements}
|
||||
elementRegen={elementRegen}
|
||||
/>
|
||||
</DebugName>
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
createActiveGolem,
|
||||
} from '@/lib/game/data/golems/utils';
|
||||
import type { GolemDesign } from '@/lib/game/data/golems/types';
|
||||
import type { RuntimeActiveGolem } from '@/lib/game/types';
|
||||
|
||||
// ─── Helper ───────────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -274,9 +275,9 @@ describe('canAffordGolemDesign', () => {
|
||||
// ─── Active Golem Creation ────────────────────────────────────────────────────
|
||||
|
||||
describe('createActiveGolem', () => {
|
||||
it('creates active golem with correct initial state', () => {
|
||||
it('creates RuntimeActiveGolem with correct initial state', () => {
|
||||
const design = makeDesign('basic', 'earth', 'simple');
|
||||
const active = createActiveGolem(design, 5);
|
||||
const active = createActiveGolem(design, 5) as RuntimeActiveGolem;
|
||||
|
||||
expect(active.designId).toBe(design.id);
|
||||
expect(active.summonedFloor).toBe(5);
|
||||
@@ -288,7 +289,7 @@ describe('createActiveGolem', () => {
|
||||
|
||||
it('guardian golem starts with full mana', () => {
|
||||
const design = makeDesign('guardian', 'crystalSteelHybrid', 'guardian');
|
||||
const active = createActiveGolem(design, 10);
|
||||
const active = createActiveGolem(design, 10) as RuntimeActiveGolem;
|
||||
|
||||
expect(active.currentMana).toBe(500);
|
||||
expect(active.roomsRemaining).toBe(8);
|
||||
|
||||
@@ -16,7 +16,7 @@ export type {
|
||||
ComputedGolemStats,
|
||||
GolemManaCost,
|
||||
GolemUnlockRequirement,
|
||||
ActiveGolemV2,
|
||||
|
||||
} from './types';
|
||||
|
||||
export { elemCost, rawCost } from './types';
|
||||
|
||||
@@ -135,18 +135,3 @@ export interface ComputedGolemStats {
|
||||
specialEffect: FrameSpecial;
|
||||
}
|
||||
|
||||
// ─── Runtime Active Golem (in combat) ───────────────────────────────────
|
||||
|
||||
export interface ActiveGolemV2 {
|
||||
/** Reference to the GolemDesign used */
|
||||
designId: string;
|
||||
design: GolemDesign;
|
||||
summonedFloor: number;
|
||||
attackProgress: number;
|
||||
roomsRemaining: number;
|
||||
currentMana: number;
|
||||
/** Index for alternating/cycling spells */
|
||||
spellCastIndex: number;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
// ─── Golem Helper Functions ──────────────────────────────────────────────
|
||||
// Component-based construction system utilities.
|
||||
|
||||
import type { RuntimeActiveGolem } from '../../types';
|
||||
import type {
|
||||
ComputedGolemStats,
|
||||
GolemDesign,
|
||||
GolemManaCost,
|
||||
GolemUnlockRequirement,
|
||||
ActiveGolemV2,
|
||||
} from './types';
|
||||
import { CORES } from './cores';
|
||||
import { FRAMES } from './frames';
|
||||
@@ -144,22 +144,21 @@ export function canAffordGolemDesign(
|
||||
return { canAfford: true, missing: '' };
|
||||
}
|
||||
|
||||
// ─── Active Golem V2 Helpers ──────────────────────────────────────────────
|
||||
// ─── Active Golem Helpers ─────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* Create a new ActiveGolemV2 from a GolemDesign for combat.
|
||||
* Create a new RuntimeActiveGolem from a GolemDesign for combat.
|
||||
*/
|
||||
export function createActiveGolem(
|
||||
design: GolemDesign,
|
||||
currentFloor: number,
|
||||
): ActiveGolemV2 {
|
||||
): RuntimeActiveGolem {
|
||||
return {
|
||||
designId: design.id,
|
||||
design,
|
||||
summonedFloor: currentFloor,
|
||||
attackProgress: 0,
|
||||
roomsRemaining: design.core.maxRoomDuration,
|
||||
currentMana: design.core.manaCapacity, // Starts full
|
||||
currentMana: design.core.manaCapacity,
|
||||
spellCastIndex: 0,
|
||||
};
|
||||
}
|
||||
@@ -181,39 +180,3 @@ export function getMindCircuit(id: string) {
|
||||
return MIND_CIRCUITS[id] || null;
|
||||
}
|
||||
|
||||
// ─── Legacy Compatibility ────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* @deprecated Use getGolemSlots instead
|
||||
*/
|
||||
export function getGolemFloorDuration(_skills: Record<string, number>): number {
|
||||
return 3; // Default room duration for legacy calls
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use computeGolemStats instead
|
||||
*/
|
||||
export function getGolemDamage(
|
||||
golemId: string,
|
||||
_skills: Record<string, number>,
|
||||
): number {
|
||||
// Legacy lookup — returns 0 for component-based golems
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use computeGolemStats instead
|
||||
*/
|
||||
export function getGolemAttackSpeed(
|
||||
golemId: string,
|
||||
_skills: Record<string, number>,
|
||||
): number {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Component-based system doesn't use skill-based maintenance multiplier
|
||||
*/
|
||||
export function getGolemMaintenanceMultiplier(_skills: Record<string, number>): number {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -190,6 +190,13 @@ export const useGameStore = create<GameCoordinatorStore>()(
|
||||
if (!elements[elem].unlocked) elements[elem] = { ...elements[elem], unlocked: true };
|
||||
elements[elem] = { ...elements[elem], current: Math.min(elements[elem].max, elements[elem].current + entry.finalRate * HOURS_PER_TICK) };
|
||||
}
|
||||
// Compute per-element net regen: produced rate - drain from being used as component
|
||||
const elementRegen: Record<string, number> = {};
|
||||
for (const [elem, entry] of Object.entries(conversionResult.rates)) {
|
||||
const produced = entry.finalRate;
|
||||
const drained = conversionResult.elementDrain[elem] || 0;
|
||||
elementRegen[elem] = produced - drained;
|
||||
}
|
||||
// Net raw regen = gross regen - conversion drains - incursion
|
||||
const netRawRegen = Math.max(0, baseRegen * (1 - incursionStrength) * meditationMultiplier - conversionResult.totalRawDrain);
|
||||
const actualRegen = Math.floor(Math.min(netRawRegen * HOURS_PER_TICK, maxMana - rawMana) * 1000) / 1000;
|
||||
@@ -305,7 +312,7 @@ export const useGameStore = create<GameCoordinatorStore>()(
|
||||
|
||||
// Phase 3: Write
|
||||
writes.game = { day, hour, incursionStrength };
|
||||
writes.mana = { rawMana, meditateTicks, totalManaGathered, elements };
|
||||
writes.mana = { rawMana, meditateTicks, totalManaGathered, elements, elementRegen };
|
||||
|
||||
applyTickWrites(writes, storeSetters);
|
||||
} catch (error: unknown) {
|
||||
|
||||
@@ -19,6 +19,8 @@ export interface ManaState {
|
||||
meditateTicks: number;
|
||||
totalManaGathered: number;
|
||||
elements: Record<string, ElementState>;
|
||||
/** Per-element net regen rates (from unified conversion system) */
|
||||
elementRegen: Record<string, number>;
|
||||
}
|
||||
|
||||
// ─── Mana Actions ────────────────────────────────────────────────────────────
|
||||
@@ -40,6 +42,7 @@ export interface ManaActions {
|
||||
spendElementMana: (element: string, amount: number) => Result<void>;
|
||||
setElementMax: (max: number) => void;
|
||||
computeElementMaxWithBonuses: (perElementBonuses: Record<string, number>) => void;
|
||||
setElementRegen: (regen: Record<string, number>) => void;
|
||||
|
||||
// Reset
|
||||
resetMana: (prestigeUpgrades: Record<string, number>) => void;
|
||||
@@ -66,6 +69,7 @@ export const useManaStore = create<ManaStore>()(
|
||||
}
|
||||
])
|
||||
) as Record<string, ElementState>,
|
||||
elementRegen: {},
|
||||
|
||||
setRawMana: (amount: number) => {
|
||||
set({ rawMana: Math.max(0, amount) });
|
||||
@@ -148,17 +152,21 @@ export const useManaStore = create<ManaStore>()(
|
||||
});
|
||||
},
|
||||
|
||||
setElementRegen: (regen: Record<string, number>) => {
|
||||
set({ elementRegen: regen });
|
||||
},
|
||||
|
||||
resetMana: (prestigeUpgrades: Record<string, number>) => {
|
||||
const elementMax = 10 + (prestigeUpgrades.elementalAttune || 0) * 25;
|
||||
const startingMana = 10 + (prestigeUpgrades.manaStart || 0) * 10;
|
||||
set({ rawMana: startingMana, meditateTicks: 0, totalManaGathered: 0, elements: makeInitialElements(elementMax, prestigeUpgrades) });
|
||||
set({ rawMana: startingMana, meditateTicks: 0, totalManaGathered: 0, elements: makeInitialElements(elementMax, prestigeUpgrades), elementRegen: {} });
|
||||
},
|
||||
}),
|
||||
{
|
||||
storage: createSafeStorage(),
|
||||
name: 'mana-loop-mana',
|
||||
version: 2,
|
||||
partialize: (state) => ({ rawMana: state.rawMana, meditateTicks: state.meditateTicks, totalManaGathered: state.totalManaGathered, elements: state.elements }),
|
||||
partialize: (state) => ({ rawMana: state.rawMana, meditateTicks: state.meditateTicks, totalManaGathered: state.totalManaGathered, elements: state.elements, elementRegen: state.elementRegen }),
|
||||
migrate: (persistedState: any, _version) => {
|
||||
if (persistedState && persistedState.elements) {
|
||||
for (const k of Object.keys(persistedState.elements)) {
|
||||
|
||||
Reference in New Issue
Block a user