Phase 4: Study effects (remaining 6)

This commit is contained in:
Refactoring Agent
2026-04-24 18:32:15 +02:00
parent c8cabf3e4b
commit 0f0b800e60
4 changed files with 82 additions and 17 deletions
+8 -5
View File
@@ -157,9 +157,10 @@ export function computeTotalMaxMana(
effects?: UnifiedEffects effects?: UnifiedEffects
): number { ): number {
const pu = state.prestigeUpgrades; const pu = state.prestigeUpgrades;
const skillMult = effects?.skillLevelMultiplier || 1;
const base = const base =
100 + 100 +
(state.skills.manaWell || 0) * 100 + (state.skills.manaWell || 0) * 100 * skillMult +
(pu.manaWell || 0) * 500; (pu.manaWell || 0) * 500;
if (!effects) { if (!effects) {
@@ -178,10 +179,11 @@ export function computeTotalRegen(
): number { ): number {
const pu = state.prestigeUpgrades; const pu = state.prestigeUpgrades;
const temporalBonus = 1 + (pu.temporalEcho || 0) * 0.1; const temporalBonus = 1 + (pu.temporalEcho || 0) * 0.1;
const skillMult = effects?.skillLevelMultiplier || 1;
const base = const base =
2 + 2 +
(state.skills.manaFlow || 0) * 1 + (state.skills.manaFlow || 0) * 1 * skillMult +
(state.skills.manaSpring || 0) * 2 + (state.skills.manaSpring || 0) * 2 * skillMult +
(pu.manaFlow || 0) * 0.5; (pu.manaFlow || 0) * 0.5;
let regen = base * temporalBonus; let regen = base * temporalBonus;
@@ -202,10 +204,11 @@ export function computeTotalClickMana(
state: Pick<GameState, 'skills' | 'skillUpgrades' | 'skillTiers' | 'equipmentInstances' | 'equippedInstances'>, state: Pick<GameState, 'skills' | 'skillUpgrades' | 'skillTiers' | 'equipmentInstances' | 'equippedInstances'>,
effects?: UnifiedEffects effects?: UnifiedEffects
): number { ): number {
const skillMult = effects?.skillLevelMultiplier || 1;
const base = const base =
1 + 1 +
(state.skills.manaTap || 0) * 1 + (state.skills.manaTap || 0) * 1 * skillMult +
(state.skills.manaSurge || 0) * 3; (state.skills.manaSurge || 0) * 3 * skillMult;
if (!effects) { if (!effects) {
effects = getUnifiedEffects(state as any); effects = getUnifiedEffects(state as any);
+32 -9
View File
@@ -302,9 +302,10 @@ export function computeMaxMana(
effects?: ComputedEffects | UnifiedEffects effects?: ComputedEffects | UnifiedEffects
): number { ): number {
const pu = state.prestigeUpgrades; const pu = state.prestigeUpgrades;
const skillMult = (effects as any)?.skillLevelMultiplier || 1;
const base = const base =
100 + 100 +
(state.skills.manaWell || 0) * 100 + (state.skills.manaWell || 0) * 100 * skillMult +
(pu.manaWell || 0) * 500; (pu.manaWell || 0) * 500;
// If effects not provided, compute unified effects (includes equipment) // If effects not provided, compute unified effects (includes equipment)
@@ -350,10 +351,11 @@ export function computeRegen(
): number { ): number {
const pu = state.prestigeUpgrades; const pu = state.prestigeUpgrades;
const temporalBonus = 1 + (pu.temporalEcho || 0) * 0.1; const temporalBonus = 1 + (pu.temporalEcho || 0) * 0.1;
const skillMult = (effects as any)?.skillLevelMultiplier || 1;
const base = const base =
2 + 2 +
(state.skills.manaFlow || 0) * 1 + (state.skills.manaFlow || 0) * 1 * skillMult +
(state.skills.manaSpring || 0) * 2 + (state.skills.manaSpring || 0) * 2 * skillMult +
(pu.manaFlow || 0) * 0.5; (pu.manaFlow || 0) * 0.5;
let regen = base * temporalBonus; let regen = base * temporalBonus;
@@ -399,10 +401,11 @@ export function computeClickMana(
state: Pick<GameState, 'skills' | 'skillUpgrades' | 'skillTiers' | 'equipmentInstances' | 'equippedInstances'>, state: Pick<GameState, 'skills' | 'skillUpgrades' | 'skillTiers' | 'equipmentInstances' | 'equippedInstances'>,
effects?: ComputedEffects | UnifiedEffects effects?: ComputedEffects | UnifiedEffects
): number { ): number {
const skillMult = (effects as any)?.skillLevelMultiplier || 1;
const base = const base =
1 + 1 +
(state.skills.manaTap || 0) * 1 + (state.skills.manaTap || 0) * 1 * skillMult +
(state.skills.manaSurge || 0) * 3; (state.skills.manaSurge || 0) * 3 * skillMult;
// If effects not provided, compute unified effects (includes equipment) // If effects not provided, compute unified effects (includes equipment)
if (!effects && state.equipmentInstances && state.equippedInstances) { if (!effects && state.equipmentInstances && state.equippedInstances) {
@@ -437,16 +440,18 @@ function getElementalBonus(spellElem: string, floorElem: string): number {
export function calcDamage( export function calcDamage(
state: Pick<GameState, 'skills' | 'signedPacts'>, state: Pick<GameState, 'skills' | 'signedPacts'>,
spellId: string, spellId: string,
floorElem?: string floorElem?: string,
effects?: ComputedEffects | UnifiedEffects
): number { ): number {
const sp = SPELLS_DEF[spellId]; const sp = SPELLS_DEF[spellId];
if (!sp) return 5; if (!sp) return 5;
const skills = state.skills; const skills = state.skills;
const baseDmg = sp.dmg + (skills.combatTrain || 0) * 5; const skillMult = (effects as any)?.skillLevelMultiplier || 1;
const pct = 1 + (skills.arcaneFury || 0) * 0.1; const baseDmg = sp.dmg + (skills.combatTrain || 0) * 5 * skillMult;
const pct = 1 + (skills.arcaneFury || 0) * 0.1 * skillMult;
// Elemental mastery bonus // Elemental mastery bonus
const elemMasteryBonus = 1 + (skills.elementalMastery || 0) * 0.15; const elemMasteryBonus = 1 + (skills.elementalMastery || 0) * 0.15 * skillMult;
// Guardian bane bonus // Guardian bane bonus
const guardianBonus = floorElem && GUARDIANS[Object.values(GUARDIANS).find(g => g.element === floorElem)?.hp ? 0 : 0] const guardianBonus = floorElem && GUARDIANS[Object.values(GUARDIANS).find(g => g.element === floorElem)?.hp ? 0 : 0]
@@ -954,6 +959,17 @@ export const useGameStore = create<GameStore>()(
// Calculate base study speed // Calculate base study speed
let studySpeedMult = getStudySpeedMultiplier(skills); let studySpeedMult = getStudySpeedMultiplier(skills);
// STUDY_RUSH: First hour of study is 2x speed
if (hasSpecial(effects, SPECIAL_EFFECTS.STUDY_RUSH) && consecutiveStudyHours === 0) {
studySpeedMult *= 2;
log = [`⚡ Study Rush activated! Double speed for the first hour!`, ...log.slice(0, 49)];
}
// MENTAL_CLARITY: +10% study speed when mana > 75%
if (hasSpecial(effects, SPECIAL_EFFECTS.MENTAL_CLARITY) && state.rawMana > maxMana * 0.75) {
studySpeedMult *= 1.10;
}
// DEEP_CONCENTRATION: +20% study speed when mana > 90% // DEEP_CONCENTRATION: +20% study speed when mana > 90%
if (hasSpecial(effects, SPECIAL_EFFECTS.DEEP_CONCENTRATION) && state.rawMana > maxMana * 0.9) { if (hasSpecial(effects, SPECIAL_EFFECTS.DEEP_CONCENTRATION) && state.rawMana > maxMana * 0.9) {
studySpeedMult *= 1.20; studySpeedMult *= 1.20;
@@ -1009,6 +1025,13 @@ export const useGameStore = create<GameStore>()(
skillProgress = { ...skillProgress, [skillId]: 0 }; skillProgress = { ...skillProgress, [skillId]: 0 };
log = [`${SKILLS_DEF[skillId]?.name} Lv.${newLevel} mastered!`, ...log.slice(0, 49)]; log = [`${SKILLS_DEF[skillId]?.name} Lv.${newLevel} mastered!`, ...log.slice(0, 49)];
// STUDY_REFUND: 25% mana back on study complete
if (hasSpecial(effects, SPECIAL_EFFECTS.STUDY_REFUND)) {
const refundAmount = Math.floor(currentStudyTarget.totalCost * 0.25);
rawMana += refundAmount;
log = [`💰 Study Refund: ${refundAmount} mana returned!`, ...log.slice(0, 49)];
}
// Check if this skill unlocks effects (research skills) // Check if this skill unlocks effects (research skills)
const effectsToUnlock = EFFECT_RESEARCH_MAPPING[skillId]; const effectsToUnlock = EFFECT_RESEARCH_MAPPING[skillId];
if (effectsToUnlock && newLevel >= (SKILLS_DEF[skillId]?.max || 1)) { if (effectsToUnlock && newLevel >= (SKILLS_DEF[skillId]?.max || 1)) {
+33 -3
View File
@@ -3,6 +3,7 @@
import type { GameState } from './types'; import type { GameState } from './types';
import { SKILLS_DEF, SPELLS_DEF, getStudyCostMultiplier } from './constants'; import { SKILLS_DEF, SPELLS_DEF, getStudyCostMultiplier } from './constants';
import { computeEffects, hasSpecial, SPECIAL_EFFECTS } from './upgrade-effects';
// ─── Study Actions Interface ────────────────────────────────────────────────── // ─── Study Actions Interface ──────────────────────────────────────────────────
@@ -39,19 +40,37 @@ export function createStudySlice(
// Calculate total mana cost and cost per hour // Calculate total mana cost and cost per hour
const costMult = getStudyCostMultiplier(state.skills); const costMult = getStudyCostMultiplier(state.skills);
const totalCost = Math.floor(sk.base * (currentLevel + 1) * costMult); let totalCost = Math.floor(sk.base * (currentLevel + 1) * costMult);
// CHAIN_STUDY: -5% cost per maxed skill
const effects = computeEffects(state.skillUpgrades || {}, state.skillTiers || {});
if (hasSpecial(effects, SPECIAL_EFFECTS.CHAIN_STUDY)) {
const maxedSkills = Object.entries(SKILLS_DEF).filter(([id, sk]) =>
(state.skills[id] || 0) >= sk.max
).length;
const discount = Math.pow(0.95, maxedSkills); // -5% per maxed skill
totalCost = Math.floor(totalCost * discount);
}
const manaCostPerHour = Math.ceil(totalCost / sk.studyTime); const manaCostPerHour = Math.ceil(totalCost / sk.studyTime);
// Must have at least 1 hour worth of mana to start // Must have at least 1 hour worth of mana to start
if (state.rawMana < manaCostPerHour) return; if (state.rawMana < manaCostPerHour) return;
// KNOWLEDGE_TRANSFER: New skills start at 10% progress
let initialProgress = state.skillProgress[skillId] || 0;
if (hasSpecial(effects, SPECIAL_EFFECTS.KNOWLEDGE_TRANSFER) && initialProgress === 0) {
initialProgress = sk.studyTime * 0.10; // 10% of required time
log = [`📖 Knowledge Transfer: Starting with 10% progress!`, ...state.log.slice(0, 49)];
}
// Start studying (no upfront cost - mana is deducted per hour during study) // Start studying (no upfront cost - mana is deducted per hour during study)
set({ set({
currentAction: 'study', currentAction: 'study',
currentStudyTarget: { currentStudyTarget: {
type: 'skill', type: 'skill',
id: skillId, id: skillId,
progress: state.skillProgress[skillId] || 0, progress: initialProgress,
required: sk.studyTime, required: sk.studyTime,
manaCostPerHour: manaCostPerHour, manaCostPerHour: manaCostPerHour,
totalCost: totalCost, totalCost: totalCost,
@@ -68,7 +87,18 @@ export function createStudySlice(
// Calculate total mana cost and cost per hour // Calculate total mana cost and cost per hour
const costMult = getStudyCostMultiplier(state.skills); const costMult = getStudyCostMultiplier(state.skills);
const totalCost = Math.floor(sp.unlock * costMult); let totalCost = Math.floor(sp.unlock * costMult);
// CHAIN_STUDY: -5% cost per maxed skill
const effects = computeEffects(state.skillUpgrades || {}, state.skillTiers || {});
if (hasSpecial(effects, SPECIAL_EFFECTS.CHAIN_STUDY)) {
const maxedSkills = Object.entries(SKILLS_DEF).filter(([id, sk]) =>
(state.skills[id] || 0) >= sk.max
).length;
const discount = Math.pow(0.95, maxedSkills); // -5% per maxed skill
totalCost = Math.floor(totalCost * discount);
}
const studyTime = sp.studyTime || (sp.tier * 4); const studyTime = sp.studyTime || (sp.tier * 4);
const manaCostPerHour = Math.ceil(totalCost / studyTime); const manaCostPerHour = Math.ceil(totalCost / studyTime);
+9
View File
@@ -56,6 +56,9 @@ export interface ComputedEffects {
// All active upgrades for display // All active upgrades for display
activeUpgrades: ActiveUpgradeEffect[]; activeUpgrades: ActiveUpgradeEffect[];
// DEEP_UNDERSTANDING: +10% bonus from all skill levels
skillLevelMultiplier: number;
} }
// ─── Special Effect IDs ──────────────────────────────────────────────────────── // ─── Special Effect IDs ────────────────────────────────────────────────────────
@@ -231,8 +234,14 @@ export function computeEffects(
permanentRegenBonus: 0, permanentRegenBonus: 0,
specials: new Set<string>(), specials: new Set<string>(),
activeUpgrades, activeUpgrades,
skillLevelMultiplier: 1,
}; };
// Apply DEEP_UNDERSTANDING: +10% bonus from all skill levels
if (hasSpecial(effects, SPECIAL_EFFECTS.DEEP_UNDERSTANDING)) {
effects.skillLevelMultiplier = 1.10;
}
// Apply each upgrade effect // Apply each upgrade effect
for (const upgrade of activeUpgrades) { for (const upgrade of activeUpgrades) {
const { effect } = upgrade; const { effect } = upgrade;