From 7843fbb6c41af10f09b7e699f2f82cf3dbd655ee Mon Sep 17 00:00:00 2001 From: Seth Posner Date: Fri, 23 Dec 2022 22:53:47 -0800 Subject: [PATCH] Create initial packing layer --- src/data/layers/packing.tsx | 434 +++++++++++++++++++++++ src/data/layers/styles/day-gradients.css | 17 + src/data/projEntry.tsx | 6 +- 3 files changed, 455 insertions(+), 2 deletions(-) create mode 100644 src/data/layers/packing.tsx diff --git a/src/data/layers/packing.tsx b/src/data/layers/packing.tsx new file mode 100644 index 0000000..a1bf454 --- /dev/null +++ b/src/data/layers/packing.tsx @@ -0,0 +1,434 @@ +import { isArray } from "@vue/shared"; +import HotkeyVue from "components/Hotkey.vue"; +import SpacerVue from "components/layout/Spacer.vue"; +import { setUpDailyProgressTracker } from "data/common"; +import { main } from "data/projEntry"; +import { createBar } from "features/bars/bar"; +import { createBuyable, GenericBuyable } from "features/buyable"; +import { createClickable } from "features/clickables/clickable"; +import { jsx, showIf } from "features/feature"; +import { createHotkey } from "features/hotkey"; +import { createMilestone, GenericMilestone } from "features/milestones/milestone"; +import MainDisplayVue from "features/resources/MainDisplay.vue"; +import { createResource, trackBest, trackTotal, Resource } from "features/resources/resource"; +import { createLayer, BaseLayer } from "game/layers"; +import { createSequentialModifier } from "game/modifiers"; +import { noPersist, persistent } from "game/persistence"; +import Decimal, { DecimalSource, format, formatWhole } from "util/bignum"; +import { Direction } from "util/common"; +import { render, renderRow } from "util/vue"; +import { computed, ComputedRef, unref } from "vue"; +import metal from "./metal"; +import oil from "./oil"; +import { createCollapsibleMilestones } from "data/common" +import { globalBus } from "game/events"; + +const id = "packing" +const day = 24; + +const layer = createLayer(id, function (this: BaseLayer) { + const name = "Packing the Sleigh"; + const color = "lightblue"; + + const packedPresents = createResource(0, "packed presents"); + const bestPresents = trackBest(packedPresents); + const totalPresents = trackTotal(packedPresents); + const totalPresentsResource = createResource(computed(() => totalPresents.value), "total packed presents"); + + const sledSpace = 64e6; + const packingResets = persistent(0); + + const resetPacking = createClickable(() => ({ + display: { + description: "Do it all again, but better" + }, + visibility: () => showIf(Decimal.lt(packedPresents.value, 8e9) && Decimal.lte(remainingSize.value, 0)), + onClick() { + packedPresents.value = 0; + packingResets.value++; + } + })) + + const packingProgress = persistent(0); + const packingProgressBar = createBar(() => ({ + direction: Direction.Right, + width: 100, + height: 10, + fillStyle: { + animation: "15s packing-bar linear infinite", + }, + progress: () => packingProgress.value + })) + const packPresent = createClickable(() => ({ + display: { + description: jsx(() => ( + <> +

+ Pack a present +


+ {render(packingProgressBar)} + + )) + }, + visibility: () => showIf(Decimal.gt(remainingSize.value, 0)), + canClick: () => Decimal.gte(packingProgress.value, 1), + onClick() { + if (Decimal.lt(packingProgress.value, 1)) { + return; + } + packedPresents.value = Decimal.add(packedPresents.value, 1); + packingProgress.value = 0; + } + })); + const packHotkey = createHotkey(() => ({ + key: "p", + description: "Pack a present", + onPress() { if (packPresent.canClick.value) packPresent.onClick(); }, + enabled: noPersist(main.days[day - 1].opened) + })); + + const packingDensity = computed(() => { + switch(packingResets.value) { + default: return 0.6; + case 1: return 0.7; + case 2: return 0.85; + case 3: return 1; + } + }); + + const packedPresentsSize = computed(() => Decimal.times(packedPresents.value, 0.008).dividedBy(packingDensity.value)); + const remainingSize = computed(() => Decimal.sub(sledSpace, packedPresentsSize.value)); + + const elfPackingSpeed = createSequentialModifier(() => [ + + ]); + const computedElfPackingSpeed = computed(() => elfPackingSpeed.apply(1)); + + const loaderPackingSpeed = createSequentialModifier(() => [ + + ]); + const computedLoaderPackingSpeed = computed(() => loaderPackingSpeed.apply(1000)); + const helpers = { + elf: createBuyable(() => ({ + visibility: () => showIf(Decimal.gte(totalPresents.value, 10)), + cost() { return Decimal.pow(1.2, this.amount.value).times(10).floor() }, + resource: totalPresentsResource, + display: jsx(() => ( + <> +

Hire an elf assistant

+ Packs {format(computedElfPackingSpeed.value)} presents per second +

+ Amount: {formatWhole(helpers.elf.amount.value)}
+

+ Currently packing {format(Decimal.times(helpers.elf.amount.value, computedElfPackingSpeed.value))} presents per second
+
Requires: {formatWhole(unref(helpers.elf.cost!))} {helpers.elf.resource!.displayName}
+ + )), + style: { + width: "200px" + } + })), + loader: createBuyable(() => ({ + visibility: () => showIf(false), + metalCost: computed(() => Decimal.pow(1.5, helpers.loader.amount.value).times(1e40) ), + oilCost: computed(() => Decimal.pow(1.5, helpers.loader.amount.value).times(1e20) ), + canPurchase(this: GenericBuyable & {metalCost: ComputedRef, oilCost: ComputedRef}) { + return Decimal.gte(metal.metal.value, this.metalCost.value) + && Decimal.gte(oil.oil.value, this.oilCost.value) + }, + display: jsx(() => ( + <> +

Build a loader

+ Loads {format(computedLoaderPackingSpeed.value)} presents per second +

+ Amount: {formatWhole(helpers.loader.amount.value)}
+

+ Currently packing {format(Decimal.times(helpers.loader.amount.value, computedLoaderPackingSpeed.value))} persents per second
+
+ Cost: {displayCost(metal.metal, helpers.loader.metalCost.value, metal.metal.displayName)}, + {displayCost(oil.oil, helpers.loader.oilCost.value, oil.oil.displayName)}
+ + )) + })) + } as { + elf: GenericBuyable, + loader: GenericBuyable & {metalCost: ComputedRef, oilCost: ComputedRef} + }; + + const packingMilestones: Record = { + logBoost: createMilestone(() => ({ + display: { + requirement: `25 ${packedPresents.displayName}`, + effectDisplay: "Trees size is raised to the 1.25th power" + }, + shouldEarn: () => Decimal.gte(packedPresents.value, 25) + })), + boxBoost: createMilestone(() => ({ + display: { + requirement: `120 ${packedPresents.displayName}`, + effectDisplay: "Boxes are 10% bigger" + }, + shouldEarn: () => Decimal.gte(packedPresents.value, 120), + visibility: () => showIf(packingMilestones.logBoost.earned.value) + })) , + clothBoost: createMilestone(() => ({ + display: { + requirement: `600 ${packedPresents.displayName}`, + effectDisplay: "Sheep grow 10x as much wool" + }, + shouldEarn: () => Decimal.gte(packedPresents.value, 600), + visibility: () => showIf(packingMilestones.boxBoost.earned.value) + })) , + oilBoost: createMilestone(() => ({ + display: { + requirement: `2,800 ${packedPresents.displayName}`, + effectDisplay: "Triple drill power" + }, + shouldEarn: () => Decimal.gte(packedPresents.value, 2800), + visibility: () => showIf(packingMilestones.clothBoost.earned.value) + })) , + coalBoost: createMilestone(() => ({ + display: { + requirement: `14,000 ${packedPresents.displayName}`, + effectDisplay: "Coal producer costs grow half as fast" + }, + shouldEarn: () => Decimal.gte(packedPresents.value, 14000), + visibility: () => showIf(packingMilestones.oilBoost.earned.value) + })) , + metalBoost: createMilestone(() => ({ + display: { + requirement: `69,200 ${packedPresents.displayName}`, + effectDisplay: "Raise ore purity to the 1.5th power" + }, + shouldEarn: () => Decimal.gte(packedPresents.value, 69200), + visibility: () => showIf(packingMilestones.coalBoost.earned.value) + })) , + wrappingPaperBoost: createMilestone(() => ({ + display: { + requirement: `340,000 ${packedPresents.displayName}`, + effectDisplay: "Double the strength of wrapping paper bonuses" + }, + shouldEarn: () => Decimal.gte(packedPresents.value, 340000), + visibility: () => showIf(packingMilestones.metalBoost.earned.value) + })) , + oreBoost: createMilestone(() => ({ + display: { + requirement: `1,670,000 ${packedPresents.displayName}`, + effectDisplay: "Ore mining speed multiplies ore gain" + }, + shouldEarn: () => Decimal.gte(packedPresents.value, 1670000), + visibility: () => showIf(packingMilestones.wrappingPaperBoost.earned.value) + })) , + ribbonBoost: createMilestone(() => ({ + display: { + requirement: `8,230,000 ${packedPresents.displayName}`, + effectDisplay: "Ribbons are 90% cheaper" + }, + shouldEarn: () => Decimal.gte(packedPresents.value, 8230000), + visibility: () => showIf(packingMilestones.oreBoost.earned.value) + })) , + secondaryDyeBoost: createMilestone(() => ({ + display: { + requirement: `40,400,000 ${packedPresents.displayName}`, + effectDisplay: "Double the second effect of each secondary dye" + }, + shouldEarn: () => Decimal.gte(packedPresents.value, 40400000), + visibility: () => showIf(packingMilestones.ribbonBoost.earned.value) + })) , + paperBoost: createMilestone(() => ({ + display: { + requirement: `199,000,000 ${packedPresents.displayName}`, + effectDisplay: "Produce 10x as much paper" + }, + shouldEarn: () => Decimal.gte(packedPresents.value, 199000000), + visibility: () => showIf(packingMilestones.secondaryDyeBoost.earned.value) + })) , + primaryDyeBoost: createMilestone(() => ({ + display: { + requirement: `977,000,000 ${packedPresents.displayName}`, + effectDisplay: "Quintuple primary dye gain" + }, + shouldEarn: () => Decimal.gte(packedPresents.value, 977000000), + visibility: () => showIf(packingMilestones.paperBoost.earned.value) + })) , + wrappingPaperBoost2: createMilestone(() => ({ + display: { + requirement: `664,000 ${packedPresents.displayName}`, + effectDisplay: "Double the strength of wrapping paper bonuses, again" + }, + shouldEarn: () => Decimal.gte(packedPresents.value, 664000) && packingResets.value >= 1, + visibility: () => showIf(packingResets.value >= 1) + })) , + coalBoost2: createMilestone(() => ({ + display: { + requirement: `6,360,000 ${packedPresents.displayName}`, + effectDisplay: "Coal producers grow half as fast, again" + }, + shouldEarn: () => Decimal.gte(packedPresents.value, 6360000) && packingResets.value >= 1, + visibility: () => showIf(packingMilestones.wrappingPaperBoost2.earned.value) + })) , + oreBoost2: createMilestone(() => ({ + display: { + requirement: `60,900,000 ${packedPresents.displayName}`, + effectDisplay: "Ore mining speed multiplies ore gain, again" + }, + shouldEarn: () => Decimal.gte(packedPresents.value, 60900000) && packingResets.value >= 1, + visibility: () => showIf(packingMilestones.coalBoost2.earned.value) + })) , + primaryDyeBoost2: createMilestone(() => ({ + display: { + requirement: `584,000,000 ${packedPresents.displayName}`, + effectDisplay: "Quintuple primary dye gain, again" + }, + shouldEarn: () => Decimal.gte(packedPresents.value, 584000000) && packingResets.value >= 1, + visibility: () => showIf(packingMilestones.oreBoost2.earned.value) + })) , + ribbonBoost2: createMilestone(() => ({ + display: { + requirement: `734,000 ${packedPresents.displayName}`, + effectDisplay: "Ribbons are 90% cheaper, again" + }, + shouldEarn: () => Decimal.gte(packedPresents.value, 734000) && packingResets.value >= 2, + visibility: () => showIf(packingMilestones.primaryDyeBoost2.earned.value) + })) , + boxesBoost2: createMilestone(() => ({ + display: { + requirement: `7,200,000 ${packedPresents.displayName}`, + effectDisplay: "Boxes are 10% bigger, again" + }, + shouldEarn: () => Decimal.gte(packedPresents.value, 7200000) && packingResets.value >= 2, + visibility: () => showIf(packingMilestones.ribbonBoost2.earned.value) + })) , + secondaryDyeBoost2: createMilestone(() => ({ + display: { + requirement: `70,700,000 ${packedPresents.displayName}`, + effectDisplay: "Double the second effect of each secondary dye, again" + }, + shouldEarn: () => Decimal.gte(packedPresents.value, 70700000) && packingResets.value >= 2, + visibility: () => showIf(packingMilestones.boxesBoost2.earned.value) + })) , + paperBoost2: createMilestone(() => ({ + display: { + requirement: `693,000,000 ${packedPresents.displayName}`, + effectDisplay: "Produce another 10x as much paper" + }, + shouldEarn: () => Decimal.gte(packedPresents.value, 693000000) && packingResets.value >= 2, + visibility: () => showIf(packingMilestones.secondaryDyeBoost2.earned.value) + })) , + oilBoost2: createMilestone(() => ({ + display: { + requirement: `820,000 ${packedPresents.displayName}`, + effectDisplay: "Triple drill power, again" + }, + shouldEarn: () => Decimal.gte(packedPresents.value, 820000) && packingResets.value >= 3, + visibility: () => showIf(packingMilestones.paperBoost2.earned.value) + })) , + clothBoost2: createMilestone(() => ({ + display: { + requirement: `8,150,000 ${packedPresents.displayName}`, + effectDisplay: "Sheep grow 10x as much wool, again" + }, + shouldEarn: () => Decimal.gte(packedPresents.value, 8150000) && packingResets.value >= 3, + visibility: () => showIf(packingMilestones.oilBoost2.earned.value) + })) , + logsBoost2: createMilestone(() => ({ + display: { + requirement: `81,000,000 ${packedPresents.displayName}`, + effectDisplay: "Raise tree size to the 1.25th power, again" + }, + shouldEarn: () => Decimal.gte(packedPresents.value, 81000000) && packingResets.value >= 3, + visibility: () => showIf(packingMilestones.clothBoost2.earned.value) + })) , + metalBoost2: createMilestone(() => ({ + display: { + requirement: `800,000,000 ${packedPresents.displayName}`, + effectDisplay: "Raise ore purity to the 1.5th power, again" + }, + shouldEarn: () => Decimal.gte(packedPresents.value, 800000000) && packingResets.value >= 3, + visibility: () => showIf(packingMilestones.logsBoost2.earned.value) + })) + }; + const { collapseMilestones, display: milestonesDisplay } = + createCollapsibleMilestones(packingMilestones); + + const { trackerDisplay } = setUpDailyProgressTracker({ + resource: packedPresents, + ignoreTotal: true, + goal: 8e9, + name, + day, + background: { + gradient: "packing-bar", + duration: "15s" + }, + textColor: "var(--feature-foreground)", + }); + + globalBus.on("update", diff => { + if (Decimal.lt(main.day.value, day)) { + return; + } + + if (Decimal.gte(packingProgress.value, 1)) { + packingProgress.value = 1; + } + else { + packingProgress.value = Decimal.add(packingProgress.value, diff); + if (packPresent.isHolding.value) { + packPresent.onClick(); + } + } + + if (Decimal.lt(remainingSize.value, 0)) { + return; + } + packedPresents.value = Decimal.add( + Decimal.times(helpers.elf.amount.value, computedElfPackingSpeed.value), + Decimal.times(helpers.loader.amount.value, computedLoaderPackingSpeed.value) + ).times(diff).plus(packedPresents.value).min(8e9); + }) + + return { + name, + day, + color, + packedPresents, + bestPresents, + totalPresents, + packingResets, + packingProgress, + helpers, + packingMilestones, + collapseMilestones, + display: jsx(() => ( + <> + {render(trackerDisplay)} + + + + {render(resetPacking)} + {render(packPresent)} + + {renderRow(...Object.values(helpers))} + + {milestonesDisplay()} + + )), + minimizedDisplay: jsx(() => (
{name} {formatWhole(packedPresents.value)} {packedPresents.displayName}
)) + }; +}); + +export default layer; + +function displayCost( + res: Resource | Resource[], + cost: DecimalSource, + label: string +) { + const affordable = (isArray(res) ? res : [res]).every(res => Decimal.gte(res.value, cost)); + return ( + + {format(cost)} {label} + + ); +} \ No newline at end of file diff --git a/src/data/layers/styles/day-gradients.css b/src/data/layers/styles/day-gradients.css index b540378..a3b0286 100644 --- a/src/data/layers/styles/day-gradients.css +++ b/src/data/layers/styles/day-gradients.css @@ -77,4 +77,21 @@ yellow 10px 20px ); } +} + +@keyframes packing-bar { + from { + background: 0 0 / 170px 170px repeat repeating-linear-gradient(-45deg, + rgb(255, 76, 76) 0 10px, white 10px 20px, + rgb(65, 255, 95) 20px 30px, white 30px 40px, + rgb(76, 76, 255) 40px 50px, white 50px 60px + ); + } + to { + background: 170px 0 / 170px 170px repeat repeating-linear-gradient(-45deg, + rgb(255, 76, 76) 0 10px, white 10px 20px, + rgb(65, 255, 95) 20px 30px, white 30px 40px, + rgb(76, 76, 255) 40px 50px, white 50px 60px + ); + } } \ No newline at end of file diff --git a/src/data/projEntry.tsx b/src/data/projEntry.tsx index 349bac1..24d6f34 100644 --- a/src/data/projEntry.tsx +++ b/src/data/projEntry.tsx @@ -55,6 +55,7 @@ import toysSymbol from "./symbols/truck.png"; import advFactorySymbol from "./symbols/teddyBear.png"; import advManagementSymbol from "./symbols/workshopMansion.png"; import wrappingPaperSymbol from "./symbols/wrappingPaper.png"; +import packing from "./layers/packing"; export interface Day extends VueFeature { day: number; @@ -500,7 +501,7 @@ export const main = createLayer("main", function (this: BaseLayer) { createDay(() => ({ day: 24, shouldNotify: false, - layer: null, // "packing the presents" + layer: "packing", symbol: "", story: "", completedStory: "", @@ -615,7 +616,8 @@ export const getInitialLayers = ( wrappingPaper, ribbon, toys, - factory + factory, + packing ]; /**