basic management layer

This commit is contained in:
circle-gon 2022-12-10 22:38:42 +00:00
commit c24255acc3
22 changed files with 1587 additions and 156 deletions

4
package-lock.json generated
View file

@ -49,7 +49,7 @@
"vue-tsc": "^0.38.1" "vue-tsc": "^0.38.1"
}, },
"engines": { "engines": {
"node": "16.x" "node": ">=16"
} }
}, },
"node_modules/@ampproject/remapping": { "node_modules/@ampproject/remapping": {
@ -6749,7 +6749,6 @@
"node_modules/vue-panzoom": { "node_modules/vue-panzoom": {
"version": "1.1.6", "version": "1.1.6",
"resolved": "git+ssh://git@github.com/thepaperpilot/vue-panzoom.git#fa3cc91f6842cdfbd1bfb433c75cac01f177fe2d", "resolved": "git+ssh://git@github.com/thepaperpilot/vue-panzoom.git#fa3cc91f6842cdfbd1bfb433c75cac01f177fe2d",
"integrity": "sha512-d4URo4PVl2jCFG1WNY+5lDQ8nloOVLf2gFLqE+TLNmF43+F/STgld0A58uf9aq2xbaupVJdZAp/prGtve9ESRQ==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"panzoom": "^9.4.1" "panzoom": "^9.4.1"
@ -11902,7 +11901,6 @@
}, },
"vue-panzoom": { "vue-panzoom": {
"version": "git+ssh://git@github.com/thepaperpilot/vue-panzoom.git#fa3cc91f6842cdfbd1bfb433c75cac01f177fe2d", "version": "git+ssh://git@github.com/thepaperpilot/vue-panzoom.git#fa3cc91f6842cdfbd1bfb433c75cac01f177fe2d",
"integrity": "sha512-d4URo4PVl2jCFG1WNY+5lDQ8nloOVLf2gFLqE+TLNmF43+F/STgld0A58uf9aq2xbaupVJdZAp/prGtve9ESRQ==",
"from": "vue-panzoom@https://github.com/thepaperpilot/vue-panzoom.git", "from": "vue-panzoom@https://github.com/thepaperpilot/vue-panzoom.git",
"requires": { "requires": {
"panzoom": "^9.4.1" "panzoom": "^9.4.1"

View file

@ -55,6 +55,6 @@
"vue-tsc": "^0.38.1" "vue-tsc": "^0.38.1"
}, },
"engines": { "engines": {
"node": "16.x" "node": ">=16"
} }
} }

View file

@ -56,6 +56,43 @@
border-radius: var(--border-radius); border-radius: var(--border-radius);
} }
.row-grid.mergeAdjacent > .feature:not(.dontMerge),
.row-grid.mergeAdjacent > .tooltip-container > .feature:not(.dontMerge) {
margin-left: 0;
margin-right: 0;
margin-bottom: 0;
margin-top: 0;
border-radius: 0;
}
.row-grid.mergeAdjacent > .feature:not(.dontMerge):last-child,
.row-grid.mergeAdjacent > .tooltip-container:last-child > .feature:not(.dontMerge) {
border-radius: 0 0 0 0;
}
.row-grid.mergeAdjacent > .feature:not(.dontMerge):first-child,
.row-grid.mergeAdjacent > .tooltip-container:first-child > .feature:not(.dontMerge) {
border-radius: 0 0 0 0;
}
.table-grid > .row-grid.mergeAdjacent:last-child > .feature:not(.dontMerge):first-child {
border-radius: 0 0 0 var(--border-radius);
}
.table-grid > .row-grid.mergeAdjacent:first-child > .feature:not(.dontMerge):last-child {
border-radius: 0 var(--border-radius) 0 0;
}
.table-grid > .row-grid.mergeAdjacent:first-child > .feature:not(.dontMerge):first-child {
border-radius: var(--border-radius) 0 0 0;
}
.table-grid > .row-grid.mergeAdjacent:last-child > .feature:not(.dontMerge):last-child {
border-radius: 0 0 var(--border-radius) 0;
}
/* /*
TODO how to implement mergeAdjacent for grids? TODO how to implement mergeAdjacent for grids?
.row.mergeAdjacent + .row.mergeAdjacent > .feature:not(.dontMerge) { .row.mergeAdjacent + .row.mergeAdjacent > .feature:not(.dontMerge) {

View file

@ -20,16 +20,13 @@
class="scene-item" class="scene-item"
style="left: 72%; bottom: 8%; width: 40px; height: 40px" style="left: 72%; bottom: 8%; width: 40px; height: 40px"
/> />
<img <img v-if="day >= 8" :src="oil" class="scene-item" style="left: 80%; bottom: 6%" />
v-if="(day >= 8)"
:src="oil"
class="scene-item"
style="left: 80%; bottom: 6%"
/>
<img v-if="day >= 3" :src="elves" class="scene-item" style="left: 52%; bottom: 12%" /> <img v-if="day >= 3" :src="elves" class="scene-item" style="left: 52%; bottom: 12%" />
<div v-if="day >= 4" class="scene-bubble" style="left: 50%; bottom: 38%"> <div v-if="day >= 4" class="scene-bubble" style="left: 50%; bottom: 38%">
<img v-if="day >= 4" :src="paper" class="scene-item" /> <img v-if="day >= 4" :src="paper" class="scene-item" />
<img v-if="day >= 5" :src="boxes" class="scene-item" /> <img v-if="day >= 5" :src="boxes" class="scene-item" />
<img v-if="day >= 9" :src="plastic" class="scene-item" />
<img v-if="day >= 10" :src="dyes" class="scene-item" />
</div> </div>
</div> </div>
</template> </template>
@ -44,6 +41,8 @@ import boxes from "./symbols/cardboardBox.png";
import metal from "./symbols/metal.png"; import metal from "./symbols/metal.png";
import cloth from "./symbols/cloth.png"; import cloth from "./symbols/cloth.png";
import oil from "./symbols/oil.png"; import oil from "./symbols/oil.png";
import plastic from "./symbols/plastic.png";
import dyes from "./symbols/dyes.png";
defineProps<{ defineProps<{
day: number; day: number;

View file

@ -417,8 +417,9 @@ export function setUpDailyProgressTracker(options: {
display: VueFeature | CoercableComponent; display: VueFeature | CoercableComponent;
}; };
usingLog?: Ref<boolean>; usingLog?: Ref<boolean>;
ignoreTotal?: boolean
}) { }) {
const total = trackTotal(options.resource); const total = options.ignoreTotal ? options.resource : trackTotal(options.resource);
const progressFunc = () => { const progressFunc = () => {
if (main.day.value !== options.day) return 1; if (main.day.value !== options.day) return 1;
let progress = Decimal.add(total.value, 1); let progress = Decimal.add(total.value, 1);
@ -452,7 +453,7 @@ export function setUpDailyProgressTracker(options: {
<div> <div>
{main.day.value === options.day ? ( {main.day.value === options.day ? (
<> <>
Reach {formatWhole(options.goal)} total {options.resource.displayName} to Reach {formatWhole(options.goal)} {options.ignoreTotal ? "" : ("total ")}{options.resource.displayName} to
complete the day complete the day
</> </>
) : ( ) : (

View file

@ -10,14 +10,18 @@ import { createClickable } from "features/clickables/clickable";
import { createCumulativeConversion, createPolynomialScaling } from "features/conversion"; import { createCumulativeConversion, createPolynomialScaling } from "features/conversion";
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 } from "features/resources/resource"; import { createResource, displayResource, Resource } from "features/resources/resource";
import { createUpgrade } from "features/upgrades/upgrade"; import { createUpgrade } from "features/upgrades/upgrade";
import { globalBus } from "game/events";
import { BaseLayer, createLayer } from "game/layers"; import { BaseLayer, createLayer } from "game/layers";
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 { render, renderRow } from "util/vue"; import { render, renderRow } from "util/vue";
import { unref } from "vue"; import { unref } from "vue";
import paper from "./paper";
import plastic from "./plastic";
import trees from "./trees"; import trees from "./trees";
import dyes from "./dyes";
const id = "boxes"; const id = "boxes";
const day = 6; const day = 6;
@ -100,6 +104,35 @@ const layer = createLayer(id, function (this: BaseLayer) {
})); }));
const upgrades = { logsUpgrade, ashUpgrade, coalUpgrade }; const upgrades = { logsUpgrade, ashUpgrade, coalUpgrade };
const oreUpgrade = createUpgrade(() => ({
resource: noPersist(boxes),
cost: 1e8,
visibility: () => showIf(plastic.upgrades.boxTools.bought.value),
display: {
title: "Carry ore in boxes",
description: "Double ore per mining op"
}
}));
const metalUpgrade = createUpgrade(() => ({
resource: noPersist(boxes),
cost: 1e9,
visibility: () => showIf(plastic.upgrades.boxTools.bought.value),
display: {
title: "Carry metal in boxes",
description: "Double ore purity"
}
}));
const plasticUpgrade = createUpgrade(() => ({
resource: noPersist(boxes),
cost: 1e10,
visibility: () => showIf(plastic.upgrades.boxTools.bought.value),
display: {
title: "Carry plastic in boxes",
description: "Double plastic gain"
}
}));
const row2Upgrades = { oreUpgrade, metalUpgrade, plasticUpgrade };
const logBoxesBuyable = createBuyable(() => ({ const logBoxesBuyable = createBuyable(() => ({
display: { display: {
title: "Carry more logs", title: "Carry more logs",
@ -110,10 +143,12 @@ const layer = createLayer(id, function (this: BaseLayer) {
}, },
resource: noPersist(boxes), resource: noPersist(boxes),
cost() { cost() {
return Decimal.pow(3, logBoxesBuyable.amount.value).times(100); let v = this.amount.value;
v = Decimal.pow(0.95, paper.books.boxBook.amount.value).times(v);
return Decimal.pow(3, v).times(100).div(dyes.boosts.orange2.value);
}, },
visibility: () => showIf(logsUpgrade.bought.value) visibility: () => showIf(logsUpgrade.bought.value)
})) as GenericBuyable; })) as GenericBuyable & { resource: Resource };
const ashBoxesBuyable = createBuyable(() => ({ const ashBoxesBuyable = createBuyable(() => ({
display: { display: {
title: "Carry more ash", title: "Carry more ash",
@ -124,10 +159,12 @@ const layer = createLayer(id, function (this: BaseLayer) {
}, },
resource: noPersist(boxes), resource: noPersist(boxes),
cost() { cost() {
return Decimal.pow(5, ashBoxesBuyable.amount.value).times(1000); let v = this.amount.value;
v = Decimal.pow(0.95, paper.books.boxBook.amount.value).times(v);
return Decimal.pow(5, v).times(1000).div(dyes.boosts.orange2.value);;
}, },
visibility: () => showIf(ashUpgrade.bought.value) visibility: () => showIf(ashUpgrade.bought.value)
})) as GenericBuyable; })) as GenericBuyable & { resource: Resource };
const coalBoxesBuyable = createBuyable(() => ({ const coalBoxesBuyable = createBuyable(() => ({
display: { display: {
title: "Carry more coal", title: "Carry more coal",
@ -138,12 +175,25 @@ const layer = createLayer(id, function (this: BaseLayer) {
}, },
resource: noPersist(boxes), resource: noPersist(boxes),
cost() { cost() {
return Decimal.pow(7, coalBoxesBuyable.amount.value).times(1000); let v = this.amount.value;
v = Decimal.pow(0.95, paper.books.boxBook.amount.value).times(v);
return Decimal.pow(7, v).times(1000).div(dyes.boosts.orange2.value);
}, },
visibility: () => showIf(coalUpgrade.bought.value) visibility: () => showIf(coalUpgrade.bought.value)
})) as GenericBuyable; })) as GenericBuyable & { resource: Resource };
const buyables = { logBoxesBuyable, ashBoxesBuyable, coalBoxesBuyable }; const buyables = { logBoxesBuyable, ashBoxesBuyable, coalBoxesBuyable };
globalBus.on("update", diff => {
if (Decimal.lt(main.day.value, day)) {
return;
}
boxes.value = Decimal.times(diff, plastic.buyables.passiveBoxes.amount.value)
.times(boxesConversion.currentGain.value)
.div(100)
.add(boxes.value);
});
const { total: totalBoxes, trackerDisplay } = setUpDailyProgressTracker({ const { total: totalBoxes, trackerDisplay } = setUpDailyProgressTracker({
resource: boxes, resource: boxes,
goal: 5e4, goal: 5e4,
@ -160,6 +210,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
totalBoxes, totalBoxes,
boxesConversion, boxesConversion,
upgrades, upgrades,
row2Upgrades,
buyables, buyables,
minWidth: 700, minWidth: 700,
display: jsx(() => ( display: jsx(() => (
@ -171,6 +222,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
{render(makeBoxes)} {render(makeBoxes)}
<Spacer /> <Spacer />
{renderRow(...Object.values(upgrades))} {renderRow(...Object.values(upgrades))}
{renderRow(...Object.values(row2Upgrades))}
{renderRow(...Object.values(buyables))} {renderRow(...Object.values(buyables))}
</> </>
)) ))

View file

@ -8,16 +8,20 @@ import Modal from "components/Modal.vue";
import { createCollapsibleModifierSections, setUpDailyProgressTracker } from "data/common"; import { createCollapsibleModifierSections, setUpDailyProgressTracker } from "data/common";
import { main } from "data/projEntry"; import { main } from "data/projEntry";
import { createBar } from "features/bars/bar"; import { createBar } 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 } from "features/feature"; import { jsx, showIf } from "features/feature";
import { createHotkey } from "features/hotkey"; import { createHotkey } from "features/hotkey";
import MainDisplay from "features/resources/MainDisplay.vue"; import MainDisplay from "features/resources/MainDisplay.vue";
import { createResource } from "features/resources/resource"; import { createResource, Resource } from "features/resources/resource";
import { createUpgrade } from "features/upgrades/upgrade"; import { createUpgrade } 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 { createAdditiveModifier, createSequentialModifier } from "game/modifiers"; import {
createAdditiveModifier,
createMultiplicativeModifier,
createSequentialModifier
} from "game/modifiers";
import { noPersist, persistent } from "game/persistence"; import { noPersist, persistent } from "game/persistence";
import Decimal, { DecimalSource } from "util/bignum"; import Decimal, { DecimalSource } from "util/bignum";
import { formatWhole } from "util/break_eternity"; import { formatWhole } from "util/break_eternity";
@ -26,6 +30,7 @@ import { render, renderCol, renderRow } from "util/vue";
import { computed, ref } from "vue"; import { computed, ref } from "vue";
import metal from "./metal"; import metal from "./metal";
import paper from "./paper"; import paper from "./paper";
import plastic from "./plastic";
import trees from "./trees"; import trees from "./trees";
const id = "cloth"; const id = "cloth";
@ -176,39 +181,42 @@ const layer = createLayer(id, function (this: BaseLayer) {
cost() { cost() {
let v = this.amount.value; let v = this.amount.value;
if (Decimal.gte(v, 100)) v = Decimal.pow(v, 2).div(100); if (Decimal.gte(v, 100)) v = Decimal.pow(v, 2).div(100);
v = Decimal.pow(0.95, paper.books.clothBook.amount.value).times(v);
return Decimal.pow(1.5, v).times(1e14); return Decimal.pow(1.5, v).times(1e14);
}, },
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 };
const betterShears = createBuyable(() => ({ const betterShears = createBuyable(() => ({
resource: metal.metal, resource: metal.metal,
cost() { cost() {
let v = this.amount.value; let v = this.amount.value;
if (Decimal.gte(v, 100)) v = Decimal.pow(v, 2).div(100); if (Decimal.gte(v, 100)) v = Decimal.pow(v, 2).div(100);
v = Decimal.pow(0.95, paper.books.clothBook.amount.value).times(v);
return Decimal.pow(1.4, v).times(10000); return Decimal.pow(1.4, v).times(10000);
}, },
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 };
const fasterSpinning = createBuyable(() => ({ const fasterSpinning = createBuyable(() => ({
resource: paper.paper, resource: paper.paper,
cost() { cost() {
let v = this.amount.value; let v = this.amount.value;
if (Decimal.gte(v, 100)) v = Decimal.pow(v, 2).div(100); if (Decimal.gte(v, 100)) v = Decimal.pow(v, 2).div(100);
v = Decimal.pow(0.95, paper.books.clothBook.amount.value).times(v);
return Decimal.pow(1.3, v).times(1000000); return Decimal.pow(1.3, v).times(1000000);
}, },
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 };
const treesUpgrade1 = createUpgrade(() => ({ const treesUpgrade1 = createUpgrade(() => ({
resource: noPersist(cloth), resource: noPersist(cloth),
@ -236,7 +244,16 @@ const layer = createLayer(id, function (this: BaseLayer) {
description: "Quadruple trees planted" description: "Quadruple trees planted"
} }
})); }));
const treesUpgrades = { treesUpgrade3, treesUpgrade2, treesUpgrade1 }; const treesUpgrade4 = createUpgrade(() => ({
resource: noPersist(cloth),
cost: 1e3,
visibility: () => showIf(plastic.upgrades.clothTools.bought.value),
display: {
title: "Felt-Gripped Axe",
description: "10x log gain"
}
}));
const treesUpgrades = { treesUpgrade4, treesUpgrade3, treesUpgrade2, treesUpgrade1 };
const metalUpgrade1 = createUpgrade(() => ({ const metalUpgrade1 = createUpgrade(() => ({
resource: noPersist(cloth), resource: noPersist(cloth),
@ -264,7 +281,16 @@ const layer = createLayer(id, function (this: BaseLayer) {
description: "Triple coal gain" description: "Triple coal gain"
} }
})); }));
const metalUpgrades = { metalUpgrade3, metalUpgrade2, metalUpgrade1 }; const metalUpgrade4 = createUpgrade(() => ({
resource: noPersist(cloth),
cost: 2e3,
visibility: () => showIf(plastic.upgrades.clothTools.bought.value),
display: {
title: "Felt-Gripped Pick",
description: "Quadruple coal gain"
}
}));
const metalUpgrades = { metalUpgrade4, metalUpgrade3, metalUpgrade2, metalUpgrade1 };
const paperUpgrade1 = createUpgrade(() => ({ const paperUpgrade1 = createUpgrade(() => ({
resource: noPersist(cloth), resource: noPersist(cloth),
@ -292,12 +318,31 @@ const layer = createLayer(id, function (this: BaseLayer) {
description: "Double paper gain" description: "Double paper gain"
} }
})); }));
const paperUpgrades = { paperUpgrade3, paperUpgrade2, paperUpgrade1 }; const paperUpgrade4 = createUpgrade(() => ({
resource: noPersist(cloth),
cost: 4e3,
visibility: () => showIf(plastic.upgrades.clothTools.bought.value),
display: {
title: "Felt Elbow Pads",
description: "10x paper gain"
}
}));
const paperUpgrades = { paperUpgrade4, paperUpgrade3, paperUpgrade2, paperUpgrade1 };
const sheepGain = createSequentialModifier(() => [ const sheepGain = createSequentialModifier(() => [
createAdditiveModifier(() => ({ createAdditiveModifier(() => ({
addend: buildPens.amount, addend: buildPens.amount,
description: "Build more pens" description: "Build more pens"
})),
createMultiplicativeModifier(() => ({
multiplier: () => Decimal.div(plastic.buyables.clothGains.amount.value, 10).add(1),
description: "Plastic Shepherd",
enabled: () => Decimal.gte(plastic.buyables.clothGains.amount.value, 1)
})),
createMultiplicativeModifier(() => ({
multiplier: 2,
description: "Shepherding for Dummies",
enabled: paper.upgrades.clothUpgrade.bought
})) }))
]); ]);
const computedSheepGain = computed(() => sheepGain.apply(1)); const computedSheepGain = computed(() => sheepGain.apply(1));
@ -308,6 +353,16 @@ const layer = createLayer(id, function (this: BaseLayer) {
createAdditiveModifier(() => ({ createAdditiveModifier(() => ({
addend: betterShears.amount, addend: betterShears.amount,
description: "Make stronger shears" description: "Make stronger shears"
})),
createMultiplicativeModifier(() => ({
multiplier: () => Decimal.div(plastic.buyables.clothGains.amount.value, 10).add(1),
description: "Plastic Shepherd",
enabled: () => Decimal.gte(plastic.buyables.clothGains.amount.value, 1)
})),
createMultiplicativeModifier(() => ({
multiplier: 2,
description: "Shepherding for Dummies",
enabled: paper.upgrades.clothUpgrade.bought
})) }))
]); ]);
const computedShearingAmount = computed(() => shearingAmount.apply(1)); const computedShearingAmount = computed(() => shearingAmount.apply(1));
@ -318,6 +373,16 @@ const layer = createLayer(id, function (this: BaseLayer) {
createAdditiveModifier(() => ({ createAdditiveModifier(() => ({
addend: fasterSpinning.amount, addend: fasterSpinning.amount,
description: "Learn how to spin" description: "Learn how to spin"
})),
createMultiplicativeModifier(() => ({
multiplier: () => Decimal.div(plastic.buyables.clothGains.amount.value, 10).add(1),
description: "Plastic Shepherd",
enabled: () => Decimal.gte(plastic.buyables.clothGains.amount.value, 1)
})),
createMultiplicativeModifier(() => ({
multiplier: 2,
description: "Shepherding for Dummies",
enabled: paper.upgrades.clothUpgrade.bought
})) }))
]); ]);
const computedSpinningAmount = computed(() => spinningAmount.apply(1)); const computedSpinningAmount = computed(() => spinningAmount.apply(1));

View file

@ -2,42 +2,42 @@
* @module * @module
* @hidden * @hidden
*/ */
import Column from "components/layout/Column.vue";
import Row from "components/layout/Row.vue";
import Spacer from "components/layout/Spacer.vue"; import Spacer from "components/layout/Spacer.vue";
import Modal from "components/Modal.vue"; import Modal from "components/Modal.vue";
import MainDisplay from "features/resources/MainDisplay.vue";
import Row from "components/layout/Row.vue";
import Column from "components/layout/Column.vue";
import { import {
createCollapsibleModifierSections, changeActiveBuyables, createCollapsibleModifierSections,
setUpDailyProgressTracker, setUpDailyProgressTracker
changeActiveBuyables
} from "data/common"; } from "data/common";
import { main } from "data/projEntry"; import { main } from "data/projEntry";
import { createBuyable, GenericBuyable } from "features/buyable"; import { createBuyable, GenericBuyable } from "features/buyable";
import { jsx, JSXFunction, showIf, StyleValue, Visibility } from "features/feature"; import { jsx, JSXFunction, showIf, StyleValue, Visibility } from "features/feature";
import MainDisplay from "features/resources/MainDisplay.vue";
import { createResource, Resource } from "features/resources/resource"; import { createResource, Resource } from "features/resources/resource";
import { createUpgrade, Upgrade } 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 {
createAdditiveModifier,
createExponentialModifier,
createMultiplicativeModifier,
createSequentialModifier,
Modifier
} from "game/modifiers";
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 { WithRequired } from "util/common";
import { render, renderRow } from "util/vue"; import { render, renderRow } from "util/vue";
import { computed, ref, unref } from "vue"; import { computed, ref, unref } from "vue";
import trees from "./trees";
import {
createAdditiveModifier,
createExponentialModifier,
createMultiplicativeModifier,
createSequentialModifier,
Modifier
} from "game/modifiers";
import { createUpgrade, Upgrade } from "features/upgrades/upgrade";
import elves from "./elves";
import paper from "./paper";
import boxes from "./boxes"; import boxes from "./boxes";
import metal from "./metal";
import cloth from "./cloth"; import cloth from "./cloth";
import { WithRequired } from "util/common"; import elves from "./elves";
import metal from "./metal";
import oil from "./oil"; import oil from "./oil";
import paper from "./paper";
import trees from "./trees";
import dyes from "./dyes";
interface BetterFertilizerUpgOptions { interface BetterFertilizerUpgOptions {
canAfford: () => boolean; canAfford: () => boolean;
@ -552,7 +552,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
enabled: elves.elves.bonfireElf.bought enabled: elves.elves.bonfireElf.bought
})), })),
createMultiplicativeModifier(() => ({ createMultiplicativeModifier(() => ({
multiplier: () => Decimal.div(buildKiln.amount.value, 100).add(1), multiplier: () => Decimal.div(buildKiln.amount.value, 100).times(dyes.boosts.green2.value).add(1),
description: "Kiln Synergy", description: "Kiln Synergy",
enabled: elves.elves.kilnElf.bought enabled: elves.elves.kilnElf.bought
})), })),
@ -566,6 +566,16 @@ const layer = createLayer(id, function (this: BaseLayer) {
description: "Mining helmet", description: "Mining helmet",
enabled: cloth.metalUpgrades.metalUpgrade3.bought enabled: cloth.metalUpgrades.metalUpgrade3.bought
})), })),
createMultiplicativeModifier(() => ({
multiplier: 4,
description: "Felt-Gripped Pick",
enabled: cloth.metalUpgrades.metalUpgrade4.bought
})),
createMultiplicativeModifier(() => ({
multiplier: 2,
description: "12 Elves Trained",
enabled: elves.milestones[11].earned
})),
createExponentialModifier(() => ({ createExponentialModifier(() => ({
exponent: 1.25, exponent: 1.25,
description: "3 Elves Trained", description: "3 Elves Trained",
@ -634,7 +644,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
enabled: elves.elves.bonfireElf.bought enabled: elves.elves.bonfireElf.bought
})), })),
createMultiplicativeModifier(() => ({ createMultiplicativeModifier(() => ({
multiplier: () => Decimal.div(buildKiln.amount.value, 100).add(1), multiplier: () => Decimal.div(buildKiln.amount.value, 100).times(dyes.boosts.green2.value).add(1),
description: "Kiln Synergy", description: "Kiln Synergy",
enabled: elves.elves.kilnElf.bought enabled: elves.elves.kilnElf.bought
})), })),

560
src/data/layers/dyes.tsx Normal file
View file

@ -0,0 +1,560 @@
/**
* @module
* @hidden
*/
import Modal from "components/Modal.vue";
import MainDisplay from "features/resources/MainDisplay.vue";
import Row from "components/layout/Row.vue";
import Spacer from "components/layout/Spacer.vue";
import Sqrt from "components/math/Sqrt.vue";
import { BuyableOptions, GenericBuyable, createBuyable } from "features/buyable";
import { jsx, JSXFunction, showIf, Visibility } from "features/feature";
import { createResource, Resource } from "features/resources/resource";
import { globalBus } from "game/events";
import { BaseLayer, createLayer } from "game/layers";
import { noPersist, persistent } from "game/persistence";
import Decimal, { DecimalSource, format, formatWhole } from "util/bignum";
import { computed, ComputedRef, ref, Ref, unref } from "vue";
import trees from "./trees";
import oil from "./oil";
import { coerceComponent, render, renderCol, renderRow } from "util/vue";
import { setUpDailyProgressTracker, createCollapsibleModifierSections } from "data/common";
import { createAdditiveModifier, createMultiplicativeModifier, createSequentialModifier, Modifier } from "game/modifiers";
import { WithRequired } from "util/common";
import { createUpgrade, GenericUpgrade } from "features/upgrades/upgrade";
import { createLazyProxy } from "util/proxies";
import coal from "./coal";
interface Dye {
name: string,
amount: Resource<DecimalSource>,
buyable: GenericBuyable,
toGenerate: WithRequired<Modifier, "description" | "revert">,
computedToGenerate: ComputedRef<DecimalSource>,
display: JSXFunction
}
type DyeUpg = "blueDyeUpg" | "redDyeUpg" | "yellowDyeUpg" | "yellowDyeUpg2" | "redDyeUpg2" | "blueDyeUpg2" | "coalUpg"
const id = "dyes";
const day = 11;
const layer = createLayer(id, function (this: BaseLayer) {
const name = "Dyes";
const color = "#D4D4F4";
function createDye(
optionsFunc: () => {
name: string;
color: string;
costs: {
base: Ref<DecimalSource> | DecimalSource;
root?: Ref<DecimalSource> | DecimalSource,
res: Resource<DecimalSource>
}[];
listedBoosts: {
visible: Ref<boolean> | boolean,
desc: Ref<string>
}[];
dyesToReset: {
name: string,
reset: VoidFunction
}[]
} & Partial<BuyableOptions>
): Dye {
return createLazyProxy(() => {
const options = optionsFunc();
const amount = createResource<DecimalSource>(0, optionsFunc().name);
const toGenerate = createSequentialModifier(() => [
createAdditiveModifier(() => ({
addend: () => Decimal.add(buyable.amount.value, 1),
description: `${options.name} Chambers`
})),
createMultiplicativeModifier(() => ({
multiplier: boosts.orange1,
description: "Orange Dye Boost 1",
enabled: options.color == "red" || options.color == "yellow"
})),
createMultiplicativeModifier(() => ({
multiplier: boosts.green1,
description: "Green Dye Boost 1",
enabled: options.color == "yellow" || options.color == "blue"
})),
createMultiplicativeModifier(() => ({
multiplier: boosts.purple1,
description: "Purple Dye Boost 1",
enabled: options.color == "red" || options.color == "blue"
})),
createMultiplicativeModifier(() => ({
multiplier: 2,
description: "Wetter Dyes",
enabled: () => upgrades.yellowDyeUpg.bought.value && options.color == "red" || options.color == "yellow" || options.color == "blue"
}))
]) as WithRequired<Modifier, "description" | "revert">;
const computedToGenerate = computed(() => toGenerate.apply(0));
const buyable: GenericBuyable = createBuyable(() => ({
...options,
style: () => ({ backgroundColor: unref(buyable.canPurchase) ? color : "#545454", minWidth: "200px" }),
display: jsx(() => {
return (
<span>
<h3>{options.name} Chambers</h3>
<br/>
Create {format(computedToGenerate.value)} {options.name}{options.dyesToReset.length > 0 ? ", but reset " + options.dyesToReset.map(dye => dye.name).join(", ") : ""}.
<br/>
<br/>
<span class="white-space: pre-wrap">
Currently: {options.listedBoosts.filter(b => unref(b.visible)).map(b => render(jsx(() => <div>{unref(b.desc)}</div>)))}
</span>
<br/>
<div>
Cost: {options.costs.map(c => render(jsx(() =>
<div>
{format(unref(Decimal.pow(unref(buyable.cost) ?? Decimal.dInf, unref(c.root ?? 1)).times(unref(c.base))))}
{" "}{c.res.displayName}<br/>
</div>)))}
</div>
</span>
);
}),
cost() {
let v = buyable.amount.value;
if (Decimal.gte(v, 25)) v = Decimal.pow(v, 2).div(20) // intentional price jump #2
if (Decimal.gte(v, 10)) v = Decimal.pow(v, 2).div(5); // intentional price jump
return Decimal.div(v, 10).plus(1);
},
canPurchase: computed((cost?: DecimalSource) => {
if (unref(buyable.visibility) != Visibility.Visible) return false;
const trueCost = cost ?? unref(buyable.cost) ?? Decimal.dInf;
return options.costs.every(c => Decimal.div(c.res.value, unref(c.base)).root(unref(c.root ?? 1)).gte(trueCost));
}),
onPurchase(cost?: DecimalSource) {
const trueCost = cost ?? unref(buyable.cost) ?? Decimal.dInf;
options.costs.forEach(c => {
c.res.value = Decimal.sub(c.res.value, Decimal.pow(trueCost, unref(c.root ?? 1)).times(unref(c.base)));
});
amount.value = Decimal.add(amount.value, computedToGenerate.value);
buyable.amount.value = Decimal.add(buyable.amount.value, 1);
options.dyesToReset.forEach(dye => dye.reset());
}
}));
return {
name: options.name,
amount,
buyable,
toGenerate,
computedToGenerate,
display: jsx(() => (
<div class="col" style="max-width: 200px">
<MainDisplay resource={amount} color={options.color} style="margin-bottom: 0" />
<Spacer />
{render(buyable)}
</div>
))
}
})
}
const dyes: Record<"red" | "yellow" | "blue" | "orange" | "green" | "purple", Dye> = {
red: createDye(() => ({
name: "Red Dye",
color: "red",
costs: [
{
base: '2e18',
root: 5,
res: trees.logs
},
{
base: computed(() => upgrades.yellowDyeUpg2.bought.value ? '2.5e5' : '5e5'),
root: 2,
res: oil.oil
}
],
listedBoosts: [
{
visible: true,
desc: computed(() => `+${format(boosts.red1.value)} effective Oil Pumps (does not impact coal consumption)`)
}
],
dyesToReset: [],
})),
yellow: createDye(() => ({
name: "Yellow Dye",
color: "yellow",
costs: [
{
base: '1e18',
root: 5,
res: trees.logs
},
{
base: computed(() => upgrades.yellowDyeUpg2.bought.value ? '5e5' : '1e6'),
root: 2,
res: oil.oil
}
],
listedBoosts: [
{
visible: true,
desc: computed(() => `x${format(boosts.yellow1.value)} Paper \& Plastic gain`)
}
],
dyesToReset: [],
})),
blue: createDye(() => ({
name: "Blue Dye",
color: "blue",
costs: [
{
base: '5e17',
root: 5,
res: trees.logs
},
{
base: computed(() => upgrades.yellowDyeUpg2.bought.value ? '1e6' : '2e6'),
root: 2,
res: oil.oil
}
],
listedBoosts: [
{
visible: true,
desc: computed(() => `+${formatWhole(boosts.blue1.value)} forest size (after all other modifiers).`)
}
],
dyesToReset: [],
})),
orange: createDye(() => ({
name: "Orange Dye",
color: "orange",
costs: [
{
base: 15,
root: 2,
res: dyes.red.amount
},
{
base: 10,
root: 2,
res: dyes.yellow.amount
}
],
listedBoosts: [
{
visible: true,
desc: computed(() => `x${format(boosts.orange1.value)} Red and Yellow Dye gain`)
},
{
visible: true,
desc: computed(() => `/${format(boosts.orange2.value)} Box buyable costs.`)
}
],
dyesToReset: [{
name: "Red Dye",
reset() {
dyes.red.amount.value = 0;
dyes.red.buyable.amount.value = 0;
}
}, {
name: "Yellow Dye",
reset() {
dyes.yellow.amount.value = 0;
dyes.yellow.buyable.amount.value = 0;
}
}],
})),
green: createDye(() => ({
name: "Green Dye",
color: "green",
costs: [
{
base: 15,
root: 2,
res: dyes.yellow.amount
},
{
base: 10,
root: 2,
res: dyes.blue.amount
}
],
listedBoosts: [
{
visible: true,
desc: computed(() => `x${format(boosts.green1.value)} Yellow and Blue Dye gain`)
},
{
visible: true,
desc: computed(() => `x${formatWhole(Decimal.sub(boosts.green2.value, 1).times(100))}% Kiln synergy effect.`)
}
],
dyesToReset: [{
name: "Yellow Dye",
reset() {
dyes.yellow.amount.value = 0;
dyes.yellow.buyable.amount.value = 0;
}
},{
name: "Blue Dye",
reset() {
dyes.blue.amount.value = 0;
dyes.blue.buyable.amount.value = 0;
}
}],
})),
purple: createDye(() => ({
name: "Purple Dye",
color: "purple",
costs: [
{
base: 15,
root: 2,
res: dyes.blue.amount
},
{
base: 10,
root: 2,
res: dyes.red.amount
}
],
listedBoosts: [
{
visible: true,
desc: computed(() => `x${format(boosts.purple1.value)} Red and Blue Dye gain`)
},
{
visible: true,
desc: computed(() => `x${format(boosts.purple2.value)} Smelting Speed and Ore Purity`)
}
],
dyesToReset: [{
name: "Blue Dye",
reset() {
dyes.blue.amount.value = 0;
dyes.blue.buyable.amount.value = 0;
}
}, {
name: "Red Dye",
reset() {
dyes.red.amount.value = 0;
dyes.red.buyable.amount.value = 0;
}
}],
}))
};
const boosts = {
red1: computed(() => Decimal.pow(Decimal.add(dyes.red.amount.value, 1).log2().plus(1).log2().div(2), upgrades.blueDyeUpg2.bought.value ? 1.5 : 1)),
yellow1: computed(() => Decimal.add(dyes.yellow.amount.value, 1).log2().plus(1)),
blue1: computed(() => Decimal.add(dyes.blue.amount.value, 1).log2().sqrt().times(5e6)),
orange1: computed(() => Decimal.pow(2, Decimal.add(dyes.orange.amount.value, 1).log2().sqrt()).pow(upgrades.coalUpg.bought.value ? 1.2 : 1)),
orange2: computed(() => Decimal.add(dyes.orange.amount.value, 1).log2().plus(1)),
green1: computed(() => Decimal.pow(2, Decimal.add(dyes.green.amount.value, 1).log2().sqrt()).pow(upgrades.coalUpg.bought.value ? 1.2 : 1)),
green2: computed(() => Decimal.add(dyes.green.amount.value, 1).log2().plus(1).pow(upgrades.coalUpg.bought.value ? 2 : 1)),
purple1: computed(() => Decimal.pow(2, Decimal.add(dyes.purple.amount.value, 1).log2().sqrt()).pow(upgrades.coalUpg.bought.value ? 1.2 : 1)),
purple2: computed(() => Decimal.add(dyes.purple.amount.value, 1).log2().plus(1)),
}
const [generalTab, generalTabCollapsed] = createCollapsibleModifierSections(() => [
{
title: "Red Dye Creation",
modifier: dyes.red.toGenerate,
base: 0
},
{
title: "Yellow Dye Creation",
modifier: dyes.yellow.toGenerate,
base: 0
},
{
title: "Blue Dye Creation",
modifier: dyes.blue.toGenerate,
base: 0
},
{
title: "Orange Dye Creation",
modifier: dyes.orange.toGenerate,
base: 0
},
{
title: "Green Dye Creation",
modifier: dyes.green.toGenerate,
base: 0
},
{
title: "Purple Dye Creation",
modifier: dyes.purple.toGenerate,
base: 0
}
]);
const upgrades: Record<DyeUpg, GenericUpgrade> = {
blueDyeUpg: createUpgrade(() => ({
visibility: () => showIf(Decimal.add(dyes.orange.amount.value, dyes.green.amount.value).add(dyes.purple.amount.value).gte(1) || upgrades.blueDyeUpg.bought.value),
display: {
title: "Is Blue Dye just Water?",
description: jsx(() => <>Multiply Log gain by log<sub>10</sub>(Auto Cutting Amount)+1.</>)
},
cost: 1000,
resource: dyes.blue.amount,
onPurchase() {
dyes.blue.amount.value = 0;
dyes.blue.buyable.amount.value = 0;
}
})),
redDyeUpg: createUpgrade(() => ({
visibility: () => showIf(Decimal.add(dyes.orange.amount.value, dyes.green.amount.value).add(dyes.purple.amount.value).gte(10) || upgrades.redDyeUpg.bought.value),
display: {
title: "Glistening Paint",
description: jsx(() => <>Multiply Ore Purity by log<sub>10</sub>(Cloth)+1.</>)
},
cost: 1500,
resource: dyes.red.amount,
onPurchase() {
dyes.red.amount.value = 0;
dyes.red.buyable.amount.value = 0;
}
})),
yellowDyeUpg: createUpgrade(() => ({
visibility: () => showIf(Decimal.add(dyes.orange.amount.value, dyes.green.amount.value).add(dyes.purple.amount.value).gte(100) || upgrades.yellowDyeUpg.bought.value),
display: {
title: "Wetter Dyes",
description: "Double Red, Yellow, and Blue Dye gain, but reset their amounts."
},
cost: 2000,
resource: dyes.yellow.amount,
onPurchase() {
dyes.red.amount.value = 0;
dyes.red.buyable.amount.value = 0;
dyes.yellow.amount.value = 0;
dyes.yellow.buyable.amount.value = 0;
dyes.blue.amount.value = 0;
dyes.blue.buyable.amount.value = 0;
}
})),
yellowDyeUpg2: createUpgrade(() => ({
visibility: () => showIf(upgrades.yellowDyeUpg.bought.value),
display: {
title: "Golden Wash",
description: "Halve the Oil cost of Red, Yellow, and Blue Dyes."
},
cost: 5000,
resource: dyes.yellow.amount,
onPurchase() {
dyes.yellow.amount.value = 0;
dyes.yellow.buyable.amount.value = 0;
}
})),
redDyeUpg2: createUpgrade(() => ({
visibility: () => showIf(upgrades.redDyeUpg.bought.value),
display: {
title: "De Louvre",
description: jsx(() => <>Multiply Smelting Speed by <Sqrt>Refineries+1</Sqrt>.</>)
},
cost: 6000,
resource: dyes.red.amount,
onPurchase() {
dyes.red.amount.value = 0;
dyes.red.buyable.amount.value = 0;
}
})),
blueDyeUpg2: createUpgrade(() => ({
visibility: () => showIf(upgrades.blueDyeUpg.bought.value),
display: {
title: "Hydrophobia",
description: "Raise Red Dye's effect ^1.5."
},
cost: 7500,
resource: dyes.blue.amount,
onPurchase() {
dyes.blue.amount.value = 0;
dyes.blue.buyable.amount.value = 0;
}
})),
coalUpg: createUpgrade(() => ({
visibility: () => showIf(upgrades.blueDyeUpg2.bought.value && upgrades.redDyeUpg2.bought.value && upgrades.yellowDyeUpg2.bought.value),
display: {
title: "Denser Spectrum",
description: "Orange, Green, and Purple Dyes' first effect is raised ^1.2, and Green Dye's second effect is squared. Buying this resets Red, Yellow, and Blue Dyes.",
},
cost: "5e30",
resource: coal.coal,
onPurchase() {
dyes.red.amount.value = 0;
dyes.red.buyable.amount.value = 0;
dyes.yellow.amount.value = 0;
dyes.yellow.buyable.amount.value = 0;
dyes.blue.amount.value = 0;
dyes.blue.buyable.amount.value = 0;
}
}))
}
const showModifiersModal = ref(false);
const modifiersModal = jsx(() => (
<Modal
modelValue={showModifiersModal.value}
onUpdate:modelValue={(value: boolean) => (showModifiersModal.value = value)}
v-slots={{
header: () => <h2>{name} Modifiers</h2>,
body: generalTab
}}
/>
));
const dyeSum = createResource<DecimalSource>(computed(() => Object.values(dyes).reduce<DecimalSource>((a,c) => Decimal.add(a, c.amount.value), 0)), "Sum of Dyes");
const { total: totalDyeSum, trackerDisplay } = setUpDailyProgressTracker({
resource: dyeSum,
goal: 6e4,
name,
day,
color,
textColor: "var(--feature-foreground)",
modal: {
show: showModifiersModal,
display: modifiersModal
},
ignoreTotal: true
});
return {
name,
color,
dyes,
dyeSum,
boosts,
totalDyeSum,
minWidth: 700,
generalTabCollapsed,
upgrades,
display: jsx(() => (
<>
{render(trackerDisplay)}
<Spacer />
{renderRow(dyes.red.display, dyes.yellow.display, dyes.blue.display)}
<Spacer />
{renderRow(dyes.orange.display, dyes.green.display, dyes.purple.display)}
<Spacer />
<div class="row" style="vertical-align: top">
{renderCol(upgrades.redDyeUpg, upgrades.redDyeUpg2)}
{renderCol(upgrades.yellowDyeUpg, upgrades.yellowDyeUpg2)}
{renderCol(upgrades.blueDyeUpg, upgrades.blueDyeUpg2)}
</div>
{render(upgrades.coalUpg)}
</>
))
}
});
export default layer;

View file

@ -2,6 +2,7 @@
* @module * @module
* @hidden * @hidden
*/ */
import { isArray } from "@vue/shared";
import Toggle from "components/fields/Toggle.vue"; import Toggle from "components/fields/Toggle.vue";
import Spacer from "components/layout/Spacer.vue"; import Spacer from "components/layout/Spacer.vue";
import Modal from "components/Modal.vue"; import Modal from "components/Modal.vue";
@ -25,8 +26,10 @@ import { Computable, convertComputable } from "util/computed";
import { render, renderRow } from "util/vue"; import { render, renderRow } from "util/vue";
import { computed, ref, Ref, unref, watchEffect } from "vue"; import { computed, ref, Ref, unref, watchEffect } from "vue";
import boxes from "./boxes"; import boxes from "./boxes";
import cloth from "./cloth";
import coal from "./coal"; import coal from "./coal";
import paper from "./paper"; import paper from "./paper";
import plastic from "./plastic";
import trees from "./trees"; import trees from "./trees";
import workshop from "./workshop"; import workshop from "./workshop";
@ -86,6 +89,17 @@ const layer = createLayer(id, function (this: BaseLayer) {
if (foundationMilestone.earned.value) { if (foundationMilestone.earned.value) {
workshop.foundationProgress.value = 100; workshop.foundationProgress.value = 100;
} }
if (coalUpgradesMilestone.earned.value) {
coal.warmerCutters.bought.value = true;
coal.warmerPlanters.bought.value = true;
coal.basicFertilizer.bought.value = true;
coal.unlockBonfire.bought.value = true;
coal.dedicatedCutters.bought.value = true;
coal.dedicatedPlanters.bought.value = true;
coal.betterFertilizer.bought.value = true;
coal.unlockKiln.bought.value = true;
coal.efficientSmelther.bought.value = true;
}
}); });
} }
})); }));
@ -100,6 +114,11 @@ const layer = createLayer(id, function (this: BaseLayer) {
multiplier: () => Decimal.times(paper.books.cuttersBook.amount.value, 0.1).add(1), multiplier: () => Decimal.times(paper.books.cuttersBook.amount.value, 0.1).add(1),
description: "Now You're Logging!", description: "Now You're Logging!",
enabled: () => Decimal.gt(paper.books.cuttersBook.amount.value, 0) enabled: () => Decimal.gt(paper.books.cuttersBook.amount.value, 0)
})),
createMultiplicativeModifier(() => ({
multiplier: 2,
description: "10 Elves Trained",
enabled: elvesMilestone2.earned
})) }))
]); ]);
const planterCooldown = createSequentialModifier(() => [ const planterCooldown = createSequentialModifier(() => [
@ -112,6 +131,11 @@ const layer = createLayer(id, function (this: BaseLayer) {
multiplier: () => Decimal.times(paper.books.plantersBook.amount.value, 0.1).add(1), multiplier: () => Decimal.times(paper.books.plantersBook.amount.value, 0.1).add(1),
description: "The Man Who Planted Trees", description: "The Man Who Planted Trees",
enabled: () => Decimal.gt(paper.books.plantersBook.amount.value, 0) enabled: () => Decimal.gt(paper.books.plantersBook.amount.value, 0)
})),
createMultiplicativeModifier(() => ({
multiplier: 2,
description: "10 Elves Trained",
enabled: elvesMilestone2.earned
})) }))
]); ]);
const expanderCooldown = createSequentialModifier(() => [ const expanderCooldown = createSequentialModifier(() => [
@ -124,6 +148,11 @@ const layer = createLayer(id, function (this: BaseLayer) {
multiplier: () => Decimal.times(paper.books.expandersBook.amount.value, 0.1).add(1), multiplier: () => Decimal.times(paper.books.expandersBook.amount.value, 0.1).add(1),
description: "Logjam", description: "Logjam",
enabled: () => Decimal.gt(paper.books.expandersBook.amount.value, 0) enabled: () => Decimal.gt(paper.books.expandersBook.amount.value, 0)
})),
createMultiplicativeModifier(() => ({
multiplier: 2,
description: "10 Elves Trained",
enabled: elvesMilestone2.earned
})) }))
]); ]);
const heatedCutterCooldown = createSequentialModifier(() => [ const heatedCutterCooldown = createSequentialModifier(() => [
@ -136,6 +165,11 @@ const layer = createLayer(id, function (this: BaseLayer) {
multiplier: () => Decimal.times(paper.books.heatedCuttersBook.amount.value, 0.1).add(1), multiplier: () => Decimal.times(paper.books.heatedCuttersBook.amount.value, 0.1).add(1),
description: "Fahrenheit 451", description: "Fahrenheit 451",
enabled: () => Decimal.gt(paper.books.heatedCuttersBook.amount.value, 0) enabled: () => Decimal.gt(paper.books.heatedCuttersBook.amount.value, 0)
})),
createMultiplicativeModifier(() => ({
multiplier: 2,
description: "10 Elves Trained",
enabled: elvesMilestone2.earned
})) }))
]); ]);
const heatedPlanterCooldown = createSequentialModifier(() => [ const heatedPlanterCooldown = createSequentialModifier(() => [
@ -149,6 +183,11 @@ const layer = createLayer(id, function (this: BaseLayer) {
Decimal.times(paper.books.heatedPlantersBook.amount.value, 0.1).add(1), Decimal.times(paper.books.heatedPlantersBook.amount.value, 0.1).add(1),
description: "Tillamook Burn Country", description: "Tillamook Burn Country",
enabled: () => Decimal.gt(paper.books.heatedPlantersBook.amount.value, 0) enabled: () => Decimal.gt(paper.books.heatedPlantersBook.amount.value, 0)
})),
createMultiplicativeModifier(() => ({
multiplier: 2,
description: "10 Elves Trained",
enabled: elvesMilestone2.earned
})) }))
]); ]);
const fertilizerCooldown = createSequentialModifier(() => [ const fertilizerCooldown = createSequentialModifier(() => [
@ -161,6 +200,11 @@ const layer = createLayer(id, function (this: BaseLayer) {
multiplier: () => Decimal.times(paper.books.fertilizerBook.amount.value, 0.1).add(1), multiplier: () => Decimal.times(paper.books.fertilizerBook.amount.value, 0.1).add(1),
description: "The Garden Tree's Handbook", description: "The Garden Tree's Handbook",
enabled: () => Decimal.gt(paper.books.fertilizerBook.amount.value, 0) enabled: () => Decimal.gt(paper.books.fertilizerBook.amount.value, 0)
})),
createMultiplicativeModifier(() => ({
multiplier: 2,
description: "10 Elves Trained",
enabled: elvesMilestone2.earned
})) }))
]); ]);
const smallFireCooldown = createSequentialModifier(() => [ const smallFireCooldown = createSequentialModifier(() => [
@ -173,6 +217,11 @@ const layer = createLayer(id, function (this: BaseLayer) {
multiplier: () => Decimal.times(paper.books.smallFireBook.amount.value, 0.1).add(1), multiplier: () => Decimal.times(paper.books.smallFireBook.amount.value, 0.1).add(1),
description: "Firestarter", description: "Firestarter",
enabled: () => Decimal.gt(paper.books.smallFireBook.amount.value, 0) enabled: () => Decimal.gt(paper.books.smallFireBook.amount.value, 0)
})),
createMultiplicativeModifier(() => ({
multiplier: 2,
description: "10 Elves Trained",
enabled: elvesMilestone2.earned
})) }))
]); ]);
const bonfireCooldown = createSequentialModifier(() => [ const bonfireCooldown = createSequentialModifier(() => [
@ -185,6 +234,11 @@ const layer = createLayer(id, function (this: BaseLayer) {
multiplier: () => Decimal.times(paper.books.bonfireBook.amount.value, 0.1).add(1), multiplier: () => Decimal.times(paper.books.bonfireBook.amount.value, 0.1).add(1),
description: "An Arsonist's Guide to Writer's Homes in New England", description: "An Arsonist's Guide to Writer's Homes in New England",
enabled: () => Decimal.gt(paper.books.bonfireBook.amount.value, 0) enabled: () => Decimal.gt(paper.books.bonfireBook.amount.value, 0)
})),
createMultiplicativeModifier(() => ({
multiplier: 2,
description: "10 Elves Trained",
enabled: elvesMilestone2.earned
})) }))
]); ]);
const kilnCooldown = createSequentialModifier(() => [ const kilnCooldown = createSequentialModifier(() => [
@ -197,6 +251,62 @@ const layer = createLayer(id, function (this: BaseLayer) {
multiplier: () => Decimal.times(paper.books.kilnBook.amount.value, 0.1).add(1), multiplier: () => Decimal.times(paper.books.kilnBook.amount.value, 0.1).add(1),
description: "Little Fires Everywhere", description: "Little Fires Everywhere",
enabled: () => Decimal.gt(paper.books.kilnBook.amount.value, 0) enabled: () => Decimal.gt(paper.books.kilnBook.amount.value, 0)
})),
createMultiplicativeModifier(() => ({
multiplier: 2,
description: "10 Elves Trained",
enabled: elvesMilestone2.earned
}))
]);
const paperCooldown = createSequentialModifier(() => [
createMultiplicativeModifier(() => ({
multiplier: 2,
description: "6 Elves Trained",
enabled: elvesMilestone.earned
})),
createMultiplicativeModifier(() => ({
multiplier: () => Decimal.times(paper.books.paperBook.amount.value, 0.1).add(1),
description: "The Book Thief",
enabled: () => Decimal.gt(paper.books.paperBook.amount.value, 0)
})),
createMultiplicativeModifier(() => ({
multiplier: 2,
description: "10 Elves Trained",
enabled: elvesMilestone2.earned
}))
]);
const boxCooldown = createSequentialModifier(() => [
createMultiplicativeModifier(() => ({
multiplier: 2,
description: "6 Elves Trained",
enabled: elvesMilestone.earned
})),
createMultiplicativeModifier(() => ({
multiplier: () => Decimal.times(paper.books.boxBook.amount.value, 0.1).add(1),
description: "Not a box",
enabled: () => Decimal.gt(paper.books.boxBook.amount.value, 0)
})),
createMultiplicativeModifier(() => ({
multiplier: 2,
description: "10 Elves Trained",
enabled: elvesMilestone2.earned
}))
]);
const clothCooldown = createSequentialModifier(() => [
createMultiplicativeModifier(() => ({
multiplier: 2,
description: "6 Elves Trained",
enabled: elvesMilestone.earned
})),
createMultiplicativeModifier(() => ({
multiplier: () => Decimal.times(paper.books.clothBook.amount.value, 0.1).add(1),
description: "Fuzzy Bee and Friends",
enabled: () => Decimal.gt(paper.books.clothBook.amount.value, 0)
})),
createMultiplicativeModifier(() => ({
multiplier: 2,
description: "10 Elves Trained",
enabled: elvesMilestone2.earned
})) }))
]); ]);
@ -263,6 +373,27 @@ const layer = createLayer(id, function (this: BaseLayer) {
base: 10, base: 10,
unit: "/s", unit: "/s",
visible: elves.kilnElf.bought visible: elves.kilnElf.bought
},
{
title: "Star Auto-Buy Frequency",
modifier: paperCooldown,
base: 10,
unit: "/s",
visible: elves.paperElf.bought
},
{
title: "Bell Auto-Buy Frequency",
modifier: boxCooldown,
base: 10,
unit: "/s",
visible: elves.boxElf.bought
},
{
title: "Gingersnap Auto-Buy Frequency",
modifier: clothCooldown,
base: 10,
unit: "/s",
visible: elves.clothElf.bought
} }
]); ]);
const showModifiersModal = ref(false); const showModifiersModal = ref(false);
@ -277,11 +408,21 @@ const layer = createLayer(id, function (this: BaseLayer) {
/> />
)); ));
const trainingCost = computed(() => {
let cost = Decimal.pow(4, totalElves.value).times(1e6);
if (Decimal.gte(totalElves.value, 9)) {
cost = Decimal.times(cost, 1e15);
}
return cost;
});
function createElf( function createElf(
options: { options: {
name: string; name: string;
description: string; description: string;
buyable: GenericBuyable & { resource: Resource }; buyable:
| (GenericBuyable & { resource: Resource })
| (GenericBuyable & { resource: Resource })[];
cooldownModifier: Modifier; cooldownModifier: Modifier;
customCost?: (amount: DecimalSource) => DecimalSource; customCost?: (amount: DecimalSource) => DecimalSource;
hasToggle?: boolean; hasToggle?: boolean;
@ -291,7 +432,6 @@ const layer = createLayer(id, function (this: BaseLayer) {
canBuy?: Computable<boolean>; canBuy?: Computable<boolean>;
} & Partial<ClickableOptions> } & Partial<ClickableOptions>
) { ) {
const trainingCost = computed(() => Decimal.pow(4, totalElves.value).times(1e6));
const buyProgress = persistent<DecimalSource>(0); const buyProgress = persistent<DecimalSource>(0);
const toggle = options.hasToggle ? persistent<boolean>(false) : ref(true); const toggle = options.hasToggle ? persistent<boolean>(false) : ref(true);
@ -303,23 +443,27 @@ const layer = createLayer(id, function (this: BaseLayer) {
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);
while (Decimal.gte(buyProgress.value, cooldown)) { (isArray(options.buyable) ? options.buyable : [options.buyable]).forEach(
if ( buyable => {
options.customCost == undefined while (Decimal.gte(buyProgress.value, cooldown)) {
? unref(options.buyable.canPurchase) if (
: Decimal.gte( options.customCost == undefined
options.buyable.resource.value, ? unref(buyable.canPurchase)
options.customCost(options.buyable.amount.value) : Decimal.gte(
) buyable.resource.value,
) { options.customCost(buyable.amount.value)
options.buyable.amount.value = Decimal.add(options.buyable.amount.value, 1); )
buyProgress.value = Decimal.sub(buyProgress.value, cooldown); ) {
options.onAutoPurchase?.(); buyable.amount.value = Decimal.add(buyable.amount.value, 1);
} else { buyProgress.value = Decimal.sub(buyProgress.value, cooldown);
buyProgress.value = cooldown; options.onAutoPurchase?.();
break; } else {
buyProgress.value = cooldown;
break;
}
}
} }
} );
} }
} }
@ -447,7 +591,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
hasToggle: true, hasToggle: true,
toggleDesc: "Activate auto-purchased bonfires", toggleDesc: "Activate auto-purchased bonfires",
onAutoPurchase() { onAutoPurchase() {
const spent = unref(this.buyable.cost!); const spent = unref((this.buyable as GenericBuyable).cost!);
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) {
@ -479,6 +623,31 @@ const layer = createLayer(id, function (this: BaseLayer) {
canBuy: coal.unlockKiln.bought canBuy: coal.unlockKiln.bought
}); });
const fireElves = [smallFireElf, bonfireElf, kilnElf]; const fireElves = [smallFireElf, bonfireElf, kilnElf];
const paperElf = createElf({
name: "Star",
description:
"Star will automatically purchase all books you can afford, without actually spending any paper.",
buyable: Object.values(paper.books),
cooldownModifier: paperCooldown,
visibility: () => showIf(plastic.elfUpgrades.paperElf.bought.value)
});
const boxElf = createElf({
name: "Bell",
description:
"Bell will automatically purchase all box buyables you can afford, without actually spending any boxes.",
buyable: Object.values(boxes.buyables),
cooldownModifier: boxCooldown,
visibility: () => showIf(plastic.elfUpgrades.boxElf.bought.value)
});
const clothElf = createElf({
name: "Gingersnap",
description:
"Gingersnap will automatically purchase all cloth buyables you can afford, without actually spending any resources.",
buyable: [cloth.buildPens, cloth.betterShears, cloth.fasterSpinning],
cooldownModifier: clothCooldown,
visibility: () => showIf(plastic.elfUpgrades.clothElf.bought.value)
});
const plasticElves = [paperElf, boxElf, clothElf];
const elves = { const elves = {
cuttersElf, cuttersElf,
plantersElf, plantersElf,
@ -488,7 +657,10 @@ const layer = createLayer(id, function (this: BaseLayer) {
fertilizerElf, fertilizerElf,
smallFireElf, smallFireElf,
bonfireElf, bonfireElf,
kilnElf kilnElf,
paperElf,
boxElf,
clothElf
}; };
const totalElves = computed(() => Object.values(elves).filter(elf => elf.bought.value).length); const totalElves = computed(() => Object.values(elves).filter(elf => elf.bought.value).length);
@ -564,6 +736,30 @@ const layer = createLayer(id, function (this: BaseLayer) {
shouldEarn: () => Decimal.gte(totalElves.value, 9), shouldEarn: () => Decimal.gte(totalElves.value, 9),
visibility: () => showIf(forestMilestone2.earned.value) visibility: () => showIf(forestMilestone2.earned.value)
})); }));
const elvesMilestone2 = createMilestone(() => ({
display: {
requirement: "10 Elves Trained",
effectDisplay: "Elves work twice as fast (again)"
},
shouldEarn: () => Decimal.gte(totalElves.value, 10),
visibility: () => showIf(main.day.value >= 10)
}));
const coalUpgradesMilestone = createMilestone(() => ({
display: {
requirement: "11 Elves Trained",
effectDisplay: "Coal upgrades aren't reset after training"
},
shouldEarn: () => Decimal.gte(totalElves.value, 11),
visibility: () => showIf(elvesMilestone2.earned.value)
}));
const coalGainMilestone2 = createMilestone(() => ({
display: {
requirement: "12 Elves Trained",
effectDisplay: "Double coal gain"
},
shouldEarn: () => Decimal.gte(totalElves.value, 12),
visibility: () => showIf(coalUpgradesMilestone.earned.value)
}));
// Gosh why did I make these as an array at first // Gosh why did I make these as an array at first
const milestones = [ const milestones = [
manualMilestone, manualMilestone,
@ -574,7 +770,10 @@ const layer = createLayer(id, function (this: BaseLayer) {
elvesMilestone, elvesMilestone,
foundationMilestone, foundationMilestone,
forestMilestone2, forestMilestone2,
treeUpgradesMilestone treeUpgradesMilestone,
elvesMilestone2,
coalUpgradesMilestone,
coalGainMilestone2
]; ];
const milestonesDict = { const milestonesDict = {
manualMilestone, manualMilestone,
@ -585,7 +784,10 @@ const layer = createLayer(id, function (this: BaseLayer) {
elvesMilestone, elvesMilestone,
foundationMilestone, foundationMilestone,
forestMilestone2, forestMilestone2,
treeUpgradesMilestone treeUpgradesMilestone,
elvesMilestone2,
coalUpgradesMilestone,
coalGainMilestone2
}; };
const { collapseMilestones, display: milestonesDisplay } = const { collapseMilestones, display: milestonesDisplay } =
createCollapsibleMilestones(milestonesDict); createCollapsibleMilestones(milestonesDict);
@ -641,6 +843,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
{renderRow(...treesElves)} {renderRow(...treesElves)}
{renderRow(...coalElves)} {renderRow(...coalElves)}
{renderRow(...fireElves)} {renderRow(...fireElves)}
{renderRow(...plasticElves)}
</div> </div>
{milestonesDisplay()} {milestonesDisplay()}
</> </>

View file

@ -26,6 +26,10 @@ import { noPersist } from "game/persistence";
import { createBuyable, GenericBuyable } from "features/buyable"; import { createBuyable, GenericBuyable } from "features/buyable";
import { main } from "../projEntry"; import { main } from "../projEntry";
import oil from "./oil"; import oil from "./oil";
import boxes from "./boxes";
import cloth from "./cloth";
import plastic from "./plastic";
import dyes from "./dyes";
const id = "metal"; const id = "metal";
const day = 7; const day = 7;
@ -59,6 +63,21 @@ const layer = createLayer(id, function (this: BaseLayer) {
multiplier: () => Decimal.add(hotterForgeEffect.value, 1), multiplier: () => Decimal.add(hotterForgeEffect.value, 1),
description: "Hotter Forges", description: "Hotter Forges",
enabled: () => Decimal.gte(hotterForge.amount.value, 1) enabled: () => Decimal.gte(hotterForge.amount.value, 1)
})),
createMultiplicativeModifier(() => ({
multiplier: 2,
description: "Carry metal in boxes",
enabled: boxes.row2Upgrades.metalUpgrade.bought
})),
createMultiplicativeModifier(() => ({
multiplier: dyes.boosts.purple2,
description: "Purple Dye Boost 2",
enabled: () => Decimal.gte(dyes.dyes.purple.amount.value, 1)
})),
createMultiplicativeModifier(() => ({
multiplier: () => Decimal.add(cloth.cloth.value, 1).log10().plus(1),
description: "Glistening Paint",
enabled: dyes.upgrades.redDyeUpg.bought
})) }))
]); ]);
const computedOrePurity = computed(() => orePurity.apply(0.1)); const computedOrePurity = computed(() => orePurity.apply(0.1));
@ -75,10 +94,21 @@ const layer = createLayer(id, function (this: BaseLayer) {
enabled: coal.efficientSmelther.bought enabled: coal.efficientSmelther.bought
})), })),
createMultiplicativeModifier(() => ({ createMultiplicativeModifier(() => ({
multiplier: () => Decimal.mul(oil.activeSmelter.value, oil.oilEffectiveness.value).add(1), multiplier: () =>
Decimal.mul(oil.activeSmelter.value, oil.oilEffectiveness.value).add(1),
description: "Oil Smelter", description: "Oil Smelter",
enabled: () => Decimal.gt(oil.activeSmelter.value, 0) enabled: () => Decimal.gt(oil.activeSmelter.value, 0)
})), })),
createMultiplicativeModifier(() => ({
multiplier: dyes.boosts.purple2,
description: "Purple Dye Boost 2",
enabled: () => Decimal.gte(dyes.dyes.purple.amount.value, 1)
})),
createMultiplicativeModifier(() => ({
multiplier: () => Decimal.add(plastic.activeRefinery.value, 1).sqrt(),
description: "De Louvre",
enabled: dyes.upgrades.redDyeUpg2.bought
}))
]); ]);
const computedAutoSmeltSpeed = computed(() => autoSmeltSpeed.apply(0)); const computedAutoSmeltSpeed = computed(() => autoSmeltSpeed.apply(0));
const autoSmeltMulti = createSequentialModifier(() => [ const autoSmeltMulti = createSequentialModifier(() => [
@ -88,10 +118,11 @@ const layer = createLayer(id, function (this: BaseLayer) {
enabled: coal.efficientSmelther.bought enabled: coal.efficientSmelther.bought
})), })),
createMultiplicativeModifier(() => ({ createMultiplicativeModifier(() => ({
multiplier: () => Decimal.add(oil.activeBurner.value, 1).mul(oil.oilEffectiveness.value), multiplier: () =>
Decimal.add(oil.activeBurner.value, 1).mul(oil.oilEffectiveness.value),
description: "Blaster Burner", description: "Blaster Burner",
enabled: oil.row2Upgrades[2].bought enabled: oil.row2Upgrades[2].bought
})), }))
]); ]);
const computedAutoSmeltMulti = computed(() => autoSmeltMulti.apply(1)); const computedAutoSmeltMulti = computed(() => autoSmeltMulti.apply(1));
@ -150,13 +181,18 @@ const layer = createLayer(id, function (this: BaseLayer) {
createMultiplicativeModifier(() => ({ createMultiplicativeModifier(() => ({
multiplier: () => Decimal.mul(oil.depth.value, 0.05).add(1), multiplier: () => Decimal.mul(oil.depth.value, 0.05).add(1),
description: "25m Well Depth", description: "25m Well Depth",
enabled: oil.depthMilestones[2].earned, enabled: oil.depthMilestones[2].earned
})), })),
createMultiplicativeModifier(() => ({ createMultiplicativeModifier(() => ({
multiplier: oil.extractorOre, multiplier: oil.extractorOre,
description: "Heavy Extractor", description: "Heavy Extractor",
enabled: () => Decimal.gt(oil.activeExtractor.value, 0) enabled: () => Decimal.gt(oil.activeExtractor.value, 0)
})), })),
createMultiplicativeModifier(() => ({
multiplier: 2,
description: "Carry ore in boxes",
enabled: boxes.row2Upgrades.oreUpgrade.bought
}))
]); ]);
const computedOreAmount = computed(() => oreAmount.apply(1)); const computedOreAmount = computed(() => oreAmount.apply(1));
const oreSpeed = createSequentialModifier(() => [ const oreSpeed = createSequentialModifier(() => [
@ -203,7 +239,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
})), })),
createMultiplicativeModifier(() => ({ createMultiplicativeModifier(() => ({
multiplier: computedOreSpeed multiplier: computedOreSpeed
})), }))
]); ]);
const computedOreGain = computed(() => oreGain.apply(0)); const computedOreGain = computed(() => oreGain.apply(0));
const netOreGain = createSequentialModifier(() => [ const netOreGain = createSequentialModifier(() => [
@ -216,7 +252,6 @@ const layer = createLayer(id, function (this: BaseLayer) {
})) }))
]); ]);
const computedNetOreGain = computed(() => netOreGain.apply(0)); const computedNetOreGain = computed(() => netOreGain.apply(0));
const simplePickaxe = createUpgrade(() => ({ const simplePickaxe = createUpgrade(() => ({
resource: noPersist(metal), resource: noPersist(metal),
@ -248,7 +283,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
visibility: () => visibility: () =>
showIf( showIf(
crucible.bought.value || crucible.bought.value ||
Decimal.div(bestOre.value, computedOrePurity.value).plus(bestMetal.value).gte(1) Decimal.div(bestOre.value, computedOrePurity.value).plus(bestMetal.value).gte(1)
) )
})) as GenericUpgrade; })) as GenericUpgrade;
const coalDrill = createUpgrade(() => ({ const coalDrill = createUpgrade(() => ({
@ -262,12 +297,14 @@ const layer = createLayer(id, function (this: BaseLayer) {
visibility: () => visibility: () =>
showIf( showIf(
Decimal.gte(oreDrill.amount.value, 1) && Decimal.gte(oreDrill.amount.value, 1) &&
(coalDrill.bought.value || (coalDrill.bought.value ||
Decimal.lt( main.days[7].opened.value ||
coal.computedCoalGain.value, Decimal.lt(
Decimal.times(computedOreAmount.value, computedOreSpeed.value) coal.computedCoalGain.value,
.times(coalCost) Decimal.times(computedOreAmount.value, computedOreSpeed.value).times(
)) coalCost
)
))
), ),
onPurchase() { onPurchase() {
main.days[2].recentlyUpdated.value = true; main.days[2].recentlyUpdated.value = true;
@ -299,7 +336,6 @@ const layer = createLayer(id, function (this: BaseLayer) {
visibility: () => showIf(oil.depthMilestones[4].earned.value) visibility: () => showIf(oil.depthMilestones[4].earned.value)
})); }));
const oreDrill = createBuyable(() => ({ const oreDrill = createBuyable(() => ({
resource: noPersist(metal), resource: noPersist(metal),
cost() { cost() {
@ -318,9 +354,9 @@ const layer = createLayer(id, function (this: BaseLayer) {
visibility: () => visibility: () =>
showIf( showIf(
Decimal.gte(oreDrill.amount.value, 1) || Decimal.gte(oreDrill.amount.value, 1) ||
Decimal.div(bestOre.value, computedOrePurity.value) Decimal.div(bestOre.value, computedOrePurity.value)
.plus(bestMetal.value) .plus(bestMetal.value)
.gte(10) .gte(10)
), ),
style: { width: "200px" } style: { width: "200px" }
})) as GenericBuyable; })) as GenericBuyable;
@ -342,8 +378,8 @@ const layer = createLayer(id, function (this: BaseLayer) {
visibility: () => visibility: () =>
showIf( showIf(
Decimal.gte(industrialCrucible.amount.value, 1) || Decimal.gte(industrialCrucible.amount.value, 1) ||
Decimal.gte(oreDrill.amount.value, 4) || Decimal.gte(oreDrill.amount.value, 4) ||
Decimal.gte(bestOre.value, 50) Decimal.gte(bestOre.value, 50)
), ),
style: { width: "200px" } style: { width: "200px" }
})) as GenericBuyable; })) as GenericBuyable;
@ -378,10 +414,8 @@ const layer = createLayer(id, function (this: BaseLayer) {
if (autoSmeltEnabled.value) { if (autoSmeltEnabled.value) {
smeltOre( smeltOre(
Decimal.min( Decimal.min(smeltableOre.value, Decimal.times(computedAutoSmeltSpeed.value, diff)),
smeltableOre.value, computedAutoSmeltMulti.value
Decimal.times(computedAutoSmeltSpeed.value, diff)
), computedAutoSmeltMulti.value
); );
} }
}); });
@ -418,7 +452,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
title: "Mining Speed", title: "Mining Speed",
modifier: oreSpeed, modifier: oreSpeed,
base: 0.1, base: 0.1,
unit: "/s", unit: "/s"
} }
]); ]);
const showModifiersModal = ref(false); const showModifiersModal = ref(false);
@ -478,16 +512,23 @@ const layer = createLayer(id, function (this: BaseLayer) {
sticky={false} sticky={false}
productionDisplay={jsx(() => ( productionDisplay={jsx(() => (
<> <>
{autoSmeltEnabled.value && Decimal.gte(industrialCrucible.amount.value, 1) {autoSmeltEnabled.value &&
Decimal.gte(industrialCrucible.amount.value, 1)
? `+${formatLimit( ? `+${formatLimit(
[ [
[computedAutoSmeltSpeed.value, "smelting speed"], [computedAutoSmeltSpeed.value, "smelting speed"],
[computedOreGain.value, "ore gain"], [computedOreGain.value, "ore gain"],
[Decimal.div(coal.computedCoalGain.value, coalCost), "coal gain"] [
], Decimal.div(coal.computedCoalGain.value, coalCost),
"/s", "coal gain"
Decimal.mul(computedOrePurity.value, computedAutoSmeltMulti.value) ]
)}` ],
"/s",
Decimal.mul(
computedOrePurity.value,
computedAutoSmeltMulti.value
)
)}`
: undefined} : undefined}
</> </>
))} ))}
@ -499,7 +540,9 @@ const layer = createLayer(id, function (this: BaseLayer) {
<Toggle <Toggle
title="Auto Smelt" title="Auto Smelt"
modelValue={autoSmeltEnabled.value} modelValue={autoSmeltEnabled.value}
onUpdate:modelValue={(value: boolean) => (autoSmeltEnabled.value = value)} onUpdate:modelValue={(value: boolean) =>
(autoSmeltEnabled.value = value)
}
/> />
</div> </div>
) : undefined} ) : undefined}
@ -520,7 +563,14 @@ const layer = createLayer(id, function (this: BaseLayer) {
</div> </div>
{render(oreBar)} {render(oreBar)}
<Spacer /> <Spacer />
{renderRow(simplePickaxe, doublePickaxe, crucible, coalDrill, industrialFurnace, efficientDrill)} {renderRow(
simplePickaxe,
doublePickaxe,
crucible,
coalDrill,
industrialFurnace,
efficientDrill
)}
{renderRow(oreDrill, industrialCrucible, hotterForge)} {renderRow(oreDrill, industrialCrucible, hotterForge)}
</> </>
)) ))

View file

@ -32,6 +32,9 @@ 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 } from "util/bignum";
import plastic from "./plastic";
import paper from "./paper";
import dyes from "./dyes";
const id = "oil"; const id = "oil";
const day = 9; const day = 9;
@ -221,7 +224,8 @@ const layer = createLayer(id, function (this: BaseLayer) {
Decimal.pow(row2Upgrades[3].bought.value ? 4 : 5, activePump.value) Decimal.pow(row2Upgrades[3].bought.value ? 4 : 5, activePump.value)
); );
const pumpOil = computed(() => const pumpOil = computed(() =>
Decimal.pow(activePump.value, 2) Decimal.add(activePump.value, computedExtraOilPumps.value)
.pow(2)
.mul(activeHeavy.value) .mul(activeHeavy.value)
.mul(Decimal.add(activeHeavy2.value, 1)) .mul(Decimal.add(activeHeavy2.value, 1))
.mul(activeExtractor.value) .mul(activeExtractor.value)
@ -413,7 +417,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
display: { display: {
requirement: "150m Well Depth", requirement: "150m Well Depth",
effectDisplay: effectDisplay:
"It appears that coal and metal appear a lot more when you go this deep! Unlock more coal and metal upgrades!" "It appears that coal and metal appear a lot more when you go this deep! Unlock an upgrade apiece for coal and metal!"
}, },
shouldEarn: () => Decimal.gte(depth.value, 150), shouldEarn: () => Decimal.gte(depth.value, 150),
visibility: () => showIf(depthMilestones[3].earned.value) visibility: () => showIf(depthMilestones[3].earned.value)
@ -598,7 +602,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
cost: 25000, cost: 25000,
display: { display: {
title: "Oil Integration", title: "Oil Integration",
description: "Reduce Oil Well's coal consumption multipler from 5 to 4" description: "Reduce Oil Pump's coal consumption multipler from 5 to 4"
}, },
style: { color: colorText } style: { color: colorText }
})), })),
@ -667,6 +671,11 @@ const layer = createLayer(id, function (this: BaseLayer) {
description: "Metal Drill Upgrade", description: "Metal Drill Upgrade",
enabled: row1Upgrades[3].bought enabled: row1Upgrades[3].bought
})), })),
createMultiplicativeModifier(() => ({
multiplier: 2,
description: "Guide to drilling",
enabled: paper.upgrades.drillingUpgrade.bought
})),
createMultiplicativeModifier(() => ({ createMultiplicativeModifier(() => ({
multiplier: () => coalEffectiveness.value, multiplier: () => coalEffectiveness.value,
description: "Effectiveness", description: "Effectiveness",
@ -700,6 +709,11 @@ const layer = createLayer(id, function (this: BaseLayer) {
description: "3000m Well Depth", description: "3000m Well Depth",
enabled: depthMilestones[7].earned enabled: depthMilestones[7].earned
})), })),
createMultiplicativeModifier(() => ({
multiplier: 2,
description: "Oil and where to find it",
enabled: paper.upgrades.oilUpgrade.bought
})),
createMultiplicativeModifier(() => ({ createMultiplicativeModifier(() => ({
multiplier: () => coalEffectiveness.value, multiplier: () => coalEffectiveness.value,
description: "Effectiveness", description: "Effectiveness",
@ -718,6 +732,11 @@ const layer = createLayer(id, function (this: BaseLayer) {
addend: () => Decimal.negate(smelterOil.value), addend: () => Decimal.negate(smelterOil.value),
description: "Oil Smelter", description: "Oil Smelter",
enabled: () => Decimal.gt(activeSmelter.value, 0) enabled: () => Decimal.gt(activeSmelter.value, 0)
})),
createAdditiveModifier(() => ({
addend: () => Decimal.negate(plastic.oilCost.value),
description: "Oil Refinery",
enabled: () => Decimal.gt(plastic.activeRefinery.value, 0)
})) }))
]); ]);
const computedOilConsumption = computed(() => oilConsumption.apply(0)); const computedOilConsumption = computed(() => oilConsumption.apply(0));
@ -736,6 +755,15 @@ const layer = createLayer(id, function (this: BaseLayer) {
]); ]);
const computedOilSubstitution = computed(() => oilSubstitution.apply(0)); const computedOilSubstitution = computed(() => oilSubstitution.apply(0));
const extraOilPumps = createSequentialModifier(() => [
createAdditiveModifier(() => ({
addend: dyes.boosts.red1,
description: "Red Dye Boost 1",
enabled: () => Decimal.gte(dyes.dyes.red.amount.value, 1)
}))
])
const computedExtraOilPumps = computed(() => extraOilPumps.apply(0));
const [generalTab, generalTabCollapsed] = createCollapsibleModifierSections(() => [ const [generalTab, generalTabCollapsed] = createCollapsibleModifierSections(() => [
{ {
title: "Coal Consumption", title: "Coal Consumption",
@ -782,6 +810,14 @@ const layer = createLayer(id, function (this: BaseLayer) {
visible() { visible() {
return Decimal.gt(computedOilSubstitution.value, 0); return Decimal.gt(computedOilSubstitution.value, 0);
} }
},
{
title: "Extra Oil Pumps",
modifier: extraOilPumps,
base: 0,
visible() {
return Decimal.gt(computedExtraOilPumps.value, 0)
}
} }
]); ]);
const showModifiersModal = ref(false); const showModifiersModal = ref(false);
@ -826,7 +862,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
oil.value = Decimal.sub( oil.value = Decimal.sub(
oil.value, oil.value,
Decimal.mul(oilCost, oilEffectiveness.value).mul(diff) Decimal.mul(oilCost, oilEffectiveness.value).mul(diff)
); ).max(0);
} else { } else {
oilEffectiveness.value = Decimal.dOne; oilEffectiveness.value = Decimal.dOne;
} }
@ -889,12 +925,12 @@ const layer = createLayer(id, function (this: BaseLayer) {
<> <>
{render(trackerDisplay)} {render(trackerDisplay)}
<Spacer /> <Spacer />
{Decimal.lt(coalEffectiveness.value, 1) {Decimal.lt(coalEffectiveness.value, 1) ? (
? "Coal efficiency: " + format(Decimal.mul(coalEffectiveness.value, 100)) + "%" <div>Coal efficiency: {format(Decimal.mul(coalEffectiveness.value, 100))}%</div>
: null} ) : null}
{Decimal.lt(oilEffectiveness.value, 1) {Decimal.lt(oilEffectiveness.value, 1) ? (
? "Oil efficiency: " + format(Decimal.mul(oilEffectiveness.value, 100)) + "%" <div>Oil efficiency: {format(Decimal.mul(oilEffectiveness.value, 100))}%</div>
: null} ) : null}
<MainDisplay <MainDisplay
resource={oil} resource={oil}
color={color} color={color}

View file

@ -5,23 +5,28 @@
import Spacer from "components/layout/Spacer.vue"; import Spacer from "components/layout/Spacer.vue";
import Modal from "components/Modal.vue"; import Modal from "components/Modal.vue";
import { createCollapsibleModifierSections, setUpDailyProgressTracker } from "data/common"; import { createCollapsibleModifierSections, setUpDailyProgressTracker } from "data/common";
import { main } from "data/projEntry";
import { BuyableOptions, createBuyable, GenericBuyable } from "features/buyable"; import { BuyableOptions, createBuyable, GenericBuyable } from "features/buyable";
import { createClickable } from "features/clickables/clickable"; import { createClickable } from "features/clickables/clickable";
import { createCumulativeConversion, createPolynomialScaling } from "features/conversion"; import { createCumulativeConversion, createPolynomialScaling } from "features/conversion";
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 } from "features/resources/resource"; import { createResource, displayResource, Resource } from "features/resources/resource";
import { createUpgrade } from "features/upgrades/upgrade";
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, formatWhole } from "util/bignum";
import { WithRequired } from "util/common"; import { WithRequired } from "util/common";
import { render, renderCol } from "util/vue"; import { render, renderCol, renderRow } from "util/vue";
import { computed, ref, unref } from "vue"; import { computed, 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 from "./elves";
import plastic from "./plastic";
import trees from "./trees"; import trees from "./trees";
import dyes from "./dyes";
const id = "paper"; const id = "paper";
const day = 5; const day = 5;
@ -96,9 +101,16 @@ const layer = createLayer(id, function (this: BaseLayer) {
showAmount: false showAmount: false
}, },
resource: noPersist(paper), resource: noPersist(paper),
cost: () => Decimal.pow(5, buyable.amount.value).times(10), cost() {
let v = this.amount.value;
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, 10000)) v = Decimal.pow(v, 2).div(10000);
v = Decimal.pow(0.95, paperBook.amount.value).times(v);
return Decimal.pow(5, v).times(10);
},
style: "width: 600px" style: "width: 600px"
})) as GenericBuyable; })) as GenericBuyable & { resource: Resource };
return buyable; return buyable;
} }
@ -150,6 +162,24 @@ const layer = createLayer(id, function (this: BaseLayer) {
buyableName: "Kiln", buyableName: "Kiln",
visibility: () => showIf(elves.elves.kilnElf.bought.value) visibility: () => showIf(elves.elves.kilnElf.bought.value)
}); });
const paperBook = createBook({
name: "The Book Thief",
elfName: "Star",
buyableName: "Paper Buyables",
visibility: () => showIf(elves.elves.paperElf.bought.value)
});
const boxBook = createBook({
name: "Not a box",
elfName: "Bell",
buyableName: "Box Buyables",
visibility: () => showIf(elves.elves.boxElf.bought.value)
});
const clothBook = createBook({
name: "Fuzzy Bee and Friends",
elfName: "Gingersnap",
buyableName: "Cloth Buyables",
visibility: () => showIf(elves.elves.clothElf.bought.value)
});
const books = { const books = {
cuttersBook, cuttersBook,
plantersBook, plantersBook,
@ -159,9 +189,41 @@ const layer = createLayer(id, function (this: BaseLayer) {
fertilizerBook, fertilizerBook,
smallFireBook, smallFireBook,
bonfireBook, bonfireBook,
kilnBook kilnBook,
paperBook,
boxBook,
clothBook
}; };
const clothUpgrade = createUpgrade(() => ({
resource: noPersist(paper),
cost: 1e8,
visibility: () => showIf(plastic.upgrades.paperTools.bought.value),
display: {
title: "Shepherding for Dummies",
description: "Double effectiveness of all cloth actions"
}
}));
const drillingUpgrade = createUpgrade(() => ({
resource: noPersist(paper),
cost: 1e9,
visibility: () => showIf(plastic.upgrades.paperTools.bought.value),
display: {
title: "Guide to drilling",
description: "Double drilling power"
}
}));
const oilUpgrade = createUpgrade(() => ({
resource: noPersist(paper),
cost: 1e10,
visibility: () => showIf(plastic.upgrades.paperTools.bought.value),
display: {
title: "Oil and where to find it",
description: "Double oil gain"
}
}));
const upgrades = { clothUpgrade, drillingUpgrade, oilUpgrade };
const paperGain = createSequentialModifier(() => [ const paperGain = createSequentialModifier(() => [
createMultiplicativeModifier(() => ({ createMultiplicativeModifier(() => ({
multiplier: 2, multiplier: 2,
@ -177,6 +239,16 @@ const layer = createLayer(id, function (this: BaseLayer) {
multiplier: 2, multiplier: 2,
description: "Scholar's jacket", description: "Scholar's jacket",
enabled: cloth.paperUpgrades.paperUpgrade3.bought enabled: cloth.paperUpgrades.paperUpgrade3.bought
})),
createMultiplicativeModifier(() => ({
multiplier: 10,
description: "Felt Elbow Pads",
enabled: cloth.paperUpgrades.paperUpgrade4.bought
})),
createMultiplicativeModifier(() => ({
multiplier: dyes.boosts.yellow1,
description: "Yellow Dye Boost 1",
enabled: () => Decimal.gte(dyes.dyes.yellow.amount.value, 1)
})) }))
]) as WithRequired<Modifier, "description" | "revert">; ]) as WithRequired<Modifier, "description" | "revert">;
@ -199,6 +271,17 @@ const layer = createLayer(id, function (this: BaseLayer) {
/> />
)); ));
globalBus.on("update", diff => {
if (Decimal.lt(main.day.value, day)) {
return;
}
paper.value = Decimal.times(diff, plastic.buyables.passivePaper.amount.value)
.times(paperConversion.currentGain.value)
.div(100)
.add(paper.value);
});
const { total: totalPaper, trackerDisplay } = setUpDailyProgressTracker({ const { total: totalPaper, trackerDisplay } = setUpDailyProgressTracker({
resource: paper, resource: paper,
goal: 5e3, goal: 5e3,
@ -220,6 +303,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
totalPaper, totalPaper,
paperConversion, paperConversion,
books, books,
upgrades,
generalTabCollapsed, generalTabCollapsed,
minWidth: 700, minWidth: 700,
display: jsx(() => ( display: jsx(() => (
@ -230,6 +314,8 @@ const layer = createLayer(id, function (this: BaseLayer) {
<Spacer /> <Spacer />
{render(makePaper)} {render(makePaper)}
<Spacer /> <Spacer />
{renderRow(...Object.values(upgrades))}
<Spacer />
{renderCol(...Object.values(books))} {renderCol(...Object.values(books))}
</> </>
)) ))

326
src/data/layers/plastic.tsx Normal file
View file

@ -0,0 +1,326 @@
/**
* @module
* @hidden
*/
import Column from "components/layout/Column.vue";
import Row from "components/layout/Row.vue";
import Spacer from "components/layout/Spacer.vue";
import Modal from "components/Modal.vue";
import {
changeActiveBuyables,
createCollapsibleModifierSections,
setUpDailyProgressTracker
} from "data/common";
import { main } from "data/projEntry";
import { createBuyable, GenericBuyable } from "features/buyable";
import { jsx, showIf } from "features/feature";
import MainDisplay from "features/resources/MainDisplay.vue";
import { createResource, Resource } from "features/resources/resource";
import { createUpgrade, GenericUpgrade } from "features/upgrades/upgrade";
import { globalBus } from "game/events";
import { BaseLayer, createLayer } from "game/layers";
import {
createAdditiveModifier,
createMultiplicativeModifier,
createSequentialModifier
} from "game/modifiers";
import { noPersist, persistent } from "game/persistence";
import Decimal, { DecimalSource, format, formatWhole } from "util/bignum";
import { render, renderCol, renderRow } from "util/vue";
import { computed, ref, unref } from "vue";
import boxes from "./boxes";
import metal from "./metal";
import oil from "./oil";
import dyes from "./dyes";
const id = "plastic";
const day = 10;
const layer = createLayer(id, function (this: BaseLayer) {
const name = "Plastic";
const color = "#DCD9CD";
const plastic = createResource<DecimalSource>(0, "plastic");
const [generalTab, generalTabCollapsed] = createCollapsibleModifierSections(() => [
{
title: "Plastic Gain",
modifier: plasticGain,
base: 0
}
]);
const showModifiersModal = ref(false);
const modifiersModal = jsx(() => (
<Modal
modelValue={showModifiersModal.value}
onUpdate:modelValue={(value: boolean) => (showModifiersModal.value = value)}
v-slots={{
header: () => <h2>{name} Modifiers</h2>,
body: generalTab
}}
/>
));
const activeRefinery = persistent<DecimalSource>(0);
const oilCost = computed(() => Decimal.times(activeRefinery.value, 100));
const buildRefinery = createBuyable(() => ({
resource: metal.metal,
cost() {
const v = new Decimal(this.amount.value);
return Decimal.pow(1.2, v).times(1e7);
},
display: jsx(() => (
<>
<h3>Refinery</h3>
<br />
Refines oil into plastic pellets
<br />
Consumes 100 oil/s to create 1 plastic/s
<br />
<br />
Currently:
<br />-{format(oilCost.value)} oil/sec
<br />+{format(activeRefinery.value)} plastic/sec
<br />
<br />
Cost: {formatWhole(unref(buildRefinery.cost!))}{" "}
{buildRefinery.resource!.displayName}
</>
)),
onPurchase() {
activeRefinery.value = Decimal.add(activeRefinery.value, 1);
},
style: {
width: "300px"
}
})) as GenericBuyable & { resource: Resource };
const {
min: minRefinery,
max: maxRefinery,
add: addRefinery,
remove: removeRefinery
} = changeActiveBuyables({
buyable: buildRefinery,
active: activeRefinery,
style: { minHeight: "20px", width: "40px", color: "var(--feature-foreground)" }
});
const upgradeCost = computed(() =>
Decimal.pow(
5,
Decimal.add(
[...Object.values(upgrades), ...Object.values(elfUpgrades)].filter(
upg => upg.bought.value
).length,
2
)
)
);
const paperTools = createUpgrade(() => ({
resource: noPersist(plastic),
cost: upgradeCost,
display: () => ({
title: "Plastic Scissors",
description: "Unlock paper upgrades",
showCost: !paperTools.bought.value
})
})) as GenericUpgrade;
const boxTools = createUpgrade(() => ({
resource: noPersist(plastic),
cost: upgradeCost,
display: () => ({
title: "Plastic Level",
description: "Unlock box upgrades",
showCost: !boxTools.bought.value
})
})) as GenericUpgrade;
const clothTools = createUpgrade(() => ({
resource: noPersist(plastic),
cost: upgradeCost,
display: () => ({
title: "Plastic Cane",
description: "Unlock cloth upgrades",
showCost: !clothTools.bought.value
})
})) as GenericUpgrade;
const upgrades = { paperTools, boxTools, clothTools };
const paperElf = createUpgrade(() => ({
resource: noPersist(plastic),
cost: upgradeCost,
visibility: () => showIf(paperTools.bought.value),
display: () => ({
title: "Paper Elf Recruitment",
description: "Double plastic gain and unlock a new elf for training",
showCost: !paperElf.bought.value
})
})) as GenericUpgrade;
const boxElf = createUpgrade(() => ({
resource: noPersist(plastic),
cost: upgradeCost,
visibility: () => showIf(boxTools.bought.value),
display: () => ({
title: "Box Elf Recruitment",
description: "Double plastic gain and unlock a new elf for training",
showCost: !boxElf.bought.value
})
})) as GenericUpgrade;
const clothElf = createUpgrade(() => ({
resource: noPersist(plastic),
cost: upgradeCost,
visibility: () => showIf(clothTools.bought.value),
display: () => ({
title: "Cloth Elf Recruitment",
description: "Double plastic gain and unlock a new elf for training",
showCost: !clothElf.bought.value
})
})) as GenericUpgrade;
const elfUpgrades = { paperElf, boxElf, clothElf };
const passivePaper = createBuyable(() => ({
resource: noPersist(plastic),
cost() {
const amount = this.amount.value;
return Decimal.pow(1.3, amount).times(100);
},
visibility: () => showIf(paperElf.bought.value),
display: {
title: "Plastic Printing Press",
description: "Gain +1% of your paper gain per second",
effectDisplay: jsx(() => <>{formatWhole(passivePaper.amount.value)}%</>),
showAmount: false
}
})) as GenericBuyable;
const passiveBoxes = createBuyable(() => ({
resource: noPersist(plastic),
cost() {
const amount = this.amount.value;
return Decimal.pow(1.3, amount).times(100);
},
visibility: () => showIf(boxElf.bought.value),
display: {
title: "Plastic Box Folder",
description: "Gain +1% of your box gain per second",
effectDisplay: jsx(() => <>{formatWhole(passiveBoxes.amount.value)}%</>),
showAmount: false
}
})) as GenericBuyable;
const clothGains = createBuyable(() => ({
resource: noPersist(plastic),
cost() {
const amount = this.amount.value;
return Decimal.pow(1.3, amount).times(100);
},
visibility: () => showIf(clothElf.bought.value),
display: {
title: "Plastic Shepherd",
description: "All cloth actions are +10% more efficient",
effectDisplay: jsx(() => (
<>{formatWhole(Decimal.times(clothGains.amount.value, 10))}%</>
)),
showAmount: false
}
})) as GenericBuyable;
const buyables = { passivePaper, passiveBoxes, clothGains };
const plasticGain = createSequentialModifier(() => [
createAdditiveModifier(() => ({
addend: activeRefinery,
description: "Oil Refinery",
enabled: () => Decimal.gt(activeRefinery.value, 0)
})),
createMultiplicativeModifier(() => ({
multiplier: 2,
description: "Paper Elf Recruitment",
enabled: paperElf.bought
})),
createMultiplicativeModifier(() => ({
multiplier: 2,
description: "Box Elf Recruitment",
enabled: boxElf.bought
})),
createMultiplicativeModifier(() => ({
multiplier: 2,
description: "Cloth Elf Recruitment",
enabled: clothElf.bought
})),
createMultiplicativeModifier(() => ({
multiplier: 2,
description: "Carry plastic in boxes",
enabled: boxes.row2Upgrades.plasticUpgrade.bought
})),
createMultiplicativeModifier(() => ({
multiplier: () => oil.oilEffectiveness.value,
description: "Effectiveness",
enabled: () => Decimal.lt(oil.oilEffectiveness.value, 1)
})),
createMultiplicativeModifier(() => ({
multiplier: dyes.boosts.yellow1,
description: "Yellow Dye Boost 1",
enabled: () => Decimal.gte(dyes.dyes.yellow.amount.value, 1)
}))
]);
const computedPlasticGain = computed(() => plasticGain.apply(0));
globalBus.on("update", diff => {
if (Decimal.lt(main.day.value, day)) {
return;
}
plastic.value = Decimal.times(diff, computedPlasticGain.value).add(plastic.value);
});
const { total: totalPlastic, trackerDisplay } = setUpDailyProgressTracker({
resource: plastic,
goal: 2.5e5,
name,
day,
color,
textColor: "var(--feature-foreground)",
modal: {
show: showModifiersModal,
display: modifiersModal
}
});
return {
name,
color,
plastic,
totalPlastic,
buildRefinery,
activeRefinery,
oilCost,
upgrades,
elfUpgrades,
buyables,
generalTabCollapsed,
minWidth: 700,
display: jsx(() => (
<>
{render(trackerDisplay)}
<Spacer />
<MainDisplay resource={plastic} color={color} style="margin-bottom: 0" effectDisplay={
Decimal.gt(computedPlasticGain.value, 0)
? `+${format(computedPlasticGain.value)}/s`
: undefined
} />
<Spacer />
<Column>
{render(buildRefinery)}
<div>
{formatWhole(Decimal.floor(activeRefinery.value))}/
{formatWhole(Decimal.floor(buildRefinery.amount.value))}
</div>
{renderRow(minRefinery, removeRefinery, addRefinery, maxRefinery)}
</Column>
<Row>
{renderCol(paperTools, paperElf, passivePaper)}
{renderCol(boxTools, boxElf, passiveBoxes)}
{renderCol(clothTools, clothElf, clothGains)}
</Row>
</>
))
};
});
export default layer;

View file

@ -34,6 +34,7 @@ import coal from "./coal";
import elves from "./elves"; import elves from "./elves";
import paper from "./paper"; import paper from "./paper";
import workshop from "./workshop"; import workshop from "./workshop";
import dyes from "./dyes";
const id = "trees"; const id = "trees";
const day = 1; const day = 1;
@ -76,6 +77,11 @@ const layer = createLayer(id, function (this: BaseLayer) {
multiplier: 4, multiplier: 4,
description: "Lumberjack Boots", description: "Lumberjack Boots",
enabled: cloth.treesUpgrades.treesUpgrade1.bought enabled: cloth.treesUpgrades.treesUpgrade1.bought
})),
createAdditiveModifier(() => ({
addend: dyes.boosts.blue1,
description: "Blue Dye Boost 1",
enabled: () => Decimal.gte(dyes.dyes.blue.amount.value, 1)
})) }))
]) as WithRequired<Modifier, "description" | "revert">; ]) as WithRequired<Modifier, "description" | "revert">;
const trees = createResource( const trees = createResource(
@ -414,6 +420,16 @@ const layer = createLayer(id, function (this: BaseLayer) {
description: "Carry more logs", description: "Carry more logs",
enabled: boxes.upgrades.logsUpgrade.bought enabled: boxes.upgrades.logsUpgrade.bought
})), })),
createMultiplicativeModifier(() => ({
multiplier: 10,
description: "Felt-Gripped Axe",
enabled: cloth.treesUpgrades.treesUpgrade4.bought
})),
createMultiplicativeModifier(() => ({
multiplier: computed(() => Decimal.add(computedAutoCuttingAmount.value, 1).log10().plus(1)),
description: "Is Blue Dye just Water?",
enabled: dyes.upgrades.blueDyeUpg.bought
})),
createExponentialModifier(() => ({ createExponentialModifier(() => ({
exponent: 1.2, exponent: 1.2,
description: "100% Foundation Completed", description: "100% Foundation Completed",

View file

@ -29,6 +29,8 @@ import boxesSymbol from "./symbols/cardboardBox.png";
import metalSymbol from "./symbols/metal.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 oilSymbol from "./symbols/oil.png";
import plasticSymbol from "./symbols/plastic.png";
import dyesSymbol from "./symbols/dyes.png";
import managementSymbol from "./symbols/elfManagement.png" import managementSymbol from "./symbols/elfManagement.png"
import coal from "./layers/coal"; import coal from "./layers/coal";
import elves from "./layers/elves"; import elves from "./layers/elves";
@ -37,7 +39,6 @@ import boxes from "./layers/boxes";
import metal from "./layers/metal"; import metal from "./layers/metal";
import cloth from "./layers/cloth"; import cloth from "./layers/cloth";
import oil from "./layers/oil"; import oil from "./layers/oil";
import management from "./layers/management";
export interface Day extends VueFeature { export interface Day extends VueFeature {
day: number; day: number;
@ -238,18 +239,20 @@ export const main = createLayer("main", function (this: BaseLayer) {
createDay(() => ({ createDay(() => ({
day: 10, day: 10,
shouldNotify: false, shouldNotify: false,
layer: null, // "plastic" layer: "plastic",
symbol: "", symbol: plasticSymbol,
story: "", story: "Now that plenty of oil has been prepared, it's time to start refining it into plastic! This should be incredibly useful not only for toys, but making tools and other items!",
completedStory: "" completedStory:
"You've started refining massive amounts of oil into slightly less massive amounts of plastic. You have a slight pang of regret thinking of the environmental impact, but ultimately decide Christmas is worth it. Good Job!"
})), })),
createDay(() => ({ createDay(() => ({
day: 11, day: 11,
shouldNotify: false, shouldNotify: false,
layer: null, // "dyes" layer: "dyes",
symbol: "", symbol: dyesSymbol,
story: "", story: "To make toys, we're going to need some color to make them look nice and enticing! We can't just give kids clear toys after all! To add some color to our toys, we'll need some dyes!",
completedStory: "" completedStory:
"After all that effort, you finally have a rainbow of dyes to choose from! Now the children won't be able to resist the toys you have to offer, once you get them made of course..."
})), })),
createDay(() => ({ createDay(() => ({
day: 12, day: 12,
@ -414,19 +417,7 @@ export const main = createLayer("main", function (this: BaseLayer) {
export const getInitialLayers = ( export const getInitialLayers = (
/* eslint-disable-next-line @typescript-eslint/no-unused-vars */ /* eslint-disable-next-line @typescript-eslint/no-unused-vars */
player: Partial<PlayerData> player: Partial<PlayerData>
): Array<GenericLayer> => [ ): Array<GenericLayer> => [main, trees, workshop, coal, elves, paper, boxes, metal, cloth, oil];
main,
trees,
workshop,
coal,
elves,
paper,
boxes,
metal,
cloth,
oil,
management
];
/** /**
* A computed ref whose value is true whenever the game is over. * A computed ref whose value is true whenever the game is over.

BIN
src/data/symbols/dyes.png Normal file

Binary file not shown.

After

(image error) Size: 2.1 KiB

Binary file not shown.

After

(image error) Size: 7.6 KiB

View file

@ -109,21 +109,21 @@ export default defineComponent({
}; };
switch (unref(direction)) { switch (unref(direction)) {
case Direction.Up: case Direction.Up:
barStyle.clipPath = `inset(${normalizedProgress.value}% 0% 0% 0%)`; barStyle.clipPath = `inset(${normalizedProgress.value}% -2px -2px -2px)`;
barStyle.width = unwrapRef(width) + 1 + "px"; barStyle.width = unwrapRef(width) + 2 + "px";
break; break;
case Direction.Down: case Direction.Down:
barStyle.clipPath = `inset(0% 0% ${normalizedProgress.value}% 0%)`; barStyle.clipPath = `inset(-2px -2px ${normalizedProgress.value}% -2px)`;
barStyle.width = unwrapRef(width) + 1 + "px"; barStyle.width = unwrapRef(width) + 2 + "px";
break; break;
case Direction.Right: case Direction.Right:
barStyle.clipPath = `inset(0% ${normalizedProgress.value}% 0% 0%)`; barStyle.clipPath = `inset(-2px ${normalizedProgress.value}% -2px -2px)`;
break; break;
case Direction.Left: case Direction.Left:
barStyle.clipPath = `inset(0% 0% 0% ${normalizedProgress.value} + '%)`; barStyle.clipPath = `inset(-2px -2px -2px ${normalizedProgress.value} + '%)`;
break; break;
case Direction.Default: case Direction.Default:
barStyle.clipPath = "inset(0% 50% 0% 0%)"; barStyle.clipPath = "inset(-2px 50% -2px -2px)";
break; break;
} }
return barStyle; return barStyle;
@ -146,6 +146,8 @@ export default defineComponent({
.bar { .bar {
position: relative; position: relative;
display: table; display: table;
overflow: hidden;
border-radius: 10px;
} }
.overlayTextContainer { .overlayTextContainer {
@ -166,7 +168,6 @@ export default defineComponent({
border-radius: 10px; border-radius: 10px;
border-color: var(--foreground); border-color: var(--foreground);
overflow: hidden; overflow: hidden;
mask-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAA5JREFUeNpiYGBgAAgwAAAEAAGbA+oJAAAAAElFTkSuQmCC);
margin: 0; margin: 0;
} }

View file

@ -4,9 +4,9 @@
:style="{ :style="{
visibility: unref(visibility) === Visibility.Hidden ? 'hidden' : undefined visibility: unref(visibility) === Visibility.Hidden ? 'hidden' : undefined
}" }"
class="table" class="table-grid"
> >
<div v-for="row in unref(rows)" class="row" :class="{ mergeAdjacent }" :key="row"> <div v-for="row in unref(rows)" class="row-grid" :class="{ mergeAdjacent }" :key="row">
<GridCell <GridCell
v-for="col in unref(cols)" v-for="col in unref(cols)"
:key="col" :key="col"

View file

@ -3,7 +3,7 @@
<div <div
class="main-display-container" class="main-display-container"
:class="classes ?? {}" :class="classes ?? {}"
:style="[{ height: `${(effectRef?.$el.clientHeight ?? 0) + 50}px` }, style ?? {}]" :style="[{ 'min-height': `${(effectRef?.$el.clientHeight ?? 0) + 50}px` }, style ?? {}]"
> >
<div class="main-display"> <div class="main-display">
<span v-if="showPrefix">You have </span> <span v-if="showPrefix">You have </span>
@ -23,7 +23,7 @@
<div v-else <div v-else
class="main-display-container" class="main-display-container"
:class="classes ?? {}" :class="classes ?? {}"
:style="[{ height: '50px' }, style ?? {}]" :style="[{ 'min-height': '50px' }, style ?? {}]"
> >
<div class="main-display"> <div class="main-display">
<span v-if="showPrefix">You have </span> <span v-if="showPrefix">You have </span>

View file

@ -49,7 +49,7 @@ requestAnimationFrame(async () => {
const toast = useToast(); const toast = useToast();
const { updateServiceWorker } = useRegisterSW({ const { updateServiceWorker } = useRegisterSW({
onNeedRefresh() { onNeedRefresh() {
toast.info("New content available, click or reload to update.", { toast.info("New content available, click here to update.", {
timeout: false, timeout: false,
closeOnClick: false, closeOnClick: false,
draggable: false, draggable: false,