This commit is contained in:
thepaperpilot 2021-02-21 11:31:54 -06:00
parent b74c340580
commit 75dee2cefe
14 changed files with 897 additions and 356 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

View file

@ -11,8 +11,10 @@
<script type="text/javascript" src="js/technical/layerSupport.js"></script>
<script type="text/javascript" src="js/colors.js"></script>
<script type="text/javascript" src="js/Layers/flowers.js"></script>
<script type="text/javascript" src="js/Layers/distill.js"></script>
<script type="text/javascript" src="js/Layers/study.js"></script>
<script type="text/javascript" src="js/Layers/sands.js"></script>
<script type="text/javascript" src="js/Layers/generators.js"></script>
<script type="text/javascript" src="js/tree.js"></script>
<script type="text/javascript" src="js/mod.js"></script>
<script type="text/javascript" src="js/technical/temp.js"></script>

216
js/Layers/distill.js Normal file
View file

@ -0,0 +1,216 @@
function getInstrument(instrument, requiredLevel, symbol, label = instrument.charAt(0).toUpperCase() + instrument.slice(1)) {
if (getJobLevel("distill").lt(requiredLevel)) {
return null;
}
return ["row", [
["column", [
["buyable", instrument],
["display-text", `<button class="smallUpg${layers.distill.buyables[instrument].canAfford() ? " can" : " locked"}" style="width: 175px; background: ${layers.distill.buyables[instrument].canAfford() ? distillColor : "#bf8f8f"}; border-radius: 20px; color: black;" onClick="layers.distill.buyables.${instrument}.buyMax()">Buy Max</button>`]
]],
"blank",
["display-text", `<div class="instrument" style="--instrument-progress: ${player.distill.anims ? Decimal.times(player.distill[`${instrument}Progress`], buyableEffect("distill", instrument)).times(100).toFixed(2) : 0}%">
<span>${label}</span><br/>
<span class="instrumentLogo">${symbol}</span><br/>
<span>x${format(player.distill[`${instrument}Completions`].div(100).add(1))}</span>
</div>`]
]];
}
function getInstrumentBuyable(id, title, baseSpeed, baseCost, costExponent) {
return {
title: `${title}<br/>`,
style: {
width: "175px",
height: "175px"
},
display() {
return `Make retort finish ${format(baseSpeed, 3)} more times/sec.<br/>(Capped at ${format(baseSpeed.times(100))})${getBuyableAmount("distill", id).lt(100) ? `<br/><br/>Currently: ${format(this.effect())}<br/><br/>Cost: ${format(this.cost())} essentia` : ""}`;
},
cost(x) {
const amount = x || getBuyableAmount("distill", id);
return new Decimal(baseCost).times(new Decimal(costExponent).pow(amount));
},
buyMax() {
const amount = getBuyableAmount("distill", id);
const amountAffordable = player.distill.points.times(costExponent.sub(1)).div(new Decimal(baseCost).times(Decimal.pow(costExponent, amount))).add(1).log(costExponent).floor().clamp(0, Decimal.sub(100, amount));
const cost = baseCost.times(costExponent.pow(amount).times(costExponent.pow(amountAffordable).sub(1))).div(costExponent.sub(1));
player.distill.points = player.distill.points.sub(cost);
setBuyableAmount("distill", id, amount.add(amountAffordable));
},
effect() {
let speed = new Decimal(baseSpeed);
speed = speed.times(getBuyableAmount("distill", id));
return speed;
},
canAfford() {
return player.distill.points.gte(this.cost()) && getBuyableAmount("distill", id).lt(100);
},
buy() {
player.distill.points = player.distill.points.sub(this.cost());
setBuyableAmount("distill", id, getBuyableAmount("distill", id).add(1));
},
unlocked: true
};
}
function updateInstrument(instrument, requiredLevel, diff) {
if (getJobLevel("distill").lt(requiredLevel) || buyableEffect("distill", instrument).eq(0)) {
return;
}
player.distill[`${instrument}Progress`] = player.distill[`${instrument}Progress`].add(diff);
const completionDuration = Decimal.div(1, buyableEffect("distill", instrument));
const completions = player.distill[`${instrument}Progress`].div(completionDuration).floor();
if (completions.gt(0)) {
player.distill[`${instrument}Progress`] = player.distill[`${instrument}Progress`].sub(completionDuration.times(completions));
player.distill[`${instrument}Completions`] = player.distill[`${instrument}Completions`].add(completions);
addPoints("distill", completions.times(getEssentiaMult()));
}
}
function getEssentiaMult() {
let gain = new Decimal(1);
gain = gain.times(player.distill.retortCompletions.div(100).add(1));
gain = gain.times(player.distill.alembicCompletions.div(100).add(1));
gain = gain.times(player.distill.crucibleCompletions.div(100).add(1));
gain = gain.times(player.distill.bainMarieCompletions.div(100).add(1));
gain = gain.times(player.distill.vapoursCompletions.div(100).add(1));
if (player.generators.distillActive) {
gain = gain.sqrt();
}
return gain;
}
addLayer("distill", {
name: "distill",
resource: "essentia",
image: "images/PIXNIO-252785-4924x3283.jpg",
color: distillColor,
jobName: "Distill flowers",
showJobDelay: 0.25,
layerShown: () => player.chapter > 1 && hasMilestone("flowers", 4),
startData() {
return {
unlocked: true,
points: new Decimal(0),
total: new Decimal(0),
xp: new Decimal(0),
lastLevel: new Decimal(0),
anims: true,
timeLoopActive: false,
retortProgress: new Decimal(0),
retortCompletions: new Decimal(0),
alembicProgress: new Decimal(0),
alembicCompletions: new Decimal(0),
crucibleProgress: new Decimal(0),
crucibleCompletions: new Decimal(0),
bainMarieProgress: new Decimal(0),
bainMarieCompletions: new Decimal(0),
vapoursProgress: new Decimal(0),
vapoursCompletions: new Decimal(0)
};
},
tabFormat: () => [
"main-display",
["display-text", `You are getting ${format(getEssentiaMult())} essentia every time an instrument finishes.`],
"blank",
["display-text", (() => {
if (!hasMilestone("distill", 0)) {
return "Discover new ways to harness the power of the flower essence at level 2";
}
if (!hasMilestone("distill", 1)) {
return "Discover new ways to harness the power of the flower essence at level 4";
}
if (!hasMilestone("distill", 3)) {
return "Discover new ways to harness the power of the flower essence at level 6";
}
if (!hasMilestone("distill", 4)) {
return "Discover new ways to harness the power of the flower essence at level 8";
}
return "";
})()],
"blank",
["row", [
["display-text", "Animations"],
"blank",
["toggle", ["distill", "anims"]]
]],
"blank",
getInstrument("retort", 0, "🝭"),
"blank",
getInstrument("alembic", 2, "🝪"),
"blank",
getInstrument("crucible", 4, "🝧"),
"blank",
getInstrument("bainMarie", 6, "🝫", "Bain-Marie"),
"blank",
getInstrument("vapours", 8, "🝬", "Bath of Vapours"),
"blank",
["milestones-filtered", [2, 5, 6]]
],
update(diff) {
if (player.tab === this.layer || player[this.layer].timeLoopActive) {
if (player.generators.distillActive) {
diff = new Decimal(diff).div(10);
}
updateInstrument("retort", 0, diff);
updateInstrument("alembic", 2, diff);
updateInstrument("crucible", 4, diff);
updateInstrument("bainMarie", 6, diff);
updateInstrument("vapours", 8, diff);
}
let jobLevel = new Decimal(getJobLevel(this.layer));
if (jobLevel.neq(player[this.layer].lastLevel)) {
doPopup("none", `Level ${jobLevel}`, "Level Up!", 3, layers[this.layer].color);
player[this.layer].lastLevel = jobLevel;
}
},
onAddPoints(gain) {
let xpGain = gain;
player[this.layer].xp = player[this.layer].xp.add(xpGain);
},
milestones: {
0: {
requirementDescription: "Level 2",
done: () => player.distill.xp.gte(10)
},
1: {
requirementDescription: "Level 4",
done: () => player.distill.xp.gte(1e3)
},
2: {
title: "\"The only true wisdom consists in knowing that you know nothing.\"",
requirementDescription: "Level 5",
"effectDescription": "Unlock studying job",
done: () => player.distill.xp.gte(1e4)
},
3: {
requirementDescription: "Level 6",
done: () => player.distill.xp.gte(1e5)
},
4: {
requirementDescription: "Level 8",
done: () => player.distill.xp.gte(1e7)
},
5: {
title: "That's us, dude!",
requirementDescription: "Level 10",
"effectDescription": "Unlock time experiments job",
done: () => player.distill.xp.gte(1e9),
unlocked: () => hasMilestone("distill", 2)
},
6: {
title: "Oh, yeah!",
requirementDescription: "Level 25",
"effectDescription": "Unlock ???",
done: () => player.distill.xp.gte(1e24) && player.chapter > 2,
unlocked: () => hasMilestone("distill", 5) && player.chapter > 2
}
},
buyables: {
retort: getInstrumentBuyable("retort", "Be excellent to each other.", new Decimal(0.06), new Decimal(10), new Decimal(1.05)),
alembic: getInstrumentBuyable("alembic", "EXCELLENT!", new Decimal(0.03), new Decimal(100), new Decimal(1.1)),
crucible: getInstrumentBuyable("crucible", "Party on dudes!", new Decimal(0.02), new Decimal(1000), new Decimal(1.15)),
bainMarie: getInstrumentBuyable("bainMarie", "Greetings, my excellent friends.", new Decimal(0.015), new Decimal(10000), new Decimal(1.2)),
vapours: getInstrumentBuyable("vapours", "Most outstanding, Rufus! Let's jam!", new Decimal(0.012), new Decimal(100000), new Decimal(1.25))
}
});

View file

@ -36,6 +36,9 @@ addLayer("flowers", {
}
gain = gain.times(buyableEffect("flowers", 11));
gain = gain.pow(buyableEffect("flowers", 13));
if (player.generators.flowerActive) {
gain = gain.sqrt().div(10);
}
return gain;
},
passiveGeneration: new Decimal(1),
@ -96,6 +99,9 @@ addLayer("flowers", {
],
update(diff) {
if (player.tab === this.layer || player[this.layer].timeLoopActive) {
if (player.generators.flowerActive) {
diff = diff / 10;
}
player[this.layer].realTime += diff;
}
let jobLevel = new Decimal(getJobLevel(this.layer));
@ -140,7 +146,7 @@ addLayer("flowers", {
title: "the telling so credible and sober",
requirementDescription: "Level 25",
"effectDescription": "Unlock ???",
done: () => player.flowers.xp.gte(1e24),
done: () => player.flowers.xp.gte(1e24) && player.chapter > 2,
unlocked: () => player.chapter > 2
}
},
@ -198,7 +204,8 @@ addLayer("flowers", {
return `Each casting of this spell increases its cost, and raises flower collection rate to an additive +.05 power (softcapped immediately).<br/><br/>Currently: ^${format(this.effect())}<br/><br/>Cost: ${format(this.cost())} flowers`;
},
cost(x) {
return new Decimal(250000).times(new Decimal(10).pow(x || getBuyableAmount(this.layer, this.id)));
const amount = x || getBuyableAmount(this.layer, this.id);
return new Decimal(250000).times(amount.sub(10).max(0).add(10).pow(amount));
},
effect() {
return new Decimal(.05).times(getBuyableAmount(this.layer, this.id).pow(.6)).add(1);

181
js/Layers/generators.js Normal file
View file

@ -0,0 +1,181 @@
addLayer("generators", {
name: "generators",
resource: "joules",
image: "images/PIXNIO-1742428-5028x2828.jpg",
color: electricColor,
jobName: "Run Generators",
showJobDelay: 1,
layerShown: () => hasMilestone("study", 5),
startData() {
return {
unlocked: true,
points: new Decimal(0),
xp: new Decimal(0),
lastLevel: new Decimal(0),
timeLoopActive: false,
flowerActive: false,
studyActive: false,
sandsActive: false
};
},
getResetGain() {
if (!tmp[this.layer].layerShown || (player.tab !== this.layer && !player[this.layer].timeLoopActive)) {
return new Decimal(0);
}
let gain = new Decimal(0);
if (player.generators.flowerActive) {
gain = gain.add(getJobLevel("flowers").div(10));
}
if (player.generators.studyActive) {
gain = gain.add(getJobLevel("study").div(10));
}
if (player.generators.sandsActive) {
gain = gain.add(getJobLevel("sands").div(10));
}
gain = gain.times(new Decimal(1.1).pow(getJobLevel(this.layer)));
return gain;
},
passiveGeneration: new Decimal(1),
tabFormat: {
"Main": {
content: () => [
"main-display",
["display-text", `You are collecting <span style="color: ${electricColor}; text-shadow: ${electricColor} 0 0 10px">${format(tmp.generators.getResetGain)}</span> joules per second`],
"blank",
["display-text", (() => {
if (!hasMilestone("generators", 0)) {
return "Discover new ways to harness the electric power at level 2";
}
if (!hasMilestone("generators", 1)) {
return "Discover new ways to harness the electric power at level 4";
}
if (!hasMilestone("generators", 2)) {
return "Discover new ways to harness the electric power at level 6";
}
if (!hasMilestone("generators", 3)) {
return "Discover new ways to harness the electric power at level 8";
}
if (!hasMilestone("generators", 4)) {
return "Discover new ways to harness the electric power at level 10";
}
return "";
})()],
"blank",
"blank",
["row", [["clickable", "flowersGenerator"], "blank", ["clickable", "studyGenerator"], "blank", ["clickable", "sandsGenerator"]]],
"blank",
"blank",
["milestones-filtered", [2, 5, 6]]
]
}
},
update(diff) {
if (player.tab === this.layer || player[this.layer].timeLoopActive) {
}
let jobLevel = new Decimal(getJobLevel(this.layer));
if (jobLevel.neq(player[this.layer].lastLevel) && player[this.layer].lastLevel.lte(100)) {
doPopup("none", `Level ${formatWhole(jobLevel)}`, "Level Up!", 3, layers[this.layer].color);
player[this.layer].lastLevel = jobLevel;
}
},
onAddPoints(gain) {
let xpGain = gain;
player[this.layer].xp = player[this.layer].xp.add(xpGain);
},
milestones: {
0: {
requirementDescription: "Level 2",
done: () => player.generators.xp.gte(10)
},
1: {
requirementDescription: "Level 4",
done: () => player.generators.xp.gte(1e3)
},
2: {
title: "Silence Earthling!",
requirementDescription: "Level 5",
"effectDescription": "Unlock a new feature in collecting job",
done: () => player.generators.xp.gte(1e4)
},
3: {
requirementDescription: "Level 6",
done: () => player.generators.xp.gte(1e5)
},
4: {
requirementDescription: "Level 8",
done: () => player.generators.xp.gte(1e7)
},
5: {
title: "My name is Darth Vader.",
requirementDescription: "Level 10",
"effectDescription": "Unlock a new feature in ??? job",
done: () => player.generators.xp.gte(1e9),
unlocked: () => hasMilestone("generators", 2)
},
6: {
title: "I am an extraterrestrial",
requirementDescription: "Level 25",
"effectDescription": "Unlock ???",
done: () => player.generators.xp.gte(1e24) && player.chapter > 2,
unlocked: () => player.chapter > 3
}
},
clickables: {
flowersGenerator: {
title: "I hate manure!<br/>",
display: () => `Generate electricity based on gather level.<br/><br/>Flowers gain is softcapped immediately and the job runs 10x slower.<br/><br/>Currently: <b>${player.generators.flowerActive ? "ACTIVE" : "INACTIVE"}</b>`,
class: () => ({ "gradient-border": player.generators.flowerActive }),
style: {
width: "200px",
height: "200px"
},
onClick() {
player.generators.flowerActive = !player.generators.flowerActive;
}
},
studyGenerator: {
title: "Great Scott!<br/>",
display: () => `Generate electricity based on study level.<br/><br/>Properties gain is softcapped immediately and the job runs 10x slower.<br/><br/>Currently: <b>${player.generators.studyActive ? "ACTIVE" : "INACTIVE"}</b>`,
class: () => ({ "gradient-border": player.generators.studyActive }),
style: {
width: "200px",
height: "200px"
},
onClick() {
player.generators.studyActive = !player.generators.studyActive;
}
},
sandsGenerator: {
title: "This is heavy!<br/>",
display: () => `Generate electricity based on experiment level.<br/><br/>Potentia gain is softcapped immediately and the job runs 10x slower.<br/><br/>Currently: <b>${player.generators.sandsActive ? "ACTIVE" : "INACTIVE"}</b>`,
class: () => ({ "gradient-border": player.generators.sandsActive }),
style: {
width: "200px",
height: "200px"
},
onClick() {
player.generators.sandsActive = !player.generators.sandsActive;
}
},
// TODO ??? generator
// "Nobody Calls Me Chicken."
// "Wait A Minute, Doc."
// "When the hell are they."
},
buyables: {
rows: 1,
cols: 4,
11: {
title: "1.21 Gigawatts!?!<br/>"
},
12: {
title: "88 Miles Per Hour<br/>"
},
13: {
title: "Where Were Going, We Dont Need Roads.<br/>"
},
14: {
title: "I finally invent something that works!<br/>"
}
}
});

View file

@ -13,6 +13,9 @@ function getFallSpeed() {
fallSpeed = fallSpeed.times(2);
}
}
if (player.generators.sandsActive) {
fallSpeed = fallSpeed.div(10);
}
return fallSpeed;
}
@ -20,6 +23,9 @@ function getFlipSpeed() {
let flipSpeed = new Decimal(1);
flipSpeed = flipSpeed.times(new Decimal(1.1).pow(getJobLevel("sands")));
flipSpeed = flipSpeed.times(buyableEffect("sands", 22));
if (player.generators.sandsActive) {
flipSpeed = flipSpeed.div(10);
}
return flipSpeed;
}
@ -49,6 +55,9 @@ function getPotentiaMult() {
gain = gain.times(2);
}
}
if (player.generators.sandsActive) {
gain = gain.sqrt();
}
return gain;
}
@ -58,14 +67,14 @@ addLayer("sands", {
image: "images/pexels-photo-1095601.jpeg",
color: sandsColor,
jobName: "Experiments with time",
showJobDelay: 0.5,
layerShown: () => player.chapter > 1 && hasMilestone("study", 2),
showJobDelay: 0.75,
layerShown: () => hasMilestone("distill", 2),
startData() {
return {
unlocked: true,
points: new Decimal(1),
xp: new Decimal(1),
lastLevel: new Decimal(1),
points: new Decimal(0),
xp: new Decimal(0),
lastLevel: new Decimal(0),
timeLoopActive: false,
grainsFallen: new Decimal(0),
shrunkAmount: new Decimal(0),
@ -82,7 +91,6 @@ addLayer("sands", {
const percentChipped = new Decimal(1).sub(player.sands.shrunkAmount.div(nextStoneCost())).times(10000);
return [
"main-display",
"blank",
["display-text", (() => {
if (!hasMilestone("sands", 0)) {
return "Discover new ways to experiment at level 2";
@ -101,10 +109,10 @@ addLayer("sands", {
"blank",
["display-text", formatWhole(getTotalGrains().sub(player.sands.grainsFallen))],
["display-text", `<div style="
--fill-duration: ${player.sands.flipping || player.sands.grainsFallen.eq(getTotalGrains()) ? 1 : getTotalGrains().div(getFallMult()).ceil().times(4).div(player.devSpeed).div(getFallSpeed()).toNumber() + 0.05}s;
--fill-delay: -${player.sands.flipping || player.sands.grainsFallen.eq(getTotalGrains()) ? .999 : player.sands.grainsFallen.div(getFallMult()).floor().times(4).div(player.devSpeed).div(getFallSpeed()).toNumber()}s;
--fill-duration: ${player.sands.flipping || player.sands.grainsFallen.eq(getTotalGrains()) ? 1 : getTotalGrains().div(getFallMult()).ceil().times(4).div(player.devSpeed || 1).div(getFallSpeed()).toNumber() + 0.05}s;
--fill-delay: -${player.sands.flipping || player.sands.grainsFallen.eq(getTotalGrains()) ? .999 : player.sands.grainsFallen.div(getFallMult()).floor().times(4).div(player.devSpeed || 1).div(getFallSpeed()).toNumber()}s;
--fill-state: ${player.sands.grainsFallen.eq(getTotalGrains()) || player.sands.flipping ? "paused" : "running"};
--flip-duration: ${new Decimal(5).div(player.devSpeed).div(getFlipSpeed()).toNumber() + 0.05}s;
--flip-duration: ${new Decimal(5).div(player.devSpeed || 1).div(getFlipSpeed()).toNumber() + 0.05}s;
--flip-state: ${player.sands.flipping ? "running" : "paused"};
"><div class="hourglass"></div></div>`],
["display-text", formatWhole(player.sands.grainsFallen)],
@ -152,10 +160,10 @@ addLayer("sands", {
"blank",
["display-text", formatWhole(getTotalGrains().sub(player.sands.grainsFallen))],
["display-text", `<div style="
--fill-duration: ${player.sands.flipping || player.sands.grainsFallen.eq(getTotalGrains()) ? 1 : getTotalGrains().div(getFallMult()).ceil().times(4).div(player.devSpeed).div(getFallSpeed()).toNumber() + 0.05}s;
--fill-delay: -${player.sands.flipping || player.sands.grainsFallen.eq(getTotalGrains()) ? .999 : player.sands.grainsFallen.div(getFallMult()).floor().times(4).div(player.devSpeed).div(getFallSpeed()).toNumber()}s;
--fill-duration: ${player.sands.flipping || player.sands.grainsFallen.eq(getTotalGrains()) ? 1 : getTotalGrains().div(getFallMult()).ceil().times(4).div(player.devSpeed || 1).div(getFallSpeed()).toNumber() + 0.05}s;
--fill-delay: -${player.sands.flipping || player.sands.grainsFallen.eq(getTotalGrains()) ? .999 : player.sands.grainsFallen.div(getFallMult()).floor().times(4).div(player.devSpeed || 1).div(getFallSpeed()).toNumber()}s;
--fill-state: ${player.sands.grainsFallen.eq(getTotalGrains()) || player.sands.flipping ? "paused" : "running"};
--flip-duration: ${new Decimal(5).div(player.devSpeed).div(getFlipSpeed()).toNumber() + 0.05}s;
--flip-duration: ${new Decimal(5).div(player.devSpeed || 1).div(getFlipSpeed()).toNumber() + 0.05}s;
--flip-state: ${player.sands.flipping ? "running" : "paused"};
"><div class="hourglass"></div></div>`],
["display-text", formatWhole(player.sands.grainsFallen)],
@ -197,6 +205,9 @@ addLayer("sands", {
shrinkGain = shrinkGain.times(new Decimal(1.1).pow(getJobLevel(this.layer)));
shrinkGain = shrinkGain.times(buyableEffect("sands", 11));
shrinkGain = shrinkGain.times(buyableEffect("sands", 21));
if (player.generators.sandsActive) {
shrinkGain = shrinkGain.div(10);
}
player[this.layer].shrunkAmount = player[this.layer].shrunkAmount.add(shrinkGain);
}
@ -277,7 +288,7 @@ addLayer("sands", {
5: {
title: "I mean, this stuff is way too advanced for me.",
requirementDescription: "Level 10",
"effectDescription": "Unlock ??? job",
"effectDescription": "Unlock rituals job",
done: () => player.sands.xp.gte(1e9),
unlocked: () => hasMilestone("sands", 2)
},
@ -285,7 +296,7 @@ addLayer("sands", {
title: "And what if I can't fix this? What are we gonna do?",
requirementDescription: "Level 25",
"effectDescription": "Unlock ???",
done: () => player.sands.xp.gte(1e24),
done: () => player.sands.xp.gte(1e24) && player.chapter > 2,
unlocked: () => hasMilestone("sands", 5) && player.chapter > 2
}
},

View file

@ -12,14 +12,21 @@ const cards = {
gainBigPoints: createCard("In his experience the Universe simply didn't work like that.", level => `Successfully study ${format(getResetGain("study").times(level.add(1)).pow(1.2))} properties. Destroy this card.`, (level, canDestroy = true) => {
addPoints("study", getResetGain("study").times(level.add(1)).pow(1.2));
if (canDestroy) {
const index = player.study.cards.findIndex(el => el[0] === "gainBigPoints");
const index = player.study.cards.indexOf("gainBigPoints");
if (index >= 0) {
player.study.cards.splice(index, 1);
}
}
}),
gainInsight: createCard("And it shall be called... the Earth.", level => level == 0 ? "Gain a key insight." : `Gain ${formatWhole(level.add(1))} key insights.`, level => player.study.insights = player.study.insights.add(level).add(1)),
gainBigInsight: createCard("Yes! I shall design this computer for you.", level => `Gain ${new Decimal(player.study.cards.length).times(level.add(1)).sqrt().floor()} key insights.<br/>(based on number of cards in the deck)`, level => player.study.insights = player.study.insights.add(new Decimal(player.study.cards.length).times(level.add(1)).sqrt().floor())),
gainInsight: createCard("And it shall be called... the Earth.", level => level == 0 ? "Gain a key insight." : `Gain ${formatWhole(level.add(1))} key insights.`, level => {
player.study.insights = player.study.insights.add(level).add(1);
player.study.xp = player.study.xp.add(level.add(1).times(10));
}),
gainBigInsight: createCard("Yes! I shall design this computer for you.", level => `Gain ${new Decimal(player.study.cards.length).times(level.add(1)).sqrt().floor()} key insights.<br/>(based on number of cards in the deck)`, level => {
const amount = new Decimal(player.study.cards.length).times(level.add(1)).sqrt().floor();
player.study.insights = player.study.insights.add(amount);
player.study.xp = player.study.xp.add(amount.times(10));
}),
playTwice: createCard("Oh no, not again.", level => level == 0 ? "Play the next card twice." : `Play the next card twice, with the effect boosted by ${level.div(4)} levels.`, null, (nextCard, level) => {
if (nextCard in cards && cards[nextCard].onDraw) {
cards[nextCard].onDraw(cardLevel(nextCard).add(level.div(4)));
@ -27,7 +34,7 @@ const cards = {
}
}),
increasePointsGain: createCard("Have another drink, enjoy yourself.", level => {
const effect = softcap(player.study.increasePointsGain, new Decimal(100).times(level.add(1)), .25).times(10);
const effect = softcap(player.study.increasePointsGain, new Decimal(100).times(level.add(1))).times(10);
let text = `Permanently increase studied properties gain by 10%.<br/><br/>Currently: +${formatWhole(effect)}%`;
if (player.study.increasePointsGain.gt(new Decimal(100).times(level.add(1)))) {
text = text + "<br/>(softcapped)";
@ -50,18 +57,20 @@ const cards = {
}
return text;
}, () => player.study.sellDiscount = player.study.sellDiscount.add(1)),
soldOut: createCard("Out of Stock!")
soldOut: createCard("Out of Stock!"),
gainXp: createCard("A billion times over ... and no one learns anything.", level => `Gain xp equal to ${level == 0 ? "" : `${format(level.div(4).add(1))}x times `}your number of properties.`, level => player.study.xp = player.study.xp.add(player.study.points.times(level.div(4).add(1))))
};
const shopCards = [
{ card: "gainPoints", price: 3 },
{ card: "gainInsight", price: 5 },
{ card: "gainBigPoints", price: 23 },
{ card: "gainBigInsight", price: 42 },
{ card: "playTwice", price: 50 },
{ card: "increasePointsGain", price: 10 },
{ card: "multiplyPointsGain", price: 25 },
{ card: "sellDiscount", price: 80 },
{ card: "gainPoints", price: 1 },
{ card: "gainInsight", price: 2 },
{ card: "gainBigPoints", price: 8 },
{ card: "gainBigInsight", price: 13 },
{ card: "playTwice", price: 16 },
{ card: "increasePointsGain", price: 6 },
{ card: "multiplyPointsGain", price: 18 },
{ card: "sellDiscount", price: 14 },
{ card: "gainXp", price: 25 },
];
const baseCards = () => {
@ -87,7 +96,7 @@ const cardFormat = (card, id = "", className = "", onclick = "", overrideLevel =
function getCardUpgradeBuyable(id) {
const cost = x => {
const amount = x || getBuyableAmount("study", id);
return new Decimal(100).pow(amount.add(1)).times(10);
return new Decimal(100).pow(amount.add(1));
};
return {
title: "Upgrade card<br/>",
@ -130,10 +139,19 @@ function getDrawDuration() {
let drawSpeed = new Decimal(10);
drawSpeed = drawSpeed.div(new Decimal(1.1).pow(getJobLevel("study")));
drawSpeed = drawSpeed.times(new Decimal(2).pow(player.study.deep));
if (player.generators.studyActive) {
drawSpeed = drawSpeed.times(10);
}
return drawSpeed;
}
const REFRESH_PERIOD = 300;
function getRefreshPeriod() {
let refreshPeriod = new Decimal(120);
if (player.generators.studyActive) {
refreshPeriod = refreshPeriod.times(10);
}
return refreshPeriod;
}
addLayer("study", {
name: "study",
@ -141,8 +159,8 @@ addLayer("study", {
image: "images/orchid_sketch.jpg",
color: studyColor,
jobName: "Study flowers",
showJobDelay: 0.25,
layerShown: () => player.chapter > 1 && hasMilestone("flowers", 4),
showJobDelay: 0.5,
layerShown: () => hasMilestone("distill", 2),
startData() {
return {
unlocked: true,
@ -170,8 +188,11 @@ addLayer("study", {
return new Decimal(0);
}
let gain = new Decimal(10);
gain = gain.times(softcap(player.study.increasePointsGain, new Decimal(100).times(cardLevel("increasePointsGain").add(1)), .25).times(0.1).add(1));
gain = gain.times(softcap(player.study.increasePointsGain, new Decimal(100).times(cardLevel("increasePointsGain").add(1))).times(0.1).add(1));
gain = gain.times(new Decimal(1.02).pow(softcap(player.study.multiplyPointsGain, new Decimal(100).times(cardLevel("multiplyPointsGain").div(4).add(1)), .2)));
if (player.generators.studyActive) {
gain = gain.sqrt().div(10);
}
return gain;
},
tabFormat: {
@ -181,16 +202,16 @@ addLayer("study", {
"blank",
["display-text", (() => {
if (!hasMilestone("study", 0)) {
return "Discover new ways to study at level 2";
return "Discover new ways to harness the power of the cards at level 2";
}
if (!hasMilestone("study", 1)) {
return "Discover new ways to study at level 4";
return "Discover new ways to harness the power of the cards at level 4";
}
if (!hasMilestone("study", 3)) {
return "Discover new ways to study at level 6";
return "Discover new ways to harness the power of the cards at level 6";
}
if (!hasMilestone("study", 4)) {
return "Discover new ways to study at level 8";
return "Discover new ways to harness the power of the cards at level 8";
}
return "";
})()],
@ -209,7 +230,7 @@ addLayer("study", {
content: () => [
["display-text", `<span>You have <h2 style="color: darkcyan; text-shadow: darkcyan 0 0 10px">${formatWhole(player.study.insights)}</h2> key insights</span>`],
"blank",
["display-text", `Cards refresh in ${new Decimal(REFRESH_PERIOD - player.study.refreshProgress).clampMax(REFRESH_PERIOD - 0.01).toFixed(2)} seconds`],
["display-text", `Cards refresh in ${new Decimal(getRefreshPeriod() - player.study.refreshProgress).clampMax(getRefreshPeriod() - 0.01).toFixed(2)} seconds`],
"blank",
["row", player.study.shop.map(({ card, price }, i) =>
["column", [
@ -280,7 +301,7 @@ addLayer("study", {
if (hasMilestone("study", 0)) {
player[this.layer].refreshProgress += diff;
}
if (player[this.layer].refreshProgress > REFRESH_PERIOD) {
if (player[this.layer].refreshProgress > getRefreshPeriod()) {
player[this.layer].refreshProgress = 0;
player[this.layer].shop = getShop();
for (let card of document.getElementsByClassName("shopCard")) {
@ -314,8 +335,11 @@ addLayer("study", {
2: {
title: "And all dared to brave unknown terrors, to do mighty deeds,",
requirementDescription: "Level 5",
"effectDescription": "Unlock time experiments job",
done: () => player.study.xp.gte(1e4)
"effectDescription": "Unlock a time loop",
done: () => player.study.xp.gte(1e4),
onComplete: () => {
player.timeSlots = player.timeSlots.add(1);
}
},
3: {
requirementDescription: "Level 6",
@ -328,7 +352,7 @@ addLayer("study", {
5: {
title: "to boldly split infinitives that no man had split before—",
requirementDescription: "Level 10",
"effectDescription": "Unlock ??? job",
"effectDescription": "Unlock generators job",
done: () => player.study.xp.gte(1e9),
unlocked: () => hasMilestone("study", 2)
},
@ -336,7 +360,7 @@ addLayer("study", {
title: "and thus was the Empire forged.",
requirementDescription: "Level 25",
"effectDescription": "Unlock ???",
done: () => player.study.xp.gte(1e24),
done: () => player.study.xp.gte(1e24) && player.chapter > 2,
unlocked: () => hasMilestone("study", 5) && player.chapter > 2
}
},
@ -351,7 +375,7 @@ addLayer("study", {
return `Remove a card from your deck. Cost multiplies by 100 for each card destroyed.<br/><br/>Cost: ${formatWhole(this.cost())} properties studied`;
},
cost(x) {
let cost = new Decimal(1e3).times(new Decimal(100).pow(player[this.layer].cardsSold));
let cost = new Decimal(500).times(new Decimal(10).pow(player[this.layer].cardsSold));
cost = cost.times(new Decimal(0.98).pow(softcap(player.study.sellDiscount, new Decimal(100).times(cardLevel("multiplyPointsGain").div(4).add(1)), .5)));
return cost;
},
@ -426,7 +450,8 @@ addLayer("study", {
playTwice: getCardUpgradeBuyable("playTwice"),
increasePointsGain: getCardUpgradeBuyable("increasePointsGain"),
multiplyPointsGain: getCardUpgradeBuyable("multiplyPointsGain"),
sellDiscount: getCardUpgradeBuyable("sellDiscount")
sellDiscount: getCardUpgradeBuyable("sellDiscount"),
gainXp: getCardUpgradeBuyable("gainXp")
}
});

View file

@ -1,7 +1,11 @@
// https://color.adobe.com/create/color-wheel
// Colors
const logoBackgroundColor = "#1a75bb";
const logoHighlightColor = "#000080";
const backgroundColor = "#2a323d";
const flowersColor = "#F1EBD9";
const distillColor = "#8AFFC1";
const studyColor = "#654321";
const sandsColor = "#C2B280";
const electricColor = "#89C6FF";

View file

@ -318,7 +318,7 @@ function loadVue() {
template: `
<button
v-if="tmp[layer].clickables && tmp[layer].clickables[data]!== undefined && tmp[layer].clickables[data].unlocked !== false"
v-bind:class="{ upg: true, can: tmp[layer].clickables[data].canClick !== false, locked: tmp[layer].clickables[data].canClick === false}"
v-bind:class="{ upg: true, can: tmp[layer].clickables[data].canClick !== false, locked: tmp[layer].clickables[data].canClick === false, ...tmp[layer].clickables[data].class}"
v-bind:style="[tmp[layer].clickables[data].canClick !== false ? {'background-color': tmp[layer].color} : {}, size ? {'height': size, 'width': size} : {}, tmp[layer].clickables[data].style]"
v-on="handlers">
<span v-if= "tmp[layer].clickables[data].title"><h2 v-html="tmp[layer].clickables[data].title"></h2><br></span>

View file

@ -12,11 +12,17 @@ let modInfo = {
// Set your version in num and name
let VERSION = {
num: "0.15",
name: "Chapter 2 (Time Experiments)",
num: "0.20",
name: "Chapter 2 (Distilling)",
};
let changelog = `<h1>Changelog:</h1><br>
<br><h3>v.0.20</h3><br>
- Re-arranged and re-balanced jobs
- Added distill job
- Added first mechanic of generators job
- Reset saves back to start of chapter 2
- Several bug fixes
<br><h3>v.0.15</h3><br>
- Finishing naming time experiments job upgrades<br>
- Rebalanced time experiments job<br>
@ -76,7 +82,7 @@ var displayThings = [
// Determines when the game "ends"
function isEndgame() {
return player.points.gte(new Decimal("e280000000"));
return getJobLevel("generators").gte(2) && getJobLevel("sands").gte(10);
}
@ -91,24 +97,16 @@ function maxTickLength() {
// Use this if you need to undo inflation from an older version. If the version is older than the version that fixed the issue,
// you can cap their current resources with this.
function fixOldSave(oldVersion){
if (oldVersion === "0.0") {
player.chapter = 1;
player.flowers.points = player.flowers.points.clampMax(1e9);
player.flowers.points = player.flowers.points.clampMax(player.flowers.xp);
} else if (oldVersion === "0.1") {
player.flowers.xp = player.flowers.xp.clampMax(1e15);
player.flowers.points = player.flowers.points.clampMax(player.flowers.xp);
player.study.cards = baseCards();
} else if (oldVersion === "0.11") {
player.study.xp = player.study.xp.clampMax(1e6);
player.study.points = player.study.points.clampMax(player.study.xp);
player.study.cards = player.study.cards.map(c => c[0]);
player.study.lastCard = player.study.lastCard[0];
} else if (oldVersion === "0.12") {
player.study.cards = player.study.cards.map(c => c[0]);
player.study.lastCard = player.study.lastCard[0];
} else if (oldVersion === "0.13") {
player.study.unlocked = true;
player.sands.unlocked = true;
if (["0.0", "0.1", "0.11", "0.12", "0.13", "0.14", "0.15"].includes(oldVersion) && player.chapter !== 1) {
layerDataReset("study");
layerDataReset("sands");
player.flowers.timeLoopActive = false;
player.usedTimeSlots = new Decimal(0);
player.timeSlots = new Decimal(1);
player.flowers.xp = player.flowers.xp.clampMax(1e9);
player.flowers.points = player.flowers.points.clampMax(1e6);
setBuyableAmount("flowers", 11, (getBuyableAmount("flowers", 11) || new Decimal(0)).clampMax(6));
setBuyableAmount("flowers", 12, (getBuyableAmount("flowers", 12) || new Decimal(0)).clampMax(3));
setBuyableAmount("flowers", 13, (getBuyableAmount("flowers", 13) || new Decimal(0)).clampMax(0));
}
}
}

View file

@ -25,7 +25,7 @@ function getJobLevel(job) {
if (player[job].xp.eq(0)) {
return new Decimal(0);
}
return player[job].xp.clampMin(1).log10().floor().add(1);
return softcap(player[job].xp.clampMin(1).log10().floor().add(1), new Decimal(25)).floor();
}
function getJobProgressBar(job) {
@ -38,8 +38,12 @@ function getJobProgressBar(job) {
if (level.eq(0)) {
return 0;
}
let previousLevelRequirement = level.sub(1).pow10();
let progress = player[job].xp.clampMin(1).sub(previousLevelRequirement).div(level.pow10().sub(previousLevelRequirement));
let previousLevelRequirement = level.lt(25) ? level.sub(1).pow10() :
level.div(new Decimal(25).sqrt()).pow(2).floor();
let nextLevelRequirement = level.lt(25) ? level.pow10() :
level.add(1).div(new Decimal(25).sqrt()).pow(2).floor();
let currentXp = level.lt(25) ? player[job].xp.clampMin() : player[job].xp.log10();
let progress = currentXp.sub(previousLevelRequirement).div(nextLevelRequirement.sub(previousLevelRequirement));
return progress;
},
fillStyle: { backgroundColor: layers[job].color },
@ -60,8 +64,10 @@ function toggleTimeLoop(layer) {
addLayer("tree-tab", {
bars: {
flowers: getJobProgressBar("flowers"),
distill: getJobProgressBar("distill"),
study: getJobProgressBar("study"),
sands: getJobProgressBar("sands")
sands: getJobProgressBar("sands"),
generators: getJobProgressBar("generators")
},
tabFormat: () => player.chapter < 3 ?
[
@ -73,8 +79,10 @@ addLayer("tree-tab", {
player.chapter === 2 ? ["display-text", `You have <span style="color: white; text-shadow: white 0 0 10px">${formatWhole(player.timeSlots.sub(player.usedTimeSlots))}</span> free time slots`] : null,
player.chapter === 2 ? "blank" : null,
["job", "flowers"],
["job", "distill"],
["job", "study"],
["job", "sands"]
["job", "sands"],
["job", "generators"]
] :
{
"Main": {
@ -85,8 +93,10 @@ addLayer("tree-tab", {
"blank",
"blank",
["job", "flowers"],
["job", "distill"],
["job", "study"],
["job", "sands"]
["job", "sands"],
["job", "generators"]
]
}
},
@ -97,7 +107,7 @@ addLayer("tree-tab", {
},
discovery: {
title: "Chapter 2: Discovery",
body: `[WIP, needs feedback from Hudson]<br/>The field is completely barren... Fortunately, I've collected enough <span style="color: ${flowersColor}">flowers</span> that I can finally create a time loop. Not only will this allow me to revert the field whenever it empties, it'll now open me up to close myself in the loop, effectively allowing it to run while the real me continues with my next task: <span style="color: ${studyColor}">Studying</span> the <span style="color: ${flowersColor}">flowers</span>, and eventually experimenting with how to further take advantage of the time altering properties of these <span style="color: ${flowersColor}">flowers</span>.<br/><br/>It'll be prudent of me not to forget about collecting <span style="color: ${flowersColor}">flowers</span>, as I'll still need them as I move forward.`
body: `[WIP, needs feedback from Hudson]<br/>The field is completely barren... Fortunately, I've collected enough <span style="color: ${flowersColor}">flowers</span> that I can finally create a time loop. Not only will this allow me to revert the field whenever it empties, it'll now open me up to close myself in the loop, effectively allowing it to run while the real me continues with my next task: <span style="color: ${distillColor}">Distilling</span> the <span style="color: ${flowersColor}">flowers</span>, and eventually experimenting with how to further take advantage of the time altering properties of them.<br/><br/>It'll be prudent of me not to forget about collecting <span style="color: ${flowersColor}">flowers</span>, as I'll still need them as I move forward, and in general should balance the time I spend on every job I can do.`
}
}
});

View file

@ -1,278 +1,303 @@
// ************ Save stuff ************
function save() {
localStorage.setItem(modInfo.id, btoa(JSON.stringify(player)));
}
function startPlayerBase() {
return {
tab: layoutInfo.startTab,
navTab: (layoutInfo.showTree ? "tree-tab" : "none"),
time: Date.now(),
autosave: true,
notify: {},
msDisplay: "always",
offlineProd: true,
versionType: modInfo.id,
version: VERSION.num,
beta: VERSION.beta,
timePlayed: 0,
keepGoing: false,
hasNaN: false,
hideChallenges: false,
showStory: true,
points: modInfo.initialStartPoints,
subtabs: {},
lastSafeTab: (layoutInfo.showTree ? "none" : layoutInfo.startTab)
};
}
function getStartPlayer() {
playerdata = startPlayerBase();
if (addedPlayerData) {
extradata = addedPlayerData();
for (thing in extradata)
playerdata[thing] = extradata[thing];
}
playerdata.infoboxes = {};
for (layer in layers) {
playerdata[layer] = getStartLayerData(layer);
if (layers[layer].tabFormat && !Array.isArray(layers[layer].tabFormat)) {
playerdata.subtabs[layer] = {};
playerdata.subtabs[layer].mainTabs = Object.keys(layers[layer].tabFormat)[0];
}
if (layers[layer].microtabs) {
if (playerdata.subtabs[layer] == undefined)
playerdata.subtabs[layer] = {};
for (item in layers[layer].microtabs)
playerdata.subtabs[layer][item] = Object.keys(layers[layer].microtabs[item])[0];
}
if (layers[layer].infoboxes) {
if (playerdata.infoboxes[layer] == undefined)
playerdata.infoboxes[layer] = {};
for (item in layers[layer].infoboxes)
playerdata.infoboxes[layer][item] = false;
}
}
return playerdata;
}
function getStartLayerData(layer) {
layerdata = {};
if (layers[layer].startData)
layerdata = layers[layer].startData();
if (layerdata.unlocked === undefined)
layerdata.unlocked = true;
if (layerdata.total === undefined)
layerdata.total = new Decimal(0);
if (layerdata.best === undefined)
layerdata.best = new Decimal(0);
if (layerdata.resetTime === undefined)
layerdata.resetTime = 0;
layerdata.buyables = getStartBuyables(layer);
if (layerdata.clickables == undefined)
layerdata.clickables = getStartClickables(layer);
layerdata.spentOnBuyables = new Decimal(0);
layerdata.upgrades = [];
layerdata.milestones = [];
layerdata.achievements = [];
layerdata.challenges = getStartChallenges(layer);
return layerdata;
}
function getStartBuyables(layer) {
let data = {};
if (layers[layer].buyables) {
for (id in layers[layer].buyables)
if (isPlainObject(layers[layer].buyables[id]))
data[id] = new Decimal(0);
}
return data;
}
function getStartClickables(layer) {
let data = {};
if (layers[layer].clickables) {
for (id in layers[layer].clickables)
if (isPlainObject(layers[layer].clickables[id]))
data[id] = "";
}
return data;
}
function getStartChallenges(layer) {
let data = {};
if (layers[layer].challenges) {
for (id in layers[layer].challenges)
if (isPlainObject(layers[layer].challenges[id]))
data[id] = 0;
}
return data;
}
function fixSave() {
defaultData = getStartPlayer();
fixData(defaultData, player);
for (layer in layers) {
if (player[layer].best !== undefined)
player[layer].best = new Decimal(player[layer].best);
if (player[layer].total !== undefined)
player[layer].total = new Decimal(player[layer].total);
if (layers[layer].tabFormat && !Array.isArray(layers[layer].tabFormat)) {
if (!Object.keys(layers[layer].tabFormat).includes(player.subtabs[layer].mainTabs))
player.subtabs[layer].mainTabs = Object.keys(layers[layer].tabFormat)[0];
}
if (layers[layer].microtabs) {
for (item in layers[layer].microtabs)
if (!Object.keys(layers[layer].microtabs[item]).includes(player.subtabs[layer][item]))
player.subtabs[layer][item] = Object.keys(layers[layer].microtabs[item])[0];
}
}
}
function fixData(defaultData, newData) {
for (item in defaultData) {
if (defaultData[item] == null) {
if (newData[item] === undefined)
newData[item] = null;
}
else if (Array.isArray(defaultData[item])) {
if (newData[item] === undefined)
newData[item] = defaultData[item];
else
fixData(defaultData[item], newData[item]);
}
else if (defaultData[item] instanceof Decimal) { // Convert to Decimal
if (newData[item] === undefined)
newData[item] = defaultData[item];
else
newData[item] = new Decimal(newData[item]);
}
else if ((!!defaultData[item]) && (typeof defaultData[item] === "object")) {
if (newData[item] === undefined || (typeof defaultData[item] !== "object"))
newData[item] = defaultData[item];
else
fixData(defaultData[item], newData[item]);
}
else {
if (newData[item] === undefined)
newData[item] = defaultData[item];
}
}
}
function load() {
let get = localStorage.getItem(modInfo.id);
if (get === null || get === undefined)
player = getStartPlayer();
else
player = Object.assign(getStartPlayer(), JSON.parse(atob(get)));
fixSave();
if (player.offlineProd) {
if (player.offTime === undefined)
player.offTime = { remain: 0 };
player.offTime.remain += (Date.now() - player.time) / 1000;
}
player.time = Date.now();
versionCheck();
changeTheme();
changeTreeQuality();
updateLayers();
setupModInfo();
setupTemp();
updateTemp();
updateTemp();
loadVue();
}
function setupModInfo() {
modInfo.changelog = changelog;
modInfo.winText = winText ? winText : `Congratulations! You have reached the end and beaten this game, but for now...`;
}
function fixNaNs() {
NaNcheck(player);
}
function NaNcheck(data) {
for (item in data) {
if (data[item] == null) {
}
else if (Array.isArray(data[item])) {
NaNcheck(data[item]);
}
else if (data[item] !== data[item] || data[item] === decimalNaN) {
if (NaNalert === true || confirm("Invalid value found in player, named '" + item + "'. Please let the creator of this mod know! Would you like to try to auto-fix the save and keep going?")) {
NaNalert = true;
data[item] = (data[item] !== data[item] ? 0 : decimalZero);
}
else {
clearInterval(interval);
player.autosave = false;
NaNalert = true;
}
}
else if (data[item] instanceof Decimal) { // Convert to Decimal
}
else if ((!!data[item]) && (data[item].constructor === Object)) {
NaNcheck(data[item]);
}
}
}
function exportSave() {
let str = btoa(JSON.stringify(player));
const el = document.createElement("textarea");
el.value = str;
document.body.appendChild(el);
el.select();
el.setSelectionRange(0, 99999);
document.execCommand("copy");
document.body.removeChild(el);
}
function importSave(imported = undefined, forced = false) {
if (imported === undefined)
imported = prompt("Paste your save here");
try {
tempPlr = Object.assign(getStartPlayer(), JSON.parse(atob(imported)));
if (tempPlr.versionType != modInfo.id && !forced && !confirm("This save appears to be for a different mod! Are you sure you want to import?")) // Wrong save (use "Forced" to force it to accept.)
return;
player = tempPlr;
player.versionType = modInfo.id;
fixSave();
versionCheck();
save();
window.location.reload();
} catch (e) {
return;
}
}
function versionCheck() {
let setVersion = true;
if (player.versionType === undefined || player.version === undefined) {
player.versionType = modInfo.id;
player.version = 0;
}
if (setVersion) {
if (player.versionType == modInfo.id && VERSION.num > player.version) {
player.keepGoing = false;
if (fixOldSave)
fixOldSave(player.version);
}
player.versionType = getStartPlayer().versionType;
player.version = VERSION.num;
player.beta = VERSION.beta;
}
}
var saveInterval = setInterval(function () {
if (player === undefined)
return;
if (gameEnded && !player.keepGoing)
return;
if (player.autosave)
save();
}, 5000);
// ************ Save stuff ************
function save() {
localStorage.setItem(modInfo.id, btoa(JSON.stringify(player)));
}
function startPlayerBase() {
return {
tab: layoutInfo.startTab,
navTab: (layoutInfo.showTree ? "tree-tab" : "none"),
time: Date.now(),
autosave: true,
notify: {},
msDisplay: "always",
offlineProd: true,
versionType: modInfo.id,
version: VERSION.num,
beta: VERSION.beta,
timePlayed: 0,
keepGoing: false,
hasNaN: false,
hideChallenges: false,
showStory: true,
points: modInfo.initialStartPoints,
subtabs: {},
lastSafeTab: (layoutInfo.showTree ? "none" : layoutInfo.startTab)
};
}
function getStartPlayer() {
playerdata = startPlayerBase();
if (addedPlayerData) {
extradata = addedPlayerData();
for (thing in extradata) {
playerdata[thing] = extradata[thing];
}
}
playerdata.infoboxes = {};
for (layer in layers) {
playerdata[layer] = getStartLayerData(layer);
if (layers[layer].tabFormat && !Array.isArray(layers[layer].tabFormat)) {
playerdata.subtabs[layer] = {};
playerdata.subtabs[layer].mainTabs = Object.keys(layers[layer].tabFormat)[0];
}
if (layers[layer].microtabs) {
if (playerdata.subtabs[layer] == undefined) {
playerdata.subtabs[layer] = {};
}
for (item in layers[layer].microtabs) {
playerdata.subtabs[layer][item] = Object.keys(layers[layer].microtabs[item])[0];
}
}
if (layers[layer].infoboxes) {
if (playerdata.infoboxes[layer] == undefined) {
playerdata.infoboxes[layer] = {};
}
for (item in layers[layer].infoboxes) {
playerdata.infoboxes[layer][item] = false;
}
}
}
return playerdata;
}
function getStartLayerData(layer) {
layerdata = {};
if (layers[layer].startData) {
layerdata = layers[layer].startData();
}
if (layerdata.unlocked === undefined) {
layerdata.unlocked = true;
}
if (layerdata.total === undefined) {
layerdata.total = new Decimal(0);
}
if (layerdata.best === undefined) {
layerdata.best = new Decimal(0);
}
if (layerdata.resetTime === undefined) {
layerdata.resetTime = 0;
}
layerdata.buyables = getStartBuyables(layer);
if (layerdata.clickables == undefined) {
layerdata.clickables = getStartClickables(layer);
}
layerdata.spentOnBuyables = new Decimal(0);
layerdata.upgrades = [];
layerdata.milestones = [];
layerdata.achievements = [];
layerdata.challenges = getStartChallenges(layer);
return layerdata;
}
function getStartBuyables(layer) {
let data = {};
if (layers[layer].buyables) {
for (id in layers[layer].buyables) {
if (isPlainObject(layers[layer].buyables[id])) {
data[id] = new Decimal(0);
}
}
}
return data;
}
function getStartClickables(layer) {
let data = {};
if (layers[layer].clickables) {
for (id in layers[layer].clickables) {
if (isPlainObject(layers[layer].clickables[id])) {
data[id] = "";
}
}
}
return data;
}
function getStartChallenges(layer) {
let data = {};
if (layers[layer].challenges) {
for (id in layers[layer].challenges) {
if (isPlainObject(layers[layer].challenges[id])) {
data[id] = 0;
}
}
}
return data;
}
function fixSave() {
defaultData = getStartPlayer();
fixData(defaultData, player);
setBuyableAmount("distill", "retort", (getBuyableAmount("distill", "retort") || new Decimal(0)).max(5));
for (layer in layers) {
if (player[layer].best !== undefined) {
player[layer].best = new Decimal(player[layer].best);
}
if (player[layer].total !== undefined) {
player[layer].total = new Decimal(player[layer].total);
}
if (layers[layer].tabFormat && !Array.isArray(layers[layer].tabFormat)) {
if (!Object.keys(layers[layer].tabFormat).includes(player.subtabs[layer].mainTabs)) {
player.subtabs[layer].mainTabs = Object.keys(layers[layer].tabFormat)[0];
}
}
if (layers[layer].microtabs) {
for (item in layers[layer].microtabs) {
if (!Object.keys(layers[layer].microtabs[item]).includes(player.subtabs[layer][item])) {
player.subtabs[layer][item] = Object.keys(layers[layer].microtabs[item])[0];
}
}
}
}
}
function fixData(defaultData, newData) {
for (item in defaultData) {
if (defaultData[item] == null) {
if (newData[item] === undefined) {
newData[item] = null;
}
} else if (Array.isArray(defaultData[item])) {
if (newData[item] === undefined) {
newData[item] = defaultData[item];
} else {
fixData(defaultData[item], newData[item]);
}
} else if (defaultData[item] instanceof Decimal) { // Convert to Decimal
if (newData[item] === undefined) {
newData[item] = defaultData[item];
} else {
newData[item] = new Decimal(newData[item]);
}
} else if ((!!defaultData[item]) && (typeof defaultData[item] === "object")) {
if (newData[item] === undefined || (typeof defaultData[item] !== "object")) {
newData[item] = defaultData[item];
} else {
fixData(defaultData[item], newData[item]);
}
} else {
if (newData[item] === undefined) {
newData[item] = defaultData[item];
}
}
}
}
function load() {
let get = localStorage.getItem(modInfo.id);
if (get === null || get === undefined) {
player = getStartPlayer();
} else {
player = Object.assign(getStartPlayer(), JSON.parse(atob(get)));
}
fixSave();
if (player.offlineProd) {
if (player.offTime === undefined) {
player.offTime = { remain: 0 };
}
player.offTime.remain += (Date.now() - player.time) / 1000;
}
player.time = Date.now();
versionCheck();
changeTheme();
changeTreeQuality();
updateLayers();
setupModInfo();
setupTemp();
updateTemp();
updateTemp();
loadVue();
}
function setupModInfo() {
modInfo.changelog = changelog;
modInfo.winText = winText ? winText : "Congratulations! You have reached the end and beaten this game, but for now...";
}
function fixNaNs() {
NaNcheck(player);
}
function NaNcheck(data) {
for (item in data) {
if (data[item] == null) {
} else if (Array.isArray(data[item])) {
NaNcheck(data[item]);
} else if (data[item] !== data[item] || data[item] === decimalNaN) {
if (NaNalert === true || confirm("Invalid value found in player, named '" + item + "'. Please let the creator of this mod know! Would you like to try to auto-fix the save and keep going?")) {
NaNalert = true;
data[item] = (data[item] !== data[item] ? 0 : decimalZero);
} else {
clearInterval(interval);
player.autosave = false;
NaNalert = true;
}
} else if (data[item] instanceof Decimal) { // Convert to Decimal
} else if ((!!data[item]) && (data[item].constructor === Object)) {
NaNcheck(data[item]);
}
}
}
function exportSave() {
let str = btoa(JSON.stringify(player));
const el = document.createElement("textarea");
el.value = str;
document.body.appendChild(el);
el.select();
el.setSelectionRange(0, 99999);
document.execCommand("copy");
document.body.removeChild(el);
}
function importSave(imported = undefined, forced = false) {
if (imported === undefined) {
imported = prompt("Paste your save here");
}
try {
tempPlr = Object.assign(getStartPlayer(), JSON.parse(atob(imported)));
if (tempPlr.versionType != modInfo.id && !forced && !confirm("This save appears to be for a different mod! Are you sure you want to import?")) // Wrong save (use "Forced" to force it to accept.)
{
return;
}
player = tempPlr;
player.versionType = modInfo.id;
fixSave();
versionCheck();
save();
window.location.reload();
} catch (e) {
return;
}
}
function versionCheck() {
let setVersion = true;
if (player.versionType === undefined || player.version === undefined) {
player.versionType = modInfo.id;
player.version = 0;
}
if (setVersion) {
if (player.versionType == modInfo.id && VERSION.num > player.version) {
player.keepGoing = false;
if (fixOldSave) {
fixOldSave(player.version);
}
}
player.versionType = getStartPlayer().versionType;
player.version = VERSION.num;
player.beta = VERSION.beta;
}
}
var saveInterval = setInterval(function () {
if (player === undefined) {
return;
}
if (gameEnded && !player.keepGoing) {
return;
}
if (player.autosave) {
save();
}
}, 5000);

View file

@ -917,4 +917,66 @@ button > * {
b, h3 {
text-shadow: 0 0 black;
}
}
.gradient-border {
--border-width: 4px;
position: relative;
background-clip: content-box;
}
.gradient-border::before {
position: absolute;
content: "";
background: inherit;
z-index: -1;
top: 0;
left: 0;
right: 0;
bottom: 0;
border-radius: 25%;
}
.gradient-border::after {
position: absolute;
content: "";
top: calc(-1 * var(--border-width));
left: calc(-1 * var(--border-width));
z-index: -2;
width: calc(100% + var(--border-width) * 2);
height: calc(100% + var(--border-width) * 2);
background: linear-gradient(60deg, rgba(14,0,255,1) 0%, rgba(4,194,118,1) 16%, rgba(9,9,121,1) 35%, rgba(6,139,170,1) 59%, rgba(113,3,216,1) 81%, rgba(0,212,255,1) 100%);
background-size: 300% 300%;
background-position: 0 50%;
border-radius: 25%;
animation: moveGradient 8s alternate infinite;
}
@keyframes moveGradient {
50% {
background-position: 100% 50%;
}
}
.instrument {
width: 400px;
padding: 10px;
border-radius: 10px;
border: 2px solid rgb(138, 255, 193);
position: relative;
overflow: hidden;
}
.instrument::before {
content: "";
position: absolute;
top: 0;
bottom: 0;
left: 0;
width: var(--instrument-progress);
background: rgb(138, 255, 193);
z-index: -1;
opacity: 0.5;
border-radius: 10px;
}
.instrumentLogo {
font-size: xxx-large;
}