Change mastery system to swap out persistent refs

This commit is contained in:
Seth Posner 2022-12-16 15:24:24 -08:00
parent 5235dc924e
commit e314f234eb
5 changed files with 319 additions and 1206 deletions

View file

@ -83,10 +83,10 @@ const layer = createLayer(id, function (this: BaseLayer) {
const ash = createResource<DecimalSource>(0, "ash");
const activeFires = persistent<DecimalSource>(0);
const fireLogs = computed(() => Decimal.times(main.isMastery.value ? mastery.activeFires.value : activeFires.value, 1000));
const fireCoal = computed(() => Decimal.times(main.isMastery.value ? mastery.activeFires.value : activeFires.value, 0.1));
const fireLogs = computed(() => Decimal.times(activeFires.value, 1000));
const fireCoal = computed(() => Decimal.times(activeFires.value, 0.1));
const fireAsh = computed(() => {
let gain = Decimal.times(main.isMastery.value ? mastery.activeFires.value : activeFires.value, 50);
let gain = Decimal.times(activeFires.value, 50);
if (management.elfTraining.smallfireElfTraining.milestones[0].earned.value) {
gain = gain.times(5);
}
@ -148,16 +148,16 @@ const layer = createLayer(id, function (this: BaseLayer) {
const fireResource = createResource(buildFire.amount, "small fires");
const activeBonfires = persistent<DecimalSource>(0);
const bonfireLogs = computed(() => Decimal.times(main.isMastery.value ? mastery.activeBonfires.value : activeBonfires.value, 10000));
const bonfireLogs = computed(() => Decimal.times(activeBonfires.value, 10000));
const bonfireCoal = computed(() => {
let gain = Decimal.times(main.isMastery.value ? mastery.activeBonfires.value : activeBonfires.value, 10);
let gain = Decimal.times(activeBonfires.value, 10);
if (management.elfTraining.bonfireElfTraining.milestones[0].earned.value) {
gain = gain.times(5);
}
return gain;
});
const bonfireAsh = computed(() => {
let gain = Decimal.times(main.isMastery.value ? mastery.activeBonfires.value : activeBonfires.value, 1000);
let gain = Decimal.times(activeBonfires.value, 1000);
if (management.elfTraining.bonfireElfTraining.milestones[0].earned.value) {
gain = gain.times(5);
}
@ -210,16 +210,16 @@ const layer = createLayer(id, function (this: BaseLayer) {
active: activeBonfires
});
const activeKilns = persistent<DecimalSource>(0);
const kilnLogs = computed(() => Decimal.times(main.isMastery.value ? mastery.activeKilns.value : activeKilns.value, 1e6));
const kilnLogs = computed(() => Decimal.times(activeKilns.value, 1e6));
const kilnCoal = computed(() => {
let gain = Decimal.times(main.isMastery.value ? mastery.activeKilns.value : activeKilns.value, 1e4);
let gain = Decimal.times(activeKilns.value, 1e4);
if (management.elfTraining.kilnElfTraining.milestones[0].earned.value) {
gain = gain.times(5);
}
return gain;
});
const kilnAsh = computed(() => {
let gain = Decimal.times(main.isMastery.value ? mastery.activeKilns.value : activeKilns.value, 1e4);
let gain = Decimal.times(activeKilns.value, 1e4);
if (management.elfTraining.kilnElfTraining.milestones[0].earned.value) {
gain = gain.times(5);
}
@ -278,7 +278,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
const activeDrills = persistent<DecimalSource>(0);
const drillCoal = computed(() =>
Decimal.times(
Decimal.pow(main.isMastery.value ? mastery.activeDrills.value : activeDrills.value, oil.row2Upgrades[1].bought.value ? 2 : 1),
Decimal.pow(activeDrills.value, oil.row2Upgrades[1].bought.value ? 2 : 1),
5e7
)
.times(metal.efficientDrill.bought.value ? 2 : 1)
@ -603,17 +603,17 @@ const layer = createLayer(id, function (this: BaseLayer) {
const heatedCutterEffect = createSequentialModifier(() => [
createAdditiveModifier(() => ({
addend() {
return Decimal.times(main.isMastery.value ? mastery.heatedCutters.amount.value : heatedCutters.amount.value, 0.25);
return Decimal.times(heatedCutters.amount.value, 0.25);
},
description: "Heated Cutters",
enabled() {
return Decimal.gt(main.isMastery.value ? mastery.heatedCutters.amount.value : heatedCutters.amount.value, 0);
return Decimal.gt(heatedCutters.amount.value, 0);
}
})),
createMultiplicativeModifier(() => ({
multiplier: 2,
description: "Dedicated Cutter Heaters",
enabled: () => main.isMastery.value ? mastery.dedicatedCutters.bought.value : dedicatedCutters.bought.value
enabled: () => dedicatedCutters.bought.value
}))
]);
const computedHeatedCutterEffect = computed(() => heatedCutterEffect.apply(1));
@ -621,17 +621,17 @@ const layer = createLayer(id, function (this: BaseLayer) {
const heatedPlanterEffect = createSequentialModifier(() => [
createAdditiveModifier(() => ({
addend() {
return Decimal.times(main.isMastery.value ? mastery.heatedPlanters.amount.value : heatedPlanters.amount.value, 0.25);
return Decimal.times(heatedPlanters.amount.value, 0.25);
},
description: "Heated Planters",
enabled() {
return Decimal.gt(main.isMastery.value ? mastery.heatedPlanters.amount.value : heatedPlanters.amount.value, 0);
return Decimal.gt(heatedPlanters.amount.value, 0);
}
})),
createMultiplicativeModifier(() => ({
multiplier: 2,
description: "Dedicated Planter Heaters",
enabled: () => main.isMastery.value ? mastery.dedicatedPlanters.bought.value : dedicatedPlanters.bought.value
enabled: () => dedicatedPlanters.bought.value
}))
]);
const computedHeatedPlanterEffect = computed(() => heatedPlanterEffect.apply(1));
@ -639,17 +639,17 @@ const layer = createLayer(id, function (this: BaseLayer) {
const fertilizerEffect = createSequentialModifier(() => [
createAdditiveModifier(() => ({
addend() {
return Decimal.times(main.isMastery.value ? mastery.moreFertilizer.amount.value : moreFertilizer.amount.value, 0.25);
return Decimal.times(moreFertilizer.amount.value, 0.25);
},
description: "Fertilized Soil",
enabled() {
return Decimal.gt(main.isMastery.value ? mastery.moreFertilizer.amount.value : moreFertilizer.amount.value, 0);
return Decimal.gt(moreFertilizer.amount.value, 0);
}
})),
createMultiplicativeModifier(() => ({
multiplier: 2,
description: "Mulched Soil",
enabled: () => main.isMastery.value ? mastery.betterFertilizer.bought.value : betterFertilizer.bought.value
enabled: () => betterFertilizer.bought.value
}))
]);
const computedFertilizerEffect = computed(() => fertilizerEffect.apply(1));
@ -661,7 +661,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
},
description: "Small Fires",
enabled() {
return Decimal.gt(main.isMastery.value ? mastery.activeFires.value : activeFires.value, 0);
return Decimal.gt(activeFires.value, 0);
}
})),
createAdditiveModifier(() => ({
@ -670,7 +670,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
},
description: "Bonfires",
enabled() {
return Decimal.gt(main.isMastery.value ? mastery.activeBonfires.value : activeBonfires.value, 0);
return Decimal.gt(activeBonfires.value, 0);
}
})),
createAdditiveModifier(() => ({
@ -679,7 +679,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
},
description: "Charcoal Kilns",
enabled() {
return Decimal.gt(main.isMastery.value ? mastery.activeKilns.value : activeKilns.value, 0);
return Decimal.gt(activeKilns.value, 0);
}
})),
createAdditiveModifier(() => ({
@ -688,7 +688,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
},
description: "Coal Drills",
enabled() {
return Decimal.gt(main.isMastery.value ? mastery.activeDrills.value : activeDrills.value, 0);
return Decimal.gt(activeDrills.value, 0);
}
})),
createMultiplicativeModifier(() => ({
@ -703,7 +703,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
})),
createMultiplicativeModifier(() => ({
multiplier: () => {
let v = main.isMastery.value ? mastery.buildFire.amount.value : buildFire.amount.value;
let v = buildFire.amount.value;
if (management.elfTraining.smallfireElfTraining.milestones[0].earned.value) {
v = Decimal.div(buildBonfire.amount.value, 10).add(v);
}
@ -717,13 +717,13 @@ const layer = createLayer(id, function (this: BaseLayer) {
enabled: elves.elves.smallFireElf.bought
})),
createMultiplicativeModifier(() => ({
multiplier: () => Decimal.div(main.isMastery.value ? mastery.buildBonfire.amount.value : buildBonfire.amount.value, 1000).add(1),
multiplier: () => Decimal.div(buildBonfire.amount.value, 1000).add(1),
description: "Bonfires Synergy",
enabled: elves.elves.bonfireElf.bought
})),
createMultiplicativeModifier(() => ({
multiplier: () =>
Decimal.div(main.isMastery.value ? mastery.buildKiln.amount.value : buildKiln.amount.value, 100).times(dyes.boosts.green2.value).add(1),
Decimal.div(buildKiln.amount.value, 100).times(dyes.boosts.green2.value).add(1),
description: "Kiln Synergy",
enabled: elves.elves.kilnElf.bought
})),
@ -795,7 +795,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
},
description: "Small Fires",
enabled() {
return Decimal.gt(main.isMastery.value ? mastery.activeFires.value : activeFires.value, 0);
return Decimal.gt(activeFires.value, 0);
}
})),
createAdditiveModifier(() => ({
@ -804,7 +804,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
},
description: "Bonfires",
enabled() {
return Decimal.gt(main.isMastery.value ? mastery.activeBonfires.value : activeBonfires.value, 0);
return Decimal.gt(activeBonfires.value, 0);
}
})),
createAdditiveModifier(() => ({
@ -828,7 +828,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
})),
createMultiplicativeModifier(() => ({
multiplier: () => {
let v = main.isMastery.value ? mastery.buildFire.amount.value : buildFire.amount.value;
let v = buildFire.amount.value;
if (management.elfTraining.smallfireElfTraining.milestones[0].earned.value) {
v = Decimal.div(buildBonfire.amount.value, 100).add(v);
}
@ -838,13 +838,13 @@ const layer = createLayer(id, function (this: BaseLayer) {
enabled: elves.elves.smallFireElf.bought
})),
createMultiplicativeModifier(() => ({
multiplier: () => Decimal.div(main.isMastery.value ? mastery.buildBonfire.amount.value : buildBonfire.amount.value, 1000).add(1),
multiplier: () => Decimal.div(buildBonfire.amount.value, 1000).add(1),
description: "Bonfires Synergy",
enabled: elves.elves.bonfireElf.bought
})),
createMultiplicativeModifier(() => ({
multiplier: () =>
Decimal.div(main.isMastery.value ? mastery.buildKiln.amount.value : buildKiln.amount.value, 100).times(dyes.boosts.green2.value).add(1),
Decimal.div(buildKiln.amount.value, 100).times(dyes.boosts.green2.value).add(1),
description: "Kiln Synergy",
enabled: elves.elves.kilnElf.bought
})),
@ -888,7 +888,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
},
description: "Small Fires",
enabled() {
return Decimal.gt(main.isMastery.value ? mastery.activeFires.value : activeFires.value, 0);
return Decimal.gt(activeFires.value, 0);
}
})),
createAdditiveModifier(() => ({
@ -897,7 +897,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
},
description: "Bonfires",
enabled() {
return Decimal.gt(main.isMastery.value ? mastery.activeBonfires.value : activeBonfires.value, 0);
return Decimal.gt(activeBonfires.value, 0);
}
})),
createAdditiveModifier(() => ({
@ -906,7 +906,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
},
description: "Charcoal Kilns",
enabled() {
return Decimal.gt(main.isMastery.value ? mastery.activeKilns.value : activeKilns.value, 0);
return Decimal.gt(activeKilns.value, 0);
}
}))
]);
@ -919,9 +919,9 @@ const layer = createLayer(id, function (this: BaseLayer) {
base: 0,
visible() {
return (
Decimal.gt(main.isMastery.value ? mastery.activeFires.value : activeFires.value, 0) ||
Decimal.gt(main.isMastery.value ? mastery.activeBonfires.value : activeBonfires.value, 0) ||
Decimal.gt(main.isMastery.value ? mastery.activeKilns.value : activeKilns.value, 0)
Decimal.gt(activeFires.value, 0) ||
Decimal.gt(activeBonfires.value, 0) ||
Decimal.gt(activeKilns.value, 0)
);
}
},
@ -931,9 +931,9 @@ const layer = createLayer(id, function (this: BaseLayer) {
base: 0,
visible() {
return (
Decimal.gt(main.isMastery.value ? mastery.activeFires.value : activeFires.value, 0) ||
Decimal.gt(main.isMastery.value ? mastery.activeBonfires.value : activeBonfires.value, 0) ||
Decimal.gt(main.isMastery.value ? mastery.activeKilns.value : activeKilns.value, 0)
Decimal.gt(activeFires.value, 0) ||
Decimal.gt(activeBonfires.value, 0) ||
Decimal.gt(activeKilns.value, 0)
);
}
},
@ -943,9 +943,9 @@ const layer = createLayer(id, function (this: BaseLayer) {
base: 0,
visible() {
return (
Decimal.gt(main.isMastery.value ? mastery.activeFires.value : activeFires.value, 0) ||
Decimal.gt(main.isMastery.value ? mastery.activeBonfires.value : activeBonfires.value, 0) ||
Decimal.gt(main.isMastery.value ? mastery.activeKilns.value : activeKilns.value, 0)
Decimal.gt(activeFires.value, 0) ||
Decimal.gt(activeBonfires.value, 0) ||
Decimal.gt(activeKilns.value, 0)
);
}
}
@ -995,489 +995,63 @@ const layer = createLayer(id, function (this: BaseLayer) {
}
});
const mastery = (() => {
const activeFires = persistent<DecimalSource>(0);
const activeBonfires = persistent<DecimalSource>(0);
const activeKilns = persistent<DecimalSource>(0);
const coal = createResource<DecimalSource>(0,"coal");
const ash = createResource<DecimalSource>(0,"ash");
const buildFire = createBuyable(() => ({
resource: noPersist(trees.mastery.logs), // apparently necessary
cost() {
let v = Decimal.times(buildBonfire.amount.value, unref(buildBonfire.cost!)).plus(
this.amount.value
);
if (Decimal.gte(v, 100)) v = Decimal.pow(v, 2).div(100);
if (Decimal.gte(v, 10000)) v = Decimal.pow(v, 2).div(10000);
v = Decimal.pow(0.95, paper.books.smallFireBook.totalAmount.value).times(v);
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(() => (
<>
<h3>Small Fire</h3>
<br />
Burn 1000 logs for 0.1 coal and 50 ash
<br />
<br />
Currently:
<br />-{format(fireLogs.value)} logs/sec
<br />+{format(fireCoal.value)} coal/sec
<br />+{format(fireAsh.value)} ash/sec
<br />
<br />
Cost: {formatWhole(unref(buildFire.cost!))} {buildFire.resource!.displayName}
</>
)),
onPurchase() {
activeFires.value = Decimal.add(activeFires.value, 1);
},
style: {
color: colorText,
width: "160px"
}
})) as ElfBuyable & { resource: Resource };
const {
min: minFire,
max: maxFire,
add: addFire,
remove: removeFire
} = changeActiveBuyables({
active: activeFires,
buyable: buildFire
});
const fireResource = createResource(buildFire.amount, "small fires");
const buildBonfire = createBuyable(() => ({
resource: fireResource,
cost() {
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(() => (
<>
<h3>Bonfire</h3>
<br />
Burn 10,000 logs for 10 coal and 1000 ash
<br />
<br />
Currently:
<br />-{format(bonfireLogs.value)} logs/sec
<br />+{format(bonfireCoal.value)} coal/sec
<br />+{format(bonfireAsh.value)} ash/sec
<br />
<br />
Cost: {formatWhole(unref(buildBonfire.cost!))} {buildBonfire.resource!.displayName}
</>
)),
onPurchase(cost) {
activeFires.value = Decimal.sub(activeFires.value, cost!).max(0);
activeBonfires.value = Decimal.add(activeBonfires.value, 1);
},
style: {
color: colorText,
width: "160px"
},
visibility: () => showIf(unlockBonfire.bought.value)
})) as ElfBuyable & { resource: Resource };
const {
min: minBonfire,
max: maxBonfire,
add: addBonfire,
remove: removeBonfire
} = changeActiveBuyables({
buyable: buildBonfire,
active: activeBonfires
});
const buildKiln = createBuyable(() => ({
resource: noPersist(trees.mastery.logs),
cost() {
let v = this.amount.value;
if (Decimal.gte(v, 100)) v = Decimal.pow(v, 2).div(100);
if (Decimal.gte(v, 10000)) v = Decimal.pow(v, 2).div(10000);
v = Decimal.pow(0.95, paper.books.kilnBook.totalAmount.value).times(v);
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(() => (
<>
<h3>Charcoal Kiln</h3>
<br />
Burn 1,000,000 logs for 10,000 coal and 10,000 ash
<br />
<br />
Currently:
<br />-{format(kilnLogs.value)} logs/sec
<br />+{format(kilnCoal.value)} coal/sec
<br />+{format(kilnAsh.value)} ash/sec
<br />
<br />
Cost: {formatWhole(unref(buildKiln.cost!))} {buildKiln.resource!.displayName}
</>
)),
onPurchase() {
activeKilns.value = Decimal.add(activeKilns.value, 1);
},
style: {
color: colorText,
width: "160px"
},
visibility: () => showIf(unlockKiln.bought.value)
})) as ElfBuyable & { resource: Resource };
const {
min: minKiln,
max: maxKiln,
add: addKiln,
remove: removeKiln
} = changeActiveBuyables({
buyable: buildKiln,
active: activeKilns
});
const warmerCutters = createUpgrade(() => ({
resource: noPersist(coal),
cost: 5,
display: {
title: "Warmer Cutters",
description: "Cut down twice as many trees/s"
},
style: { color: colorText }
}));
const warmerPlanters = createUpgrade(() => ({
resource: noPersist(coal),
cost: 5,
display: {
title: "Warmer Planters",
description: "Plant twice as many trees/s"
},
style: { color: colorText }
}));
const basicFertilizer = createUpgrade(() => ({
resource: noPersist(ash),
cost: 5000,
display: {
title: "Ashy Soil",
description: "Trees give 25% more logs"
},
style: { color: colorText }
}));
const unlockBonfire = createUpgrade(() => ({
resource: fireResource,
cost: 10,
display: {
title: "Bigger Fires",
description: "Put all those fires together into a larger blaze"
},
onPurchase() {
fireResource.value = Decimal.add(fireResource.value, this.cost);
},
style: { color: colorText }
}));
const row1upgrades = [warmerCutters, warmerPlanters, basicFertilizer, unlockBonfire];
const dedicatedCutters = createUpgrade(() => ({
resource: noPersist(coal),
cost: 250,
display: {
title: "Dedicated Cutter Heaters",
description: "Double the bonus from Heated Cutters"
},
style: { color: colorText },
visibility: () => showIf(unlockBonfire.bought.value)
}));
const dedicatedPlanters = createUpgrade(() => ({
resource: noPersist(coal),
cost: 250,
display: {
title: "Dedicated Planter Heaters",
description: "Double the bonus from Heated Planters"
},
style: { color: colorText },
visibility: () => showIf(unlockBonfire.bought.value)
}));
const betterFertilizer: Upgrade<BetterFertilizerUpgOptions> = createUpgrade(() => ({
canAfford() {
return Decimal.gte(trees.logs.value, 1e5) && Decimal.gte(ash.value, 1e5);
},
onPurchase() {
trees.logs.value = Decimal.sub(trees.logs.value, 1e5);
ash.value = Decimal.sub(ash.value, 1e5);
},
display: jsx(() => (
<>
<h3>Mulched Soil</h3>
<br />
Double the bonus from Fertilized Soil
<br />
<br />
Cost: {formatWhole(1e5)} {trees.logs.displayName}
<br />
{formatWhole(1e5)} {ash.displayName}
</>
)),
style: { color: colorText },
visibility: () => showIf(unlockBonfire.bought.value)
}));
const unlockKiln: Upgrade<UnlockKilnUpgOptions> = createUpgrade(() => ({
resource: trees.logs,
cost: 1e7,
display: {
title: "Efficient Fires",
description: "Move the fires underground to keep the coal from turning to ash"
},
style: { color: colorText },
visibility: () => showIf(unlockBonfire.bought.value)
}));
const row2upgrades = [dedicatedCutters, dedicatedPlanters, betterFertilizer, unlockKiln];
const efficientSmelther: Upgrade<EfficientSmeltherUpgOptions> = createUpgrade(() => ({
resource: noPersist(coal),
cost: 1e19,
display: {
title: "Efficient Crucibles",
description: "Double auto smelting speed and triple metal gain from auto smelting"
},
style: { color: colorText },
visibility: () => showIf(oil.depthMilestones[4].earned.value)
}));
const row3upgrades = [efficientSmelther];
const buildDrill = createBuyable(() => ({
resource: metal.metal,
cost() {
let v = this.amount.value;
if (Decimal.gte(v, 100)) v = Decimal.pow(v, 2).div(100);
if (Decimal.gte(v, 10000)) v = Decimal.pow(v, 2).div(10000);
v = Decimal.pow(0.95, paper.books.coalDrillBook.totalAmount.value).times(v);
let cost = Decimal.pow(1.15, v).times(10);
if (management.elfTraining.fertilizerElfTraining.milestones[2].earned.value) {
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;
},
inverseCost(x: DecimalSource) {
if (management.elfTraining.coalDrillElfTraining.milestones[2].earned.value) {
x = Decimal.mul(x, 10);
}
if (management.elfTraining.fertilizerElfTraining.milestones[2].earned.value) {
x = Decimal.mul(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(() => (
<>
<h3>Coal Drill</h3>
<br />
Dig through the ground to find 50,000,000 coal
<br />
<br />
Currently:
<br />+{format(drillCoal.value)} coal/sec
<br />
<br />
Cost: {formatWhole(unref(buildDrill.cost!))} {buildDrill.resource.displayName}
</>
)),
onPurchase() {
activeDrills.value = Decimal.add(activeDrills.value, 1);
},
style: {
color: colorText,
width: "160px"
},
visibility: () => showIf(metal.coalDrill.bought.value)
})) as ElfBuyable & { resource: Resource };
const activeDrills = persistent<DecimalSource>(0)
const {
max: maxDrill,
min: minDrill,
add: addDrill,
remove: removeDrill
} = changeActiveBuyables({
buyable: buildDrill,
active: activeDrills
});
const heatedCutters = createBuyable(() => ({
resource: noPersist(coal),
cost() {
let v = 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, 2e6)) v = Decimal.pow(v, 2).div(2e6);
v = Decimal.pow(0.95, paper.books.heatedCuttersBook.totalAmount.value).times(v);
if (management.elfTraining.heatedCutterElfTraining.milestones[0].earned.value) {
v = Decimal.pow(0.95, paper.books.heatedCuttersBook.totalAmount.value).times(v);
}
v = v.div(wrappingPaper.boosts.rainbow1.value);
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: {
title: "Heated Cutters",
description: "Even warmer cutters cut down trees faster",
effectDisplay: jsx(() => (
<>Cutters cut down trees {format(computedHeatedCutterEffect.value)}x faster</>
))
},
style: { color: colorText },
visibility: () => showIf(warmerCutters.bought.value)
})) as ElfBuyable & { display: { title: string }; resource: Resource };
const heatedPlanters = createBuyable(() => ({
resource: noPersist(coal),
cost() {
let v = 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, 2e6)) v = Decimal.pow(v, 2).div(2e6);
v = Decimal.pow(0.95, paper.books.heatedPlantersBook.totalAmount.value).times(v);
if (management.elfTraining.heatedPlanterElfTraining.milestones[0].earned.value) {
v = Decimal.pow(0.95, paper.books.heatedPlantersBook.totalAmount.value).times(v);
}
v = v.div(wrappingPaper.boosts.rainbow1.value);
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: {
title: "Heated Planters",
description: "Even warmer planters plant trees faster",
effectDisplay: jsx(() => (
<>Planters plant trees {format(computedHeatedPlanterEffect.value)}x faster</>
))
},
style: { color: colorText },
visibility: () => showIf(warmerPlanters.bought.value)
})) as ElfBuyable & { display: { title: string }; resource: Resource };
const moreFertilizer = createBuyable(() => ({
resource: noPersist(ash),
cost() {
let v = 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, 2e6)) v = Decimal.pow(v, 2).div(2e6);
v = Decimal.pow(0.95, paper.books.fertilizerBook.totalAmount.value).times(v);
if (management.elfTraining.fertilizerElfTraining.milestones[1].earned.value) {
v = Decimal.pow(0.95, paper.books.fertilizerBook.totalAmount.value).times(v);
}
v = v.div(wrappingPaper.boosts.rainbow1.value);
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: {
title: "Fertilized Soil",
description: "More fertilizer helps trees grow bigger",
effectDisplay: jsx(() => (
<>Trees give {format(computedFertilizerEffect.value)}x more logs</>
))
},
style: { color: colorText },
visibility: () => showIf(basicFertilizer.bought.value)
})) as ElfBuyable & { display: { title: string }; resource: Resource };
const row3buyables = [heatedCutters, heatedPlanters, moreFertilizer];
return {
buildFire,
activeFires,
buildBonfire,
activeBonfires,
buildKiln,
activeKilns,
minFire,
maxFire,
addFire,
removeFire,
minBonfire,
maxBonfire,
addBonfire,
removeBonfire,
minKiln,
maxKiln,
addKiln,
removeKiln,
row1upgrades,
row2upgrades,
row3upgrades,
unlockBonfire,
unlockKiln,
dedicatedCutters,
dedicatedPlanters,
betterFertilizer,
efficientSmelther,
warmerCutters,
warmerPlanters,
basicFertilizer,
activeDrills,
buildDrill,
minDrill,
maxDrill,
addDrill,
removeDrill,
coal,
ash,
heatedCutters,
heatedPlanters,
moreFertilizer,
row3buyables,
}
})()
const mastery = {
coal: persistent<DecimalSource>(0),
totalCoal: persistent<DecimalSource>(0),
ash: persistent<DecimalSource>(0),
activeFires: persistent<DecimalSource>(0),
buildFire: { amount: persistent<DecimalSource>(0) },
activeBonfires: persistent<DecimalSource>(0),
buildBonfire: { amount: persistent<DecimalSource>(0) },
activeKilns: persistent<DecimalSource>(0),
buildKiln: { amount: persistent<DecimalSource>(0) },
activeDrills: persistent<DecimalSource>(0),
buildDrill: { amount: persistent<DecimalSource>(0) },
warmerCutters: { bought: persistent<boolean>(false) },
warmerPlanters: { bought: persistent<boolean>(false) },
basicFertilizer: { bought: persistent<boolean>(false) },
unlockBonfire: { bought: persistent<boolean>(false) },
dedicatedCutters: { bought: persistent<boolean>(false) },
dedicatedPlanters: { bought: persistent<boolean>(false) },
betterFertilizer: { bought: persistent<boolean>(false) },
unlockKiln: { bought: persistent<boolean>(false) },
efficientSmelther: { bought: persistent<boolean>(false) },
arsonistAssistance: { bought: persistent<boolean>(false) },
refinedCoal: { bought: persistent<boolean>(false) },
coloredFire: { bought: persistent<boolean>(false) },
heatedCutters: { amount: persistent<DecimalSource>(0) },
heatedPlanters: { amount: persistent<DecimalSource>(0) },
moreFertilizer: { amount: persistent<DecimalSource>(0) }
};
function swapMastery() {
[coal.value, mastery.coal.value] = [mastery.coal.value, coal.value];
[totalCoal.value, mastery.totalCoal.value] = [mastery.totalCoal.value, totalCoal.value];
[ash.value, mastery.ash.value] = [mastery.ash.value, ash.value];
[activeFires.value, mastery.activeFires.value] = [mastery.activeFires.value, activeFires.value];
[buildFire.amount.value, mastery.buildFire.amount.value] = [mastery.buildFire.amount.value, buildFire.amount.value];
[activeBonfires.value, mastery.activeBonfires.value] = [mastery.activeBonfires.value, activeBonfires.value];
[buildBonfire.amount.value, mastery.buildBonfire.amount.value] = [mastery.buildBonfire.amount.value, buildBonfire.amount.value];
[activeKilns.value, mastery.activeKilns.value] = [mastery.activeKilns.value, activeKilns.value];
[buildKiln.amount.value, mastery.buildKiln.amount.value] = [mastery.buildKiln.amount.value, buildKiln.amount.value];
[activeDrills.value, mastery.activeDrills.value] = [mastery.activeDrills.value, activeDrills.value];
[buildDrill.amount.value, mastery.buildDrill.amount.value] = [mastery.buildDrill.amount.value, buildDrill.amount.value];
[warmerCutters.bought.value, mastery.warmerCutters.bought.value] = [mastery.warmerCutters.bought.value, warmerCutters.bought.value];
[warmerPlanters.bought.value, mastery.warmerPlanters.bought.value] = [mastery.warmerPlanters.bought.value, warmerPlanters.bought.value];
[basicFertilizer.bought.value, mastery.basicFertilizer.bought.value] = [mastery.basicFertilizer.bought.value, basicFertilizer.bought.value];
[unlockBonfire.bought.value, mastery.unlockBonfire.bought.value] = [mastery.unlockBonfire.bought.value, unlockBonfire.bought.value];
[dedicatedCutters.bought.value, mastery.dedicatedCutters.bought.value] = [mastery.dedicatedCutters.bought.value, dedicatedCutters.bought.value];
[dedicatedPlanters.bought.value, mastery.dedicatedPlanters.bought.value] = [mastery.dedicatedPlanters.bought.value, dedicatedPlanters.bought.value];
[betterFertilizer.bought.value, mastery.betterFertilizer.bought.value] = [mastery.betterFertilizer.bought.value, betterFertilizer.bought.value];
[unlockKiln.bought.value, mastery.unlockKiln.bought.value] = [mastery.unlockKiln.bought.value, unlockKiln.bought.value];
[efficientSmelther.bought.value, mastery.efficientSmelther.bought.value] = [mastery.efficientSmelther.bought.value, efficientSmelther.bought.value];
[arsonistAssistance.bought.value, mastery.arsonistAssistance.bought.value] = [mastery.arsonistAssistance.bought.value, arsonistAssistance.bought.value];
[refinedCoal.bought.value, mastery.refinedCoal.bought.value] = [mastery.refinedCoal.bought.value, refinedCoal.bought.value];
[coloredFire.bought.value, mastery.coloredFire.bought.value] = [mastery.coloredFire.bought.value, coloredFire.bought.value];
[heatedCutters.amount.value, mastery.heatedCutters.amount.value] = [mastery.heatedCutters.amount.value, heatedCutters.amount.value];
[heatedPlanters.amount.value, mastery.heatedPlanters.amount.value] = [mastery.heatedPlanters.amount.value, heatedPlanters.amount.value];
[moreFertilizer.amount.value, mastery.moreFertilizer.amount.value] = [mastery.moreFertilizer.amount.value, moreFertilizer.amount.value];
}
const mastered = persistent<boolean>(false);
return {
name,
@ -1514,13 +1088,12 @@ const layer = createLayer(id, function (this: BaseLayer) {
computedFertilizerEffect,
generalTabCollapsed,
minWidth: 700,
mastery,
display: jsx(() => (
<>
{render(trackerDisplay)}
<Spacer />
<MainDisplay
resource={main.isMastery.value ? mastery.coal : coal}
resource={coal}
color={colorCoal}
style={{ marginBottom: 0 }}
resourceStyle={{ textShadow: "grey 0px 0px 10px" }}
@ -1532,7 +1105,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
/>
<Spacer />
<MainDisplay
resource={main.isMastery.value ? mastery.ash : ash}
resource={ash}
color={colorAsh}
style="margin-bottom: 0"
effectDisplay={
@ -1544,36 +1117,36 @@ const layer = createLayer(id, function (this: BaseLayer) {
<Spacer />
<Row>
<Column>
{render(main.isMastery.value ? mastery.buildFire : buildFire)}
{render(buildFire)}
<div>
{formatWhole(Decimal.floor(main.isMastery ? mastery.activeFires.value : activeFires.value))}/
{formatWhole(Decimal.floor(main.isMastery ? mastery.buildFire.amount.value : buildFire.amount.value))}
</div>
{renderRow(... main.isMastery.value ? [mastery.minFire, mastery.removeFire, mastery.addFire, mastery.maxFire] : [minFire, removeFire, addFire, maxFire])}
{renderRow(minFire, removeFire, addFire, maxFire)}
</Column>
{(main.isMastery.value ? mastery.unlockBonfire.bought.value : unlockBonfire.bought.value) ? (
{(unlockBonfire.bought.value) ? (
<>
<Spacer />
<Column>
{render(buildBonfire)}
<div>
{formatWhole(main.isMastery.value ? mastery.activeBonfires.value : activeBonfires.value)}/
{formatWhole(main.isMastery.value ? mastery.buildBonfire.amount.value : buildBonfire.amount.value)}
{formatWhole(activeBonfires.value)}/
{formatWhole(buildBonfire.amount.value)}
</div>
{renderRow(...main.isMastery.value ? [mastery.minBonfire, mastery.removeBonfire, mastery.addBonfire, mastery.maxBonfire] : [minBonfire, removeBonfire, addBonfire, maxBonfire] )}
{renderRow(minBonfire, removeBonfire, addBonfire, maxBonfire)}
</Column>
</>
) : undefined}
{(main.isMastery.value ? mastery.unlockKiln.bought.value : unlockKiln.bought.value) ? (
{(unlockKiln.bought.value) ? (
<>
<Spacer />
<Column>
{render(main.isMastery.value ? mastery.buildKiln : buildKiln)}
{render(buildKiln)}
<div>
{formatWhole(main.isMastery.value ? mastery.activeKilns.value : activeKilns.value)}/
{formatWhole(main.isMastery.value ? mastery.buildKiln.amount.value : buildKiln.amount.value)}
{formatWhole(activeKilns.value)}/
{formatWhole(buildKiln.amount.value)}
</div>
{renderRow(...main.isMastery.value ? [mastery.minKiln, mastery.removeKiln, mastery.addKiln, mastery.maxKiln] : [minKiln, removeKiln, addKiln, maxKiln])}
{renderRow(minKiln, removeKiln, addKiln, maxKiln)}
</Column>
</>
) : undefined}
@ -1581,26 +1154,25 @@ const layer = createLayer(id, function (this: BaseLayer) {
<>
<Spacer />
<Column>
{render(main.isMastery.value ? mastery.buildDrill : buildDrill)}
{render(buildDrill)}
<div>
{formatWhole(main.isMastery.value ? mastery.activeDrills.value : activeDrills.value)}/
{formatWhole(main.isMastery.value ? mastery.buildDrill.amount.value : buildDrill.amount.value)}
{formatWhole(activeDrills.value)}/
{formatWhole(buildDrill.amount.value)}
</div>
{renderRow(...main.isMastery.value ? [mastery.minDrill, mastery.removeDrill, mastery.addDrill, mastery.maxDrill] : [minDrill, removeDrill, addDrill, maxDrill])}
{renderRow(minDrill, removeDrill, addDrill, maxDrill)}
</Column>
</>
) : undefined}
</Row>
<Spacer />
{renderGrid(...main.isMastery.value ? [mastery.row1upgrades, mastery.row2upgrades, mastery.row3upgrades] : [row1upgrades, row2upgrades, row3upgrades] )}
{renderRow(...main.isMastery.value ? mastery.row3buyables : row3buyables)}
{renderGrid(row1upgrades, row2upgrades, row3upgrades)}
{renderRow(...row3buyables)}
</>
)),
minimizedDisplay: jsx(() => (
<div>
{name} - {format(main.isMastery.value ? mastery.coal.value : coal.value)} {coal.displayName}
</div>
))
minimizedDisplay: jsx(() => (<div>{name} - {format(coal.value)} {coal.displayName}</div>)),
mastery,
swapMastery,
mastered
};
});

View file

@ -7,12 +7,12 @@ import Modal from "components/Modal.vue";
import { createCollapsibleModifierSections, setUpDailyProgressTracker } from "data/common";
import { main } from "data/projEntry";
import { createBar } from "features/bars/bar";
import { createBuyable, GenericBuyable } from "features/buyable";
import { createBuyable } from "features/buyable";
import { createClickable } from "features/clickables/clickable";
import { jsx, showIf } from "features/feature";
import { createHotkey } from "features/hotkey";
import MainDisplay from "features/resources/MainDisplay.vue";
import { createResource, Resource } from "features/resources/resource";
import { createResource, Resource, trackTotal } from "features/resources/resource";
import { createUpgrade } from "features/upgrades/upgrade";
import { globalBus } from "game/events";
import { BaseLayer, createLayer } from "game/layers";
@ -26,7 +26,6 @@ import {
import { noPersist, persistent } from "game/persistence";
import Decimal, { DecimalSource, format, formatGain, formatLimit, formatWhole } from "util/bignum";
import { Direction, WithRequired } from "util/common";
import { createLazyProxy } from "util/proxies";
import { render, renderGrid, renderRow } from "util/vue";
import { computed, ref } from "vue";
import boxes from "./boxes";
@ -52,23 +51,17 @@ const layer = createLayer(id, function (this: BaseLayer) {
const logs = createResource<DecimalSource>(0, "logs");
// Think of saplings as spent trees
const saplings = createResource<DecimalSource>(0, "saplings");
const mastered = persistent<boolean>(false);
const ema = ref<DecimalSource>(0);
const averageLogGain = ref<DecimalSource>(0);
const lastAutoCuttingAmount = ref<DecimalSource>(0);
const lastAutoPlantedAmount = ref<DecimalSource>(0);
const totalTrees = createSequentialModifier(() => [
createAdditiveModifier(() => ({
addend: () =>
Decimal.times(
(main.isMastery.value ? mastery.expandingForestBuyable : expandingForestBuyable)
.amount.value,
10
),
addend: () => Decimal.times(expandingForestBuyable.amount.value, 10),
description: "Expand Forest",
enabled: (main.isMastery.value ? mastery.researchUpgrade2 : researchUpgrade2).bought
enabled: researchUpgrade2.bought
})),
createAdditiveModifier(() => ({
addend: () => Decimal.div(workshop.foundationProgress.value, 2),
@ -98,9 +91,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
createAdditiveModifier(() => ({
addend: () => Decimal.pow(computedManualCuttingAmount.value, 0.99),
description: "Hope Level 1",
enabled: () =>
management.elfTraining.expandersElfTraining.milestones[0].earned.value &&
!main.isMastery.value
enabled: management.elfTraining.expandersElfTraining.milestones[0].earned
}))
]) as WithRequired<Modifier, "description" | "revert">;
const trees = createResource(
@ -301,14 +292,12 @@ const layer = createLayer(id, function (this: BaseLayer) {
createAdditiveModifier(() => ({
addend: 1,
description: "Wooden Fingers",
enabled: (main.isMastery ? mastery.manualCutUpgrade1 : manualCutUpgrade1).bought
enabled: manualCutUpgrade1.bought
})),
createAdditiveModifier(() => ({
addend: computedAutoCuttingAmount,
description: "Smart Knives",
enabled: main.isMastery.value
? mastery.manualCutUpgrade3.bought
: manualCutUpgrade3.bought
enabled: manualCutUpgrade3.bought
}))
]);
const computedManualCuttingAmount = computed(() => manualCuttingAmount.apply(1));
@ -316,9 +305,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
createMultiplicativeModifier(() => ({
multiplier: 0.5,
description: "Sharper Fingers",
enabled: main.isMastery.value
? mastery.manualCutUpgrade2.bought
: manualCutUpgrade2.bought
enabled: manualCutUpgrade2.bought
})),
createMultiplicativeModifier(() => ({
multiplier: () => Decimal.pow(0.5, elves.totalElves.value),
@ -367,17 +354,13 @@ const layer = createLayer(id, function (this: BaseLayer) {
createMultiplicativeModifier(() => ({
multiplier: () => Decimal.pow(1.1, main.day.value),
description: "Holly Level 4",
enabled: () =>
management.elfTraining.cutterElfTraining.milestones[3].earned.value &&
!main.isMastery.value
enabled: management.elfTraining.cutterElfTraining.milestones[3].earned
})),
createAdditiveModifier(() => ({
addend: () =>
Decimal.sub(lastAutoPlantedAmount.value, lastAutoCuttingAmount.value).max(0),
description: "Ivy Level 5",
enabled: () =>
management.elfTraining.planterElfTraining.milestones[4].earned.value &&
!main.isMastery.value
enabled: management.elfTraining.planterElfTraining.milestones[4].earned
}))
]) as WithRequired<Modifier, "description" | "revert">;
const computedAutoCuttingAmount = computed(() => autoCuttingAmount.apply(0));
@ -386,16 +369,12 @@ const layer = createLayer(id, function (this: BaseLayer) {
createAdditiveModifier(() => ({
addend: 1,
description: "Leafy Fingers",
enabled: main.isMastery.value
? mastery.manualPlantUpgrade1.bought
: manualPlantUpgrade1.bought
enabled: manualPlantUpgrade1.bought
})),
createAdditiveModifier(() => ({
addend: computedAutoPlantingAmount,
description: "Smart Spades",
enabled: main.isMastery.value
? mastery.manualPlantUpgrade3.bought
: manualPlantUpgrade3.bought
enabled: manualPlantUpgrade3.bought
}))
]);
const computedManualPlantingAmount = computed(() => manualPlantingAmount.apply(1));
@ -403,9 +382,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
createMultiplicativeModifier(() => ({
multiplier: 0.5,
description: "Greener Fingers",
enabled: main.isMastery.value
? mastery.manualPlantUpgrade2.bought
: manualPlantUpgrade2.bought
enabled: manualPlantUpgrade2.bought
})),
createMultiplicativeModifier(() => ({
multiplier: () => Decimal.pow(0.5, elves.totalElves.value),
@ -419,16 +396,11 @@ const layer = createLayer(id, function (this: BaseLayer) {
createAdditiveModifier(() => ({
addend: 1,
description: "Automated Spade",
enabled: main.isMastery.value
? mastery.autoPlantUpgrade1.bought
: autoPlantUpgrade1.bought
enabled: autoPlantUpgrade1.bought.value
})),
createAdditiveModifier(() => ({
addend: () =>
Decimal.div(
main.isMastery.value
? mastery.autoPlantingBuyable1.amount.value
: autoPlantingBuyable1.amount.value,
addend: () => Decimal.div(
autoPlantingBuyable1.amount.value,
2
),
description: "Generic Planters",
@ -462,49 +434,41 @@ const layer = createLayer(id, function (this: BaseLayer) {
createMultiplicativeModifier(() => ({
multiplier: 2,
description: "Ivy Level 1",
enabled: () =>
management.elfTraining.planterElfTraining.milestones[0].earned.value &&
!main.isMastery.value
enabled: management.elfTraining.planterElfTraining.milestones[0].earned
})),
createMultiplicativeModifier(() => ({
multiplier: () => Decimal.pow(trees.value, 0.2).max(1).log10().pow_base(2),
description: "Ivy Level 3",
enabled: () =>
management.elfTraining.planterElfTraining.milestones[2].earned.value &&
!main.isMastery.value
enabled: management.elfTraining.planterElfTraining.milestones[2].earned
})),
createMultiplicativeModifier(() => ({
multiplier: 2,
description: "Mary Level 4",
enabled: () =>
management.elfTraining.heatedPlanterElfTraining.milestones[3].earned.value &&
!main.isMastery.value
enabled: management.elfTraining.heatedPlanterElfTraining.milestones[3].earned
})),
createAdditiveModifier(() => ({
addend: () =>
Decimal.sub(lastAutoCuttingAmount.value, lastAutoPlantedAmount.value).max(0),
addend: () => Decimal.sub(lastAutoCuttingAmount.value, lastAutoPlantedAmount.value).max(0),
description: "Ivy Level 5",
enabled: () =>
management.elfTraining.planterElfTraining.milestones[4].earned.value &&
!main.isMastery.value
enabled: management.elfTraining.planterElfTraining.milestones[4].earned
}))
]) as WithRequired<Modifier, "description" | "revert">;
const computedAutoPlantingAmount = computed(() => autoPlantingAmount.apply(0));
const logGain = createSequentialModifier(() => [
createAdditiveModifier(() => ({
addend: () => totalTrees.apply(0),
description: "Tree Mastery",
enabled: () => main.isMastery.value || mastered.value
})),
createMultiplicativeModifier(() => ({
multiplier: 1.25,
description: "Research I",
enabled: main.isMastery.value
? mastery.researchUpgrade1.bought
: researchUpgrade1.bought
enabled: researchUpgrade1.bought
})),
createMultiplicativeModifier(() => ({
multiplier: 1.25,
description: "Research II",
enabled: main.isMastery.value
? mastery.researchUpgrade2.bought
: researchUpgrade2.bought
enabled: researchUpgrade2.bought
})),
createMultiplicativeModifier(() => ({
multiplier: () =>
@ -559,22 +523,12 @@ const layer = createLayer(id, function (this: BaseLayer) {
createMultiplicativeModifier(() => ({
multiplier: computed(() => Decimal.add(computedAutoCuttingAmount.value, 1).root(9)),
description: "Holly Level 1",
enabled() {
return (
management.elfTraining.cutterElfTraining.milestones[0].earned.value &&
!main.isMastery.value
);
}
enabled: management.elfTraining.cutterElfTraining.milestones[0].earned
})),
createMultiplicativeModifier(() => ({
multiplier: () => Decimal.sqrt(management.totalElfLevels.value),
description: "Noel Level 1",
enabled() {
return (
management.elfTraining.fertilizerElfTraining.milestones[0].earned.value &&
!main.isMastery.value
);
}
enabled: management.elfTraining.fertilizerElfTraining.milestones[0].earned
})),
createMultiplicativeModifier(() => ({
multiplier: wrappingPaper.boosts.christmas1,
@ -621,7 +575,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
minHeight: "80px"
},
canClick: () =>
Decimal.gte(main.isMastery.value ? mastery.trees.value : trees.value, 1) &&
Decimal.gte(trees.value, 1) &&
Decimal.gte(manualCutProgress.value, computedManualCuttingCooldown.value),
onClick() {
if (Decimal.lt(manualCutProgress.value, computedManualCuttingCooldown.value)) {
@ -629,7 +583,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
}
const amount = Decimal.floor(
Decimal.min(
main.isMastery.value ? mastery.trees.value : trees.value,
trees.value,
Decimal.times(
computedManualCuttingAmount.value,
Decimal.div(
@ -639,19 +593,8 @@ const layer = createLayer(id, function (this: BaseLayer) {
)
)
);
if (main.isMastery.value) {
mastery.logs.value = Decimal.add(
mastery.logs.value,
Decimal.times(logGain.apply(1), amount)
);
mastery.saplings.value = Decimal.add(
Decimal.mul(mastery.saplings.value, 2),
amount
);
} else {
logs.value = Decimal.add(logs.value, Decimal.times(logGain.apply(1), amount));
saplings.value = Decimal.add(saplings.value, amount);
}
logs.value = Decimal.add(logs.value, Decimal.times(logGain.apply(1), amount));
saplings.value = Decimal.add(saplings.value, amount.times((main.isMastery.value || mastered.value) ? 2 : 1));
manualCutProgress.value = 0;
}
}));
@ -683,7 +626,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
minHeight: "80px"
},
canClick: () =>
Decimal.gte(main.isMastery.value ? mastery.saplings.value : saplings.value, 1) &&
Decimal.gte(saplings.value, 1) &&
Decimal.gte(manualPlantProgress.value, computedManualPlantingCooldown.value),
onClick() {
if (Decimal.lt(manualPlantProgress.value, computedManualPlantingCooldown.value)) {
@ -691,7 +634,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
}
const amount = Decimal.floor(
Decimal.min(
main.isMastery.value ? mastery.saplings.value : saplings.value,
saplings.value,
Decimal.times(
computedManualPlantingAmount.value,
Decimal.div(
@ -701,11 +644,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
)
)
);
if (main.isMastery.value) {
mastery.saplings.value = Decimal.sub(mastery.saplings.value, amount);
} else {
saplings.value = Decimal.sub(saplings.value, amount);
}
saplings.value = Decimal.sub(saplings.value, amount);
manualPlantProgress.value = 0;
}
}));
@ -715,67 +654,55 @@ const layer = createLayer(id, function (this: BaseLayer) {
title: "Logs per Tree",
modifier: logGain,
base: 1,
visible: main.isMastery.value
? mastery.researchUpgrade1.bought
: researchUpgrade1.bought
visible: researchUpgrade1.bought
},
{
title: "Manual Cutting Amount",
modifier: manualCuttingAmount,
base: 1,
visible: main.isMastery.value
? mastery.manualCutUpgrade1.bought
: manualCutUpgrade1.bought,
visible: manualCutUpgrade1.bought,
unit: "/click"
},
{
title: "Manual Cutting Cooldown",
modifier: manualCuttingCooldown,
base: 1,
visible: main.isMastery.value
? mastery.manualCutUpgrade1.bought
: manualCutUpgrade1.bought,
visible: manualCutUpgrade1.bought,
unit: "s"
},
{
title: "Manual Planting Amount",
modifier: manualPlantingAmount,
base: 1,
visible: main.isMastery.value
? mastery.manualPlantUpgrade1.bought
: manualPlantUpgrade1.bought,
visible: manualPlantUpgrade1.bought,
unit: "/click"
},
{
title: "Manual Planting Cooldown",
modifier: manualPlantingCooldown,
base: 1,
visible: main.isMastery.value
? mastery.manualPlantUpgrade1.bought
: manualPlantUpgrade1.bought,
visible: manualPlantUpgrade1.bought,
unit: "s"
},
{
title: `Auto Cutting Amount`,
modifier: autoCuttingAmount,
base: 0,
visible: main.isMastery.value ? mastery.autoCutUpgrade1.bought : autoCutUpgrade1.bought,
visible: autoCutUpgrade1.bought,
unit: "/s"
},
{
title: `Auto Planting Amount`,
modifier: autoPlantingAmount,
base: 0,
visible: main.isMastery.value ? mastery.autoCutUpgrade1.bought : autoCutUpgrade1.bought,
visible: autoCutUpgrade1.bought,
unit: "/s"
},
{
title: `Forest Size`,
modifier: totalTrees,
base: 10,
visible: main.isMastery.value
? mastery.researchUpgrade2.bought
: researchUpgrade2.bought
visible: researchUpgrade2.bought.value
}
]);
const showModifiersModal = ref(false);
@ -824,31 +751,22 @@ const layer = createLayer(id, function (this: BaseLayer) {
lastAutoCuttingAmount.value = Decimal.isNaN(cuttingAmount) ? 0 : cuttingAmount;
const amountCut = Decimal.min(
main.isMastery ? mastery.trees.value : trees.value,
trees.value,
Decimal.times(computedAutoCuttingAmount.value, diff)
);
const logsGained = Decimal.mul(logGain.apply(1), amountCut);
const effectiveLogsGained = Decimal.div(logsGained, diff);
ema.value = Decimal.mul(effectiveLogsGained, SMOOTHING_FACTOR).add(
Decimal.mul(ema.value, Decimal.dOne.sub(SMOOTHING_FACTOR))
averageLogGain.value = Decimal.mul(effectiveLogsGained, SMOOTHING_FACTOR).add(
Decimal.mul(averageLogGain.value, Decimal.dOne.sub(SMOOTHING_FACTOR))
);
if (main.isMastery.value) {
mastery.logs.value = Decimal.add(mastery.logs.value, logsGained);
mastery.saplings.value = Decimal.add(Decimal.mul(mastery.saplings.value, 2), amountCut);
} else {
logs.value = Decimal.add(logs.value, logsGained);
saplings.value = Decimal.add(Decimal.mul(saplings.value, mastered ? 2 : 1), amountCut);
}
logs.value = Decimal.add(logs.value, logsGained);
saplings.value = Decimal.add(Decimal.mul(saplings.value, (main.isMastery.value || mastered.value) ? 2 : 1), amountCut);
const amountPlanted = Decimal.min(
saplings.value,
Decimal.times(computedAutoPlantingAmount.value, diff)
);
if (main.isMastery.value) {
mastery.saplings.value = Decimal.sub(mastery.saplings.value, amountPlanted);
} else {
saplings.value = Decimal.sub(saplings.value, amountPlanted);
}
saplings.value = Decimal.sub(saplings.value, amountPlanted);
});
const netSaplingGain = computed(() =>
@ -885,224 +803,49 @@ const layer = createLayer(id, function (this: BaseLayer) {
}
});
// This would be a lazy proxy if the typings worked properly, REEE
// Doesn't matter too much, nothing needs lazy inittialization
const mastery = (() => {
const logs = createResource<DecimalSource>(0, "logs");
const saplings = createResource<DecimalSource>(0, "saplings");
const manualCutUpgrade1 = createUpgrade(() => ({
resource: noPersist(logs),
cost: 10,
display: {
title: "Wooden Fingers",
description: "Cut down an additional tree per click"
}
}));
const manualPlantUpgrade1 = createUpgrade(() => ({
resource: noPersist(logs),
cost: 10,
display: {
title: "Leafy Fingers",
description: "Plant an additional tree per click"
}
}));
const autoCutUpgrade1 = createUpgrade(() => ({
resource: noPersist(logs),
cost: 25,
display: {
title: "Automated Knives",
description: "Cut down a tree every second"
}
}));
const autoPlantUpgrade1 = createUpgrade(() => ({
resource: noPersist(logs),
cost: 25,
display: {
title: "Automated Spade",
description: "Plant a tree every second"
}
}));
const researchUpgrade1 = createUpgrade(() => ({
resource: noPersist(logs),
cost: 40,
display: {
title: "Research I",
description: "Trees give 25% more logs, and unlock more upgrades"
}
}));
const row1Upgrades = [
manualCutUpgrade1,
manualPlantUpgrade1,
autoCutUpgrade1,
autoPlantUpgrade1,
researchUpgrade1
];
const manualCutUpgrade2 = createUpgrade(() => ({
resource: noPersist(logs),
cost: 50,
visibility: () => showIf(researchUpgrade1.bought.value),
display: {
title: "Sharper Fingers",
description: "Manually cut trees twice as often"
}
}));
const manualPlantUpgrade2 = createUpgrade(() => ({
resource: noPersist(logs),
cost: 50,
visibility: () => showIf(researchUpgrade1.bought.value),
display: {
title: "Greener Fingers",
description: "Manually Plant trees twice as often"
}
}));
const manualCutUpgrade3 = createUpgrade(() => ({
resource: noPersist(logs),
cost: 150,
visibility: () => showIf(researchUpgrade1.bought.value),
display: {
title: "Smart Knives",
description:
"Each time you manually chop trees, gain 1s of automatic tree chopping production"
}
}));
const manualPlantUpgrade3 = createUpgrade(() => ({
resource: noPersist(logs),
cost: 150,
visibility: () => showIf(researchUpgrade1.bought.value),
display: {
title: "Smart Spades",
description:
"Each time you manually plant trees, gain 1s of automatic tree planting production"
}
}));
const researchUpgrade2 = createUpgrade(() => ({
resource: noPersist(logs),
cost: 300,
visibility: () => showIf(researchUpgrade1.bought.value),
display: {
title: "Research II",
description: "Trees give 25% more logs, and unlock repeatable purchases"
}
}));
const row2Upgrades = [
manualCutUpgrade2,
manualPlantUpgrade2,
manualCutUpgrade3,
manualPlantUpgrade3,
researchUpgrade2
];
const autoCuttingBuyable1 = createBuyable(() => ({
resource: noPersist(logs),
cost() {
let v = 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, 2e6)) v = Decimal.pow(v, 2).div(2e6);
if (Decimal.gte(v, 2e30)) v = Decimal.pow(v, 10).div(Decimal.pow(2e30, 9));
v = Decimal.pow(0.95, paper.books.cuttersBook.totalAmount.value).times(v);
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, 9)).root(10);
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: {
title: "Generic Cutters",
description: "Each cutter cuts down 1 tree/s"
},
visibility: () => showIf(researchUpgrade2.bought.value)
})) as ElfBuyable & { display: { title: string }; resource: Resource };
const autoPlantingBuyable1 = createBuyable(() => ({
resource: noPersist(logs),
cost() {
let v = 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, 2e6)) v = Decimal.pow(v, 2).div(2e6);
if (Decimal.gte(v, 2e30)) v = Decimal.pow(v, 10).div(Decimal.pow(2e30, 9));
v = Decimal.pow(0.95, paper.books.plantersBook.totalAmount.value).times(v);
const cost = Decimal.times(100, v).add(200);
/*if (management.elfTraining.planterElfTraining.milestones[3].earned.value) {
cost = Decimal.div(cost, 10);
}*/
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, 9)).root(10);
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: {
title: "Generic Planters",
description: "Each planter plants 0.5 trees/s"
},
visibility: () => showIf(researchUpgrade2.bought.value)
})) as ElfBuyable & { display: { title: string }; resource: Resource };
const expandingForestBuyable = createBuyable(() => ({
resource: noPersist(logs),
cost() {
let v = this.amount.value;
if (Decimal.gte(v, 100)) v = Decimal.pow(v, 2).div(100);
if (Decimal.gte(v, 1e5)) v = Decimal.pow(v, 2).div(1e5);
if (Decimal.gte(v, 1e15)) v = Decimal.pow(v, 10).div(1e135);
v = Decimal.pow(0.95, paper.books.expandersBook.totalAmount.value).times(v);
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: {
title: "Expand Forest",
description: "Add 10 trees to the forest"
},
visibility: () => showIf(researchUpgrade2.bought.value)
})) as ElfBuyable & { display: { title: string }; resource: Resource };
const trees = createResource(
computed(() => Decimal.sub(totalTrees.apply(10), saplings.value)),
"trees"
);
return {
logs,
saplings,
trees,
manualCutUpgrade1,
manualCutUpgrade2,
manualCutUpgrade3,
manualPlantUpgrade1,
manualPlantUpgrade2,
manualPlantUpgrade3,
autoCuttingBuyable1,
autoPlantingBuyable1,
expandingForestBuyable,
researchUpgrade1,
researchUpgrade2,
autoCutUpgrade1,
autoPlantUpgrade1,
row1Buyables,
row1Upgrades,
row2Upgrades
};
})();
//mastery.manualCutUpgrade1
const mastery = {
logs: persistent<DecimalSource>(0),
totalLogs: persistent<DecimalSource>(0),
saplings: persistent<DecimalSource>(0),
row1Upgrades: [
{ bought: persistent<boolean>(false) },
{ bought: persistent<boolean>(false) },
{ bought: persistent<boolean>(false) },
{ bought: persistent<boolean>(false) },
{ bought: persistent<boolean>(false) }
],
row2Upgrades: [
{ bought: persistent<boolean>(false) },
{ bought: persistent<boolean>(false) },
{ bought: persistent<boolean>(false) },
{ bought: persistent<boolean>(false) },
{ bought: persistent<boolean>(false) }
],
row1Buyables: [
{ amount: persistent<DecimalSource>(0) },
{ amount: persistent<DecimalSource>(0) },
{ amount: persistent<DecimalSource>(0) }
]
};
function swapMastery() {
[logs.value, mastery.logs.value] = [mastery.logs.value, logs.value];
[totalLogs.value, mastery.totalLogs.value] = [mastery.totalLogs.value, totalLogs.value];
[saplings.value, mastery.saplings.value] = [mastery.saplings.value, saplings.value];
[row1Upgrades[0].bought.value, mastery.row1Upgrades[0].bought.value] = [mastery.row1Upgrades[0].bought.value, row1Upgrades[0].bought.value];
[row1Upgrades[1].bought.value, mastery.row1Upgrades[1].bought.value] = [mastery.row1Upgrades[1].bought.value, row1Upgrades[1].bought.value];
[row1Upgrades[2].bought.value, mastery.row1Upgrades[2].bought.value] = [mastery.row1Upgrades[2].bought.value, row1Upgrades[2].bought.value];
[row1Upgrades[3].bought.value, mastery.row1Upgrades[3].bought.value] = [mastery.row1Upgrades[3].bought.value, row1Upgrades[3].bought.value];
[row1Upgrades[4].bought.value, mastery.row1Upgrades[4].bought.value] = [mastery.row1Upgrades[4].bought.value, row1Upgrades[4].bought.value];
[row2Upgrades[0].bought.value, mastery.row2Upgrades[0].bought.value] = [mastery.row2Upgrades[0].bought.value, row2Upgrades[0].bought.value];
[row2Upgrades[1].bought.value, mastery.row2Upgrades[1].bought.value] = [mastery.row2Upgrades[1].bought.value, row2Upgrades[1].bought.value];
[row2Upgrades[2].bought.value, mastery.row2Upgrades[2].bought.value] = [mastery.row2Upgrades[2].bought.value, row2Upgrades[2].bought.value];
[row2Upgrades[3].bought.value, mastery.row2Upgrades[3].bought.value] = [mastery.row2Upgrades[3].bought.value, row2Upgrades[3].bought.value];
[row2Upgrades[4].bought.value, mastery.row2Upgrades[4].bought.value] = [mastery.row2Upgrades[4].bought.value, row2Upgrades[4].bought.value];
[row1Buyables[0].amount.value, mastery.row1Buyables[0].amount.value] = [mastery.row1Buyables[0].amount.value, row1Buyables[0].amount.value];
[row1Buyables[1].amount.value, mastery.row1Buyables[1].amount.value] = [mastery.row1Buyables[1].amount.value, row1Buyables[1].amount.value];
[row1Buyables[2].amount.value, mastery.row1Buyables[2].amount.value] = [mastery.row1Buyables[2].amount.value, row1Buyables[2].amount.value];
}
const mastered = persistent<boolean>(false);
return {
name,
@ -1122,19 +865,18 @@ const layer = createLayer(id, function (this: BaseLayer) {
manualPlantProgress,
generalTabCollapsed,
computedAutoCuttingAmount,
mastery,
minWidth: 700,
display: jsx(() => (
<>
{render(trackerDisplay)}
<Spacer />
<MainDisplay
resource={main.isMastery.value ? mastery.logs : logs}
resource={logs}
color={colorBright}
style="margin-bottom: 0"
productionDisplay={
Decimal.gt(computedAutoCuttingAmount.value, 0)
? `+${format(ema.value)}/s average<br/>equilibrium: +${formatLimit(
? `+${format(averageLogGain.value)}/s average<br/>equilibrium: +${formatLimit(
[
[computedAutoCuttingAmount.value, "cutting speed"],
[computedAutoPlantingAmount.value, "planting speed"],
@ -1147,13 +889,13 @@ const layer = createLayer(id, function (this: BaseLayer) {
}
/>
<MainDisplay
resource={main.isMastery.value ? mastery.saplings : saplings}
resource={saplings}
color={colorDark}
style="margin-bottom: 0"
productionDisplay={formatGain(netSaplingGain.value)}
/>
<MainDisplay
resource={main.isMastery.value ? mastery.trees : trees}
resource={trees}
color={colorDark}
style="margin-bottom: 0"
productionDisplay={formatGain(netTreeGain.value)}
@ -1162,22 +904,15 @@ const layer = createLayer(id, function (this: BaseLayer) {
{renderRow(cutTree, plantTree)}
<div>Tip: You can hold down on actions to perform them automatically</div>
<Spacer />
{renderGrid(
...(main.isMastery.value
? [mastery.row1Upgrades, mastery.row2Upgrades]
: [row1Upgrades, row2Upgrades])
)}
{renderGrid(row1Upgrades, row2Upgrades)}
<Spacer />
{renderRow(...(main.isMastery.value ? mastery.row1Buyables : row1Buyables))}
{renderRow(...row1Buyables)}
</>
)),
minimizedDisplay: jsx(() => (
<div>
{name} - {format(main.isMastery.value ? mastery.logs.value : logs.value)}{" "}
{logs.displayName}
</div>
)),
mastered
minimizedDisplay: jsx(() => (<div>{name} - {format(logs.value)} {logs.displayName}</div>)),
mastery,
swapMastery,
mastered,
};
});

View file

@ -39,7 +39,6 @@ const layer = createLayer(id, function (this: BaseLayer) {
const name = "Workshop";
const color = "#D66B02";
const colorDark = "#D66B02";
const mastered = persistent<boolean>(false);
const foundationProgress = createResource<DecimalSource>(0, "foundation progress");
@ -52,9 +51,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
createExponentialModifier(() => ({
exponent: 0.99,
description: "Holly Level 5",
enabled: () =>
management.elfTraining.cutterElfTraining.milestones[4].earned.value &&
!main.isMastery.value
enabled: management.elfTraining.cutterElfTraining.milestones[4].earned
}))
]);
@ -81,6 +78,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
roundUpCost: true,
// buyMax: management.elfTraining.expandersElfTraining.milestones[2].earned,
spend(gain, spent) {
if (main.isMastery.value || mastered.value) return;
trees.logs.value = Decimal.sub(trees.logs.value, spent);
}
}));
@ -90,73 +88,40 @@ const layer = createLayer(id, function (this: BaseLayer) {
<>
<b style="font-size: x-large">
Build{" "}
{formatWhole(
(main.isMastery.value ? mastery.foundationConversion : foundationConversion)
.actualGain.value
)}
{formatWhole(foundationConversion.actualGain.value)}
% of the foundation
</b>
<br />
<br />
<span style="font-size: large">
{main.isMastery.value || mastered ? "Requirement" : "Cost"}:{" "}
{(main.isMastery.value || mastered.value) ? "Requirement" : "Cost"}:{" "}
{displayResource(
main.isMastery.value ? trees.mastery.logs : trees.logs,
Decimal.gte(
(main.isMastery.value
? mastery.foundationConversion
: foundationConversion
).actualGain.value,
1
)
? (main.isMastery.value
? mastery.foundationConversion
: foundationConversion
).currentAt.value
: (main.isMastery.value
? mastery.foundationConversion
: foundationConversion
).nextAt.value
)}{" "}
{trees.logs.displayName}
trees.logs,
Decimal.gte(foundationConversion.actualGain.value, 1)
? foundationConversion.currentAt.value
: foundationConversion.nextAt.value
)} {trees.logs.displayName}
</span>
</>
)),
visibility: () =>
showIf(
main.isMastery.value
? Decimal.lt(mastery.foundationProgress.value, 100)
: Decimal.lt(
foundationProgress.value,
management.elfTraining.expandersElfTraining.milestones[2].earned.value
? 1000
: 100
)
),
showIf(Decimal.lt(
foundationProgress.value,
management.elfTraining.expandersElfTraining.milestones[2].earned.value
? 1000
: 100
)),
canClick: () => {
if (main.isMastery.value) {
if (
Decimal.lt(trees.mastery.logs.value, mastery.foundationConversion.nextAt.value)
) {
return false;
}
if (Decimal.gte(foundationProgress.value, 100)) {
return false;
}
} else {
if (Decimal.lt(trees.logs.value, foundationConversion.nextAt.value)) {
return false;
}
if (
Decimal.gte(
foundationProgress.value,
management.elfTraining.expandersElfTraining.milestones[2].earned.value
? 1000
: 100
)
) {
return false;
}
if (Decimal.lt(trees.logs.value, foundationConversion.nextAt.value)) {
return false;
}
if (Decimal.gte(
foundationProgress.value,
management.elfTraining.expandersElfTraining.milestones[2].earned.value
? 1000
: 100
)) {
return false;
}
return true;
},
@ -164,7 +129,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
if (!unref(this.canClick)) {
return;
}
(main.isMastery.value ? mastery.foundationConversion : foundationConversion).convert();
foundationConversion.convert();
},
style: "width: 600px; min-height: unset"
}));
@ -350,200 +315,41 @@ const layer = createLayer(id, function (this: BaseLayer) {
}
});
const mastery = (() => {
const foundationProgress = createResource<DecimalSource>(0, "foundation progress");
const foundationConversion = createIndependentConversion(() => ({
scaling: addSoftcap(
addSoftcap(
createPolynomialScaling(addScaling(250), 1.5),
addScaling(5423),
1 / 1e10
),
addScaling(1e20),
3e8
),
baseResource: trees.logs,
gainResource: noPersist(foundationProgress),
roundUpCost: true,
// buyMax: management.elfTraining.expandersElfTraining.milestones[2].earned,
spend(gain, spent) {}
}));
const logGainMilestone1 = createMilestone(() => ({
display: {
requirement: "1% Foundation Completed",
effectDisplay: "Trees give 5% more logs for each % of foundation completed"
},
shouldEarn: () => Decimal.gte(foundationProgress.value, 1),
showPopups: shouldShowPopups
}));
const autoCutMilestone1 = createMilestone(() => ({
display: {
requirement: "10% Foundation Completed",
effectDisplay:
"Cut an additional tree per second for each 5% of foundation completed"
},
shouldEarn: () => Decimal.gte(foundationProgress.value, 10),
visibility: () => showIf(logGainMilestone1.earned.value),
showPopups: shouldShowPopups
}));
const autoPlantMilestone1 = createMilestone(() => ({
display: {
requirement: "20% Foundation Completed",
effectDisplay:
"Plant an additional tree per second for each 10% of foundation completed"
},
shouldEarn: () => Decimal.gte(foundationProgress.value, 20),
visibility: () => showIf(autoCutMilestone1.earned.value),
showPopups: shouldShowPopups
}));
const autoCutMilestone2 = createMilestone(() => ({
display: {
requirement: "30% Foundation Completed",
effectDisplay: "All automatic tree cutting is doubled"
},
shouldEarn: () => Decimal.gte(foundationProgress.value, 30),
visibility: () => showIf(autoPlantMilestone1.earned.value),
showPopups: shouldShowPopups
}));
const autoPlantMilestone2 = createMilestone(() => ({
display: {
requirement: "40% Foundation Completed",
effectDisplay: "All automatic tree planting is doubled"
},
shouldEarn: () => Decimal.gte(foundationProgress.value, 40),
visibility: () => showIf(autoCutMilestone2.earned.value),
showPopups: shouldShowPopups
}));
const logGainMilestone2 = createMilestone(() => ({
display: {
requirement: "50% Foundation Completed",
effectDisplay: "Trees give twice as many logs"
},
shouldEarn: () => Decimal.gte(foundationProgress.value, 50),
visibility: () => showIf(autoPlantMilestone2.earned.value),
showPopups: shouldShowPopups
}));
const morePlantsMilestone1 = createMilestone(() => ({
display: {
requirement: "75% Foundation Completed",
effectDisplay: "The forest gains an extra tree for every 2% of foundation completed"
},
shouldEarn: () => Decimal.gte(foundationProgress.value, 75),
visibility: () => showIf(logGainMilestone2.earned.value),
showPopups: shouldShowPopups
}));
const logGainMilestone3 = createMilestone(() => ({
display: {
requirement: "100% Foundation Completed",
effectDisplay: "Log per tree is raised to the 1.2th power"
},
shouldEarn: () => Decimal.gte(foundationProgress.value, 100),
visibility: () => showIf(morePlantsMilestone1.earned.value),
showPopups: shouldShowPopups
}));
const extraExpansionMilestone1 = createMilestone(() => ({
display: {
requirement: "200% Foundation Completed",
effectDisplay: "The 1% milestone is now +2% and multiplicative"
},
shouldEarn: () => Decimal.gte(foundationProgress.value, 200),
visibility: () =>
showIf(
logGainMilestone3.earned.value &&
management.elfTraining.expandersElfTraining.milestones[2].earned.value
),
showPopups: shouldShowPopups
}));
const extraExpansionMilestone2 = createMilestone(() => ({
display: {
requirement: "400% Foundation Completed",
effectDisplay: "Gain +10% metal for every 10% foundation completed"
},
shouldEarn: () => Decimal.gte(foundationProgress.value, 400),
visibility: () =>
showIf(
extraExpansionMilestone1.earned.value &&
management.elfTraining.expandersElfTraining.milestones[2].earned.value
),
showPopups: shouldShowPopups
}));
const extraExpansionMilestone3 = createMilestone(() => ({
display: {
requirement: "600% Foundation Completed",
effectDisplay: "Gain +10% oil for every 10% foundation completed"
},
shouldEarn: () => Decimal.gte(foundationProgress.value, 600),
visibility: () =>
showIf(
extraExpansionMilestone2.earned.value &&
management.elfTraining.expandersElfTraining.milestones[2].earned.value
),
showPopups: shouldShowPopups
}));
const extraExpansionMilestone4 = createMilestone(() => ({
display: {
requirement: "800% Foundation Completed",
effectDisplay: "Gain +10% plastic for every 10% foundation completed"
},
shouldEarn: () => Decimal.gte(foundationProgress.value, 800),
visibility: () =>
showIf(
extraExpansionMilestone3.earned.value &&
management.elfTraining.expandersElfTraining.milestones[2].earned.value
),
showPopups: shouldShowPopups
}));
const extraExpansionMilestone5 = createMilestone(() => ({
display: {
requirement: "1000% Foundation Completed",
effectDisplay: "Double paper, boxes, and all cloth actions"
},
shouldEarn: () => Decimal.gte(foundationProgress.value, 1000),
visibility: () =>
showIf(
extraExpansionMilestone4.earned.value &&
management.elfTraining.expandersElfTraining.milestones[2].earned.value
),
showPopups: shouldShowPopups
}));
const milestones = {
logGainMilestone1,
autoCutMilestone1,
autoPlantMilestone1,
autoCutMilestone2,
autoPlantMilestone2,
logGainMilestone2,
morePlantsMilestone1,
logGainMilestone3,
extraExpansionMilestone1,
extraExpansionMilestone2,
extraExpansionMilestone3,
extraExpansionMilestone4,
extraExpansionMilestone5
};
const { collapseMilestones, display: milestonesDisplay } =
createCollapsibleMilestones(milestones);
return {
foundationProgress,
foundationConversion,
milestones,
collapseMilestones,
milestonesDisplay,
logGainMilestone1,
autoCutMilestone1,
autoPlantMilestone1,
autoCutMilestone2,
autoPlantMilestone2,
logGainMilestone2,
morePlantsMilestone1,
logGainMilestone3,
extraExpansionMilestone1,
extraExpansionMilestone2,
extraExpansionMilestone3,
extraExpansionMilestone4,
extraExpansionMilestone5
};
})();
const mastery = {
foundationProgress: persistent<DecimalSource>(0),
milestones: {
logGainMilestone1: { earned: persistent<boolean>(false) },
autoCutMilestone1: { earned: persistent<boolean>(false) },
autoPlantMilestone1: { earned: persistent<boolean>(false) },
autoCutMilestone2: { earned: persistent<boolean>(false) },
autoPlantMilestone2: { earned: persistent<boolean>(false) },
logGainMilestone2: { earned: persistent<boolean>(false) },
morePlantsMilestone1: { earned: persistent<boolean>(false) },
logGainMilestone3: { earned: persistent<boolean>(false) },
extraExpansionMilestone1: { earned: persistent<boolean>(false) },
extraExpansionMilestone2: { earned: persistent<boolean>(false) },
extraExpansionMilestone3: { earned: persistent<boolean>(false) },
extraExpansionMilestone4: { earned: persistent<boolean>(false) },
extraExpansionMilestone5: { earned: persistent<boolean>(false) },
}
};
function swapMastery() {
[foundationProgress.value, mastery.foundationProgress.value] = [mastery.foundationProgress.value, foundationProgress.value];
[milestones.logGainMilestone1.earned.value, mastery.milestones.logGainMilestone1.earned.value] = [mastery.milestones.logGainMilestone1.earned.value, milestones.logGainMilestone1.earned.value];
[milestones.autoCutMilestone1.earned.value, mastery.milestones.autoCutMilestone1.earned.value] = [mastery.milestones.autoCutMilestone1.earned.value, milestones.autoCutMilestone1.earned.value];
[milestones.autoPlantMilestone1.earned.value, mastery.milestones.autoPlantMilestone1.earned.value] = [mastery.milestones.autoPlantMilestone1.earned.value, milestones.autoPlantMilestone1.earned.value];
[milestones.autoCutMilestone2.earned.value, mastery.milestones.autoCutMilestone2.earned.value] = [mastery.milestones.autoCutMilestone2.earned.value, milestones.autoCutMilestone2.earned.value];
[milestones.autoPlantMilestone2.earned.value, mastery.milestones.autoPlantMilestone2.earned.value] = [mastery.milestones.autoPlantMilestone2.earned.value, milestones.autoPlantMilestone2.earned.value];
[milestones.logGainMilestone2.earned.value, mastery.milestones.logGainMilestone2.earned.value] = [mastery.milestones.logGainMilestone2.earned.value, milestones.logGainMilestone2.earned.value];
[milestones.morePlantsMilestone1.earned.value, mastery.milestones.morePlantsMilestone1.earned.value] = [mastery.milestones.morePlantsMilestone1.earned.value, milestones.morePlantsMilestone1.earned.value];
[milestones.logGainMilestone3.earned.value, mastery.milestones.logGainMilestone3.earned.value] = [mastery.milestones.logGainMilestone3.earned.value, milestones.logGainMilestone3.earned.value];
[milestones.extraExpansionMilestone1.earned.value, mastery.milestones.extraExpansionMilestone1.earned.value] = [mastery.milestones.extraExpansionMilestone1.earned.value, milestones.extraExpansionMilestone1.earned.value];
[milestones.extraExpansionMilestone2.earned.value, mastery.milestones.extraExpansionMilestone2.earned.value] = [mastery.milestones.extraExpansionMilestone2.earned.value, milestones.extraExpansionMilestone2.earned.value];
[milestones.extraExpansionMilestone3.earned.value, mastery.milestones.extraExpansionMilestone3.earned.value] = [mastery.milestones.extraExpansionMilestone3.earned.value, milestones.extraExpansionMilestone3.earned.value];
[milestones.extraExpansionMilestone4.earned.value, mastery.milestones.extraExpansionMilestone4.earned.value] = [mastery.milestones.extraExpansionMilestone4.earned.value, milestones.extraExpansionMilestone4.earned.value];
[milestones.extraExpansionMilestone5.earned.value, mastery.milestones.extraExpansionMilestone5.earned.value] = [mastery.milestones.extraExpansionMilestone5.earned.value, milestones.extraExpansionMilestone5.earned.value];
}
const mastered = persistent<boolean>(false);
return {
name,
@ -555,8 +361,6 @@ const layer = createLayer(id, function (this: BaseLayer) {
collapseMilestones,
minWidth: 700,
buildFoundationHK,
mastery,
mastered,
display: jsx(() => (
<>
<div>
@ -569,11 +373,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
<div>
<span>The foundation is </span>
<h2 style={`color: ${color}; text-shadow: 0 0 10px ${color}`}>
{formatWhole(
main.isMastery.value
? mastery.foundationProgress.value
: foundationProgress.value
)}
{formatWhole(foundationProgress.value)}
</h2>
% completed
</div>
@ -583,14 +383,13 @@ const layer = createLayer(id, function (this: BaseLayer) {
) : null}
{render(buildFoundation)}
<Spacer />
{(main.isMastery.value ? mastery.milestonesDisplay : milestonesDisplay)()}
{milestonesDisplay()}
</>
)),
minimizedDisplay: jsx(() => (
<div>
{name} - {format(foundationProgress.value)}% {foundationProgress.displayName}
</div>
))
minimizedDisplay: jsx(() => (<div>{name} - {format(foundationProgress.value)}% {foundationProgress.displayName}</div>)),
mastery,
swapMastery,
mastered
};
});

View file

@ -7,7 +7,7 @@ import {
jsx
} from "features/feature";
import { BaseLayer, createLayer, GenericLayer, layers } from "game/layers";
import { persistent } from "game/persistence";
import { Persistent, persistent } from "game/persistence";
import type { LayerData, PlayerData } from "game/player";
import player from "game/player";
import Decimal, { format, formatTime } from "util/bignum";
@ -49,7 +49,6 @@ import dyes from "./layers/dyes";
import letters from "./layers/letters";
import management from "./layers/management";
import wrappingPaper from "./layers/wrapping-paper";
import { createReset } from "features/reset";
export interface Day extends VueFeature {
day: number;
@ -62,20 +61,6 @@ export interface Day extends VueFeature {
shouldNotify: ProcessedComputable<boolean>;
}
const masterableLayers = [
trees,
workshop,
coal,
elves,
paper,
boxes,
metal,
cloth,
oil,
plastic,
dyes
];
export const main = createLayer("main", function (this: BaseLayer) {
const day = persistent<number>(1);
const timeUntilNewDay = computed(
@ -87,9 +72,29 @@ export const main = createLayer("main", function (this: BaseLayer) {
const loreTitle = ref<string>("");
const loreBody = ref<CoercableComponent | undefined>();
const swappingMastery = ref(false);
const isMastery = persistent<boolean>(false);
const toggleMastery = () => {
swappingMastery.value = true;
isMastery.value = !isMastery.value;
for (const layer of [
trees,
workshop,
coal,
// elves,
// paper,
// boxes,
// metal,
// cloth,
// oil,
// plastic,
// dyes,
// management,
// letters
]) { layer.swapMastery() }
swappingMastery.value = false;
};
function createDay(
@ -420,6 +425,7 @@ export const main = createLayer("main", function (this: BaseLayer) {
minWidth: 700,
isMastery,
toggleMastery,
swappingMastery,
display: jsx(() => (
<>
{player.devSpeed === 0 ? <div>Game Paused</div> : null}

View file

@ -1,3 +1,4 @@
import { main } from "data/projEntry";
import { globalBus } from "game/events";
import { NonPersistent, Persistent, State } from "game/persistence";
import { persistent } from "game/persistence";
@ -67,7 +68,7 @@ export function trackBest(resource: Resource): Ref<DecimalSource> {
export function trackTotal(resource: Resource): Ref<DecimalSource> {
const total = persistent(resource.value);
watch(resource, (amount, prevAmount) => {
if (loadingSave.value) {
if (loadingSave.value || main.swappingMastery.value) {
return;
}
if (Decimal.gt(amount, prevAmount)) {