/** Functions to create the individual sections of the Statistics page */ import * as GameData from '../../../Data/Gamedata.ts'; import { MaxChainCookieReward } from '../../../Cache/Stats/ChainCookies'; import { CacheAvgCPSWithChoEgg, CacheCentEgg, CacheChainFrenzyMaxReward, CacheChainFrenzyRequired, CacheChainFrenzyRequiredNext, CacheChainFrenzyWrathRequired, CacheChainFrenzyWrathRequiredNext, CacheChainMaxReward, CacheChainRequired, CacheChainRequiredNext, CacheChainWrathMaxReward, CacheChainWrathRequired, CacheChainWrathRequiredNext, CacheConjure, CacheConjureReward, CacheDragonsFortuneMultAdjustment, CacheEdifice, CacheEdificeBuilding, CacheGoldenCookiesMult, CacheHCPerSecond, CacheLastChoEgg, CacheLucky, CacheLuckyFrenzy, CacheLuckyReward, CacheLuckyRewardFrenzy, CacheLuckyWrathReward, CacheLuckyWrathRewardFrenzy, CacheNoGoldSwitchCookiesPS, CacheRealCookiesEarned, CacheSeaSpec, CacheWrathCookiesMult, CacheWrinklersTotal, } from '../../../Cache/VariablesAndData'; import { CMOptions } from '../../../Config/VariablesAndData'; import ResetBonus from '../../../Sim/SimulationEvents/ResetAscension'; import GetCPS from '../../HelperFunctions/GetCPS'; import GetWrinkConfigBank from '../../HelperFunctions/GetWrinkConfigBank'; import { ColourGreen, ColourRed, ColourTextPre } from '../../VariablesAndData'; import { StatsListing, StatsHeader, StatsMissDisp } from './CreateDOMElements'; import Beautify from '../../BeautifyAndFormatting/Beautify'; import FormatTime from '../../BeautifyAndFormatting/FormatTime'; /** * This function creates the "Lucky" section of the stats page * @returns {object} section The object contating the Lucky section */ export function LuckySection() { // This sets which tooltip to display for certain stats const goldCookTooltip = Game.auraMult("Dragon's Fortune") ? 'GoldCookDragonsFortuneTooltipPlaceholder' : 'GoldCookTooltipPlaceholder'; const section = document.createElement('div'); section.className = 'CMStatsLuckySection'; const luckyColour = Game.cookies + GetWrinkConfigBank() < CacheLucky ? ColourRed : ColourGreen; const luckyTime = Game.cookies + GetWrinkConfigBank() < CacheLucky ? FormatTime((CacheLucky - (Game.cookies + GetWrinkConfigBank())) / GetCPS()) : ''; const luckyReqFrag = document.createDocumentFragment(); const luckyReqSpan = document.createElement('span'); luckyReqSpan.style.fontWeight = 'bold'; luckyReqSpan.className = ColourTextPre + luckyColour; luckyReqSpan.textContent = Beautify(CacheLucky); luckyReqFrag.appendChild(luckyReqSpan); if (luckyTime !== '') { const luckyReqSmall = document.createElement('small'); luckyReqSmall.textContent = ` (${luckyTime})`; luckyReqFrag.appendChild(luckyReqSmall); } section.appendChild( StatsListing('withTooltip', '"Lucky!" cookies required', luckyReqFrag, goldCookTooltip), ); const luckyColourFrenzy = Game.cookies + GetWrinkConfigBank() < CacheLuckyFrenzy ? ColourRed : ColourGreen; const luckyTimeFrenzy = Game.cookies + GetWrinkConfigBank() < CacheLuckyFrenzy ? FormatTime((CacheLuckyFrenzy - (Game.cookies + GetWrinkConfigBank())) / GetCPS()) : ''; const luckyReqFrenFrag = document.createDocumentFragment(); const luckyReqFrenSpan = document.createElement('span'); luckyReqFrenSpan.style.fontWeight = 'bold'; luckyReqFrenSpan.className = ColourTextPre + luckyColourFrenzy; luckyReqFrenSpan.textContent = Beautify(CacheLuckyFrenzy); luckyReqFrenFrag.appendChild(luckyReqFrenSpan); if (luckyTimeFrenzy !== '') { const luckyReqFrenSmall = document.createElement('small'); luckyReqFrenSmall.textContent = ` (${luckyTimeFrenzy})`; luckyReqFrenFrag.appendChild(luckyReqFrenSmall); } section.appendChild( StatsListing( 'withTooltip', '"Lucky!" cookies required (frenzy)', luckyReqFrenFrag, goldCookTooltip, ), ); const luckySplit = CacheLuckyReward !== CacheLuckyWrathReward; const luckyRewardMaxSpan = document.createElement('span'); luckyRewardMaxSpan.style.fontWeight = 'bold'; luckyRewardMaxSpan.className = ColourTextPre + CacheLuckyReward; luckyRewardMaxSpan.textContent = Beautify(CacheLuckyReward) + (luckySplit ? ` / ${Beautify(CacheLuckyWrathReward)}` : ''); section.appendChild( StatsListing( 'withTooltip', `"Lucky!" reward (max)${luckySplit ? ' (golden / wrath)' : ''}`, luckyRewardMaxSpan, goldCookTooltip, ), ); const luckyRewardFrenzyMaxSpan = document.createElement('span'); luckyRewardFrenzyMaxSpan.style.fontWeight = 'bold'; luckyRewardFrenzyMaxSpan.className = ColourTextPre + luckyRewardFrenzyMaxSpan; luckyRewardFrenzyMaxSpan.textContent = Beautify(CacheLuckyRewardFrenzy) + (luckySplit ? ` / ${Beautify(CacheLuckyWrathRewardFrenzy)}` : ''); section.appendChild( StatsListing( 'withTooltip', `"Lucky!" reward (max) (frenzy)${luckySplit ? ' (golden / wrath)' : ''}`, luckyRewardFrenzyMaxSpan, goldCookTooltip, ), ); const luckyCurBase = Math.min( (Game.cookies + GetWrinkConfigBank()) * 0.15, CacheNoGoldSwitchCookiesPS * CacheDragonsFortuneMultAdjustment * 60 * 15, ) + 13; const luckyCurSpan = document.createElement('span'); luckyCurSpan.style.fontWeight = 'bold'; luckyCurSpan.className = ColourTextPre + luckyCurSpan; luckyCurSpan.textContent = Beautify(CacheGoldenCookiesMult * luckyCurBase) + (luckySplit ? ` / ${Beautify(CacheWrathCookiesMult * luckyCurBase)}` : ''); section.appendChild( StatsListing( 'withTooltip', `"Lucky!" reward (cur)${luckySplit ? ' (golden / wrath)' : ''}`, luckyCurSpan, goldCookTooltip, ), ); return section; } /** * This function creates the "Chain" section of the stats page * @returns {object} section The object contating the Chain section */ export function ChainSection() { // This sets which tooltip to display for certain stats const goldCookTooltip = Game.auraMult("Dragon's Fortune") ? 'GoldCookDragonsFortuneTooltipPlaceholder' : 'GoldCookTooltipPlaceholder'; const section = document.createElement('div'); section.className = 'CMStatsChainSection'; const chainColour = Game.cookies + GetWrinkConfigBank() < CacheChainRequired ? ColourRed : ColourGreen; const chainTime = Game.cookies + GetWrinkConfigBank() < CacheChainRequired ? FormatTime((CacheChainRequired - (Game.cookies + GetWrinkConfigBank())) / GetCPS()) : ''; const chainReqFrag = document.createDocumentFragment(); const chainReqSpan = document.createElement('span'); chainReqSpan.style.fontWeight = 'bold'; chainReqSpan.className = ColourTextPre + chainColour; chainReqSpan.textContent = Beautify(CacheChainRequired); chainReqFrag.appendChild(chainReqSpan); if (chainTime !== '') { const chainReqSmall = document.createElement('small'); chainReqSmall.textContent = ` (${chainTime})`; chainReqFrag.appendChild(chainReqSmall); } section.appendChild( StatsListing('withTooltip', '"Chain" cookies required', chainReqFrag, goldCookTooltip), ); const chainWrathColour = Game.cookies + GetWrinkConfigBank() < CacheChainWrathRequired ? ColourRed : ColourGreen; const chainWrathTime = Game.cookies + GetWrinkConfigBank() < CacheChainWrathRequired ? FormatTime((CacheChainWrathRequired - (Game.cookies + GetWrinkConfigBank())) / GetCPS()) : ''; const chainWrathReqFrag = document.createDocumentFragment(); const chainWrathReqSpan = document.createElement('span'); chainWrathReqSpan.style.fontWeight = 'bold'; chainWrathReqSpan.className = ColourTextPre + chainWrathColour; chainWrathReqSpan.textContent = Beautify(CacheChainWrathRequired); chainWrathReqFrag.appendChild(chainWrathReqSpan); if (chainWrathTime !== '') { const chainWrathReqSmall = document.createElement('small'); chainWrathReqSmall.textContent = ` (${chainWrathTime})`; chainWrathReqFrag.appendChild(chainWrathReqSmall); } section.appendChild( StatsListing( 'withTooltip', '"Chain" cookies required (Wrath)', chainWrathReqFrag, goldCookTooltip, ), ); const chainColourFrenzy = Game.cookies + GetWrinkConfigBank() < CacheChainFrenzyRequired ? ColourRed : ColourGreen; const chainTimeFrenzy = Game.cookies + GetWrinkConfigBank() < CacheChainFrenzyRequired ? FormatTime((CacheChainFrenzyRequired - (Game.cookies + GetWrinkConfigBank())) / GetCPS()) : ''; const chainReqFrenFrag = document.createDocumentFragment(); const chainReqFrenSpan = document.createElement('span'); chainReqFrenSpan.style.fontWeight = 'bold'; chainReqFrenSpan.className = ColourTextPre + chainColourFrenzy; chainReqFrenSpan.textContent = Beautify(CacheChainFrenzyRequired); chainReqFrenFrag.appendChild(chainReqFrenSpan); if (chainTimeFrenzy !== '') { const chainReqFrenSmall = document.createElement('small'); chainReqFrenSmall.textContent = ` (${chainTimeFrenzy})`; chainReqFrenFrag.appendChild(chainReqFrenSmall); } section.appendChild( StatsListing( 'withTooltip', '"Chain" cookies required (Frenzy)', chainReqFrenFrag, goldCookTooltip, ), ); const chainWrathColourFrenzy = Game.cookies + GetWrinkConfigBank() < CacheChainFrenzyWrathRequired ? ColourRed : ColourGreen; const chainWrathTimeFrenzy = Game.cookies + GetWrinkConfigBank() < CacheChainFrenzyWrathRequired ? FormatTime( (CacheChainFrenzyWrathRequired - (Game.cookies + GetWrinkConfigBank())) / GetCPS(), ) : ''; const chainWrathReqFrenFrag = document.createDocumentFragment(); const chainWrathReqFrenSpan = document.createElement('span'); chainWrathReqFrenSpan.style.fontWeight = 'bold'; chainWrathReqFrenSpan.className = ColourTextPre + chainWrathColourFrenzy; chainWrathReqFrenSpan.textContent = Beautify(CacheChainFrenzyWrathRequired); chainWrathReqFrenFrag.appendChild(chainWrathReqFrenSpan); if (chainWrathTimeFrenzy !== '') { const chainWrathReqFrenSmall = document.createElement('small'); chainWrathReqFrenSmall.textContent = ` (${chainWrathTimeFrenzy})`; chainWrathReqFrenFrag.appendChild(chainWrathReqFrenSmall); } section.appendChild( StatsListing( 'withTooltip', '"Chain" cookies required (frenzy) (Wrath)', chainWrathReqFrenFrag, goldCookTooltip, ), ); section.appendChild( StatsListing( 'withTooltip', '"Chain" reward (max) (golden / wrath)', document.createTextNode( `${Beautify(CacheChainMaxReward[0])} / ${Beautify(CacheChainWrathMaxReward[0])}`, ), goldCookTooltip, ), ); section.appendChild( StatsListing( 'withTooltip', '"Chain" reward (max) (frenzy) (golden / wrath)', document.createTextNode( `${Beautify(CacheChainFrenzyMaxReward[0])} / ${Beautify(CacheChainFrenzyMaxReward[0])}`, ), goldCookTooltip, ), ); const chainCurMax = Math.min( Game.cookiesPs * 60 * 60 * 6 * CacheDragonsFortuneMultAdjustment, Game.cookies * 0.5, ); const chainCur = MaxChainCookieReward(7, chainCurMax, CacheGoldenCookiesMult)[0]; const chainCurWrath = MaxChainCookieReward(6, chainCurMax, CacheWrathCookiesMult)[0]; section.appendChild( StatsListing( 'withTooltip', '"Chain" reward (cur) (golden / wrath)', document.createTextNode(`${Beautify(chainCur)} / ${Beautify(chainCurWrath)}`), goldCookTooltip, ), ); section.appendChild( StatsListing( 'withTooltip', 'CPS needed for next level (g / w)', document.createTextNode( `${Beautify(CacheChainRequiredNext)} / ${Beautify(CacheChainWrathRequiredNext)}`, ), 'ChainNextLevelPlaceholder', ), ); section.appendChild( StatsListing( 'withTooltip', 'CPS needed for next level (frenzy) (g / w)', document.createTextNode( `${Beautify(CacheChainFrenzyRequiredNext)} / ${Beautify( CacheChainFrenzyWrathRequiredNext, )}`, ), 'ChainNextLevelPlaceholder', ), ); return section; } /** * This function creates the "Spells" section of the stats page * @returns {object} section The object contating the Spells section */ export function SpellsSection() { const section = document.createElement('div'); section.className = 'CMStatsSpellsSection'; const conjureColour = Game.cookies + GetWrinkConfigBank() < CacheConjure ? ColourRed : ColourGreen; const conjureTime = Game.cookies + GetWrinkConfigBank() < CacheConjure ? FormatTime((CacheConjure - (Game.cookies + GetWrinkConfigBank())) / GetCPS()) : ''; const conjureReqFrag = document.createDocumentFragment(); const conjureReqSpan = document.createElement('span'); conjureReqSpan.style.fontWeight = 'bold'; conjureReqSpan.className = ColourTextPre + conjureColour; conjureReqSpan.textContent = Beautify(CacheConjure); conjureReqFrag.appendChild(conjureReqSpan); if (conjureTime !== '') { const conjureReqSmall = document.createElement('small'); conjureReqSmall.textContent = ` (${conjureTime})`; conjureReqFrag.appendChild(conjureReqSmall); } section.appendChild( StatsListing( 'withTooltip', '"Conjure Baked Goods" cookies required', conjureReqFrag, 'GoldCookTooltipPlaceholder', ), ); section.appendChild( StatsListing( 'withTooltip', '"Conjure Baked Goods" reward (max)', document.createTextNode(Beautify(CacheConjureReward)), 'GoldCookTooltipPlaceholder', ), ); const conjureFrenzyColour = Game.cookies + GetWrinkConfigBank() < CacheConjure * 7 ? ColourRed : ColourGreen; const conjureFrenzyCur = Math.min( (Game.cookies + GetWrinkConfigBank()) * 0.15, CacheNoGoldSwitchCookiesPS * 60 * 30, ); const conjureFrenzyTime = Game.cookies + GetWrinkConfigBank() < CacheConjure * 7 ? FormatTime((CacheConjure * 7 - (Game.cookies + GetWrinkConfigBank())) / GetCPS()) : ''; const conjureFrenzyReqFrag = document.createDocumentFragment(); const conjureFrenzyReqSpan = document.createElement('span'); conjureFrenzyReqSpan.style.fontWeight = 'bold'; conjureFrenzyReqSpan.className = ColourTextPre + conjureFrenzyColour; conjureFrenzyReqSpan.textContent = Beautify(CacheConjure * 7); conjureFrenzyReqFrag.appendChild(conjureFrenzyReqSpan); if (conjureFrenzyTime !== '') { const conjureFrenzyReqSmall = document.createElement('small'); conjureFrenzyReqSmall.textContent = ` (${conjureFrenzyTime})`; conjureFrenzyReqFrag.appendChild(conjureFrenzyReqSmall); } section.appendChild( StatsListing( 'withTooltip', '"Conjure Baked Goods" cookies required (frenzy)', conjureFrenzyReqFrag, 'GoldCookTooltipPlaceholder', ), ); section.appendChild( StatsListing( 'withTooltip', '"Conjure Baked Goods" reward (max) (frenzy)', document.createTextNode(Beautify(CacheConjureReward * 7)), 'GoldCookTooltipPlaceholder', ), ); section.appendChild( StatsListing( 'withTooltip', '"Conjure Baked Goods" reward (cur)', document.createTextNode(Beautify(conjureFrenzyCur)), 'GoldCookTooltipPlaceholder', ), ); if (CacheEdifice) { section.appendChild( StatsListing( 'withTooltip', '"Spontaneous Edifice" cookies required (most expensive building)', document.createTextNode(`${Beautify(CacheEdifice)} (${CacheEdificeBuilding})`), 'GoldCookTooltipPlaceholder', ), ); } return section; } /** * This function creates the "Garden" section of the stats page * @returns {object} section The object contating the Spells section */ export function GardenSection() { const section = document.createElement('div'); section.className = 'CMStatsGardenSection'; const bakeberryColour = Game.cookies < Game.cookiesPs * 60 * 10 * 100 ? ColourRed : ColourGreen; const bakeberryFrag = document.createElement('span'); bakeberryFrag.style.fontWeight = 'bold'; bakeberryFrag.className = ColourTextPre + bakeberryColour; bakeberryFrag.textContent = Beautify(Game.cookiesPs * 60 * 10 * 100); section.appendChild( StatsListing('basic', 'Cookies required for max reward of Bakeberry: ', bakeberryFrag), ); const chocorootColour = Game.cookies < Game.cookiesPs * 60 * 100 ? ColourRed : ColourGreen; const chocorootFrag = document.createElement('span'); chocorootFrag.style.fontWeight = 'bold'; chocorootFrag.className = ColourTextPre + chocorootColour; chocorootFrag.textContent = Beautify(Game.cookiesPs * 60 * 100); section.appendChild( StatsListing('basic', 'Cookies required for max reward of Chocoroot: ', chocorootFrag), ); const queenbeetColour = Game.cookies < Game.cookiesPs * 60 * 60 * 25 ? ColourRed : ColourGreen; const queenbeetFrag = document.createElement('span'); queenbeetFrag.style.fontWeight = 'bold'; queenbeetFrag.className = ColourTextPre + queenbeetColour; queenbeetFrag.textContent = Beautify(Game.cookiesPs * 60 * 60 * 25); section.appendChild( StatsListing('basic', 'Cookies required for max reward of Queenbeet: ', queenbeetFrag), ); const duketaterColour = Game.cookies < Game.cookiesPs * 60 * 15 * 100 ? ColourRed : ColourGreen; const duketaterFrag = document.createElement('span'); duketaterFrag.style.fontWeight = 'bold'; duketaterFrag.className = ColourTextPre + duketaterColour; duketaterFrag.textContent = Beautify(Game.cookiesPs * 60 * 15 * 100); section.appendChild( StatsListing('basic', 'Cookies required for max reward of Duketater: ', duketaterFrag), ); const missingPlantDrops = []; Object.keys(GameData.PlantDrops).forEach((i) => { if (!Game.HasUnlocked(GameData.PlantDrops[i])) { missingPlantDrops.push(GameData.PlantDrops[i]); } }); if (missingPlantDrops.length !== 0) { section.appendChild( StatsListing('basic', 'Rare plant drops left to unlock', StatsMissDisp(missingPlantDrops)), ); } return section; } /** * This function creates the "Prestige" section of the stats page * @returns {object} section The object contating the Prestige section */ export function PrestigeSection() { const section = document.createElement('div'); section.className = 'CMStatsPrestigeSection'; const possiblePresMax = Math.floor( Game.HowMuchPrestige( CacheRealCookiesEarned + Game.cookiesReset + CacheWrinklersTotal + (Game.HasUnlocked('Chocolate egg') && !Game.Has('Chocolate egg') ? CacheLastChoEgg : 0), ), ); section.appendChild( StatsListing( 'withTooltip', 'Prestige level (cur / max)', document.createTextNode(`${Beautify(Game.prestige)} / ${Beautify(possiblePresMax)}`), 'PrestMaxTooltipPlaceholder', ), ); const neededCook = Math.max( 0, Game.HowManyCookiesReset(possiblePresMax + 1) - (CacheRealCookiesEarned + Game.cookiesReset + CacheWrinklersTotal + ((Game.HasUnlocked('Chocolate egg') && !Game.Has('Chocolate egg') ? CacheLastChoEgg : 0) ? CacheLastChoEgg : 0)), ); const cookiesNextFrag = document.createDocumentFragment(); cookiesNextFrag.appendChild(document.createTextNode(Beautify(neededCook))); const cookiesNextSmall = document.createElement('small'); cookiesNextSmall.textContent = ` (${FormatTime(neededCook / CacheAvgCPSWithChoEgg, 1)})`; cookiesNextFrag.appendChild(cookiesNextSmall); section.appendChild( StatsListing( 'withTooltip', 'Cookies to next level', cookiesNextFrag, 'NextPrestTooltipPlaceholder', ), ); section.appendChild( StatsListing( 'withTooltip', 'Heavenly chips (cur / max)', document.createTextNode( `${Beautify(Game.heavenlyChips)} / ${Beautify( possiblePresMax - Game.prestige + Game.heavenlyChips, )}`, ), 'HeavenChipMaxTooltipPlaceholder', ), ); section.appendChild( StatsListing( 'basic', 'Heavenly chips per second (last 5 seconds)', document.createTextNode(Beautify(CacheHCPerSecond, 2)), ), ); const HCTarget = Number(CMOptions.HeavenlyChipsTarget); if (!Number.isNaN(HCTarget)) { const CookiesTillTarget = HCTarget - Math.floor(Game.HowMuchPrestige(Game.cookiesReset + Game.cookiesEarned)); if (CookiesTillTarget > 0) { section.appendChild( StatsListing( 'basic', 'Heavenly chips to target set in settings (cur)', document.createTextNode(Beautify(CookiesTillTarget)), ), ); section.appendChild( StatsListing( 'basic', 'Time till target (cur, current 5 second average)', document.createTextNode(FormatTime(CookiesTillTarget / CacheHCPerSecond)), ), ); } } const resetBonus = ResetBonus(possiblePresMax); const resetFrag = document.createDocumentFragment(); resetFrag.appendChild(document.createTextNode(Beautify(resetBonus))); const increase = Math.round((resetBonus / Game.cookiesPs) * 10000); if (Number.isFinite(increase) && increase !== 0) { const resetSmall = document.createElement('small'); resetSmall.textContent = ` (${increase / 100}% of income)`; resetFrag.appendChild(resetSmall); } section.appendChild( StatsListing('withTooltip', 'Reset bonus income', resetFrag, 'ResetTooltipPlaceholder'), ); const currentPrestige = Math.floor(Game.HowMuchPrestige(Game.cookiesReset)); const willHave = Math.floor(Game.HowMuchPrestige(Game.cookiesReset + Game.cookiesEarned)); const willGet = willHave - currentPrestige; if (!Game.Has('Lucky digit')) { let delta7 = 7 - (willHave % 10); if (delta7 < 0) delta7 += 10; const next7Reset = willGet + delta7; const next7Total = willHave + delta7; const frag7 = document.createDocumentFragment(); frag7.appendChild( document.createTextNode( `${next7Total.toLocaleString()} / ${next7Reset.toLocaleString()} (+${delta7})`, ), ); section.appendChild(StatsListing('basic', 'Next "Lucky Digit" (total / reset)', frag7)); } if (!Game.Has('Lucky number')) { let delta777 = 777 - (willHave % 1000); if (delta777 < 0) delta777 += 1000; const next777Reset = willGet + delta777; const next777Total = willHave + delta777; const frag777 = document.createDocumentFragment(); frag777.appendChild( document.createTextNode( `${next777Total.toLocaleString()} / ${next777Reset.toLocaleString()} (+${delta777})`, ), ); section.appendChild(StatsListing('basic', 'Next "Lucky Number" (total / reset)', frag777)); } if (!Game.Has('Lucky payout')) { let delta777777 = 777777 - (willHave % 1000000); if (delta777777 < 0) delta777777 += 1000000; const next777777Reset = willGet + delta777777; const next777777Total = willHave + delta777777; const frag777777 = document.createDocumentFragment(); frag777777.appendChild( document.createTextNode( `${next777777Total.toLocaleString()} / ${next777777Reset.toLocaleString()} (+${delta777777})`, ), ); section.appendChild(StatsListing('basic', 'Next "Lucky Payout" (total / reset)', frag777777)); } return section; } /** * This function creates the "Season Specials" section of the stats page * @returns {object} section The object contating the Season Specials section */ export function SeasonSection() { const section = document.createElement('div'); section.className = 'CMStatsSeasonSection'; let specDisp = false; const missingHalloweenCookies = []; Object.keys(GameData.HalloCookies).forEach((i) => { if (!Game.Has(GameData.HalloCookies[i])) { missingHalloweenCookies.push(GameData.HalloCookies[i]); specDisp = true; } }); const missingChristmasCookies = []; Object.keys(GameData.ChristCookies).forEach((i) => { if (!Game.Has(GameData.ChristCookies[i])) { missingChristmasCookies.push(GameData.ChristCookies[i]); specDisp = true; } }); const missingValentineCookies = []; Object.keys(GameData.ValCookies).forEach((i) => { if (!Game.Has(GameData.ValCookies[i])) { missingValentineCookies.push(GameData.ValCookies[i]); specDisp = true; } }); const missingNormalEggs = []; Object.keys(Game.eggDrops).forEach((i) => { if (!Game.HasUnlocked(Game.eggDrops[i])) { missingNormalEggs.push(Game.eggDrops[i]); specDisp = true; } }); const missingRareEggs = []; Object.keys(Game.rareEggDrops).forEach((i) => { if (!Game.HasUnlocked(Game.rareEggDrops[i])) { missingRareEggs.push(Game.rareEggDrops[i]); specDisp = true; } }); const choEgg = Game.HasUnlocked('Chocolate egg') && !Game.Has('Chocolate egg'); const centEgg = Game.Has('Century egg'); if (Game.season === 'christmas' || specDisp || choEgg || centEgg) { section.appendChild(StatsHeader('Season Specials', 'Sea')); if (CMOptions.Header.Sea) { if (missingHalloweenCookies.length !== 0) { section.appendChild( StatsListing( 'basic', 'Halloween cookies left to buy', StatsMissDisp(missingHalloweenCookies), ), ); let failRateHalloween = 0.95; if (Game.HasAchiev('Spooky cookies')) failRateHalloween = 0.8; if (Game.Has('Starterror')) failRateHalloween *= 0.9; failRateHalloween *= 1 / Game.dropRateMult(); if (Game.hasGod) { const godLvl = Game.hasGod('seasons'); if (godLvl === 1) failRateHalloween *= 0.9; else if (godLvl === 2) failRateHalloween *= 0.95; else if (godLvl === 3) failRateHalloween *= 0.97; } const obtainedCookiesChance = missingHalloweenCookies.length / 7; section.appendChild( StatsListing( 'basic', 'Chance of receiving a cookie from wrinkler/shiny wrinkler', document.createTextNode( `${Beautify((1 - failRateHalloween) * obtainedCookiesChance * 100)}% / ${Beautify( (1 - failRateHalloween * 0.9) * obtainedCookiesChance * 100, )}%`, ), ), ); } if (missingChristmasCookies.length !== 0) { section.appendChild( StatsListing( 'basic', 'Christmas cookies left to buy', StatsMissDisp(missingChristmasCookies), ), ); let failRateChristmas = 0.8; if (Game.HasAchiev('Let it snow')) failRateChristmas = 0.6; failRateChristmas *= 1 / Game.dropRateMult(); if (Game.Has('Starsnow')) failRateChristmas *= 0.95; if (Game.hasGod) { const godLvl = Game.hasGod('seasons'); if (godLvl === 1) failRateChristmas *= 0.9; else if (godLvl === 2) failRateChristmas *= 0.95; else if (godLvl === 3) failRateChristmas *= 0.97; } const obtainedCookiesChance = missingChristmasCookies.length / 7; section.appendChild( StatsListing( 'basic', 'Chance of receiving a cookie from reindeer', document.createTextNode( `${Beautify((1 - failRateChristmas) * obtainedCookiesChance * 100)}%`, ), ), ); } if (missingValentineCookies.length !== 0) { section.appendChild( StatsListing( 'basic', 'Valentine cookies left to buy', StatsMissDisp(missingValentineCookies), ), ); } const dropRateEgg = function (StartingFailRate) { let failRateEgg = StartingFailRate * (1 / Game.dropRateMult()); if (Game.HasAchiev('Hide & seek champion')) failRateEgg *= 0.7; if (Game.Has('Omelette')) failRateEgg *= 0.9; if (Game.Has('Starspawn')) failRateEgg *= 0.9; if (Game.hasGod) { const godLvl = Game.hasGod('seasons'); if (godLvl === 1) failRateEgg *= 0.9; else if (godLvl === 2) failRateEgg *= 0.95; else if (godLvl === 3) failRateEgg *= 0.97; } // Calculations courtesy of @svschouw, at https://github.com/Aktanusa/CookieMonster/issues/25 const succesRateEgg = 1 - failRateEgg; const obtainedEggs = Game.eggDrops.length - missingNormalEggs.length; const obtainedRareEggs = Game.rareEggDrops.length - missingRareEggs.length; const pNormal1 = succesRateEgg * 0.9 * (1 - obtainedEggs / Game.eggDrops.length); const pRare1 = succesRateEgg * 0.1 * (1 - obtainedRareEggs / Game.rareEggDrops.length); const pRedropNormal = succesRateEgg * 0.9 * (obtainedEggs / Game.eggDrops.length); const pRedropRare = succesRateEgg * 0.1 * (obtainedRareEggs / Game.rareEggDrops.length); const pRedrop = pRedropNormal + pRedropRare; const pNormal2 = pRedrop * 0.9 * (1 - obtainedEggs / Game.eggDrops.length); const pRare2 = pRedrop * 0.1 * (1 - obtainedRareEggs / Game.rareEggDrops.length); return [pNormal1 + pNormal2, pRare1 + pRare2]; }; if (missingNormalEggs.length !== 0) { section.appendChild( StatsListing( 'basic', 'Normal easter eggs left to unlock', StatsMissDisp(missingNormalEggs), ), ); section.appendChild( StatsListing( 'basic', 'Chance of receiving an egg from wrinkler/golden cookie', document.createTextNode( `${Beautify(dropRateEgg(0.98)[0] * 100)}% / ${Beautify(dropRateEgg(0.9)[0] * 100)}%`, ), ), ); } if (missingRareEggs.length !== 0) { section.appendChild( StatsListing('basic', 'Rare easter eggs left to unlock', StatsMissDisp(missingRareEggs)), ); section.appendChild( StatsListing( 'basic', 'Chance of receiving a rare egg from wrinkler/golden cookie', document.createTextNode( `${Beautify(dropRateEgg(0.98)[1] * 100)}% / ${Beautify(dropRateEgg(0.9)[1] * 100)}%`, ), ), ); } if (Game.season === 'christmas') section.appendChild( StatsListing('basic', 'Reindeer reward', document.createTextNode(Beautify(CacheSeaSpec))), ); if (choEgg) { section.appendChild( StatsListing( 'withTooltip', 'Chocolate egg cookies', document.createTextNode(Beautify(CacheLastChoEgg)), 'ChoEggTooltipPlaceholder', ), ); } if (centEgg) { section.appendChild( StatsListing( 'basic', 'Century egg multiplier', document.createTextNode(`${Math.round((CacheCentEgg - 1) * 10000) / 100}%`), ), ); } } } return section; }