Merge remote-tracking branch 'origin/main' into days-15-16

This commit is contained in:
Chunkybanana 2022-12-15 00:26:12 +00:00
commit 21ad38c1df
16 changed files with 1046 additions and 232 deletions

View file

@ -27,6 +27,7 @@ import { WithRequired } from "util/common";
import { render, renderGrid, renderRow } from "util/vue"; import { render, renderGrid, renderRow } from "util/vue";
import { computed, ComputedRef, ref, unref } from "vue"; import { computed, ComputedRef, ref, unref } from "vue";
import dyes from "./dyes"; import dyes from "./dyes";
import { ElfBuyable } from "./elves";
import management from "./management"; import management from "./management";
import paper from "./paper"; import paper from "./paper";
import plastic from "./plastic"; import plastic from "./plastic";
@ -34,7 +35,7 @@ import trees from "./trees";
import workshop from "./workshop"; import workshop from "./workshop";
import wrappingPaper from "./wrapping-paper"; import wrappingPaper from "./wrapping-paper";
export type BoxesBuyable = GenericBuyable & { export type BoxesBuyable = ElfBuyable & {
resource: Resource; resource: Resource;
freeLevels: ComputedRef<DecimalSource>; freeLevels: ComputedRef<DecimalSource>;
totalAmount: ComputedRef<Decimal>; totalAmount: ComputedRef<Decimal>;
@ -179,6 +180,12 @@ const layer = createLayer(id, function (this: BaseLayer) {
display: { display: {
title: "Carry dye in boxes", title: "Carry dye in boxes",
description: "Double all dye gain" description: "Double all dye gain"
},
onPurchase() {
(["red", "yellow", "blue", "orange", "green", "purple"] as const).forEach(dyeColor => {
dyes.dyes[dyeColor].amount.value = 0;
dyes.dyes[dyeColor].buyable.amount.value = 0;
});
} }
})) as GenericUpgrade; })) as GenericUpgrade;
const xpUpgrade = createUpgrade(() => ({ const xpUpgrade = createUpgrade(() => ({
@ -225,6 +232,19 @@ const layer = createLayer(id, function (this: BaseLayer) {
.div(dyes.boosts.orange2.value) .div(dyes.boosts.orange2.value)
.div(wrappingPaper.boosts.ocean1.value); .div(wrappingPaper.boosts.ocean1.value);
}, },
inverseCost(x: DecimalSource) {
let scaling = 3;
if (management.elfTraining.boxElfTraining.milestones[2].earned.value) {
scaling--;
}
let v = Decimal.mul(x, wrappingPaper.boosts.ocean1.value)
.mul(dyes.boosts.orange2.value)
.div(100).log(scaling);
v = v.div(Decimal.pow(0.95, paper.books.boxBook.totalAmount.value));
return Decimal.isNaN(v) ? Decimal.dZero : v.floor().max(0);
},
visibility: () => showIf(logsUpgrade.bought.value), visibility: () => showIf(logsUpgrade.bought.value),
freeLevels: computed(() => freeLevels: computed(() =>
management.elfTraining.boxElfTraining.milestones[0].earned.value management.elfTraining.boxElfTraining.milestones[0].earned.value
@ -269,6 +289,18 @@ const layer = createLayer(id, function (this: BaseLayer) {
} }
return Decimal.pow(scaling, v).times(1000).div(dyes.boosts.orange2.value); return Decimal.pow(scaling, v).times(1000).div(dyes.boosts.orange2.value);
}, },
inverseCost(x: DecimalSource) {
let scaling = 5;
if (management.elfTraining.boxElfTraining.milestones[2].earned.value) {
scaling--;
}
let v = Decimal.mul(x, dyes.boosts.orange2.value)
.div(1000).log(scaling);
v = v.div(Decimal.pow(0.95, paper.books.boxBook.totalAmount.value));
return Decimal.isNaN(v) ? Decimal.dZero : v.floor().max(0);
},
visibility: () => showIf(ashUpgrade.bought.value), visibility: () => showIf(ashUpgrade.bought.value),
freeLevels: computed(() => freeLevels: computed(() =>
management.elfTraining.boxElfTraining.milestones[0].earned.value management.elfTraining.boxElfTraining.milestones[0].earned.value
@ -313,6 +345,18 @@ const layer = createLayer(id, function (this: BaseLayer) {
} }
return Decimal.pow(scaling, v).times(1000).div(dyes.boosts.orange2.value); return Decimal.pow(scaling, v).times(1000).div(dyes.boosts.orange2.value);
}, },
inverseCost(x: DecimalSource) {
let scaling = 7;
if (management.elfTraining.boxElfTraining.milestones[2].earned.value) {
scaling--;
}
let v = Decimal.mul(x, dyes.boosts.orange2.value)
.div(1000).log(scaling);
v = v.div(Decimal.pow(0.95, paper.books.boxBook.totalAmount.value));
return Decimal.isNaN(v) ? Decimal.dZero : v.floor().max(0);
},
visibility: () => showIf(coalUpgrade.bought.value), visibility: () => showIf(coalUpgrade.bought.value),
freeLevels: computed(() => freeLevels: computed(() =>
management.elfTraining.boxElfTraining.milestones[0].earned.value management.elfTraining.boxElfTraining.milestones[0].earned.value
@ -356,7 +400,23 @@ const layer = createLayer(id, function (this: BaseLayer) {
if (management.elfTraining.boxElfTraining.milestones[2].earned.value) { if (management.elfTraining.boxElfTraining.milestones[2].earned.value) {
scaling--; scaling--;
} }
return Decimal.pow(scaling, v).times(1e25).div(dyes.boosts.orange2.value).div(wrappingPaper.boosts.ocean1.value); return Decimal.pow(scaling, v)
.times(1e25)
.div(dyes.boosts.orange2.value)
.div(wrappingPaper.boosts.ocean1.value);
},
inverseCost(x: DecimalSource) {
let scaling = 10;
if (management.elfTraining.boxElfTraining.milestones[2].earned.value) {
scaling--;
}
let v = Decimal.mul(x, wrappingPaper.boosts.ocean1.value)
.mul(dyes.boosts.orange2.value)
.div(1e25).log(scaling);
v = v.div(Decimal.pow(0.95, paper.books.boxBook.totalAmount.value));
return Decimal.isNaN(v) ? Decimal.dZero : v.floor().max(0);
}, },
visibility: () => showIf(management.elfTraining.boxElfTraining.milestones[3].earned.value), visibility: () => showIf(management.elfTraining.boxElfTraining.milestones[3].earned.value),
freeLevels: computed(() => freeLevels: computed(() =>
@ -402,6 +462,18 @@ const layer = createLayer(id, function (this: BaseLayer) {
} }
return Decimal.pow(scaling, v).times(1e28).div(dyes.boosts.orange2.value); return Decimal.pow(scaling, v).times(1e28).div(dyes.boosts.orange2.value);
}, },
inverseCost(x: DecimalSource) {
let scaling = 15;
if (management.elfTraining.boxElfTraining.milestones[2].earned.value) {
scaling--;
}
let v = Decimal.mul(x, dyes.boosts.orange2.value)
.div(1e28).log(scaling);
v = v.div(Decimal.pow(0.95, paper.books.boxBook.totalAmount.value));
return Decimal.isNaN(v) ? Decimal.dZero : v.floor().max(0);
},
visibility: () => showIf(management.elfTraining.boxElfTraining.milestones[3].earned.value), visibility: () => showIf(management.elfTraining.boxElfTraining.milestones[3].earned.value),
freeLevels: computed(() => freeLevels: computed(() =>
management.elfTraining.boxElfTraining.milestones[0].earned.value management.elfTraining.boxElfTraining.milestones[0].earned.value
@ -444,7 +516,19 @@ const layer = createLayer(id, function (this: BaseLayer) {
if (management.elfTraining.boxElfTraining.milestones[2].earned.value) { if (management.elfTraining.boxElfTraining.milestones[2].earned.value) {
scaling--; scaling--;
} }
return Decimal.pow(scaling, v).times(1000).div(dyes.boosts.orange2.value); return Decimal.pow(scaling, v).times(1e31).div(dyes.boosts.orange2.value);
},
inverseCost(x: DecimalSource) {
let scaling = 20;
if (management.elfTraining.boxElfTraining.milestones[2].earned.value) {
scaling--;
}
let v = Decimal.mul(x, dyes.boosts.orange2.value)
.div(1e31).log(scaling);
v = v.div(Decimal.pow(0.95, paper.books.boxBook.totalAmount.value));
return Decimal.isNaN(v) ? Decimal.dZero : v.floor().max(0);
}, },
visibility: () => showIf(management.elfTraining.boxElfTraining.milestones[3].earned.value), visibility: () => showIf(management.elfTraining.boxElfTraining.milestones[3].earned.value),
freeLevels: computed(() => freeLevels: computed(() =>

View file

@ -28,7 +28,9 @@ import { formatWhole } from "util/break_eternity";
import { Direction } from "util/common"; import { Direction } from "util/common";
import { render, renderCol, renderRow } from "util/vue"; import { render, renderCol, renderRow } from "util/vue";
import { computed, ref } from "vue"; import { computed, ref } from "vue";
import boxes from "./boxes";
import dyes from "./dyes"; import dyes from "./dyes";
import { ElfBuyable } from "./elves";
import management from "./management"; import management from "./management";
import metal from "./metal"; import metal from "./metal";
import paper from "./paper"; import paper from "./paper";
@ -187,11 +189,17 @@ const layer = createLayer(id, function (this: BaseLayer) {
v = Decimal.pow(0.95, paper.books.clothBook.totalAmount.value).times(v); v = Decimal.pow(0.95, paper.books.clothBook.totalAmount.value).times(v);
return Decimal.pow(1.5, v).times(1e14); return Decimal.pow(1.5, v).times(1e14);
}, },
inverseCost(x: DecimalSource) {
let v = Decimal.div(x, 1e14).log(1.5);
v = v.div(Decimal.pow(0.95, paper.books.clothBook.totalAmount.value));
if (Decimal.gte(v, 100)) v = Decimal.mul(v, 100).root(2);
return Decimal.isNaN(v) ? Decimal.dZero : v.floor().max(0);
},
display: { display: {
title: "Build more pens", title: "Build more pens",
description: "Breed +1 sheep at once" description: "Breed +1 sheep at once"
} }
})) as GenericBuyable & { resource: Resource }; })) as ElfBuyable & { resource: Resource };
const betterShears = createBuyable(() => ({ const betterShears = createBuyable(() => ({
resource: metal.metal, resource: metal.metal,
@ -201,11 +209,17 @@ const layer = createLayer(id, function (this: BaseLayer) {
v = Decimal.pow(0.95, paper.books.clothBook.totalAmount.value).times(v); v = Decimal.pow(0.95, paper.books.clothBook.totalAmount.value).times(v);
return Decimal.pow(1.4, v).times(10000); return Decimal.pow(1.4, v).times(10000);
}, },
inverseCost(x: DecimalSource) {
let v = Decimal.div(x, 10000).log(1.4);
v = v.div(Decimal.pow(0.95, paper.books.clothBook.totalAmount.value));
if (Decimal.gte(v, 100)) v = Decimal.mul(v, 100).root(2);
return Decimal.isNaN(v) ? Decimal.dZero : v.floor().max(0);
},
display: { display: {
title: "Make stronger shears", title: "Make stronger shears",
description: "Shear +1 sheep at once" description: "Shear +1 sheep at once"
} }
})) as GenericBuyable & { resource: Resource }; })) as ElfBuyable & { resource: Resource };
const fasterSpinning = createBuyable(() => ({ const fasterSpinning = createBuyable(() => ({
resource: paper.paper, resource: paper.paper,
@ -215,11 +229,17 @@ const layer = createLayer(id, function (this: BaseLayer) {
v = Decimal.pow(0.95, paper.books.clothBook.totalAmount.value).times(v); v = Decimal.pow(0.95, paper.books.clothBook.totalAmount.value).times(v);
return Decimal.pow(1.3, v).times(1000000); return Decimal.pow(1.3, v).times(1000000);
}, },
inverseCost(x: DecimalSource) {
let v = Decimal.div(x, 1000000).log(1.3);
v = v.div(Decimal.pow(0.95, paper.books.clothBook.totalAmount.value));
if (Decimal.gte(v, 100)) v = Decimal.mul(v, 100).root(2);
return Decimal.isNaN(v) ? Decimal.dZero : v.floor().max(0);
},
display: { display: {
title: "Learn how to spin", title: "Learn how to spin",
description: "Spin +1 wool at once" description: "Spin +1 wool at once"
} }
})) as GenericBuyable & { resource: Resource }; })) as ElfBuyable & { resource: Resource };
const treesUpgrade1 = createUpgrade(() => ({ const treesUpgrade1 = createUpgrade(() => ({
resource: noPersist(cloth), resource: noPersist(cloth),
@ -366,6 +386,11 @@ const layer = createLayer(id, function (this: BaseLayer) {
multiplier: 2, multiplier: 2,
description: "1000% Foundation Completed", description: "1000% Foundation Completed",
enabled: workshop.milestones.extraExpansionMilestone5.earned enabled: workshop.milestones.extraExpansionMilestone5.earned
})),
createMultiplicativeModifier(() => ({
multiplier: 2,
description: "Carry cloth in boxes",
enabled: boxes.row3Upgrades.clothUpgrade.bought
})) }))
]); ]);
const computedSheepGain = computed(() => sheepGain.apply(1)); const computedSheepGain = computed(() => sheepGain.apply(1));
@ -401,6 +426,11 @@ const layer = createLayer(id, function (this: BaseLayer) {
multiplier: 2, multiplier: 2,
description: "1000% Foundation Completed", description: "1000% Foundation Completed",
enabled: workshop.milestones.extraExpansionMilestone5.earned enabled: workshop.milestones.extraExpansionMilestone5.earned
})),
createMultiplicativeModifier(() => ({
multiplier: 2,
description: "Carry cloth in boxes",
enabled: boxes.row3Upgrades.clothUpgrade.bought
})) }))
]); ]);
const computedShearingAmount = computed(() => shearingAmount.apply(1)); const computedShearingAmount = computed(() => shearingAmount.apply(1));
@ -436,6 +466,11 @@ const layer = createLayer(id, function (this: BaseLayer) {
multiplier: 2, multiplier: 2,
description: "1000% Foundation Completed", description: "1000% Foundation Completed",
enabled: workshop.milestones.extraExpansionMilestone5.earned enabled: workshop.milestones.extraExpansionMilestone5.earned
})),
createMultiplicativeModifier(() => ({
multiplier: 2,
description: "Carry cloth in boxes",
enabled: boxes.row3Upgrades.clothUpgrade.bought
})) }))
]); ]);
const computedSpinningAmount = computed(() => spinningAmount.apply(1)); const computedSpinningAmount = computed(() => spinningAmount.apply(1));

View file

@ -33,7 +33,7 @@ import { render, renderGrid, renderRow } from "util/vue";
import { computed, ref, unref } from "vue"; import { computed, ref, unref } from "vue";
import boxes from "./boxes"; import boxes from "./boxes";
import cloth from "./cloth"; import cloth from "./cloth";
import elves from "./elves"; import elves, { ElfBuyable } from "./elves";
import metal from "./metal"; import metal from "./metal";
import oil from "./oil"; import oil from "./oil";
import paper from "./paper"; import paper from "./paper";
@ -41,6 +41,7 @@ import trees from "./trees";
import dyes from "./dyes"; import dyes from "./dyes";
import management from "./management"; import management from "./management";
import wrappingPaper from "./wrapping-paper"; import wrappingPaper from "./wrapping-paper";
import plastic from "./plastic";
interface BetterFertilizerUpgOptions { interface BetterFertilizerUpgOptions {
canAfford: () => boolean; canAfford: () => boolean;
@ -102,6 +103,14 @@ const layer = createLayer(id, function (this: BaseLayer) {
v = Decimal.pow(0.95, paper.books.smallFireBook.totalAmount.value).times(v); v = Decimal.pow(0.95, paper.books.smallFireBook.totalAmount.value).times(v);
return v.pow(1.5).times(1e4); return v.pow(1.5).times(1e4);
}, },
inverseCost(x: DecimalSource) {
let v = Decimal.div(x, 1e4).root(1.5);
v = v.div(Decimal.pow(0.95, paper.books.smallFireBook.totalAmount.value));
if (Decimal.gte(v, 10000)) v = Decimal.mul(v, 10000).root(2);
if (Decimal.gte(v, 100)) v = Decimal.mul(v, 100).root(2);
v = v.sub(Decimal.times(buildBonfire.amount.value, unref(buildBonfire.cost!)));
return Decimal.isNaN(v) ? Decimal.dZero : v.floor().max(0);
},
display: jsx(() => ( display: jsx(() => (
<> <>
<h3>Small Fire</h3> <h3>Small Fire</h3>
@ -125,7 +134,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
color: colorText, color: colorText,
width: "160px" width: "160px"
} }
})) as GenericBuyable & { resource: Resource }; })) as ElfBuyable & { resource: Resource };
const { const {
min: minFire, min: minFire,
@ -159,6 +168,9 @@ const layer = createLayer(id, function (this: BaseLayer) {
cost() { cost() {
return Decimal.pow(0.95, paper.books.bonfireBook.totalAmount.value).times(10); return Decimal.pow(0.95, paper.books.bonfireBook.totalAmount.value).times(10);
}, },
inverseCost(x: DecimalSource) {
return Decimal.div(x, Decimal.pow(0.95, paper.books.bonfireBook.totalAmount.value).times(10)).floor();
},
display: jsx(() => ( display: jsx(() => (
<> <>
<h3>Bonfire</h3> <h3>Bonfire</h3>
@ -184,7 +196,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
width: "160px" width: "160px"
}, },
visibility: () => showIf(unlockBonfire.bought.value) visibility: () => showIf(unlockBonfire.bought.value)
})) as GenericBuyable & { resource: Resource }; })) as ElfBuyable & { resource: Resource };
const { const {
min: minBonfire, min: minBonfire,
max: maxBonfire, max: maxBonfire,
@ -219,6 +231,13 @@ const layer = createLayer(id, function (this: BaseLayer) {
v = Decimal.pow(0.95, paper.books.kilnBook.totalAmount.value).times(v); v = Decimal.pow(0.95, paper.books.kilnBook.totalAmount.value).times(v);
return Decimal.pow(1.1, v).times(1e7); return Decimal.pow(1.1, v).times(1e7);
}, },
inverseCost(x: DecimalSource) {
let v = Decimal.div(x, 1e7).log(1.1);
v = v.div(Decimal.pow(0.95, paper.books.kilnBook.totalAmount.value));
if (Decimal.gte(v, 10000)) v = Decimal.mul(v, 10000).root(2);
if (Decimal.gte(v, 100)) v = Decimal.mul(v, 100).root(2);
return Decimal.isNaN(v) ? Decimal.dZero : v.floor().max(0);
},
display: jsx(() => ( display: jsx(() => (
<> <>
<h3>Charcoal Kiln</h3> <h3>Charcoal Kiln</h3>
@ -243,7 +262,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
width: "160px" width: "160px"
}, },
visibility: () => showIf(unlockKiln.bought.value) visibility: () => showIf(unlockKiln.bought.value)
})) as GenericBuyable & { resource: Resource }; })) as ElfBuyable & { resource: Resource };
const { const {
min: minKiln, min: minKiln,
max: maxKiln, max: maxKiln,
@ -275,8 +294,24 @@ const layer = createLayer(id, function (this: BaseLayer) {
if (management.elfTraining.fertilizerElfTraining.milestones[2].earned.value) { if (management.elfTraining.fertilizerElfTraining.milestones[2].earned.value) {
cost = cost.div(Decimal.add(trees.totalLogs.value, Math.E).ln()); cost = cost.div(Decimal.add(trees.totalLogs.value, Math.E).ln());
} }
if (management.elfTraining.coalDrillElfTraining.milestones[2].earned.value) {
cost = cost.div(10);
}
return cost; return cost;
}, },
inverseCost(x: DecimalSource) {
if (management.elfTraining.coalDrillElfTraining.milestones[2].earned.value) {
x = Decimal.div(x, 10);
}
if (management.elfTraining.fertilizerElfTraining.milestones[2].earned.value) {
x = Decimal.div(x, Decimal.add(trees.totalLogs.value, Math.E).ln());
}
let v = Decimal.div(x, 10).log(1.15);
v = v.div(Decimal.pow(0.95, paper.books.coalDrillBook.totalAmount.value));
if (Decimal.gte(v, 10000)) v = Decimal.mul(v, 10000).root(2);
if (Decimal.gte(v, 100)) v = Decimal.mul(v, 100).root(2);
return Decimal.isNaN(v) ? Decimal.dZero : v.floor().max(0);
},
display: jsx(() => ( display: jsx(() => (
<> <>
<h3>Coal Drill</h3> <h3>Coal Drill</h3>
@ -299,7 +334,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
width: "160px" width: "160px"
}, },
visibility: () => showIf(metal.coalDrill.bought.value) visibility: () => showIf(metal.coalDrill.bought.value)
})) as GenericBuyable & { resource: Resource }; })) as ElfBuyable & { resource: Resource };
const { const {
max: maxDrill, max: maxDrill,
min: minDrill, min: minDrill,
@ -417,7 +452,40 @@ const layer = createLayer(id, function (this: BaseLayer) {
style: { color: colorText }, style: { color: colorText },
visibility: () => showIf(oil.depthMilestones[4].earned.value) visibility: () => showIf(oil.depthMilestones[4].earned.value)
})); }));
const row3upgrades = [efficientSmelther]; const arsonistAssistance = createUpgrade(() => ({
resource: noPersist(coal),
cost: 1e45,
display: {
title: "Arsonist Assistance",
description: "Every elf at or above level 5 doubles ash gain"
},
style: { color: colorText },
visibility: () =>
showIf(management.elfTraining.coalDrillElfTraining.milestones[3].earned.value)
}));
const refinedCoal = createUpgrade(() => ({
resource: noPersist(coal),
cost: 1e50,
display: {
title: "Refined Coal",
description: "Refineries boost coal gain"
},
style: { color: colorText },
visibility: () =>
showIf(management.elfTraining.coalDrillElfTraining.milestones[3].earned.value)
}));
const coloredFire = createUpgrade(() => ({
resource: noPersist(coal),
cost: 1e55,
display: {
title: "Colored Fire",
description: "Green dye also affects small fire synergy"
},
style: { color: colorText },
visibility: () =>
showIf(management.elfTraining.coalDrillElfTraining.milestones[3].earned.value)
}));
const row3upgrades = [efficientSmelther, arsonistAssistance, refinedCoal, coloredFire];
const heatedCutters = createBuyable(() => ({ const heatedCutters = createBuyable(() => ({
resource: noPersist(coal), resource: noPersist(coal),
@ -433,6 +501,18 @@ const layer = createLayer(id, function (this: BaseLayer) {
v = v.div(wrappingPaper.boosts.rainbow1.value); v = v.div(wrappingPaper.boosts.rainbow1.value);
return Decimal.add(v, 1).pow(2.5).times(10); return Decimal.add(v, 1).pow(2.5).times(10);
}, },
inverseCost(x: DecimalSource) {
let v = Decimal.div(x, 10).root(2.5).sub(1);
v = v.mul(wrappingPaper.boosts.rainbow1.value);
if (management.elfTraining.heatedCutterElfTraining.milestones[0].earned.value) {
v = v.div(Decimal.pow(0.95, paper.books.heatedCuttersBook.totalAmount.value));
}
v = v.div(Decimal.pow(0.95, paper.books.heatedCuttersBook.totalAmount.value));
if (Decimal.gte(v, 2e6)) v = Decimal.mul(v, 2e6).root(2);
if (Decimal.gte(v, 200)) v = Decimal.mul(v, 200).root(2);
if (Decimal.gte(v, 50)) v = Decimal.mul(v, 50).root(2);
return Decimal.isNaN(v) ? Decimal.dZero : v.floor().max(0);
},
display: { display: {
title: "Heated Cutters", title: "Heated Cutters",
description: "Even warmer cutters cut down trees faster", description: "Even warmer cutters cut down trees faster",
@ -442,7 +522,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
}, },
style: { color: colorText }, style: { color: colorText },
visibility: () => showIf(warmerCutters.bought.value) visibility: () => showIf(warmerCutters.bought.value)
})) as GenericBuyable & { display: { title: string }; resource: Resource }; })) as ElfBuyable & { display: { title: string }; resource: Resource };
const heatedPlanters = createBuyable(() => ({ const heatedPlanters = createBuyable(() => ({
resource: noPersist(coal), resource: noPersist(coal),
cost() { cost() {
@ -457,6 +537,18 @@ const layer = createLayer(id, function (this: BaseLayer) {
v = v.div(wrappingPaper.boosts.rainbow1.value); v = v.div(wrappingPaper.boosts.rainbow1.value);
return Decimal.add(v, 1).pow(2.5).times(10); return Decimal.add(v, 1).pow(2.5).times(10);
}, },
inverseCost(x: DecimalSource) {
let v = Decimal.div(x, 10).root(2.5).sub(1);
v = v.mul(wrappingPaper.boosts.rainbow1.value);
if (management.elfTraining.heatedPlanterElfTraining.milestones[0].earned.value) {
v = v.div(Decimal.pow(0.95, paper.books.heatedPlantersBook.totalAmount.value));
}
v = v.div(Decimal.pow(0.95, paper.books.heatedPlantersBook.totalAmount.value));
if (Decimal.gte(v, 2e6)) v = Decimal.mul(v, 2e6).root(2);
if (Decimal.gte(v, 200)) v = Decimal.mul(v, 200).root(2);
if (Decimal.gte(v, 50)) v = Decimal.mul(v, 50).root(2);
return Decimal.isNaN(v) ? Decimal.dZero : v.floor().max(0);
},
display: { display: {
title: "Heated Planters", title: "Heated Planters",
description: "Even warmer planters plant trees faster", description: "Even warmer planters plant trees faster",
@ -466,7 +558,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
}, },
style: { color: colorText }, style: { color: colorText },
visibility: () => showIf(warmerPlanters.bought.value) visibility: () => showIf(warmerPlanters.bought.value)
})) as GenericBuyable & { display: { title: string }; resource: Resource }; })) as ElfBuyable & { display: { title: string }; resource: Resource };
const moreFertilizer = createBuyable(() => ({ const moreFertilizer = createBuyable(() => ({
resource: noPersist(ash), resource: noPersist(ash),
cost() { cost() {
@ -481,6 +573,18 @@ const layer = createLayer(id, function (this: BaseLayer) {
v = v.div(wrappingPaper.boosts.rainbow1.value); v = v.div(wrappingPaper.boosts.rainbow1.value);
return Decimal.add(v, 1).pow(1.5).times(50000); return Decimal.add(v, 1).pow(1.5).times(50000);
}, },
inverseCost(x: DecimalSource) {
let v = Decimal.div(x, 50000).root(1.5).sub(1);
v = v.mul(wrappingPaper.boosts.rainbow1.value);
if (management.elfTraining.fertilizerElfTraining.milestones[0].earned.value) {
v = v.div(Decimal.pow(0.95, paper.books.fertilizerBook.totalAmount.value));
}
v = v.div(Decimal.pow(0.95, paper.books.fertilizerBook.totalAmount.value));
if (Decimal.gte(v, 2e6)) v = Decimal.mul(v, 2e6).root(2);
if (Decimal.gte(v, 200)) v = Decimal.mul(v, 200).root(2);
if (Decimal.gte(v, 50)) v = Decimal.mul(v, 50).root(2);
return Decimal.isNaN(v) ? Decimal.dZero : v.floor().max(0);
},
display: { display: {
title: "Fertilized Soil", title: "Fertilized Soil",
description: "More fertilizer helps trees grow bigger", description: "More fertilizer helps trees grow bigger",
@ -490,7 +594,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
}, },
style: { color: colorText }, style: { color: colorText },
visibility: () => showIf(basicFertilizer.bought.value) visibility: () => showIf(basicFertilizer.bought.value)
})) as GenericBuyable & { display: { title: string }; resource: Resource }; })) as ElfBuyable & { display: { title: string }; resource: Resource };
const row3buyables = [heatedCutters, heatedPlanters, moreFertilizer]; const row3buyables = [heatedCutters, heatedPlanters, moreFertilizer];
const heatedCutterEffect = createSequentialModifier(() => [ const heatedCutterEffect = createSequentialModifier(() => [
@ -600,7 +704,11 @@ const layer = createLayer(id, function (this: BaseLayer) {
if (management.elfTraining.smallfireElfTraining.milestones[0].earned.value) { if (management.elfTraining.smallfireElfTraining.milestones[0].earned.value) {
v = Decimal.div(buildBonfire.amount.value, 10).add(v); v = Decimal.div(buildBonfire.amount.value, 10).add(v);
} }
return Decimal.div(v, 10000).add(1); let multi = Decimal.div(v, 10000).add(1);
if (coloredFire.bought.value) {
multi = Decimal.add(multi, dyes.dyes.green.amount.value);
}
return multi;
}, },
description: "Small Fires Synergy", description: "Small Fires Synergy",
enabled: elves.elves.smallFireElf.bought enabled: elves.elves.smallFireElf.bought
@ -643,7 +751,14 @@ const layer = createLayer(id, function (this: BaseLayer) {
supportLowNumbers: true supportLowNumbers: true
})), })),
createMultiplicativeModifier(() => ({ createMultiplicativeModifier(() => ({
multiplier: () => Decimal.mul(oil.depth.value, 0.25).add(1), multiplier: () =>
Decimal.mul(oil.depth.value, 0.25)
.pow(
management.elfTraining.coalDrillElfTraining.milestones[4].earned.value
? 1.5
: 1
)
.add(1),
description: "5m Well Depth", description: "5m Well Depth",
enabled: oil.depthMilestones[0].earned enabled: oil.depthMilestones[0].earned
})), })),
@ -652,6 +767,16 @@ const layer = createLayer(id, function (this: BaseLayer) {
description: "Heavy Extractor", description: "Heavy Extractor",
enabled: () => Decimal.gt(oil.activeExtractor.value, 0) enabled: () => Decimal.gt(oil.activeExtractor.value, 0)
})), })),
createMultiplicativeModifier(() => ({
multiplier: Decimal.add(coal.value, 1).log10().add(1).sqrt(),
description: "Peppermint Level 2",
enabled: management.elfTraining.coalDrillElfTraining.milestones[1].earned
})),
createMultiplicativeModifier(() => ({
multiplier: Decimal.add(plastic.buildRefinery.amount.value, 1).sqrt(),
description: "Refined Coal",
enabled: refinedCoal.bought
})),
createExponentialModifier(() => ({ createExponentialModifier(() => ({
exponent: 1.05, exponent: 1.05,
description: "Jack Level 2", description: "Jack Level 2",
@ -725,6 +850,11 @@ const layer = createLayer(id, function (this: BaseLayer) {
description: "Mining boots", description: "Mining boots",
enabled: cloth.metalUpgrades.metalUpgrade1.bought enabled: cloth.metalUpgrades.metalUpgrade1.bought
})), })),
createMultiplicativeModifier(() => ({
multiplier: () => Decimal.pow(2, management.level5Elves.value),
description: "Arson Assistance",
enabled: arsonistAssistance.bought
})),
createExponentialModifier(() => ({ createExponentialModifier(() => ({
exponent: 1.1, exponent: 1.1,
description: "Joy Level 2", description: "Joy Level 2",
@ -739,6 +869,11 @@ const layer = createLayer(id, function (this: BaseLayer) {
exponent: 1.1, exponent: 1.1,
description: "Snowball Level 2", description: "Snowball Level 2",
enabled: management.elfTraining.kilnElfTraining.milestones[1].earned enabled: management.elfTraining.kilnElfTraining.milestones[1].earned
})),
createAdditiveModifier(() => ({
addend: paper.paper,
description: "Paper Burning",
enabled: paper.upgrades2.ashUpgrade.bought
})) }))
]); ]);
const computedAshGain = computed(() => ashGain.apply(0)); const computedAshGain = computed(() => ashGain.apply(0));
@ -874,6 +1009,9 @@ const layer = createLayer(id, function (this: BaseLayer) {
betterFertilizer, betterFertilizer,
unlockKiln, unlockKiln,
efficientSmelther, efficientSmelther,
arsonistAssistance,
refinedCoal,
coloredFire,
heatedCutters, heatedCutters,
heatedPlanters, heatedPlanters,
moreFertilizer, moreFertilizer,

View file

@ -31,12 +31,14 @@ import oil from "./oil";
import trees from "./trees"; import trees from "./trees";
import wrappingPaper from "./wrapping-paper"; import wrappingPaper from "./wrapping-paper";
import paper from "./paper"; import paper from "./paper";
import boxes from "./boxes";
import { ElfBuyable } from "./elves";
interface Dye { interface Dye {
name: string; name: string;
amount: Resource<DecimalSource> & amount: Resource<DecimalSource> &
Persistent<DecimalSource> & { [NonPersistent]: Resource<DecimalSource> }; Persistent<DecimalSource> & { [NonPersistent]: Resource<DecimalSource> };
buyable: GenericBuyable; buyable: ElfBuyable;
toGenerate: WithRequired<Modifier, "description" | "revert">; toGenerate: WithRequired<Modifier, "description" | "revert">;
computedToGenerate: ComputedRef<DecimalSource>; computedToGenerate: ComputedRef<DecimalSource>;
display: JSXFunction; display: JSXFunction;
@ -89,6 +91,22 @@ const layer = createLayer(id, function (this: BaseLayer) {
description: `${options.name} Chambers` description: `${options.name} Chambers`
})) }))
]; ];
if (options.color === "yellow" && oil.row3Upgrades[0].bought.value){
modifiers.push(
createMultiplicativeModifier(() => ({
multiplier(){return Decimal.add(dyes.red.amount.value,1).log10().pow(0.75)},
description: "Dye Synergy I"
}))
)
}
if (options.color === "red" && oil.row3Upgrades[3].bought.value){
modifiers.push(
createMultiplicativeModifier(() => ({
multiplier(){return Decimal.add(dyes.blue.amount.value,1).log10()},
description: "Dye Synergy II"
}))
)
}
if (options.color === "red" || options.color === "yellow") { if (options.color === "red" || options.color === "yellow") {
modifiers.push( modifiers.push(
createMultiplicativeModifier(() => ({ createMultiplicativeModifier(() => ({
@ -156,11 +174,18 @@ const layer = createLayer(id, function (this: BaseLayer) {
enabled: management.elfTraining.clothElfTraining.milestones[2].earned enabled: management.elfTraining.clothElfTraining.milestones[2].earned
})) }))
); );
modifiers.push(
createMultiplicativeModifier(() => ({
multiplier: 2,
description: "Carry dye in boxes",
enabled: boxes.row3Upgrades.dyeUpgrade.bought
}))
);
return modifiers; return modifiers;
}) as WithRequired<Modifier, "description" | "revert">; }) as WithRequired<Modifier, "description" | "revert">;
const computedToGenerate = computed(() => toGenerate.apply(0)); const computedToGenerate = computed(() => toGenerate.apply(0));
const buyable: GenericBuyable = createBuyable(() => { const buyable: ElfBuyable = createBuyable(() => {
const costs = convertComputable(options.costs); const costs = convertComputable(options.costs);
return { return {
...options, ...options,
@ -219,6 +244,19 @@ const layer = createLayer(id, function (this: BaseLayer) {
v = Decimal.mul(v, Decimal.pow(0.95, paper.books.dyeBook.totalAmount.value)); v = Decimal.mul(v, Decimal.pow(0.95, paper.books.dyeBook.totalAmount.value));
return Decimal.div(v, 10).plus(1); return Decimal.div(v, 10).plus(1);
}, },
inverseCostPre(x: DecimalSource) {
let v = Decimal.sub(x, 1).mul(10);
v = v.div(Decimal.pow(0.95, paper.books.dyeBook.totalAmount.value));
if (Decimal.gte(v, 10)) v = Decimal.mul(v, 5).root(2);
if (Decimal.gte(v, 25)) v = Decimal.mul(v, 20).root(2);
return Decimal.isNaN(v) ? Decimal.dZero : v.floor().max(0);
},
inverseCost() {
if (unref(buyable.visibility) != Visibility.Visible) return Decimal.dZero;
return unref(costs).reduce((pre, c) =>
Decimal.min(this.inverseCostPre(Decimal.div(c.res.value, unref(c.base)).root(unref(c.root ?? 1))), pre)
, Decimal.dInf);
},
canPurchase: computed((cost?: DecimalSource) => { canPurchase: computed((cost?: DecimalSource) => {
if (unref(buyable.visibility) != Visibility.Visible) return false; if (unref(buyable.visibility) != Visibility.Visible) return false;
const trueCost = cost ?? unref(buyable.cost) ?? Decimal.dInf; const trueCost = cost ?? unref(buyable.cost) ?? Decimal.dInf;
@ -234,7 +272,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
amount.value = Decimal.add(amount.value, computedToGenerate.value); amount.value = Decimal.add(amount.value, computedToGenerate.value);
buyable.amount.value = Decimal.add(buyable.amount.value, 1); buyable.amount.value = Decimal.add(buyable.amount.value, 1);
if (!wrappingPaper.milestones.secondaryNoReset.earned) { if (!wrappingPaper.milestones.secondaryNoReset.earned.value) {
unref(costs).forEach(c => { unref(costs).forEach(c => {
c.res.value = Decimal.sub( c.res.value = Decimal.sub(
c.res.value, c.res.value,
@ -490,15 +528,15 @@ const layer = createLayer(id, function (this: BaseLayer) {
blue1: computed(() => Decimal.add(dyes.blue.amount.value, 1).log2().sqrt().times(5e6)), blue1: computed(() => Decimal.add(dyes.blue.amount.value, 1).log2().sqrt().times(5e6)),
orange1: computed(() => orange1: computed(() =>
Decimal.pow(2, Decimal.add(dyes.orange.amount.value, 1).log2().sqrt()).pow( Decimal.pow(2, Decimal.add(dyes.orange.amount.value, 1).log2().sqrt())
upgrades.coalUpg.bought.value ? 1.2 : 1 .pow(upgrades.coalUpg.bought.value ? 1.2 : 1)
) .pow(management.elfTraining.clothElfTraining.milestones[3].earned.value ? 1.1 : 1)
), ),
orange2: computed(() => Decimal.add(dyes.orange.amount.value, 1).log2().plus(1)), orange2: computed(() => Decimal.add(dyes.orange.amount.value, 1).log2().plus(1).pow(oil.row3Upgrades[1].bought.value ? 2.5 : 1)),
green1: computed(() => green1: computed(() =>
Decimal.pow(2, Decimal.add(dyes.green.amount.value, 1).log2().sqrt()).pow( Decimal.pow(2, Decimal.add(dyes.green.amount.value, 1).log2().sqrt())
upgrades.coalUpg.bought.value ? 1.2 : 1 .pow(upgrades.coalUpg.bought.value ? 1.2 : 1)
) .pow(management.elfTraining.clothElfTraining.milestones[3].earned.value ? 1.1 : 1)
), ),
green2: computed(() => green2: computed(() =>
Decimal.add(dyes.green.amount.value, 1) Decimal.add(dyes.green.amount.value, 1)
@ -507,9 +545,9 @@ const layer = createLayer(id, function (this: BaseLayer) {
.pow(upgrades.coalUpg.bought.value ? 2 : 1) .pow(upgrades.coalUpg.bought.value ? 2 : 1)
), ),
purple1: computed(() => purple1: computed(() =>
Decimal.pow(2, Decimal.add(dyes.purple.amount.value, 1).log2().sqrt()).pow( Decimal.pow(2, Decimal.add(dyes.purple.amount.value, 1).log2().sqrt())
upgrades.coalUpg.bought.value ? 1.2 : 1 .pow(upgrades.coalUpg.bought.value ? 1.2 : 1)
) .pow(management.elfTraining.clothElfTraining.milestones[3].earned.value ? 1.1 : 1)
), ),
purple2: computed(() => Decimal.add(dyes.purple.amount.value, 1).log2().plus(1)) purple2: computed(() => Decimal.add(dyes.purple.amount.value, 1).log2().plus(1))
}; };

View file

@ -38,8 +38,14 @@ import workshop from "./workshop";
import wrappingPaper from "./wrapping-paper"; import wrappingPaper from "./wrapping-paper";
import dyes from "./dyes"; import dyes from "./dyes";
export interface ElfBuyable extends GenericBuyable {
/** The inverse function of the cost formula, used to calculate the maximum amount that can be bought by elves. */
inverseCost: (x?: DecimalSource) => DecimalSource;
}
const id = "elves"; const id = "elves";
const day = 4; const day = 4;
const layer = createLayer(id, function (this: BaseLayer) { const layer = createLayer(id, function (this: BaseLayer) {
const name = "Elves"; const name = "Elves";
const colorBright = "red"; const colorBright = "red";
@ -531,6 +537,9 @@ const layer = createLayer(id, function (this: BaseLayer) {
if (Decimal.gte(totalElves.value, 9)) { if (Decimal.gte(totalElves.value, 9)) {
cost = Decimal.times(cost, 1e15); cost = Decimal.times(cost, 1e15);
} }
if (Decimal.gte(totalElves.value, 12)) {
cost = Decimal.times(cost, 1e15);
}
return cost; return cost;
}); });
@ -539,13 +548,15 @@ const layer = createLayer(id, function (this: BaseLayer) {
name: string; name: string;
description: string; description: string;
buyable: buyable:
| (GenericBuyable & { resource?: Resource }) | (ElfBuyable & { resource?: Resource })
| (GenericBuyable & { resource?: Resource })[]; | (ElfBuyable & { resource?: Resource })[];
cooldownModifier: Modifier; cooldownModifier: Modifier;
customCost?: (amount: DecimalSource) => DecimalSource;
hasToggle?: boolean; hasToggle?: boolean;
toggleDesc?: string; toggleDesc?: string;
onAutoPurchase?: (buyable: GenericBuyable & { resource?: Resource }) => void; onAutoPurchase?: (
buyable: ElfBuyable & { resource?: Resource },
amount: DecimalSource
) => void;
onPurchase?: VoidFunction; // Will get overriden by the custom onpurchase, but that's fine onPurchase?: VoidFunction; // Will get overriden by the custom onpurchase, but that's fine
canBuy?: Computable<boolean>; canBuy?: Computable<boolean>;
buyMax?: Computable<boolean>; buyMax?: Computable<boolean>;
@ -563,27 +574,32 @@ const layer = createLayer(id, function (this: BaseLayer) {
function update(diff: number) { function update(diff: number) {
if (upgrade.bought.value && unref(isActive)) { if (upgrade.bought.value && unref(isActive)) {
buyProgress.value = Decimal.add(buyProgress.value, diff); buyProgress.value = Decimal.add(buyProgress.value, diff);
const cooldown = Decimal.recip(computedAutoBuyCooldown.value); const cooldown = Decimal.recip(computedAutoBuyCooldown.value);
amountOfTimesDone.value += diff / cooldown.toNumber(); amountOfTimesDone.value += diff / cooldown.toNumber();
let maxBuyAmount = Decimal.div(buyProgress.value, cooldown).floor();
buyProgress.value = Decimal.sub(buyProgress.value, maxBuyAmount.mul(cooldown));
if (unref(buyMax)) maxBuyAmount = Decimal.dInf;
(isArray(options.buyable) ? options.buyable : [options.buyable]).forEach( (isArray(options.buyable) ? options.buyable : [options.buyable]).forEach(
buyable => { buyable => {
while (buyMax ? true : Decimal.gte(buyProgress.value, cooldown)) { const buyAmount = Decimal.min(
if ( Decimal.sub(
options.customCost && buyable.resource buyable.inverseCost(buyable.resource?.value),
? Decimal.gte( buyable.amount.value
buyable.resource.value, ).add(1),
options.customCost(buyable.amount.value) maxBuyAmount
) );
: unref(buyable.canPurchase)
) { if (buyAmount.lte(0)) return;
buyable.amount.value = Decimal.add(buyable.amount.value, 1);
buyProgress.value = Decimal.sub(buyProgress.value, cooldown); buyable.amount.value = Decimal.add(buyable.amount.value, buyAmount);
options.onAutoPurchase?.(buyable); maxBuyAmount = Decimal.sub(maxBuyAmount, buyAmount);
} else { options.onAutoPurchase?.(buyable, buyAmount);
buyProgress.value = cooldown;
break; if (maxBuyAmount.lte(0)) return;
}
}
} }
); );
} }
@ -702,9 +718,9 @@ const layer = createLayer(id, function (this: BaseLayer) {
visibility: () => showIf(boxes.upgrades.logsUpgrade.bought.value), visibility: () => showIf(boxes.upgrades.logsUpgrade.bought.value),
hasToggle: true, hasToggle: true,
toggleDesc: "Activate auto-purchased small fires", toggleDesc: "Activate auto-purchased small fires",
onAutoPurchase() { onAutoPurchase(_, amount) {
if (smallFireElf.toggle.value) { if (smallFireElf.toggle.value) {
coal.activeFires.value = Decimal.add(coal.activeFires.value, 1); coal.activeFires.value = Decimal.add(coal.activeFires.value, amount);
} }
}, },
onPurchase() { onPurchase() {
@ -720,12 +736,12 @@ const layer = createLayer(id, function (this: BaseLayer) {
visibility: () => showIf(boxes.upgrades.ashUpgrade.bought.value), visibility: () => showIf(boxes.upgrades.ashUpgrade.bought.value),
hasToggle: true, hasToggle: true,
toggleDesc: "Activate auto-purchased bonfires", toggleDesc: "Activate auto-purchased bonfires",
onAutoPurchase() { onAutoPurchase(buyable, amount) {
const spent = unref((this.buyable as GenericBuyable).cost!); const spent = Decimal.mul(unref(buyable.cost ?? 0), amount);
coal.activeFires.value = Decimal.sub(coal.activeFires.value, spent).max(0); coal.activeFires.value = Decimal.sub(coal.activeFires.value, spent).max(0);
coal.buildFire.amount.value = Decimal.sub(coal.buildFire.amount.value, spent).max(0); coal.buildFire.amount.value = Decimal.sub(coal.buildFire.amount.value, spent).max(0);
if (bonfireElf.toggle.value) { if (bonfireElf.toggle.value) {
coal.activeBonfires.value = Decimal.add(coal.activeBonfires.value, 1); coal.activeBonfires.value = Decimal.add(coal.activeBonfires.value, amount);
} }
}, },
onPurchase() { onPurchase() {
@ -742,9 +758,9 @@ const layer = createLayer(id, function (this: BaseLayer) {
visibility: () => showIf(boxes.upgrades.coalUpgrade.bought.value), visibility: () => showIf(boxes.upgrades.coalUpgrade.bought.value),
hasToggle: true, hasToggle: true,
toggleDesc: "Activate auto-purchased kilns", toggleDesc: "Activate auto-purchased kilns",
onAutoPurchase() { onAutoPurchase(_, amount) {
if (kilnElf.toggle.value) { if (kilnElf.toggle.value) {
coal.activeKilns.value = Decimal.add(coal.activeKilns.value, 1); coal.activeKilns.value = Decimal.add(coal.activeKilns.value, amount);
} }
}, },
onPurchase() { onPurchase() {
@ -788,9 +804,9 @@ const layer = createLayer(id, function (this: BaseLayer) {
showIf(management.elfTraining.expandersElfTraining.milestones[3].earned.value), showIf(management.elfTraining.expandersElfTraining.milestones[3].earned.value),
hasToggle: true, hasToggle: true,
toggleDesc: "Activate auto-purchased coal drills", toggleDesc: "Activate auto-purchased coal drills",
onAutoPurchase() { onAutoPurchase(_, amount) {
if (coalDrillElf.toggle.value) { if (coalDrillElf.toggle.value) {
coal.activeDrills.value = Decimal.add(coal.activeDrills.value, 1); coal.activeDrills.value = Decimal.add(coal.activeDrills.value, amount);
} }
} }
}); });
@ -804,14 +820,14 @@ const layer = createLayer(id, function (this: BaseLayer) {
showIf(management.elfTraining.fertilizerElfTraining.milestones[4].earned.value), showIf(management.elfTraining.fertilizerElfTraining.milestones[4].earned.value),
hasToggle: true, hasToggle: true,
toggleDesc: "Activate auto-purchased oil drills", toggleDesc: "Activate auto-purchased oil drills",
onAutoPurchase(buyable) { onAutoPurchase(buyable, amount) {
if (heavyDrillElf.toggle.value) { if (heavyDrillElf.toggle.value) {
if (buyable === oil.buildHeavy) { if (buyable === oil.buildHeavy) {
oil.activeHeavy.value = Decimal.add(oil.activeHeavy.value, 1); oil.activeHeavy.value = Decimal.add(oil.activeHeavy.value, amount);
} else if (buyable === oil.buildHeavy) { } else if (buyable === oil.buildHeavy2) {
oil.activeHeavy.value = Decimal.add(oil.activeHeavy.value, 1); oil.activeHeavy2.value = Decimal.add(oil.activeHeavy2.value, amount);
} else if (buyable === oil.buildHeavy) { } else if (buyable === oil.buildExtractor) {
oil.activeHeavy.value = Decimal.add(oil.activeHeavy.value, 1); oil.activeExtractor.value = Decimal.add(oil.activeExtractor.value, amount);
} }
} }
} }
@ -826,14 +842,14 @@ const layer = createLayer(id, function (this: BaseLayer) {
showIf(management.elfTraining.heatedCutterElfTraining.milestones[4].earned.value), showIf(management.elfTraining.heatedCutterElfTraining.milestones[4].earned.value),
hasToggle: true, hasToggle: true,
toggleDesc: "Activate auto-purchased oil-using machines", toggleDesc: "Activate auto-purchased oil-using machines",
onAutoPurchase(buyable) { onAutoPurchase(buyable, amount) {
if (heavyDrillElf.toggle.value) { if (heavyDrillElf.toggle.value) {
if (buyable === oil.buildPump) { if (buyable === oil.buildPump) {
oil.activePump.value = Decimal.add(oil.activePump.value, 1); oil.activePump.value = Decimal.add(oil.activePump.value, amount);
} else if (buyable === oil.buildBurner) { } else if (buyable === oil.buildBurner) {
oil.activeBurner.value = Decimal.add(oil.activeBurner.value, 1); oil.activeBurner.value = Decimal.add(oil.activeBurner.value, amount);
} else if (buyable === oil.buildSmelter) { } else if (buyable === oil.buildSmelter) {
oil.activeSmelter.value = Decimal.add(oil.activeSmelter.value, 1); oil.activeSmelter.value = Decimal.add(oil.activeSmelter.value, amount);
} }
} }
} }

View file

@ -1,11 +1,10 @@
import Spacer from "components/layout/Spacer.vue"; import Spacer from "components/layout/Spacer.vue";
import Fraction from "components/math/Fraction.vue";
import Sqrt from "components/math/Sqrt.vue"; import Sqrt from "components/math/Sqrt.vue";
import Modal from "components/Modal.vue"; import Modal from "components/Modal.vue";
import { createCollapsibleMilestones, createCollapsibleModifierSections } from "data/common"; import { createCollapsibleMilestones, createCollapsibleModifierSections } from "data/common";
import { main } from "data/projEntry"; import { main } from "data/projEntry";
import { createBar, GenericBar } from "features/bars/bar"; import { createBar, GenericBar } from "features/bars/bar";
import { createBuyable } from "features/buyable"; import { createBuyable, GenericBuyable } from "features/buyable";
import { createClickable } from "features/clickables/clickable"; import { createClickable } from "features/clickables/clickable";
import { jsx, showIf, Visibility } from "features/feature"; import { jsx, showIf, Visibility } from "features/feature";
import { createMilestone, GenericMilestone } from "features/milestones/milestone"; import { createMilestone, GenericMilestone } from "features/milestones/milestone";
@ -20,8 +19,7 @@ import {
} from "game/modifiers"; } from "game/modifiers";
import { persistent } from "game/persistence"; import { persistent } from "game/persistence";
import Decimal, { DecimalSource, format, formatTime, formatWhole } from "util/bignum"; import Decimal, { DecimalSource, format, formatTime, formatWhole } from "util/bignum";
import { Direction } from "util/common"; import { Direction, WithRequired } from "util/common";
import { ProcessedComputable } from "util/computed";
import { render, renderCol, renderGrid } from "util/vue"; import { render, renderCol, renderGrid } from "util/vue";
import { computed, ComputedRef, ref, Ref, unref, watchEffect } from "vue"; import { computed, ComputedRef, ref, Ref, unref, watchEffect } from "vue";
import boxes from "./boxes"; import boxes from "./boxes";
@ -30,10 +28,13 @@ import coal from "./coal";
import dyes from "./dyes"; import dyes from "./dyes";
import elves from "./elves"; import elves from "./elves";
import metal from "./metal"; import metal from "./metal";
import oil from "./oil";
import paper from "./paper"; import paper from "./paper";
import plastic from "./plastic"; import plastic from "./plastic";
import trees from "./trees"; import trees from "./trees";
import "./styles/management.css";
const id = "management"; const id = "management";
const day = 12; const day = 12;
const advancedDay = 13; const advancedDay = 13;
@ -112,13 +113,35 @@ const layer = createLayer(id, () => {
style: "width: 150px", style: "width: 150px",
cost: 1e13 cost: 1e13
})); }));
const advancedUpgrade = createUpgrade(() => ({
display: {
title: "Advanced Training",
description:
"Time for some advanced training! Now that all the elves know the basics, you have a foundation you can truly build off of. Everyone seems to be learning twice as quickly!"
},
visibility: () =>
showIf(main.day.value >= advancedDay && main.days[advancedDay - 1].opened.value),
resource: boxes.boxes,
style: "width: 150px",
cost: 1e26
}));
const globalXPModifier = createSequentialModifier(() => [ const globalXPModifier = createSequentialModifier(() => [
createMultiplicativeModifier(() => ({ createMultiplicativeModifier(() => ({
multiplier: classroomEffect, multiplier: classroomEffect,
description: "Classroom Effect", description: "Classroom Effect",
enabled: classroomUpgrade.bought enabled: classroomUpgrade.bought
})),
createMultiplicativeModifier(() => ({
multiplier: 2,
description: "Advanced Training",
enabled: advancedUpgrade.bought
})),
createMultiplicativeModifier(() => ({
multiplier: 2,
description: "Carry experience in boxes???",
enabled: boxes.row3Upgrades.xpUpgrade.bought
})) }))
]); ]) as WithRequired<Modifier, "description" | "revert">;
const globalXPModifierComputed = computed(() => globalXPModifier.apply(1)); const globalXPModifierComputed = computed(() => globalXPModifier.apply(1));
// ------------------------------------------------------------------------------- Training core function // ------------------------------------------------------------------------------- Training core function
@ -128,7 +151,7 @@ const layer = createLayer(id, () => {
name: string; name: string;
computedAutoBuyCooldown: ComputedRef<DecimalSource>; computedAutoBuyCooldown: ComputedRef<DecimalSource>;
amountOfTimesDone: Ref<number>; amountOfTimesDone: Ref<number>;
visibility: ProcessedComputable<Visibility>; bought: Ref<boolean>;
}, },
milestones: Array<GenericMilestone>, milestones: Array<GenericMilestone>,
...modifiers: Modifier[] ...modifiers: Modifier[]
@ -157,28 +180,41 @@ const layer = createLayer(id, () => {
if (elf.name == "Star" || elf.name == "Bell") { if (elf.name == "Star" || elf.name == "Bell") {
costMulti /= 3; costMulti /= 3;
} }
const costBase = Decimal.mul(paperElfMilestones[3].earned.value ? 2000 : 4000, costMulti); const costBase = computed(() => {
const expRequiredForNextLevel = computed(() => Decimal.pow(5, level.value).mul(costBase)); return Decimal.mul(paperElfMilestones[3].earned.value ? 2000 : 4000, costMulti);
});
const expRequiredForNextLevel = computed(() =>
Decimal.pow(5, level.value).mul(costBase.value)
)
const level = computed(() => const level = computed(() =>
Decimal.affordGeometricSeries(exp.value, costBase, 5, 0) Decimal.affordGeometricSeries(exp.value, costBase.value, 5, 0)
.min(schools.amount.value) .min(schools.amount.value)
.toNumber() .toNumber()
); );
const expToNextLevel = computed(() => const expToNextLevel = computed(() =>
Decimal.sub(exp.value, Decimal.sumGeometricSeries(level.value, costBase, 5, 0)) Decimal.sub(exp.value, Decimal.sumGeometricSeries(level.value, costBase.value, 5, 0))
); );
const bar = createBar(() => ({ const bar = createBar(() => ({
direction: Direction.Right, direction: Direction.Right,
width: 160, width: 160,
height: 12, height: 14,
style: () => ({ style: () => ({
"margin-top": "8px", "margin-top": "8px",
"box-shadow": focusTargets.value[elf.name] background: color,
? "0 0 12px " + (currentShown.value == elf.name ? "black" : "white") "box-shadow":
: "" currentShown.value == elf.name
? "0 0 12px black"
: focusTargets.value[elf.name]
? "0 0 12px white"
: ""
}),
baseStyle: "margin-top: -1px",
fillStyle: () => ({
"margin-top": "-1px",
"transition-duration": "0s",
background: "white",
animation: focusTargets.value[elf.name] ? ".5s focused-xp-bar linear infinite" : ""
}), }),
baseStyle: "margin-top: 0",
fillStyle: "margin-top: 0; transition-duration: 0s",
borderStyle: () => borderStyle: () =>
Decimal.gte(level.value, schools.amount.value) ? "border-color: red" : "", Decimal.gte(level.value, schools.amount.value) ? "border-color: red" : "",
progress: () => Decimal.div(expToNextLevel.value, expRequiredForNextLevel.value), progress: () => Decimal.div(expToNextLevel.value, expRequiredForNextLevel.value),
@ -234,7 +270,7 @@ const layer = createLayer(id, () => {
}, },
style: () => ({ style: () => ({
width: "190px", width: "190px",
background: currentShown.value == elf.name ? "var(--foreground)" : "" background: currentShown.value == elf.name ? "var(--accent2)" : ""
}), }),
onClick() { onClick() {
currentShown.value = elf.name; currentShown.value = elf.name;
@ -242,7 +278,7 @@ const layer = createLayer(id, () => {
canClick() { canClick() {
return currentShown.value !== elf.name; return currentShown.value !== elf.name;
}, },
visibility: elf.visibility, visibility: () => showIf(elf.bought.value),
name: elf.name, name: elf.name,
state, state,
displayMilestone, displayMilestone,
@ -304,7 +340,7 @@ const layer = createLayer(id, () => {
createMilestone(() => ({ createMilestone(() => ({
display: { display: {
requirement: "Holly Level 5", requirement: "Holly Level 5",
effectDisplay: "Raise workshop expansion cost by 0.95" effectDisplay: "Raise workshop expansion cost by 0.99"
}, },
visibility: () => showIf(cutterElfMilestones[3].earned.value && main.day.value >= 13), visibility: () => showIf(cutterElfMilestones[3].earned.value && main.day.value >= 13),
shouldEarn: () => cutterElfTraining.level.value >= 5 shouldEarn: () => cutterElfTraining.level.value >= 5
@ -543,7 +579,7 @@ const layer = createLayer(id, () => {
}, },
visibility: () => visibility: () =>
showIf(fertilizerElfMilestones[3].earned.value && main.day.value >= 13), showIf(fertilizerElfMilestones[3].earned.value && main.day.value >= 13),
shouldEarn: () => heatedPlanterElfTraining.level.value >= 5 shouldEarn: () => fertilizerElfTraining.level.value >= 5
})) }))
] as Array<GenericMilestone>; ] as Array<GenericMilestone>;
const smallfireElfMilestones = [ const smallfireElfMilestones = [
@ -796,23 +832,26 @@ const layer = createLayer(id, () => {
createMilestone(() => ({ createMilestone(() => ({
display: { display: {
requirement: "Gingersnap Level 4", requirement: "Gingersnap Level 4",
effectDisplay: "Raise secondary dyes' first effects to the 1.1" effectDisplay:
"Raise secondary dyes' first effects to the 1.1 but reset primary dyes"
}, },
visibility: () => showIf(clothElfMilestones[2].earned.value && main.day.value >= 13), visibility: () => showIf(clothElfMilestones[2].earned.value && main.day.value >= 13),
shouldEarn: () => clothElfTraining.level.value >= 4, shouldEarn: () => clothElfTraining.level.value >= 4,
onComplete() { onComplete() {
(["red", "yellow", "blue"] as const).forEach( (["red", "yellow", "blue"] as const).forEach(dyeColor => {
dyeColor => { dyes.dyes[dyeColor].amount.value = 0;
dyes.dyes[dyeColor].amount.value = 0; dyes.dyes[dyeColor].buyable.amount.value = 0;
dyes.dyes[dyeColor].buyable.amount.value = 0; });
}
);
} }
})), })),
createMilestone(() => ({ createMilestone(() => ({
display: { display: {
requirement: "Gingersnap Level 5", requirement: "Gingersnap Level 5",
effectDisplay: "Well depth divides metal machine costs" effectDisplay: jsx(() => (
<>
<Sqrt>Well depth</Sqrt> divides metal machine costs
</>
))
}, },
visibility: () => showIf(clothElfMilestones[3].earned.value && main.day.value >= 13), visibility: () => showIf(clothElfMilestones[3].earned.value && main.day.value >= 13),
shouldEarn: () => clothElfTraining.level.value >= 5 shouldEarn: () => clothElfTraining.level.value >= 5
@ -837,7 +876,7 @@ const layer = createLayer(id, () => {
createMilestone(() => ({ createMilestone(() => ({
display: { display: {
requirement: "Peppermint Level 3", requirement: "Peppermint Level 3",
effectDisplay: "The coal drill cost is decreased" effectDisplay: "The coal drill cost is 10x cheaper"
}, },
visibility: () => showIf(coalDrillElfMilestones[1].earned.value), visibility: () => showIf(coalDrillElfMilestones[1].earned.value),
shouldEarn: () => coalDrillElfTraining.level.value >= 3 shouldEarn: () => coalDrillElfTraining.level.value >= 3
@ -854,7 +893,7 @@ const layer = createLayer(id, () => {
createMilestone(() => ({ createMilestone(() => ({
display: { display: {
requirement: "Peppermint Level 5", requirement: "Peppermint Level 5",
effectDisplay: "Well depth boosts coal gain more" effectDisplay: "Well depth boosts coal gain an additional half time"
}, },
visibility: () => visibility: () =>
showIf(coalDrillElfMilestones[3].earned.value && main.day.value >= 13), showIf(coalDrillElfMilestones[3].earned.value && main.day.value >= 13),
@ -880,7 +919,7 @@ const layer = createLayer(id, () => {
createMilestone(() => ({ createMilestone(() => ({
display: { display: {
requirement: "Twinkle Level 3", requirement: "Twinkle Level 3",
effectDisplay: "Auto smelting purity is tripled." effectDisplay: "Auto smelting multi is tripled."
}, },
visibility: () => showIf(metalElfMilestones[1].earned.value), visibility: () => showIf(metalElfMilestones[1].earned.value),
shouldEarn: () => metalElfTraining.level.value >= 3 shouldEarn: () => metalElfTraining.level.value >= 3
@ -888,7 +927,7 @@ const layer = createLayer(id, () => {
createMilestone(() => ({ createMilestone(() => ({
display: { display: {
requirement: "Twinkle Level 4", requirement: "Twinkle Level 4",
effectDisplay: "All metal buyables are cheaper" effectDisplay: "All metal machines are 10x cheaper"
}, },
visibility: () => showIf(metalElfMilestones[2].earned.value && main.day.value >= 13), visibility: () => showIf(metalElfMilestones[2].earned.value && main.day.value >= 13),
shouldEarn: () => metalElfTraining.level.value >= 4 shouldEarn: () => metalElfTraining.level.value >= 4
@ -896,7 +935,7 @@ const layer = createLayer(id, () => {
createMilestone(() => ({ createMilestone(() => ({
display: { display: {
requirement: "Twinkle Level 5", requirement: "Twinkle Level 5",
effectDisplay: "Unlock another row of metal upgrades" effectDisplay: "Unlock another row of focus upgrades"
}, },
visibility: () => showIf(metalElfMilestones[3].earned.value && main.day.value >= 13), visibility: () => showIf(metalElfMilestones[3].earned.value && main.day.value >= 13),
shouldEarn: () => metalElfTraining.level.value >= 5 shouldEarn: () => metalElfTraining.level.value >= 5
@ -954,7 +993,7 @@ const layer = createLayer(id, () => {
createMilestone(() => ({ createMilestone(() => ({
display: { display: {
requirement: "Frosty Level 2", requirement: "Frosty Level 2",
effectDisplay: "Oil pumps are cheaper" effectDisplay: "Oil pumps are 10x cheaper"
}, },
visibility: () => showIf(heavyDrillElfMilestones[0].earned.value), visibility: () => showIf(heavyDrillElfMilestones[0].earned.value),
shouldEarn: () => heavyDrillElfTraining.level.value >= 2 shouldEarn: () => heavyDrillElfTraining.level.value >= 2
@ -970,7 +1009,11 @@ const layer = createLayer(id, () => {
createMilestone(() => ({ createMilestone(() => ({
display: { display: {
requirement: "Frosty Level 4", requirement: "Frosty Level 4",
effectDisplay: "Heavy drill's ln is now log2.5" effectDisplay: jsx(() => (
<>
Heavy drill drill's ln is now log<sub>2.5</sub>
</>
))
}, },
visibility: () => visibility: () =>
showIf(heavyDrillElfMilestones[2].earned.value && main.day.value >= 13), showIf(heavyDrillElfMilestones[2].earned.value && main.day.value >= 13),
@ -1034,8 +1077,24 @@ const layer = createLayer(id, () => {
const kilnElfTraining = createElfTraining(elves.elves.kilnElf, kilnElfMilestones); const kilnElfTraining = createElfTraining(elves.elves.kilnElf, kilnElfMilestones);
const fireElfTraining = [smallfireElfTraining, bonfireElfTraining, kilnElfTraining]; const fireElfTraining = [smallfireElfTraining, bonfireElfTraining, kilnElfTraining];
const paperElfTraining = createElfTraining(elves.elves.paperElf, paperElfMilestones); const paperElfTraining = createElfTraining(
const boxElfTraining = createElfTraining(elves.elves.boxElf, boxElfMilestones); elves.elves.paperElf,
paperElfMilestones,
createMultiplicativeModifier(() => ({
multiplier: () => Decimal.add(oil.oil.value, 1).log10(),
description: "Frosty Level 1",
enabled: heavyDrillElfMilestones[0].earned
}))
);
const boxElfTraining = createElfTraining(
elves.elves.boxElf,
boxElfMilestones,
createMultiplicativeModifier(() => ({
multiplier: () => Decimal.add(oil.oil.value, 1).log10(),
description: "Frosty Level 1",
enabled: heavyDrillElfMilestones[0].earned
}))
);
const clothElfTraining = createElfTraining(elves.elves.clothElf, clothElfMilestones); const clothElfTraining = createElfTraining(elves.elves.clothElf, clothElfMilestones);
const plasticElfTraining = [paperElfTraining, boxElfTraining, clothElfTraining]; const plasticElfTraining = [paperElfTraining, boxElfTraining, clothElfTraining];
const coalDrillElfTraining = createElfTraining( const coalDrillElfTraining = createElfTraining(
@ -1121,10 +1180,12 @@ const layer = createLayer(id, () => {
if (Decimal.eq(focusTime.value, 0)) { if (Decimal.eq(focusTime.value, 0)) {
focusTargets.value = {}; focusTargets.value = {};
focusMulti.value = Decimal.pow( const speed = focusUpgrade5.bought.value ? 2000 : 1000;
focusMaxMulti.value, let stoppedAt = 1 - Math.abs(Math.sin((Date.now() / speed) * 2));
1 - Math.abs(Math.sin((Date.now() / 1000) * 2)) if (focusUpgrade4.bought.value) {
); stoppedAt = 1 - (1 - stoppedAt) ** 2;
}
focusMulti.value = Decimal.pow(focusMaxMulti.value, stoppedAt);
} }
}); });
@ -1140,13 +1201,28 @@ const layer = createLayer(id, () => {
multiplier: 2, multiplier: 2,
description: "Focus Upgrade 1", description: "Focus Upgrade 1",
enabled: focusUpgrade1.bought enabled: focusUpgrade1.bought
})),
createAdditiveModifier(() => ({
addend() {
return Decimal.add(dyes.dyes.orange.amount.value, dyes.dyes.purple.amount.value)
.add(dyes.dyes.green.amount.value)
.add(1)
.cbrt();
},
description: "Colorful Focus",
enabled: oil.row3Upgrades[2].bought
})) }))
]); ]) as WithRequired<Modifier, "revert" | "description">;
const maximumElvesModifier = createSequentialModifier(() => [ const maximumElvesModifier = createSequentialModifier(() => [
createAdditiveModifier(() => ({ createAdditiveModifier(() => ({
addend: 1, addend: 1,
description: "Focus Upgrade 2", description: "Focus Upgrade 2",
enabled: focusUpgrade2.bought enabled: focusUpgrade2.bought
})),
createAdditiveModifier(() => ({
addend: 1,
description: "Focus Upgrade 6",
enabled: focusUpgrade6.bought
})) }))
]); ]);
@ -1165,11 +1241,12 @@ const layer = createLayer(id, () => {
const focusMeter = createBar(() => ({ const focusMeter = createBar(() => ({
direction: Direction.Right, direction: Direction.Right,
width: 566, width: 566,
height: 25, height: 50,
style: `border-radius: 4px 4px 0 0`, style: `border-radius: 4px 4px 0 0`,
borderStyle: `border-radius: 4px 4px 0 0`, borderStyle: `border-radius: 4px 4px 0 0`,
fillStyle: () => ({ fillStyle: () => ({
background: focusTime.value > 0 ? color : "#7f7f00", background: focusTime.value > 0 ? color : "#7f7f00",
animation: focusTime.value > 0 ? "1s focused-focus-bar linear infinite" : "",
opacity: focusTime.value > 0 ? focusTime.value / 10 : 1, opacity: focusTime.value > 0 ? focusTime.value / 10 : 1,
transition: "none" transition: "none"
}), }),
@ -1216,7 +1293,12 @@ const layer = createLayer(id, () => {
onClick() { onClick() {
focusCooldown.value = Decimal.fromValue(cooldown.value).toNumber(); focusCooldown.value = Decimal.fromValue(cooldown.value).toNumber();
focusTime.value = 10; focusTime.value = 10;
rerollFocusTargets(12, maximumElves.value); rerollFocusTargets(
Object.values(elfTraining).filter(
elf => unref(elf.visibility) === Visibility.Visible
).length,
maximumElves.value
);
} }
})); }));
@ -1257,12 +1339,44 @@ const layer = createLayer(id, () => {
cost: 1e35 cost: 1e35
})); }));
const upgrades = [focusUpgrade1, focusUpgrade2, focusUpgrade3]; const upgrades = [focusUpgrade1, focusUpgrade2, focusUpgrade3];
const focusUpgrade4 = createUpgrade(() => ({
display: {
title: "Focus Improver",
description:
"The bar moves slower when it's closer to the right and faster when it's closer to the left"
},
resource: trees.logs,
visibility: () => showIf(elfTraining.metalElfTraining.milestones[4].earned.value),
cost: 1e40
}));
const focusUpgrade5 = createUpgrade(() => ({
display: {
title: "Focus Focuser",
description: "The bar moves 2x slower"
},
resource: trees.logs,
visibility: () => showIf(elfTraining.metalElfTraining.milestones[4].earned.value),
cost: 1e45
}));
const focusUpgrade6 = createUpgrade(() => ({
display: {
title: "Focus Doubler",
description: "Focus now applies to 6 elves."
},
resource: trees.logs,
visibility: () => showIf(elfTraining.metalElfTraining.milestones[4].earned.value),
cost: 1e50
}));
const upgrades2 = [focusUpgrade4, focusUpgrade5, focusUpgrade6];
// ------------------------------------------------------------------------------- Schools // ------------------------------------------------------------------------------- Schools
const schoolCost = computed(() => { const schoolCost = computed(() => {
const schoolFactor = Decimal.pow(10, schools.amount.value); const schoolFactor = Decimal.pow(10, schools.amount.value);
const nerfedSchoolFactor = Decimal.pow(5, schools.amount.value); const nerfedSchoolFactor = Decimal.pow(4, schools.amount.value);
const woodFactor = Decimal.pow(2e4, Decimal.pow(schools.amount.value, 0.75)); let woodFactor = Decimal.pow(2e4, Decimal.pow(schools.amount.value, 0.75));
if (Decimal.gte(schools.amount.value, 4)) {
woodFactor = woodFactor.div(1e3);
}
const coalFactor = Decimal.pow(2000, schools.amount.value); const coalFactor = Decimal.pow(2000, schools.amount.value);
return { return {
wood: woodFactor.mul(1e21), wood: woodFactor.mul(1e21),
@ -1282,20 +1396,23 @@ const layer = createLayer(id, () => {
<h3>Build a School</h3> <h3>Build a School</h3>
<div> <div>
You gotta start somewhere, right? Each school increases the maximum level for You gotta start somewhere, right? Each school increases the maximum level for
elves by 1, maximum of {main.days[13].opened ? 5 : 3} schools. elves by 1, maximum of {main.days[13].opened.value ? 5 : 3} schools.
</div> </div>
<div> <div>
You have {formatWhole(schools.amount.value)} schools, which are currently You have {formatWhole(schools.amount.value)} schools, which are currently
letting elves learn up to level {formatWhole(schools.amount.value)}. letting elves learn up to level {formatWhole(schools.amount.value)}.
</div> </div>
<div> {Decimal.lt(schools.amount.value, unref(schools.purchaseLimit)) ? (
Costs {format(schoolCost.value.wood)} logs, {format(schoolCost.value.coal)}{" "} <div>
coal, {format(schoolCost.value.paper)} paper, {format(schoolCost.value.boxes)}{" "} Costs {format(schoolCost.value.wood)} logs, {format(schoolCost.value.coal)}{" "}
boxes, {format(schoolCost.value.metalIngots)} metal ingots,{" "} coal, {format(schoolCost.value.paper)} paper,{" "}
{format(schoolCost.value.cloth)} cloth, {format(schoolCost.value.plastic)}{" "} {format(schoolCost.value.boxes)} boxes,{" "}
plastic, and requires {format(schoolCost.value.dye)} of red, yellow, and blue {format(schoolCost.value.metalIngots)} metal ingots,{" "}
dye {format(schoolCost.value.cloth)} cloth, {format(schoolCost.value.plastic)}{" "}
</div> plastic, and requires {format(schoolCost.value.dye)} of red, yellow, and
blue dye
</div>
) : null}
</> </>
)), )),
canPurchase(): boolean { canPurchase(): boolean {
@ -1309,7 +1426,8 @@ const layer = createLayer(id, () => {
schoolCost.value.plastic.lte(plastic.plastic.value) && schoolCost.value.plastic.lte(plastic.plastic.value) &&
schoolCost.value.dye.lte(dyes.dyes.blue.amount.value) && schoolCost.value.dye.lte(dyes.dyes.blue.amount.value) &&
schoolCost.value.dye.lte(dyes.dyes.red.amount.value) && schoolCost.value.dye.lte(dyes.dyes.red.amount.value) &&
schoolCost.value.dye.lte(dyes.dyes.yellow.amount.value) schoolCost.value.dye.lte(dyes.dyes.yellow.amount.value) &&
Decimal.lt(schools.amount.value, unref(schools.purchaseLimit))
); );
}, },
onPurchase() { onPurchase() {
@ -1328,7 +1446,7 @@ const layer = createLayer(id, () => {
}, },
visibility: computed(() => showIf(teaching.bought.value)), visibility: computed(() => showIf(teaching.bought.value)),
style: "width: 600px" style: "width: 600px"
})); })) as GenericBuyable;
const classroomCost = computed(() => { const classroomCost = computed(() => {
const classroomFactor = Decimal.add(classrooms.amount.value, 1).pow(1.5); const classroomFactor = Decimal.add(classrooms.amount.value, 1).pow(1.5);
@ -1341,7 +1459,9 @@ const layer = createLayer(id, () => {
}); });
const classroomEffect = computed(() => { const classroomEffect = computed(() => {
return Decimal.add(classrooms.amount.value, 1).pow(0.9); return Decimal.add(classrooms.amount.value, 1)
.pow(0.9)
.pow(paper.upgrades2.classroomUpgrade.bought.value ? 1.1 : 1);
}); });
const classrooms = createBuyable(() => ({ const classrooms = createBuyable(() => ({
@ -1521,9 +1641,11 @@ const layer = createLayer(id, () => {
schools, schools,
classrooms, classrooms,
classroomUpgrade, classroomUpgrade,
advancedUpgrade,
focusMultiplier: focusMulti, focusMultiplier: focusMulti,
upgrades, upgrades,
upgrades2,
focusTargets, focusTargets,
focusCooldown, focusCooldown,
focusTime, focusTime,
@ -1547,7 +1669,7 @@ const layer = createLayer(id, () => {
{render(dayProgress)} {render(dayProgress)}
<br /> <br />
{renderCol(schools, classrooms)} {renderCol(schools, classrooms)}
{renderGrid([teaching, classroomUpgrade])} {renderGrid([teaching, classroomUpgrade, advancedUpgrade])}
<Spacer /> <Spacer />
{Decimal.gt(schools.amount.value, 0) ? ( {Decimal.gt(schools.amount.value, 0) ? (
<> <>

View file

@ -34,6 +34,7 @@ import dyes from "./dyes";
import management from "./management"; import management from "./management";
import workshop from "./workshop"; import workshop from "./workshop";
import paper from "./paper"; import paper from "./paper";
import { ElfBuyable } from "./elves";
const id = "metal"; const id = "metal";
const day = 7; const day = 7;
@ -94,6 +95,11 @@ const layer = createLayer(id, function (this: BaseLayer) {
description: "Joy Level 4", description: "Joy Level 4",
enabled: management.elfTraining.smallfireElfTraining.milestones[3].earned enabled: management.elfTraining.smallfireElfTraining.milestones[3].earned
})), })),
createMultiplicativeModifier(() => ({
multiplier: () => Decimal.add(management.schools.amount.value, 1),
description: "Twinkle Level 1",
enabled: management.elfTraining.metalElfTraining.milestones[0].earned
})),
createExponentialModifier(() => ({ createExponentialModifier(() => ({
exponent: 1.1, exponent: 1.1,
description: "Mary Level 2", description: "Mary Level 2",
@ -148,6 +154,21 @@ const layer = createLayer(id, function (this: BaseLayer) {
multiplier: () => Decimal.div(management.totalElfExp.value, 1000).add(1).sqrt(), multiplier: () => Decimal.div(management.totalElfExp.value, 1000).add(1).sqrt(),
description: "Mary Level 5", description: "Mary Level 5",
enabled: management.elfTraining.heatedPlanterElfTraining.milestones[4].earned enabled: management.elfTraining.heatedPlanterElfTraining.milestones[4].earned
})),
createMultiplicativeModifier(() => ({
multiplier: () =>
Decimal.pow(1.25, management.elfTraining.metalElfTraining.level.value),
description: "Twinkle Level 2",
enabled: management.elfTraining.metalElfTraining.milestones[1].earned
})),
createMultiplicativeModifier(() => ({
multiplier: () =>
Decimal.add(dyes.dyes.red.amount.value, dyes.dyes.blue.amount.value)
.add(dyes.dyes.yellow.amount.value)
.add(1)
.log10(),
description: "The Ultimate Metal Dye",
enabled: oil.row3Upgrades[4].bought
})) }))
]); ]);
const computedAutoSmeltSpeed = computed(() => autoSmeltSpeed.apply(0)); const computedAutoSmeltSpeed = computed(() => autoSmeltSpeed.apply(0));
@ -159,9 +180,14 @@ const layer = createLayer(id, function (this: BaseLayer) {
})), })),
createMultiplicativeModifier(() => ({ createMultiplicativeModifier(() => ({
multiplier: () => multiplier: () =>
Decimal.add(oil.activeBurner.value, 1).mul(oil.oilEffectiveness.value), Decimal.add(oil.effectiveBurners.value, 1).mul(oil.oilEffectiveness.value),
description: "Blaster Burner", description: "Blaster Burner",
enabled: oil.row2Upgrades[2].bought enabled: oil.row2Upgrades[2].bought
})),
createMultiplicativeModifier(() => ({
multiplier: 3,
description: "Twinkle Level 3",
enabled: management.elfTraining.metalElfTraining.milestones[2].earned
})) }))
]); ]);
const computedAutoSmeltMulti = computed(() => autoSmeltMulti.apply(1)); const computedAutoSmeltMulti = computed(() => autoSmeltMulti.apply(1));
@ -381,7 +407,25 @@ const layer = createLayer(id, function (this: BaseLayer) {
cost() { cost() {
let v = new Decimal(this.amount.value); let v = new Decimal(this.amount.value);
v = Decimal.pow(0.95, paper.books.metalBook.totalAmount.value).times(v); v = Decimal.pow(0.95, paper.books.metalBook.totalAmount.value).times(v);
return Decimal.pow(1.15, v).times(10); let cost = Decimal.pow(1.15, v).times(10);
if (management.elfTraining.clothElfTraining.milestones[4].earned.value) {
cost = Decimal.div(cost, Decimal.add(oil.depth.value, 1).sqrt());
}
if (management.elfTraining.metalElfTraining.milestones[3].earned.value) {
cost = Decimal.div(cost, 10);
}
return cost;
},
inverseCost(x: DecimalSource) {
if (management.elfTraining.metalElfTraining.milestones[3].earned.value) {
x = Decimal.mul(x, 10);
}
if (management.elfTraining.clothElfTraining.milestones[4].earned.value) {
x = Decimal.mul(x, Decimal.add(oil.depth.value, 1).sqrt());
}
let v = Decimal.div(x, 10).log(1.15);
v = v.div(Decimal.pow(0.95, paper.books.metalBook.totalAmount.value));
return Decimal.isNaN(v) ? Decimal.dZero : v.floor().max(0);
}, },
display: { display: {
title: "Metal Drill", title: "Metal Drill",
@ -401,13 +445,31 @@ const layer = createLayer(id, function (this: BaseLayer) {
.gte(10) .gte(10)
), ),
style: { width: "200px" } style: { width: "200px" }
})) as GenericBuyable & { resource: Resource }; })) as ElfBuyable & { resource: Resource };
const industrialCrucible = createBuyable(() => ({ const industrialCrucible = createBuyable(() => ({
resource: noPersist(metal), resource: noPersist(metal),
cost() { cost() {
let v = new Decimal(this.amount.value); let v = new Decimal(this.amount.value);
v = Decimal.pow(0.95, paper.books.metalBook.totalAmount.value).times(v); v = Decimal.pow(0.95, paper.books.metalBook.totalAmount.value).times(v);
return Decimal.pow(1.15, Decimal.times(v, 10)).times(10); let cost = Decimal.pow(1.15, Decimal.times(v, 10)).times(10);
if (management.elfTraining.clothElfTraining.milestones[4].earned.value) {
cost = Decimal.div(cost, Decimal.add(oil.depth.value, 1).sqrt());
}
if (management.elfTraining.metalElfTraining.milestones[3].earned.value) {
cost = Decimal.div(cost, 10);
}
return cost;
},
inverseCost(x: DecimalSource) {
if (management.elfTraining.metalElfTraining.milestones[3].earned.value) {
x = Decimal.mul(x, 10);
}
if (management.elfTraining.clothElfTraining.milestones[4].earned.value) {
x = Decimal.mul(x, Decimal.add(oil.depth.value, 1).sqrt());
}
let v = Decimal.div(x, 10).log(1.15).div(10);
v = v.div(Decimal.pow(0.95, paper.books.metalBook.totalAmount.value));
return Decimal.isNaN(v) ? Decimal.dZero : v.floor().max(0);
}, },
display: { display: {
title: "Industrial Crucible", title: "Industrial Crucible",
@ -426,14 +488,32 @@ const layer = createLayer(id, function (this: BaseLayer) {
Decimal.gte(bestOre.value, 50) Decimal.gte(bestOre.value, 50)
), ),
style: { width: "200px" } style: { width: "200px" }
})) as GenericBuyable & { resource: Resource }; })) as ElfBuyable & { resource: Resource };
const autoSmeltEnabled = persistent<boolean>(true); const autoSmeltEnabled = persistent<boolean>(true);
const hotterForge = createBuyable(() => ({ const hotterForge = createBuyable(() => ({
resource: coal.coal, resource: coal.coal,
cost() { cost() {
let v = new Decimal(this.amount.value); let v = new Decimal(this.amount.value);
v = Decimal.pow(0.95, paper.books.metalBook.totalAmount.value).times(v); v = Decimal.pow(0.95, paper.books.metalBook.totalAmount.value).times(v);
return Decimal.pow(10, v).times(1e12); let cost = Decimal.pow(10, v).times(1e12);
if (management.elfTraining.clothElfTraining.milestones[4].earned.value) {
cost = Decimal.div(cost, Decimal.add(oil.depth.value, 1).sqrt());
}
if (management.elfTraining.metalElfTraining.milestones[3].earned.value) {
cost = Decimal.div(cost, 10);
}
return cost;
},
inverseCost(x: DecimalSource) {
if (management.elfTraining.metalElfTraining.milestones[3].earned.value) {
x = Decimal.mul(x, 10);
}
if (management.elfTraining.clothElfTraining.milestones[4].earned.value) {
x = Decimal.mul(x, Decimal.add(oil.depth.value, 1).sqrt());
}
let v = Decimal.div(x, 1e12).log(10);
v = v.div(Decimal.pow(0.95, paper.books.metalBook.totalAmount.value));
return Decimal.isNaN(v) ? Decimal.dZero : v.floor().max(0);
}, },
display: { display: {
title: "Hotter Forges", title: "Hotter Forges",
@ -449,7 +529,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
visibility: () => visibility: () =>
showIf(Decimal.gte(hotterForge.amount.value, 1) || industrialFurnace.bought.value), showIf(Decimal.gte(hotterForge.amount.value, 1) || industrialFurnace.bought.value),
style: { width: "200px" } style: { width: "200px" }
})) as GenericBuyable & { resource: Resource }; })) as ElfBuyable & { resource: Resource };
const hotterForgeEffect = computed(() => Decimal.times(hotterForge.amount.value, 0.25)); const hotterForgeEffect = computed(() => Decimal.times(hotterForge.amount.value, 0.25));
globalBus.on("update", diff => { globalBus.on("update", diff => {

View file

@ -24,19 +24,22 @@ import metal from "./metal";
import { import {
createSequentialModifier, createSequentialModifier,
createAdditiveModifier, createAdditiveModifier,
createMultiplicativeModifier createMultiplicativeModifier,
Modifier
} from "game/modifiers"; } from "game/modifiers";
import { main } from "data/projEntry"; import { main } from "data/projEntry";
import { globalBus } from "game/events"; import { globalBus } from "game/events";
import coal from "./coal"; import coal from "./coal";
import { createUpgrade, GenericUpgrade } from "features/upgrades/upgrade"; import { createUpgrade, GenericUpgrade } from "features/upgrades/upgrade";
import { createMilestone, GenericMilestone } from "features/milestones/milestone"; import { createMilestone, GenericMilestone } from "features/milestones/milestone";
import { formatGain } from "util/bignum"; import { formatGain, formatSmall } from "util/bignum";
import plastic from "./plastic"; import plastic from "./plastic";
import paper from "./paper"; import paper from "./paper";
import dyes from "./dyes"; import dyes from "./dyes";
import management from "./management"; import management from "./management";
import workshop from "./workshop"; import workshop from "./workshop";
import { WithRequired } from "util/common";
import { ElfBuyable } from "./elves";
const id = "oil"; const id = "oil";
const day = 9; const day = 9;
@ -84,7 +87,12 @@ const layer = createLayer(id, function (this: BaseLayer) {
const activeHeavy = persistent<DecimalSource>(0); const activeHeavy = persistent<DecimalSource>(0);
const heavyCoal = computed(() => const heavyCoal = computed(() =>
Decimal.times(Decimal.pow(activeHeavy.value, heavy2Power.value).pow(2), 1e14) Decimal.times(
Decimal.pow(activeHeavy.value, heavy2Power.value).pow(
management.elfTraining.coalDrillElfTraining.milestones[0].earned.value ? 2.5 : 2
),
1e14
)
); );
const heavyPower = computed(() => const heavyPower = computed(() =>
Decimal.times(Decimal.pow(activeHeavy.value, heavy2Power.value), 1) Decimal.times(Decimal.pow(activeHeavy.value, heavy2Power.value), 1)
@ -93,17 +101,29 @@ const layer = createLayer(id, function (this: BaseLayer) {
resource: metal.metal, resource: metal.metal,
cost() { cost() {
let v = new Decimal(this.amount.value); let v = new Decimal(this.amount.value);
if (Decimal.gte(v, 100)) v = Decimal.pow(v, 4).div(100**3);
v = Decimal.pow(0.95, paper.books.heavyDrillBook.totalAmount.value).times(v); v = Decimal.pow(0.95, paper.books.heavyDrillBook.totalAmount.value).times(v);
return Decimal.pow(1.3, v).times(2.5e4); return Decimal.pow(1.3, v).times(2.5e4);
}, },
inverseCost(x: DecimalSource) {
let v = Decimal.div(x, 2.5e4).log(1.3);
v = v.div(Decimal.pow(0.95, paper.books.heavyDrillBook.totalAmount.value));
if (Decimal.gte(v, 100)) v = Decimal.mul(v, 100**3).root(4);
return Decimal.isNaN(v) ? Decimal.dZero : v.floor().max(0);
},
display: jsx(() => ( display: jsx(() => (
<> <>
<h3>Heavy Drill</h3> <h3>Heavy Drill</h3>
<br /> <br />
A large drill specialized at deep mining. A large drill specialized at deep mining.
<br /> <br />
Consumes 1e14*(Heavy Drills amount)<sup>2</sup> coal/sec for (Heavy Drills amount) Consumes 1e14*(Heavy Drills amount)
drill power. <sup>
{management.elfTraining.coalDrillElfTraining.milestones[0].earned.value
? 2.5
: 2}
</sup>{" "}
coal/sec for (Heavy Drills amount) drill power.
<br /> <br />
<br /> <br />
Currently: Currently:
@ -121,7 +141,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
color: colorText, color: colorText,
width: "160px" width: "160px"
} }
})) as GenericBuyable & { resource: Resource }; })) as ElfBuyable & { resource: Resource };
const { const {
min: minHeavy, min: minHeavy,
max: maxHeavy, max: maxHeavy,
@ -132,21 +152,44 @@ const layer = createLayer(id, function (this: BaseLayer) {
active: activeHeavy active: activeHeavy
}); });
const activeHeavy2 = persistent<DecimalSource>(0); const activeHeavy2 = persistent<DecimalSource>(0);
const heavy2Power = computed(() => Decimal.add(activeHeavy2.value, Math.E).ln()); const heavy2Power = computed(() => {
let power = Decimal.add(activeHeavy2.value, Math.E);
if (management.elfTraining.heavyDrillElfTraining.milestones[3].earned.value) {
power = power.log(2.5);
} else {
power = power.ln();
}
return power;
});
const buildHeavy2 = createBuyable(() => ({ const buildHeavy2 = createBuyable(() => ({
resource: metal.metal, resource: metal.metal,
cost() { cost() {
let v = new Decimal(this.amount.value); let v = new Decimal(this.amount.value);
if (Decimal.gte(v, 50)) v = Decimal.pow(v, 4).div(50**3);
v = Decimal.pow(0.95, paper.books.heavyDrillBook.totalAmount.value).times(v); v = Decimal.pow(0.95, paper.books.heavyDrillBook.totalAmount.value).times(v);
return Decimal.pow(2, v).times(1e5); return Decimal.pow(2, v).times(1e5);
}, },
inverseCost(x: DecimalSource) {
let v = Decimal.div(x, 1e5).log(2);
v = v.div(Decimal.pow(0.95, paper.books.heavyDrillBook.totalAmount.value));
if (Decimal.gte(v, 50)) v = Decimal.mul(v, 50**3).root(4);
return Decimal.isNaN(v) ? Decimal.dZero : v.floor().max(0);
},
display: jsx(() => ( display: jsx(() => (
<> <>
<h3>Heavy Drill Drill</h3> <h3>Heavy Drill Drill</h3>
<br /> <br />
Attach extra drills to Heavy Drills to make them faster Attach extra drills to Heavy Drills to make them faster
<br /> <br />
Raise amount of effective Heavy Drills by ^ln(Heavy Drill Drill amount + e). Raise amount of effective Heavy Drills by ^
{management.elfTraining.heavyDrillElfTraining.milestones[3].earned.value ? (
<>
log<sub>2.5</sub>
</>
) : (
<>ln</>
)}
(Heavy Drill Drill amount + e).
<br /> <br />
(also affects coal consumption). (also affects coal consumption).
<br /> <br />
@ -165,7 +208,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
color: colorText, color: colorText,
width: "160px" width: "160px"
} }
})) as GenericBuyable & { resource: Resource }; })) as ElfBuyable & { resource: Resource };
const { const {
min: minHeavy2, min: minHeavy2,
max: maxHeavy2, max: maxHeavy2,
@ -184,9 +227,16 @@ const layer = createLayer(id, function (this: BaseLayer) {
resource: metal.metal, resource: metal.metal,
cost() { cost() {
let v = new Decimal(this.amount.value); let v = new Decimal(this.amount.value);
if (Decimal.gte(v, 10)) v = Decimal.pow(v, 4).div(10**3);
v = Decimal.pow(0.95, paper.books.heavyDrillBook.totalAmount.value).times(v); v = Decimal.pow(0.95, paper.books.heavyDrillBook.totalAmount.value).times(v);
return Decimal.pow(8, v).times(2e5); return Decimal.pow(8, v).times(2e5);
}, },
inverseCost(x: DecimalSource) {
let v = Decimal.div(x, 2e5).log(8);
v = v.div(Decimal.pow(0.95, paper.books.heavyDrillBook.totalAmount.value));
if (Decimal.gte(v, 10)) v = Decimal.mul(v, 10**3).root(4);
return Decimal.isNaN(v) ? Decimal.dZero : v.floor().max(0);
},
display: jsx(() => ( display: jsx(() => (
<> <>
<h3>Heavy Extractor</h3> <h3>Heavy Extractor</h3>
@ -197,7 +247,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
<br /> <br />
<br /> <br />
Currently: Currently:
<br />×{format(extractorPower.value)} drill power <br />×{formatSmall(extractorPower.value)} drill power
<br />×{format(extractorCoal.value)} coal/sec <br />×{format(extractorCoal.value)} coal/sec
<br />×{format(extractorOre.value)} ore/sec <br />×{format(extractorOre.value)} ore/sec
<br /> <br />
@ -213,7 +263,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
color: colorText, color: colorText,
width: "160px" width: "160px"
} }
})) as GenericBuyable & { resource: Resource }; })) as ElfBuyable & { resource: Resource };
const { const {
min: minExtractor, min: minExtractor,
max: maxExtractor, max: maxExtractor,
@ -234,19 +284,41 @@ const layer = createLayer(id, function (this: BaseLayer) {
.mul(activeHeavy.value) .mul(activeHeavy.value)
.mul(Decimal.add(activeHeavy2.value, 1)) .mul(Decimal.add(activeHeavy2.value, 1))
.mul(activeExtractor.value) .mul(activeExtractor.value)
.mul(depth.value) .mul(
Decimal.pow(
depth.value,
management.elfTraining.oilElfTraining.milestones[0].earned.value ? 1.2 : 1
)
)
.div(1e5) .div(1e5)
); );
const buildPump = createBuyable(() => ({ const buildPump = createBuyable(() => ({
resource: metal.metal, resource: metal.metal,
cost() { cost() {
let v = new Decimal(this.amount.value); let v = new Decimal(this.amount.value);
if (Decimal.gte(v, 100)) v = Decimal.pow(v, 4).div(100);
v = Decimal.pow(0.95, paper.books.oilBook.totalAmount.value).times(v); v = Decimal.pow(0.95, paper.books.oilBook.totalAmount.value).times(v);
let price = Decimal.pow(16, v).times(2e6); let price = Decimal.pow(16, v).times(2e6);
if (row2Upgrades[4].bought.value) if (row2Upgrades[4].bought.value) {
price = price.div(Decimal.add(totalOil.value, 1).root(6)); price = price.div(Decimal.add(totalOil.value, 1).root(6));
}
if (management.elfTraining.heavyDrillElfTraining.milestones[1].earned.value) {
price = price.div(10);
}
return price; return price;
}, },
inverseCost(x: DecimalSource) {
if (management.elfTraining.heavyDrillElfTraining.milestones[1].earned.value) {
x = Decimal.mul(x, 10);
}
if (row2Upgrades[4].bought.value) {
x = Decimal.mul(x, Decimal.add(totalOil.value, 1).root(6));
}
let v = Decimal.div(x, 2e6).log(16);
v = v.div(Decimal.pow(0.95, paper.books.heavyDrillBook.totalAmount.value));
if (Decimal.gte(v, 100)) v = Decimal.mul(v, 100).root(4);
return Decimal.isNaN(v) ? Decimal.dZero : v.floor().max(0);
},
display: jsx(() => ( display: jsx(() => (
<> <>
<h3>Oil Pump</h3> <h3>Oil Pump</h3>
@ -272,7 +344,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
color: colorText, color: colorText,
width: "160px" width: "160px"
} }
})) as GenericBuyable & { resource: Resource }; })) as ElfBuyable & { resource: Resource };
const { const {
max: maxPump, max: maxPump,
min: minPump, min: minPump,
@ -284,16 +356,30 @@ const layer = createLayer(id, function (this: BaseLayer) {
}); });
const activeBurner = persistent<DecimalSource>(0); const activeBurner = persistent<DecimalSource>(0);
const burnerOil = computed(() => Decimal.pow(activeBurner.value, 2)); const effectiveBurners = computed(() => {
const burnerCoal = computed(() => Decimal.pow(activeBurner.value, 3).mul(1e19)); let burners = activeBurner.value;
const burnerMetal = computed(() => Decimal.add(activeBurner.value, 1)); if (management.elfTraining.heavyDrillElfTraining.milestones[2].earned.value) {
burners = Decimal.pow(burners, 1.5);
}
return burners;
});
const burnerOil = computed(() => Decimal.pow(effectiveBurners.value, 2));
const burnerCoal = computed(() => Decimal.pow(effectiveBurners.value, 3).mul(1e19));
const burnerMetal = computed(() => Decimal.add(effectiveBurners.value, 1));
const buildBurner = createBuyable(() => ({ const buildBurner = createBuyable(() => ({
resource: noPersist(oil), resource: noPersist(oil),
cost() { cost() {
let v = new Decimal(this.amount.value); let v = new Decimal(this.amount.value);
if (Decimal.gte(v, 100)) v = Decimal.pow(v, 4).div(100);
v = Decimal.pow(0.95, paper.books.oilBook.totalAmount.value).times(v); v = Decimal.pow(0.95, paper.books.oilBook.totalAmount.value).times(v);
return Decimal.pow(2, v).times(50); return Decimal.pow(2, v).times(50);
}, },
inverseCost(x: DecimalSource) {
let v = Decimal.div(x, 50).log(2);
v = v.div(Decimal.pow(0.95, paper.books.oilBook.totalAmount.value));
if (Decimal.gte(v, 100)) v = Decimal.mul(v, 100).root(4);
return Decimal.isNaN(v) ? Decimal.dZero : v.floor().max(0);
},
display: jsx(() => ( display: jsx(() => (
<> <>
<h3>Oil Burner</h3> <h3>Oil Burner</h3>
@ -326,7 +412,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
color: colorText, color: colorText,
width: "160px" width: "160px"
} }
})) as GenericBuyable & { resource: Resource }; })) as ElfBuyable & { resource: Resource };
const { const {
max: maxBurner, max: maxBurner,
min: minBurner, min: minBurner,
@ -344,12 +430,24 @@ const layer = createLayer(id, function (this: BaseLayer) {
resource: metal.metal, resource: metal.metal,
cost() { cost() {
let v = new Decimal(this.amount.value); let v = new Decimal(this.amount.value);
if (Decimal.gte(v, 50)) v = Decimal.pow(v, 2).div(50);
if (Decimal.gte(v, 200)) v = Decimal.pow(v, 2).div(200);
if (Decimal.gte(v, 1e4)) v = Decimal.pow(v, 2).div(1e4);
v = Decimal.pow(0.95, paper.books.oilBook.totalAmount.value).times(v); v = Decimal.pow(0.95, paper.books.oilBook.totalAmount.value).times(v);
let price = Decimal.pow(10, v).times(1e7); let price = Decimal.pow(10, v).times(1e7);
if (row2Upgrades[4].bought.value) if (row2Upgrades[4].bought.value)
price = price.div(Decimal.add(totalOil.value, 1).root(6)); price = price.div(Decimal.add(totalOil.value, 1).root(6));
return price; return price;
}, },
inverseCost(x: DecimalSource) {
if (row2Upgrades[4].bought.value) {
x = Decimal.mul(x, Decimal.add(totalOil.value, 1).root(6));
}
let v = Decimal.div(x, 1e7).log(10);
v = v.div(Decimal.pow(0.95, paper.books.oilBook.totalAmount.value));
if (Decimal.gte(v, 100)) v = Decimal.mul(v, 100).root(4);
return Decimal.isNaN(v) ? Decimal.dZero : v.floor().max(0);
},
display: jsx(() => ( display: jsx(() => (
<> <>
<h3>Oil Smelter</h3> <h3>Oil Smelter</h3>
@ -374,7 +472,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
color: colorText, color: colorText,
width: "160px" width: "160px"
} }
})) as GenericBuyable & { resource: Resource }; })) as ElfBuyable & { resource: Resource };
const { const {
max: maxSmelter, max: maxSmelter,
@ -601,7 +699,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
cost: 1500, cost: 1500,
display: { display: {
title: "Blaster Burner", title: "Blaster Burner",
description: "The Oil Burner can now increase your metal gain." description: "The Oil Burner can now increase your auto smelting multi."
}, },
style: { color: colorText } style: { color: colorText }
})), })),
@ -629,7 +727,63 @@ const layer = createLayer(id, function (this: BaseLayer) {
style: { color: colorText } style: { color: colorText }
})) }))
]; ];
const row3Upgrades = [
createUpgrade(() => ({
resource: noPersist(oil),
cost: 1e11,
display: {
title: "Dye Synergy I",
description: "Red dye boosts yellow dye gain *(log(x)^0.75)"
},
visibility: () =>
showIf(management.elfTraining.oilElfTraining.milestones[4].earned.value),
style: { color: colorText }
})),
createUpgrade(() => ({
resource: noPersist(oil),
cost: 1e12,
display: {
title: "Orange-colored boxes",
description: "Orange dye's 2nd effect is raised to the 2.5"
},
visibility: () =>
showIf(management.elfTraining.oilElfTraining.milestones[4].earned.value),
style: { color: colorText }
})),
createUpgrade(() => ({
resource: noPersist(oil),
cost: 1e13,
display: {
title: "Colorful Focus",
description: "Sum of secondary dyes increases max focus multiplier by cbrt(x)"
},
visibility: () =>
showIf(management.elfTraining.oilElfTraining.milestones[4].earned.value),
style: { color: colorText }
})),
createUpgrade(() => ({
resource: noPersist(oil),
cost: 1e14,
display: {
title: "Dye Synergy II",
description: "Blue dye boosts red dye gain *log(x)"
},
visibility: () =>
showIf(management.elfTraining.oilElfTraining.milestones[4].earned.value),
style: { color: colorText }
})),
createUpgrade(() => ({
resource: noPersist(oil),
cost: 1e15,
display: {
title: "The Ultimate Metal Dye",
description: "Sum of primary dyes boosts auto smelt speed"
},
visibility: () =>
showIf(management.elfTraining.oilElfTraining.milestones[4].earned.value),
style: { color: colorText }
}))
];
const coalConsumption = createSequentialModifier(() => [ const coalConsumption = createSequentialModifier(() => [
createAdditiveModifier(() => ({ createAdditiveModifier(() => ({
addend: () => Decimal.negate(heavyCoal.value), addend: () => Decimal.negate(heavyCoal.value),
@ -684,6 +838,16 @@ const layer = createLayer(id, function (this: BaseLayer) {
description: "Guide to drilling", description: "Guide to drilling",
enabled: paper.upgrades.drillingUpgrade.bought enabled: paper.upgrades.drillingUpgrade.bought
})), })),
createMultiplicativeModifier(() => ({
multiplier: () => Decimal.add(totalOil.value, 1).log10().add(1),
description: "Cocoa Level 2",
enabled: management.elfTraining.oilElfTraining.milestones[1].earned
})),
createMultiplicativeModifier(() => ({
multiplier: 2,
description: "Cocoa Level 3",
enabled: management.elfTraining.oilElfTraining.milestones[2].earned
})),
createMultiplicativeModifier(() => ({ createMultiplicativeModifier(() => ({
multiplier: () => coalEffectiveness.value, multiplier: () => coalEffectiveness.value,
description: "Effectiveness", description: "Effectiveness",
@ -742,8 +906,13 @@ const layer = createLayer(id, function (this: BaseLayer) {
multiplier: () => Decimal.add(buildHeavy2.amount.value, 1).sqrt(), multiplier: () => Decimal.add(buildHeavy2.amount.value, 1).sqrt(),
description: "Faith Level 4", description: "Faith Level 4",
enabled: management.elfTraining.bonfireElfTraining.milestones[3].earned enabled: management.elfTraining.bonfireElfTraining.milestones[3].earned
})),
createMultiplicativeModifier(() => ({
multiplier: 2,
description: "Cocoa Level 3",
enabled: management.elfTraining.oilElfTraining.milestones[2].earned
})) }))
]); ]) as WithRequired<Modifier, "description" | "revert">;
const computedOilSpeed = computed(() => oilSpeed.apply(0)); const computedOilSpeed = computed(() => oilSpeed.apply(0));
const oilConsumption = createSequentialModifier(() => [ const oilConsumption = createSequentialModifier(() => [
@ -923,6 +1092,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
activePump, activePump,
buildPump, buildPump,
activeBurner, activeBurner,
effectiveBurners,
buildBurner, buildBurner,
activeSmelter, activeSmelter,
buildSmelter, buildSmelter,
@ -938,6 +1108,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
row1Upgrades, row1Upgrades,
row2Upgrades, row2Upgrades,
row3Upgrades,
minWidth: 700, minWidth: 700,
@ -954,6 +1125,9 @@ const layer = createLayer(id, function (this: BaseLayer) {
if (oilMilestones[1].earned.value) { if (oilMilestones[1].earned.value) {
upgrades.push(row2Upgrades); upgrades.push(row2Upgrades);
} }
if (management.elfTraining.oilElfTraining.milestones[4].earned.value) {
upgrades.push(row3Upgrades);
}
return ( return (
<> <>
{render(trackerDisplay)} {render(trackerDisplay)}

View file

@ -12,18 +12,18 @@ import { createCumulativeConversion, createPolynomialScaling } from "features/co
import { jsx, showIf } from "features/feature"; import { jsx, showIf } from "features/feature";
import MainDisplay from "features/resources/MainDisplay.vue"; import MainDisplay from "features/resources/MainDisplay.vue";
import { createResource, displayResource, Resource } from "features/resources/resource"; import { createResource, displayResource, Resource } from "features/resources/resource";
import { createUpgrade } from "features/upgrades/upgrade"; import { createUpgrade, GenericUpgrade } from "features/upgrades/upgrade";
import { globalBus } from "game/events"; import { globalBus } from "game/events";
import { BaseLayer, createLayer } from "game/layers"; import { BaseLayer, createLayer } from "game/layers";
import { createMultiplicativeModifier, createSequentialModifier, Modifier } from "game/modifiers"; import { createMultiplicativeModifier, createSequentialModifier, Modifier } from "game/modifiers";
import { noPersist } from "game/persistence"; import { noPersist } from "game/persistence";
import Decimal, { DecimalSource, format, formatWhole } from "util/bignum"; import Decimal, { DecimalSource, format, formatSmall, formatWhole } from "util/bignum";
import { WithRequired } from "util/common"; import { WithRequired } from "util/common";
import { render, renderCol, renderRow } from "util/vue"; import { render, renderCol, renderRow } from "util/vue";
import { computed, ComputedRef, ref, unref } from "vue"; import { computed, ComputedRef, ref, unref } from "vue";
import cloth from "./cloth"; import cloth from "./cloth";
import coal from "./coal"; import coal from "./coal";
import elves from "./elves"; import elves, { ElfBuyable } from "./elves";
import plastic from "./plastic"; import plastic from "./plastic";
import trees from "./trees"; import trees from "./trees";
import dyes from "./dyes"; import dyes from "./dyes";
@ -104,7 +104,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
description: `Print a copy of "${options.name}", which ${options.elfName} will use to improve their skills! Each copy printed will reduce the "${options.buyableName}" price scaling by 0.95x and make ${options.elfName} purchase +10% faster!`, description: `Print a copy of "${options.name}", which ${options.elfName} will use to improve their skills! Each copy printed will reduce the "${options.buyableName}" price scaling by 0.95x and make ${options.elfName} purchase +10% faster!`,
effectDisplay: jsx(() => ( effectDisplay: jsx(() => (
<> <>
{format(Decimal.pow(0.95, buyable.totalAmount.value))}x price scaling,{" "} {formatSmall(Decimal.pow(0.95, buyable.totalAmount.value))}x price scaling,{" "}
{format(Decimal.div(buyable.totalAmount.value, 10).add(1))}x auto-purchase {format(Decimal.div(buyable.totalAmount.value, 10).add(1))}x auto-purchase
speed speed
</> </>
@ -113,21 +113,49 @@ const layer = createLayer(id, function (this: BaseLayer) {
}, },
resource: noPersist(paper), resource: noPersist(paper),
cost() { cost() {
let v = this.amount.value; let v = buyable.amount.value;
if (options.elfName === "Star" && Decimal.gte(v, 10))
v = Decimal.pow(10, Decimal.div(v, 10));
if (options.elfName === "Star" || options.elfName === "Bell") v = Decimal.pow(v, 2); if (options.elfName === "Star" || options.elfName === "Bell") v = Decimal.pow(v, 2);
if (Decimal.gte(v, 100)) v = Decimal.pow(v, 2).div(100); if (Decimal.gte(v, 100)) v = Decimal.pow(v, 2).div(100);
if (Decimal.gte(v, 10000)) v = Decimal.pow(v, 2).div(10000); if (Decimal.gte(v, 10000)) v = Decimal.pow(v, 2).div(10000);
v = Decimal.pow(0.95, paperBook.totalAmount.value).times(v); v = Decimal.pow(0.95, paperBook.totalAmount.value).times(v);
let scaling = 5; let scaling = 5;
if (management.elfTraining.paperElfTraining.milestones[0].earned.value) { if (management.elfTraining.paperElfTraining.milestones[2].earned.value) {
scaling--; scaling--;
} }
let cost = Decimal.pow(scaling, v).times(10); let cost = Decimal.pow(scaling, v).times(10);
if (management.elfTraining.paperElfTraining.milestones[0].earned.value) { if (management.elfTraining.paperElfTraining.milestones[0].earned.value) {
cost = Decimal.div(cost, sumBooks.value.max(1)); cost = Decimal.div(cost, sumBooks.value.max(1));
} }
if (bookUpgrade.bought.value) {
cost = cost.div(10);
}
return cost; return cost;
}, },
inverseCost(x: DecimalSource) {
if (bookUpgrade.bought.value) {
x = Decimal.mul(x, 10);
}
if (management.elfTraining.paperElfTraining.milestones[0].earned.value) {
x = Decimal.mul(x, sumBooks.value.max(1));
}
let scaling = 5;
if (management.elfTraining.paperElfTraining.milestones[2].earned.value) {
scaling--;
}
let v = Decimal.div(x, 10).log(scaling);
v = v.div(Decimal.pow(0.95, paperBook.totalAmount.value));
if (Decimal.gte(v, 10000)) v = Decimal.mul(v, 10000).root(2);
if (Decimal.gte(v, 100)) v = Decimal.mul(v, 100).root(2);
if (options.elfName === "Star" || options.elfName === "Bell")
v = Decimal.root(v, 2);
if (options.elfName === "Star" && Decimal.gte(v, 10)) v = v.log10().mul(10);
return Decimal.isNaN(v) ? Decimal.dZero : v.floor().max(0);
},
style: "width: 600px", style: "width: 600px",
freeLevels: computed(() => freeLevels: computed(() =>
management.elfTraining.paperElfTraining.milestones[4].earned.value management.elfTraining.paperElfTraining.milestones[4].earned.value
@ -135,7 +163,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
: 0 : 0
), ),
totalAmount: computed(() => Decimal.add(buyable.amount.value, buyable.freeLevels.value)) totalAmount: computed(() => Decimal.add(buyable.amount.value, buyable.freeLevels.value))
})) as GenericBuyable & { })) as ElfBuyable & {
resource: Resource; resource: Resource;
freeLevels: ComputedRef<DecimalSource>; freeLevels: ComputedRef<DecimalSource>;
totalAmount: ComputedRef<DecimalSource>; totalAmount: ComputedRef<DecimalSource>;
@ -294,7 +322,37 @@ const layer = createLayer(id, function (this: BaseLayer) {
} }
})); }));
const upgrades = { clothUpgrade, drillingUpgrade, oilUpgrade }; const upgrades = { clothUpgrade, drillingUpgrade, oilUpgrade };
const ashUpgrade = createUpgrade(() => ({
resource: noPersist(paper),
cost: 1e36,
visibility: () =>
showIf(management.elfTraining.heavyDrillElfTraining.milestones[4].earned.value),
display: {
title: "Paper Burning",
description: "Paper adds to ash gain after all other modifiers"
}
})) as GenericUpgrade;
const bookUpgrade = createUpgrade(() => ({
resource: noPersist(paper),
cost: 1e40,
visibility: () =>
showIf(management.elfTraining.heavyDrillElfTraining.milestones[4].earned.value),
display: {
title: "Book Cheapener",
description: "Books are less expensive"
}
}));
const classroomUpgrade = createUpgrade(() => ({
resource: noPersist(paper),
cost: 1e44,
visibility: () =>
showIf(management.elfTraining.heavyDrillElfTraining.milestones[4].earned.value),
display: {
title: "Classroom Supplies",
description: "Classrooms' effect is raised to the 1.1"
}
}));
const upgrades2 = { ashUpgrade, bookUpgrade, classroomUpgrade };
const paperGain = createSequentialModifier(() => [ const paperGain = createSequentialModifier(() => [
createMultiplicativeModifier(() => ({ createMultiplicativeModifier(() => ({
multiplier: 2, multiplier: 2,
@ -338,7 +396,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
description: "Star Level 2", description: "Star Level 2",
enabled: management.elfTraining.paperElfTraining.milestones[1].earned enabled: management.elfTraining.paperElfTraining.milestones[1].earned
})) }))
]); ]) as WithRequired<Modifier, "description" | "revert">;
const computedAshCost = computed(() => ashCost.apply(1e6)); const computedAshCost = computed(() => ashCost.apply(1e6));
const [generalTab, generalTabCollapsed] = createCollapsibleModifierSections(() => [ const [generalTab, generalTabCollapsed] = createCollapsibleModifierSections(() => [
@ -399,6 +457,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
paperConversion, paperConversion,
books, books,
upgrades, upgrades,
upgrades2,
generalTabCollapsed, generalTabCollapsed,
minWidth: 700, minWidth: 700,
display: jsx(() => ( display: jsx(() => (

View file

@ -27,7 +27,7 @@ import {
import { noPersist, persistent } from "game/persistence"; import { noPersist, persistent } from "game/persistence";
import Decimal, { DecimalSource, format, formatWhole } from "util/bignum"; import Decimal, { DecimalSource, format, formatWhole } from "util/bignum";
import { render, renderCol, renderRow } from "util/vue"; import { render, renderCol, renderRow } from "util/vue";
import { computed, ref, unref } from "vue"; import { computed, ComputedRef, ref, unref } from "vue";
import boxes from "./boxes"; import boxes from "./boxes";
import metal from "./metal"; import metal from "./metal";
import oil from "./oil"; import oil from "./oil";
@ -63,7 +63,11 @@ const layer = createLayer(id, function (this: BaseLayer) {
)); ));
const activeRefinery = persistent<DecimalSource>(0); const activeRefinery = persistent<DecimalSource>(0);
const oilCost = computed(() => Decimal.times(activeRefinery.value, 100)); const oilCost = computed(() =>
Decimal.times(activeRefinery.value, 100).times(
management.elfTraining.oilElfTraining.milestones[3].earned.value ? 5 : 1
)
) as ComputedRef<DecimalSource>;
const buildRefinery = createBuyable(() => ({ const buildRefinery = createBuyable(() => ({
resource: metal.metal, resource: metal.metal,
cost() { cost() {
@ -230,7 +234,10 @@ const layer = createLayer(id, function (this: BaseLayer) {
const plasticGain = createSequentialModifier(() => [ const plasticGain = createSequentialModifier(() => [
createAdditiveModifier(() => ({ createAdditiveModifier(() => ({
addend: activeRefinery, addend: () =>
management.elfTraining.oilElfTraining.milestones[3].earned.value
? Decimal.times(activeRefinery.value, 5)
: activeRefinery.value,
description: "Oil Refinery", description: "Oil Refinery",
enabled: () => Decimal.gt(activeRefinery.value, 0) enabled: () => Decimal.gt(activeRefinery.value, 0)
})), })),
@ -271,7 +278,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
enabled: workshop.milestones.extraExpansionMilestone4.earned enabled: workshop.milestones.extraExpansionMilestone4.earned
})), })),
createMultiplicativeModifier(() => ({ createMultiplicativeModifier(() => ({
multiplier: () => Decimal.add(oil.buildExtractor.amount.value, 1).sqrt(), multiplier: () => Decimal.add(oil.buildExtractor.amount.value, 1),
description: "Snowball Level 4", description: "Snowball Level 4",
enabled: management.elfTraining.kilnElfTraining.milestones[3].earned enabled: management.elfTraining.kilnElfTraining.milestones[3].earned
})) }))

View file

@ -0,0 +1,21 @@
@keyframes focused-focus-bar {
from {
background: 0 0 / 28px 28px repeat
repeating-linear-gradient(-45deg, red, red 10px, green 10px, green 20px);
}
to {
background: 28px 0px / 28px 28px repeat
repeating-linear-gradient(-45deg, red, red 10px, green 10px, green 20px);
}
}
@keyframes focused-xp-bar {
from {
background: 0 0 / 28px 28px repeat
repeating-linear-gradient(-45deg, yellow, yellow 10px, lime 10px, lime 20px);
}
to {
background: 28px 0px / 28px 28px repeat
repeating-linear-gradient(-45deg, yellow, yellow 10px, lime 10px, lime 20px);
}
}

View file

@ -27,12 +27,12 @@ import { noPersist, persistent } from "game/persistence";
import Decimal, { DecimalSource, format, formatGain, formatLimit, formatWhole } from "util/bignum"; import Decimal, { DecimalSource, format, formatGain, formatLimit, formatWhole } from "util/bignum";
import { Direction, WithRequired } from "util/common"; import { Direction, WithRequired } from "util/common";
import { render, renderGrid, renderRow } from "util/vue"; import { render, renderGrid, renderRow } from "util/vue";
import { computed, ref, watch } from "vue"; import { computed, ref } from "vue";
import boxes from "./boxes"; import boxes from "./boxes";
import cloth from "./cloth"; import cloth from "./cloth";
import coal from "./coal"; import coal from "./coal";
import dyes from "./dyes"; import dyes from "./dyes";
import elves from "./elves"; import elves, { ElfBuyable } from "./elves";
import management from "./management"; import management from "./management";
import paper from "./paper"; import paper from "./paper";
import workshop from "./workshop"; import workshop from "./workshop";
@ -54,6 +54,9 @@ const layer = createLayer(id, function (this: BaseLayer) {
const ema = ref<DecimalSource>(0); const ema = ref<DecimalSource>(0);
const lastAutoCuttingAmount = ref<DecimalSource>(0);
const lastAutoPlantedAmount = ref<DecimalSource>(0);
const totalTrees = createSequentialModifier(() => [ const totalTrees = createSequentialModifier(() => [
createAdditiveModifier(() => ({ createAdditiveModifier(() => ({
addend: () => Decimal.times(expandingForestBuyable.amount.value, 10), addend: () => Decimal.times(expandingForestBuyable.amount.value, 10),
@ -211,12 +214,21 @@ const layer = createLayer(id, function (this: BaseLayer) {
v = Decimal.pow(0.95, paper.books.cuttersBook.totalAmount.value).times(v); v = Decimal.pow(0.95, paper.books.cuttersBook.totalAmount.value).times(v);
return Decimal.times(100, v).add(200); return Decimal.times(100, v).add(200);
}, },
inverseCost(x: DecimalSource) {
let v = Decimal.sub(x, 200).div(100);
v = v.div(Decimal.pow(0.95, paper.books.cuttersBook.totalAmount.value));
if (Decimal.gte(v, 2e30)) v = Decimal.mul(v, Decimal.pow(2e30, 9999)).root(10000);
if (Decimal.gte(v, 2e6)) v = Decimal.mul(v, 2e6).root(2);
if (Decimal.gte(v, 200)) v = Decimal.mul(v, 200).root(2);
if (Decimal.gte(v, 50)) v = Decimal.mul(v, 50).root(2);
return Decimal.isNaN(v) ? Decimal.dZero : v.floor().max(0);
},
display: { display: {
title: "Generic Cutters", title: "Generic Cutters",
description: "Each cutter cuts down 1 tree/s" description: "Each cutter cuts down 1 tree/s"
}, },
visibility: () => showIf(researchUpgrade2.bought.value) visibility: () => showIf(researchUpgrade2.bought.value)
})) as GenericBuyable & { display: { title: string }; resource: Resource }; })) as ElfBuyable & { display: { title: string }; resource: Resource };
const autoPlantingBuyable1 = createBuyable(() => ({ const autoPlantingBuyable1 = createBuyable(() => ({
resource: noPersist(logs), resource: noPersist(logs),
cost() { cost() {
@ -232,12 +244,24 @@ const layer = createLayer(id, function (this: BaseLayer) {
} }
return cost; return cost;
}, },
inverseCost(x: DecimalSource) {
if (management.elfTraining.planterElfTraining.milestones[3].earned.value) {
x = Decimal.mul(x, 10);
}
let v = Decimal.sub(x, 200).div(100);
v = v.div(Decimal.pow(0.95, paper.books.plantersBook.totalAmount.value));
if (Decimal.gte(v, 2e30)) v = Decimal.mul(v, Decimal.pow(2e30, 9999)).root(10000);
if (Decimal.gte(v, 2e6)) v = Decimal.mul(v, 2e6).root(2);
if (Decimal.gte(v, 200)) v = Decimal.mul(v, 200).root(2);
if (Decimal.gte(v, 50)) v = Decimal.mul(v, 50).root(2);
return Decimal.isNaN(v) ? Decimal.dZero : v.floor().max(0);
},
display: { display: {
title: "Generic Planters", title: "Generic Planters",
description: "Each planter plants 0.5 trees/s" description: "Each planter plants 0.5 trees/s"
}, },
visibility: () => showIf(researchUpgrade2.bought.value) visibility: () => showIf(researchUpgrade2.bought.value)
})) as GenericBuyable & { display: { title: string }; resource: Resource }; })) as ElfBuyable & { display: { title: string }; resource: Resource };
const expandingForestBuyable = createBuyable(() => ({ const expandingForestBuyable = createBuyable(() => ({
resource: noPersist(logs), resource: noPersist(logs),
cost() { cost() {
@ -248,12 +272,20 @@ const layer = createLayer(id, function (this: BaseLayer) {
v = Decimal.pow(0.95, paper.books.expandersBook.totalAmount.value).times(v); v = Decimal.pow(0.95, paper.books.expandersBook.totalAmount.value).times(v);
return Decimal.pow(Decimal.add(v, 1), 1.5).times(500); return Decimal.pow(Decimal.add(v, 1), 1.5).times(500);
}, },
inverseCost(x: DecimalSource) {
let v = Decimal.div(x, 500).root(1.5).sub(1);
v = v.div(Decimal.pow(0.95, paper.books.expandersBook.totalAmount.value));
if (Decimal.gte(v, 1e15)) v = Decimal.mul(v, 1e135).root(10);
if (Decimal.gte(v, 1e5)) v = Decimal.mul(v, 1e5).root(2);
if (Decimal.gte(v, 100)) v = Decimal.mul(v, 100).root(2);
return Decimal.isNaN(v) ? Decimal.dZero : v.floor().max(0);
},
display: { display: {
title: "Expand Forest", title: "Expand Forest",
description: "Add 10 trees to the forest" description: "Add 10 trees to the forest"
}, },
visibility: () => showIf(researchUpgrade2.bought.value) visibility: () => showIf(researchUpgrade2.bought.value)
})) as GenericBuyable & { display: { title: string }; resource: Resource }; })) as ElfBuyable & { display: { title: string }; resource: Resource };
const row1Buyables = [autoCuttingBuyable1, autoPlantingBuyable1, expandingForestBuyable]; const row1Buyables = [autoCuttingBuyable1, autoPlantingBuyable1, expandingForestBuyable];
const manualCuttingAmount = createSequentialModifier(() => [ const manualCuttingAmount = createSequentialModifier(() => [
@ -326,20 +358,12 @@ const layer = createLayer(id, function (this: BaseLayer) {
})), })),
createAdditiveModifier(() => ({ createAdditiveModifier(() => ({
addend: () => addend: () =>
Decimal.sub(lastAutoCuttingAmount.value, lastAutoPlantedAmount.value).max(0), Decimal.sub(lastAutoPlantedAmount.value, lastAutoCuttingAmount.value).max(0),
description: "Ivy Level 5", description: "Ivy Level 5",
enabled: management.elfTraining.planterElfTraining.milestones[4].earned enabled: management.elfTraining.planterElfTraining.milestones[4].earned
})) }))
]) as WithRequired<Modifier, "description" | "revert">; ]) as WithRequired<Modifier, "description" | "revert">;
const computedAutoCuttingAmount = computed(() => autoCuttingAmount.apply(0)); const computedAutoCuttingAmount = computed(() => autoCuttingAmount.apply(0));
const lastAutoCuttingAmount = ref<DecimalSource>(0);
setInterval(
() =>
watch(computedAutoCuttingAmount, cut => {
lastAutoCuttingAmount.value = cut;
}),
0
);
const manualPlantingAmount = createSequentialModifier(() => [ const manualPlantingAmount = createSequentialModifier(() => [
createAdditiveModifier(() => ({ createAdditiveModifier(() => ({
@ -421,20 +445,12 @@ const layer = createLayer(id, function (this: BaseLayer) {
})), })),
createAdditiveModifier(() => ({ createAdditiveModifier(() => ({
addend: () => addend: () =>
Decimal.sub(lastAutoPlantedAmount.value, lastAutoCuttingAmount.value).max(0), Decimal.sub(lastAutoCuttingAmount.value, lastAutoPlantedAmount.value).max(0),
description: "Ivy Level 5", description: "Ivy Level 5",
enabled: management.elfTraining.planterElfTraining.milestones[4].earned enabled: management.elfTraining.planterElfTraining.milestones[4].earned
})) }))
]) as WithRequired<Modifier, "description" | "revert">; ]) as WithRequired<Modifier, "description" | "revert">;
const computedAutoPlantingAmount = computed(() => autoPlantingAmount.apply(0)); const computedAutoPlantingAmount = computed(() => autoPlantingAmount.apply(0));
const lastAutoPlantedAmount = ref<DecimalSource>(0);
setInterval(
() =>
watch(computedAutoPlantingAmount, planted => {
lastAutoPlantedAmount.value = planted;
}),
0
);
const logGain = createSequentialModifier(() => [ const logGain = createSequentialModifier(() => [
createMultiplicativeModifier(() => ({ createMultiplicativeModifier(() => ({
@ -711,6 +727,17 @@ const layer = createLayer(id, function (this: BaseLayer) {
} }
} }
const plantingAmount = Decimal.sub(
computedAutoPlantingAmount.value,
Decimal.sub(lastAutoCuttingAmount.value, lastAutoPlantedAmount.value).max(0)
);
const cuttingAmount = Decimal.sub(
computedAutoCuttingAmount.value,
Decimal.sub(lastAutoPlantedAmount.value, lastAutoCuttingAmount.value).max(0)
);
lastAutoPlantedAmount.value = plantingAmount;
lastAutoCuttingAmount.value = cuttingAmount;
const amountCut = Decimal.min( const amountCut = Decimal.min(
trees.value, trees.value,
Decimal.times(computedAutoCuttingAmount.value, diff) Decimal.times(computedAutoCuttingAmount.value, diff)

View file

@ -17,7 +17,11 @@ import { createHotkey } from "features/hotkey";
import { createMilestone } from "features/milestones/milestone"; import { createMilestone } from "features/milestones/milestone";
import { createResource, displayResource } from "features/resources/resource"; import { createResource, displayResource } from "features/resources/resource";
import { BaseLayer, createLayer } from "game/layers"; import { BaseLayer, createLayer } from "game/layers";
import { createExponentialModifier, createMultiplicativeModifier, createSequentialModifier } from "game/modifiers"; import {
createExponentialModifier,
createMultiplicativeModifier,
createSequentialModifier
} from "game/modifiers";
import { noPersist } from "game/persistence"; import { noPersist } from "game/persistence";
import Decimal, { DecimalSource, format, formatWhole } from "util/bignum"; import Decimal, { DecimalSource, format, formatWhole } from "util/bignum";
import { Direction } from "util/common"; import { Direction } from "util/common";
@ -54,10 +58,10 @@ const layer = createLayer(id, function (this: BaseLayer) {
createMultiplicativeModifier(() => ({ createMultiplicativeModifier(() => ({
multiplier: computed(() => wrappingPaper.boosts.beach1.value), multiplier: computed(() => wrappingPaper.boosts.beach1.value),
description: "Beach Wrapping Paper", description: "Beach Wrapping Paper",
enabled: computed(() => Decimal.gt(wrappingPaper.boosts.beach1.value,1)) enabled: computed(() => Decimal.gt(wrappingPaper.boosts.beach1.value, 1))
})), })),
createExponentialModifier(() => ({ createExponentialModifier(() => ({
exponent: 0.95, // Needs fixing exponent: 1 / 0.99,
description: "Holly Level 5", description: "Holly Level 5",
enabled: management.elfTraining.cutterElfTraining.milestones[4].earned enabled: management.elfTraining.cutterElfTraining.milestones[4].earned
})) }))
@ -90,7 +94,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
management.elfTraining.expandersElfTraining.milestones[2].earned.value management.elfTraining.expandersElfTraining.milestones[2].earned.value
), ),
canClick: () => canClick: () =>
Decimal.gte(trees.logs.value, foundationConversion.currentAt.value) && Decimal.gte(trees.logs.value, foundationConversion.nextAt.value) &&
(Decimal.lt(foundationProgress.value, 100) || (Decimal.lt(foundationProgress.value, 100) ||
management.elfTraining.expandersElfTraining.milestones[2].earned.value), management.elfTraining.expandersElfTraining.milestones[2].earned.value),
onClick() { onClick() {

View file

@ -8,7 +8,7 @@ import {
} from "features/feature"; } from "features/feature";
import { BaseLayer, createLayer, GenericLayer, layers } from "game/layers"; import { BaseLayer, createLayer, GenericLayer, layers } from "game/layers";
import { persistent } from "game/persistence"; import { persistent } from "game/persistence";
import type { LayerData, PlayerData } from "game/player"; import type { PlayerData } from "game/player";
import player from "game/player"; import player from "game/player";
import { format, formatTime } from "util/bignum"; import { format, formatTime } from "util/bignum";
import { Computable, convertComputable, ProcessedComputable } from "util/computed"; import { Computable, convertComputable, ProcessedComputable } from "util/computed";
@ -18,23 +18,24 @@ import type { Ref } from "vue";
import { computed, ref, unref } from "vue"; import { computed, ref, unref } from "vue";
import "./advent.css"; import "./advent.css";
import Day from "./Day.vue"; import Day from "./Day.vue";
import trees from "./layers/trees";
import workshop from "./layers/workshop";
import treeSymbol from "./symbols/tree.png";
import workshopSymbol from "./symbols/sws.png";
import coalSymbol from "./symbols/coal.png";
import elfSymbol from "./symbols/elf.png";
import paperSymbol from "./symbols/paperStacks.png";
import boxesSymbol from "./symbols/cardboardBox.png"; import boxesSymbol from "./symbols/cardboardBox.png";
import metalSymbol from "./symbols/metal.png";
import clothSymbol from "./symbols/cloth.png"; import clothSymbol from "./symbols/cloth.png";
import oilSymbol from "./symbols/oil.png"; import coalSymbol from "./symbols/coal.png";
import plasticSymbol from "./symbols/plastic.png";
import dyesSymbol from "./symbols/dyes.png"; import dyesSymbol from "./symbols/dyes.png";
import elfSymbol from "./symbols/elf.png";
import managementSymbol from "./symbols/elfManagement.png"; import managementSymbol from "./symbols/elfManagement.png";
import metalSymbol from "./symbols/metal.png";
import oilSymbol from "./symbols/oil.png";
import paperSymbol from "./symbols/paperStacks.png";
import plasticSymbol from "./symbols/plastic.png";
import workshopSymbol from "./symbols/sws.png";
import treeSymbol from "./symbols/tree.png";
import advManagementSymbol from "./symbols/workshopMansion.png";
import wrappingPaperSymbol from "./symbols/wrappingPaper.png"; import wrappingPaperSymbol from "./symbols/wrappingPaper.png";
import coal from "./layers/coal"; import coal from "./layers/coal";
import elves from "./layers/elves"; import elves from "./layers/elves";
import trees from "./layers/trees";
import workshop from "./layers/workshop";
import paper from "./layers/paper"; import paper from "./layers/paper";
import boxes from "./layers/boxes"; import boxes from "./layers/boxes";
import metal from "./layers/metal"; import metal from "./layers/metal";
@ -160,6 +161,7 @@ export const main = createLayer("main", function (this: BaseLayer) {
// Mobile, use single tab mode // Mobile, use single tab mode
player.tabs.splice(1, Infinity, layer ?? "trees"); player.tabs.splice(1, Infinity, layer ?? "trees");
} }
layers[layer ?? "trees"]!.minimized.value = false;
}, },
onUnlockLayer() { onUnlockLayer() {
if (layer) { if (layer) {
@ -291,8 +293,8 @@ export const main = createLayer("main", function (this: BaseLayer) {
createDay(() => ({ createDay(() => ({
day: 13, day: 13,
shouldNotify: false, shouldNotify: false,
layer: null, // "management" (advanced) layer: "management",
symbol: "", symbol: advManagementSymbol,
story: "So after a good night's rest you decide that maybe making these elves able to do all the work for you isn't something to be scared of, but rather encouraged. Let's spend another day continuing to train them up and really get this place spinning. They are Santa's elves after all, they're supposed to be able to run everything without you!", story: "So after a good night's rest you decide that maybe making these elves able to do all the work for you isn't something to be scared of, but rather encouraged. Let's spend another day continuing to train them up and really get this place spinning. They are Santa's elves after all, they're supposed to be able to run everything without you!",
completedStory: completedStory:
"The elves are doing an incredible job, and Santa does not seem keen on firing you - Score! Now you can get to work on guiding this properly trained highly functional group of hard workers to make Christmas as great as possible. Good Job!" "The elves are doing an incredible job, and Santa does not seem keen on firing you - Score! Now you can get to work on guiding this properly trained highly functional group of hard workers to make Christmas as great as possible. Good Job!"
@ -311,7 +313,8 @@ export const main = createLayer("main", function (this: BaseLayer) {
layer: "wrappingPaper", layer: "wrappingPaper",
symbol: wrappingPaperSymbol, symbol: wrappingPaperSymbol,
story: "You'll need to produce wrapping paper so the presents can be wrapped. The elves are getting a bit bored of their boring old workstations, so you decide to let them decorate with some wrapping paper.", story: "You'll need to produce wrapping paper so the presents can be wrapped. The elves are getting a bit bored of their boring old workstations, so you decide to let them decorate with some wrapping paper.",
completedStory: "You've produced enough wrapping paper, and the elves are happy with their new workstations. However, some will need more than just wrapping paper to decorate." completedStory:
"You've produced enough wrapping paper, and the elves are happy with their new workstations. However, some will need more than just wrapping paper to decorate."
})), })),
createDay(() => ({ createDay(() => ({
day: 16, day: 16,

View file

@ -14,17 +14,6 @@
...unref(classes) ...unref(classes)
}" }"
> >
<div
class="overlayTextContainer border"
:style="[
{ width: unref(width) + 'px', height: unref(height) + 'px' },
unref(borderStyle) ?? {}
]"
>
<span v-if="component" class="overlayText" :style="unref(textStyle)">
<component :is="component" />
</span>
</div>
<div <div
class="border" class="border"
:style="[ :style="[
@ -36,6 +25,17 @@
> >
<div class="fill" :style="[barStyle, unref(style) ?? {}, unref(fillStyle) ?? {}]" /> <div class="fill" :style="[barStyle, unref(style) ?? {}, unref(fillStyle) ?? {}]" />
</div> </div>
<div
class="overlayTextContainer border"
:style="[
{ width: unref(width) + 'px', height: (unref(height) - 1) + 'px' },
unref(borderStyle) ?? {}
]"
>
<span v-if="component" class="overlayText" :style="unref(textStyle)">
<component :is="component" />
</span>
</div>
<MarkNode :mark="unref(mark)" /> <MarkNode :mark="unref(mark)" />
<Node :id="id" /> <Node :id="id" />
</div> </div>
@ -109,21 +109,21 @@ export default defineComponent({
}; };
switch (unref(direction)) { switch (unref(direction)) {
case Direction.Up: case Direction.Up:
barStyle.clipPath = `inset(${normalizedProgress.value}% -2px -2px -2px)`; barStyle.clipPath = `inset(${normalizedProgress.value}% -1px -1px -1px)`;
barStyle.width = unwrapRef(width) + 2 + "px"; barStyle.width = unwrapRef(width) + 1 + "px";
break; break;
case Direction.Down: case Direction.Down:
barStyle.clipPath = `inset(-2px -2px ${normalizedProgress.value}% -2px)`; barStyle.clipPath = `inset(-1px -1px ${normalizedProgress.value}% -1px)`;
barStyle.width = unwrapRef(width) + 2 + "px"; barStyle.width = unwrapRef(width) + 1 + "px";
break; break;
case Direction.Right: case Direction.Right:
barStyle.clipPath = `inset(-2px ${normalizedProgress.value}% -2px -2px)`; barStyle.clipPath = `inset(-1px ${normalizedProgress.value}% -1px -1px)`;
break; break;
case Direction.Left: case Direction.Left:
barStyle.clipPath = `inset(-2px -2px -2px ${normalizedProgress.value} + '%)`; barStyle.clipPath = `inset(-1px -1px -1px ${normalizedProgress.value} + '%)`;
break; break;
case Direction.Default: case Direction.Default:
barStyle.clipPath = "inset(-2px 50% -2px -2px)"; barStyle.clipPath = "inset(-1px 50% -1px -1px)";
break; break;
} }
return barStyle; return barStyle;
@ -148,10 +148,12 @@ export default defineComponent({
display: table; display: table;
overflow: hidden; overflow: hidden;
border-radius: 10px; border-radius: 10px;
padding-bottom: 1px;
} }
.overlayTextContainer { .overlayTextContainer {
position: absolute; position: absolute;
top: 0;
border-radius: 10px; border-radius: 10px;
vertical-align: middle; vertical-align: middle;
display: flex; display: flex;
@ -168,13 +170,17 @@ export default defineComponent({
border-radius: 10px; border-radius: 10px;
border-color: var(--foreground); border-color: var(--foreground);
overflow: hidden; overflow: hidden;
margin: 0; }
.border:not(.overlayTextContainer) {
margin: -1px 0 -1px -1px;
} }
.fill { .fill {
position: absolute; position: absolute;
background-color: var(--foreground); background-color: var(--foreground);
overflow: hidden; overflow: hidden;
padding: 2px 1px;
margin-left: -0.5px; margin-left: -0.5px;
transition-duration: 0.2s; transition-duration: 0.2s;
z-index: 2; z-index: 2;

View file

@ -70,7 +70,7 @@ ul {
/* Scrollbar stuff */ /* Scrollbar stuff */
* { * {
scrollbar-color: #ffffff0f var(--accent1); scrollbar-color: var(--accent1) #ffffff0f;
} }
::-webkit-scrollbar { ::-webkit-scrollbar {