fix(pact-system): resolve 5 spec-vs-code discrepancies (DISC-4,6,8,11,12)
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
- DISC-11: Fix floor 140/150 element composition in guardian-data.ts Floor 140 now uses [light, fire, radiantflames] (was [sand, earth, water]) Floor 150 now uses [air, death, miasma] (was [lightning, fire, air]) - DISC-12: Reconcile spec §7.1 vs §8.2 tables in pact-system-spec.md Updated §8.2 to match §7.1 authoritative element mappings - DISC-4: Deduplicate pact ritual completion logic Refactored pact-ritual.ts pipeline to delegate completion to prestigeStore.completePactRitual() instead of duplicating state writes - DISC-6: Add 4 missing boon types to guardians critChance (floor 90), manaGain (floor 110), prestigeInsight (floor 200), studySpeed (floor 220) — all 12 spec boon types now used - DISC-8: Add comment clarifying signedPactDetails persistence Code already correct (not reset by startNewLoop/resetPrestigeForNewLoop) - Updated spire-utils.test.ts to match corrected floor 140/150 elements
This commit is contained in:
@@ -209,9 +209,11 @@ export const useGameStore = create<GameCoordinatorStore>()(
|
||||
rawMana = Math.max(0, Math.min(rawMana + netRawRegen * HOURS_PER_TICK, maxMana));
|
||||
let totalManaGathered = ctx.mana.totalManaGathered + Math.max(0, actualRegen);
|
||||
|
||||
const pactResult = processPactRitual(ctx.prestige.pactRitualFloor, ctx.prestige.pactRitualProgress, ctx.prestige.signedPacts, ctx.prestige.defeatedGuardians, ctx.prestige.prestigeUpgrades.pactAffinity || 0, disciplineEffects.bonuses.pactAffinityBonus || 0, ctx.prestige.signedPactDetails, day, hour);
|
||||
const pactResult = processPactRitual(ctx.prestige.pactRitualFloor, ctx.prestige.pactRitualProgress, ctx.prestige.prestigeUpgrades.pactAffinity || 0, disciplineEffects.bonuses.pactAffinityBonus || 0);
|
||||
if (pactResult.writes) writes.prestige = { ...(writes.prestige || {}), ...pactResult.writes };
|
||||
pactResult.logs.forEach(l => addLog(l));
|
||||
if (pactResult.completed) {
|
||||
usePrestigeStore.getState().completePactRitual(addLog);
|
||||
}
|
||||
|
||||
const dr = useDisciplineStore.getState().processTick({ rawMana, elements });
|
||||
rawMana = dr.rawMana; elements = dr.elements;
|
||||
|
||||
@@ -1,76 +1,48 @@
|
||||
// ─── Pact Ritual Pipeline Phase ───────────────────────────────────────────────
|
||||
// Processes pact ritual signing during the game tick.
|
||||
// Progress advancement only — completion is delegated to prestigeStore.completePactRitual().
|
||||
|
||||
import { useManaStore } from '../manaStore';
|
||||
import { getGuardianForFloor } from '../../data/guardian-encounters';
|
||||
import { HOURS_PER_TICK } from '../../constants';
|
||||
import type { PrestigeState } from '../prestigeStore';
|
||||
|
||||
export interface PactRitualResult {
|
||||
/** Null when no ritual is in progress. */
|
||||
writes: {
|
||||
signedPacts?: number[];
|
||||
defeatedGuardians?: number[];
|
||||
signedPactDetails?: PrestigeState['signedPactDetails'];
|
||||
pactRitualFloor: number | null;
|
||||
pactRitualProgress: number;
|
||||
} | null;
|
||||
logs: string[];
|
||||
/** True when the ritual reached completion threshold this tick. */
|
||||
completed: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process pact ritual progression. Advances progress and completes signing
|
||||
* when enough enough hours have accumulated.
|
||||
* Process pact ritual progression. Advances progress each tick.
|
||||
* Returns `completed: true` when enough hours have accumulated;
|
||||
* the caller (gameStore tick) must then invoke
|
||||
* `usePrestigeStore.getState().completePactRitual(addLog)` to
|
||||
* finalise signing — this avoids duplicating the completion logic.
|
||||
*/
|
||||
export function processPactRitual(
|
||||
pactRitualFloor: number | null,
|
||||
pactRitualProgress: number,
|
||||
signedPacts: number[],
|
||||
defeatedGuardians: number[],
|
||||
pactAffinityUpgrade: number,
|
||||
pactAffinityBonus: number,
|
||||
signedPactDetails: PrestigeState['signedPactDetails'],
|
||||
currentDay: number,
|
||||
currentHour: number,
|
||||
): PactRitualResult {
|
||||
if (pactRitualFloor === null) return { writes: null, logs: [] };
|
||||
const logs: string[] = [];
|
||||
if (pactRitualFloor === null) return { writes: null, completed: false };
|
||||
|
||||
const guardian = getGuardianForFloor(pactRitualFloor);
|
||||
if (!guardian) return { writes: null, logs: [] };
|
||||
if (!guardian) return { writes: null, completed: false };
|
||||
|
||||
const pactAffinity = Math.min(0.9, pactAffinityUpgrade * 0.1 + pactAffinityBonus);
|
||||
const requiredTime = guardian.pactTime * (1 - pactAffinity);
|
||||
|
||||
if (pactRitualProgress + HOURS_PER_TICK >= requiredTime) {
|
||||
logs.push(`📜 Pact signed with ${guardian.name}! You have gained their boons.`);
|
||||
const manaStore = useManaStore.getState();
|
||||
for (const manaType of guardian.unlocksMana || []) {
|
||||
const result = manaStore.unlockElement(manaType, 0);
|
||||
if (result.success) {
|
||||
logs.push(`✨ ${manaType.charAt(0).toUpperCase() + manaType.slice(1)} mana unlocked!`);
|
||||
}
|
||||
}
|
||||
return {
|
||||
writes: {
|
||||
signedPacts: [...signedPacts, pactRitualFloor],
|
||||
defeatedGuardians: defeatedGuardians.filter(f => f !== pactRitualFloor),
|
||||
signedPactDetails: {
|
||||
...signedPactDetails,
|
||||
[pactRitualFloor]: {
|
||||
floor: pactRitualFloor,
|
||||
guardianId: guardian.name || `floor-${pactRitualFloor}`,
|
||||
signedAt: { day: currentDay, hour: currentHour },
|
||||
skillLevels: {},
|
||||
},
|
||||
},
|
||||
pactRitualFloor: null,
|
||||
pactRitualProgress: 0,
|
||||
},
|
||||
logs,
|
||||
};
|
||||
// Signal completion — state writes happen inside completePactRitual()
|
||||
return { writes: null, completed: true };
|
||||
}
|
||||
|
||||
return {
|
||||
writes: { pactRitualFloor, pactRitualProgress: pactRitualProgress + HOURS_PER_TICK, signedPacts, defeatedGuardians },
|
||||
logs,
|
||||
writes: { pactRitualFloor, pactRitualProgress: pactRitualProgress + HOURS_PER_TICK },
|
||||
completed: false,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -246,6 +246,8 @@ export const usePrestigeStore = create<PrestigeStore>()(
|
||||
pactRitualFloor: null,
|
||||
pactRitualProgress: 0,
|
||||
loopInsight: 0,
|
||||
// NOTE: signedPactDetails is intentionally NOT reset here.
|
||||
// Per spec §5.1, it persists across loops for historical tracking.
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
Reference in New Issue
Block a user