Vue.component("charger", { props: ["layer", "data"], template: ` `, data() { const index = this.data.index; const touchstart = () => { player.color.batteries[index].active = true; }; const touchend = () => { player.color.batteries[index].active = false; }; const handlers = { mouseenter: touchstart, touchstart: touchstart, touchend: touchend, mouseleave: touchend }; return { handlers }; } }); Vue.component("battery", { props: ["layer", "data"], template: `
` }); Vue.component("tree-tab-challenge", { props: ["layer", "data"], template: "" }); Vue.component("buyMax", { props: ["layer", "data"], template: `
` }); addLayer("color", { name: "color", resource: "color energy", color: "white", startData() { return { points: new Decimal(0), // vue is giving me trouble, so I had to do this... // hope I don't need over 100 batteries (end game should have 14) batteries: new Array(100).fill(1).reduce((acc,curr,i) => { acc[i] = { active: false, progress: 0, lastActive: 0 }; return acc; }, {}) }; }, getResetGain() { let { base, multi } = getRedColorEffect(); let gain = new Decimal(0.1).add(base); let batteryGain = new Decimal(0); for (const index in player.color.batteries) { batteryGain = batteryGain.add(player.color.batteries[index].progress); } gain = gain.add(batteryGain.times(getBlueColorEffect())); gain = gain.times(multi); if (hasUpgrade(this.layer, 1)) { gain = gain.times(5); } if (hasUpgrade(this.layer, 5)) { gain = gain.times(upgradeEffect(this.layer, 5)); } gain = gain.times(buyableEffect("color", 3)); if (hasYellowEffect(5)) { gain = gain.times(getBlueColorEffect()).max(1); } gain = gain.pow(buyableEffect("color", 55)); return gain; }, update(diff) { for (const index in player.color.batteries) { const battery = player.color.batteries[index]; let gain = new Decimal(diff); if (battery.active || (index % 2 === 1 && hasCyanEffect(4)) || (index % 2 === 0 && hasCyanEffect(5))) { gain = gain.div(10); gain = gain.times(buyableEffect("color", 13)); battery.lastActive = 0; } else if (hasCyanEffect(2) && battery.lastActive >= 0 && battery.lastActive < getTotalSecondaryLight().div(4)) { gain = gain.div(10); gain = gain.times(buyableEffect("color", 13)); battery.lastActive = battery.lastActive + diff; } else { gain = gain.times(-1).div(20); gain = gain.div(buyableEffect("color", 13)); battery.lastActive = -1; } battery.progress = new Decimal(battery.progress).add(gain).clamp(0, 1).toNumber(); } }, automate() { if (hasCyanEffect(1)) { for (id in tmp[this.layer].upgrades) { if (isPlainObject(tmp[this.layer].upgrades[id]) && (layers[this.layer].upgrades[id].canAfford === undefined || layers[this.layer].upgrades[id].canAfford() === true)) { buyUpg(this.layer, id); } } if (hasCyanEffect(3)) { for (id in layers[this.layer].buyables) { /* if (layers[this.layer].buyables[id].buyMax) { layers[this.layer].buyables[id].buyMax(); } */ if (isPlainObject(tmp[this.layer].buyables[id]) && (layers[this.layer].buyables[id].canAfford === undefined || layers[this.layer].buyables[id].canAfford() === true)) { buyBuyable(this.layer, id); } } } } }, passiveGeneration: new Decimal(1), tabFormat: () => [ ["tree-tab-challenge", 1], "blank", ["display-text", `You have

${format(player.color.points)}

color energy`], "blank", ["display-text", `You are collecting ${format(tmp.color.getResetGain)} color energy per second`], "blank", ["row", [["upgrade", 1], ["upgrade", 5], ["upgrade", 21]]], ["row", [["upgrade", 2], ["upgrade", 8], ["upgrade", 34]]], "blank", ["row", [["buyable", 3], ["buyable", 13], ["buyable", 55]]], ["row", [["buyMax", 3], ["buyMax", 13], ["buyMax", 55]]], "blank", ["row", new Array(getNumBatteries().times(2).max(1).sub(1).toNumber()).fill(1).map((_, i) => i % 2 === 0 ? ["column", [ ["charger", { index: i, color: getCurrentColor(.5) }], "blank", ["display-text", `+${format(new Decimal((player.color.batteries[i] && player.color.batteries[i].progress) || 0).times(getBlueColorEffect()))}`], ["battery", i], ["blank", "34px"] ]] : "blank")] ], buyables: { 3: { title: "Alhazen", display() { return `
Rebuyable. Double color energy gain.

Currently: x${format(this.effect())}

Cost: ${format(this.cost())} color energy`; }, style: () => ({ color: "white" }), color: () => getCurrentColor(.5), cost(x) { const amount = x || getBuyableAmount(this.layer, this.id); return new Decimal(100).times(new Decimal(10).pow(amount)); }, effect() { return new Decimal(2).pow(this.getLevel()); }, canAfford() { return player[this.layer].points.gte(this.cost()); }, buy() { player[this.layer].points = player[this.layer].points.sub(this.cost()); setBuyableAmount(this.layer, this.id, getBuyableAmount(this.layer, this.id).add(1)); }, buyMax() { const amount = getBuyableAmount(this.layer, this.id); const costExponent = new Decimal(10); const baseCost = new Decimal(100); const amountAffordable = player[this.layer].points.times(costExponent.sub(1)).div(new Decimal(baseCost).times(Decimal.pow(costExponent, amount))).add(1).log(costExponent).floor(); const cost = baseCost.times(costExponent.pow(amount).times(costExponent.pow(amountAffordable).sub(1))).div(costExponent.sub(1)); player[this.layer].points = player[this.layer].points.sub(cost); setBuyableAmount(this.layer, this.id, amount.add(amountAffordable)); }, unlocked() { return player.green.gte(this.id); }, getLevel() { let amount = getBuyableAmount(this.layer, this.id); amount = amount.add(Decimal.clamp(player.green.sub(3), 0, 1)); amount = amount.add(Decimal.clamp(player.green.sub(5), 0, 2)); amount = amount.add(Decimal.clamp(player.green.sub(8), 0, 4)); if (hasUpgrade("color", 34)) { amount = amount.add(layers.color.buyables["13"].getLevel()); } return amount; } }, 13: { title: "Newton", display() { return `
Rebuyable. Batteries charge 10% faster and deplete 10% slower.

Currently: x${format(this.effect())}

Cost: ${format(this.cost())} color energy`; }, style: () => ({ color: "white" }), color: () => getCurrentColor(.5), cost(x) { const amount = x || getBuyableAmount(this.layer, this.id); return new Decimal(1000).times(new Decimal(25).pow(amount)); }, effect() { return this.getLevel().times(0.1).add(1); }, canAfford() { return player[this.layer].points.gte(this.cost()); }, buy() { player[this.layer].points = player[this.layer].points.sub(this.cost()); setBuyableAmount(this.layer, this.id, getBuyableAmount(this.layer, this.id).add(1)); }, buyMax() { const amount = getBuyableAmount(this.layer, this.id); const costExponent = new Decimal(25); const baseCost = new Decimal(1000); const amountAffordable = player[this.layer].points.times(costExponent.sub(1)).div(new Decimal(baseCost).times(Decimal.pow(costExponent, amount))).add(1).log(costExponent).floor(); const cost = baseCost.times(costExponent.pow(amount).times(costExponent.pow(amountAffordable).sub(1))).div(costExponent.sub(1)); player[this.layer].points = player[this.layer].points.sub(cost); setBuyableAmount(this.layer, this.id, amount.add(amountAffordable)); }, unlocked() { return player.green.gte(this.id); }, getLevel() { let amount = getBuyableAmount(this.layer, this.id); amount = amount.add(Decimal.clamp(player.green.sub(13), 0, 7)); amount = amount.add(Decimal.clamp(player.green.sub(21), 0, 12)); amount = amount.add(Decimal.clamp(player.green.sub(34), 0, 20)); if (hasUpgrade("color", 34)) { amount = amount.add(layers.color.buyables["55"].getLevel()); } if (hasYellowEffect(4)) { amount = amount.add(getTotalSecondaryLight); } return amount; } }, 55: { title: "Einstein", display() { return `
Rebuyable. Add 0.01 to the color gain exponent.

Currently: ^${format(this.effect())}

Cost: ${format(this.cost())} color energy`; }, style: () => ({ color: "white" }), color: () => getCurrentColor(.5), cost(x) { const amount = x || getBuyableAmount(this.layer, this.id); return new Decimal(1e21).tetrate(amount.div(100).add(1)); }, effect() { return this.getLevel().times(0.01).add(1); }, canAfford() { return player[this.layer].points.gte(this.cost()); }, buy() { player[this.layer].points = player[this.layer].points.sub(this.cost()); setBuyableAmount(this.layer, this.id, getBuyableAmount(this.layer, this.id).add(1)); }, buyMax() { /* TODO how to buy max a tetration formula const amount = getBuyableAmount(this.layer, this.id); const costExponent = new Decimal(100); const baseCost = new Decimal(1e21); const amountAffordable = player[this.layer].points.times(costExponent.sub(1)).div(new Decimal(baseCost).times(Decimal.pow(costExponent, amount))).add(1).log(costExponent).floor(); const cost = baseCost.times(costExponent.pow(amount).times(costExponent.pow(amountAffordable).sub(1))).div(costExponent.sub(1)); player[this.layer].points = player[this.layer].points.sub(cost); setBuyableAmount(this.layer, this.id, amount.add(amountAffordable)); */ // Since it tetrates this will hopefully be fine while (this.canAfford()) { this.buy(); } }, unlocked() { return player.green.gte(this.id); }, getLevel() { let amount = getBuyableAmount(this.layer, this.id); amount = amount.add(Decimal.max(player.green.sub(55), 0)); return amount; } }, }, upgrades: { 1: { title: "Corpuscular theory", description: "
Multiply color energy gain by 5", cost: new Decimal(1), style: () => ({ color: "white" }), color: () => getCurrentColor(.5), unlocked() { return player.green.gte(this.id); } }, 2: { title: "Double Slit Experiment", description: "
Half the goal for each unlocked battery + 1", cost: new Decimal(1e3), style: () => ({ color: "white" }), color: () => getCurrentColor(.5), unlocked() { return player.green.gte(this.id); }, effect() { return Decimal.pow(2, getNumBatteries().add(1)); }, effectDisplay() { return `/${formatWhole(this.effect())}`; } }, 5: { title: "Wave Theory", description: "
Color energy gain is multiplied by 5 raised to the amount of unspent light + 1", cost: new Decimal(1e6), style: () => ({ color: "white" }), color: () => getCurrentColor(.5), unlocked() { return player.green.gte(this.id); }, effect() { return Decimal.pow(5, player.points.sub(player.red).sub(player.green).sub(player.blue).add(1)); }, effectDisplay() { return `x${formatWhole(this.effect())}`; } }, 8: { title: "Emission theory", description: "
Increase battery cap based on time spent in this challenge", cost: new Decimal(1e4), style: () => ({ color: "white" }), color: () => getCurrentColor(.5), unlocked() { return player.green.gte(this.id); }, effect() { return new Decimal(player.color.resetTime).max(1); }, effectDisplay() { return `x${format(this.effect())}`; } }, 21: { title: "Quantum theory", description: "
Apply red light effect's additional times based on unspent light", cost: new Decimal(1e12), style: () => ({ color: "white" }), color: () => getCurrentColor(.5), unlocked() { return player.green.gte(this.id); }, effect() { return player.points.sub(player.red).sub(player.green).sub(player.blue).add(1).pow(.1).add(.5); }, effectDisplay() { return `+${format(this.effect())} times`; } }, 34: { title: "Special Relativity", description: "
Each buyable gives free levels to the previous buyable.", cost: new Decimal(1e18), style: () => ({ color: "white" }), color: () => getCurrentColor(.5), unlocked() { return player.green.gte(this.id); } } } }); // animate electricity svg const numberOfPoints = 20; const lineWidth = 4; const amplitude = 30; const margin = 10; const maxHeight = 400 - margin * 2; const width = 100; let animateElectricity = () => { const containers = document.querySelectorAll(".battery > svg"); for (let i = 0; i < containers.length; i++) { const container = containers[i]; const height = parseInt(getComputedStyle(container).getPropertyValue("height").slice(0, -2)); if (height === margin * 2) { continue; } if (Math.random() < .5) { continue; } const numPoints = Math.max(3, Math.floor(numberOfPoints * height / maxHeight)); let coords = new Array(numPoints).fill(1).map((_,i) => { let first = i == 0; let last = i == numPoints - 1; let y = (height - margin * 2) / (numPoints - 1) * i + margin; let x = (first || last) ? width / 2 : (width - amplitude) / 2 + Math.random() * amplitude; return { x, y }; }); // Draw path let path = container.querySelector("path"); path.setAttribute("d", "M" + coords.map(coord => coord.x + "," + coord.y).join(" L")); // Style path let deviation = Math.random() * (5 - 2) + 2; path.style.opacity = deviation / 5 + 0.2; path.style.strokeWidth = lineWidth; // Style glow let glow = container.querySelector("#glow feDropShadow"); glow.setAttribute("stdDeviation", deviation); } requestAnimationFrame(animateElectricity); }; requestAnimationFrame(animateElectricity);