715 lines
25 KiB
JavaScript
715 lines
25 KiB
JavaScript
|
Vue.component("sand", {
|
||
|
props: ["layer", "data"],
|
||
|
template: `
|
||
|
<div class="chipping-container">
|
||
|
<div v-for="i in 100" class="chipping">
|
||
|
<div class="chipping-fill instant"
|
||
|
v-bind:style="{ height: percentChipped.sub((i - 1) * 100).clamp(0, 100).div(10).floor().times(10).toNumber() + '%' }"></div>
|
||
|
<div class="chipping-fill instant"
|
||
|
v-bind:style="{ float: 'left', height: '10%', width: percentChipped.sub((i - 1) * 100).clamp(0, 100).sub(percentChipped.sub((i - 1) * 100).clamp(0, 100).div(10).floor().times(10)).times(10).toNumber() + '%' }"></div>
|
||
|
</div>
|
||
|
</div>
|
||
|
`,
|
||
|
computed: {
|
||
|
percentChipped: () => new Decimal(1).sub(player.sands.shrunkAmount.div(nextStoneCost())).times(10000)
|
||
|
}
|
||
|
});
|
||
|
|
||
|
/*
|
||
|
Cannot use this class because the animations don't reset properly, and seem to be calcualting the duration or delays incorrectly.
|
||
|
For now it seems easier to just keep it as a display-text. I don't think it's actually that non-performant.
|
||
|
|
||
|
Vue.component("hourglass", {
|
||
|
props: ["layer", "data"],
|
||
|
template: `<div>
|
||
|
<div>{{ formatWhole(totalGrains.sub(grainsFallen)) }}</div>
|
||
|
<div v-bind:style="userStyle">
|
||
|
<div class="hourglass"></div>
|
||
|
</div>
|
||
|
<div>{{ formatWhole(grainsFallen) }}</div>
|
||
|
</div>`,
|
||
|
computed: {
|
||
|
userStyle: () => {
|
||
|
const flipping = player.sands.flipping;
|
||
|
const finished = player.sands.grainsFallen.eq(getTotalGrains());
|
||
|
const fallSpeed = new Decimal(4).div(player.devSpeed || 1).div(getFallSpeed());
|
||
|
const fallMult = getFallMult();
|
||
|
return {
|
||
|
"--fill-duration": (flipping || finished ? 1 : getTotalGrains().div(fallMult).ceil().times(fallSpeed).toNumber() + 0.05) + "s",
|
||
|
"--fill-delay": "-" + (flipping || finished ? .999 : player.sands.grainsFallen.div(fallMult).floor().times(fallSpeed).toNumber()) + "s",
|
||
|
"--fill-state": flipping || finished ? "paused" : "running",
|
||
|
"--flip-duration": new Decimal(5).div(player.devSpeed || 1).div(getFlipSpeed()).toNumber() + 0.05 + "s",
|
||
|
"--flip-state": flipping ? "running" : "paused"
|
||
|
};
|
||
|
},
|
||
|
totalGrains: getTotalGrains,
|
||
|
grainsFallen: () => player.sands.grainsFallen
|
||
|
}
|
||
|
});
|
||
|
*/
|
||
|
|
||
|
function nextStoneCost() {
|
||
|
return new Decimal(10).times(new Decimal(1.05).pow(player.sands.stonesChipped));
|
||
|
}
|
||
|
|
||
|
function getFallSpeed() {
|
||
|
let fallSpeed = new Decimal(1);
|
||
|
fallSpeed = fallSpeed.times(new Decimal(1.1).pow(getJobLevel("sands")));
|
||
|
fallSpeed = fallSpeed.times(buyableEffect("sands", 12));
|
||
|
if (player.sands.chipping && hasUpgrade("sands", 15)) {
|
||
|
if (hasUpgrade("sands", 13)) {
|
||
|
fallSpeed = fallSpeed.times(upgradeEffect("sands", 13).add(1));
|
||
|
} else {
|
||
|
fallSpeed = fallSpeed.times(2);
|
||
|
}
|
||
|
}
|
||
|
if (player.generators.sandsActive && (player.tab === "generators" || player.generators.timeLoopActive)) {
|
||
|
fallSpeed = fallSpeed.div(10);
|
||
|
}
|
||
|
return fallSpeed;
|
||
|
}
|
||
|
|
||
|
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 && (player.tab === "generators" || player.generators.timeLoopActive)) {
|
||
|
flipSpeed = flipSpeed.div(10);
|
||
|
}
|
||
|
return flipSpeed;
|
||
|
}
|
||
|
|
||
|
function getTotalGrains() {
|
||
|
let grains = new Decimal(player.sands.stonesChipped);
|
||
|
grains = grains.times(buyableEffect("sands", 14));
|
||
|
grains = grains.times(buyableEffect("sands", 24));
|
||
|
grains = grains.sub(player.sands.spentGrains);
|
||
|
return grains.max(0);
|
||
|
}
|
||
|
|
||
|
function getFallMult() {
|
||
|
let fallAmount = new Decimal(1);
|
||
|
fallAmount = fallAmount.times(buyableEffect("sands", 13));
|
||
|
return fallAmount;
|
||
|
}
|
||
|
|
||
|
function getPotentiaMult() {
|
||
|
let gain = new Decimal(1);
|
||
|
gain = gain.times(buyableEffect("sands", 23));
|
||
|
if (hasUpgrade("sands", 14)) {
|
||
|
gain = gain.times(upgradeEffect("sands", 14));
|
||
|
}
|
||
|
if (player.sands.chipping && hasUpgrade("sands", 25)) {
|
||
|
if (hasUpgrade("sands", 13)) {
|
||
|
gain = gain.times(upgradeEffect("sands", 13).add(1));
|
||
|
} else {
|
||
|
gain = gain.times(2);
|
||
|
}
|
||
|
}
|
||
|
gain = gain.times(layers.generators.clickables.sands.effect());
|
||
|
if (player.sands.selectedLens === "potentia") {
|
||
|
gain = gain.times(buyableEffect("sands", "glass"));
|
||
|
}
|
||
|
gain = gain.times(ritualEffect("gain"));
|
||
|
if (player.generators.sandsActive && (player.tab === "generators" || player.generators.timeLoopActive)) {
|
||
|
gain = gain.sqrt();
|
||
|
}
|
||
|
return gain;
|
||
|
}
|
||
|
|
||
|
addLayer("sands", {
|
||
|
name: "sands",
|
||
|
resource: "potentia",
|
||
|
image: "images/pexels-photo-1095601.jpeg",
|
||
|
color: sandsColor,
|
||
|
jobName: "Experiments with time",
|
||
|
showJobDelay: 0.75,
|
||
|
layerShown: () => hasMilestone("study", 5),
|
||
|
startData() {
|
||
|
return {
|
||
|
unlocked: true,
|
||
|
points: new Decimal(0),
|
||
|
xp: new Decimal(0),
|
||
|
lastLevel: new Decimal(0),
|
||
|
timeLoopActive: false,
|
||
|
grainsFallen: new Decimal(0),
|
||
|
shrunkAmount: new Decimal(0),
|
||
|
chipping: false,
|
||
|
flipping: false,
|
||
|
stonesChipped: new Decimal(0),
|
||
|
fallTime: new Decimal(0),
|
||
|
flipTime: new Decimal(0),
|
||
|
lensLevel: new Decimal(0),
|
||
|
selectedLens: "chip",
|
||
|
spentGrains: new Decimal(0)
|
||
|
};
|
||
|
},
|
||
|
tabFormat: {
|
||
|
"Main": {
|
||
|
content: () => {
|
||
|
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";
|
||
|
}
|
||
|
if (!hasMilestone("sands", 1)) {
|
||
|
return "Discover new ways to experiment at level 4";
|
||
|
}
|
||
|
if (!hasMilestone("sands", 3)) {
|
||
|
return "Discover new ways to experiment at level 6";
|
||
|
}
|
||
|
if (!hasMilestone("sands", 4)) {
|
||
|
return "Discover new ways to experiment at level 8";
|
||
|
}
|
||
|
return "";
|
||
|
})()],
|
||
|
"blank",
|
||
|
["sticky", ["80px", ["column", [
|
||
|
["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 || 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 || 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)]
|
||
|
]]]],
|
||
|
"blank",
|
||
|
["clickable", "flip"],
|
||
|
"blank",
|
||
|
"blank",
|
||
|
["display-text", `Zoom Level: 1 / ${format(nextStoneCost().div(10))}x`],
|
||
|
"blank",
|
||
|
"sand",
|
||
|
"blank",
|
||
|
["clickable", "chip"],
|
||
|
"blank",
|
||
|
"blank",
|
||
|
["milestones-filtered", [2, 5, 6]]
|
||
|
];
|
||
|
}
|
||
|
},
|
||
|
"Upgrades": {
|
||
|
content: () => [
|
||
|
"main-display",
|
||
|
"blank",
|
||
|
["display-text", (() => {
|
||
|
if (!hasMilestone("sands", 0)) {
|
||
|
return "Discover new ways to experiment at level 2";
|
||
|
}
|
||
|
if (!hasMilestone("sands", 1)) {
|
||
|
return "Discover new ways to experiment at level 4";
|
||
|
}
|
||
|
if (!hasMilestone("sands", 3)) {
|
||
|
return "Discover new ways to experiment at level 6";
|
||
|
}
|
||
|
if (!hasMilestone("sands", 4)) {
|
||
|
return "Discover new ways to experiment at level 8";
|
||
|
}
|
||
|
return "";
|
||
|
})()],
|
||
|
"blank",
|
||
|
["sticky", ["80px", ["column", [
|
||
|
["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 || 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 || 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)]
|
||
|
]]]],
|
||
|
"blank",
|
||
|
["clickable", "flip"],
|
||
|
"blank",
|
||
|
"blank",
|
||
|
"buyables",
|
||
|
"blank",
|
||
|
"upgrades"
|
||
|
],
|
||
|
unlocked: () => hasMilestone("sands", 0),
|
||
|
shouldNotify: () => Object.values(tmp.sands.upgrades).some(upgrade => upgrade.unlocked && upgrade.canAfford) || Object.values(tmp.sands.buyables).some(buyable => buyable.id !== "glass" && buyable.unlocked && buyable.canAfford)
|
||
|
},
|
||
|
"Glass": {
|
||
|
content: () => [
|
||
|
"main-display",
|
||
|
"blank",
|
||
|
["buyable", "glass"],
|
||
|
"blank",
|
||
|
["row", [
|
||
|
["clickable", "redLens"],
|
||
|
"blank",
|
||
|
["clickable", "greenLens"],
|
||
|
"blank",
|
||
|
["clickable", "blueLens"]
|
||
|
]]
|
||
|
],
|
||
|
unlocked: () => hasMilestone("generators", 2),
|
||
|
shouldNotify: () => tmp.sands.buyables.glass.unlocked && tmp.sands.buyables.glass.canAfford
|
||
|
}
|
||
|
},
|
||
|
update(diff) {
|
||
|
if (player.tab === this.layer || player[this.layer].timeLoopActive) {
|
||
|
let shrinkGain = new Decimal(0);
|
||
|
if (hasUpgrade("sands", 11)) {
|
||
|
shrinkGain = shrinkGain.add(.1);
|
||
|
}
|
||
|
if (hasUpgrade("sands", 12)) {
|
||
|
shrinkGain = shrinkGain.add(.2);
|
||
|
}
|
||
|
if (hasUpgrade("sands", 21)) {
|
||
|
shrinkGain = shrinkGain.add(.3);
|
||
|
}
|
||
|
if (hasUpgrade("sands", 22)) {
|
||
|
shrinkGain = shrinkGain.add(.4);
|
||
|
}
|
||
|
if (player[this.layer].chipping) {
|
||
|
if (hasUpgrade("sands", 13)) {
|
||
|
shrinkGain = shrinkGain.add(upgradeEffect("sands", 13));
|
||
|
} else {
|
||
|
shrinkGain = shrinkGain.add(1);
|
||
|
}
|
||
|
}
|
||
|
if (shrinkGain.gt(0)) {
|
||
|
shrinkGain = shrinkGain.times(diff);
|
||
|
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.sands.selectedLens === "chip") {
|
||
|
shrinkGain = shrinkGain.times(buyableEffect("sands", "glass"));
|
||
|
}
|
||
|
if (player.generators.sandsActive && (player.tab === "generators" || player.generators.timeLoopActive)) {
|
||
|
shrinkGain = shrinkGain.div(10);
|
||
|
}
|
||
|
player[this.layer].shrunkAmount = player[this.layer].shrunkAmount.add(shrinkGain);
|
||
|
}
|
||
|
|
||
|
// https://gameanalytics.com/blog/idle-game-mathematics/
|
||
|
// b = 100
|
||
|
// r = 1.1
|
||
|
let grainsGain = player[this.layer].shrunkAmount.times(new Decimal(1.1).sub(1)).div(nextStoneCost()).add(1).log(1.1).floor();
|
||
|
if (grainsGain.gt(0)) {
|
||
|
player[this.layer].shrunkAmount = player[this.layer].shrunkAmount.sub(nextStoneCost().times(new Decimal(1.1).pow(grainsGain).sub(1)).div(new Decimal(1.1).sub(1)));
|
||
|
player[this.layer].stonesChipped = player[this.layer].stonesChipped.add(grainsGain);
|
||
|
}
|
||
|
|
||
|
if (player[this.layer].flipping) {
|
||
|
player[this.layer].fallTime = new Decimal(0);
|
||
|
player[this.layer].flipTime = player[this.layer].flipTime.add(getFlipSpeed().times(diff));
|
||
|
const flipDuration = new Decimal(5);
|
||
|
if (player[this.layer].flipTime.gt(flipDuration)) {
|
||
|
player[this.layer].flipping = false;
|
||
|
player[this.layer].flipTime = new Decimal(0);
|
||
|
player[this.layer].grainsFallen = new Decimal(0);
|
||
|
}
|
||
|
} else {
|
||
|
player[this.layer].flipTime = new Decimal(0);
|
||
|
if (player[this.layer].grainsFallen.lt(getTotalGrains())) {
|
||
|
player[this.layer].fallTime = player[this.layer].fallTime.add(getFallSpeed().times(diff));
|
||
|
const fallDuration = new Decimal(4);
|
||
|
const fallenGrains = player[this.layer].fallTime.div(fallDuration).floor().times(getFallMult()).clampMax(getTotalGrains().sub(player[this.layer].grainsFallen));
|
||
|
if (fallenGrains.gt(0)) {
|
||
|
addPoints(this.layer, fallenGrains.times(getPotentiaMult()));
|
||
|
player[this.layer].grainsFallen = player[this.layer].grainsFallen.add(fallenGrains);
|
||
|
if (fallenGrains.eq(getTotalGrains())) {
|
||
|
player[this.layer].fallTime = new Decimal(0);
|
||
|
} else {
|
||
|
player[this.layer].fallTime = player[this.layer].fallTime.sub(fallenGrains.div(getFallMult()).times(fallDuration));
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
player[this.layer].fallTime = new Decimal(0);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
onAddPoints(gain) {
|
||
|
let xpGain = gain;
|
||
|
if (hasUpgrade("generators", 13)) {
|
||
|
xpGain = xpGain.times(layers.generators.clickables[this.layer].effect());
|
||
|
}
|
||
|
if (player.sands.selectedLens === "xp") {
|
||
|
xpGain = xpGain.times(Decimal.pow(buyableEffect("sands", "glass"), 2));
|
||
|
}
|
||
|
xpGain = xpGain.times(ritualEffect("globalXp"));
|
||
|
player[this.layer].xp = player[this.layer].xp.add(xpGain);
|
||
|
checkJobXP(this.layer);
|
||
|
},
|
||
|
milestones: {
|
||
|
0: {
|
||
|
requirementDescription: "Level 2",
|
||
|
done: () => player.sands.xp.gte(10)
|
||
|
},
|
||
|
1: {
|
||
|
requirementDescription: "Level 4",
|
||
|
done: () => player.sands.xp.gte(1e3)
|
||
|
},
|
||
|
2: {
|
||
|
title: "I don't even know what I'm doing.",
|
||
|
requirementDescription: "Level 5",
|
||
|
"effectDescription": "Unlock a new time slot",
|
||
|
done: () => player.sands.xp.gte(1e4),
|
||
|
onComplete: () => {
|
||
|
player.timeSlots = player.timeSlots.add(1);
|
||
|
}
|
||
|
},
|
||
|
3: {
|
||
|
requirementDescription: "Level 6",
|
||
|
done: () => player.sands.xp.gte(1e5)
|
||
|
},
|
||
|
4: {
|
||
|
requirementDescription: "Level 8",
|
||
|
done: () => player.sands.xp.gte(1e7)
|
||
|
},
|
||
|
5: {
|
||
|
title: "I mean, this stuff is way too advanced for me.",
|
||
|
requirementDescription: "Level 10",
|
||
|
"effectDescription": "Unlock rituals job",
|
||
|
done: () => player.sands.xp.gte(1e9),
|
||
|
unlocked: () => hasMilestone("sands", 2)
|
||
|
},
|
||
|
6: {
|
||
|
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) && player.chapter > 2,
|
||
|
unlocked: () => hasMilestone("sands", 5) && player.chapter > 2
|
||
|
}
|
||
|
},
|
||
|
clickables: {
|
||
|
chip: {
|
||
|
title: "Keep Moving Forward<br/>",
|
||
|
display: "Hover over this to chip away at the stone until it's the size of a grain of sand.",
|
||
|
touchstart: () => {
|
||
|
player.sands.chipping = true;
|
||
|
},
|
||
|
touchend: () => {
|
||
|
player.sands.chipping = false;
|
||
|
}
|
||
|
},
|
||
|
flip: {
|
||
|
title: "But he doesn't give up!<br/>",
|
||
|
display: "Flip the hourglass",
|
||
|
canClick: () => player.sands.grainsFallen.gt(0) && !player.sands.flipping,
|
||
|
onClick: () => {
|
||
|
player.sands.flipping = true;
|
||
|
}
|
||
|
},
|
||
|
redLens: {
|
||
|
title: "Red Lens<br/>",
|
||
|
display() {
|
||
|
return `Focus on chipping speed to improve it by x${formatWhole(layers.sands.buyables.glass.effect())}`;
|
||
|
},
|
||
|
style: {
|
||
|
borderColor: "red"
|
||
|
},
|
||
|
canClick: () => player.sands.selectedLens !== "chip",
|
||
|
onClick: () => player.sands.selectedLens = "chip"
|
||
|
},
|
||
|
greenLens: {
|
||
|
title: "Green Lens<br/>",
|
||
|
display() {
|
||
|
return `Focus on potentia gain to improve it by x${formatWhole(layers.sands.buyables.glass.effect())}`;
|
||
|
},
|
||
|
style: {
|
||
|
borderColor: "green"
|
||
|
},
|
||
|
canClick: () => player.sands.selectedLens !== "potentia",
|
||
|
onClick: () => player.sands.selectedLens = "potentia"
|
||
|
},
|
||
|
blueLens: {
|
||
|
title: "Blue Lens<br/>",
|
||
|
display() {
|
||
|
return `Focus on xp gain to improve it by x${formatWhole(Decimal.pow(layers.sands.buyables.glass.effect(), 2))}`;
|
||
|
},
|
||
|
style: {
|
||
|
borderColor: "blue"
|
||
|
},
|
||
|
canClick: () => player.sands.selectedLens !== "xp",
|
||
|
onClick: () => player.sands.selectedLens = "xp"
|
||
|
}
|
||
|
},
|
||
|
buyables: {
|
||
|
rows: 2,
|
||
|
cols: 4,
|
||
|
glass: {
|
||
|
title: "His insurance won't pay for contacts.<br/>",
|
||
|
layer: "sands",
|
||
|
id: "glass",
|
||
|
display() {
|
||
|
return `Melt sand into glass. Doubles the effectiveness of lenses. Requires 110% of the cost to buy.<br/><br/>Currently: ${formatWhole(this.effect())}<br/><br/>Cost: ${format(this.cost())} grains of sand`;
|
||
|
},
|
||
|
cost(x) {
|
||
|
const amount = x || getBuyableAmount(this.layer, this.id);
|
||
|
return new Decimal(1e6).times(Decimal.pow(10, amount));
|
||
|
},
|
||
|
effect() {
|
||
|
return Decimal.pow(2, getBuyableAmount(this.layer, this.id).add(1));
|
||
|
},
|
||
|
canAfford() {
|
||
|
return getTotalGrains().gte(this.cost().times(1.1));
|
||
|
},
|
||
|
buy() {
|
||
|
setBuyableAmount(this.layer, this.id, getBuyableAmount(this.layer, this.id).add(1));
|
||
|
player.sands.spentGrains = new Decimal("1".repeat(getBuyableAmount("sands", "glass").toNumber()) + "000000");
|
||
|
},
|
||
|
unlocked: true
|
||
|
},
|
||
|
11: {
|
||
|
title: "It's my dad's motto.<br/>",
|
||
|
display() {
|
||
|
return `Additively increases chipping speed by 25%<br/><br/>Currently: x${format(this.effect())}<br/><br/>Cost: ${format(this.cost())} potentia`;
|
||
|
},
|
||
|
cost(x) {
|
||
|
const amount = x || getBuyableAmount(this.layer, this.id);
|
||
|
return new Decimal(10).times(new Decimal(2).pow(amount));
|
||
|
},
|
||
|
effect() {
|
||
|
return new Decimal(.25).times(getBuyableAmount(this.layer, this.id)).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));
|
||
|
},
|
||
|
unlocked: () => hasMilestone("sands", 0)
|
||
|
},
|
||
|
12: {
|
||
|
title: "That's strange. She usually takes the Harley.<br/>",
|
||
|
display() {
|
||
|
return `Additively increases how quickly grains of sand fall by 100%<br/><br/>Currently: x${format(this.effect())}<br/><br/>Cost: ${format(this.cost())} potentia`;
|
||
|
},
|
||
|
cost(x) {
|
||
|
const amount = x || getBuyableAmount(this.layer, this.id);
|
||
|
return new Decimal(2).pow(Decimal.add(amount, 3));
|
||
|
},
|
||
|
effect() {
|
||
|
return new Decimal(1).times(getBuyableAmount(this.layer, this.id)).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));
|
||
|
},
|
||
|
unlocked: () => hasMilestone("sands", 0)
|
||
|
},
|
||
|
13: {
|
||
|
title: "You're smart, you fix it!<br/>",
|
||
|
display() {
|
||
|
return `Additively increases how many grains of sand can fall through the hourglass at once by 1<br/><br/>Currently: x${format(this.effect())}<br/><br/>Cost: ${format(this.cost())} potentia`;
|
||
|
},
|
||
|
cost(x) {
|
||
|
const amount = x || getBuyableAmount(this.layer, this.id);
|
||
|
return new Decimal(1.5).times(new Decimal(4).pow(Decimal.add(amount, 2)));
|
||
|
},
|
||
|
effect() {
|
||
|
return getBuyableAmount(this.layer, this.id).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));
|
||
|
},
|
||
|
unlocked: () => hasMilestone("sands", 0)
|
||
|
},
|
||
|
14: {
|
||
|
title: "You want to know what I think about this?<br/>",
|
||
|
display() {
|
||
|
return `Additively and retroactively increases how many grains of sand you gather from each completely chipped stone by 1<br/><br/>Currently: x${format(this.effect())}<br/><br/>Cost: ${format(this.cost())} potentia`;
|
||
|
},
|
||
|
cost(x) {
|
||
|
const amount = x || getBuyableAmount(this.layer, this.id);
|
||
|
return new Decimal(25).times(new Decimal(6).pow(amount));
|
||
|
},
|
||
|
effect() {
|
||
|
return getBuyableAmount(this.layer, this.id).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));
|
||
|
},
|
||
|
unlocked: () => hasMilestone("sands", 0)
|
||
|
},
|
||
|
21: {
|
||
|
title: "I'm ignoring you for time reasons.<br/>",
|
||
|
display() {
|
||
|
return `Multiplicatively increases chipping speed by 50%<br/><br/>Currently: x${format(this.effect())}<br/><br/>Cost: ${format(this.cost())} potentia`;
|
||
|
},
|
||
|
cost(x) {
|
||
|
const amount = x || getBuyableAmount(this.layer, this.id);
|
||
|
return new Decimal(2).times(new Decimal(5).pow(Decimal.add(amount, 1)));
|
||
|
},
|
||
|
effect() {
|
||
|
return new Decimal(1.5).pow(getBuyableAmount(this.layer, this.id));
|
||
|
},
|
||
|
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));
|
||
|
},
|
||
|
unlocked: () => hasMilestone("sands", 3)
|
||
|
},
|
||
|
22: {
|
||
|
title: "From failure, you learn; from success not so much.<br/>",
|
||
|
display() {
|
||
|
return `Multiplicatively increases how quickly the hourglass flips by 20%<br/><br/>Currently: x${format(this.effect())}<br/><br/>Cost: ${format(this.cost())} potentia`;
|
||
|
},
|
||
|
cost(x) {
|
||
|
const amount = x || getBuyableAmount(this.layer, this.id);
|
||
|
return new Decimal(3).times(new Decimal(2).pow(Decimal.add(amount, 1)));
|
||
|
},
|
||
|
effect() {
|
||
|
return new Decimal(1.2).pow(getBuyableAmount(this.layer, this.id));
|
||
|
},
|
||
|
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));
|
||
|
},
|
||
|
unlocked: () => hasMilestone("sands", 3)
|
||
|
},
|
||
|
23: {
|
||
|
title: "To...the future!<br/>",
|
||
|
display() {
|
||
|
return `Additively increases how much potentia you collect from each grain that falls by 1<br/><br/>Currently: x${format(this.effect())}<br/><br/>Cost: ${format(this.cost())} potentia`;
|
||
|
},
|
||
|
cost(x) {
|
||
|
const amount = x || getBuyableAmount(this.layer, this.id);
|
||
|
return new Decimal(50).times(new Decimal(2).pow(amount));
|
||
|
},
|
||
|
effect() {
|
||
|
return getBuyableAmount(this.layer, this.id).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));
|
||
|
},
|
||
|
unlocked: () => hasMilestone("sands", 3)
|
||
|
},
|
||
|
24: {
|
||
|
title: "Or, what's left of it.<br/>",
|
||
|
display() {
|
||
|
return `Multiplicatively and retroactively increases how many grains of sand you gather 2x<br/><br/>Currently: x${format(this.effect())}<br/><br/>Cost: ${format(this.cost())} potentia`;
|
||
|
},
|
||
|
cost(x) {
|
||
|
const amount = x || getBuyableAmount(this.layer, this.id);
|
||
|
if (hasUpgrade("sands", 24)) {
|
||
|
return new Decimal(75).times(new Decimal(8).pow(amount));
|
||
|
}
|
||
|
return new Decimal(75).times(new Decimal(10).pow(amount));
|
||
|
},
|
||
|
effect() {
|
||
|
return new Decimal(2).pow(getBuyableAmount(this.layer, this.id));
|
||
|
},
|
||
|
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));
|
||
|
},
|
||
|
unlocked: () => hasMilestone("sands", 3)
|
||
|
}
|
||
|
},
|
||
|
upgrades: {
|
||
|
rows: 2,
|
||
|
cols: 5,
|
||
|
11: {
|
||
|
title: "I have a big head,<br>",
|
||
|
description: "Automatically chip the stone at +10% efficiency",
|
||
|
cost: new Decimal(200),
|
||
|
unlocked: () => hasMilestone("sands", 1)
|
||
|
},
|
||
|
12: {
|
||
|
title: "and little arms!<br>",
|
||
|
description: "Automatically chip the stone at +20% efficiency",
|
||
|
cost: new Decimal(400),
|
||
|
unlocked: () => hasMilestone("sands", 1)
|
||
|
},
|
||
|
13: {
|
||
|
title: "I'm not sure how well<br>",
|
||
|
description: "Multiply <b>\"Keep Moving Forward\"</b>'s effect by this job's level<br/>",
|
||
|
cost: new Decimal(800),
|
||
|
unlocked: () => hasMilestone("sands", 1),
|
||
|
effect: () => getJobLevel("sands"),
|
||
|
effectDisplay() {
|
||
|
return `x${format(this.effect())}`;
|
||
|
}
|
||
|
},
|
||
|
14: {
|
||
|
title: "this plan was thought through.<br>",
|
||
|
description: "Potentia gain is increased based on total number of grains<br/>",
|
||
|
cost: new Decimal(1600),
|
||
|
unlocked: () => hasMilestone("sands", 1),
|
||
|
effect: () => getTotalGrains().pow(.25).add(1),
|
||
|
effectDisplay() {
|
||
|
return `x${format(this.effect())}`;
|
||
|
}
|
||
|
},
|
||
|
15: {
|
||
|
title: "Master?<br>",
|
||
|
description: "<b>\"Keep Moving Forward\"</b> also speeds up grains falling through the hourglass<br/>",
|
||
|
cost: new Decimal(6400),
|
||
|
unlocked: () => hasMilestone("sands", 1)
|
||
|
},
|
||
|
21: {
|
||
|
title: "I'll take two!<br>",
|
||
|
description: "Automatically chip the stone at +30% efficiency",
|
||
|
cost: new Decimal(1e6),
|
||
|
unlocked: () => hasMilestone("sands", 4)
|
||
|
},
|
||
|
22: {
|
||
|
title: "Bake them cookies, Lucille!<br>",
|
||
|
description: "Automatically chip the stone at +40% efficiency",
|
||
|
cost: new Decimal(2e6),
|
||
|
unlocked: () => hasMilestone("sands", 4)
|
||
|
},
|
||
|
23: {
|
||
|
title: "You are now under my control<br>",
|
||
|
description: "Flip speed affects fall speed at 5% efficiency<br/>",
|
||
|
cost: new Decimal(5e6),
|
||
|
unlocked: () => hasMilestone("sands", 4),
|
||
|
effect: () => getFlipSpeed().sub(1).div(20).add(1),
|
||
|
effectDisplay() {
|
||
|
return `x${format(this.effect())}`;
|
||
|
}
|
||
|
},
|
||
|
24: {
|
||
|
title: "Stop laughing<br>",
|
||
|
description: "Reduce the cost scaling of <b>\"Or, what's left of it.\"</b><br/>",
|
||
|
cost: new Decimal(2.5e7),
|
||
|
unlocked: () => hasMilestone("sands", 4)
|
||
|
},
|
||
|
25: {
|
||
|
title: "Excellent<br>",
|
||
|
description: "<b>\"Keep Moving Forward\"</b> also increases potentia gain<br/>",
|
||
|
cost: new Decimal(1e8),
|
||
|
unlocked: () => hasMilestone("sands", 4)
|
||
|
}
|
||
|
},
|
||
|
bars: {
|
||
|
job: getJobProgressBar("sands", sandsColor)
|
||
|
}
|
||
|
});
|