9.6 KiB
Task6-1 Context: Proposal 1 - Unlocked Mana Type Capacity
Overview
Gathered context for implementing Proposal 1: Unlocked Mana Type Capacity. This proposal likely relates to either:
- Increasing the mana capacity (max) of unlocked mana types
- Increasing the number of mana types that can be unlocked
1. Existing Prestige Upgrade Structure
File: src/lib/game/constants/prestige.ts
PrestigeDef Interface (from src/lib/game/types/skills.ts)
export interface PrestigeDef {
name: string;
desc: string;
max: number;
cost: number;
}
Current Prestige Upgrades (relevant to mana/elements)
export const PRESTIGE_DEF: Record<string, PrestigeDef> = {
// ... other upgrades ...
// Existing elemental capacity upgrade
elementalAttune: {
name: "Elemental Attunement",
desc: "+25 elemental mana cap",
max: 10,
cost: 600
},
// Starting elemental mana upgrade
elemStart: {
name: "Elem. Start",
desc: "Start with 5 of each unlocked element",
max: 3,
cost: 800
},
// ... other upgrades ...
};
Key observations:
- All prestige upgrades use the same structure: name, description, max level, cost
elementalAttunealready provides +25 elemental mana cap per level (max 10 levels = +250 cap)elemStartgives starting elemental mana when a new loop begins- Upgrades are stored as
Record<string, number>where the value is the current level
2. How Mana Type Unlocks Are Tracked
Element State Structure
File: src/lib/game/types/elements.ts
export interface ElementState {
current: number;
max: number;
unlocked: boolean;
}
Elements Storage in GameState
File: src/lib/game/types/game.ts
export interface GameState {
// ...
elements: Record<string, ElementState>;
// ...
}
Base Unlocked Elements
File: src/lib/game/constants/elements.ts
export const BASE_UNLOCKED_ELEMENTS = ['transference'];
Key observations:
- Only
transferencestarts unlocked by default - All other 12 elements (fire, water, air, earth, light, dark, death, metal, sand, lightning, crystal, stellar, void) start locked
- Elements have a boolean
unlockedfield - no partial unlocking or limits on number of unlocked types
Unlocking New Elements
File: src/lib/game/store.ts (lines 2176-2195)
unlockElement: (element: string) => {
const state = get();
if (state.elements[element]?.unlocked) return;
const cost = 500;
if (state.rawMana < cost) return;
// ELEMENTAL_AFFINITY: New elements start with 10 capacity
const effects = getUnifiedEffects(state.skillUpgrades, state.skillTiers);
const newElementMax = hasSpecial(effects, SPECIAL_EFFECTS.ELEMENTAL_AFFINITY) ? 10 : 0;
set({
rawMana: state.rawMana - cost,
elements: {
...state.elements,
[element]: { ...state.elements[element], unlocked: true, max: newElementMax },
},
log: [`✨ ${ELEMENTS[element].name} affinity unlocked!`, ...state.log.slice(0, 49)],
});
},
Key observations:
- Unlocking an element costs 500 raw mana
- When unlocked, the element gets
unlocked: true - New elements start with
max: 0unless ELEMENTAL_AFFINITY special effect is active (then max: 10) - No limit on the NUMBER of elements that can be unlocked - players can unlock all 12+ types
Element Definitions
File: src/lib/game/constants/elements.ts
Total element types:
- Base (7): fire, water, air, earth, light, dark, death
- Utility (1): transference
- Composite (3): metal, sand, lightning
- Exotic (3): crystal, stellar, void
Total: 14 element types (13 unlockable + transference which starts unlocked)
3. How Mana Capacity Is Applied
computeElementMax Function
File: src/lib/game/store.ts (lines 415-432)
export function computeElementMax(
state: Pick<GameState, 'skills' | 'prestigeUpgrades' | 'skillUpgrades' | 'skillTiers'>,
effects?: ComputedEffects | UnifiedEffects,
element?: string
): number {
const pu = state.prestigeUpgrades;
const base = 10 + (state.skills.elemAttune || 0) * 50 + (pu.elementalAttune || 0) * 25;
// Apply upgrade effects if provided
if (effects) {
let bonus = effects.elementCapBonus; // Global bonus
// Add per-element bonus if element is specified and available
if (element && (effects as UnifiedEffects).perElementCapBonus) {
const perElementBonus = (effects as UnifiedEffects).perElementCapBonus[element];
if (perElementBonus) {
bonus += perElementBonus;
}
}
return Math.floor((base + bonus) * effects.elementCapMultiplier);
}
return base;
}
Key observations:
- Base capacity formula:
10 + (elemAttune skill levels * 50) + (elementalAttune prestige levels * 25) - Effects system can modify capacity via:
elementCapBonus: Global flat bonuselementCapMultiplier: Global multiplierperElementCapBonus[element]: Per-element flat bonus (from equipment)
- Currently, all unlocked elements share the SAME max capacity (calculated once and applied to all)
- The
perElementCapBonusexists but is currently only used for equipment effects
Usage in Store Initialization
File: src/lib/game/store.ts (lines 670-710)
function makeInitial(overrides: Partial<GameState> = {}): GameState {
const pu = overrides.prestigeUpgrades || {};
// ...
const elemMax = computeElementMax(
{ skills: overrides.skills || {}, prestigeUpgrades: pu, skillUpgrades: overrides.skillUpgrades, skillTiers: overrides.skillTiers },
effects
);
const elements: Record<string, { current: number; max: number; unlocked: boolean }> = {};
Object.keys(ELEMENTS).forEach((k) => {
const isUnlocked = BASE_UNLOCKED_ELEMENTS.includes(k);
let startAmount = 0;
// Start with some elemental mana if elemStart upgrade
if (isUnlocked && pu.elemStart) {
startAmount = pu.elemStart * 5;
}
elements[k] = {
current: overrides.elements?.[k]?.current ?? startAmount,
max: elemMax, // <-- Same max for ALL elements
unlocked: isUnlocked,
};
});
// ...
}
Key observation: The same elemMax is applied to ALL elements regardless of type or unlock status.
4. Save Data Structure (Cross-Loop Persistence)
GameState Prestige-Related Fields
File: src/lib/game/types/game.ts
export interface GameState {
// ...
// Prestige
insight: number;
totalInsight: number;
prestigeUpgrades: Record<string, number>;
memorySlots: number;
memories: string[];
// Elements
elements: Record<string, ElementState>;
// ...
}
What Persists Through Loops
File: src/lib/game/store.ts (lines 2255-2290)
startNewLoop: () => {
const state = get();
const insightGained = state.loopInsight || calcInsight(state);
const total = state.insight + insightGained;
// ... (keep some spells through temporal memory)
const newState = makeInitial({
loopCount: state.loopCount + 1,
insight: total,
totalInsight: (state.totalInsight || 0) + insightGained,
prestigeUpgrades: state.prestigeUpgrades, // <-- PERSISTS
memories: state.memories,
skills: state.skills,
manaHeartBonus: newHeartBonus,
});
// ...
set(newState);
},
Key observations:
prestigeUpgrades(all upgrade levels) persist through loopsinsightandtotalInsightpersist and accumulateelementsare NOT persisted - they are reinitialized inmakeInitial()- On new loop, element unlocks are lost (player must re-unlock elements)
BASE_UNLOCKED_ELEMENTSandpu.elemStartdetermine which elements start unlocked/have starting mana
Purchasing Prestige Upgrades
File: src/lib/game/store.ts (lines 2235-2250)
doPrestige: (id: string) => {
// ...
const lvl = state.prestigeUpgrades[id] || 0;
if (lvl >= pd.max || state.insight < pd.cost) return;
const newPU = { ...state.prestigeUpgrades, [id]: lvl + 1 };
set({
insight: state.insight - pd.cost,
prestigeUpgrades: newPU,
// ...
});
},
Key observations:
- Upgrades purchased with
insightcurrency - Each level costs the same amount (flat cost model)
- Max level check prevents over-purchasing
- New upgrade level is saved to
prestigeUpgradesrecord
Summary of Key Points for Task6-1
- Prestige upgrades follow a simple structure:
{ name, desc, max, cost } - Element capacity is currently global (same for all elements), calculated from:
- Base: 10
- Skill:
elemAttunelevels × 50 - Prestige:
elementalAttunelevels × 25 - Effects: bonuses and multipliers
- Element unlocks are per-type (boolean), cost 500 raw mana each
- No limit on number of unlocked element types currently exists
- Per-element capacity bonuses exist in effects system (
perElementCapBonus) but aren't widely used - Cross-loop persistence: prestige upgrades and insight persist; element unlocks do NOT persist
- 14 total element types available (13 unlockable + transference)
Questions for Implementation
Depending on what "Unlocked Mana Type Capacity" means:
If it means increasing capacity (max mana) of unlocked types:
- Could add a new prestige upgrade similar to
elementalAttune - Could modify the
computeElementMaxfunction - Could add per-element capacity tracking
If it means increasing the NUMBER of types that can be unlocked:
- Need to add a limit/cap on unlocked types (currently unlimited)
- Need to add a prestige upgrade to increase this limit
- Need to modify
unlockElementto check against the limit