diff --git a/app.js b/app.js index 2486dd4..1773aa8 100644 --- a/app.js +++ b/app.js @@ -1941,6 +1941,8 @@ function getEffectiveMPS() { return effectiveMPS; } +let autoClickerTick = 0; + function gameLoop() { // Skip production if in prestige mode if (PrestigeModule.isPrestigeMode()) { @@ -1956,6 +1958,20 @@ function gameLoop() { } StatisticsModule.setCurrentMana(mana); + // Auto-clicker from prestige upgrade (1 click per second) + if (PrestigeModule.hasAutoClicker && PrestigeModule.hasAutoClicker()) { + autoClickerTick++; + if (autoClickerTick >= 10) { + autoClickerTick = 0; + let autoMPC = manaPerClick; + if (typeof RunestonesModule !== 'undefined') autoMPC += RunestonesModule.getTempMPCBonus(); + if (typeof SpellcastingModule !== 'undefined') autoMPC *= SpellcastingModule.getMPCMultiplier(); + if (autoMPC < 1) autoMPC = 1; + mana += autoMPC; + StatisticsModule.addManaByClick(autoMPC); + } + } + // Check achievements and unlocks AchievementsModule.checkAchievements(StatisticsModule.getStats()); checkUnlocks(); @@ -1976,6 +1992,10 @@ function gameLoop() { if (typeof SpellcastingModule !== 'undefined') { coinRate *= SpellcastingModule.getWishingWellMultiplier(); } + // Apply Well Keeper prestige upgrade + if (PrestigeModule.hasWellBoost && PrestigeModule.hasWellBoost()) { + coinRate *= 2; + } WishingWellModule.addCoins(coinRate / 10); // Divide by 10 since loop runs 10x per second WishingWellModule.updateDisplay(); } @@ -2014,6 +2034,21 @@ function resetForPrestige() { // Apply prestige building boosts and recalculate PrestigeModule.applyAllPrestigeBuildingBoosts(); + + // Apply starting mana from prestige upgrades + const startingMana = PrestigeModule.getStartingMana(); + if (startingMana > 0) mana = startingMana; + + // Apply starting buildings from prestige upgrades + const startingBuildings = PrestigeModule.getStartingBuildings(); + Object.entries(startingBuildings).forEach(([id, count]) => { + const building = buildings.find(b => b.id === id); + if (building) { + building.owned += count; + building.isUnlocked = true; + } + }); + recalculateMPS(); // Reset upgrades (all upgrades reset each run) diff --git a/modules/prestige.js b/modules/prestige.js index 81e47ea..2ce79ac 100644 --- a/modules/prestige.js +++ b/modules/prestige.js @@ -60,8 +60,91 @@ const PrestigeModule = (function() { isPurchased: false, unlockCost: 0, requiresUpgrade: 'mana-crystal-upgrade' + }, + { + id: 'arcane-auto-gather', + name: 'Arcane Auto-Gather', + description: 'Automatically gathers Mana once per second (as if clicking).', + flavorText: 'Why click when magic can do it for you?', + cost: 15, + isAutoClicker: true, + isPurchased: false, + unlockCost: 0, + requiresUpgrade: 'spell-core' + }, + { + id: 'head-start', + name: 'Head Start', + description: 'Start each run with 1,000 Mana.', + flavorText: 'A small gift from your past self.', + cost: 5, + startingMana: 1000, + isPurchased: false, + unlockCost: 0 + }, + { + id: 'greater-head-start', + name: 'Greater Head Start', + description: 'Start each run with 100,000 Mana.', + flavorText: 'A generous gift from your much wiser past self.', + cost: 20, + startingMana: 100000, + isPurchased: false, + unlockCost: 0, + requiresUpgrade: 'head-start' + }, + { + id: 'runestone-affinity', + name: 'Runestone Affinity', + description: 'Runestones appear 30% more frequently.', + flavorText: 'The stones sense your presence and are drawn to you.', + cost: 8, + isRunestoneBoost: true, + isPurchased: false, + unlockCost: 0 + }, + { + id: 'spell-power-reservoir', + name: 'Spell Power Reservoir', + description: 'Spell Power regenerates 50% faster.', + flavorText: 'A deeper well of arcane energy to draw from.', + cost: 12, + isSpellRegenBoost: true, + isPurchased: false, + unlockCost: 0, + requiresUpgrade: 'mana-crystal-upgrade' + }, + { + id: 'crystal-multiplication', + name: 'Crystal Multiplication', + description: 'Boosts MPS by 10%.', + flavorText: 'Your crystals resonate with accumulated power.', + cost: 25, + mpsBonus: 0.10, + isPurchased: false, + unlockCost: 0, + requiresUpgrade: 'spell-core' + }, + { + id: 'hand-of-the-ancients', + name: 'Hand of the Ancients', + description: 'Start each run with 5 Wizard\'s Hands.', + flavorText: 'Spectral hands from past lives join your cause.', + cost: 10, + startingBuilding: { id: 'wizards-hand', count: 5 }, + isPurchased: false, + unlockCost: 0 + }, + { + id: 'well-keeper', + name: 'Well Keeper', + description: 'Wishing Well coin generation doubled.', + flavorText: 'The well remembers your generosity.', + cost: 15, + isWellBoost: true, + isPurchased: false, + unlockCost: 0 } - // Future prestige upgrades go here ]; // Calculate Mana Crystals from total mana using Cookie Clicker formula @@ -718,6 +801,26 @@ const PrestigeModule = (function() { prestigeUpgrades.forEach(u => u.isPurchased = false); } + function hasAutoClicker() { + const upgrade = prestigeUpgrades.find(u => u.id === 'arcane-auto-gather'); + return upgrade && upgrade.isPurchased; + } + + function hasRunestoneBoost() { + const upgrade = prestigeUpgrades.find(u => u.id === 'runestone-affinity'); + return upgrade && upgrade.isPurchased; + } + + function hasSpellRegenBoost() { + const upgrade = prestigeUpgrades.find(u => u.id === 'spell-power-reservoir'); + return upgrade && upgrade.isPurchased; + } + + function hasWellBoost() { + const upgrade = prestigeUpgrades.find(u => u.id === 'well-keeper'); + return upgrade && upgrade.isPurchased; + } + function getPrestigeUpgrades() { return prestigeUpgrades; } @@ -745,6 +848,10 @@ const PrestigeModule = (function() { getPrestigeUpgrades, getStartingMana, getStartingBuildings, + hasAutoClicker, + hasRunestoneBoost, + hasSpellRegenBoost, + hasWellBoost, addPrestigePotential, getPrestigePotential, getHighestPotentialTier, diff --git a/modules/runestones.js b/modules/runestones.js index 76de807..9c9e029 100644 --- a/modules/runestones.js +++ b/modules/runestones.js @@ -286,7 +286,11 @@ const RunestonesModule = (function() { ]; function getRandomSpawnInterval() { - return Math.floor(Math.random() * (MAX_SPAWN_INTERVAL - MIN_SPAWN_INTERVAL)) + MIN_SPAWN_INTERVAL; + let interval = Math.floor(Math.random() * (MAX_SPAWN_INTERVAL - MIN_SPAWN_INTERVAL)) + MIN_SPAWN_INTERVAL; + if (typeof PrestigeModule !== 'undefined' && PrestigeModule.hasRunestoneBoost && PrestigeModule.hasRunestoneBoost()) { + interval = Math.floor(interval * 0.7); + } + return interval; } function init() { diff --git a/modules/spellcasting.js b/modules/spellcasting.js index 6df070e..1df8702 100644 --- a/modules/spellcasting.js +++ b/modules/spellcasting.js @@ -214,9 +214,13 @@ const SpellcastingModule = (function() { // Update spell timers (called every 100ms from game loop) function update(deltaSeconds) { - // Regenerate spell power + // Regenerate spell power (with optional prestige boost) if (spellPower < MAX_SPELL_POWER) { - spellPower = Math.min(MAX_SPELL_POWER, spellPower + SPELL_POWER_REGEN_RATE * deltaSeconds); + let regenRate = SPELL_POWER_REGEN_RATE; + if (typeof PrestigeModule !== 'undefined' && PrestigeModule.hasSpellRegenBoost && PrestigeModule.hasSpellRegenBoost()) { + regenRate *= 1.5; + } + spellPower = Math.min(MAX_SPELL_POWER, spellPower + regenRate * deltaSeconds); } // Update active spell durations