From dcec8aaccae0299dec2bc1b63cd4e81414a011a5 Mon Sep 17 00:00:00 2001 From: someoneWasTaken94 <121205769+someoneWasTaken94@users.noreply.github.com> Date: Thu, 22 Dec 2022 13:31:25 +0000 Subject: [PATCH 01/48] most of multi-size code implemented --- src/data/layers/factory.tsx | 172 ++++++++++++++++++++++++++---------- 1 file changed, 123 insertions(+), 49 deletions(-) diff --git a/src/data/layers/factory.tsx b/src/data/layers/factory.tsx index 324704b..321fa90 100644 --- a/src/data/layers/factory.tsx +++ b/src/data/layers/factory.tsx @@ -394,6 +394,10 @@ const factory = createLayer(id, () => { type: "command" | "conveyor" | "processor"; description: string; energyCost?: number; + size?: { + width: number; + height: number; + }; /** amount it consumes */ inputs?: Record< @@ -433,7 +437,20 @@ const factory = createLayer(id, () => { interface FactoryInternalProcessor extends FactoryInternalBase { type: Exclude; } - type FactoryInternal = FactoryInternalConveyor | FactoryInternalProcessor; + + /** + * Fragment is just a hint that this spot is occupied by another component + * Does not actually do anything, but stores the string that the actual + * component is stored under + */ + interface FactoryInternalFragment { + type: "fragment"; + initalLocation: string; + } + type FactoryInternal = + | FactoryInternalConveyor + | FactoryInternalProcessor + | FactoryInternalFragment; interface Block { sprite: Sprite; @@ -538,6 +555,7 @@ const factory = createLayer(id, () => { const _data = components.value[id]; const _compData = compInternalData[id]; if (_data === undefined || _compData === undefined) continue; + if (_compData.type === "fragment") continue; const factoryData = FACTORY_COMPONENTS[_data.type]; // debugger; if (_data.type === "conveyor") { @@ -555,7 +573,7 @@ const factory = createLayer(id, () => { const dirAmt = directionToNum(inputDirection); if (dirType === "h") { if ((block.x - x) * dirAmt >= 1 + block.turbulance) { - const compBehind = compInternalData[x + dirAmt + "x" + y]; + let compBehind = compInternalData[x + dirAmt + "x" + y]; const storedComp = components.value[x + dirAmt + "x" + y]; // empty spot @@ -568,6 +586,12 @@ const factory = createLayer(id, () => { block.turbulance = Math.random() * 0.4 - 0.2; (compBehind as FactoryInternalConveyor).nextPackages.push(block); } else { + if (compBehind.type === "fragment") { + // this should be a factory processor, if it isn't something went wrong + compBehind = compInternalData[ + compBehind.initalLocation + ] as FactoryInternalProcessor; + } // send it to the factory // destory its sprite and data const factoryData = storedComp as FactoryComponentProcessor; @@ -591,7 +615,7 @@ const factory = createLayer(id, () => { } } else { if ((block.y - y) * dirAmt >= 1 + block.turbulance) { - const compBehind = compInternalData[x + "x" + (y + dirAmt)]; + let compBehind = compInternalData[x + "x" + (y + dirAmt)]; const storedComp = components.value[x + "x" + (y + dirAmt)]; // empty spot @@ -606,6 +630,12 @@ const factory = createLayer(id, () => { } else { // send it to the factory // destory its sprite and data + if (compBehind.type === "fragment") { + // this should be a factory processor, if it isn't something went wrong + compBehind = compInternalData[ + compBehind.initalLocation + ] as FactoryInternalProcessor; + } const data = storedComp as FactoryComponentProcessor; if (factoryData.inputs?.[block.type] !== undefined) { if (data.inputStock === undefined) data.inputStock = {}; @@ -747,6 +777,10 @@ const factory = createLayer(id, () => { const factoryBaseData = FACTORY_COMPONENTS[data.type]; if (factoryBaseData == undefined) return; + const size = factoryBaseData.size ?? { width: 1, height: 1 }; + + // this is too big + if (x + size.width >= factorySize.width || y + size.height >= factorySize.height) return; const sheet = Assets.get(factoryBaseData.imageSrc); const sprite = new Sprite(sheet); @@ -805,18 +839,43 @@ const factory = createLayer(id, () => { }), sprite } as FactoryInternalProcessor; + for (let _x = 0; _x < size.width; _x++) { + for (let _y = 0; _y < size.height; _y++) { + compInternalData[_x + "x" + _y] = { + type: "fragment", + initalLocation: x + "x" + y + }; + } + } spriteContainer.addChild(sprite); } - + function removeFactoryComp(x: number, y: number) { const data = compInternalData[x + "x" + y]; if (data === undefined) return; + if (data.type === "fragment") { + const [x, y] = data.initalLocation.split("x").map(i => +i); + removeFactoryComp(x, y); + return; + } + if (data.type === "conveyor") { const cData = data as FactoryInternalConveyor; for (const p of cData.packages) { p.sprite.destroy(); } + } else { + const size = FACTORY_COMPONENTS[data.type].size ?? { width: 1, height: 1 }; + + // delete all components + for (let x = 0; x < size.width; x++) { + for (let y = 0; y < size.height; y++) { + // this will be handled below + if (x === 0 && y === 0) continue; + delete compInternalData[x + "x" + y]; + } + } } delete components.value[x + "x" + y]; @@ -917,7 +976,8 @@ const factory = createLayer(id, () => { if (compSelected.value === "rotateLeft") { if ( components.value[x + "x" + y] != null && - components.value[x + "x" + y].direction != null + components.value[x + "x" + y].direction != null && + compInternalData[x + "x" + y].type !== "fragment" ) { components.value[x + "x" + y] = { ...components.value[x + "x" + y], @@ -927,12 +987,15 @@ const factory = createLayer(id, () => { Direction.Left ) }; - compInternalData[x + "x" + y].sprite.rotation -= Math.PI / 2; + ( + compInternalData[x + "x" + y] as FactoryInternalProcessor + ).sprite.rotation -= Math.PI / 2; } } else if (compSelected.value === "rotateRight") { if ( components.value[x + "x" + y] != null && - components.value[x + "x" + y].direction != null + components.value[x + "x" + y].direction != null && + compInternalData[x + "x" + y]?.type !== "fragment" ) { components.value[x + "x" + y] = { ...components.value[x + "x" + y], @@ -942,9 +1005,18 @@ const factory = createLayer(id, () => { Direction.Right ) }; - compInternalData[x + "x" + y].sprite.rotation += Math.PI / 2; + ( + compInternalData[x + "x" + y] as FactoryInternalProcessor + ).sprite.rotation += Math.PI / 2; } } else if (compSelected.value === "delete") { + if (compInternalData[x + "x" + y]?.type === "fragment") { + [x, y] = ( + compInternalData[x + "x" + y] as FactoryInternalFragment + ).initalLocation + .split("x") + .map(i => +i); + } removeFactoryComp(x, y); } else if (compSelected.value !== "cursor") { if (components.value[x + "x" + y] == null) { @@ -976,10 +1048,11 @@ const factory = createLayer(id, () => { function onCompClick(name: FactoryCompNames) { compSelected.value = name; } - + function setTracks() { for (const [key, comp] of Object.entries(compInternalData)) { if (comp == null) continue; + if (comp.type === "fragment") continue; if (comp.type === "conveyor") { for (const pkg of [...comp.nextPackages, ...comp.packages]) { pkg.sprite.destroy(); @@ -988,7 +1061,7 @@ const factory = createLayer(id, () => { comp.nextPackages = []; comp.packages = []; } else { - const producerComp = components.value[key] as FactoryComponentProducer; + const producerComp = components.value[key] as FactoryComponentProcessor; if (producerComp.outputStock !== undefined) { for (const key in producerComp.outputStock) { delete producerComp.outputStock[key]; @@ -1003,9 +1076,10 @@ const factory = createLayer(id, () => { } } } - + function clearFactory() { for (const key of Object.keys(compInternalData)) { + if (compInternalData[key].type === "fragment") continue; const [x, y] = key.split("x").map(i => +i); removeFactoryComp(x, y); } @@ -1059,44 +1133,44 @@ const factory = createLayer(id, () => { onContextmenu={(e: MouseEvent) => e.preventDefault()} />
- - - - -
- + + + + + +
Date: Fri, 23 Dec 2022 01:08:46 +0000 Subject: [PATCH 02/48] do changes --- src/data/layers/factory.tsx | 179 +++++++++++++++++------------------- 1 file changed, 85 insertions(+), 94 deletions(-) diff --git a/src/data/layers/factory.tsx b/src/data/layers/factory.tsx index 0f426df..388d6de 100644 --- a/src/data/layers/factory.tsx +++ b/src/data/layers/factory.tsx @@ -29,8 +29,8 @@ import { noPersist, Persistent, persistent, State } from "game/persistence"; import Decimal, { DecimalSource, format, formatWhole } from "util/bignum"; import { Direction } from "util/common"; import { ProcessedComputable } from "util/computed"; -import { render, renderRow } from "util/vue"; -import { computed, ComputedRef, reactive, ref, unref, watchEffect } from "vue"; +import { render, renderRow, VueFeature } from "util/vue"; +import { computed, ComputedRef, reactive, ref, shallowRef, unref, watchEffect } from "vue"; import coal from "./coal"; import _block from "./factory-components/block.svg"; import _blockMaker from "./factory-components/blockmaker.svg"; @@ -249,7 +249,7 @@ const factory = createLayer(id, () => { key: "0", name: "Conveyor", type: "conveyor", - description: "Moves items at 1 block per second.", + description: "Moves items at 1 block per tick.", energyCost: 1, tick: 1, ports: { @@ -267,7 +267,7 @@ const factory = createLayer(id, () => { key: "1", name: "Wood Machine", type: "processor", - description: "Produces 1 wood every 1 second.", + description: "Produces 1 wood per tick.", energyCost: 10, tick: 1, outputs: { @@ -282,7 +282,7 @@ const factory = createLayer(id, () => { key: "2", name: "Cloth Machine", type: "processor", - description: "Produces 1 cloth every 1 second.", + description: "Produces 1 cloth per tick.", energyCost: 10, tick: 1, outputs: { @@ -297,7 +297,7 @@ const factory = createLayer(id, () => { key: "3", name: "Dye Machine", type: "processor", - description: "Produces 1 dye every 1 second.", + description: "Produces 1 dye per tick.", energyCost: 10, tick: 1, outputs: { @@ -312,7 +312,7 @@ const factory = createLayer(id, () => { key: "4", name: "Metal Machine", type: "processor", - description: "Produces 1 metal every 1 second.", + description: "Produces 1 metal per tick.", energyCost: 10, tick: 1, outputs: { @@ -327,7 +327,7 @@ const factory = createLayer(id, () => { key: "5", name: "Plastic Machine", type: "processor", - description: "Produces 1 plastic every 1 second.", + description: "Produces 1 plastic per tick.", energyCost: 10, tick: 1, outputs: { @@ -341,7 +341,7 @@ const factory = createLayer(id, () => { key: "shift+1", name: "Sawmill", type: "processor", - description: "Turns 1 wood into 1 plank every second.", + description: "Turns 1 wood into 1 plank per tick.", energyCost: 2, tick: 1, inputs: { @@ -360,7 +360,7 @@ const factory = createLayer(id, () => { key: "shift+2", name: "Thread Spinner", type: "processor", - description: "Turns 1 cloth into 1 thread every second.", + description: "Turns 1 cloth into 1 thread per tick.", energyCost: 2, tick: 1, inputs: { @@ -384,7 +384,7 @@ const factory = createLayer(id, () => { () => `Turns 1 plastic into ${ toys.milestones.milestone5.earned.value ? "2 wheels" : "1 wheel" - } every second.` + } per tick.` ), energyCost: 2, tick: 1, @@ -404,7 +404,7 @@ const factory = createLayer(id, () => { key: "ctrl+shift+1", name: "Wooden Block Maker", type: "processor", - description: "Turns 1 plank into 1 wooden block every second.", + description: "Turns 1 plank into 1 wooden block per tick.", energyCost: 20, tick: 1, inputs: { @@ -424,7 +424,7 @@ const factory = createLayer(id, () => { key: "ctrl+shift+2", name: "Clothes Maker", type: "processor", - description: "Turns 2 threads, 3 cloth, and 1 dye into 1 clothes every second.", + description: "Turns 2 threads, 3 cloth, and 1 dye into 1 clothes per tick.", energyCost: 20, tick: 1, inputs: { @@ -450,7 +450,7 @@ const factory = createLayer(id, () => { key: "ctrl+shift+3", name: "Trucks Maker", type: "processor", - description: "Turns 2 metal and 4 wheels into 1 truck every second.", + description: "Turns 2 metal and 4 wheels into 1 truck per tick.", energyCost: 20, tick: 1, inputs: { @@ -575,10 +575,6 @@ const factory = createLayer(id, () => { type: "command" | "conveyor" | "processor"; description: ProcessedComputable; energyCost?: number; - size?: { - width: number; - height: number; - }; /** amount it consumes */ inputs?: Stock; @@ -605,21 +601,12 @@ const factory = createLayer(id, () => { } interface FactoryInternalProcessor extends FactoryInternalBase { type: Exclude; - } + lastProdTimes: number[]; - /** - * Fragment is just a hint that this spot is occupied by another component - * Does not actually do anything, but stores the string that the actual - * component is stored under - */ - interface FactoryInternalFragment { - type: "fragment"; - initalLocation: string; + lastFactoryProd: number; + average: ComputedRef; } - type FactoryInternal = - | FactoryInternalConveyor - | FactoryInternalProcessor - | FactoryInternalFragment; + type FactoryInternal = FactoryInternalConveyor | FactoryInternalProcessor; interface Block { sprite: Sprite; @@ -760,9 +747,6 @@ const factory = createLayer(id, () => { loaded = true; watchEffect(updateGraphics); }); - (window as any).internal = compInternalData; - (window as any).comp = components; - (window as any).blocks = movingBlocks; function moveBlock(block: Block, newBlock: FactoryInternal, blockData: FactoryComponent) { // empty spot @@ -800,7 +784,6 @@ const factory = createLayer(id, () => { const _data = components.value[id]; const _compData = compInternalData[id]; if (_data === undefined || _compData === undefined) continue; - if (_compData.type === "fragment") continue; const factoryData = FACTORY_COMPONENTS[_data.type]; // debugger; if (_data.type === "conveyor") { @@ -818,7 +801,7 @@ const factory = createLayer(id, () => { const dirAmt = directionToNum(inputDirection); if (dirType === "h") { if ((block.x - x) * dirAmt >= 1 + block.turbulance) { - let compBehind = compInternalData[x + dirAmt + "x" + y]; + const compBehind = compInternalData[x + dirAmt + "x" + y]; const storedComp = components.value[x + dirAmt + "x" + y]; moveBlock(block, compBehind, storedComp); @@ -834,7 +817,7 @@ const factory = createLayer(id, () => { } } else { if ((block.y - y) * dirAmt >= 1 + block.turbulance) { - let compBehind = compInternalData[x + "x" + (y + dirAmt)]; + const compBehind = compInternalData[x + "x" + (y + dirAmt)]; const storedComp = components.value[x + "x" + (y + dirAmt)]; moveBlock(block, compBehind, storedComp); @@ -883,6 +866,12 @@ const factory = createLayer(id, () => { } } data.ticksDone -= cyclesDone * factoryData.tick; + const now = Date.now(); + const diff = (now - compData.lastFactoryProd) / 1000; + compData.lastProdTimes.push(diff); + console.log(compData.lastProdTimes); + if (compData.lastProdTimes.length > 10) compData.lastProdTimes.shift(); + compData.lastFactoryProd = now; } } else { data.ticksDone += factoryTicks; @@ -982,10 +971,6 @@ const factory = createLayer(id, () => { const factoryBaseData = FACTORY_COMPONENTS[data.type]; if (factoryBaseData == undefined) return; - const size = factoryBaseData.size ?? { width: 1, height: 1 }; - - // this is too big - if (x + size.width >= factorySize.width || y + size.height >= factorySize.height) return; const sheet = Assets.get(factoryBaseData.imageSrc); const sprite = new Sprite(sheet); @@ -1031,6 +1016,26 @@ const factory = createLayer(id, () => { type: data.type, packages: isConveyor ? [] : undefined, nextPackages: isConveyor ? [] : undefined, + lastProdTimes: !isConveyor ? (reactive([]) as number[]) : undefined, + lastFactoryProd: !isConveyor + ? Date.now() - + 1000 * Decimal.div(data.ticksDone ?? 0, computedTickRate.value).toNumber() + : undefined, + average: !isConveyor + ? computed(() => { + const times = (compInternalData[x + "x" + y] as FactoryInternalProcessor) + .lastProdTimes; + if (times.length === 0) return undefined; + + // times is in SECONDS, not ticks + // seconds * Ticks per second -> ticks taken + + return Decimal.mul(times.length, factoryBaseData.tick) + .div(times.reduce((x, n) => x + n, 0)) + .div(computedTickRate.value) + .toNumber(); + }) + : undefined, canProduce: computed(() => { if (data.type === "conveyor") return true; if (!(factoryBaseData.canProduce?.value ?? true)) return false; @@ -1054,14 +1059,6 @@ const factory = createLayer(id, () => { }), sprite } as FactoryInternalProcessor; - for (let _x = 0; _x < size.width; _x++) { - for (let _y = 0; _y < size.height; _y++) { - compInternalData[_x + "x" + _y] = { - type: "fragment", - initalLocation: x + "x" + y - }; - } - } spriteContainer.addChild(sprite); } @@ -1069,28 +1066,11 @@ const factory = createLayer(id, () => { const data = compInternalData[x + "x" + y]; if (data === undefined) return; - if (data.type === "fragment") { - const [x, y] = data.initalLocation.split("x").map(i => +i); - removeFactoryComp(x, y); - return; - } - if (data.type === "conveyor") { const cData = data as FactoryInternalConveyor; for (const p of cData.packages) { p.sprite.destroy(); } - } else { - const size = FACTORY_COMPONENTS[data.type].size ?? { width: 1, height: 1 }; - - // delete all components - for (let x = 0; x < size.width; x++) { - for (let y = 0; y < size.height; y++) { - // this will be handled below - if (x === 0 && y === 0) continue; - delete compInternalData[x + "x" + y]; - } - } } delete components.value[x + "x" + y]; @@ -1135,6 +1115,7 @@ const factory = createLayer(id, () => { const pointerDown = ref(false), pointerDrag = ref(false), compHovered = ref(undefined), + compInternalHovered = shallowRef(undefined), paused = ref(false); function onFactoryPointerMove(e: PointerEvent) { @@ -1164,12 +1145,12 @@ const factory = createLayer(id, () => { } if (!pointerDown.value && !pointerDrag.value) { const { tx, ty } = spriteContainer.localTransform; - compHovered.value = - components.value[ - Math.round(roundDownTo(x - tx, blockSize) / blockSize) + - "x" + - Math.round(roundDownTo(y - ty, blockSize) / blockSize) - ]; + const xyPos = + Math.round(roundDownTo(x - tx, blockSize) / blockSize) + + "x" + + Math.round(roundDownTo(y - ty, blockSize) / blockSize); + compHovered.value = components.value[xyPos]; + compInternalHovered.value = compInternalData[xyPos]; } } function onFactoryPointerDown(e: PointerEvent) { @@ -1191,8 +1172,7 @@ const factory = createLayer(id, () => { if (compSelected.value === "rotateLeft") { if ( components.value[x + "x" + y] != null && - components.value[x + "x" + y].direction != null && - compInternalData[x + "x" + y].type !== "fragment" + components.value[x + "x" + y].direction != null ) { components.value[x + "x" + y] = { ...components.value[x + "x" + y], @@ -1202,15 +1182,12 @@ const factory = createLayer(id, () => { Direction.Left ) }; - ( - compInternalData[x + "x" + y] as FactoryInternalProcessor - ).sprite.rotation -= Math.PI / 2; + compInternalData[x + "x" + y].sprite.rotation -= Math.PI / 2; } } else if (compSelected.value === "rotateRight") { if ( components.value[x + "x" + y] != null && - components.value[x + "x" + y].direction != null && - compInternalData[x + "x" + y]?.type !== "fragment" + components.value[x + "x" + y].direction != null ) { components.value[x + "x" + y] = { ...components.value[x + "x" + y], @@ -1220,18 +1197,9 @@ const factory = createLayer(id, () => { Direction.Right ) }; - ( - compInternalData[x + "x" + y] as FactoryInternalProcessor - ).sprite.rotation += Math.PI / 2; + compInternalData[x + "x" + y].sprite.rotation += Math.PI / 2; } } else if (compSelected.value === "delete") { - if (compInternalData[x + "x" + y]?.type === "fragment") { - [x, y] = ( - compInternalData[x + "x" + y] as FactoryInternalFragment - ).initalLocation - .split("x") - .map(i => +i); - } removeFactoryComp(x, y); } else if (compSelected.value !== "cursor") { if (components.value[x + "x" + y] == null) { @@ -1267,7 +1235,6 @@ const factory = createLayer(id, () => { function setTracks() { for (const [key, comp] of Object.entries(compInternalData)) { if (comp == null) continue; - if (comp.type === "fragment") continue; if (comp.type === "conveyor") { const cComp = comp as FactoryInternalConveyor; for (const pkg of [...cComp.nextPackages, ...cComp.packages]) { @@ -1278,6 +1245,7 @@ const factory = createLayer(id, () => { cComp.packages = []; } else { const producerComp = components.value[key] as FactoryComponentProcessor; + const cComp = comp as FactoryInternalProcessor; if (producerComp.outputStock !== undefined) { for (const key in producerComp.outputStock) { delete producerComp.outputStock[key as ResourceNames]; @@ -1289,13 +1257,14 @@ const factory = createLayer(id, () => { } } producerComp.ticksDone = 0; + cComp.lastFactoryProd = Date.now(); + cComp.lastProdTimes.splice(0, Infinity); } } } function clearFactory() { for (const key of Object.keys(compInternalData)) { - if (compInternalData[key].type === "fragment") continue; const [x, y] = key.split("x").map(i => +i); removeFactoryComp(x, y); } @@ -1401,7 +1370,7 @@ const factory = createLayer(id, () => { } const hoveredComponent = jsx(() => - compHovered.value !== undefined ? ( + compHovered.value !== undefined && compInternalHovered.value !== undefined ? (
{
{unref(FACTORY_COMPONENTS[compHovered.value.type].description)}
- {compHovered.value.type !== "conveyor" ? ( + {compHovered.value.type !== "conveyor" && + compInternalHovered.value.type !== "conveyor" ? ( <> {showStockAmount( compHovered.value.inputStock, @@ -1435,6 +1405,27 @@ const factory = createLayer(id, () => { "Outputs:", false )} +
+ Efficency:{" "} + {compInternalHovered.value.average.value !== undefined ? ( + 1 + ? "purple" + : compInternalHovered.value.average.value >= 0.9 + ? "green" + : compInternalHovered.value.average.value >= 0.5 + ? "yellow" + : "red" + }} + > + {formatWhole(compInternalHovered.value.average.value * 100)} + + ) : ( + "--" + )} + % ) : undefined}
@@ -1595,7 +1586,7 @@ const factory = createLayer(id, () => { display: jsx(() => ( <> {render(modifiersModal)} - {render(tabs)} + {render(tabs as VueFeature)} )) }; From 2aa68be8521eb73628ece96e125c4c0f06fb89c5 Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Thu, 22 Dec 2022 17:58:22 -0600 Subject: [PATCH 03/48] Basic reindeer stuff --- src/data/layers/reindeer.tsx | 83 ++++++++++++++++++++++++++++++++++++ src/data/projEntry.tsx | 7 +-- 2 files changed, 87 insertions(+), 3 deletions(-) create mode 100644 src/data/layers/reindeer.tsx diff --git a/src/data/layers/reindeer.tsx b/src/data/layers/reindeer.tsx new file mode 100644 index 0000000..3a3f448 --- /dev/null +++ b/src/data/layers/reindeer.tsx @@ -0,0 +1,83 @@ +/** + * @module + * @hidden + */ +import Spacer from "components/layout/Spacer.vue"; +import Modal from "components/Modal.vue"; +import { createCollapsibleModifierSections, setUpDailyProgressTracker } from "data/common"; +import { main } from "data/projEntry"; +import { jsx } from "features/feature"; +import MainDisplay from "features/resources/MainDisplay.vue"; +import { createResource } from "features/resources/resource"; +import { globalBus } from "game/events"; +import { BaseLayer, createLayer } from "game/layers"; +import Decimal, { DecimalSource, format } from "util/bignum"; +import { render } from "util/vue"; +import { ref } from "vue"; + +const id = "reindeer"; +const day = 21; +const layer = createLayer(id, function (this: BaseLayer) { + const name = "Reindeer"; + const color = "brown"; + + const food = createResource(0, "reindeer food"); + + const [generalTab, generalTabCollapsed] = createCollapsibleModifierSections(() => []); + const showModifiersModal = ref(false); + const modifiersModal = jsx(() => ( + (showModifiersModal.value = value)} + v-slots={{ + header: () =>

{name} Modifiers

, + body: generalTab + }} + /> + )); + + globalBus.on("update", diff => { + if (Decimal.lt(main.day.value, day)) { + return; + } + }); + + const { total: totalFood, trackerDisplay } = setUpDailyProgressTracker({ + resource: food, + goal: 1e3, + name, + day, + background: color, + modal: { + show: showModifiersModal, + display: modifiersModal + } + }); + + return { + name, + day, + color, + food, + totalFood, + generalTabCollapsed, + minWidth: 700, + display: jsx(() => ( + <> + {render(trackerDisplay)} + + + + )), + minimizedDisplay: jsx(() => ( +
+ {name}{" "} + + {format(food.value)} {food.displayName} + +
+ )) + }; +}); + +export default layer; diff --git a/src/data/projEntry.tsx b/src/data/projEntry.tsx index 97ffcd9..c036c3d 100644 --- a/src/data/projEntry.tsx +++ b/src/data/projEntry.tsx @@ -473,10 +473,11 @@ export const main = createLayer("main", function (this: BaseLayer) { createDay(() => ({ day: 21, shouldNotify: false, - layer: null, // "reindeer" + layer: "reindeer", symbol: "", - story: "", - completedStory: "", + story: "Now that the toys are being taken care of, it's time to make sure everything is prepped for the big night. One immediate concern is the reindeer, who are going to have to be in tip-top shape. Fortunately, Santa has a recipe to a very strong vitamin-filled kibble that'll get them pumped in no time!", + completedStory: + "Alright, now that the reindeer have been given all their ste- vitamins, I mean, they should be prepared for Christmas. Good Job!", masteredStory: "" })), createDay(() => ({ From e706daf9bb0048b74bc2b6475b5fd76993af29e4 Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Thu, 22 Dec 2022 19:07:50 -0600 Subject: [PATCH 04/48] Actually add reindeer --- src/data/projEntry.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/data/projEntry.tsx b/src/data/projEntry.tsx index c036c3d..23855ed 100644 --- a/src/data/projEntry.tsx +++ b/src/data/projEntry.tsx @@ -31,6 +31,7 @@ import metal from "./layers/metal"; import oil from "./layers/oil"; import paper from "./layers/paper"; import plastic from "./layers/plastic"; +import reindeer from "./layers/reindeer"; import ribbon from "./layers/ribbon"; import toys from "./layers/toys"; import trees from "./layers/trees"; @@ -616,7 +617,8 @@ export const getInitialLayers = ( wrappingPaper, ribbon, toys, - factory + factory, + reindeer ]; /** From 1a857411ee0b3dad7a5aa1fe49ee6688bc8b92c5 Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Thu, 22 Dec 2022 20:59:29 -0600 Subject: [PATCH 05/48] Add reindeer clickables --- src/data/layers/reindeer.tsx | 230 +++++++++++++++++++++++++++++++---- src/features/hotkey.tsx | 3 + 2 files changed, 210 insertions(+), 23 deletions(-) diff --git a/src/data/layers/reindeer.tsx b/src/data/layers/reindeer.tsx index 3a3f448..75ce093 100644 --- a/src/data/layers/reindeer.tsx +++ b/src/data/layers/reindeer.tsx @@ -2,26 +2,181 @@ * @module * @hidden */ +import HotkeyVue from "components/Hotkey.vue"; import Spacer from "components/layout/Spacer.vue"; import Modal from "components/Modal.vue"; import { createCollapsibleModifierSections, setUpDailyProgressTracker } from "data/common"; import { main } from "data/projEntry"; +import { createBar, GenericBar } from "features/bars/bar"; +import { createClickable } from "features/clickables/clickable"; import { jsx } from "features/feature"; +import { createHotkey, GenericHotkey } from "features/hotkey"; import MainDisplay from "features/resources/MainDisplay.vue"; -import { createResource } from "features/resources/resource"; +import { createResource, Resource } from "features/resources/resource"; import { globalBus } from "game/events"; import { BaseLayer, createLayer } from "game/layers"; -import Decimal, { DecimalSource, format } from "util/bignum"; -import { render } from "util/vue"; -import { ref } from "vue"; +import { persistent } from "game/persistence"; +import Decimal, { DecimalSource, format, formatWhole } from "util/bignum"; +import { Direction } from "util/common"; +import { render, renderGrid } from "util/vue"; +import { computed, ref, unref, watchEffect } from "vue"; const id = "reindeer"; const day = 21; const layer = createLayer(id, function (this: BaseLayer) { const name = "Reindeer"; - const color = "brown"; + const color = "saddlebrown"; - const food = createResource(0, "reindeer food"); + const feedGoal = 1e3; + + // TODO focus + + function createReindeer(options: { + name: string; + key: string; + boostDescription: string; + boostAmount: DecimalSource; + }) { + const timesFed = persistent(0); + const progress = persistent(0); + + const hotkey = createHotkey(() => ({ + key: "Numpad " + options.key, + description: "Feed " + options.name, + enabled: main.days[day - 1].opened, + onPress: clickable.onClick + })) as GenericHotkey; + + const clickable = createClickable(() => { + const computedCooldown = computed(() => 10); + + const progressBar = createBar(() => ({ + direction: Direction.Right, + width: 140, + height: 10, + style: "margin-top: 8px", + borderStyle: "border-color: black", + baseStyle: "margin-top: -1px", + fillStyle: "margin-top: -1px; transition-duration: 0s; background: black", + progress: () => Decimal.div(progress.value, computedCooldown.value) + })); + + return { + ...options, + hotkey, + timesFed, + progress, + display: { + title: jsx(() => ( +

+ Feed {options.name} +

+ )), + description: jsx(() => ( + <> +
+ Each time you feed {options.name} will increase your{" "} + {options.boostDescription} by +{format(options.boostAmount)}x + + Currently {format(Decimal.pow(options.boostAmount, timesFed.value))}x +
+ {render(progressBar)} + + )) + }, + style: { + width: "160px", + height: "160px" + }, + canClick() { + return Decimal.gte(progress.value, computedCooldown.value); + }, + onClick() { + if (!unref(clickable.canClick)) { + return; + } + const amount = Decimal.div(progress.value, computedCooldown.value); + timesFed.value = Decimal.add(timesFed.value, amount); + progress.value = 0; + }, + update(diff: number) { + console.log(progress.value, computedCooldown.value, diff); + if (Decimal.gte(progress.value, computedCooldown.value)) { + progress.value = computedCooldown.value; + } else { + progress.value = Decimal.add(progress.value, diff); + if (clickable.isHolding.value) { + clickable.onClick(); + } + } + } + }; + }); + return clickable; + } + const dasher = createReindeer({ + name: "Dasher", + key: "7", + boostDescription: "log gain", + boostAmount: 1 + }); + const dancer = createReindeer({ + name: "Dancer", + key: "8", + boostDescription: "coal gain", + boostAmount: 0.1 + }); + const prancer = createReindeer({ + name: "Prancer", + key: "9", + boostDescription: "paper gain", + boostAmount: 0.1 + }); + const vixen = createReindeer({ + name: "Vixen", + key: "4", + boostDescription: "boxes gain", + boostAmount: 0.1 + }); + const comet = createReindeer({ + name: "Comet", + key: "5", + boostDescription: "metal gain", + boostAmount: 0.1 + }); + const cupid = createReindeer({ + name: "Cupid", + key: "6", + boostDescription: "cloth actions", + boostAmount: 0.1 + }); + const donner = createReindeer({ + name: "Donner", + key: "1", + boostDescription: "oil gain", + boostAmount: 0.01 + }); + const blitzen = createReindeer({ + name: "Blitzen", + key: "2", + boostDescription: "plastic gain", + boostAmount: 0.1 + }); + const rudolph = createReindeer({ + name: "Rudolph", + key: "3", + boostDescription: "dye gain", + boostAmount: 0.01 + }); + const reindeer = { dasher, dancer, prancer, vixen, comet, cupid, donner, blitzen, rudolph }; + + const sumTimesFed = computed(() => + Object.values(reindeer) + .map(r => r.timesFed.value) + .reduce(Decimal.add, Decimal.dZero) + ); + + // TODO upgrades const [generalTab, generalTabCollapsed] = createCollapsibleModifierSections(() => []); const showModifiersModal = ref(false); @@ -40,17 +195,30 @@ const layer = createLayer(id, function (this: BaseLayer) { if (Decimal.lt(main.day.value, day)) { return; } + + Object.values(reindeer).forEach(reindeer => reindeer.update(diff)); }); - const { total: totalFood, trackerDisplay } = setUpDailyProgressTracker({ - resource: food, - goal: 1e3, - name, - day, - background: color, - modal: { - show: showModifiersModal, - display: modifiersModal + const dayProgress = createBar(() => ({ + direction: Direction.Right, + width: 600, + height: 25, + fillStyle: `backgroundColor: ${color}`, + progress: () => (main.day.value === day ? Decimal.div(sumTimesFed.value, feedGoal) : 1), + display: jsx(() => + main.day.value === day ? ( + <> + {formatWhole(sumTimesFed.value)}/{formatWhole(feedGoal)} + + ) : ( + "" + ) + ) + })) as GenericBar; + + watchEffect(() => { + if (main.day.value === day && Decimal.gte(sumTimesFed.value, feedGoal)) { + main.completeDay(); } }); @@ -58,23 +226,39 @@ const layer = createLayer(id, function (this: BaseLayer) { name, day, color, - food, - totalFood, + reindeer, generalTabCollapsed, minWidth: 700, display: jsx(() => ( <> - {render(trackerDisplay)} +
+ {main.day.value === day + ? `Feed reindeer ${formatWhole(feedGoal)} times to complete the day` + : `${name} Complete!`}{" "} + -{" "} + +
+ {render(dayProgress)} + {render(modifiersModal)} - +
You have fed reindeer {formatWhole(sumTimesFed.value)} times
+ + {renderGrid( + [dasher, dancer, prancer], + [vixen, comet, cupid], + [donner, blitzen, rudolph] + )} )), minimizedDisplay: jsx(() => (
- {name}{" "} - - {format(food.value)} {food.displayName} - + {name} {format(sumTimesFed.value)} times fed
)) }; diff --git a/src/features/hotkey.tsx b/src/features/hotkey.tsx index 65e9ae3..b7bfaf2 100644 --- a/src/features/hotkey.tsx +++ b/src/features/hotkey.tsx @@ -89,6 +89,9 @@ document.onkeydown = function (e) { if (e.ctrlKey) { key = "ctrl+" + key; } + if (e.code.startsWith("Numpad") && `Numpad ${key}` in hotkeys) { + key = "Numpad " + key; + } const hotkey = hotkeys[key]; if (hotkey && unref(hotkey.enabled)) { e.preventDefault(); From 3d64b039058cdf216b25e46f4a80e5da44f250b8 Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Thu, 22 Dec 2022 21:53:51 -0600 Subject: [PATCH 06/48] Add each reindeer's modifier --- src/data/layers/boxes.tsx | 2 ++ src/data/layers/cloth.tsx | 10 +++++++--- src/data/layers/coal.tsx | 2 ++ src/data/layers/dyes.tsx | 2 ++ src/data/layers/metal.tsx | 2 ++ src/data/layers/oil.tsx | 4 +++- src/data/layers/paper.tsx | 4 +++- src/data/layers/plastic.tsx | 4 +++- src/data/layers/reindeer.tsx | 20 +++++++++++++++----- src/data/layers/trees.tsx | 2 ++ 10 files changed, 41 insertions(+), 11 deletions(-) diff --git a/src/data/layers/boxes.tsx b/src/data/layers/boxes.tsx index 98b8b8b..2d534fb 100644 --- a/src/data/layers/boxes.tsx +++ b/src/data/layers/boxes.tsx @@ -31,6 +31,7 @@ import elves, { ElfBuyable } from "./elves"; import management from "./management"; import paper from "./paper"; import plastic from "./plastic"; +import reindeer from "./reindeer"; import trees from "./trees"; import workshop from "./workshop"; import wrappingPaper from "./wrapping-paper"; @@ -55,6 +56,7 @@ const layer = createLayer(id, function (this: BaseLayer) { description: "1000% Foundation Completed", enabled: workshop.milestones.extraExpansionMilestone5.earned })), + reindeer.reindeer.vixen.modifier, createExponentialModifier(() => ({ exponent: 1.1, description: "Bell Level 2", diff --git a/src/data/layers/cloth.tsx b/src/data/layers/cloth.tsx index 8f4f227..1c3d0a7 100644 --- a/src/data/layers/cloth.tsx +++ b/src/data/layers/cloth.tsx @@ -36,6 +36,7 @@ import management from "./management"; import metal from "./metal"; import paper from "./paper"; import plastic from "./plastic"; +import reindeer from "./reindeer"; import trees from "./trees"; import workshop from "./workshop"; @@ -449,7 +450,8 @@ const layer = createLayer(id, function (this: BaseLayer) { multiplier: dyes.boosts.yellow2, description: "Yellow Dye", enabled: dyes.masteryEffectActive - })) + })), + reindeer.reindeer.cupid.modifier ]); const computedSheepGain = computed(() => sheepGain.apply(1)); const breedingCooldown = createSequentialModifier(() => []); @@ -494,7 +496,8 @@ const layer = createLayer(id, function (this: BaseLayer) { multiplier: dyes.boosts.yellow2, description: "Yellow Dye", enabled: dyes.masteryEffectActive - })) + })), + reindeer.reindeer.cupid.modifier ]); const computedShearingAmount = computed(() => shearingAmount.apply(1)); const shearingCooldown = createSequentialModifier(() => []); @@ -539,7 +542,8 @@ const layer = createLayer(id, function (this: BaseLayer) { multiplier: dyes.boosts.yellow2, description: "Yellow Dye", enabled: dyes.masteryEffectActive - })) + })), + reindeer.reindeer.cupid.modifier ]); const computedSpinningAmount = computed(() => spinningAmount.apply(1)); const spinningCooldown = createSequentialModifier(() => []); diff --git a/src/data/layers/coal.tsx b/src/data/layers/coal.tsx index 8aa20f3..17e6659 100644 --- a/src/data/layers/coal.tsx +++ b/src/data/layers/coal.tsx @@ -40,6 +40,7 @@ import metal from "./metal"; import oil from "./oil"; import paper from "./paper"; import plastic from "./plastic"; +import reindeer from "./reindeer"; import trees from "./trees"; import wrappingPaper from "./wrapping-paper"; @@ -785,6 +786,7 @@ const layer = createLayer(id, function (this: BaseLayer) { description: "Refined Coal", enabled: refinedCoal.bought })), + reindeer.reindeer.dancer.modifier, createExponentialModifier(() => ({ exponent: 1.05, description: "Jack Level 2", diff --git a/src/data/layers/dyes.tsx b/src/data/layers/dyes.tsx index 6d94dff..da71c0b 100644 --- a/src/data/layers/dyes.tsx +++ b/src/data/layers/dyes.tsx @@ -36,6 +36,7 @@ import oil from "./oil"; import paper from "./paper"; import trees from "./trees"; import toys from "./toys"; +import reindeer from "./reindeer"; interface Dye { name: string; @@ -200,6 +201,7 @@ const layer = createLayer(id, function (this: BaseLayer) { enabled: boxes.row3Upgrades.dyeUpgrade.bought })) ); + modifiers.push(reindeer.reindeer.rudolph.modifier); return modifiers; }) as WithRequired; const computedToGenerate = computed(() => toGenerate.apply(0)); diff --git a/src/data/layers/metal.tsx b/src/data/layers/metal.tsx index 7251725..c6d338f 100644 --- a/src/data/layers/metal.tsx +++ b/src/data/layers/metal.tsx @@ -37,6 +37,7 @@ import plastic from "./plastic"; import workshop from "./workshop"; import wrappingPaper from "./wrapping-paper"; import toys from "./toys"; +import reindeer from "./reindeer"; const id = "metal"; const day = 7; @@ -105,6 +106,7 @@ const layer = createLayer(id, function (this: BaseLayer) { description: "Twinkle Level 1", enabled: management.elfTraining.metalElfTraining.milestones[0].earned })), + reindeer.reindeer.comet.modifier, createExponentialModifier(() => ({ exponent: 1.1, description: "Mary Level 2", diff --git a/src/data/layers/oil.tsx b/src/data/layers/oil.tsx index a047ba9..5611dca 100644 --- a/src/data/layers/oil.tsx +++ b/src/data/layers/oil.tsx @@ -41,6 +41,7 @@ import workshop from "./workshop"; import { WithRequired } from "util/common"; import { ElfBuyable } from "./elves"; import toys from "./toys"; +import reindeer from "./reindeer"; const id = "oil"; const day = 9; @@ -957,7 +958,8 @@ const layer = createLayer(id, function (this: BaseLayer) { multiplier: 50, description: "350 toys", enabled: toys.milestones.milestone4.earned - })) + })), + reindeer.reindeer.donner.modifier ]) as WithRequired; const computedOilSpeed = computed(() => oilSpeed.apply(0)); diff --git a/src/data/layers/paper.tsx b/src/data/layers/paper.tsx index 1b817a2..d96b654 100644 --- a/src/data/layers/paper.tsx +++ b/src/data/layers/paper.tsx @@ -27,6 +27,7 @@ import dyes from "./dyes"; import elves, { ElfBuyable } from "./elves"; import management from "./management"; import plastic from "./plastic"; +import reindeer from "./reindeer"; import ribbon from "./ribbon"; import trees from "./trees"; import workshop from "./workshop"; @@ -423,7 +424,8 @@ const layer = createLayer(id, function (this: BaseLayer) { multiplier: wrappingPaper.boosts.sunshine1, description: "Sunshine Wrapping Paper", enabled: () => Decimal.gte(wrappingPaper.boosts.sunshine1.value, 2) - })) + })), + reindeer.reindeer.prancer.modifier ]) as WithRequired; const ashCost = createSequentialModifier(() => [ createMultiplicativeModifier(() => ({ diff --git a/src/data/layers/plastic.tsx b/src/data/layers/plastic.tsx index b79c0b7..be9a09e 100644 --- a/src/data/layers/plastic.tsx +++ b/src/data/layers/plastic.tsx @@ -37,6 +37,7 @@ import oil from "./oil"; import paper from "./paper"; import workshop from "./workshop"; import toys from "./toys"; +import reindeer from "./reindeer"; const id = "plastic"; const day = 10; @@ -379,7 +380,8 @@ const layer = createLayer(id, function (this: BaseLayer) { multiplier: 50, description: "350 toys", enabled: toys.milestones.milestone4.earned - })) + })), + reindeer.reindeer.blitzen.modifier ]); const computedPlasticGain = computed(() => plasticGain.apply(0)); diff --git a/src/data/layers/reindeer.tsx b/src/data/layers/reindeer.tsx index 75ce093..7324b66 100644 --- a/src/data/layers/reindeer.tsx +++ b/src/data/layers/reindeer.tsx @@ -5,16 +5,15 @@ import HotkeyVue from "components/Hotkey.vue"; import Spacer from "components/layout/Spacer.vue"; import Modal from "components/Modal.vue"; -import { createCollapsibleModifierSections, setUpDailyProgressTracker } from "data/common"; +import { createCollapsibleModifierSections } from "data/common"; import { main } from "data/projEntry"; import { createBar, GenericBar } from "features/bars/bar"; import { createClickable } from "features/clickables/clickable"; import { jsx } from "features/feature"; import { createHotkey, GenericHotkey } from "features/hotkey"; -import MainDisplay from "features/resources/MainDisplay.vue"; -import { createResource, Resource } from "features/resources/resource"; import { globalBus } from "game/events"; import { BaseLayer, createLayer } from "game/layers"; +import { createMultiplicativeModifier } from "game/modifiers"; import { persistent } from "game/persistence"; import Decimal, { DecimalSource, format, formatWhole } from "util/bignum"; import { Direction } from "util/common"; @@ -61,11 +60,23 @@ const layer = createLayer(id, function (this: BaseLayer) { progress: () => Decimal.div(progress.value, computedCooldown.value) })); + const modifier = createMultiplicativeModifier(() => ({ + multiplier: effect, + description: options.name, + enabled: () => Decimal.gt(timesFed.value, 0) + })); + + const effect = computed(() => + Decimal.times(options.boostAmount, timesFed.value).add(1) + ); + return { ...options, hotkey, timesFed, progress, + effect, + modifier, display: { title: jsx(() => (

@@ -78,7 +89,7 @@ const layer = createLayer(id, function (this: BaseLayer) { Each time you feed {options.name} will increase your{" "} {options.boostDescription} by +{format(options.boostAmount)}x - Currently {format(Decimal.pow(options.boostAmount, timesFed.value))}x + Currently {format(effect.value)}x
{render(progressBar)} @@ -100,7 +111,6 @@ const layer = createLayer(id, function (this: BaseLayer) { progress.value = 0; }, update(diff: number) { - console.log(progress.value, computedCooldown.value, diff); if (Decimal.gte(progress.value, computedCooldown.value)) { progress.value = computedCooldown.value; } else { diff --git a/src/data/layers/trees.tsx b/src/data/layers/trees.tsx index 51a799a..99c10b2 100644 --- a/src/data/layers/trees.tsx +++ b/src/data/layers/trees.tsx @@ -39,6 +39,7 @@ import paper from "./paper"; import workshop from "./workshop"; import wrappingPaper from "./wrapping-paper"; import toys from "./toys"; +import reindeer from "./reindeer"; const id = "trees"; const day = 1; @@ -551,6 +552,7 @@ const layer = createLayer(id, function (this: BaseLayer) { description: "3000 Toys", enabled: toys.milestones.milestone7.earned })), + reindeer.reindeer.dasher.modifier, createExponentialModifier(() => ({ exponent: 1.2, description: "100% Foundation Completed", From b7b40a48aae64b56cca287599985de67f6e37f6e Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Thu, 22 Dec 2022 22:40:36 -0600 Subject: [PATCH 07/48] Fixed typo for hotkeys --- src/features/hotkey.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/features/hotkey.tsx b/src/features/hotkey.tsx index b7bfaf2..cab9d40 100644 --- a/src/features/hotkey.tsx +++ b/src/features/hotkey.tsx @@ -44,7 +44,7 @@ export type GenericHotkey = Replace< } >; -const uppercaseNumbers = [")", "!", "@", "#", "$", "5", "^", "&", "*", "("]; +const uppercaseNumbers = [")", "!", "@", "#", "$", "%", "^", "&", "*", "("]; export function createHotkey( optionsFunc: OptionsFunc From 0ce3b6b131d6ebefd03c7e2c78fc766d1a710a51 Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Thu, 22 Dec 2022 23:37:27 -0600 Subject: [PATCH 08/48] Implemented focus mechanic --- src/data/layers/reindeer.tsx | 124 ++++++++++++++++++++++++++-- src/data/layers/styles/reindeer.css | 10 +++ 2 files changed, 128 insertions(+), 6 deletions(-) create mode 100644 src/data/layers/styles/reindeer.css diff --git a/src/data/layers/reindeer.tsx b/src/data/layers/reindeer.tsx index 7324b66..1e0a2ea 100644 --- a/src/data/layers/reindeer.tsx +++ b/src/data/layers/reindeer.tsx @@ -13,12 +13,13 @@ import { jsx } from "features/feature"; import { createHotkey, GenericHotkey } from "features/hotkey"; import { globalBus } from "game/events"; import { BaseLayer, createLayer } from "game/layers"; -import { createMultiplicativeModifier } from "game/modifiers"; +import { createMultiplicativeModifier, createSequentialModifier } from "game/modifiers"; import { persistent } from "game/persistence"; -import Decimal, { DecimalSource, format, formatWhole } from "util/bignum"; +import Decimal, { DecimalSource, format, formatTime, formatWhole } from "util/bignum"; import { Direction } from "util/common"; import { render, renderGrid } from "util/vue"; import { computed, ref, unref, watchEffect } from "vue"; +import "./styles/reindeer.css"; const id = "reindeer"; const day = 21; @@ -28,7 +29,82 @@ const layer = createLayer(id, function (this: BaseLayer) { const feedGoal = 1e3; - // TODO focus + const currMultiplier = persistent(1); + const currTargets = persistent>({}); + const currCooldown = persistent(0); + + const maxMultiplier = createSequentialModifier(() => []); + const computedMaxMultiplier = computed(() => maxMultiplier.apply(2)); + const targetsCount = createSequentialModifier(() => []); + const computedTargetsCount = computed(() => targetsCount.apply(1)); + const computedMaxCooldown = computed(() => 10); + + const focusMeter = createBar(() => ({ + direction: Direction.Right, + width: 476, + height: 50, + style: `border-radius: 0`, + borderStyle: `border-radius: 0`, + fillStyle: () => ({ + background: currCooldown.value > 0 ? color : "#7f7f00", + animation: currCooldown.value > 0 ? "1s focused-eating-bar linear infinite" : "", + opacity: currCooldown.value > 0 ? currCooldown.value / 10 : 1, + transition: "none" + }), + progress: () => + Decimal.sub(currMultiplier.value, 1) + .div(Decimal.sub(computedMaxMultiplier.value, 1)) + .toNumber(), + display: jsx(() => ( + <> + {format(currMultiplier.value)}x + {currCooldown.value > 0 ? ( + <> + {" "} + to {Object.keys(currTargets.value).join(", ")} for{" "} + {formatTime(currCooldown.value)} + + ) : ( + "" + )} + + )) + })) as GenericBar; + + const focusButton = createClickable(() => ({ + display: { + title: "Focus", + description: jsx(() => ( + <> + Motivate reindeer to eat, multiplying {formatWhole(computedTargetsCount.value)}{" "} + random reindeer's eating rate by up to {format(computedMaxMultiplier.value)}x + for {formatTime(computedMaxCooldown.value)}, equal to the focus bar's effect. + + )) + }, + style: { + width: "480px", + minHeight: "80px", + zIndex: 4 + }, + canClick: () => Decimal.eq(currCooldown.value, 0), + onClick() { + currCooldown.value = Decimal.fromValue(computedMaxCooldown.value).toNumber(); + let targetsSelected = 0; + currTargets.value = {}; + while (Decimal.gt(computedTargetsCount.value, targetsSelected)) { + const selectedReindeer = + Object.values(reindeer)[ + Math.floor(Math.random() * Object.values(reindeer).length) + ]; + const roll = selectedReindeer?.name ?? ""; + if (!currTargets.value[roll]) { + currTargets.value[roll] = true; + targetsSelected++; + } + } + } + })); function createReindeer(options: { name: string; @@ -56,7 +132,15 @@ const layer = createLayer(id, function (this: BaseLayer) { style: "margin-top: 8px", borderStyle: "border-color: black", baseStyle: "margin-top: -1px", - fillStyle: "margin-top: -1px; transition-duration: 0s; background: black", + fillStyle: () => ({ + marginTop: "-1px", + transitionDuration: "0s", + background: "black", + animation: + currTargets.value[options.name] && currCooldown.value > 0 + ? ".5s focused-eating-bar linear infinite" + : "" + }), progress: () => Decimal.div(progress.value, computedCooldown.value) })); @@ -114,7 +198,11 @@ const layer = createLayer(id, function (this: BaseLayer) { if (Decimal.gte(progress.value, computedCooldown.value)) { progress.value = computedCooldown.value; } else { - progress.value = Decimal.add(progress.value, diff); + let amount: DecimalSource = diff; + if (currTargets.value[options.name] && currCooldown.value > 0) { + amount = Decimal.times(amount, currMultiplier.value); + } + progress.value = Decimal.add(progress.value, amount); if (clickable.isHolding.value) { clickable.onClick(); } @@ -188,7 +276,18 @@ const layer = createLayer(id, function (this: BaseLayer) { // TODO upgrades - const [generalTab, generalTabCollapsed] = createCollapsibleModifierSections(() => []); + const [generalTab, generalTabCollapsed] = createCollapsibleModifierSections(() => [ + { + title: "Max Focus Multiplier", + modifier: maxMultiplier, + base: 2 + }, + { + title: "Focus Targets", + modifier: targetsCount, + base: 1 + } + ]); const showModifiersModal = ref(false); const modifiersModal = jsx(() => ( reindeer.update(diff)); + + currCooldown.value = Math.max(currCooldown.value - diff, 0); + + if (Decimal.eq(currCooldown.value, 0)) { + const speed = 1000; + const stoppedAt = 1 - Math.abs(Math.sin((Date.now() / speed) * 2)); + currMultiplier.value = Decimal.pow(computedMaxMultiplier.value, stoppedAt); + } }); const dayProgress = createBar(() => ({ @@ -238,6 +345,9 @@ const layer = createLayer(id, function (this: BaseLayer) { color, reindeer, generalTabCollapsed, + currMultiplier, + currTargets, + currCooldown, minWidth: 700, display: jsx(() => ( <> @@ -260,6 +370,8 @@ const layer = createLayer(id, function (this: BaseLayer) {
You have fed reindeer {formatWhole(sumTimesFed.value)} times
{renderGrid( + [focusButton], + [focusMeter], [dasher, dancer, prancer], [vixen, comet, cupid], [donner, blitzen, rudolph] diff --git a/src/data/layers/styles/reindeer.css b/src/data/layers/styles/reindeer.css new file mode 100644 index 0000000..b3c307f --- /dev/null +++ b/src/data/layers/styles/reindeer.css @@ -0,0 +1,10 @@ +@keyframes focused-eating-bar { + from { + background: 0 0 / 28px 28px repeat + repeating-linear-gradient(-45deg, brown 0 10px, saddlebrown 10px 20px); + } + to { + background: 28px 0px / 28px 28px repeat + repeating-linear-gradient(-45deg, brown 0 10px, saddlebrown 10px 20px); + } +} From cce45916f24ce0bef8aeeea04d8002bbc392e411 Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Thu, 22 Dec 2022 23:51:38 -0600 Subject: [PATCH 09/48] Fixed reindeer hotkey order --- src/data/layers/reindeer.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/data/layers/reindeer.tsx b/src/data/layers/reindeer.tsx index 1e0a2ea..738593e 100644 --- a/src/data/layers/reindeer.tsx +++ b/src/data/layers/reindeer.tsx @@ -266,7 +266,8 @@ const layer = createLayer(id, function (this: BaseLayer) { boostDescription: "dye gain", boostAmount: 0.01 }); - const reindeer = { dasher, dancer, prancer, vixen, comet, cupid, donner, blitzen, rudolph }; + // order is designed so hotkeys appear 1-9, even though they're displayed in numpad order in the layer itself + const reindeer = { donner, blitzen, rudolph, vixen, comet, cupid, dasher, dancer, prancer }; const sumTimesFed = computed(() => Object.values(reindeer) From 8615d3dbd12123276b9909826d9563ca7e4c7908 Mon Sep 17 00:00:00 2001 From: unsoftcapped3 <75136164+unsoftcapped3@users.noreply.github.com> Date: Fri, 23 Dec 2022 06:16:33 +0000 Subject: [PATCH 10/48] add sleigh file --- src/data/layers/sleigh.tsx | 276 +++++++++++++++++++++++++++++++++++++ 1 file changed, 276 insertions(+) create mode 100644 src/data/layers/sleigh.tsx diff --git a/src/data/layers/sleigh.tsx b/src/data/layers/sleigh.tsx new file mode 100644 index 0000000..21d84a4 --- /dev/null +++ b/src/data/layers/sleigh.tsx @@ -0,0 +1,276 @@ +/** + * @module + * @hidden + */ +import HotkeyVue from "components/Hotkey.vue"; +import Spacer from "components/layout/Spacer.vue"; +import Modal from "components/Modal.vue"; +import { createCollapsibleMilestones, createCollapsibleModifierSections } from "data/common"; +import { main } from "data/projEntry"; +import { createBar } from "features/bars/bar"; +import { createClickable } from "features/clickables/clickable"; +import { + addHardcap, + addSoftcap, + createIndependentConversion, + createPolynomialScaling +} from "features/conversion"; +import { jsx, showIf } from "features/feature"; +import { createHotkey } from "features/hotkey"; +import { createMilestone } from "features/milestones/milestone"; +import { createResource, displayResource } from "features/resources/resource"; +import { BaseLayer, createLayer } from "game/layers"; +import { + createAdditiveModifier, + createExponentialModifier, + createMultiplicativeModifier, + createSequentialModifier, + Modifier +} from "game/modifiers"; +import { noPersist, persistent } from "game/persistence"; +import Decimal, { DecimalSource, formatWhole } from "util/bignum"; +import { Direction, WithRequired } from "util/common"; +import { render } from "util/vue"; +import { computed, ref, unref, watchEffect } from "vue"; +import elves from "./elves"; +import factory from "./factory"; +import management from "./management"; +import toys from "./toys"; +import trees from "./trees"; +import wrappingPaper from "./wrapping-paper"; + +const id = "sleigh"; +const day = 22; +const layer = createLayer(id, function (this: BaseLayer) { + const name = "Sleigh"; + const color = "#D66B02"; + const colorDark = "#D66B02"; + + const foundationProgress = createResource(0, "foundation progress"); + + const maxFoundation = createSequentialModifier(() => [ + createAdditiveModifier(() => ({ + addend: 900, + description: "Hope Level 3", + enabled: management.elfTraining.expandersElfTraining.milestones[2].earned + })), + createAdditiveModifier(() => ({ + addend: 200, + description: "Build wooden towers", + enabled: toys.row1Upgrades[2].bought + })), + createAdditiveModifier(() => ({ + addend: () => Decimal.times(factory.factoryBuyables.expandFactory.amount.value, 100), + description: "Expand Factory", + enabled: () => Decimal.gt(factory.factoryBuyables.expandFactory.amount.value, 0) + })) + ]) as WithRequired; + const computedMaxFoundation = computed(() => maxFoundation.apply(100)); + + const foundationConversion = createIndependentConversion(() => ({ + // note: 5423 is a magic number. Don't touch this or it'll self-destruct. + scaling: addHardcap( + addSoftcap(addSoftcap(createPolynomialScaling(250, 1.5), 5423, 1 / 1e10), 1e20, 3e8), + computedMaxFoundation + ), + baseResource: trees.logs, + gainResource: noPersist(foundationProgress), + roundUpCost: true, + // buyMax: management.elfTraining.expandersElfTraining.milestones[2].earned, + spend(gain, spent) { + trees.logs.value = Decimal.sub(trees.logs.value, spent); + }, + costModifier: createSequentialModifier(() => [ + createMultiplicativeModifier(() => ({ + multiplier: wrappingPaper.boosts.beach1, + description: "Beach Wrapping Paper", + enabled: computed(() => Decimal.gt(wrappingPaper.boosts.beach1.value, 1)) + })), + createExponentialModifier(() => ({ + exponent: 1 / 0.99, + description: "Holly Level 5", + enabled: management.elfTraining.cutterElfTraining.milestones[4].earned + })), + createExponentialModifier(() => ({ + exponent: 0.1, + description: "Scaling Jump at 1000%", + enabled: computed(() => Decimal.gte(foundationProgress.value, 1000)) + })), + createMultiplicativeModifier(() => ({ + multiplier: 6969, // note: 6969 is a magic number. Don't touch this or it'll self-destruct. + description: "Scaling Jump at 1000%", + enabled: computed(() => Decimal.gte(foundationProgress.value, 1000)) + })) + ]) + })); + + const buildFoundation = createClickable(() => ({ + display: jsx(() => ( + <> + + Build {formatWhole(foundationConversion.actualGain.value)}% of the foundation{" "} + + +
+
+ + {"Cost"}:{" "} + {displayResource(trees.logs, foundationConversion.nextAt.value)}{" "} + {trees.logs.displayName} + + + )), + visibility: () => showIf(Decimal.lt(foundationProgress.value, computedMaxFoundation.value)), + canClick: () => { + if (Decimal.lt(trees.logs.value, foundationConversion.nextAt.value)) { + return false; + } + if (Decimal.gte(foundationProgress.value, computedMaxFoundation.value)) { + return false; + } + return true; + }, + onClick() { + if (!unref(this.canClick)) { + return; + } + foundationConversion.convert(); + }, + style: "width: 600px; min-height: unset" + })); + + const buildFoundationHK = createHotkey(() => ({ + key: "x", + description: "Fix sleigh", + onPress: () => { + if (buildFoundation.canClick.value) buildFoundation.onClick(); + }, + enabled: noPersist(main.days[day - 1].opened) + })); + + const shouldShowPopups = computed(() => !elves.milestones[6].earned.value); + const milestone1 = createMilestone(() => ({ + display: { + requirement: "1% Foundation Completed", + effectDisplay: "Trees give 5% more logs for each % of foundation completed" + }, + shouldEarn: () => Decimal.gte(foundationProgress.value, 1), + showPopups: shouldShowPopups + })); + const milestones = { + milestone1 + }; + const { collapseMilestones, display: milestonesDisplay } = + createCollapsibleMilestones(milestones); + + const dayProgress = createBar(() => ({ + direction: Direction.Right, + width: 600, + height: 25, + fillStyle: `backgroundColor: ${colorDark}`, + progress: () => + main.day.value === day || main.currentlyMastering.value?.name === name + ? Decimal.div(foundationProgress.value, 100) + : 1, + display: jsx(() => + main.day.value === day || main.currentlyMastering.value?.name === name ? ( + <>{formatWhole(foundationProgress.value)}% + ) : ( + "" + ) + ) + })); + + const [generalTab, generalTabCollapsed] = createCollapsibleModifierSections(() => [ + { + title: "Max Foundation", + modifier: maxFoundation, + base: 100 + } + ]); + const showModifiersModal = ref(false); + const modifiersModal = jsx(() => ( + (showModifiersModal.value = value)} + v-slots={{ + header: () =>

{name} Modifiers

, + body: generalTab + }} + /> + )); + + watchEffect(() => { + if (main.day.value === day && Decimal.gte(foundationProgress.value, 100)) { + main.completeDay(); + } else if ( + main.currentlyMastering.value?.name === name && + Decimal.gte(foundationProgress.value, 100) + ) { + main.completeMastery(); + } + }); + + return { + name, + day, + color, + foundationProgress, + foundationConversion, + milestones, + collapseMilestones, + minWidth: 700, + buildFoundationHK, + generalTabCollapsed, + display: jsx(() => ( + <> +
+ {main.day.value === day + ? `Complete the sleigh to complete the day` + : main.currentlyMastering.value?.name === name + ? `Complete the foundation to decorate the day` + : `${name} Complete!`} + {Decimal.gt(computedMaxFoundation.value, 100) ? ( + <> + {" - "} + + + ) : null} +
+ {render(dayProgress)} + {render(modifiersModal)} + +
+ The foundation is +

+ {formatWhole(foundationProgress.value)} +

+ % completed +
+ {Decimal.lt(foundationProgress.value, 100) || + management.elfTraining.expandersElfTraining.milestones[2].earned.value ? ( + + ) : null} + {render(buildFoundation)} + + {milestonesDisplay()} + + )), + minimizedDisplay: jsx(() => ( +
+ {name}{" "} + + {formatWhole(foundationProgress.value)}% {foundationProgress.displayName} + +
+ )), + }; +}); + +export default layer; From 4c8a213eb430b2a65c005dfeef47250fc56043e3 Mon Sep 17 00:00:00 2001 From: unsoftcapped3 <75136164+unsoftcapped3@users.noreply.github.com> Date: Fri, 23 Dec 2022 06:33:30 +0000 Subject: [PATCH 11/48] a bunch of sleigh things --- src/data/layers/sleigh.tsx | 187 ++++++++++++------------------------- src/data/projEntry.tsx | 4 +- 2 files changed, 64 insertions(+), 127 deletions(-) diff --git a/src/data/layers/sleigh.tsx b/src/data/layers/sleigh.tsx index 21d84a4..fb673e4 100644 --- a/src/data/layers/sleigh.tsx +++ b/src/data/layers/sleigh.tsx @@ -28,7 +28,7 @@ import { Modifier } from "game/modifiers"; import { noPersist, persistent } from "game/persistence"; -import Decimal, { DecimalSource, formatWhole } from "util/bignum"; +import Decimal, { DecimalSource, format, formatTime, formatWhole } from "util/bignum"; import { Direction, WithRequired } from "util/common"; import { render } from "util/vue"; import { computed, ref, unref, watchEffect } from "vue"; @@ -38,6 +38,12 @@ import management from "./management"; import toys from "./toys"; import trees from "./trees"; import wrappingPaper from "./wrapping-paper"; +import metal from "./metal"; +import plastic from "./plastic" +import { createBuyable, GenericBuyable } from "features/buyable"; +import { Resource } from "features/resources/resource"; +import { isArray } from "@vue/shared"; + const id = "sleigh"; const day = 22; @@ -45,108 +51,61 @@ const layer = createLayer(id, function (this: BaseLayer) { const name = "Sleigh"; const color = "#D66B02"; const colorDark = "#D66B02"; - - const foundationProgress = createResource(0, "foundation progress"); - - const maxFoundation = createSequentialModifier(() => [ - createAdditiveModifier(() => ({ - addend: 900, - description: "Hope Level 3", - enabled: management.elfTraining.expandersElfTraining.milestones[2].earned - })), - createAdditiveModifier(() => ({ - addend: 200, - description: "Build wooden towers", - enabled: toys.row1Upgrades[2].bought - })), - createAdditiveModifier(() => ({ - addend: () => Decimal.times(factory.factoryBuyables.expandFactory.amount.value, 100), - description: "Expand Factory", - enabled: () => Decimal.gt(factory.factoryBuyables.expandFactory.amount.value, 0) - })) - ]) as WithRequired; - const computedMaxFoundation = computed(() => maxFoundation.apply(100)); - - const foundationConversion = createIndependentConversion(() => ({ - // note: 5423 is a magic number. Don't touch this or it'll self-destruct. - scaling: addHardcap( - addSoftcap(addSoftcap(createPolynomialScaling(250, 1.5), 5423, 1 / 1e10), 1e20, 3e8), - computedMaxFoundation - ), - baseResource: trees.logs, - gainResource: noPersist(foundationProgress), - roundUpCost: true, - // buyMax: management.elfTraining.expandersElfTraining.milestones[2].earned, - spend(gain, spent) { - trees.logs.value = Decimal.sub(trees.logs.value, spent); - }, - costModifier: createSequentialModifier(() => [ - createMultiplicativeModifier(() => ({ - multiplier: wrappingPaper.boosts.beach1, - description: "Beach Wrapping Paper", - enabled: computed(() => Decimal.gt(wrappingPaper.boosts.beach1.value, 1)) - })), - createExponentialModifier(() => ({ - exponent: 1 / 0.99, - description: "Holly Level 5", - enabled: management.elfTraining.cutterElfTraining.milestones[4].earned - })), - createExponentialModifier(() => ({ - exponent: 0.1, - description: "Scaling Jump at 1000%", - enabled: computed(() => Decimal.gte(foundationProgress.value, 1000)) - })), - createMultiplicativeModifier(() => ({ - multiplier: 6969, // note: 6969 is a magic number. Don't touch this or it'll self-destruct. - description: "Scaling Jump at 1000%", - enabled: computed(() => Decimal.gte(foundationProgress.value, 1000)) - })) - ]) - })); - - const buildFoundation = createClickable(() => ({ + const maxProgress = 100 + 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} + + ); + } + const sleighProgress = computed(() => sleigh.amount) + const sleigh = createBuyable(() => ({ display: jsx(() => ( <> - - Build {formatWhole(foundationConversion.actualGain.value)}% of the foundation{" "} - - -
-
- - {"Cost"}:{" "} - {displayResource(trees.logs, foundationConversion.nextAt.value)}{" "} - {trees.logs.displayName} - +

Fix the sleigh

+
+ Increase sleigh fixed by 1% +
+
+ Costs {displayCost(trees.logs, Decimal.pow(10, 100), "logs")}, +
)), - visibility: () => showIf(Decimal.lt(foundationProgress.value, computedMaxFoundation.value)), - canClick: () => { - if (Decimal.lt(trees.logs.value, foundationConversion.nextAt.value)) { - return false; - } - if (Decimal.gte(foundationProgress.value, computedMaxFoundation.value)) { - return false; - } - return true; + canPurchase(): boolean { + return ( + /*classroomCost.value.wood.lte(trees.logs.value) && + classroomCost.value.paper.lte(paper.paper.value) && + classroomCost.value.boxes.lte(boxes.boxes.value) && + classroomCost.value.metalIngots.lte(metal.metal.value)*/ + true + ); }, - onClick() { - if (!unref(this.canClick)) { - return; - } - foundationConversion.convert(); + onPurchase() { + /*trees.logs.value = Decimal.sub(trees.logs.value, classroomCost.value.wood); + paper.paper.value = Decimal.sub(paper.paper.value, classroomCost.value.paper); + boxes.boxes.value = Decimal.sub(boxes.boxes.value, classroomCost.value.boxes); + metal.metal.value = Decimal.sub(metal.metal.value, classroomCost.value.metalIngots); + this.amount.value = Decimal.add(this.amount.value, 1);*/ }, - style: "width: 600px; min-height: unset" - })); + visibility: () => showIf(Decimal.lt(sleighProgress.value.value, 100)), + style: "width: 600px" + })) as GenericBuyable; - const buildFoundationHK = createHotkey(() => ({ + + /*const buildFoundationHK = createHotkey(() => ({ key: "x", description: "Fix sleigh", onPress: () => { if (buildFoundation.canClick.value) buildFoundation.onClick(); }, enabled: noPersist(main.days[day - 1].opened) - })); + }));*/ const shouldShowPopups = computed(() => !elves.milestones[6].earned.value); const milestone1 = createMilestone(() => ({ @@ -154,7 +113,7 @@ const layer = createLayer(id, function (this: BaseLayer) { requirement: "1% Foundation Completed", effectDisplay: "Trees give 5% more logs for each % of foundation completed" }, - shouldEarn: () => Decimal.gte(foundationProgress.value, 1), + shouldEarn: () => Decimal.gte(sleighProgress.value.value, 1), showPopups: shouldShowPopups })); const milestones = { @@ -170,18 +129,18 @@ const layer = createLayer(id, function (this: BaseLayer) { fillStyle: `backgroundColor: ${colorDark}`, progress: () => main.day.value === day || main.currentlyMastering.value?.name === name - ? Decimal.div(foundationProgress.value, 100) + ? Decimal.div(sleighProgress.value.value, 100) : 1, display: jsx(() => main.day.value === day || main.currentlyMastering.value?.name === name ? ( - <>{formatWhole(foundationProgress.value)}% + <>{formatWhole(sleighProgress.value.value)}% ) : ( "" ) ) })); - const [generalTab, generalTabCollapsed] = createCollapsibleModifierSections(() => [ + /*const [generalTab, generalTabCollapsed] = createCollapsibleModifierSections(() => [ { title: "Max Foundation", modifier: maxFoundation, @@ -198,66 +157,44 @@ const layer = createLayer(id, function (this: BaseLayer) { body: generalTab }} /> - )); + ));*/ watchEffect(() => { - if (main.day.value === day && Decimal.gte(foundationProgress.value, 100)) { + if (main.day.value === day && Decimal.gte(sleighProgress.value.value, 100)) { main.completeDay(); - } else if ( - main.currentlyMastering.value?.name === name && - Decimal.gte(foundationProgress.value, 100) - ) { - main.completeMastery(); - } + } }); return { name, day, color, - foundationProgress, - foundationConversion, + sleighProgress, milestones, collapseMilestones, minWidth: 700, - buildFoundationHK, - generalTabCollapsed, + sleigh, display: jsx(() => ( <>
{main.day.value === day ? `Complete the sleigh to complete the day` - : main.currentlyMastering.value?.name === name - ? `Complete the foundation to decorate the day` : `${name} Complete!`} - {Decimal.gt(computedMaxFoundation.value, 100) ? ( - <> - {" - "} - - - ) : null}
{render(dayProgress)} - {render(modifiersModal)}
The foundation is

- {formatWhole(foundationProgress.value)} + {formatWhole(sleighProgress.value.value)}

% completed
- {Decimal.lt(foundationProgress.value, 100) || + {Decimal.lt(sleighProgress.value.value, 100) || management.elfTraining.expandersElfTraining.milestones[2].earned.value ? ( ) : null} - {render(buildFoundation)} + {render(sleigh)} {milestonesDisplay()} @@ -266,7 +203,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
{name}{" "} - {formatWhole(foundationProgress.value)}% {foundationProgress.displayName} + {formatWhole(sleighProgress.value.value)}% sleigh
)), diff --git a/src/data/projEntry.tsx b/src/data/projEntry.tsx index 349bac1..f66a830 100644 --- a/src/data/projEntry.tsx +++ b/src/data/projEntry.tsx @@ -482,9 +482,9 @@ export const main = createLayer("main", function (this: BaseLayer) { createDay(() => ({ day: 22, shouldNotify: false, - layer: null, // "sleigh" + layer: "sleigh", // "sleigh" symbol: "", - story: "", + story: "default body", completedStory: "", masteredStory: "" })), From 93979988ad446a06a8d36a60884081fbd903c1f3 Mon Sep 17 00:00:00 2001 From: unsoftcapped3 <75136164+unsoftcapped3@users.noreply.github.com> Date: Fri, 23 Dec 2022 06:42:51 +0000 Subject: [PATCH 12/48] import sleigh into projentry --- src/data/projEntry.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/data/projEntry.tsx b/src/data/projEntry.tsx index f66a830..c1fff89 100644 --- a/src/data/projEntry.tsx +++ b/src/data/projEntry.tsx @@ -35,6 +35,7 @@ import ribbon from "./layers/ribbon"; import toys from "./layers/toys"; import trees from "./layers/trees"; import workshop from "./layers/workshop"; +import sleigh from "./layers/sleigh"; import wrappingPaper from "./layers/wrapping-paper"; import boxesSymbol from "./symbols/cardboardBox.png"; import clothSymbol from "./symbols/cloth.png"; @@ -615,7 +616,8 @@ export const getInitialLayers = ( wrappingPaper, ribbon, toys, - factory + factory, + sleigh ]; /** From 69c3d5b427ad48224e381ddd5eac6c97ac5b23da Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Fri, 23 Dec 2022 00:43:39 -0600 Subject: [PATCH 13/48] Implemented upgrades --- src/data/layers/cloth.tsx | 11 +- src/data/layers/reindeer.tsx | 251 +++++++++++++++++++++++++++++++---- 2 files changed, 231 insertions(+), 31 deletions(-) diff --git a/src/data/layers/cloth.tsx b/src/data/layers/cloth.tsx index 1c3d0a7..7ef24dc 100644 --- a/src/data/layers/cloth.tsx +++ b/src/data/layers/cloth.tsx @@ -21,12 +21,13 @@ import { BaseLayer, createLayer } from "game/layers"; import { createAdditiveModifier, createMultiplicativeModifier, - createSequentialModifier + createSequentialModifier, + Modifier } from "game/modifiers"; import { noPersist, persistent } from "game/persistence"; import Decimal, { DecimalSource, format } from "util/bignum"; import { formatWhole } from "util/break_eternity"; -import { Direction } from "util/common"; +import { Direction, WithRequired } from "util/common"; import { render, renderCol, renderRow } from "util/vue"; import { computed, ref, unref } from "vue"; import boxes from "./boxes"; @@ -452,7 +453,7 @@ const layer = createLayer(id, function (this: BaseLayer) { enabled: dyes.masteryEffectActive })), reindeer.reindeer.cupid.modifier - ]); + ]) as WithRequired; const computedSheepGain = computed(() => sheepGain.apply(1)); const breedingCooldown = createSequentialModifier(() => []); const computedBreedingCooldown = computed(() => breedingCooldown.apply(1)); @@ -498,7 +499,7 @@ const layer = createLayer(id, function (this: BaseLayer) { enabled: dyes.masteryEffectActive })), reindeer.reindeer.cupid.modifier - ]); + ]) as WithRequired; const computedShearingAmount = computed(() => shearingAmount.apply(1)); const shearingCooldown = createSequentialModifier(() => []); const computedShearingCooldown = computed(() => shearingCooldown.apply(1)); @@ -544,7 +545,7 @@ const layer = createLayer(id, function (this: BaseLayer) { enabled: dyes.masteryEffectActive })), reindeer.reindeer.cupid.modifier - ]); + ]) as WithRequired; const computedSpinningAmount = computed(() => spinningAmount.apply(1)); const spinningCooldown = createSequentialModifier(() => []); const computedSpinningCooldown = computed(() => spinningCooldown.apply(1)); diff --git a/src/data/layers/reindeer.tsx b/src/data/layers/reindeer.tsx index 738593e..a5f2ed2 100644 --- a/src/data/layers/reindeer.tsx +++ b/src/data/layers/reindeer.tsx @@ -11,15 +11,29 @@ import { createBar, GenericBar } from "features/bars/bar"; import { createClickable } from "features/clickables/clickable"; import { jsx } from "features/feature"; import { createHotkey, GenericHotkey } from "features/hotkey"; +import { createUpgrade } from "features/upgrades/upgrade"; import { globalBus } from "game/events"; import { BaseLayer, createLayer } from "game/layers"; -import { createMultiplicativeModifier, createSequentialModifier } from "game/modifiers"; +import { + createAdditiveModifier, + createMultiplicativeModifier, + createSequentialModifier +} from "game/modifiers"; import { persistent } from "game/persistence"; import Decimal, { DecimalSource, format, formatTime, formatWhole } from "util/bignum"; import { Direction } from "util/common"; import { render, renderGrid } from "util/vue"; import { computed, ref, unref, watchEffect } from "vue"; +import boxes from "./boxes"; +import cloth from "./cloth"; +import coal from "./coal"; +import dyes from "./dyes"; +import metal from "./metal"; +import oil from "./oil"; +import paper from "./paper"; +import plastic from "./plastic"; import "./styles/reindeer.css"; +import trees from "./trees"; const id = "reindeer"; const day = 21; @@ -27,18 +41,53 @@ const layer = createLayer(id, function (this: BaseLayer) { const name = "Reindeer"; const color = "saddlebrown"; - const feedGoal = 1e3; + const feedGoal = 2.5e3; + + const timeSinceFocus = persistent(0); const currMultiplier = persistent(1); const currTargets = persistent>({}); const currCooldown = persistent(0); + const crit = persistent(0); - const maxMultiplier = createSequentialModifier(() => []); + const maxMultiplier = createSequentialModifier(() => [ + createMultiplicativeModifier(() => ({ + multiplier: 2, + description: "Carry food in boxes", + enabled: upgrade4.bought + })) + ]); const computedMaxMultiplier = computed(() => maxMultiplier.apply(2)); - const targetsCount = createSequentialModifier(() => []); + const targetsCount = createSequentialModifier(() => [ + createAdditiveModifier(() => ({ + addend: 1, + description: "Guide to Reindeer Handling", + enabled: upgrade3.bought + })), + createAdditiveModifier(() => ({ + addend: crit, + description: "Metal clapper", + enabled: upgrade5.bought + })) + ]); const computedTargetsCount = computed(() => targetsCount.apply(1)); const computedMaxCooldown = computed(() => 10); + function focus() { + let targetsSelected = 0; + currTargets.value = {}; + timeSinceFocus.value = 0; + while (Decimal.gt(computedTargetsCount.value, targetsSelected)) { + const selectedReindeer = + Object.values(reindeer)[Math.floor(Math.random() * Object.values(reindeer).length)]; + const roll = selectedReindeer?.name ?? ""; + if (!currTargets.value[roll]) { + currTargets.value[roll] = true; + targetsSelected++; + } + } + } + const focusMeter = createBar(() => ({ direction: Direction.Right, width: 476, @@ -90,22 +139,19 @@ const layer = createLayer(id, function (this: BaseLayer) { canClick: () => Decimal.eq(currCooldown.value, 0), onClick() { currCooldown.value = Decimal.fromValue(computedMaxCooldown.value).toNumber(); - let targetsSelected = 0; - currTargets.value = {}; - while (Decimal.gt(computedTargetsCount.value, targetsSelected)) { - const selectedReindeer = - Object.values(reindeer)[ - Math.floor(Math.random() * Object.values(reindeer).length) - ]; - const roll = selectedReindeer?.name ?? ""; - if (!currTargets.value[roll]) { - currTargets.value[roll] = true; - targetsSelected++; - } - } + focus(); } })); + const cooldown = createSequentialModifier(() => [ + createMultiplicativeModifier(() => ({ + multiplier: 0.5, + description: "Pile of coal", + enabled: upgrade2.bought + })) + ]); + const computedCooldown = computed(() => cooldown.apply(10)); + function createReindeer(options: { name: string; key: string; @@ -123,8 +169,6 @@ const layer = createLayer(id, function (this: BaseLayer) { })) as GenericHotkey; const clickable = createClickable(() => { - const computedCooldown = computed(() => 10); - const progressBar = createBar(() => ({ direction: Direction.Right, width: 140, @@ -151,7 +195,9 @@ const layer = createLayer(id, function (this: BaseLayer) { })); const effect = computed(() => - Decimal.times(options.boostAmount, timesFed.value).add(1) + Decimal.times(options.boostAmount, timesFed.value) + .add(1) + .pow(upgrade9.bought.value ? 1.1 : 1) ); return { @@ -190,7 +236,10 @@ const layer = createLayer(id, function (this: BaseLayer) { if (!unref(clickable.canClick)) { return; } - const amount = Decimal.div(progress.value, computedCooldown.value); + let amount = Decimal.div(progress.value, computedCooldown.value); + if (upgrade1.bought.value) { + amount = Decimal.times(amount, 2); + } timesFed.value = Decimal.add(timesFed.value, amount); progress.value = 0; }, @@ -199,11 +248,12 @@ const layer = createLayer(id, function (this: BaseLayer) { progress.value = computedCooldown.value; } else { let amount: DecimalSource = diff; - if (currTargets.value[options.name] && currCooldown.value > 0) { + const isFocused = currTargets.value[options.name] && currCooldown.value > 0; + if (isFocused) { amount = Decimal.times(amount, currMultiplier.value); } progress.value = Decimal.add(progress.value, amount); - if (clickable.isHolding.value) { + if (clickable.isHolding.value || (upgrade8.bought.value && isFocused)) { clickable.onClick(); } } @@ -275,7 +325,124 @@ const layer = createLayer(id, function (this: BaseLayer) { .reduce(Decimal.add, Decimal.dZero) ); - // TODO upgrades + const upgrade1 = createUpgrade(() => ({ + resource: trees.logs, + cost: 0, + style: { + width: "160px" + }, + display: { + title: "Sawdust?", + description: + "Adding some sawdust to the feed allows you to make more of it. Each feed action counts twice" + } + })); + const upgrade2 = createUpgrade(() => ({ + resource: coal.coal, + cost: 0, + style: { + width: "160px" + }, + display: { + title: "Pile of coal", + description: + "Building a threatening pile of coal encourages the reindeer to behave. Each reindeer eats twice as fast" + } + })); + const upgrade3 = createUpgrade(() => ({ + resource: paper.paper, + cost: 0, + style: { + width: "160px" + }, + display: { + title: "Guide to Reindeer Handling", + description: + "Written reindeer handling instructions allow you to help more focus at once. Increase focus targets by one" + } + })); + const upgrade4 = createUpgrade(() => ({ + resource: boxes.boxes, + cost: 0, + style: { + width: "160px" + }, + display: { + title: "Carry food in boxes", + description: + "Carrying reindeer food in boxes allows you to distribute it faster. Double the maximum focus multiplier" + } + })); + const upgrade5 = createUpgrade(() => ({ + resource: metal.metal, + cost: 0, + style: { + width: "160px" + }, + display: { + title: "Metal clapper", + description: + 'Striking two rods of metal can help get more reindeer\'s attention when done right. "Critical" focuses now affect up to two additional reindeer' + } + })); + const upgrade6 = createUpgrade(() => ({ + resource: cloth.cloth, + cost: 0, + style: { + width: "160px" + }, + display: { + title: "Focus bar padding", + description: + "Adding padding to the focus bar lets you slow it down when it's closer to the max value" + } + })); + const upgrade7 = createUpgrade(() => ({ + resource: oil.oil, + cost: 0, + style: { + width: "160px" + }, + display: { + title: "Oil can do that?", + description: + "Using a lot of oil somehow let's reindeers focus themselves with a random value when left un-focused for 10s" + } + })); + const upgrade8 = createUpgrade(() => ({ + resource: plastic.plastic, + cost: 0, + style: { + width: "160px" + }, + display: { + title: "Autoamted feeder", + description: "An automated feeder let's focused reindeer eat automatically" + } + })); + const upgrade9 = createUpgrade(() => ({ + resource: dyes.dyes.white.amount, + cost: 0, + style: { + width: "160px" + }, + display: { + title: "Colorful food", + description: + "Adding some non-toxic dyes to the food makes them more powerful. Raise each reindeer's effect to the ^1.1" + } + })); + const upgrades = { + upgrade1, + upgrade2, + upgrade3, + upgrade4, + upgrade5, + upgrade6, + upgrade7, + upgrade8, + upgrade9 + }; const [generalTab, generalTabCollapsed] = createCollapsibleModifierSections(() => [ { @@ -287,6 +454,11 @@ const layer = createLayer(id, function (this: BaseLayer) { title: "Focus Targets", modifier: targetsCount, base: 1 + }, + { + title: "Eating duration", + modifier: cooldown, + base: 10 } ]); const showModifiersModal = ref(false); @@ -310,10 +482,28 @@ const layer = createLayer(id, function (this: BaseLayer) { currCooldown.value = Math.max(currCooldown.value - diff, 0); + let auto = false; + if (upgrade7.bought.value) { + timeSinceFocus.value += diff; + if (timeSinceFocus.value > 10) { + auto = true; + } + } + if (Decimal.eq(currCooldown.value, 0)) { - const speed = 1000; - const stoppedAt = 1 - Math.abs(Math.sin((Date.now() / speed) * 2)); + let speed = 1000; + if (auto) { + speed = Math.random() * 1000; + } + let stoppedAt = 1 - Math.abs(Math.sin((Date.now() / speed) * 2)); + if (upgrade6.bought.value) { + stoppedAt = 1 - (1 - stoppedAt) ** 2; + } + crit.value = stoppedAt > 0.975 ? 2 : stoppedAt > 0.9 ? 1 : 0; currMultiplier.value = Decimal.pow(computedMaxMultiplier.value, stoppedAt); + if (auto) { + focus(); + } } }); @@ -346,9 +536,12 @@ const layer = createLayer(id, function (this: BaseLayer) { color, reindeer, generalTabCollapsed, + timeSinceFocus, currMultiplier, currTargets, currCooldown, + upgrades, + crit, minWidth: 700, display: jsx(() => ( <> @@ -377,6 +570,12 @@ const layer = createLayer(id, function (this: BaseLayer) { [vixen, comet, cupid], [donner, blitzen, rudolph] )} + + {renderGrid( + [upgrade1, upgrade2, upgrade3], + [upgrade4, upgrade5, upgrade6], + [upgrade7, upgrade8, upgrade9] + )} )), minimizedDisplay: jsx(() => ( From 9ba136b8b1889ce23da1d14984847c71551cf885 Mon Sep 17 00:00:00 2001 From: unsoftcapped3 <75136164+unsoftcapped3@users.noreply.github.com> Date: Fri, 23 Dec 2022 06:56:52 +0000 Subject: [PATCH 14/48] add sleigh cost thing --- src/data/layers/sleigh.tsx | 46 +++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 26 deletions(-) diff --git a/src/data/layers/sleigh.tsx b/src/data/layers/sleigh.tsx index fb673e4..780dfe9 100644 --- a/src/data/layers/sleigh.tsx +++ b/src/data/layers/sleigh.tsx @@ -65,6 +65,14 @@ const layer = createLayer(id, function (this: BaseLayer) { ); } const sleighProgress = computed(() => sleigh.amount) + const sleighCost = computed(() => { + let v = sleighProgress.value.value; + return { + wood: Decimal.mul(1e100, Decimal.pow(1.2, v)), + metal: Decimal.mul(1e60, Decimal.pow(1.1, v)), + plastic: Decimal.mul(1e20, Decimal.pow(1.05, v)) + }; + }); const sleigh = createBuyable(() => ({ display: jsx(() => ( <> @@ -73,45 +81,31 @@ const layer = createLayer(id, function (this: BaseLayer) { Increase sleigh fixed by 1%

- Costs {displayCost(trees.logs, Decimal.pow(10, 100), "logs")}, + Costs {displayCost(trees.logs, sleighCost.value.wood, "logs")}, + {displayCost(metal.metal, sleighCost.value.metal, "metal")}, + {displayCost(plastic.plastic, sleighCost.value.plastic, "plastic")}
)), canPurchase(): boolean { return ( - /*classroomCost.value.wood.lte(trees.logs.value) && - classroomCost.value.paper.lte(paper.paper.value) && - classroomCost.value.boxes.lte(boxes.boxes.value) && - classroomCost.value.metalIngots.lte(metal.metal.value)*/ - true + sleighCost.value.wood.lte(trees.logs.value) && + sleighCost.value.metal.lte(metal.metal.value) && + sleighCost.value.plastic.lte(plastic.plastic.value) ); }, onPurchase() { - /*trees.logs.value = Decimal.sub(trees.logs.value, classroomCost.value.wood); - paper.paper.value = Decimal.sub(paper.paper.value, classroomCost.value.paper); - boxes.boxes.value = Decimal.sub(boxes.boxes.value, classroomCost.value.boxes); - metal.metal.value = Decimal.sub(metal.metal.value, classroomCost.value.metalIngots); - this.amount.value = Decimal.add(this.amount.value, 1);*/ + this.amount.value = Decimal.add(this.amount.value, 1); }, visibility: () => showIf(Decimal.lt(sleighProgress.value.value, 100)), style: "width: 600px" })) as GenericBuyable; - - /*const buildFoundationHK = createHotkey(() => ({ - key: "x", - description: "Fix sleigh", - onPress: () => { - if (buildFoundation.canClick.value) buildFoundation.onClick(); - }, - enabled: noPersist(main.days[day - 1].opened) - }));*/ - - const shouldShowPopups = computed(() => !elves.milestones[6].earned.value); + const shouldShowPopups = computed(() => true); const milestone1 = createMilestone(() => ({ display: { - requirement: "1% Foundation Completed", - effectDisplay: "Trees give 5% more logs for each % of foundation completed" + requirement: "1% Sleigh Fixed", + effectDisplay: "Ore gives 5% more metal for each % of sleigh fixed" }, shouldEarn: () => Decimal.gte(sleighProgress.value.value, 1), showPopups: shouldShowPopups @@ -184,11 +178,11 @@ const layer = createLayer(id, function (this: BaseLayer) { {render(dayProgress)}
- The foundation is + The sleigh is

{formatWhole(sleighProgress.value.value)}

- % completed + % fixed
{Decimal.lt(sleighProgress.value.value, 100) || management.elfTraining.expandersElfTraining.milestones[2].earned.value ? ( From f9799c95ed982703076f51de65de94f776d3ad54 Mon Sep 17 00:00:00 2001 From: unsoftcapped3 <75136164+unsoftcapped3@users.noreply.github.com> Date: Fri, 23 Dec 2022 06:58:15 +0000 Subject: [PATCH 15/48] remove unnecessary lines --- src/data/layers/sleigh.tsx | 51 +++----------------------------------- 1 file changed, 4 insertions(+), 47 deletions(-) diff --git a/src/data/layers/sleigh.tsx b/src/data/layers/sleigh.tsx index 780dfe9..4593cfd 100644 --- a/src/data/layers/sleigh.tsx +++ b/src/data/layers/sleigh.tsx @@ -2,49 +2,25 @@ * @module * @hidden */ -import HotkeyVue from "components/Hotkey.vue"; import Spacer from "components/layout/Spacer.vue"; -import Modal from "components/Modal.vue"; -import { createCollapsibleMilestones, createCollapsibleModifierSections } from "data/common"; +import { createCollapsibleMilestones} from "data/common"; import { main } from "data/projEntry"; import { createBar } from "features/bars/bar"; -import { createClickable } from "features/clickables/clickable"; -import { - addHardcap, - addSoftcap, - createIndependentConversion, - createPolynomialScaling -} from "features/conversion"; import { jsx, showIf } from "features/feature"; -import { createHotkey } from "features/hotkey"; import { createMilestone } from "features/milestones/milestone"; -import { createResource, displayResource } from "features/resources/resource"; import { BaseLayer, createLayer } from "game/layers"; -import { - createAdditiveModifier, - createExponentialModifier, - createMultiplicativeModifier, - createSequentialModifier, - Modifier -} from "game/modifiers"; -import { noPersist, persistent } from "game/persistence"; -import Decimal, { DecimalSource, format, formatTime, formatWhole } from "util/bignum"; -import { Direction, WithRequired } from "util/common"; +import Decimal, { DecimalSource, format, formatWhole } from "util/bignum"; +import { Direction} from "util/common"; import { render } from "util/vue"; -import { computed, ref, unref, watchEffect } from "vue"; -import elves from "./elves"; -import factory from "./factory"; +import { computed, watchEffect } from "vue"; import management from "./management"; -import toys from "./toys"; import trees from "./trees"; -import wrappingPaper from "./wrapping-paper"; import metal from "./metal"; import plastic from "./plastic" import { createBuyable, GenericBuyable } from "features/buyable"; import { Resource } from "features/resources/resource"; import { isArray } from "@vue/shared"; - const id = "sleigh"; const day = 22; const layer = createLayer(id, function (this: BaseLayer) { @@ -134,25 +110,6 @@ const layer = createLayer(id, function (this: BaseLayer) { ) })); - /*const [generalTab, generalTabCollapsed] = createCollapsibleModifierSections(() => [ - { - title: "Max Foundation", - modifier: maxFoundation, - base: 100 - } - ]); - const showModifiersModal = ref(false); - const modifiersModal = jsx(() => ( - (showModifiersModal.value = value)} - v-slots={{ - header: () =>

{name} Modifiers

, - body: generalTab - }} - /> - ));*/ - watchEffect(() => { if (main.day.value === day && Decimal.gte(sleighProgress.value.value, 100)) { main.completeDay(); From e703ba61c4ab5cf5df58ec1e5ba2ccfc84a0b9ee Mon Sep 17 00:00:00 2001 From: unsoftcapped3 <75136164+unsoftcapped3@users.noreply.github.com> Date: Fri, 23 Dec 2022 06:59:57 +0000 Subject: [PATCH 16/48] color --- src/data/layers/sleigh.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/data/layers/sleigh.tsx b/src/data/layers/sleigh.tsx index 4593cfd..0f91ce7 100644 --- a/src/data/layers/sleigh.tsx +++ b/src/data/layers/sleigh.tsx @@ -25,9 +25,8 @@ const id = "sleigh"; const day = 22; const layer = createLayer(id, function (this: BaseLayer) { const name = "Sleigh"; - const color = "#D66B02"; - const colorDark = "#D66B02"; - const maxProgress = 100 + const color = "#D71830"; + const colorDark = "#A01020"; function displayCost( res: Resource | Resource[], cost: DecimalSource, From ddffb9cbda11334d173f2cd7e15bcc2e76029e54 Mon Sep 17 00:00:00 2001 From: unsoftcapped3 <75136164+unsoftcapped3@users.noreply.github.com> Date: Fri, 23 Dec 2022 07:00:31 +0000 Subject: [PATCH 17/48] wording --- src/data/layers/sleigh.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/data/layers/sleigh.tsx b/src/data/layers/sleigh.tsx index 0f91ce7..925774b 100644 --- a/src/data/layers/sleigh.tsx +++ b/src/data/layers/sleigh.tsx @@ -128,7 +128,7 @@ const layer = createLayer(id, function (this: BaseLayer) { <>
{main.day.value === day - ? `Complete the sleigh to complete the day` + ? `Fix the sleigh to complete the day` : `${name} Complete!`}
{render(dayProgress)} From d1a02cd394e669e6cff09d4cad035e017ec1edc1 Mon Sep 17 00:00:00 2001 From: ducdat0507 <62660527+ducdat0507@users.noreply.github.com> Date: Fri, 23 Dec 2022 18:52:03 +0700 Subject: [PATCH 18/48] Automatically generate factory component desciptions --- src/data/layers/factory.tsx | 67 +++++++++++++++++------------- src/data/layers/styles/factory.css | 10 +++-- src/util/bignum.ts | 5 ++- src/util/break_eternity.ts | 6 +++ 4 files changed, 54 insertions(+), 34 deletions(-) diff --git a/src/data/layers/factory.tsx b/src/data/layers/factory.tsx index b32ceb0..d0b3b07 100644 --- a/src/data/layers/factory.tsx +++ b/src/data/layers/factory.tsx @@ -28,7 +28,7 @@ import { Modifier } from "game/modifiers"; import { noPersist, Persistent, persistent, State } from "game/persistence"; -import Decimal, { DecimalSource, format, formatWhole } from "util/bignum"; +import Decimal, { DecimalSource, format, formatList, formatWhole } from "util/bignum"; import { Direction, WithRequired } from "util/common"; import { ProcessedComputable } from "util/computed"; import { render, renderGrid, renderRow, VueFeature } from "util/vue"; @@ -287,6 +287,21 @@ const factory = createLayer(id, () => { // ---------------------------------------------- Components + + function generateComponentDescription(declaration: FactoryComponentDeclaration) { + + let str = declaration.inputs === undefined ? "Produces " : "Turns "; + if (declaration.inputs !== undefined) { + str += formatList(Object.entries(declaration.inputs) + .map(x => formatWhole(unref(x[1].amount)) + " " + RESOURCES[x[0] as ResourceNames].name)) + " into "; + } + if (declaration.outputs !== undefined) { + str += formatList(Object.entries(declaration.outputs) + .map(x => formatWhole(unref(x[1].amount)) + " " + RESOURCES[x[0] as ResourceNames].name)) + " per tick."; + } + return str; + } + const FACTORY_COMPONENTS = { cursor: { imageSrc: _cursor, @@ -343,7 +358,7 @@ const factory = createLayer(id, () => { key: "1", name: "Wood Machine", type: "processor", - description: "Produces 1 wood per tick.", + description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.wood)), energyCost: 10, tick: 1, outputs: { @@ -358,7 +373,7 @@ const factory = createLayer(id, () => { key: "2", name: "Cloth Machine", type: "processor", - description: "Produces 1 cloth per tick.", + description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.cloth)), energyCost: 10, tick: 1, outputs: { @@ -373,7 +388,7 @@ const factory = createLayer(id, () => { key: "3", name: "Dye Machine", type: "processor", - description: "Produces 1 dye per tick.", + description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.dye)), energyCost: 10, tick: 1, outputs: { @@ -388,7 +403,7 @@ const factory = createLayer(id, () => { key: "4", name: "Metal Machine", type: "processor", - description: "Produces 1 metal per tick.", + description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.metal)), energyCost: 10, tick: 1, outputs: { @@ -403,7 +418,7 @@ const factory = createLayer(id, () => { key: "5", name: "Plastic Machine", type: "processor", - description: "Produces 1 plastic per tick.", + description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.plastic)), energyCost: 10, tick: 1, outputs: { @@ -417,7 +432,7 @@ const factory = createLayer(id, () => { key: "shift+1", name: "Sawmill", type: "processor", - description: "Turns 1 wood into 1 plank per tick.", + description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.plank)), energyCost: 2, tick: 1, inputs: { @@ -436,7 +451,7 @@ const factory = createLayer(id, () => { key: "shift+2", name: "Thread Spinner", type: "processor", - description: "Turns 1 cloth into 1 thread per tick.", + description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.thread)), energyCost: 2, tick: 1, inputs: { @@ -455,13 +470,7 @@ const factory = createLayer(id, () => { key: "shift+3", name: "Wheel Crafter", type: "processor", - // TODO construct descriptions dynamically better - description: computed( - () => - `Turns 1 plastic into ${ - toys.milestones.milestone5.earned.value ? "2 wheels" : "1 wheel" - } per tick.` - ), + description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.wheel)), energyCost: 2, tick: 1, inputs: { @@ -480,7 +489,7 @@ const factory = createLayer(id, () => { key: "shift+4", name: "Button Maker", type: "processor", - description: "Turns 1 plastic into 2 buttons every second.", + description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.button)), energyCost: 2, tick: 1, inputs: { @@ -500,7 +509,7 @@ const factory = createLayer(id, () => { key: "shift+5", name: "Cloth Shredder", type: "processor", - description: "Turns 1 cloth into 1 stuffing every second.", + description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.stuffing)), energyCost: 2, tick: 1, inputs: { @@ -520,7 +529,7 @@ const factory = createLayer(id, () => { key: "shift+6", name: "Shovel Maker", type: "processor", - description: "Turns 2 plastic into 1 shovel every second.", + description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.shovel)), energyCost: 2, tick: 1, inputs: { @@ -540,7 +549,7 @@ const factory = createLayer(id, () => { key: "shift+7", name: "Bucket Maker", type: "processor", - description: "Turns 3 plastic into 1 bucket every second.", + description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.bucket)), energyCost: 2, tick: 1, inputs: { @@ -560,7 +569,7 @@ const factory = createLayer(id, () => { key: "shift+8", name: "Circuit Board Manufacturer", type: "processor", - description: "Turns 1 metal and 1 plastic into 1 circuit board every second.", + description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.circuitBoard)), energyCost: 2, tick: 1, inputs: { @@ -583,7 +592,7 @@ const factory = createLayer(id, () => { key: "ctrl+1", name: "Wooden Block Maker", type: "processor", - description: "Turns 1 plank into 1 wooden block per tick.", + description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.blocks)), energyCost: 20, tick: 1, inputs: { @@ -603,7 +612,7 @@ const factory = createLayer(id, () => { key: "ctrl+2", name: "Clothes Maker", type: "processor", - description: "Turns 2 threads, 3 cloth, and 1 dye into 1 clothes per tick.", + description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.clothes)), energyCost: 20, tick: 1, inputs: { @@ -629,7 +638,7 @@ const factory = createLayer(id, () => { key: "ctrl+3", name: "Trucks Maker", type: "processor", - description: "Turns 2 metal and 4 wheels into 1 truck per tick.", + description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.trucks)), energyCost: 20, tick: 1, inputs: { @@ -652,8 +661,7 @@ const factory = createLayer(id, () => { key: "ctrl+4", name: "Teddy Bear Maker", type: "processor", - description: - "Turns 1 thread, 1 stuffing, 1 dye, and 3 buttons into 1 teddy bear every second.", + description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.bear)), energyCost: 20, tick: 1, inputs: { @@ -683,7 +691,7 @@ const factory = createLayer(id, () => { key: "ctrl+5", name: "Shovel and Pail Maker", type: "processor", - description: "Turns 1 bucket and 1 shovel into 1 shovel and pail every second.", + description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.bucketShovel)), energyCost: 20, tick: 1, inputs: { @@ -707,8 +715,7 @@ const factory = createLayer(id, () => { key: "ctrl+6", name: "Game Console Maker", type: "processor", - description: - "Turns 1 metal, 3 plastic, and 1 circuit board into 1 game console every second.", + description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.console)), energyCost: 20, tick: 1, inputs: { @@ -730,7 +737,7 @@ const factory = createLayer(id, () => { }, visible: main.days[advancedDay - 1].opened } as FactoryComponentDeclaration - } as const; + } as Record; const RESOURCES = { // Raw resources wood: { @@ -1486,6 +1493,7 @@ const factory = createLayer(id, () => { const factoryBaseData = FACTORY_COMPONENTS[data.type]; if (factoryBaseData == undefined) return; const sheet = Assets.get(factoryBaseData.imageSrc); + const sprite = new Sprite(sheet); watchEffect(() => { @@ -1507,6 +1515,7 @@ const factory = createLayer(id, () => { ) * Math.PI) / 2; + if (factoryBaseData.extraImage != null) { const sheet = Assets.get(factoryBaseData.extraImage); const extraSprite = new Sprite(sheet); diff --git a/src/data/layers/styles/factory.css b/src/data/layers/styles/factory.css index 9a02626..7cedc3a 100644 --- a/src/data/layers/styles/factory.css +++ b/src/data/layers/styles/factory.css @@ -64,7 +64,7 @@ left: 0px; right: 0px; position: absolute; - background-color: var(--raised-background); + background-color: snow; overflow: hidden; z-index: 1; } @@ -109,7 +109,7 @@ .comp-info { position: absolute; top: 0; - right: -10px; + right: 0px; padding: 5px 10px; width: max-content; @@ -125,13 +125,14 @@ pointer-events: none; transition: transform 0.3s; - z-index: -1; + z-index: -2; } .comp-list .comp:nth-child(2n - 1) .comp-info { - right: -85px; + right: -75px; } .comp-list .comp:hover .comp-info { transform: translateX(calc(20px + 100%)); + z-index: -1; } .comp-list { @@ -159,6 +160,7 @@ position: absolute; border-right: solid 2px var(--locked); background: var(--raised-background); + box-shadow: 0 2px 10px #0007; top: 0; bottom: 0; left: 0; diff --git a/src/util/bignum.ts b/src/util/bignum.ts index 64bbeb2..1529e92 100644 --- a/src/util/bignum.ts +++ b/src/util/bignum.ts @@ -14,7 +14,8 @@ export const { formatSmall, formatLimit, invertOOM, - formatGain + formatGain, + formatList } = numberUtils; export type DecimalSource = RawDecimalSource; @@ -34,6 +35,7 @@ declare global { formatLimit: (list: [DecimalSource, string][], unit: string) => string; invertOOM: (x: DecimalSource) => Decimal; formatGain: (x: DecimalSource) => string; + formatList: (x: string[]) => string; } } window.Decimal = Decimal; @@ -48,5 +50,6 @@ window.formatSmall = formatSmall; window.formatLimit = formatLimit; window.invertOOM = invertOOM; window.formatGain = formatGain; +window.formatList = formatList; export default Decimal; diff --git a/src/util/break_eternity.ts b/src/util/break_eternity.ts index a3fc5aa..a8d83e3 100644 --- a/src/util/break_eternity.ts +++ b/src/util/break_eternity.ts @@ -219,3 +219,9 @@ export function formatGain(gain: DecimalSource) { 1: `+${format(gain)}/s` }[Decimal.compare(gain, 0)]; } + +export function formatList(list: string[]) { + if (list.length <= 0) return ""; + if (list.length == 1) return list[0]; + return list.slice(0, -1).join(", ") + " and " + list[list.length - 1]; +} From ec71587eabf25128417a8184a407a47b58ab5b1a Mon Sep 17 00:00:00 2001 From: ducdat0507 <62660527+ducdat0507@users.noreply.github.com> Date: Fri, 23 Dec 2022 20:40:31 +0700 Subject: [PATCH 19/48] NaNi? --- src/data/layers/factory.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/data/layers/factory.tsx b/src/data/layers/factory.tsx index d0b3b07..0eeda6f 100644 --- a/src/data/layers/factory.tsx +++ b/src/data/layers/factory.tsx @@ -206,7 +206,7 @@ const factory = createLayer(id, () => { createMultiplicativeModifier(() => ({ multiplier: Decimal.lt(energyEfficiency.value, 1) ? 1 - : Decimal.sub(2, Decimal.div(energyConsumption.value, computedEnergy.value)), + : Decimal.sub(2, Decimal.div(energyConsumption.value, Decimal.max(computedEnergy.value, 1))), description: "Brighter work rooms", enabled: () => upgrades[2][0].bought.value })), @@ -1387,7 +1387,6 @@ const factory = createLayer(id, () => { const now = Date.now(); const diff = (now - compData.lastFactoryProd) / 1000; compData.lastProdTimes.push(diff); - console.log(compData.lastProdTimes); if (compData.lastProdTimes.length > 10) compData.lastProdTimes.shift(); compData.lastFactoryProd = now; } From c1f6741c754c20181bb0d2df750febeacf4597d1 Mon Sep 17 00:00:00 2001 From: circle-gon <97845741+circle-gon@users.noreply.github.com> Date: Fri, 23 Dec 2022 09:28:14 -0500 Subject: [PATCH 20/48] fixes computed inputs/outputs not actually checking properly --- src/data/layers/factory.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/data/layers/factory.tsx b/src/data/layers/factory.tsx index 0eeda6f..1884ca7 100644 --- a/src/data/layers/factory.tsx +++ b/src/data/layers/factory.tsx @@ -1572,7 +1572,7 @@ const factory = createLayer(id, () => { const compData = components.value[x + "x" + y] as FactoryComponentProcessor; if (factoryBaseData.inputs !== undefined) { for (const [res, val] of Object.entries(factoryBaseData.inputs)) - if ((compData.inputStock?.[res as ResourceNames] ?? 0) < val.amount) + if ((compData.inputStock?.[res as ResourceNames] ?? 0) < unref(val.amount)) return false; } if (factoryBaseData.outputs !== undefined) { From 3313609acf929f1a1f3437d5cce38661f35d7c60 Mon Sep 17 00:00:00 2001 From: ducdat0507 <62660527+ducdat0507@users.noreply.github.com> Date: Fri, 23 Dec 2022 21:32:30 +0700 Subject: [PATCH 21/48] Presents buildings --- ...rotate_rectangle.png => __placeholder.png} | Bin src/data/layers/factory.tsx | 331 +++++++++++++++++- src/data/layers/styles/factory.css | 9 +- 3 files changed, 321 insertions(+), 19 deletions(-) rename src/data/layers/factory-components/{rotate_rectangle.png => __placeholder.png} (100%) diff --git a/src/data/layers/factory-components/rotate_rectangle.png b/src/data/layers/factory-components/__placeholder.png similarity index 100% rename from src/data/layers/factory-components/rotate_rectangle.png rename to src/data/layers/factory-components/__placeholder.png diff --git a/src/data/layers/factory.tsx b/src/data/layers/factory.tsx index 0eeda6f..c3d87f5 100644 --- a/src/data/layers/factory.tsx +++ b/src/data/layers/factory.tsx @@ -33,29 +33,51 @@ import { Direction, WithRequired } from "util/common"; import { ProcessedComputable } from "util/computed"; import { render, renderGrid, renderRow, VueFeature } from "util/vue"; import { computed, ComputedRef, reactive, ref, shallowRef, unref, watchEffect } from "vue"; +import boxes from "./boxes"; +import coal from "./coal"; +import dyes from "./dyes"; +import Factory from "./Factory.vue"; +import metal from "./metal"; +import oil from "./oil"; +import paper from "./paper"; +import plastic from "./plastic"; +import "./styles/factory.css"; +import Toy from "./Toy.vue"; +import toys from "./toys"; +import trees from "./trees"; +import workshop from "./workshop"; + import _cloth from "../symbols/cloth.png"; import _dye from "../symbols/dyes.png"; import _metal from "../symbols/metal.png"; import _plastic from "../symbols/plastic.png"; -import boxes from "./boxes"; -import coal from "./coal"; -import dyes from "./dyes"; +import _boxes from "../symbols/cardboardBox.png"; +import _wrappingPaper from "../symbols/wrappingPaper.png"; +import _ribbon from "../symbols/ribbons.png"; + import _bear from "./factory-components/bear.svg"; import _bearMaker from "./factory-components/bearmaker.svg"; +import _bearWrapper from "./factory-components/__placeholder.png"; import _block from "./factory-components/block.svg"; import _blockMaker from "./factory-components/blockmaker.svg"; +import _blockWrapper from "./factory-components/__placeholder.png"; +import _bow from "./factory-components/__placeholder.png"; +import _bowMaker from "./factory-components/__placeholder.png"; import _bucket from "./factory-components/bucket.svg"; import _bucketMaker from "./factory-components/bucketmaker.svg"; import _bucketShovel from "./factory-components/bucketshovel.svg"; import _bucketShovelMaker from "./factory-components/bucketshovelmaker.svg"; +import _bucketShovelWrapper from "./factory-components/__placeholder.png"; import _button from "./factory-components/button.svg"; import _buttonMaker from "./factory-components/buttonmaker.svg"; import _circuitBoard from "./factory-components/circuit.svg"; import _circuitBoardMaker from "./factory-components/circuitmaker.svg"; import _clothes from "./factory-components/clothes.svg"; import _clothesMaker from "./factory-components/clothesmaker.svg"; +import _clothesWrapper from "./factory-components/__placeholder.png"; import _console from "./factory-components/console.svg"; import _consoleMaker from "./factory-components/consolemaker.svg"; +import _consoleWrapper from "./factory-components/__placeholder.png"; import _conveyor from "./factory-components/conveyor.png"; import _cursor from "./factory-components/cursor.svg"; import _delete from "./factory-components/delete.svg"; @@ -73,18 +95,11 @@ import _thread from "./factory-components/thread.svg"; import _threadMaker from "./factory-components/threadmaker.svg"; import _truck from "./factory-components/truck.svg"; import _truckMaker from "./factory-components/truckmaker.svg"; +import _truckWrapper from "./factory-components/__placeholder.png"; import _wheel from "./factory-components/wheel.svg"; import _wheelMaker from "./factory-components/wheelmaker.svg"; -import Factory from "./Factory.vue"; -import metal from "./metal"; -import oil from "./oil"; -import paper from "./paper"; -import plastic from "./plastic"; -import "./styles/factory.css"; -import Toy from "./Toy.vue"; -import toys from "./toys"; -import trees from "./trees"; -import workshop from "./workshop"; +import _wrappedBox from "./factory-components/__placeholder.png"; +import _wrappedBoxMaker from "./factory-components/__placeholder.png"; const id = "factory"; @@ -356,7 +371,7 @@ const factory = createLayer(id, () => { imageSrc: _shed, extraImage: _wood, key: "1", - name: "Wood Machine", + name: "Wood Warehouse", type: "processor", description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.wood)), energyCost: 10, @@ -371,7 +386,7 @@ const factory = createLayer(id, () => { imageSrc: _shed, extraImage: _cloth, key: "2", - name: "Cloth Machine", + name: "Cloth Warehouse", type: "processor", description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.cloth)), energyCost: 10, @@ -386,7 +401,7 @@ const factory = createLayer(id, () => { imageSrc: _shed, extraImage: _dye, key: "3", - name: "Dye Machine", + name: "Dye Warehouse", type: "processor", description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.dye)), energyCost: 10, @@ -401,7 +416,7 @@ const factory = createLayer(id, () => { imageSrc: _shed, extraImage: _metal, key: "4", - name: "Metal Machine", + name: "Metal Warehouse", type: "processor", description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.metal)), energyCost: 10, @@ -416,7 +431,7 @@ const factory = createLayer(id, () => { imageSrc: _shed, extraImage: _plastic, key: "5", - name: "Plastic Machine", + name: "Plastic Warehouse", type: "processor", description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.plastic)), energyCost: 10, @@ -427,6 +442,54 @@ const factory = createLayer(id, () => { } } } as FactoryComponentDeclaration, + boxes: { + imageSrc: _shed, + extraImage: _boxes, + key: "6", + name: "Box Warehouse", + type: "processor", + description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.boxes)), + energyCost: 10, + tick: 1, + outputs: { + boxes: { + amount: 1 + } + }, + visible: main.days[presentsDay - 1].opened + } as FactoryComponentDeclaration, + wrappingPaper: { + imageSrc: _shed, + extraImage: _wrappingPaper, + key: "7", + name: "Wrapping Paper Warehouse", + type: "processor", + description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.wrappingPaper)), + energyCost: 10, + tick: 1, + outputs: { + wrappingPaper: { + amount: 1 + } + }, + visible: main.days[presentsDay - 1].opened + } as FactoryComponentDeclaration, + ribbon: { + imageSrc: _shed, + extraImage: _ribbon, + key: "8", + name: "Ribbon Warehouse", + type: "processor", + description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.ribbon)), + energyCost: 10, + tick: 1, + outputs: { + ribbon: { + amount: 1 + } + }, + visible: main.days[presentsDay - 1].opened + } as FactoryComponentDeclaration, plank: { imageSrc: _plankMaker, key: "shift+1", @@ -587,6 +650,55 @@ const factory = createLayer(id, () => { }, visible: main.days[advancedDay - 1].opened } as FactoryComponentDeclaration, + bow: { + imageSrc: _bowMaker, + key: "shift+0", + name: "Wrapped Box Manufacturer", + type: "processor", + description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.bow)), + energyCost: 2, + tick: 1, + inputs: { + ribbon: { + amount: 1 + } + }, + outputs: { + bow: { + amount: 1 + } + }, + visible: main.days[presentsDay - 1].opened + } as FactoryComponentDeclaration, + wrappedBox: { + imageSrc: _wrappedBoxMaker, + key: "shift+0", + name: "Wrapped Box Manufacturer", + type: "processor", + description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.wrappedBox)), + energyCost: 2, + tick: 1, + inputs: { + boxes: { + amount: 1 + }, + wrappingPaper: { + amount: 1 + }, + bow: { + amount: 1 + }, + ribbon: { + amount: 1 + } + }, + outputs: { + wrappedBox: { + amount: 1 + } + }, + visible: main.days[presentsDay - 1].opened + } as FactoryComponentDeclaration, blocks: { imageSrc: _blockMaker, key: "ctrl+1", @@ -736,6 +848,144 @@ const factory = createLayer(id, () => { } }, visible: main.days[advancedDay - 1].opened + } as FactoryComponentDeclaration, + wrappedBlocks: { + imageSrc: _blockWrapper, + key: "ctrl+shift+1", + name: "Wooden Block Wrapper", + type: "processor", + description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.wrappedBlocks)), + energyCost: 20, + tick: 1, + inputs: { + block: { + amount: 1 + }, + wrappedBox: { + amount: 1 + } + }, + outputs: { + wrappedBlock: { + amount: 1 + } + }, + visible: main.days[presentsDay - 1].opened + } as FactoryComponentDeclaration, + wrappedClothes: { + imageSrc: _clothesWrapper, + key: "ctrl+shift+2", + name: "Clothes Wrapper", + type: "processor", + description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.wrappedClothes)), + energyCost: 20, + tick: 1, + inputs: { + clothes: { + amount: 1 + }, + wrappedBox: { + amount: 1 + } + }, + outputs: { + wrappedClothes: { + amount: 1 + } + }, + visible: main.days[presentsDay - 1].opened + } as FactoryComponentDeclaration, + wrappedTrucks: { + imageSrc: _truckWrapper, + key: "ctrl+shift+3", + name: "Trucks Wrapper", + type: "processor", + description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.wrappedTrucks)), + energyCost: 20, + tick: 1, + inputs: { + trucks: { + amount: 1 + }, + wrappedBox: { + amount: 1 + } + }, + outputs: { + wrappedTrucks: { + amount: 1 + } + }, + visible: main.days[presentsDay - 1].opened + } as FactoryComponentDeclaration, + wrappedBear: { + imageSrc: _bearWrapper, + key: "ctrl+shift+4", + name: "Teddy Bear Wrapper", + type: "processor", + description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.wrappedBear)), + energyCost: 20, + tick: 1, + inputs: { + bear: { + amount: 1 + }, + wrappedBox: { + amount: 1 + } + }, + outputs: { + wrappedBear: { + amount: 1 + } + }, + visible: main.days[presentsDay - 1].opened + } as FactoryComponentDeclaration, + wrappedBucketShovel: { + imageSrc: _bucketShovelWrapper, + key: "ctrl+shift+5", + name: "Shovel and Pail Wrapper", + type: "processor", + description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.wrappedBucketShovel)), + energyCost: 20, + tick: 1, + inputs: { + shovelBucket: { + amount: 1 + }, + wrappedBox: { + amount: 1 + } + }, + outputs: { + wrappedShovelBucket: { + amount: 1 + } + }, + visible: main.days[presentsDay - 1].opened + } as FactoryComponentDeclaration, + wrappedConsole: { + imageSrc: _consoleWrapper, + key: "ctrl+shift+6", + name: "Game Console Wrapper", + type: "processor", + description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.wrappedConsole)), + energyCost: 20, + tick: 1, + inputs: { + console: { + amount: 1 + }, + wrappedBox: { + amount: 1 + } + }, + outputs: { + wrappedConsole: { + amount: 1 + } + }, + visible: main.days[presentsDay - 1].opened } as FactoryComponentDeclaration } as Record; const RESOURCES = { @@ -760,6 +1010,18 @@ const factory = createLayer(id, () => { name: "Metal", imageSrc: _metal }, + boxes: { + name: "Boxes", + imageSrc: _boxes + }, + wrappingPaper: { + name: "Wrapping Paper", + imageSrc: _wrappingPaper + }, + ribbon: { + name: "Ribbon", + imageSrc: _ribbon + }, // Processed resources plank: { name: "Planks", @@ -793,6 +1055,14 @@ const factory = createLayer(id, () => { name: "Circuit Board", imageSrc: _circuitBoard }, + bow: { + name: "Bow", + imageSrc: _bow + }, + wrappedBox: { + name: "Wrapped Box", + imageSrc: _wrappedBox + }, // Toys block: { name: "Wooden Blocks", @@ -817,6 +1087,31 @@ const factory = createLayer(id, () => { console: { name: "Game Console", imageSrc: _console + }, + // Wrapped toys + wrappedBlock: { + name: "Wrapped Wooden Blocks", + imageSrc: _block + }, + wrappedClothes: { + name: "Wrapped Clothes", + imageSrc: _clothes + }, + wrappedTrucks: { + name: "Wrapped Trucks", + imageSrc: _truck + }, + wrappedBear: { + name: "Wrapped Teddy Bear", + imageSrc: _bear + }, + wrappedShovelBucket: { + name: "Wrapped Shovel and Pail", + imageSrc: _bucketShovel + }, + wrappedConsole: { + name: "Wrapped Game Console", + imageSrc: _console } } as const; diff --git a/src/data/layers/styles/factory.css b/src/data/layers/styles/factory.css index 7cedc3a..da6ab57 100644 --- a/src/data/layers/styles/factory.css +++ b/src/data/layers/styles/factory.css @@ -151,8 +151,10 @@ justify-content: space-evenly; align-items: flex-start; align-content: flex-start; + justify-content: flex-start; width: 148px; direction: ltr; + text-align: left; } .comp-list::after { @@ -176,6 +178,11 @@ pointer-events: all; } +.comp-list .comp > img:first-child { + width: 50px; + height: 50px; +} + .comp-list .comp:nth-child(3)::after, .comp-list .comp:nth-child(4)::after { content: ""; @@ -192,7 +199,7 @@ .comp-list .comp:nth-child(4)::after { left: -50px; } -.comp-list .comp img.selected:not(.producedItem) { +.comp-list .comp img.selected, .comp-list .comp img.selected + img { transform: translate(-5px, -5px); filter: drop-shadow(2px 2px 0 var(--foreground)) drop-shadow(5px 5px 5px #0007); } From 894178989970bb30d66e88faaec92d35b30bd03e Mon Sep 17 00:00:00 2001 From: ducdat0507 <62660527+ducdat0507@users.noreply.github.com> Date: Fri, 23 Dec 2022 21:34:01 +0700 Subject: [PATCH 22/48] Fix bow maker's name --- src/data/layers/factory.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/data/layers/factory.tsx b/src/data/layers/factory.tsx index c3d87f5..1193bbe 100644 --- a/src/data/layers/factory.tsx +++ b/src/data/layers/factory.tsx @@ -653,7 +653,7 @@ const factory = createLayer(id, () => { bow: { imageSrc: _bowMaker, key: "shift+0", - name: "Wrapped Box Manufacturer", + name: "Bow Manufacturer", type: "processor", description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.bow)), energyCost: 2, From 428ca75b120206bb747fd127152abebeb55d92c6 Mon Sep 17 00:00:00 2001 From: ducdat0507 <62660527+ducdat0507@users.noreply.github.com> Date: Fri, 23 Dec 2022 21:35:00 +0700 Subject: [PATCH 23/48] Fix bow maker's hotkey --- src/data/layers/factory.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/data/layers/factory.tsx b/src/data/layers/factory.tsx index 1193bbe..e50955f 100644 --- a/src/data/layers/factory.tsx +++ b/src/data/layers/factory.tsx @@ -652,8 +652,8 @@ const factory = createLayer(id, () => { } as FactoryComponentDeclaration, bow: { imageSrc: _bowMaker, - key: "shift+0", - name: "Bow Manufacturer", + key: "shift+9", + name: "Bow Maker", type: "processor", description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.bow)), energyCost: 2, @@ -673,7 +673,7 @@ const factory = createLayer(id, () => { wrappedBox: { imageSrc: _wrappedBoxMaker, key: "shift+0", - name: "Wrapped Box Manufacturer", + name: "Box Wrapper", type: "processor", description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.wrappedBox)), energyCost: 2, From dcabdac385e88c5836cddef5fd2cfe245dbfa264 Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Fri, 23 Dec 2022 08:48:17 -0600 Subject: [PATCH 24/48] Fixed random error I started getting about main being undefined?? --- src/components/Options.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Options.vue b/src/components/Options.vue index 657388f..08245dc 100644 --- a/src/components/Options.vue +++ b/src/components/Options.vue @@ -98,7 +98,7 @@ const isPaused = computed({ }); const canAutoSave = computed( - () => (layers as any).main.days[(layers as any).main.day.value - 1].opened.value + () => (layers as any).main?.days[(layers as any).main?.day.value - 1].opened.value ); const autosaveTitle = jsx(() => ( From d43899e938237bec2f1a2471b3fe1d37d4e204d4 Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Fri, 23 Dec 2022 08:55:36 -0600 Subject: [PATCH 25/48] Fix build errors --- src/data/layers/factory.tsx | 66 +++++++++++++++++++++++++++---------- 1 file changed, 49 insertions(+), 17 deletions(-) diff --git a/src/data/layers/factory.tsx b/src/data/layers/factory.tsx index 1884ca7..f7f6b51 100644 --- a/src/data/layers/factory.tsx +++ b/src/data/layers/factory.tsx @@ -206,7 +206,10 @@ const factory = createLayer(id, () => { createMultiplicativeModifier(() => ({ multiplier: Decimal.lt(energyEfficiency.value, 1) ? 1 - : Decimal.sub(2, Decimal.div(energyConsumption.value, Decimal.max(computedEnergy.value, 1))), + : Decimal.sub( + 2, + Decimal.div(energyConsumption.value, Decimal.max(computedEnergy.value, 1)) + ), description: "Brighter work rooms", enabled: () => upgrades[2][0].bought.value })), @@ -287,17 +290,29 @@ const factory = createLayer(id, () => { // ---------------------------------------------- Components - function generateComponentDescription(declaration: FactoryComponentDeclaration) { - let str = declaration.inputs === undefined ? "Produces " : "Turns "; if (declaration.inputs !== undefined) { - str += formatList(Object.entries(declaration.inputs) - .map(x => formatWhole(unref(x[1].amount)) + " " + RESOURCES[x[0] as ResourceNames].name)) + " into "; + str += + formatList( + Object.entries(declaration.inputs).map( + x => + formatWhole(unref(x[1].amount)) + + " " + + RESOURCES[x[0] as ResourceNames].name + ) + ) + " into "; } if (declaration.outputs !== undefined) { - str += formatList(Object.entries(declaration.outputs) - .map(x => formatWhole(unref(x[1].amount)) + " " + RESOURCES[x[0] as ResourceNames].name)) + " per tick."; + str += + formatList( + Object.entries(declaration.outputs).map( + x => + formatWhole(unref(x[1].amount)) + + " " + + RESOURCES[x[0] as ResourceNames].name + ) + ) + " per tick."; } return str; } @@ -569,7 +584,9 @@ const factory = createLayer(id, () => { key: "shift+8", name: "Circuit Board Manufacturer", type: "processor", - description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.circuitBoard)), + description: computed(() => + generateComponentDescription(FACTORY_COMPONENTS.circuitBoard) + ), energyCost: 2, tick: 1, inputs: { @@ -691,7 +708,9 @@ const factory = createLayer(id, () => { key: "ctrl+5", name: "Shovel and Pail Maker", type: "processor", - description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.bucketShovel)), + description: computed(() => + generateComponentDescription(FACTORY_COMPONENTS.bucketShovel) + ), energyCost: 20, tick: 1, inputs: { @@ -1548,7 +1567,11 @@ const factory = createLayer(id, () => { lastProdTimes: !isConveyor ? (reactive([]) as number[]) : undefined, lastFactoryProd: !isConveyor ? Date.now() - - 1000 * Decimal.div(data.ticksDone ?? 0, computedActualTickRate.value).toNumber() + 1000 * + Decimal.div( + (data as FactoryComponentProcessor).ticksDone ?? 0, + computedActualTickRate.value + ).toNumber() : undefined, average: !isConveyor ? computed(() => { @@ -1914,32 +1937,41 @@ const factory = createLayer(id, () => { compInternalHovered.value.type !== "conveyor" ? ( <> {showStockAmount( - compHovered.value.inputStock, + (compHovered.value as FactoryComponentProcessor).inputStock, FACTORY_COMPONENTS[compHovered.value.type].inputs, "Inputs:" )} {showStockAmount( - compHovered.value.outputStock, + (compHovered.value as FactoryComponentProcessor).outputStock, FACTORY_COMPONENTS[compHovered.value.type].outputs, "Outputs:", false )}
Efficency:{" "} - {compInternalHovered.value.average.value !== undefined ? ( + {(compInternalHovered.value as FactoryInternalProcessor).average.value !== + undefined ? ( 1 + (compInternalHovered.value as FactoryInternalProcessor) + .average.value! > 1 ? "purple" - : compInternalHovered.value.average.value >= 0.9 + : ( + compInternalHovered.value as FactoryInternalProcessor + ).average.value! >= 0.9 ? "green" - : compInternalHovered.value.average.value >= 0.5 + : ( + compInternalHovered.value as FactoryInternalProcessor + ).average.value! >= 0.5 ? "yellow" : "red" }} > - {formatWhole(compInternalHovered.value.average.value * 100)} + {formatWhole( + (compInternalHovered.value as FactoryInternalProcessor).average + .value! * 100 + )} ) : ( "--" From 8367ef20992c648ba93853f3ae89d79893418790 Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Fri, 23 Dec 2022 09:42:26 -0600 Subject: [PATCH 26/48] Fixed factory error when changing saves --- src/data/layers/factory.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/data/layers/factory.tsx b/src/data/layers/factory.tsx index f7f6b51..d234204 100644 --- a/src/data/layers/factory.tsx +++ b/src/data/layers/factory.tsx @@ -1239,6 +1239,9 @@ const factory = createLayer(id, () => { let loaded = false; globalBus.on("onLoad", async () => { + if (loaded) { + return; + } loaded = false; spriteContainer.destroy({ From eea9a6f0e8e579b8c0fe96f65e55b8025f906a39 Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Fri, 23 Dec 2022 09:42:45 -0600 Subject: [PATCH 27/48] Fix visibility not working on components --- src/data/layers/factory.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/data/layers/factory.tsx b/src/data/layers/factory.tsx index d234204..bd47fef 100644 --- a/src/data/layers/factory.tsx +++ b/src/data/layers/factory.tsx @@ -1841,6 +1841,9 @@ const factory = createLayer(id, () => { {Object.entries(FACTORY_COMPONENTS).map(value => { const key = value[0] as FactoryCompNames; const item = value[1]; + if (unref(item.visible) === false) { + return null; + } return (
Date: Fri, 23 Dec 2022 09:44:13 -0600 Subject: [PATCH 28/48] Fix factory buyables and upgrade grid being visible in day 18 --- src/data/layers/factory.tsx | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/data/layers/factory.tsx b/src/data/layers/factory.tsx index bd47fef..1d97c5e 100644 --- a/src/data/layers/factory.tsx +++ b/src/data/layers/factory.tsx @@ -1057,7 +1057,7 @@ const factory = createLayer(id, () => { showAmount: false }, style: "width: 200px", - visible: () => showIf(main.days[advancedDay - 1].opened.value) + visibility: () => showIf(main.days[advancedDay - 1].opened.value) })) as GenericBuyable; const oilFuel = createBuyable(() => ({ resource: oil.oil, @@ -1071,7 +1071,7 @@ const factory = createLayer(id, () => { showAmount: false }, style: "width: 200px", - visible: () => showIf(main.days[advancedDay - 1].opened.value) + visibility: () => showIf(main.days[advancedDay - 1].opened.value) })) as GenericBuyable; const carryToys = createBuyable(() => ({ resource: boxes.boxes, @@ -1087,7 +1087,7 @@ const factory = createLayer(id, () => { showAmount: false }, style: "width: 200px", - visible: () => showIf(main.days[advancedDay - 1].opened.value) + visibility: () => showIf(main.days[advancedDay - 1].opened.value) })) as GenericBuyable; const factoryBuyables = { expandFactory, oilFuel, carryToys }; const upgrades = [ @@ -1100,7 +1100,7 @@ const factory = createLayer(id, () => { description: "Double sawmill consumption and production and metal supplier efficiency" }, - visible: () => showIf(main.days[advancedDay - 1].opened.value) + visibility: () => showIf(main.days[advancedDay - 1].opened.value) })), createUpgrade(() => ({ resource: paper.paper, @@ -1109,7 +1109,7 @@ const factory = createLayer(id, () => { title: "News Ticker", description: "Paper boosts tick speed" }, - visible: () => showIf(main.days[advancedDay - 1].opened.value) + visibility: () => showIf(main.days[advancedDay - 1].opened.value) })), createUpgrade(() => ({ resource: toys.trucks, @@ -1118,7 +1118,7 @@ const factory = createLayer(id, () => { title: "Haul wood in trucks", description: "Trucks multiply wood gain" }, - visible: () => showIf(main.days[advancedDay - 1].opened.value) + visibility: () => showIf(main.days[advancedDay - 1].opened.value) })), createUpgrade(() => ({ resource: metal.metal, @@ -1127,7 +1127,7 @@ const factory = createLayer(id, () => { title: "Diamond-tipped drills", description: "Drill power ^1.2" }, - visible: () => showIf(main.days[advancedDay - 1].opened.value) + visibility: () => showIf(main.days[advancedDay - 1].opened.value) })) ], [ @@ -1138,7 +1138,7 @@ const factory = createLayer(id, () => { title: "Larger wood pieces", description: "Wooden block producers produce 3x as much" }, - visible: () => showIf(main.days[advancedDay - 1].opened.value) + visibility: () => showIf(main.days[advancedDay - 1].opened.value) })), createUpgrade(() => ({ resource: dyes.dyes.red.amount, @@ -1147,7 +1147,7 @@ const factory = createLayer(id, () => { title: "Colorful clothes", description: "Dye producers produce 4x as much" }, - visible: () => showIf(main.days[advancedDay - 1].opened.value) + visibility: () => showIf(main.days[advancedDay - 1].opened.value) })), createUpgrade(() => ({ resource: plastic.plastic, @@ -1156,7 +1156,7 @@ const factory = createLayer(id, () => { title: "Improved plastic producers", description: "Plastic producers produce 4x as much" }, - visible: () => showIf(main.days[advancedDay - 1].opened.value) + visibility: () => showIf(main.days[advancedDay - 1].opened.value) })), createUpgrade(() => ({ resource: oil.oil, @@ -1165,7 +1165,7 @@ const factory = createLayer(id, () => { title: "Capitalism", description: "Console production is tripled" }, - visible: () => showIf(main.days[advancedDay - 1].opened.value) + visibility: () => showIf(main.days[advancedDay - 1].opened.value) })) ], [ @@ -1176,7 +1176,7 @@ const factory = createLayer(id, () => { title: "Brighter work rooms", description: "Unused electricity makes ticks faster" }, - visible: () => showIf(main.days[advancedDay - 1].opened.value) + visibility: () => showIf(main.days[advancedDay - 1].opened.value) })), createUpgrade(() => ({ resource: dyes.dyes.blue.amount, @@ -1185,7 +1185,7 @@ const factory = createLayer(id, () => { title: "Colorful teddy bears", description: "Teddy bears produce 2x as much" }, - visible: () => showIf(main.days[advancedDay - 1].opened.value) + visibility: () => showIf(main.days[advancedDay - 1].opened.value) })), createUpgrade(() => ({ resource: dyes.dyes.black.amount, @@ -1194,7 +1194,7 @@ const factory = createLayer(id, () => { title: "New Colors", description: "Unlock white dye" }, - visible: () => showIf(main.days[advancedDay - 1].opened.value) + visibility: () => showIf(main.days[advancedDay - 1].opened.value) })), createUpgrade(() => ({ resource: boxes.boxes, @@ -1203,7 +1203,7 @@ const factory = createLayer(id, () => { title: "Carry ticks in boxes", description: "Tick speed x1.5" }, - visible: () => showIf(main.days[advancedDay - 1].opened.value) + visibility: () => showIf(main.days[advancedDay - 1].opened.value) })) ] ]; From 529eabbcd05c880f6ee086d218a824056fa05f19 Mon Sep 17 00:00:00 2001 From: someoneWasTaken94 <121205769+someoneWasTaken94@users.noreply.github.com> Date: Fri, 23 Dec 2022 16:36:13 +0000 Subject: [PATCH 29/48] stuff --- src/data/layers/factory.tsx | 437 ++++++++---------------------------- 1 file changed, 90 insertions(+), 347 deletions(-) diff --git a/src/data/layers/factory.tsx b/src/data/layers/factory.tsx index e50955f..db463b3 100644 --- a/src/data/layers/factory.tsx +++ b/src/data/layers/factory.tsx @@ -33,51 +33,29 @@ import { Direction, WithRequired } from "util/common"; import { ProcessedComputable } from "util/computed"; import { render, renderGrid, renderRow, VueFeature } from "util/vue"; import { computed, ComputedRef, reactive, ref, shallowRef, unref, watchEffect } from "vue"; -import boxes from "./boxes"; -import coal from "./coal"; -import dyes from "./dyes"; -import Factory from "./Factory.vue"; -import metal from "./metal"; -import oil from "./oil"; -import paper from "./paper"; -import plastic from "./plastic"; -import "./styles/factory.css"; -import Toy from "./Toy.vue"; -import toys from "./toys"; -import trees from "./trees"; -import workshop from "./workshop"; - import _cloth from "../symbols/cloth.png"; import _dye from "../symbols/dyes.png"; import _metal from "../symbols/metal.png"; import _plastic from "../symbols/plastic.png"; -import _boxes from "../symbols/cardboardBox.png"; -import _wrappingPaper from "../symbols/wrappingPaper.png"; -import _ribbon from "../symbols/ribbons.png"; - +import boxes from "./boxes"; +import coal from "./coal"; +import dyes from "./dyes"; import _bear from "./factory-components/bear.svg"; import _bearMaker from "./factory-components/bearmaker.svg"; -import _bearWrapper from "./factory-components/__placeholder.png"; import _block from "./factory-components/block.svg"; import _blockMaker from "./factory-components/blockmaker.svg"; -import _blockWrapper from "./factory-components/__placeholder.png"; -import _bow from "./factory-components/__placeholder.png"; -import _bowMaker from "./factory-components/__placeholder.png"; import _bucket from "./factory-components/bucket.svg"; import _bucketMaker from "./factory-components/bucketmaker.svg"; import _bucketShovel from "./factory-components/bucketshovel.svg"; import _bucketShovelMaker from "./factory-components/bucketshovelmaker.svg"; -import _bucketShovelWrapper from "./factory-components/__placeholder.png"; import _button from "./factory-components/button.svg"; import _buttonMaker from "./factory-components/buttonmaker.svg"; import _circuitBoard from "./factory-components/circuit.svg"; import _circuitBoardMaker from "./factory-components/circuitmaker.svg"; import _clothes from "./factory-components/clothes.svg"; import _clothesMaker from "./factory-components/clothesmaker.svg"; -import _clothesWrapper from "./factory-components/__placeholder.png"; import _console from "./factory-components/console.svg"; import _consoleMaker from "./factory-components/consolemaker.svg"; -import _consoleWrapper from "./factory-components/__placeholder.png"; import _conveyor from "./factory-components/conveyor.png"; import _cursor from "./factory-components/cursor.svg"; import _delete from "./factory-components/delete.svg"; @@ -95,11 +73,18 @@ import _thread from "./factory-components/thread.svg"; import _threadMaker from "./factory-components/threadmaker.svg"; import _truck from "./factory-components/truck.svg"; import _truckMaker from "./factory-components/truckmaker.svg"; -import _truckWrapper from "./factory-components/__placeholder.png"; import _wheel from "./factory-components/wheel.svg"; import _wheelMaker from "./factory-components/wheelmaker.svg"; -import _wrappedBox from "./factory-components/__placeholder.png"; -import _wrappedBoxMaker from "./factory-components/__placeholder.png"; +import Factory from "./Factory.vue"; +import metal from "./metal"; +import oil from "./oil"; +import paper from "./paper"; +import plastic from "./plastic"; +import "./styles/factory.css"; +import Toy from "./Toy.vue"; +import toys from "./toys"; +import trees from "./trees"; +import workshop from "./workshop"; const id = "factory"; @@ -221,7 +206,10 @@ const factory = createLayer(id, () => { createMultiplicativeModifier(() => ({ multiplier: Decimal.lt(energyEfficiency.value, 1) ? 1 - : Decimal.sub(2, Decimal.div(energyConsumption.value, Decimal.max(computedEnergy.value, 1))), + : Decimal.sub( + 2, + Decimal.div(energyConsumption.value, Decimal.max(computedEnergy.value, 1)) + ), description: "Brighter work rooms", enabled: () => upgrades[2][0].bought.value })), @@ -302,17 +290,29 @@ const factory = createLayer(id, () => { // ---------------------------------------------- Components - function generateComponentDescription(declaration: FactoryComponentDeclaration) { - let str = declaration.inputs === undefined ? "Produces " : "Turns "; if (declaration.inputs !== undefined) { - str += formatList(Object.entries(declaration.inputs) - .map(x => formatWhole(unref(x[1].amount)) + " " + RESOURCES[x[0] as ResourceNames].name)) + " into "; + str += + formatList( + Object.entries(declaration.inputs).map( + x => + formatWhole(unref(x[1].amount)) + + " " + + RESOURCES[x[0] as ResourceNames].name + ) + ) + " into "; } if (declaration.outputs !== undefined) { - str += formatList(Object.entries(declaration.outputs) - .map(x => formatWhole(unref(x[1].amount)) + " " + RESOURCES[x[0] as ResourceNames].name)) + " per tick."; + str += + formatList( + Object.entries(declaration.outputs).map( + x => + formatWhole(unref(x[1].amount)) + + " " + + RESOURCES[x[0] as ResourceNames].name + ) + ) + " per tick."; } return str; } @@ -371,7 +371,7 @@ const factory = createLayer(id, () => { imageSrc: _shed, extraImage: _wood, key: "1", - name: "Wood Warehouse", + name: "Wood Machine", type: "processor", description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.wood)), energyCost: 10, @@ -386,7 +386,7 @@ const factory = createLayer(id, () => { imageSrc: _shed, extraImage: _cloth, key: "2", - name: "Cloth Warehouse", + name: "Cloth Machine", type: "processor", description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.cloth)), energyCost: 10, @@ -401,7 +401,7 @@ const factory = createLayer(id, () => { imageSrc: _shed, extraImage: _dye, key: "3", - name: "Dye Warehouse", + name: "Dye Machine", type: "processor", description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.dye)), energyCost: 10, @@ -416,7 +416,7 @@ const factory = createLayer(id, () => { imageSrc: _shed, extraImage: _metal, key: "4", - name: "Metal Warehouse", + name: "Metal Machine", type: "processor", description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.metal)), energyCost: 10, @@ -431,7 +431,7 @@ const factory = createLayer(id, () => { imageSrc: _shed, extraImage: _plastic, key: "5", - name: "Plastic Warehouse", + name: "Plastic Machine", type: "processor", description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.plastic)), energyCost: 10, @@ -442,54 +442,6 @@ const factory = createLayer(id, () => { } } } as FactoryComponentDeclaration, - boxes: { - imageSrc: _shed, - extraImage: _boxes, - key: "6", - name: "Box Warehouse", - type: "processor", - description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.boxes)), - energyCost: 10, - tick: 1, - outputs: { - boxes: { - amount: 1 - } - }, - visible: main.days[presentsDay - 1].opened - } as FactoryComponentDeclaration, - wrappingPaper: { - imageSrc: _shed, - extraImage: _wrappingPaper, - key: "7", - name: "Wrapping Paper Warehouse", - type: "processor", - description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.wrappingPaper)), - energyCost: 10, - tick: 1, - outputs: { - wrappingPaper: { - amount: 1 - } - }, - visible: main.days[presentsDay - 1].opened - } as FactoryComponentDeclaration, - ribbon: { - imageSrc: _shed, - extraImage: _ribbon, - key: "8", - name: "Ribbon Warehouse", - type: "processor", - description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.ribbon)), - energyCost: 10, - tick: 1, - outputs: { - ribbon: { - amount: 1 - } - }, - visible: main.days[presentsDay - 1].opened - } as FactoryComponentDeclaration, plank: { imageSrc: _plankMaker, key: "shift+1", @@ -632,7 +584,9 @@ const factory = createLayer(id, () => { key: "shift+8", name: "Circuit Board Manufacturer", type: "processor", - description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.circuitBoard)), + description: computed(() => + generateComponentDescription(FACTORY_COMPONENTS.circuitBoard) + ), energyCost: 2, tick: 1, inputs: { @@ -650,55 +604,6 @@ const factory = createLayer(id, () => { }, visible: main.days[advancedDay - 1].opened } as FactoryComponentDeclaration, - bow: { - imageSrc: _bowMaker, - key: "shift+9", - name: "Bow Maker", - type: "processor", - description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.bow)), - energyCost: 2, - tick: 1, - inputs: { - ribbon: { - amount: 1 - } - }, - outputs: { - bow: { - amount: 1 - } - }, - visible: main.days[presentsDay - 1].opened - } as FactoryComponentDeclaration, - wrappedBox: { - imageSrc: _wrappedBoxMaker, - key: "shift+0", - name: "Box Wrapper", - type: "processor", - description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.wrappedBox)), - energyCost: 2, - tick: 1, - inputs: { - boxes: { - amount: 1 - }, - wrappingPaper: { - amount: 1 - }, - bow: { - amount: 1 - }, - ribbon: { - amount: 1 - } - }, - outputs: { - wrappedBox: { - amount: 1 - } - }, - visible: main.days[presentsDay - 1].opened - } as FactoryComponentDeclaration, blocks: { imageSrc: _blockMaker, key: "ctrl+1", @@ -803,7 +708,9 @@ const factory = createLayer(id, () => { key: "ctrl+5", name: "Shovel and Pail Maker", type: "processor", - description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.bucketShovel)), + description: computed(() => + generateComponentDescription(FACTORY_COMPONENTS.bucketShovel) + ), energyCost: 20, tick: 1, inputs: { @@ -848,144 +755,6 @@ const factory = createLayer(id, () => { } }, visible: main.days[advancedDay - 1].opened - } as FactoryComponentDeclaration, - wrappedBlocks: { - imageSrc: _blockWrapper, - key: "ctrl+shift+1", - name: "Wooden Block Wrapper", - type: "processor", - description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.wrappedBlocks)), - energyCost: 20, - tick: 1, - inputs: { - block: { - amount: 1 - }, - wrappedBox: { - amount: 1 - } - }, - outputs: { - wrappedBlock: { - amount: 1 - } - }, - visible: main.days[presentsDay - 1].opened - } as FactoryComponentDeclaration, - wrappedClothes: { - imageSrc: _clothesWrapper, - key: "ctrl+shift+2", - name: "Clothes Wrapper", - type: "processor", - description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.wrappedClothes)), - energyCost: 20, - tick: 1, - inputs: { - clothes: { - amount: 1 - }, - wrappedBox: { - amount: 1 - } - }, - outputs: { - wrappedClothes: { - amount: 1 - } - }, - visible: main.days[presentsDay - 1].opened - } as FactoryComponentDeclaration, - wrappedTrucks: { - imageSrc: _truckWrapper, - key: "ctrl+shift+3", - name: "Trucks Wrapper", - type: "processor", - description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.wrappedTrucks)), - energyCost: 20, - tick: 1, - inputs: { - trucks: { - amount: 1 - }, - wrappedBox: { - amount: 1 - } - }, - outputs: { - wrappedTrucks: { - amount: 1 - } - }, - visible: main.days[presentsDay - 1].opened - } as FactoryComponentDeclaration, - wrappedBear: { - imageSrc: _bearWrapper, - key: "ctrl+shift+4", - name: "Teddy Bear Wrapper", - type: "processor", - description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.wrappedBear)), - energyCost: 20, - tick: 1, - inputs: { - bear: { - amount: 1 - }, - wrappedBox: { - amount: 1 - } - }, - outputs: { - wrappedBear: { - amount: 1 - } - }, - visible: main.days[presentsDay - 1].opened - } as FactoryComponentDeclaration, - wrappedBucketShovel: { - imageSrc: _bucketShovelWrapper, - key: "ctrl+shift+5", - name: "Shovel and Pail Wrapper", - type: "processor", - description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.wrappedBucketShovel)), - energyCost: 20, - tick: 1, - inputs: { - shovelBucket: { - amount: 1 - }, - wrappedBox: { - amount: 1 - } - }, - outputs: { - wrappedShovelBucket: { - amount: 1 - } - }, - visible: main.days[presentsDay - 1].opened - } as FactoryComponentDeclaration, - wrappedConsole: { - imageSrc: _consoleWrapper, - key: "ctrl+shift+6", - name: "Game Console Wrapper", - type: "processor", - description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.wrappedConsole)), - energyCost: 20, - tick: 1, - inputs: { - console: { - amount: 1 - }, - wrappedBox: { - amount: 1 - } - }, - outputs: { - wrappedConsole: { - amount: 1 - } - }, - visible: main.days[presentsDay - 1].opened } as FactoryComponentDeclaration } as Record; const RESOURCES = { @@ -1010,18 +779,6 @@ const factory = createLayer(id, () => { name: "Metal", imageSrc: _metal }, - boxes: { - name: "Boxes", - imageSrc: _boxes - }, - wrappingPaper: { - name: "Wrapping Paper", - imageSrc: _wrappingPaper - }, - ribbon: { - name: "Ribbon", - imageSrc: _ribbon - }, // Processed resources plank: { name: "Planks", @@ -1055,14 +812,6 @@ const factory = createLayer(id, () => { name: "Circuit Board", imageSrc: _circuitBoard }, - bow: { - name: "Bow", - imageSrc: _bow - }, - wrappedBox: { - name: "Wrapped Box", - imageSrc: _wrappedBox - }, // Toys block: { name: "Wooden Blocks", @@ -1087,31 +836,6 @@ const factory = createLayer(id, () => { console: { name: "Game Console", imageSrc: _console - }, - // Wrapped toys - wrappedBlock: { - name: "Wrapped Wooden Blocks", - imageSrc: _block - }, - wrappedClothes: { - name: "Wrapped Clothes", - imageSrc: _clothes - }, - wrappedTrucks: { - name: "Wrapped Trucks", - imageSrc: _truck - }, - wrappedBear: { - name: "Wrapped Teddy Bear", - imageSrc: _bear - }, - wrappedShovelBucket: { - name: "Wrapped Shovel and Pail", - imageSrc: _bucketShovel - }, - wrappedConsole: { - name: "Wrapped Game Console", - imageSrc: _console } } as const; @@ -1333,7 +1057,7 @@ const factory = createLayer(id, () => { showAmount: false }, style: "width: 200px", - visible: () => showIf(main.days[advancedDay - 1].opened.value) + visibility: () => showIf(main.days[advancedDay - 1].opened.value) })) as GenericBuyable; const oilFuel = createBuyable(() => ({ resource: oil.oil, @@ -1347,7 +1071,7 @@ const factory = createLayer(id, () => { showAmount: false }, style: "width: 200px", - visible: () => showIf(main.days[advancedDay - 1].opened.value) + visibility: () => showIf(main.days[advancedDay - 1].opened.value) })) as GenericBuyable; const carryToys = createBuyable(() => ({ resource: boxes.boxes, @@ -1363,7 +1087,7 @@ const factory = createLayer(id, () => { showAmount: false }, style: "width: 200px", - visible: () => showIf(main.days[advancedDay - 1].opened.value) + visibility: () => showIf(main.days[advancedDay - 1].opened.value) })) as GenericBuyable; const factoryBuyables = { expandFactory, oilFuel, carryToys }; const upgrades = [ @@ -1376,7 +1100,7 @@ const factory = createLayer(id, () => { description: "Double sawmill consumption and production and metal supplier efficiency" }, - visible: () => showIf(main.days[advancedDay - 1].opened.value) + visibility: () => showIf(main.days[advancedDay - 1].opened.value) })), createUpgrade(() => ({ resource: paper.paper, @@ -1385,7 +1109,7 @@ const factory = createLayer(id, () => { title: "News Ticker", description: "Paper boosts tick speed" }, - visible: () => showIf(main.days[advancedDay - 1].opened.value) + visibility: () => showIf(main.days[advancedDay - 1].opened.value) })), createUpgrade(() => ({ resource: toys.trucks, @@ -1394,7 +1118,7 @@ const factory = createLayer(id, () => { title: "Haul wood in trucks", description: "Trucks multiply wood gain" }, - visible: () => showIf(main.days[advancedDay - 1].opened.value) + visibility: () => showIf(main.days[advancedDay - 1].opened.value) })), createUpgrade(() => ({ resource: metal.metal, @@ -1403,7 +1127,7 @@ const factory = createLayer(id, () => { title: "Diamond-tipped drills", description: "Drill power ^1.2" }, - visible: () => showIf(main.days[advancedDay - 1].opened.value) + visibility: () => showIf(main.days[advancedDay - 1].opened.value) })) ], [ @@ -1414,7 +1138,7 @@ const factory = createLayer(id, () => { title: "Larger wood pieces", description: "Wooden block producers produce 3x as much" }, - visible: () => showIf(main.days[advancedDay - 1].opened.value) + visibility: () => showIf(main.days[advancedDay - 1].opened.value) })), createUpgrade(() => ({ resource: dyes.dyes.red.amount, @@ -1423,7 +1147,7 @@ const factory = createLayer(id, () => { title: "Colorful clothes", description: "Dye producers produce 4x as much" }, - visible: () => showIf(main.days[advancedDay - 1].opened.value) + visibility: () => showIf(main.days[advancedDay - 1].opened.value) })), createUpgrade(() => ({ resource: plastic.plastic, @@ -1432,7 +1156,7 @@ const factory = createLayer(id, () => { title: "Improved plastic producers", description: "Plastic producers produce 4x as much" }, - visible: () => showIf(main.days[advancedDay - 1].opened.value) + visibility: () => showIf(main.days[advancedDay - 1].opened.value) })), createUpgrade(() => ({ resource: oil.oil, @@ -1441,7 +1165,7 @@ const factory = createLayer(id, () => { title: "Capitalism", description: "Console production is tripled" }, - visible: () => showIf(main.days[advancedDay - 1].opened.value) + visibility: () => showIf(main.days[advancedDay - 1].opened.value) })) ], [ @@ -1452,7 +1176,7 @@ const factory = createLayer(id, () => { title: "Brighter work rooms", description: "Unused electricity makes ticks faster" }, - visible: () => showIf(main.days[advancedDay - 1].opened.value) + visibility: () => showIf(main.days[advancedDay - 1].opened.value) })), createUpgrade(() => ({ resource: dyes.dyes.blue.amount, @@ -1461,7 +1185,7 @@ const factory = createLayer(id, () => { title: "Colorful teddy bears", description: "Teddy bears produce 2x as much" }, - visible: () => showIf(main.days[advancedDay - 1].opened.value) + visibility: () => showIf(main.days[advancedDay - 1].opened.value) })), createUpgrade(() => ({ resource: dyes.dyes.black.amount, @@ -1470,7 +1194,7 @@ const factory = createLayer(id, () => { title: "New Colors", description: "Unlock white dye" }, - visible: () => showIf(main.days[advancedDay - 1].opened.value) + visibility: () => showIf(main.days[advancedDay - 1].opened.value) })), createUpgrade(() => ({ resource: boxes.boxes, @@ -1479,7 +1203,7 @@ const factory = createLayer(id, () => { title: "Carry ticks in boxes", description: "Tick speed x1.5" }, - visible: () => showIf(main.days[advancedDay - 1].opened.value) + visibility: () => showIf(main.days[advancedDay - 1].opened.value) })) ] ]; @@ -1515,6 +1239,9 @@ const factory = createLayer(id, () => { let loaded = false; globalBus.on("onLoad", async () => { + if (loaded) { + return; + } loaded = false; spriteContainer.destroy({ @@ -1843,7 +1570,11 @@ const factory = createLayer(id, () => { lastProdTimes: !isConveyor ? (reactive([]) as number[]) : undefined, lastFactoryProd: !isConveyor ? Date.now() - - 1000 * Decimal.div(data.ticksDone ?? 0, computedActualTickRate.value).toNumber() + 1000 * + Decimal.div( + (data as FactoryComponentProcessor).ticksDone ?? 0, + computedActualTickRate.value + ).toNumber() : undefined, average: !isConveyor ? computed(() => { @@ -1867,7 +1598,7 @@ const factory = createLayer(id, () => { const compData = components.value[x + "x" + y] as FactoryComponentProcessor; if (factoryBaseData.inputs !== undefined) { for (const [res, val] of Object.entries(factoryBaseData.inputs)) - if ((compData.inputStock?.[res as ResourceNames] ?? 0) < val.amount) + if ((compData.inputStock?.[res as ResourceNames] ?? 0) < unref(val.amount)) return false; } if (factoryBaseData.outputs !== undefined) { @@ -2110,6 +1841,9 @@ const factory = createLayer(id, () => { {Object.entries(FACTORY_COMPONENTS).map(value => { const key = value[0] as FactoryCompNames; const item = value[1]; + if (unref(item.visible) === false) { + return null; + } return (
{ compInternalHovered.value.type !== "conveyor" ? ( <> {showStockAmount( - compHovered.value.inputStock, + (compHovered.value as FactoryComponentProcessor).inputStock, FACTORY_COMPONENTS[compHovered.value.type].inputs, "Inputs:" )} {showStockAmount( - compHovered.value.outputStock, + (compHovered.value as FactoryComponentProcessor).outputStock, FACTORY_COMPONENTS[compHovered.value.type].outputs, "Outputs:", false )}
Efficency:{" "} - {compInternalHovered.value.average.value !== undefined ? ( + {(compInternalHovered.value as FactoryInternalProcessor).average.value !== + undefined ? ( 1 + (compInternalHovered.value as FactoryInternalProcessor) + .average.value! > 1 ? "purple" - : compInternalHovered.value.average.value >= 0.9 + : ( + compInternalHovered.value as FactoryInternalProcessor + ).average.value! >= 0.9 ? "green" - : compInternalHovered.value.average.value >= 0.5 + : ( + compInternalHovered.value as FactoryInternalProcessor + ).average.value! >= 0.5 ? "yellow" : "red" }} > - {formatWhole(compInternalHovered.value.average.value * 100)} + {formatWhole( + (compInternalHovered.value as FactoryInternalProcessor).average + .value! * 100 + )} ) : ( "--" @@ -2476,4 +2219,4 @@ const factory = createLayer(id, () => { )) }; }); -export default factory; +export default factory; \ No newline at end of file From 4b9b2f263a78c049160c638f40eb0c5c8374807a Mon Sep 17 00:00:00 2001 From: unsoftcapped3 <75136164+unsoftcapped3@users.noreply.github.com> Date: Fri, 23 Dec 2022 10:20:54 -0800 Subject: [PATCH 30/48] add message about holding L --- src/data/layers/letters.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/data/layers/letters.tsx b/src/data/layers/letters.tsx index 62b8e13..6f27eb6 100644 --- a/src/data/layers/letters.tsx +++ b/src/data/layers/letters.tsx @@ -339,6 +339,7 @@ const layer = createLayer(id, function (this: BaseLayer) { ) : null} {render(process)} + If your letters are stuck, try holding L {Decimal.lt(totalLetters.value, 8e9) ? (
The more letters you process, the more you'll improve at processing letters. From cf5486fd71225bd570f36ac240d38e891e9c2a6b Mon Sep 17 00:00:00 2001 From: unsoftcapped3 <75136164+unsoftcapped3@users.noreply.github.com> Date: Fri, 23 Dec 2022 18:43:14 +0000 Subject: [PATCH 31/48] add more milestones --- src/data/layers/sleigh.tsx | 84 +++++++++++++++++++++++++++++++++----- 1 file changed, 73 insertions(+), 11 deletions(-) diff --git a/src/data/layers/sleigh.tsx b/src/data/layers/sleigh.tsx index 925774b..93247e9 100644 --- a/src/data/layers/sleigh.tsx +++ b/src/data/layers/sleigh.tsx @@ -43,23 +43,22 @@ const layer = createLayer(id, function (this: BaseLayer) { const sleighCost = computed(() => { let v = sleighProgress.value.value; return { - wood: Decimal.mul(1e100, Decimal.pow(1.2, v)), - metal: Decimal.mul(1e60, Decimal.pow(1.1, v)), - plastic: Decimal.mul(1e20, Decimal.pow(1.05, v)) + wood: Decimal.mul(1e60, Decimal.pow(1.2, v)), + metal: Decimal.mul(1e40, Decimal.pow(1.1, v)), + plastic: Decimal.mul(1e10, Decimal.pow(1.05, v)) }; }); const sleigh = createBuyable(() => ({ display: jsx(() => ( <> -

Fix the sleigh

-
- Increase sleigh fixed by 1% -
-
- Costs {displayCost(trees.logs, sleighCost.value.wood, "logs")}, + Fix 1% of the sleigh +
+
+ + Cost: {displayCost(trees.logs, sleighCost.value.wood, "logs")}, {displayCost(metal.metal, sleighCost.value.metal, "metal")}, {displayCost(plastic.plastic, sleighCost.value.plastic, "plastic")} -
+ )), canPurchase(): boolean { @@ -85,8 +84,71 @@ const layer = createLayer(id, function (this: BaseLayer) { shouldEarn: () => Decimal.gte(sleighProgress.value.value, 1), showPopups: shouldShowPopups })); + const milestone2 = createMilestone(() => ({ + display: { + requirement: "10% Sleigh Fixed", + effectDisplay: "Gain an additional 5% more wood for each 5% of sleigh fixed" + }, + shouldEarn: () => Decimal.gte(sleighProgress.value.value, 10), + showPopups: shouldShowPopups + })); + const milestone3 = createMilestone(() => ({ + display: { + requirement: "20% Sleigh Fixed", + effectDisplay: "Gain an additional 5% more plastic for each 5% of sleigh fixed" + }, + shouldEarn: () => Decimal.gte(sleighProgress.value.value, 20), + showPopups: shouldShowPopups + })); + const milestone4 = createMilestone(() => ({ + display: { + requirement: "30% Sleigh Fixed", + effectDisplay: "All automatic metal actions are doubled" + }, + shouldEarn: () => Decimal.gte(sleighProgress.value.value, 30), + showPopups: shouldShowPopups + })); + const milestone5 = createMilestone(() => ({ + display: { + requirement: "40% Sleigh Fixed", + effectDisplay: "Plastic gain is doubled" + }, + shouldEarn: () => Decimal.gte(sleighProgress.value.value, 40), + showPopups: shouldShowPopups + })); + const milestone6 = createMilestone(() => ({ + display: { + requirement: "50% Sleigh Fixed", + effectDisplay: "Trees give 10x as many logs" + }, + shouldEarn: () => Decimal.gte(sleighProgress.value.value, 50), + showPopups: shouldShowPopups + })); + const milestone7 = createMilestone(() => ({ + display: { + requirement: "75% Sleigh Fixed", + effectDisplay: "Gain 10 extra refineries for every 2% of sleigh fixed" + }, + shouldEarn: () => Decimal.gte(sleighProgress.value.value, 75), + showPopups: shouldShowPopups + })); + const milestone8 = createMilestone(() => ({ + display: { + requirement: "100% Sleigh Fixed", + effectDisplay: "Metal per ore is raised to the 1.2th power" + }, + shouldEarn: () => Decimal.gte(sleighProgress.value.value, 100), + showPopups: shouldShowPopups + })); const milestones = { - milestone1 + milestone1, + milestone2, + milestone3, + milestone4, + milestone5, + milestone6, + milestone7, + milestone8 }; const { collapseMilestones, display: milestonesDisplay } = createCollapsibleMilestones(milestones); From 1bc299e50c9f3b2fe4a7a97e929a2895a9c12ada Mon Sep 17 00:00:00 2001 From: unsoftcapped3 <75136164+unsoftcapped3@users.noreply.github.com> Date: Fri, 23 Dec 2022 12:00:40 -0800 Subject: [PATCH 32/48] fix foundation going above what it should be --- src/data/layers/workshop.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/data/layers/workshop.tsx b/src/data/layers/workshop.tsx index 831761c..b550e2e 100644 --- a/src/data/layers/workshop.tsx +++ b/src/data/layers/workshop.tsx @@ -123,6 +123,9 @@ const layer = createLayer(id, function (this: BaseLayer) { )), visibility: () => showIf(Decimal.lt(foundationProgress.value, computedMaxFoundation.value)), canClick: () => { + if (Decimal.gt(computedMaxFoundation.value, foundationProgress.value)){ + foundationProgress.value = Decimal.min(0, computedMaxFoundation.value) + } if (Decimal.lt(trees.logs.value, foundationConversion.nextAt.value)) { return false; } From 0ad95c08ba84780fd49847f31aba9f115e320ea4 Mon Sep 17 00:00:00 2001 From: Chunkybanana <62921243+chunkybanana@users.noreply.github.com> Date: Sat, 24 Dec 2022 11:01:57 +1300 Subject: [PATCH 33/48] Box maker --- .../layers/factory-components/boxmaker.svg | 123 ++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 src/data/layers/factory-components/boxmaker.svg diff --git a/src/data/layers/factory-components/boxmaker.svg b/src/data/layers/factory-components/boxmaker.svg new file mode 100644 index 0000000..13fd7cf --- /dev/null +++ b/src/data/layers/factory-components/boxmaker.svg @@ -0,0 +1,123 @@ + + + + From b9f304b656a1a622d4dd38a4bc34fe6596e8fc72 Mon Sep 17 00:00:00 2001 From: someoneWasTaken94 <121205769+someoneWasTaken94@users.noreply.github.com> Date: Sat, 24 Dec 2022 02:12:28 +0000 Subject: [PATCH 34/48] some new content --- saves/Day 19 Complete.txt | 1 + src/data/layers/boxes.tsx | 37 ++- src/data/layers/elves.tsx | 6 +- .../layers/factory-components/boxmaker.svg | 123 ++++++++ src/data/layers/factory.tsx | 264 +++++++++++++++++- src/data/projEntry.tsx | 4 +- 6 files changed, 418 insertions(+), 17 deletions(-) create mode 100644 saves/Day 19 Complete.txt create mode 100644 src/data/layers/factory-components/boxmaker.svg diff --git a/saves/Day 19 Complete.txt b/saves/Day 19 Complete.txt new file mode 100644 index 0000000..5681eba --- /dev/null +++ b/saves/Day 19 Complete.txt @@ -0,0 +1 @@ +eyJpZCI6ImFkdmVudC1pbmNyZW1lbnRhbC0yIiwiZGV2U3BlZWQiOjAsIm5hbWUiOiJEZWZhdWx0IFNhdmUiLCJ0YWJzIjpbIm1haW4iLCJmYWN0b3J5Il0sInRpbWUiOjE2NzE3NzI2MTQ4MDgsImF1dG9zYXZlIjp0cnVlLCJvZmZsaW5lUHJvZCI6ZmFsc2UsIm9mZmxpbmVUaW1lIjpudWxsLCJ0aW1lUGxheWVkIjo5MzYxNC42NDg1MTkzNzQ1OCwia2VlcEdvaW5nIjpmYWxzZSwibW9kSUQiOiJhZHZlbnQtaW5jcmVtZW50YWwiLCJtb2RWZXJzaW9uIjoiMC41IiwibGF5ZXJzIjp7Im1haW4iOnsibWluaW1pemVkIjpmYWxzZSwiZGF5cyI6eyIwIjp7Im9wZW5lZCI6dHJ1ZSwicmVjZW50bHlVcGRhdGVkIjpmYWxzZX0sIjEiOnsib3BlbmVkIjp0cnVlLCJyZWNlbnRseVVwZGF0ZWQiOmZhbHNlfSwiMiI6eyJvcGVuZWQiOnRydWUsInJlY2VudGx5VXBkYXRlZCI6ZmFsc2V9LCIzIjp7Im9wZW5lZCI6dHJ1ZSwicmVjZW50bHlVcGRhdGVkIjpmYWxzZX0sIjQiOnsib3BlbmVkIjp0cnVlLCJyZWNlbnRseVVwZGF0ZWQiOmZhbHNlfSwiNSI6eyJvcGVuZWQiOnRydWUsInJlY2VudGx5VXBkYXRlZCI6ZmFsc2V9LCI2Ijp7Im9wZW5lZCI6dHJ1ZSwicmVjZW50bHlVcGRhdGVkIjpmYWxzZX0sIjciOnsib3BlbmVkIjp0cnVlLCJyZWNlbnRseVVwZGF0ZWQiOmZhbHNlfSwiOCI6eyJvcGVuZWQiOnRydWUsInJlY2VudGx5VXBkYXRlZCI6ZmFsc2V9LCI5Ijp7Im9wZW5lZCI6dHJ1ZSwicmVjZW50bHlVcGRhdGVkIjpmYWxzZX0sIjEwIjp7Im9wZW5lZCI6dHJ1ZSwicmVjZW50bHlVcGRhdGVkIjpmYWxzZX0sIjExIjp7Im9wZW5lZCI6dHJ1ZSwicmVjZW50bHlVcGRhdGVkIjpmYWxzZX0sIjEyIjp7Im9wZW5lZCI6dHJ1ZSwicmVjZW50bHlVcGRhdGVkIjpmYWxzZX0sIjEzIjp7Im9wZW5lZCI6dHJ1ZSwicmVjZW50bHlVcGRhdGVkIjpmYWxzZX0sIjE0Ijp7Im9wZW5lZCI6dHJ1ZSwicmVjZW50bHlVcGRhdGVkIjpmYWxzZX0sIjE1Ijp7Im9wZW5lZCI6dHJ1ZSwicmVjZW50bHlVcGRhdGVkIjpmYWxzZX0sIjE2Ijp7Im9wZW5lZCI6dHJ1ZSwicmVjZW50bHlVcGRhdGVkIjpmYWxzZX0sIjE3Ijp7Im9wZW5lZCI6dHJ1ZSwicmVjZW50bHlVcGRhdGVkIjpmYWxzZX0sIjE4Ijp7Im9wZW5lZCI6dHJ1ZSwicmVjZW50bHlVcGRhdGVkIjpmYWxzZX0sIjE5Ijp7Im9wZW5lZCI6ZmFsc2UsInJlY2VudGx5VXBkYXRlZCI6ZmFsc2V9LCIyMCI6eyJvcGVuZWQiOmZhbHNlLCJyZWNlbnRseVVwZGF0ZWQiOmZhbHNlfSwiMjEiOnsib3BlbmVkIjpmYWxzZSwicmVjZW50bHlVcGRhdGVkIjpmYWxzZX0sIjIyIjp7Im9wZW5lZCI6ZmFsc2UsInJlY2VudGx5VXBkYXRlZCI6ZmFsc2V9LCIyMyI6eyJvcGVuZWQiOmZhbHNlLCJyZWNlbnRseVVwZGF0ZWQiOmZhbHNlfX0sImRheSI6MjAsImlzTWFzdGVyeSI6ZmFsc2V9LCJ0cmVlcyI6eyJtaW5pbWl6ZWQiOmZhbHNlLCJsb2dzIjoiMi4xMzYyMzY5NzYxMzI2MjNlODIiLCJ0b3RhbExvZ3MiOiIxLjAzMTIyODMwODc2Njc5ZTg0IiwidHJlZXMiOiIxMCIsInNhcGxpbmdzIjoiMy42MzUzNzU0MDA4NDAxNzNlMjkiLCJyb3cxVXBncmFkZXMiOnsiMCI6eyJyZXNvdXJjZSI6IjEwMjg0MzYwNjYxMDguNjU5NCIsImJvdWdodCI6dHJ1ZX0sIjEiOnsicmVzb3VyY2UiOiIxMDI4NDM2MDY2MTA4LjY1OTQiLCJib3VnaHQiOnRydWV9LCIyIjp7InJlc291cmNlIjoiMTAyODQzNjA2NjEwOC42NTk0IiwiYm91Z2h0Ijp0cnVlfSwiMyI6eyJyZXNvdXJjZSI6IjEwMjg0MzYwNjYxMDguNjU5NCIsImJvdWdodCI6dHJ1ZX0sIjQiOnsicmVzb3VyY2UiOiIxMDI4NDM2MDY2MTA4LjY1OTQiLCJib3VnaHQiOnRydWV9fSwicm93MlVwZ3JhZGVzIjp7IjAiOnsicmVzb3VyY2UiOiIxMDI4NDM2MDY2MTA4LjY1OTQiLCJib3VnaHQiOnRydWV9LCIxIjp7InJlc291cmNlIjoiMTAyODQzNjA2NjEwOC42NTk0IiwiYm91Z2h0Ijp0cnVlfSwiMiI6eyJyZXNvdXJjZSI6IjEwMjg0MzYwNjYxMDguNjU5NCIsImJvdWdodCI6dHJ1ZX0sIjMiOnsicmVzb3VyY2UiOiIxMDI4NDM2MDY2MTA4LjY1OTQiLCJib3VnaHQiOnRydWV9LCI0Ijp7InJlc291cmNlIjoiMTAyODQzNjA2NjEwOC42NTk0IiwiYm91Z2h0Ijp0cnVlfX0sInJvdzFCdXlhYmxlcyI6eyIwIjp7InJlc291cmNlIjoiMTAyODQzNjA2NjEwOC42NTk0IiwiYW1vdW50IjoiNDk4NzI5MyJ9LCIxIjp7InJlc291cmNlIjoiMTAyODQzNjA2NjEwOC42NTk0IiwiYW1vdW50IjoiNTEzMjkyNSJ9LCIyIjp7InJlc291cmNlIjoiMTAyODQzNjA2NjEwOC42NTk0IiwiYW1vdW50IjoiMTIxMTE0NzMifX0sIm1hbnVhbEN1dFByb2dyZXNzIjoiMC4wMDAwMDE5MDczNDg2MzI4MTI0OTk0IiwibWFudWFsUGxhbnRQcm9ncmVzcyI6IjAuMDAwMDAxOTA3MzQ4NjMyODEyNDk5NCIsImdlbmVyYWxUYWJDb2xsYXBzZWQiOnt9LCJjcmVhdGVkU2FwbGluZ3MiOiIzLjgyOTExMTMxNzQ5MjUxMmUyOSIsIm1hc3RlcnkiOnsibG9ncyI6IjQuODcyMTUyNjU1NTIxNDA4ZTIzIiwidG90YWxMb2dzIjoiNC45MjgzMzg4NDA0MDEzMmUyMyIsInNhcGxpbmdzIjoiNjUzNzUwNTI3NDgzNjguODMiLCJyb3cxVXBncmFkZXMiOnsiMCI6eyJib3VnaHQiOnRydWV9LCIxIjp7ImJvdWdodCI6dHJ1ZX0sIjIiOnsiYm91Z2h0Ijp0cnVlfSwiMyI6eyJib3VnaHQiOnRydWV9LCI0Ijp7ImJvdWdodCI6dHJ1ZX19LCJyb3cyVXBncmFkZXMiOnsiMCI6eyJib3VnaHQiOnRydWV9LCIxIjp7ImJvdWdodCI6dHJ1ZX0sIjIiOnsiYm91Z2h0Ijp0cnVlfSwiMyI6eyJib3VnaHQiOnRydWV9LCI0Ijp7ImJvdWdodCI6dHJ1ZX19LCJyb3cxQnV5YWJsZXMiOnsiMCI6eyJhbW91bnQiOiIxMTMyOTUifSwiMSI6eyJhbW91bnQiOiIxMTMyOTUifSwiMiI6eyJhbW91bnQiOiIzMzU4MjcifX0sImNyZWF0ZWRTYXBsaW5ncyI6IjY1Mzc1ODM1MDc3MjAxLjUxNiJ9LCJtYXN0ZXJlZCI6dHJ1ZX0sIndvcmtzaG9wIjp7Im1pbmltaXplZCI6ZmFsc2UsImZvdW5kYXRpb25Qcm9ncmVzcyI6IjEzNTQiLCJmb3VuZGF0aW9uQ29udmVyc2lvbiI6eyJiYXNlUmVzb3VyY2UiOiIxMDI4NDM2MDY2MTA4LjY1OTQiLCJnYWluUmVzb3VyY2UiOiIxMDAifSwibWlsZXN0b25lcyI6eyJsb2dHYWluTWlsZXN0b25lMSI6eyJlYXJuZWQiOnRydWV9LCJhdXRvQ3V0TWlsZXN0b25lMSI6eyJlYXJuZWQiOnRydWV9LCJhdXRvUGxhbnRNaWxlc3RvbmUxIjp7ImVhcm5lZCI6dHJ1ZX0sImF1dG9DdXRNaWxlc3RvbmUyIjp7ImVhcm5lZCI6dHJ1ZX0sImF1dG9QbGFudE1pbGVzdG9uZTIiOnsiZWFybmVkIjp0cnVlfSwibG9nR2Fpbk1pbGVzdG9uZTIiOnsiZWFybmVkIjp0cnVlfSwibW9yZVBsYW50c01pbGVzdG9uZTEiOnsiZWFybmVkIjp0cnVlfSwibG9nR2Fpbk1pbGVzdG9uZTMiOnsiZWFybmVkIjp0cnVlfSwiZXh0cmFFeHBhbnNpb25NaWxlc3RvbmUxIjp7ImVhcm5lZCI6dHJ1ZX0sImV4dHJhRXhwYW5zaW9uTWlsZXN0b25lMiI6eyJlYXJuZWQiOnRydWV9LCJleHRyYUV4cGFuc2lvbk1pbGVzdG9uZTMiOnsiZWFybmVkIjp0cnVlfSwiZXh0cmFFeHBhbnNpb25NaWxlc3RvbmU0Ijp7ImVhcm5lZCI6dHJ1ZX0sImV4dHJhRXhwYW5zaW9uTWlsZXN0b25lNSI6eyJlYXJuZWQiOnRydWV9LCJleHRyYUV4cGFuc2lvbk1pbGVzdG9uZTYiOnsiZWFybmVkIjp0cnVlfSwiZXh0cmFFeHBhbnNpb25NaWxlc3RvbmU3Ijp7ImVhcm5lZCI6ZmFsc2V9fSwiY29sbGFwc2VNaWxlc3RvbmVzIjp0cnVlLCJtYXN0ZXJ5Ijp7ImZvdW5kYXRpb25Qcm9ncmVzcyI6IjEwMCIsIm1pbGVzdG9uZXMiOnsibG9nR2Fpbk1pbGVzdG9uZTEiOnsiZWFybmVkIjp0cnVlfSwiYXV0b0N1dE1pbGVzdG9uZTEiOnsiZWFybmVkIjp0cnVlfSwiYXV0b1BsYW50TWlsZXN0b25lMSI6eyJlYXJuZWQiOnRydWV9LCJhdXRvQ3V0TWlsZXN0b25lMiI6eyJlYXJuZWQiOnRydWV9LCJhdXRvUGxhbnRNaWxlc3RvbmUyIjp7ImVhcm5lZCI6dHJ1ZX0sImxvZ0dhaW5NaWxlc3RvbmUyIjp7ImVhcm5lZCI6dHJ1ZX0sIm1vcmVQbGFudHNNaWxlc3RvbmUxIjp7ImVhcm5lZCI6dHJ1ZX0sImxvZ0dhaW5NaWxlc3RvbmUzIjp7ImVhcm5lZCI6dHJ1ZX0sImV4dHJhRXhwYW5zaW9uTWlsZXN0b25lMSI6eyJlYXJuZWQiOmZhbHNlfSwiZXh0cmFFeHBhbnNpb25NaWxlc3RvbmUyIjp7ImVhcm5lZCI6ZmFsc2V9LCJleHRyYUV4cGFuc2lvbk1pbGVzdG9uZTMiOnsiZWFybmVkIjpmYWxzZX0sImV4dHJhRXhwYW5zaW9uTWlsZXN0b25lNCI6eyJlYXJuZWQiOmZhbHNlfSwiZXh0cmFFeHBhbnNpb25NaWxlc3RvbmU1Ijp7ImVhcm5lZCI6ZmFsc2V9fX0sIm1hc3RlcmVkIjp0cnVlLCJnZW5lcmFsVGFiQ29sbGFwc2VkIjp7fX0sImNvYWwiOnsibWluaW1pemVkIjpmYWxzZSwiY29hbCI6IjIuMzkxMTMyNzQwMjI2MTE3ZTE0NiIsInRvdGFsQ29hbCI6IjIuMzkxMTMyNzQwMjU0NzUzM2UxNDYiLCJhc2giOiIyLjQ0NTc4NzkwNTg1NjY1MzRlMTEyIiwiYWN0aXZlRmlyZXMiOiIwIiwiYnVpbGRGaXJlIjp7InJlc291cmNlIjoiMTAyODQzNjA2NjEwOC42NTk0IiwiYW1vdW50IjoiMCJ9LCJhY3RpdmVCb25maXJlcyI6IjIuMTY0MjExODE5NTY3MTQ2NWUyNCIsImJ1aWxkQm9uZmlyZSI6eyJyZXNvdXJjZSI6MCwiYW1vdW50IjoiMi4xNjQyMTE4MTk1NjcxNDY1ZTI0In0sImFjdGl2ZUtpbG5zIjoiNzA5NCIsImJ1aWxkS2lsbiI6eyJyZXNvdXJjZSI6IjEwMjg0MzYwNjYxMDguNjU5NCIsImFtb3VudCI6IjcwOTQifSwid2FybWVyQ3V0dGVycyI6eyJyZXNvdXJjZSI6Ijc3NzQ3ODk5NzY1LjQ4Mzc4IiwiYm91Z2h0Ijp0cnVlfSwid2FybWVyUGxhbnRlcnMiOnsicmVzb3VyY2UiOiI3Nzc0Nzg5OTc2NS40ODM3OCIsImJvdWdodCI6dHJ1ZX0sImJhc2ljRmVydGlsaXplciI6eyJyZXNvdXJjZSI6IjE0NTY4ODI2IiwiYm91Z2h0Ijp0cnVlfSwidW5sb2NrQm9uZmlyZSI6eyJyZXNvdXJjZSI6MCwiYm91Z2h0Ijp0cnVlfSwiZGVkaWNhdGVkQ3V0dGVycyI6eyJyZXNvdXJjZSI6Ijc3NzQ3ODk5NzY1LjQ4Mzc4IiwiYm91Z2h0Ijp0cnVlfSwiZGVkaWNhdGVkUGxhbnRlcnMiOnsicmVzb3VyY2UiOiI3Nzc0Nzg5OTc2NS40ODM3OCIsImJvdWdodCI6dHJ1ZX0sImJldHRlckZlcnRpbGl6ZXIiOnsiYm91Z2h0Ijp0cnVlfSwidW5sb2NrS2lsbiI6eyJyZXNvdXJjZSI6IjEwMjg0MzYwNjYxMDguNjU5NCIsImJvdWdodCI6dHJ1ZX0sImhlYXRlZEN1dHRlcnMiOnsicmVzb3VyY2UiOiI3Nzc0Nzg5OTc2NS40ODM3OCIsImFtb3VudCI6IjIxMDUzOTU4NTE2NjgifSwiaGVhdGVkUGxhbnRlcnMiOnsicmVzb3VyY2UiOiI3Nzc0Nzg5OTc2NS40ODM3OCIsImFtb3VudCI6IjIxMDUzOTU4NTE2NjgifSwibW9yZUZlcnRpbGl6ZXIiOnsicmVzb3VyY2UiOiIxNDU2ODgyNiIsImFtb3VudCI6IjEwNjc4ODQ1NjkwNDk2MSJ9LCJnZW5lcmFsVGFiQ29sbGFwc2VkIjp7fSwiYWN0aXZlRHJpbGxzIjoiMzkzOSIsImJ1aWxkRHJpbGwiOnsiYW1vdW50IjoiMzkzOSJ9LCJlZmZpY2llbnRTbWVsdGhlciI6eyJyZXNvdXJjZSI6IjEuMzM2NDc3NzkxMzI4MjUyZTE3IiwiYm91Z2h0Ijp0cnVlfSwiYXJzb25pc3RBc3Npc3RhbmNlIjp7ImJvdWdodCI6dHJ1ZX0sInJlZmluZWRDb2FsIjp7ImJvdWdodCI6dHJ1ZX0sImNvbG9yZWRGaXJlIjp7ImJvdWdodCI6dHJ1ZX0sIm1hc3RlcnkiOnsiY29hbCI6IjkuMDYyODExNzY3MjA3NTQ1ZTMzIiwidG90YWxDb2FsIjoiOS4wNjg5MjI4NzgzMTg1MzVlMzMiLCJhc2giOiIyLjY3NTI0MzQ3ODczMjE4OGUxNyIsImFjdGl2ZUZpcmVzIjoiMTA2MS44ODUzODU0NzU1Mjk4IiwiYnVpbGRGaXJlIjp7ImFtb3VudCI6IjEwNjEuODg1Mzg1NDc1NTI5OCJ9LCJhY3RpdmVCb25maXJlcyI6IjIwMDUwMyIsImJ1aWxkQm9uZmlyZSI6eyJhbW91bnQiOiIyMDA1MDMifSwiYWN0aXZlS2lsbnMiOiI2NzEiLCJidWlsZEtpbG4iOnsiYW1vdW50IjoiNjcxIn0sImFjdGl2ZURyaWxscyI6IjE2NSIsImJ1aWxkRHJpbGwiOnsiYW1vdW50IjoiMTY1In0sIndhcm1lckN1dHRlcnMiOnsiYm91Z2h0Ijp0cnVlfSwid2FybWVyUGxhbnRlcnMiOnsiYm91Z2h0Ijp0cnVlfSwiYmFzaWNGZXJ0aWxpemVyIjp7ImJvdWdodCI6dHJ1ZX0sInVubG9ja0JvbmZpcmUiOnsiYm91Z2h0Ijp0cnVlfSwiZGVkaWNhdGVkQ3V0dGVycyI6eyJib3VnaHQiOnRydWV9LCJkZWRpY2F0ZWRQbGFudGVycyI6eyJib3VnaHQiOnRydWV9LCJiZXR0ZXJGZXJ0aWxpemVyIjp7ImJvdWdodCI6dHJ1ZX0sInVubG9ja0tpbG4iOnsiYm91Z2h0Ijp0cnVlfSwiZWZmaWNpZW50U21lbHRoZXIiOnsiYm91Z2h0Ijp0cnVlfSwiYXJzb25pc3RBc3Npc3RhbmNlIjp7ImJvdWdodCI6ZmFsc2V9LCJyZWZpbmVkQ29hbCI6eyJib3VnaHQiOmZhbHNlfSwiY29sb3JlZEZpcmUiOnsiYm91Z2h0IjpmYWxzZX0sImhlYXRlZEN1dHRlcnMiOnsiYW1vdW50IjoiOTc5OCJ9LCJoZWF0ZWRQbGFudGVycyI6eyJhbW91bnQiOiI5Nzk4In0sIm1vcmVGZXJ0aWxpemVyIjp7ImFtb3VudCI6IjI1MzUifX0sIm1hc3RlcmVkIjp0cnVlfSwiZWx2ZXMiOnsibWluaW1pemVkIjpmYWxzZSwiZWx2ZXMiOnsiY3V0dGVyc0VsZiI6eyJidXlQcm9ncmVzcyI6IjAuMDAwODU0NTMxODcwODkxNjAwNSIsInJlc291cmNlIjoiNzc3NDc4OTk3NjUuNDgzNzgiLCJib3VnaHQiOnRydWUsImJ1eWFibGUiOnsicmVzb3VyY2UiOiIxMDI4NDM2MDY2MTA4LjY1OTQiLCJhbW91bnQiOiIzMTk4In0sImFtb3VudE9mVGltZXNEb25lIjowLjc5MjAwMDAwMDU3OTc5NzR9LCJwbGFudGVyc0VsZiI6eyJidXlQcm9ncmVzcyI6IjAuMDAwMjI2NjQyNTE5MzA0MzIwOSIsInJlc291cmNlIjoiNzc3NDc4OTk3NjUuNDgzNzgiLCJib3VnaHQiOnRydWUsImJ1eWFibGUiOnsicmVzb3VyY2UiOiIxMDI4NDM2MDY2MTA4LjY1OTQiLCJhbW91bnQiOiIzMTk4In0sImFtb3VudE9mVGltZXNEb25lIjowLjYyNDAwMDAwMDU4MTk1MX0sImV4cGFuZGVyc0VsZiI6eyJidXlQcm9ncmVzcyI6IjAuMDAxMTgzMzY4MDk4MTI3NjA3MyIsInJlc291cmNlIjoiNzc3NDc4OTk3NjUuNDgzNzgiLCJib3VnaHQiOnRydWUsImJ1eWFibGUiOnsicmVzb3VyY2UiOiIxMDI4NDM2MDY2MTA4LjY1OTQiLCJhbW91bnQiOiI3Mzc5In0sImFtb3VudE9mVGltZXNEb25lIjowLjYxMjAwMDAwMDU3OTUwNjN9LCJoZWF0ZWRDdXR0ZXJzRWxmIjp7ImJ1eVByb2dyZXNzIjoiMC4wMDAyMDcwNDIzOTgwMTM0NDYxNSIsInJlc291cmNlIjoiNzc3NDc4OTk3NjUuNDgzNzgiLCJib3VnaHQiOnRydWUsImJ1eWFibGUiOnsicmVzb3VyY2UiOiI3Nzc0Nzg5OTc2NS40ODM3OCIsImFtb3VudCI6IjI3MCJ9LCJhbW91bnRPZlRpbWVzRG9uZSI6MC4xODgwMDAwMDA1ODAwNzUyN30sImhlYXRlZFBsYW50ZXJzRWxmIjp7ImJ1eVByb2dyZXNzIjoiMC4wMDA3ODExMjk3NDg2MTkyNTUzIiwicmVzb3VyY2UiOiI3Nzc0Nzg5OTc2NS40ODM3OCIsImJvdWdodCI6dHJ1ZSwiYnV5YWJsZSI6eyJyZXNvdXJjZSI6Ijc3NzQ3ODk5NzY1LjQ4Mzc4IiwiYW1vdW50IjoiMjcwIn0sImFtb3VudE9mVGltZXNEb25lIjowLjk0ODAwMDAwMDU3OTUxOX0sImZlcnRpbGl6ZXJFbGYiOnsiYnV5UHJvZ3Jlc3MiOiIwLjAwMDc3NDM4MDUwODI5NjI4NTEiLCJyZXNvdXJjZSI6Ijc3NzQ3ODk5NzY1LjQ4Mzc4IiwiYm91Z2h0Ijp0cnVlLCJidXlhYmxlIjp7InJlc291cmNlIjoiMTQ1Njg4MjYiLCJhbW91bnQiOiIxMzkifSwiYW1vdW50T2ZUaW1lc0RvbmUiOjAuNzcyMDAwMDAwNTgwNjExNH0sInNtYWxsRmlyZUVsZiI6eyJidXlhYmxlIjp7InJlc291cmNlIjoiMTAyODQzNjA2NjEwOC42NTk0IiwiYW1vdW50IjowfSwidG9nZ2xlIjp0cnVlLCJidXlQcm9ncmVzcyI6IjAuMDAwOTE2MDE3MzQyMjk1MjExMSIsInJlc291cmNlIjoiNzc3NDc4OTk3NjUuNDgzNzgiLCJib3VnaHQiOnRydWUsImFtb3VudE9mVGltZXNEb25lIjowLjA1MjAwMDAwMDU4MDI1MDExNn0sImJvbmZpcmVFbGYiOnsiYnV5YWJsZSI6eyJyZXNvdXJjZSI6MCwiYW1vdW50IjowfSwidG9nZ2xlIjp0cnVlLCJidXlQcm9ncmVzcyI6IjAuMDAwNzM5MTM2MjY0NzI0MjQzOSIsInJlc291cmNlIjoiNzc3NDc4OTk3NjUuNDgzNzgiLCJib3VnaHQiOnRydWUsImFtb3VudE9mVGltZXNEb25lIjowLjU3NjAwMDAwMDU3NzUxNTR9LCJraWxuRWxmIjp7ImJ1eWFibGUiOnsicmVzb3VyY2UiOiIxMDI4NDM2MDY2MTA4LjY1OTQiLCJhbW91bnQiOiIxMDIifSwidG9nZ2xlIjp0cnVlLCJidXlQcm9ncmVzcyI6IjAuMDAwNDgyMDY5NzA3MjQ1NTQxNTUiLCJyZXNvdXJjZSI6Ijc3NzQ3ODk5NzY1LjQ4Mzc4IiwiYm91Z2h0Ijp0cnVlLCJhbW91bnRPZlRpbWVzRG9uZSI6MC4xNTIwMDAwMDA1Nzk1OTA3M30sInBhcGVyRWxmIjp7ImJ1eVByb2dyZXNzIjoiMC4wMDg2MDM4OTYxMDQxMjI2NzYiLCJib3VnaHQiOnRydWUsImFtb3VudE9mVGltZXNEb25lIjowLjYxMjAwMDAwMDAxMzU3MDZ9LCJib3hFbGYiOnsiYnV5UHJvZ3Jlc3MiOiIwLjAxMDAxMTk5ODg3MTU3MjczMiIsImJvdWdodCI6dHJ1ZSwiYW1vdW50T2ZUaW1lc0RvbmUiOjAuODU2MDAwMDAwMDkwNzE1OH0sImNsb3RoRWxmIjp7ImJ1eVByb2dyZXNzIjoiMC4wMDAyOTQ3NDY0NzQwMDAxNTcxIiwiYm91Z2h0Ijp0cnVlLCJhbW91bnRPZlRpbWVzRG9uZSI6MC40ODgwMDAwMDA2MTM0Mzk1fSwibWluaW5nRHJpbGxFbGYiOnsidG9nZ2xlIjpmYWxzZSwiYnV5UHJvZ3Jlc3MiOjAsImFtb3VudE9mVGltZXNEb25lIjowLCJib3VnaHQiOmZhbHNlfSwiaGVhdnlEcmlsbEVsZiI6eyJ0b2dnbGUiOnRydWUsImJ1eVByb2dyZXNzIjoiMC4wMDE0MDMyNzMzOTA4OTE2MDA0IiwiYW1vdW50T2ZUaW1lc0RvbmUiOjAuOTQwMDAwMDAwMzYwMzI4MiwiYm91Z2h0Ijp0cnVlfSwib2lsRWxmIjp7InRvZ2dsZSI6dHJ1ZSwiYnV5UHJvZ3Jlc3MiOiIwLjAwMDE4MzA4MTg1MjYxODc1NDk4IiwiYW1vdW50T2ZUaW1lc0RvbmUiOjAuMjA0MDAwMDAwMzU1NDYzODQsImJvdWdodCI6dHJ1ZX0sIm1ldGFsRWxmIjp7ImJ1eVByb2dyZXNzIjoiMC4wMDAxMzMxNTU5MjQ0MzM3NjE1NiIsImFtb3VudE9mVGltZXNEb25lIjowLjE5MjAwMDAwMDM1MzEzMjgsImJvdWdodCI6dHJ1ZX0sImNvYWxEcmlsbEVsZiI6eyJ0b2dnbGUiOnRydWUsImJ1eVByb2dyZXNzIjoiMC4wMDE0MDM1Mjg2Njk1NjI2OTExIiwiYW1vdW50T2ZUaW1lc0RvbmUiOjAuODQwMDAwMDAwMzY5MDg3NywiYm91Z2h0Ijp0cnVlfSwiZHllRWxmIjp7ImJ1eVByb2dyZXNzIjoiMC4wMDAwMTgzMjY3NTMzMDUzMTk5NjUiLCJhbW91bnRPZlRpbWVzRG9uZSI6MC41NDAwMDAwMDAzODQ4NzE3LCJib3VnaHQiOnRydWV9LCJwbGFzdGljRWxmIjp7ImJ1eVByb2dyZXNzIjoiMC4wMDA3MzExMjU4NDU5NjY2MDE1IiwiYW1vdW50T2ZUaW1lc0RvbmUiOjAuNTc2MDAwMDAwMzcyODc5MSwiYm91Z2h0Ijp0cnVlfX0sIm1pbGVzdG9uZXMiOnsiMCI6eyJlYXJuZWQiOnRydWV9LCIxIjp7ImVhcm5lZCI6dHJ1ZX0sIjIiOnsiZWFybmVkIjp0cnVlfSwiMyI6eyJlYXJuZWQiOnRydWV9LCI0Ijp7ImVhcm5lZCI6dHJ1ZX0sIjUiOnsiZWFybmVkIjp0cnVlfSwiNiI6eyJlYXJuZWQiOnRydWV9LCI3Ijp7ImVhcm5lZCI6dHJ1ZX0sIjgiOnsiZWFybmVkIjp0cnVlfSwiOSI6eyJlYXJuZWQiOnRydWV9LCIxMCI6eyJlYXJuZWQiOnRydWV9LCIxMSI6eyJlYXJuZWQiOnRydWV9fSwiZ2VuZXJhbFRhYkNvbGxhcHNlZCI6e30sImNvbGxhcHNlTWlsZXN0b25lcyI6ZmFsc2UsIm1hc3RlcnkiOnsiZWx2ZXMiOnsiY3V0dGVyc0VsZiI6eyJidXlQcm9ncmVzcyI6IjAuMDAwNDEzMTY1NDQyMTQxNzMzIiwiYW1vdW50T2ZUaW1lc0RvbmUiOjEuMDQ1OTE4OTA3MDM4ODY3NWUtMTEsImJvdWdodCI6dHJ1ZX0sInBsYW50ZXJzRWxmIjp7ImJ1eVByb2dyZXNzIjoiMC4wMDQxNzg1NTI0MDQ0NzY4NzEiLCJhbW91bnRPZlRpbWVzRG9uZSI6MC40MDgwMDAwMDAwMTI1MjEsImJvdWdodCI6dHJ1ZX0sImV4cGFuZGVyc0VsZiI6eyJidXlQcm9ncmVzcyI6IjAuMDA0MjE1MDIxNzM5Mzc4MTU1IiwiYW1vdW50T2ZUaW1lc0RvbmUiOjAuNzk0MDAwMDAwMDA3NTM1OCwiYm91Z2h0Ijp0cnVlfSwiaGVhdGVkQ3V0dGVyc0VsZiI6eyJidXlQcm9ncmVzcyI6IjAuMDAxNTAzODI5ODkyODI3NDM1MiIsImFtb3VudE9mVGltZXNEb25lIjowLjMwMjAwMDAwMDA0NjQ2MiwiYm91Z2h0Ijp0cnVlfSwiaGVhdGVkUGxhbnRlcnNFbGYiOnsiYnV5UHJvZ3Jlc3MiOiIwLjAwMjU5OTc3NjUwOTM1ODYwOSIsImFtb3VudE9mVGltZXNEb25lIjowLjcyNjAwMDAwMDA0OTc5MzksImJvdWdodCI6dHJ1ZX0sImZlcnRpbGl6ZXJFbGYiOnsiYnV5UHJvZ3Jlc3MiOiIwLjAwMjIzMzY2NzA0MzEyMDI4IiwiYW1vdW50T2ZUaW1lc0RvbmUiOjAuNTkyMDAwMDAwMDQ3Nzg5OSwiYm91Z2h0Ijp0cnVlfSwic21hbGxGaXJlRWxmIjp7ImJ1eVByb2dyZXNzIjoiMC4wMDI4NzMwNjA4NjYwMzAzNDE0IiwiYW1vdW50T2ZUaW1lc0RvbmUiOjAuODc2MDAwMDAwMDQ5MjAyOCwidG9nZ2xlIjp0cnVlLCJib3VnaHQiOnRydWV9LCJib25maXJlRWxmIjp7ImJ1eVByb2dyZXNzIjoiMC4wMDE3MjczNjIwMzk4MTEyMiIsImFtb3VudE9mVGltZXNEb25lIjowLjI1ODAwMDAwMDA0OTg4OTksInRvZ2dsZSI6dHJ1ZSwiYm91Z2h0Ijp0cnVlfSwia2lsbkVsZiI6eyJidXlQcm9ncmVzcyI6IjAuMDAxNTMzODU1Mjk4NTQwOTk4MSIsImFtb3VudE9mVGltZXNEb25lIjowLjY5NDAwMDAwMDA1MDAzOSwidG9nZ2xlIjp0cnVlLCJib3VnaHQiOnRydWV9LCJwYXBlckVsZiI6eyJidXlQcm9ncmVzcyI6IjAuMDAwODQyMDg2ODM0NzQ2MjA4NSIsImFtb3VudE9mVGltZXNEb25lIjowLjg4MDAwMDAwMDAwMDg4NTQsImJvdWdodCI6dHJ1ZX0sImJveEVsZiI6eyJidXlQcm9ncmVzcyI6IjAuMDA1Mjk0MTE3NjQ3MDcyNTc3IiwiYW1vdW50T2ZUaW1lc0RvbmUiOjAuMzA0MDAwMDAwMDAwOTMyODYsImJvdWdodCI6dHJ1ZX0sImNsb3RoRWxmIjp7ImJ1eVByb2dyZXNzIjoiMC4wMDM4NjI1MDk4MTkwNzU0MDUiLCJhbW91bnRPZlRpbWVzRG9uZSI6MC40MzIwMDAwMDAwMDIyMzMyNiwiYm91Z2h0Ijp0cnVlfSwiY29hbERyaWxsRWxmIjp7ImJ1eVByb2dyZXNzIjoiMC4wMTE0NTQ1NDU0NTQ1NDUyNzMiLCJhbW91bnRPZlRpbWVzRG9uZSI6MC41MDM5OTk5OTk5OTk4ODc2LCJ0b2dnbGUiOnRydWUsImJvdWdodCI6dHJ1ZX0sImhlYXZ5RHJpbGxFbGYiOnsiYnV5UHJvZ3Jlc3MiOiIwLjAxMTQ1NDU0NTQ1NDU0NTI3MyIsImFtb3VudE9mVGltZXNEb25lIjowLjUwMzk5OTk5OTk5OTg4NzYsInRvZ2dsZSI6dHJ1ZSwiYm91Z2h0Ijp0cnVlfSwib2lsRWxmIjp7ImJ1eVByb2dyZXNzIjoiMC4wMTE0NTQ1NDU0NTQ1NDUyNzMiLCJhbW91bnRPZlRpbWVzRG9uZSI6MC41MDM5OTk5OTk5OTk4ODc2LCJ0b2dnbGUiOnRydWUsImJvdWdodCI6dHJ1ZX0sIm1ldGFsRWxmIjp7ImJ1eVByb2dyZXNzIjoiMC4wMTE0NTQ1NDU0NTQ1NDUyNzMiLCJhbW91bnRPZlRpbWVzRG9uZSI6MC41MDM5OTk5OTk5OTk4ODc2LCJib3VnaHQiOnRydWV9LCJkeWVFbGYiOnsiYnV5UHJvZ3Jlc3MiOjAsImFtb3VudE9mVGltZXNEb25lIjowLCJib3VnaHQiOmZhbHNlfSwicGxhc3RpY0VsZiI6eyJidXlQcm9ncmVzcyI6IjAuMDAzNTMzNzA0NDcxMDYxNjA1IiwiYW1vdW50T2ZUaW1lc0RvbmUiOjAuOTQwMDAwMDAwMDAwNzkzNSwiYm91Z2h0Ijp0cnVlfX0sIm1pbGVzdG9uZXMiOnsiMCI6eyJlYXJuZWQiOnRydWV9LCIxIjp7ImVhcm5lZCI6dHJ1ZX0sIjIiOnsiZWFybmVkIjp0cnVlfSwiMyI6eyJlYXJuZWQiOnRydWV9LCI0Ijp7ImVhcm5lZCI6dHJ1ZX0sIjUiOnsiZWFybmVkIjp0cnVlfSwiNiI6eyJlYXJuZWQiOnRydWV9LCI3Ijp7ImVhcm5lZCI6dHJ1ZX0sIjgiOnsiZWFybmVkIjp0cnVlfSwiOSI6eyJlYXJuZWQiOnRydWV9LCIxMCI6eyJlYXJuZWQiOnRydWV9LCIxMSI6eyJlYXJuZWQiOnRydWV9fX19LCJwYXBlciI6eyJtaW5pbWl6ZWQiOmZhbHNlLCJwYXBlciI6IjguNTc5NDkxNjcwODU4MjQ2ZTEwMSIsInRvdGFsUGFwZXIiOiI4LjU3OTQ5MTk0MTY4MzAxM2UxMDEiLCJwYXBlckNvbnZlcnNpb24iOnsiZ2FpblJlc291cmNlIjoiNDA2OS45OTk5OTk5OTk5OTkifSwiYm9va3MiOnsiY3V0dGVyc0Jvb2siOnsicmVzb3VyY2UiOiI0MDY5Ljk5OTk5OTk5OTk5OSIsImFtb3VudCI6IjE4MSJ9LCJwbGFudGVyc0Jvb2siOnsicmVzb3VyY2UiOiI0MDY5Ljk5OTk5OTk5OTk5OSIsImFtb3VudCI6IjE4MSJ9LCJleHBhbmRlcnNCb29rIjp7InJlc291cmNlIjoiNDA2OS45OTk5OTk5OTk5OTkiLCJhbW91bnQiOiIxODEifSwiaGVhdGVkQ3V0dGVyc0Jvb2siOnsicmVzb3VyY2UiOiI0MDY5Ljk5OTk5OTk5OTk5OSIsImFtb3VudCI6IjE4MSJ9LCJoZWF0ZWRQbGFudGVyc0Jvb2siOnsicmVzb3VyY2UiOiI0MDY5Ljk5OTk5OTk5OTk5OSIsImFtb3VudCI6IjE4MSJ9LCJmZXJ0aWxpemVyQm9vayI6eyJyZXNvdXJjZSI6IjQwNjkuOTk5OTk5OTk5OTk5IiwiYW1vdW50IjoiMTgxIn0sInNtYWxsRmlyZUJvb2siOnsicmVzb3VyY2UiOiI0MDY5Ljk5OTk5OTk5OTk5OSIsImFtb3VudCI6IjE4MSJ9LCJib25maXJlQm9vayI6eyJyZXNvdXJjZSI6IjQwNjkuOTk5OTk5OTk5OTk5IiwiYW1vdW50IjoiMTgxIn0sImtpbG5Cb29rIjp7InJlc291cmNlIjoiNDA2OS45OTk5OTk5OTk5OTkiLCJhbW91bnQiOiIxODEifSwicGFwZXJCb29rIjp7ImFtb3VudCI6IjEyIn0sImJveEJvb2siOnsiYW1vdW50IjoiMTQifSwiY2xvdGhCb29rIjp7ImFtb3VudCI6IjE4MSJ9LCJtaW5pbmdEcmlsbEJvb2siOnsiYW1vdW50IjowfSwiaGVhdnlEcmlsbEJvb2siOnsiYW1vdW50IjoiMTUyIn0sIm9pbEJvb2siOnsiYW1vdW50IjoiMTUyIn0sIm1ldGFsQm9vayI6eyJhbW91bnQiOiIxNTIifSwiY29hbERyaWxsQm9vayI6eyJhbW91bnQiOiIxNTIifSwiZHllQm9vayI6eyJhbW91bnQiOjB9LCJwcmltYXJ5RHllQm9vayI6eyJhbW91bnQiOiIxODEifSwic2Vjb25kYXJ5RHllQm9vayI6eyJhbW91bnQiOiIxODEifSwicGxhc3RpY0Jvb2siOnsiYW1vdW50IjoiMTgxIn19LCJnZW5lcmFsVGFiQ29sbGFwc2VkIjp7fSwidXBncmFkZXMiOnsiY2xvdGhVcGdyYWRlIjp7ImJvdWdodCI6dHJ1ZX0sImRyaWxsaW5nVXBncmFkZSI6eyJib3VnaHQiOnRydWV9LCJvaWxVcGdyYWRlIjp7ImJvdWdodCI6dHJ1ZX19LCJ1cGdyYWRlczIiOnsiYXNoVXBncmFkZSI6eyJib3VnaHQiOnRydWV9LCJib29rVXBncmFkZSI6eyJib3VnaHQiOnRydWV9LCJjbGFzc3Jvb21VcGdyYWRlIjp7ImJvdWdodCI6ZmFsc2V9LCJ0cmVlVXBncmFkZSI6eyJib3VnaHQiOnRydWV9fSwibWFzdGVyeSI6eyJwYXBlciI6IjMuMjM0ODcyNDA0NzQyMDQ5ZTIzIiwidG90YWxQYXBlciI6IjMuMjM0ODc1MzAxNTIyMjY3OGUyMyIsImJvb2tzIjp7ImN1dHRlcnNCb29rIjp7ImFtb3VudCI6IjQ3In0sInBsYW50ZXJzQm9vayI6eyJhbW91bnQiOiI0NyJ9LCJleHBhbmRlcnNCb29rIjp7ImFtb3VudCI6IjQ3In0sImhlYXRlZEN1dHRlcnNCb29rIjp7ImFtb3VudCI6IjQ3In0sImhlYXRlZFBsYW50ZXJzQm9vayI6eyJhbW91bnQiOiI0NyJ9LCJmZXJ0aWxpemVyQm9vayI6eyJhbW91bnQiOiI0NyJ9LCJzbWFsbEZpcmVCb29rIjp7ImFtb3VudCI6IjQ3In0sImJvbmZpcmVCb29rIjp7ImFtb3VudCI6IjQ3In0sImtpbG5Cb29rIjp7ImFtb3VudCI6IjQ3In0sInBhcGVyQm9vayI6eyJhbW91bnQiOiI3In0sImJveEJvb2siOnsiYW1vdW50IjoiNyJ9LCJjbG90aEJvb2siOnsiYW1vdW50IjoiNDcifSwiY29hbERyaWxsQm9vayI6eyJhbW91bnQiOiIxIn0sImhlYXZ5RHJpbGxCb29rIjp7ImFtb3VudCI6IjEifSwib2lsQm9vayI6eyJhbW91bnQiOiIxIn0sIm1ldGFsQm9vayI6eyJhbW91bnQiOiIxIn0sInByaW1hcnlEeWVCb29rIjp7ImFtb3VudCI6MH0sInNlY29uZGFyeUR5ZUJvb2siOnsiYW1vdW50IjowfSwicGxhc3RpY0Jvb2siOnsiYW1vdW50IjoiNDcifX0sInVwZ3JhZGVzIjp7ImNsb3RoVXBncmFkZSI6eyJib3VnaHQiOnRydWV9LCJkcmlsbGluZ1VwZ3JhZGUiOnsiYm91Z2h0Ijp0cnVlfSwib2lsVXBncmFkZSI6eyJib3VnaHQiOnRydWV9fSwidXBncmFkZXMyIjp7ImFzaFVwZ3JhZGUiOnsiYm91Z2h0IjpmYWxzZX0sImJvb2tVcGdyYWRlIjp7ImJvdWdodCI6ZmFsc2V9LCJ0cmVlVXBncmFkZSI6eyJib3VnaHQiOmZhbHNlfX19LCJtYXN0ZXJlZCI6dHJ1ZX0sImJveGVzIjp7Im1pbmltaXplZCI6ZmFsc2UsImJveGVzIjoiMS4wMDI5MjExMzg4Nzk1NTMxZTg4IiwidG90YWxCb3hlcyI6IjEuMDEzMDg3ODAzNTIyNTc4OGU4OCIsImJveGVzQ29udmVyc2lvbiI6eyJiYXNlUmVzb3VyY2UiOiIxMDI4NDM2MDY2MTA4LjY1OTQiLCJnYWluUmVzb3VyY2UiOjB9LCJ1cGdyYWRlcyI6eyJsb2dzVXBncmFkZSI6eyJyZXNvdXJjZSI6MCwiYm91Z2h0Ijp0cnVlfSwiYXNoVXBncmFkZSI6eyJyZXNvdXJjZSI6MCwiYm91Z2h0Ijp0cnVlfSwiY29hbFVwZ3JhZGUiOnsicmVzb3VyY2UiOjAsImJvdWdodCI6dHJ1ZX19LCJidXlhYmxlcyI6eyJsb2dCb3hlc0J1eWFibGUiOnsicmVzb3VyY2UiOjAsImFtb3VudCI6IjY3NCJ9LCJhc2hCb3hlc0J1eWFibGUiOnsicmVzb3VyY2UiOjAsImFtb3VudCI6IjMwMyJ9LCJjb2FsQm94ZXNCdXlhYmxlIjp7InJlc291cmNlIjowLCJhbW91bnQiOiIyMzQifX0sInJvdzJVcGdyYWRlcyI6eyJvcmVVcGdyYWRlIjp7ImJvdWdodCI6dHJ1ZX0sIm1ldGFsVXBncmFkZSI6eyJib3VnaHQiOnRydWV9LCJwbGFzdGljVXBncmFkZSI6eyJib3VnaHQiOnRydWV9fSwicm93M1VwZ3JhZGVzIjp7ImNsb3RoVXBncmFkZSI6eyJib3VnaHQiOnRydWV9LCJkeWVVcGdyYWRlIjp7ImJvdWdodCI6dHJ1ZX0sInhwVXBncmFkZSI6eyJib3VnaHQiOnRydWV9fSwiZ2VuZXJhbFRhYkNvbGxhcHNlZCI6e30sImJ1eWFibGVzMiI6eyJvcmVCb3hlc0J1eWFibGUiOnsiYW1vdW50IjoiMTY0In0sIm1ldGFsQm94ZXNCdXlhYmxlIjp7ImFtb3VudCI6IjExNSJ9LCJwbGFzdGljQm94ZXNCdXlhYmxlIjp7ImFtb3VudCI6Ijk4In19LCJtYXN0ZXJ5Ijp7ImJveGVzIjoiNi4wMTQ5MDk4Nzg1NzU0MjllMTYiLCJ0b3RhbEJveGVzIjoiNi4wMTQ5MTM1Mjc1NDAxMzFlMTYiLCJ1cGdyYWRlcyI6eyJsb2dzVXBncmFkZSI6eyJib3VnaHQiOnRydWV9LCJhc2hVcGdyYWRlIjp7ImJvdWdodCI6dHJ1ZX0sImNvYWxVcGdyYWRlIjp7ImJvdWdodCI6dHJ1ZX19LCJyb3cyVXBncmFkZXMiOnsib3JlVXBncmFkZSI6eyJib3VnaHQiOnRydWV9LCJtZXRhbFVwZ3JhZGUiOnsiYm91Z2h0Ijp0cnVlfSwicGxhc3RpY1VwZ3JhZGUiOnsiYm91Z2h0Ijp0cnVlfX0sInJvdzNVcGdyYWRlcyI6eyJjbG90aFVwZ3JhZGUiOnsiYm91Z2h0IjpmYWxzZX0sImR5ZVVwZ3JhZGUiOnsiYm91Z2h0IjpmYWxzZX0sInhwVXBncmFkZSI6eyJib3VnaHQiOmZhbHNlfX0sImJ1eWFibGVzIjp7ImxvZ0JveGVzQnV5YWJsZSI6eyJhbW91bnQiOiI0NyJ9LCJhc2hCb3hlc0J1eWFibGUiOnsiYW1vdW50IjoiMzAifSwiY29hbEJveGVzQnV5YWJsZSI6eyJhbW91bnQiOiIyNSJ9fSwiYnV5YWJsZXMyIjp7Im9yZUJveGVzQnV5YWJsZSI6eyJhbW91bnQiOjB9LCJtZXRhbEJveGVzQnV5YWJsZSI6eyJhbW91bnQiOjB9LCJwbGFzdGljQm94ZXNCdXlhYmxlIjp7ImFtb3VudCI6MH19fSwibWFzdGVyZWQiOnRydWV9LCJtZXRhbCI6eyJtaW5pbWl6ZWQiOmZhbHNlLCJvcmUiOiIxLjY5NzYwNDY2ODE1MTE2NWUzMCIsImJlc3RPcmUiOiIxLjkwNjY4ODY5NjE2NDc1MjdlMzAiLCJvcmVQcm9ncmVzcyI6IjAuMTM3Nzk3NDE3NjgwNjc2NjYiLCJtZXRhbCI6IjYuMTY1NjU5NTU4ODMyMTYyNWU1NyIsImJlc3RNZXRhbCI6IjYuMTY1NjU5NTU4ODMyMTYyNWU1NyIsInRvdGFsTWV0YWwiOiI2LjE4OTkzNDIwNjYyMDg3NGU1NyIsInNpbXBsZVBpY2theGUiOnsiYm91Z2h0Ijp0cnVlfSwiZG91YmxlUGlja2F4ZSI6eyJib3VnaHQiOmZhbHNlfSwiY3J1Y2libGUiOnsiYm91Z2h0Ijp0cnVlfSwiY29hbERyaWxsIjp7ImJvdWdodCI6dHJ1ZX0sImluZHVzdHJpYWxGdXJuYWNlIjp7ImJvdWdodCI6dHJ1ZX0sIm9yZURyaWxsIjp7ImFtb3VudCI6IjI0MTYyNzAifSwiaW5kdXN0cmlhbENydWNpYmxlIjp7ImFtb3VudCI6IjI0MTYyNyJ9LCJhdXRvU21lbHRFbmFibGVkIjp0cnVlLCJob3R0ZXJGb3JnZSI6eyJhbW91bnQiOiIzMzUzNzkifSwiZ2VuZXJhbFRhYkNvbGxhcHNlZCI6e30sImVmZmljaWVudERyaWxsIjp7ImJvdWdodCI6dHJ1ZX0sIm1hc3RlcnkiOnsib3JlIjoiOTI3NTcyMTIwLjQ0MjYzNjUiLCJiZXN0T3JlIjoiMTk1MzMwOTAwNy4wNDQwOTgiLCJvcmVQcm9ncmVzcyI6IjAuNTMxMDMxMjY2MTM4MjM0NiIsIm1ldGFsIjoiMy42NTMyMjkxOTUxMTEwNGUxNiIsImJlc3RNZXRhbCI6IjMuNjUzMjI5MTk1MTExMDRlMTYiLCJ0b3RhbE1ldGFsIjoiMy42NTMyNTcwMzA2MzI0MDVlMTYiLCJzaW1wbGVQaWNrYXhlIjp7ImJvdWdodCI6dHJ1ZX0sImRvdWJsZVBpY2theGUiOnsiYm91Z2h0IjpmYWxzZX0sImNydWNpYmxlIjp7ImJvdWdodCI6dHJ1ZX0sImNvYWxEcmlsbCI6eyJib3VnaHQiOnRydWV9LCJpbmR1c3RyaWFsRnVybmFjZSI6eyJib3VnaHQiOnRydWV9LCJlZmZpY2llbnREcmlsbCI6eyJib3VnaHQiOnRydWV9LCJvcmVEcmlsbCI6eyJhbW91bnQiOiIyNzAifSwiaW5kdXN0cmlhbENydWNpYmxlIjp7ImFtb3VudCI6IjI3In0sImhvdHRlckZvcmdlIjp7ImFtb3VudCI6IjI0In19LCJtYXN0ZXJlZCI6dHJ1ZX0sImNsb3RoIjp7Im1pbmltaXplZCI6ZmFsc2UsImNsb3RoIjoiMi40MDQ3MTIyOTgzNTczMjY0ZTE3IiwidG90YWxDbG90aCI6IjcuNTU0ODk3MDI4MDQzODYxZTE3Iiwid29vbCI6IjEuOTg1MTYxNjY5NDM2MzA1ZTE3Iiwic2hlZXAiOiIyLjAzMTY1MTU3ODUyMzYxN2UxNyIsImJ1aWxkUGVucyI6eyJhbW91bnQiOiIyMDQzOSJ9LCJiZXR0ZXJTaGVhcnMiOnsiYW1vdW50IjoiMTk5MDcifSwiZmFzdGVyU3Bpbm5pbmciOnsiYW1vdW50IjoiMjk5NzAifSwidHJlZXNVcGdyYWRlcyI6eyJ0cmVlc1VwZ3JhZGUzIjp7ImJvdWdodCI6dHJ1ZX0sInRyZWVzVXBncmFkZTIiOnsiYm91Z2h0Ijp0cnVlfSwidHJlZXNVcGdyYWRlMSI6eyJib3VnaHQiOnRydWV9LCJ0cmVlc1VwZ3JhZGU0Ijp7ImJvdWdodCI6dHJ1ZX19LCJtZXRhbFVwZ3JhZGVzIjp7Im1ldGFsVXBncmFkZTMiOnsiYm91Z2h0Ijp0cnVlfSwibWV0YWxVcGdyYWRlMiI6eyJib3VnaHQiOnRydWV9LCJtZXRhbFVwZ3JhZGUxIjp7ImJvdWdodCI6dHJ1ZX0sIm1ldGFsVXBncmFkZTQiOnsiYm91Z2h0Ijp0cnVlfX0sInBhcGVyVXBncmFkZXMiOnsicGFwZXJVcGdyYWRlMyI6eyJib3VnaHQiOnRydWV9LCJwYXBlclVwZ3JhZGUyIjp7ImJvdWdodCI6dHJ1ZX0sInBhcGVyVXBncmFkZTEiOnsiYm91Z2h0Ijp0cnVlfSwicGFwZXJVcGdyYWRlNCI6eyJib3VnaHQiOnRydWV9fSwiZ2VuZXJhbFRhYkNvbGxhcHNlZCI6e30sImJyZWVkaW5nUHJvZ3Jlc3MiOjEsInNoZWFyaW5nUHJvZ3Jlc3MiOjEsInNwaW5uaW5nUHJvZ3Jlc3MiOjEsIm1hc3RlcnkiOnsiY2xvdGgiOiIxMTE0NTEiLCJ0b3RhbENsb3RoIjoiMTE4OTAxIiwid29vbCI6IjYyMzIwIiwic2hlZXAiOiI3NjQwMyIsImJ1aWxkUGVucyI6eyJhbW91bnQiOiIyNDgifSwiYmV0dGVyU2hlYXJzIjp7ImFtb3VudCI6IjMxMCJ9LCJmYXN0ZXJTcGlubmluZyI6eyJhbW91bnQiOiI0MTQifSwidHJlZXNVcGdyYWRlcyI6eyJ0cmVlc1VwZ3JhZGUxIjp7ImJvdWdodCI6dHJ1ZX0sInRyZWVzVXBncmFkZTIiOnsiYm91Z2h0Ijp0cnVlfSwidHJlZXNVcGdyYWRlMyI6eyJib3VnaHQiOnRydWV9LCJ0cmVlc1VwZ3JhZGU0Ijp7ImJvdWdodCI6dHJ1ZX19LCJtZXRhbFVwZ3JhZGVzIjp7Im1ldGFsVXBncmFkZTEiOnsiYm91Z2h0Ijp0cnVlfSwibWV0YWxVcGdyYWRlMiI6eyJib3VnaHQiOnRydWV9LCJtZXRhbFVwZ3JhZGUzIjp7ImJvdWdodCI6dHJ1ZX0sIm1ldGFsVXBncmFkZTQiOnsiYm91Z2h0Ijp0cnVlfX0sInBhcGVyVXBncmFkZXMiOnsicGFwZXJVcGdyYWRlMSI6eyJib3VnaHQiOnRydWV9LCJwYXBlclVwZ3JhZGUyIjp7ImJvdWdodCI6dHJ1ZX0sInBhcGVyVXBncmFkZTMiOnsiYm91Z2h0Ijp0cnVlfSwicGFwZXJVcGdyYWRlNCI6eyJib3VnaHQiOnRydWV9fX0sIm1hc3RlcmVkIjp0cnVlfSwib2lsIjp7Im1pbmltaXplZCI6ZmFsc2UsIm9pbCI6IjEuODk0NzU3NTQ1MDA4MzQ0N2UyNCIsInRvdGFsT2lsIjoiNS4yNzk0NzA5ODE3NDc4MThlMjQiLCJkZXB0aCI6IjEwNDAxMyIsImRyaWxsUHJvZ3Jlc3MiOiIxLjc0NTc1NDgwOTE5NjIwNGU0NyIsImFjdGl2ZUhlYXZ5IjoiMTAzNCIsImJ1aWxkSGVhdnkiOnsiYW1vdW50IjoiMTAzNCJ9LCJhY3RpdmVIZWF2eTIiOiI0ODEiLCJidWlsZEhlYXZ5MiI6eyJhbW91bnQiOiI0ODEifSwiYWN0aXZlRXh0cmFjdG9yIjoiMTEwIiwiYnVpbGRFeHRyYWN0b3IiOnsiYW1vdW50IjoiMTEwIn0sImFjdGl2ZVB1bXAiOiIxMDQiLCJidWlsZFB1bXAiOnsiYW1vdW50IjoiMTA0In0sImFjdGl2ZUJ1cm5lciI6IjY1NCIsImJ1aWxkQnVybmVyIjp7ImFtb3VudCI6IjY1NCJ9LCJhY3RpdmVTbWVsdGVyIjoiMzY4IiwiYnVpbGRTbWVsdGVyIjp7ImFtb3VudCI6IjM2OCJ9LCJkZXB0aE1pbGVzdG9uZXMiOnsiMCI6eyJlYXJuZWQiOnRydWV9LCIxIjp7ImVhcm5lZCI6dHJ1ZX0sIjIiOnsiZWFybmVkIjp0cnVlfSwiMyI6eyJlYXJuZWQiOnRydWV9LCI0Ijp7ImVhcm5lZCI6dHJ1ZX0sIjUiOnsiZWFybmVkIjp0cnVlfSwiNiI6eyJlYXJuZWQiOnRydWV9LCI3Ijp7ImVhcm5lZCI6dHJ1ZX19LCJjb2xsYXBzZWREZXB0aE1pbGVzdG9uZXMiOnRydWUsInJvdzFVcGdyYWRlcyI6eyIwIjp7ImJvdWdodCI6dHJ1ZX0sIjEiOnsiYm91Z2h0Ijp0cnVlfSwiMiI6eyJib3VnaHQiOnRydWV9LCIzIjp7ImJvdWdodCI6dHJ1ZX0sIjQiOnsiYm91Z2h0Ijp0cnVlfX0sInJvdzJVcGdyYWRlcyI6eyIwIjp7ImJvdWdodCI6dHJ1ZX0sIjEiOnsiYm91Z2h0Ijp0cnVlfSwiMiI6eyJib3VnaHQiOnRydWV9LCIzIjp7ImJvdWdodCI6dHJ1ZX0sIjQiOnsiYm91Z2h0Ijp0cnVlfX0sImdlbmVyYWxUYWJDb2xsYXBzZWQiOnt9LCJvaWxNaWxlc3RvbmVzIjp7IjAiOnsiZWFybmVkIjp0cnVlfSwiMSI6eyJlYXJuZWQiOnRydWV9LCIyIjp7ImVhcm5lZCI6dHJ1ZX19LCJjb2xsYXBzZWRPaWxNaWxlc3RvbmVzIjp0cnVlLCJyb3czVXBncmFkZXMiOnsiMCI6eyJib3VnaHQiOnRydWV9LCIxIjp7ImJvdWdodCI6dHJ1ZX0sIjIiOnsiYm91Z2h0Ijp0cnVlfSwiMyI6eyJib3VnaHQiOnRydWV9LCI0Ijp7ImJvdWdodCI6dHJ1ZX19LCJtYXN0ZXJ5Ijp7Im9pbCI6IjUwODA2MDY5MS44MzU4MzA2IiwidG90YWxPaWwiOiI1MTE0MTQ2NDEuODM1ODMwNiIsImRlcHRoIjoiMjMwOTMiLCJkcmlsbFByb2dyZXNzIjoiMTM1NTcyNTUyMzE2NC43ODEyIiwiYWN0aXZlSGVhdnkiOiIxMDMiLCJidWlsZEhlYXZ5Ijp7ImFtb3VudCI6IjEwMyJ9LCJhY3RpdmVIZWF2eTIiOiI0MSIsImJ1aWxkSGVhdnkyIjp7ImFtb3VudCI6IjQxIn0sImFjdGl2ZUV4dHJhY3RvciI6IjExIiwiYnVpbGRFeHRyYWN0b3IiOnsiYW1vdW50IjoiMTEifSwiYWN0aXZlUHVtcCI6IjExIiwiYnVpbGRQdW1wIjp7ImFtb3VudCI6IjExIn0sImFjdGl2ZUJ1cm5lciI6IjI1IiwiYnVpbGRCdXJuZXIiOnsiYW1vdW50IjoiMjUifSwiYWN0aXZlU21lbHRlciI6IjEyIiwiYnVpbGRTbWVsdGVyIjp7ImFtb3VudCI6IjEyIn0sImRlcHRoTWlsZXN0b25lcyI6eyIwIjp7ImVhcm5lZCI6dHJ1ZX0sIjEiOnsiZWFybmVkIjp0cnVlfSwiMiI6eyJlYXJuZWQiOnRydWV9LCIzIjp7ImVhcm5lZCI6dHJ1ZX0sIjQiOnsiZWFybmVkIjp0cnVlfSwiNSI6eyJlYXJuZWQiOnRydWV9LCI2Ijp7ImVhcm5lZCI6dHJ1ZX0sIjciOnsiZWFybmVkIjp0cnVlfX0sIm9pbE1pbGVzdG9uZXMiOnsiMCI6eyJlYXJuZWQiOnRydWV9LCIxIjp7ImVhcm5lZCI6dHJ1ZX0sIjIiOnsiZWFybmVkIjp0cnVlfX0sInJvdzFVcGdyYWRlcyI6eyIwIjp7ImJvdWdodCI6dHJ1ZX0sIjEiOnsiYm91Z2h0Ijp0cnVlfSwiMiI6eyJib3VnaHQiOnRydWV9LCIzIjp7ImJvdWdodCI6dHJ1ZX0sIjQiOnsiYm91Z2h0Ijp0cnVlfX0sInJvdzJVcGdyYWRlcyI6eyIwIjp7ImJvdWdodCI6dHJ1ZX0sIjEiOnsiYm91Z2h0Ijp0cnVlfSwiMiI6eyJib3VnaHQiOnRydWV9LCIzIjp7ImJvdWdodCI6dHJ1ZX0sIjQiOnsiYm91Z2h0Ijp0cnVlfX0sInJvdzNVcGdyYWRlcyI6eyIwIjp7ImJvdWdodCI6ZmFsc2V9LCIxIjp7ImJvdWdodCI6ZmFsc2V9LCIyIjp7ImJvdWdodCI6ZmFsc2V9LCIzIjp7ImJvdWdodCI6ZmFsc2V9LCI0Ijp7ImJvdWdodCI6ZmFsc2V9fX0sIm1hc3RlcmVkIjp0cnVlfSwicGxhc3RpYyI6eyJtaW5pbWl6ZWQiOmZhbHNlLCJwbGFzdGljIjoiMy41NzAzNTU0NzkyOTMyNTNlMjEiLCJ0b3RhbFBsYXN0aWMiOiI0LjQ3NTgxODg1NDM1Njk1N2UyMSIsImJ1aWxkUmVmaW5lcnkiOnsiYW1vdW50IjoiNTQ0In0sImFjdGl2ZVJlZmluZXJ5IjoiNTQ0IiwidXBncmFkZXMiOnsicGFwZXJUb29scyI6eyJib3VnaHQiOnRydWV9LCJib3hUb29scyI6eyJib3VnaHQiOnRydWV9LCJjbG90aFRvb2xzIjp7ImJvdWdodCI6dHJ1ZX19LCJlbGZVcGdyYWRlcyI6eyJwYXBlckVsZiI6eyJib3VnaHQiOnRydWV9LCJib3hFbGYiOnsiYm91Z2h0Ijp0cnVlfSwiY2xvdGhFbGYiOnsiYm91Z2h0Ijp0cnVlfX0sImJ1eWFibGVzIjp7InBhc3NpdmVQYXBlciI6eyJhbW91bnQiOiIyODEwOTE2In0sInBhc3NpdmVCb3hlcyI6eyJhbW91bnQiOiIyODEwOTE2In0sImNsb3RoR2FpbnMiOnsiYW1vdW50IjoiMjgxMDkxNiJ9fSwiZ2VuZXJhbFRhYkNvbGxhcHNlZCI6e30sIm1hc3RlcnkiOnsicGxhc3RpYyI6IjE2NDAwNzAuNDUyMjMyOTEyIiwidG90YWxQbGFzdGljIjoiMTY2MTkxMC40NTIyMzI5MTIiLCJhY3RpdmVSZWZpbmVyeSI6IjQ2IiwiYnVpbGRSZWZpbmVyeSI6eyJhbW91bnQiOiI0NiJ9LCJ1cGdyYWRlcyI6eyJwYXBlclRvb2xzIjp7ImJvdWdodCI6dHJ1ZX0sImJveFRvb2xzIjp7ImJvdWdodCI6dHJ1ZX0sImNsb3RoVG9vbHMiOnsiYm91Z2h0Ijp0cnVlfX0sImVsZlVwZ3JhZGVzIjp7InBhcGVyRWxmIjp7ImJvdWdodCI6dHJ1ZX0sImJveEVsZiI6eyJib3VnaHQiOnRydWV9LCJjbG90aEVsZiI6eyJib3VnaHQiOnRydWV9fSwiYnV5YWJsZXMiOnsicGFzc2l2ZVBhcGVyIjp7ImFtb3VudCI6IjY2MSJ9LCJwYXNzaXZlQm94ZXMiOnsiYW1vdW50IjoiNjYxIn0sImNsb3RoR2FpbnMiOnsiYW1vdW50IjoiNjYxIn19fSwibWFzdGVyZWQiOnRydWV9LCJkeWVzIjp7Im1pbmltaXplZCI6ZmFsc2UsImR5ZXMiOnsicmVkIjp7ImFtb3VudCI6Ijc2Mjc5ODMyNzU3Ljg5OTE5IiwiYnV5YWJsZSI6eyJhbW91bnQiOiIxMjE3In19LCJ5ZWxsb3ciOnsiYW1vdW50IjoiMTg4OTIyNDg3Mzg2LjcwOTc1IiwiYnV5YWJsZSI6eyJhbW91bnQiOiIxMTY1In19LCJibHVlIjp7ImFtb3VudCI6IjI1NzI2MjcyNTg4LjYxNjM5IiwiYnV5YWJsZSI6eyJhbW91bnQiOiIxMTE2In19LCJvcmFuZ2UiOnsiYW1vdW50IjoiNDE1NzYiLCJidXlhYmxlIjp7ImFtb3VudCI6IjgxMCJ9fSwiZ3JlZW4iOnsiYW1vdW50IjoiMzIxOTYiLCJidXlhYmxlIjp7ImFtb3VudCI6IjY5OSJ9fSwicHVycGxlIjp7ImFtb3VudCI6IjMwMzIwIiwiYnV5YWJsZSI6eyJhbW91bnQiOiI2ODEifX0sImJsYWNrIjp7ImJ1eWFibGUiOnsiYW1vdW50IjoiMjMwIn19LCJ3aGl0ZSI6eyJidXlhYmxlIjp7ImFtb3VudCI6IjIzMCJ9fX0sImdlbmVyYWxUYWJDb2xsYXBzZWQiOnt9LCJ1cGdyYWRlcyI6eyJibHVlRHllVXBnIjp7ImJvdWdodCI6dHJ1ZX0sInJlZER5ZVVwZyI6eyJib3VnaHQiOnRydWV9LCJ5ZWxsb3dEeWVVcGciOnsiYm91Z2h0Ijp0cnVlfSwieWVsbG93RHllVXBnMiI6eyJib3VnaHQiOnRydWV9LCJyZWREeWVVcGcyIjp7ImJvdWdodCI6dHJ1ZX0sImJsdWVEeWVVcGcyIjp7ImJvdWdodCI6dHJ1ZX0sImNvYWxVcGciOnsiYm91Z2h0Ijp0cnVlfX0sIm1hc3RlcnkiOnsiZHllcyI6eyJyZWQiOnsiYW1vdW50IjowLCJidXlhYmxlIjp7ImFtb3VudCI6IjE1In19LCJncmVlbiI6eyJhbW91bnQiOjAsImJ1eWFibGUiOnsiYW1vdW50IjoiNSJ9fSwiYmx1ZSI6eyJhbW91bnQiOjAsImJ1eWFibGUiOnsiYW1vdW50IjoiMTQifX0sInllbGxvdyI6eyJhbW91bnQiOjAsImJ1eWFibGUiOnsiYW1vdW50IjoiMTIifX0sInB1cnBsZSI6eyJhbW91bnQiOjAsImJ1eWFibGUiOnsiYW1vdW50IjoiNCJ9fSwib3JhbmdlIjp7ImFtb3VudCI6MCwiYnV5YWJsZSI6eyJhbW91bnQiOiI0In19fSwidXBncmFkZXMiOnsiYmx1ZUR5ZVVwZyI6eyJib3VnaHQiOnRydWV9LCJyZWREeWVVcGciOnsiYm91Z2h0Ijp0cnVlfSwieWVsbG93RHllVXBnIjp7ImJvdWdodCI6dHJ1ZX0sInllbGxvd0R5ZVVwZzIiOnsiYm91Z2h0Ijp0cnVlfSwicmVkRHllVXBnMiI6eyJib3VnaHQiOnRydWV9LCJibHVlRHllVXBnMiI6eyJib3VnaHQiOnRydWV9LCJjb2FsVXBnIjp7ImJvdWdodCI6dHJ1ZX19fSwibWFzdGVyZWQiOnRydWV9LCJtYW5hZ2VtZW50Ijp7Im1pbmltaXplZCI6ZmFsc2UsImVsZlRyYWluaW5nIjp7ImN1dHRlckVsZlRyYWluaW5nIjp7InN0YXRlIjp0cnVlLCJleHAiOiIzMTI3NDY4LjIyOTc1OTUwMTgiLCJtaWxlc3RvbmVzIjp7IjAiOnsiZWFybmVkIjp0cnVlfSwiMSI6eyJlYXJuZWQiOnRydWV9LCIyIjp7ImVhcm5lZCI6dHJ1ZX0sIjMiOnsiZWFybmVkIjp0cnVlfSwiNCI6eyJlYXJuZWQiOnRydWV9fX0sInBsYW50ZXJFbGZUcmFpbmluZyI6eyJzdGF0ZSI6dHJ1ZSwiZXhwIjoiNjI0ODQ1Ni4yMTU2NjA1NCIsIm1pbGVzdG9uZXMiOnsiMCI6eyJlYXJuZWQiOnRydWV9LCIxIjp7ImVhcm5lZCI6dHJ1ZX0sIjIiOnsiZWFybmVkIjp0cnVlfSwiMyI6eyJlYXJuZWQiOnRydWV9LCI0Ijp7ImVhcm5lZCI6dHJ1ZX19fSwiZXhwYW5kZXJzRWxmVHJhaW5pbmciOnsic3RhdGUiOmZhbHNlLCJleHAiOiI5Mzc2NDUxLjQzODk2MTQ0MyIsIm1pbGVzdG9uZXMiOnsiMCI6eyJlYXJuZWQiOnRydWV9LCIxIjp7ImVhcm5lZCI6dHJ1ZX0sIjIiOnsiZWFybmVkIjp0cnVlfSwiMyI6eyJlYXJuZWQiOnRydWV9LCI0Ijp7ImVhcm5lZCI6dHJ1ZX19fSwiaGVhdGVkQ3V0dGVyRWxmVHJhaW5pbmciOnsic3RhdGUiOnRydWUsImV4cCI6IjEyNDk2MzI3LjM5NTk2NDYxNSIsIm1pbGVzdG9uZXMiOnsiMCI6eyJlYXJuZWQiOnRydWV9LCIxIjp7ImVhcm5lZCI6dHJ1ZX0sIjIiOnsiZWFybmVkIjp0cnVlfSwiMyI6eyJlYXJuZWQiOnRydWV9LCI0Ijp7ImVhcm5lZCI6dHJ1ZX19fSwiaGVhdGVkUGxhbnRlckVsZlRyYWluaW5nIjp7InN0YXRlIjp0cnVlLCJleHAiOiIxNTYyMzk4My4yMDc5NDI2MyIsIm1pbGVzdG9uZXMiOnsiMCI6eyJlYXJuZWQiOnRydWV9LCIxIjp7ImVhcm5lZCI6dHJ1ZX0sIjIiOnsiZWFybmVkIjp0cnVlfSwiMyI6eyJlYXJuZWQiOnRydWV9LCI0Ijp7ImVhcm5lZCI6dHJ1ZX19fSwiZmVydGlsaXplckVsZlRyYWluaW5nIjp7InN0YXRlIjp0cnVlLCJleHAiOiIxODc4MDg4Mi45MTMyNTQxMiIsIm1pbGVzdG9uZXMiOnsiMCI6eyJlYXJuZWQiOnRydWV9LCIxIjp7ImVhcm5lZCI6dHJ1ZX0sIjIiOnsiZWFybmVkIjp0cnVlfSwiMyI6eyJlYXJuZWQiOnRydWV9LCI0Ijp7ImVhcm5lZCI6dHJ1ZX19fSwic21hbGxmaXJlRWxmVHJhaW5pbmciOnsic3RhdGUiOnRydWUsImV4cCI6IjIxOTA3NDkzLjM5MDE1MzU0NiIsIm1pbGVzdG9uZXMiOnsiMCI6eyJlYXJuZWQiOnRydWV9LCIxIjp7ImVhcm5lZCI6dHJ1ZX0sIjIiOnsiZWFybmVkIjp0cnVlfSwiMyI6eyJlYXJuZWQiOnRydWV9LCI0Ijp7ImVhcm5lZCI6dHJ1ZX19fSwiYm9uZmlyZUVsZlRyYWluaW5nIjp7InN0YXRlIjp0cnVlLCJleHAiOiIyNTAwNjQzNi4wMzM4ODIzMjciLCJtaWxlc3RvbmVzIjp7IjAiOnsiZWFybmVkIjp0cnVlfSwiMSI6eyJlYXJuZWQiOnRydWV9LCIyIjp7ImVhcm5lZCI6dHJ1ZX0sIjMiOnsiZWFybmVkIjp0cnVlfSwiNCI6eyJlYXJuZWQiOnRydWV9fX0sImZpcmVFbGZUcmFpbmluZyI6eyIyIjp7InN0YXRlIjp0cnVlLCJleHAiOjB9fSwia2lsbkVsZlRyYWluaW5nIjp7InN0YXRlIjp0cnVlLCJleHAiOiIyODE5MzUwNy43OTA3MTA5ODIiLCJtaWxlc3RvbmVzIjp7IjAiOnsiZWFybmVkIjp0cnVlfSwiMSI6eyJlYXJuZWQiOnRydWV9LCIyIjp7ImVhcm5lZCI6dHJ1ZX0sIjMiOnsiZWFybmVkIjp0cnVlfSwiNCI6eyJlYXJuZWQiOnRydWV9fX0sInBhcGVyRWxmVHJhaW5pbmciOnsic3RhdGUiOnRydWUsImV4cCI6IjEwNDMwOTA0LjQ2MzY2NDMwNiIsIm1pbGVzdG9uZXMiOnsiMCI6eyJlYXJuZWQiOnRydWV9LCIxIjp7ImVhcm5lZCI6dHJ1ZX0sIjIiOnsiZWFybmVkIjp0cnVlfSwiMyI6eyJlYXJuZWQiOnRydWV9LCI0Ijp7ImVhcm5lZCI6dHJ1ZX19fSwiYm94RWxmVHJhaW5pbmciOnsic3RhdGUiOmZhbHNlLCJleHAiOiIxMTQ3MDIyNC41MDQ5ODIzNDUiLCJtaWxlc3RvbmVzIjp7IjAiOnsiZWFybmVkIjp0cnVlfSwiMSI6eyJlYXJuZWQiOnRydWV9LCIyIjp7ImVhcm5lZCI6dHJ1ZX0sIjMiOnsiZWFybmVkIjp0cnVlfSwiNCI6eyJlYXJuZWQiOnRydWV9fX0sImNsb3RoRWxmVHJhaW5pbmciOnsic3RhdGUiOmZhbHNlLCJleHAiOiIzNzQ4OTM1NS4wNDcwMTA3NSIsIm1pbGVzdG9uZXMiOnsiMCI6eyJlYXJuZWQiOnRydWV9LCIxIjp7ImVhcm5lZCI6dHJ1ZX0sIjIiOnsiZWFybmVkIjp0cnVlfSwiMyI6eyJlYXJuZWQiOnRydWV9LCI0Ijp7ImVhcm5lZCI6dHJ1ZX19fSwiY29hbERyaWxsRWxmVHJhaW5pbmciOnsic3RhdGUiOmZhbHNlLCJleHAiOiI0MDYyMzY4NS4wNDA5MTI3NCIsIm1pbGVzdG9uZXMiOnsiMCI6eyJlYXJuZWQiOnRydWV9LCIxIjp7ImVhcm5lZCI6dHJ1ZX0sIjIiOnsiZWFybmVkIjp0cnVlfSwiMyI6eyJlYXJuZWQiOnRydWV9LCI0Ijp7ImVhcm5lZCI6dHJ1ZX19fSwibWV0YWxFbGZUcmFpbmluZyI6eyJzdGF0ZSI6ZmFsc2UsImV4cCI6IjUwMDQ2MDI3Ljk5OTYwOTU4IiwibWlsZXN0b25lcyI6eyIwIjp7ImVhcm5lZCI6dHJ1ZX0sIjEiOnsiZWFybmVkIjp0cnVlfSwiMiI6eyJlYXJuZWQiOnRydWV9LCIzIjp7ImVhcm5lZCI6dHJ1ZX0sIjQiOnsiZWFybmVkIjp0cnVlfX19LCJvaWxFbGZUcmFpbmluZyI6eyJzdGF0ZSI6ZmFsc2UsImV4cCI6IjQ2ODYwMzcxLjU0ODQxMTg3NiIsIm1pbGVzdG9uZXMiOnsiMCI6eyJlYXJuZWQiOnRydWV9LCIxIjp7ImVhcm5lZCI6dHJ1ZX0sIjIiOnsiZWFybmVkIjp0cnVlfSwiMyI6eyJlYXJuZWQiOnRydWV9LCI0Ijp7ImVhcm5lZCI6dHJ1ZX19fSwiaGVhdnlEcmlsbEVsZlRyYWluaW5nIjp7InN0YXRlIjpmYWxzZSwiZXhwIjoiNDM3Mzk3MzUuNjE1MTU0MzkiLCJtaWxlc3RvbmVzIjp7IjAiOnsiZWFybmVkIjp0cnVlfSwiMSI6eyJlYXJuZWQiOnRydWV9LCIyIjp7ImVhcm5lZCI6dHJ1ZX0sIjMiOnsiZWFybmVkIjp0cnVlfSwiNCI6eyJlYXJuZWQiOnRydWV9fX0sImR5ZUVsZlRyYWluaW5nIjp7InN0YXRlIjpmYWxzZSwiZXhwIjoiNTMxMjc0MDAuNjQ3NjM2MTUiLCJtaWxlc3RvbmVzIjp7IjAiOnsiZWFybmVkIjp0cnVlfSwiMSI6eyJlYXJuZWQiOnRydWV9LCIyIjp7ImVhcm5lZCI6dHJ1ZX0sIjMiOnsiZWFybmVkIjp0cnVlfSwiNCI6eyJlYXJuZWQiOnRydWV9fX0sInBsYXN0aWNFbGZUcmFpbmluZyI6eyJzdGF0ZSI6ZmFsc2UsImV4cCI6IjU2MzQyNzcwLjQ1NjgxNTUyIiwibWlsZXN0b25lcyI6eyIwIjp7ImVhcm5lZCI6dHJ1ZX0sIjEiOnsiZWFybmVkIjp0cnVlfSwiMiI6eyJlYXJuZWQiOnRydWV9LCIzIjp7ImVhcm5lZCI6dHJ1ZX0sIjQiOnsiZWFybmVkIjp0cnVlfX19fSwiY3VycmVudFNob3duIjoiVGluc2VsIiwiZ2VuZXJhbFRhYkNvbGxhcHNlZCI6e30sInRlYWNoaW5nIjp7ImJvdWdodCI6dHJ1ZX0sInNjaG9vbHMiOnsiYW1vdW50IjoiNSJ9LCJjbGFzc3Jvb21zIjp7ImFtb3VudCI6IjEwNDYifSwiY2xhc3Nyb29tVXBncmFkZSI6eyJib3VnaHQiOnRydWV9LCJmb2N1c011bHRpcGxpZXIiOiIxLjAwNjE1NzgzMjc4NzQ5ODciLCJ1cGdyYWRlcyI6eyIwIjp7ImJvdWdodCI6dHJ1ZX0sIjEiOnsiYm91Z2h0Ijp0cnVlfSwiMiI6eyJib3VnaHQiOnRydWV9fSwiZm9jdXNUYXJnZXRzIjp7fSwiZm9jdXNDb29sZG93biI6MCwiZm9jdXNUaW1lIjowLCJhZHZhbmNlZFVwZ3JhZGUiOnsiYm91Z2h0Ijp0cnVlfSwidXBncmFkZXMyIjp7IjAiOnsiYm91Z2h0Ijp0cnVlfSwiMSI6eyJib3VnaHQiOnRydWV9LCIyIjp7ImJvdWdodCI6dHJ1ZX19LCJmb2N1c011bHRpIjoiMS4xNDM1OTc3ODM1MjYyODk2IiwibWFzdGVyeSI6eyJlbGZUcmFpbmluZyI6eyJib25maXJlRWxmVHJhaW5pbmciOnsiZXhwIjowLCJtaWxlc3RvbmVzIjp7IjAiOnsiZWFybmVkIjpmYWxzZX0sIjEiOnsiZWFybmVkIjpmYWxzZX0sIjIiOnsiZWFybmVkIjpmYWxzZX0sIjMiOnsiZWFybmVkIjpmYWxzZX0sIjQiOnsiZWFybmVkIjpmYWxzZX19fSwiYm94RWxmVHJhaW5pbmciOnsiZXhwIjowLCJtaWxlc3RvbmVzIjp7IjAiOnsiZWFybmVkIjpmYWxzZX0sIjEiOnsiZWFybmVkIjpmYWxzZX0sIjIiOnsiZWFybmVkIjpmYWxzZX0sIjMiOnsiZWFybmVkIjpmYWxzZX0sIjQiOnsiZWFybmVkIjpmYWxzZX19fSwiY2xvdGhFbGZUcmFpbmluZyI6eyJleHAiOjAsIm1pbGVzdG9uZXMiOnsiMCI6eyJlYXJuZWQiOmZhbHNlfSwiMSI6eyJlYXJuZWQiOmZhbHNlfSwiMiI6eyJlYXJuZWQiOmZhbHNlfSwiMyI6eyJlYXJuZWQiOmZhbHNlfSwiNCI6eyJlYXJuZWQiOmZhbHNlfX19LCJjb2FsRHJpbGxFbGZUcmFpbmluZyI6eyJleHAiOjAsIm1pbGVzdG9uZXMiOnsiMCI6eyJlYXJuZWQiOmZhbHNlfSwiMSI6eyJlYXJuZWQiOmZhbHNlfSwiMiI6eyJlYXJuZWQiOmZhbHNlfSwiMyI6eyJlYXJuZWQiOmZhbHNlfSwiNCI6eyJlYXJuZWQiOmZhbHNlfX19LCJjdXR0ZXJFbGZUcmFpbmluZyI6eyJleHAiOjAsIm1pbGVzdG9uZXMiOnsiMCI6eyJlYXJuZWQiOmZhbHNlfSwiMSI6eyJlYXJuZWQiOmZhbHNlfSwiMiI6eyJlYXJuZWQiOmZhbHNlfSwiMyI6eyJlYXJuZWQiOmZhbHNlfSwiNCI6eyJlYXJuZWQiOmZhbHNlfX19LCJleHBhbmRlcnNFbGZUcmFpbmluZyI6eyJleHAiOjAsIm1pbGVzdG9uZXMiOnsiMCI6eyJlYXJuZWQiOmZhbHNlfSwiMSI6eyJlYXJuZWQiOmZhbHNlfSwiMiI6eyJlYXJuZWQiOmZhbHNlfSwiMyI6eyJlYXJuZWQiOmZhbHNlfSwiNCI6eyJlYXJuZWQiOmZhbHNlfX19LCJmZXJ0aWxpemVyRWxmVHJhaW5pbmciOnsiZXhwIjowLCJtaWxlc3RvbmVzIjp7IjAiOnsiZWFybmVkIjpmYWxzZX0sIjEiOnsiZWFybmVkIjpmYWxzZX0sIjIiOnsiZWFybmVkIjpmYWxzZX0sIjMiOnsiZWFybmVkIjpmYWxzZX0sIjQiOnsiZWFybmVkIjpmYWxzZX19fSwiaGVhdGVkQ3V0dGVyRWxmVHJhaW5pbmciOnsiZXhwIjowLCJtaWxlc3RvbmVzIjp7IjAiOnsiZWFybmVkIjpmYWxzZX0sIjEiOnsiZWFybmVkIjpmYWxzZX0sIjIiOnsiZWFybmVkIjpmYWxzZX0sIjMiOnsiZWFybmVkIjpmYWxzZX0sIjQiOnsiZWFybmVkIjpmYWxzZX19fSwiaGVhdGVkUGxhbnRlckVsZlRyYWluaW5nIjp7ImV4cCI6MCwibWlsZXN0b25lcyI6eyIwIjp7ImVhcm5lZCI6ZmFsc2V9LCIxIjp7ImVhcm5lZCI6ZmFsc2V9LCIyIjp7ImVhcm5lZCI6ZmFsc2V9LCIzIjp7ImVhcm5lZCI6ZmFsc2V9LCI0Ijp7ImVhcm5lZCI6ZmFsc2V9fX0sImhlYXZ5RHJpbGxFbGZUcmFpbmluZyI6eyJleHAiOjAsIm1pbGVzdG9uZXMiOnsiMCI6eyJlYXJuZWQiOmZhbHNlfSwiMSI6eyJlYXJuZWQiOmZhbHNlfSwiMiI6eyJlYXJuZWQiOmZhbHNlfSwiMyI6eyJlYXJuZWQiOmZhbHNlfSwiNCI6eyJlYXJuZWQiOmZhbHNlfX19LCJraWxuRWxmVHJhaW5pbmciOnsiZXhwIjowLCJtaWxlc3RvbmVzIjp7IjAiOnsiZWFybmVkIjpmYWxzZX0sIjEiOnsiZWFybmVkIjpmYWxzZX0sIjIiOnsiZWFybmVkIjpmYWxzZX0sIjMiOnsiZWFybmVkIjpmYWxzZX0sIjQiOnsiZWFybmVkIjpmYWxzZX19fSwibWV0YWxFbGZUcmFpbmluZyI6eyJleHAiOjAsIm1pbGVzdG9uZXMiOnsiMCI6eyJlYXJuZWQiOmZhbHNlfSwiMSI6eyJlYXJuZWQiOmZhbHNlfSwiMiI6eyJlYXJuZWQiOmZhbHNlfSwiMyI6eyJlYXJuZWQiOmZhbHNlfSwiNCI6eyJlYXJuZWQiOmZhbHNlfX19LCJvaWxFbGZUcmFpbmluZyI6eyJleHAiOjAsIm1pbGVzdG9uZXMiOnsiMCI6eyJlYXJuZWQiOmZhbHNlfSwiMSI6eyJlYXJuZWQiOmZhbHNlfSwiMiI6eyJlYXJuZWQiOmZhbHNlfSwiMyI6eyJlYXJuZWQiOmZhbHNlfSwiNCI6eyJlYXJuZWQiOmZhbHNlfX19LCJwYXBlckVsZlRyYWluaW5nIjp7ImV4cCI6MCwibWlsZXN0b25lcyI6eyIwIjp7ImVhcm5lZCI6ZmFsc2V9LCIxIjp7ImVhcm5lZCI6ZmFsc2V9LCIyIjp7ImVhcm5lZCI6ZmFsc2V9LCIzIjp7ImVhcm5lZCI6ZmFsc2V9LCI0Ijp7ImVhcm5lZCI6ZmFsc2V9fX0sInBsYW50ZXJFbGZUcmFpbmluZyI6eyJleHAiOjAsIm1pbGVzdG9uZXMiOnsiMCI6eyJlYXJuZWQiOmZhbHNlfSwiMSI6eyJlYXJuZWQiOmZhbHNlfSwiMiI6eyJlYXJuZWQiOmZhbHNlfSwiMyI6eyJlYXJuZWQiOmZhbHNlfSwiNCI6eyJlYXJuZWQiOmZhbHNlfX19LCJzbWFsbGZpcmVFbGZUcmFpbmluZyI6eyJleHAiOjAsIm1pbGVzdG9uZXMiOnsiMCI6eyJlYXJuZWQiOmZhbHNlfSwiMSI6eyJlYXJuZWQiOmZhbHNlfSwiMiI6eyJlYXJuZWQiOmZhbHNlfSwiMyI6eyJlYXJuZWQiOmZhbHNlfSwiNCI6eyJlYXJuZWQiOmZhbHNlfX19LCJkeWVFbGZUcmFpbmluZyI6eyJleHAiOjAsIm1pbGVzdG9uZXMiOnsiMCI6eyJlYXJuZWQiOmZhbHNlfSwiMSI6eyJlYXJuZWQiOmZhbHNlfSwiMiI6eyJlYXJuZWQiOmZhbHNlfSwiMyI6eyJlYXJuZWQiOmZhbHNlfSwiNCI6eyJlYXJuZWQiOmZhbHNlfX19LCJwbGFzdGljRWxmVHJhaW5pbmciOnsiZXhwIjowLCJtaWxlc3RvbmVzIjp7IjAiOnsiZWFybmVkIjpmYWxzZX0sIjEiOnsiZWFybmVkIjpmYWxzZX0sIjIiOnsiZWFybmVkIjpmYWxzZX0sIjMiOnsiZWFybmVkIjpmYWxzZX0sIjQiOnsiZWFybmVkIjpmYWxzZX19fX0sInRlYWNoaW5nIjp7ImJvdWdodCI6ZmFsc2V9LCJzY2hvb2xzIjp7ImFtb3VudCI6MH0sImNsYXNzcm9vbXMiOnsiYW1vdW50IjowfSwiY2xhc3Nyb29tVXBncmFkZSI6eyJib3VnaHQiOmZhbHNlfSwiYWR2YW5jZWRVcGdyYWRlIjp7ImJvdWdodCI6ZmFsc2V9LCJ1cGdyYWRlcyI6eyIwIjp7ImJvdWdodCI6ZmFsc2V9LCIxIjp7ImJvdWdodCI6ZmFsc2V9LCIyIjp7ImJvdWdodCI6ZmFsc2V9fSwidXBncmFkZXMyIjp7IjAiOnsiYm91Z2h0IjpmYWxzZX0sIjEiOnsiYm91Z2h0IjpmYWxzZX0sIjIiOnsiYm91Z2h0IjpmYWxzZX19LCJmb2N1c011bHRpIjoiMS4wMTI2OTg0NzU0MjAxMTg3IiwiZm9jdXNUYXJnZXRzIjp7fSwiZm9jdXNDb29sZG93biI6MCwiZm9jdXNUaW1lIjowfX0sIndyYXBwaW5nUGFwZXIiOnsibWluaW1pemVkIjpmYWxzZSwid3JhcHBpbmdQYXBlciI6eyJjaHJpc3RtYXMiOnsiYnV5YWJsZSI6eyJhbW91bnQiOiI2NyJ9fSwicmFpbmJvdyI6eyJidXlhYmxlIjp7ImFtb3VudCI6IjQ4In19LCJqYXp6eSI6eyJidXlhYmxlIjp7ImFtb3VudCI6IjgzIn19LCJzdW5zaGluZSI6eyJidXlhYmxlIjp7ImFtb3VudCI6IjU3In19LCJvY2VhbiI6eyJidXlhYmxlIjp7ImFtb3VudCI6IjUyIn19LCJiZWFjaCI6eyJidXlhYmxlIjp7ImFtb3VudCI6IjU5In19fSwiZ2VuZXJhbFRhYkNvbGxhcHNlZCI6e30sIm1pbGVzdG9uZXMiOnsicHJpbWFyeUJvb3N0Ijp7ImVhcm5lZCI6ZmFsc2V9LCJzZWNvbmRhcnlCb29zdCI6eyJlYXJuZWQiOmZhbHNlfSwiYnV5TWF4UHJpbWFyeSI6eyJlYXJuZWQiOmZhbHNlfSwic2Vjb25kYXJ5Tm9SZXNldCI6eyJlYXJuZWQiOmZhbHNlfSwiYnV5TWF4U2Vjb25kYXJ5Ijp7ImVhcm5lZCI6ZmFsc2V9LCJ1bmxvY2tEeWVFbGYiOnsiZWFybmVkIjpmYWxzZX19LCJjb2xsYXBzZU1pbGVzdG9uZXMiOnRydWUsInVubG9ja0R5ZUVsZk1pbGVzdG9uZSI6eyJlYXJuZWQiOnRydWV9fSwibGV0dGVycyI6eyJtaW5pbWl6ZWQiOmZhbHNlLCJsZXR0ZXJzIjoiMS4zMDk0ODU0MTMwNTI2MzI2ZTU0IiwidG90YWxMZXR0ZXJzIjoiNi41NDc0MjcwNjUyNjMxNjNlNTQiLCJwcm9jZXNzaW5nUHJvZ3Jlc3MiOiIyLjc5MTQ5MzU1NjEwNTI3NTZlLTI4IiwiYnV5YWJsZXMiOnsibWV0YWxCdXlhYmxlIjp7ImFtb3VudCI6IjEyIn0sInBsYXN0aWNCdXlhYmxlIjp7ImFtb3VudCI6IjIzIn0sInBhcGVyQnV5YWJsZSI6eyJhbW91bnQiOiI0MyJ9fSwibWlsZXN0b25lcyI6eyJhdXRvU21lbHRpbmdNaWxlc3RvbmUiOnsiZWFybmVkIjp0cnVlfSwibWluaW5nTWlsZXN0b25lIjp7ImVhcm5lZCI6dHJ1ZX0sInN5bmVyZ3lNaWxlc3RvbmUiOnsiZWFybmVkIjp0cnVlfSwiaW5kdXN0cmlhbENydWNpYmxlTWlsZXN0b25lIjp7ImVhcm5lZCI6dHJ1ZX19LCJnZW5lcmFsVGFiQ29sbGFwc2VkIjp7fSwiY29sbGFwc2VNaWxlc3RvbmVzIjp0cnVlLCJtYXN0ZXJ5Ijp7ImxldHRlcnMiOiIxMjU1ODAwNS41NzE1MTA4NSIsInRvdGFsTGV0dGVycyI6IjEyNTU4MDA1LjU3MTUxMDg1IiwiYnV5YWJsZXMiOnsibWV0YWxCdXlhYmxlIjp7ImFtb3VudCI6MH0sInBsYXN0aWNCdXlhYmxlIjp7ImFtb3VudCI6MH0sInBhcGVyQnV5YWJsZSI6eyJhbW91bnQiOjB9fSwibWlsZXN0b25lcyI6eyJhdXRvU21lbHRpbmdNaWxlc3RvbmUiOnsiZWFybmVkIjp0cnVlfSwibWluaW5nTWlsZXN0b25lIjp7ImVhcm5lZCI6dHJ1ZX0sInN5bmVyZ3lNaWxlc3RvbmUiOnsiZWFybmVkIjp0cnVlfSwiaW5kdXN0cmlhbENydWNpYmxlTWlsZXN0b25lIjp7ImVhcm5lZCI6dHJ1ZX19fSwibWFzdGVyZWQiOnRydWV9LCJyaWJib24iOnsibWluaW1pemVkIjpmYWxzZSwicmliYm9uIjoiMTYiLCJtaWxlc3RvbmVzIjp7InNlY29uZGFyeUR5ZUVsZiI6eyJlYXJuZWQiOnRydWV9LCJkeWVCb29rIjp7ImVhcm5lZCI6dHJ1ZX19LCJyaWJib25Qcm9ncmVzcyI6MTAsImNvbGxhcHNlTWlsZXN0b25lcyI6dHJ1ZSwiZ2VuZXJhbFRhYkNvbGxhcHNlZCI6e319LCJ0b3lzIjp7Im1pbmltaXplZCI6ZmFsc2UsImNsb3RoZXMiOiIxNTAwIiwid29vZGVuQmxvY2tzIjoiMjYzMS4wMDAwMDAwMDAwMDEiLCJ0cnVja3MiOiIyMTcwLjgxOTIiLCJ0b3RhbFRveXMiOiIyOTExNyIsImJ1eWFibGVzIjp7IjAiOnsiYW1vdW50IjoiMzQxIn0sIjEiOnsiYW1vdW50IjoiMS4wMDAwMDAwMDAwMDAwMTQyIn0sIjIiOnsiYW1vdW50IjoiMzc3In19LCJyb3cxVXBncmFkZXMiOnsiMCI6eyJib3VnaHQiOnRydWV9LCIxIjp7ImJvdWdodCI6dHJ1ZX0sIjIiOnsiYm91Z2h0Ijp0cnVlfX0sIm1pbGVzdG9uZXMiOnsibWlsZXN0b25lMSI6eyJlYXJuZWQiOnRydWV9LCJtaWxlc3RvbmUyIjp7ImVhcm5lZCI6dHJ1ZX0sIm1pbGVzdG9uZTMiOnsiZWFybmVkIjp0cnVlfSwibWlsZXN0b25lNCI6eyJlYXJuZWQiOnRydWV9LCJtaWxlc3RvbmU1Ijp7ImVhcm5lZCI6dHJ1ZX0sIm1pbGVzdG9uZTYiOnsiZWFybmVkIjp0cnVlfSwibWlsZXN0b25lNyI6eyJlYXJuZWQiOnRydWV9LCJtaWxlc3RvbmU4Ijp7ImVhcm5lZCI6dHJ1ZX19LCJnZW5lcmFsVGFiQ29sbGFwc2VkIjp7fSwiY29sbGFwc2VNaWxlc3RvbmVzIjpmYWxzZX0sImZhY3RvcnkiOnsibWluaW1pemVkIjpmYWxzZSwiY29tcG9uZW50cyI6eyItNXgtNSI6eyJ0aWNrc0RvbmUiOjEuMzE5NzY0MjYwNTU2NzA3NSwiZGlyZWN0aW9uIjoiTEVGVCIsIm91dHB1dFN0b2NrIjp7ImNsb3RoIjowfSwidHlwZSI6ImNsb3RoIn0sIi01eC00Ijp7InRpY2tzRG9uZSI6MC43ODE0OTg5MDEyNDU2NTUyLCJkaXJlY3Rpb24iOiJVUCIsIm91dHB1dFN0b2NrIjp7ImNsb3RoIjowfSwidHlwZSI6ImNsb3RoIn0sIi0zeC01Ijp7InRpY2tzRG9uZSI6MS4zMTk0MzA0ODkwNTkxNDg4LCJkaXJlY3Rpb24iOiJVUCIsImlucHV0U3RvY2siOnsiY2xvdGgiOjUwfSwib3V0cHV0U3RvY2siOnsidGhyZWFkIjowfSwidHlwZSI6InRocmVhZCJ9LCItM3gtNCI6eyJ0aWNrc0RvbmUiOjAuNzgwNTM5OTQxODM2OCwiZGlyZWN0aW9uIjoiTEVGVCIsImlucHV0U3RvY2siOnsiY2xvdGgiOjUwLCJwbGFzdGljIjoxNX0sIm91dHB1dFN0b2NrIjp7InN0dWZmaW5nIjowfSwidHlwZSI6InN0dWZmaW5nIn0sIi00eC01Ijp7InRpY2tzRG9uZSI6MCwiZGlyZWN0aW9uIjoiUklHSFQiLCJ0eXBlIjoiY29udmV5b3IifSwiLTR4LTQiOnsidGlja3NEb25lIjowLCJkaXJlY3Rpb24iOiJSSUdIVCIsInR5cGUiOiJjb252ZXlvciJ9LCIxeC01Ijp7InRpY2tzRG9uZSI6Mi40NTExMTA2MzU3NTEzNTIsImRpcmVjdGlvbiI6IlVQIiwiaW5wdXRTdG9jayI6eyJwbGFzdGljIjowLCJ0aHJlYWQiOjQ4fSwib3V0cHV0U3RvY2siOnsiYnV0dG9ucyI6MH0sInR5cGUiOiJidXR0b24ifSwiMXgtNCI6eyJ0aWNrc0RvbmUiOjAuODUwMTIwMjk2ODc1ODA3NywiZGlyZWN0aW9uIjoiUklHSFQiLCJpbnB1dFN0b2NrIjp7InBsYXN0aWMiOjF9LCJvdXRwdXRTdG9jayI6eyJidXR0b25zIjoxfSwidHlwZSI6ImJ1dHRvbiJ9LCIzeC01Ijp7InRpY2tzRG9uZSI6MC40NDEyNTY1ODg1MDk4NzU4LCJkaXJlY3Rpb24iOiJVUCIsIm91dHB1dFN0b2NrIjp7InBsYXN0aWMiOjEwMzM1fSwidHlwZSI6InBsYXN0aWMifSwiMngtNSI6eyJ0aWNrc0RvbmUiOjAsImRpcmVjdGlvbiI6IkxFRlQiLCJ0eXBlIjoiY29udmV5b3IifSwiM3gtNCI6eyJ0aWNrc0RvbmUiOjAsImRpcmVjdGlvbiI6IkRPV04iLCJ0eXBlIjoiY29udmV5b3IifSwiM3gtMyI6eyJ0aWNrc0RvbmUiOjAsImRpcmVjdGlvbiI6IkxFRlQiLCJ0eXBlIjoiY29udmV5b3IifSwiMngtMyI6eyJ0aWNrc0RvbmUiOjAsImRpcmVjdGlvbiI6IkxFRlQiLCJ0eXBlIjoiY29udmV5b3IifSwiMXgtMyI6eyJ0aWNrc0RvbmUiOjAsImRpcmVjdGlvbiI6IlVQIiwidHlwZSI6ImNvbnZleW9yIn0sIi0xeC00Ijp7InRpY2tzRG9uZSI6MC43ODIxNzk3NTc0MTMyMTc5LCJkaXJlY3Rpb24iOiJMRUZUIiwiaW5wdXRTdG9jayI6eyJ0aHJlYWQiOjQ5NCwic3R1ZmZpbmciOjU3OSwiZHllIjo0ODIyLCJidXR0b25zIjo0MTR9LCJvdXRwdXRTdG9jayI6eyJiZWFyIjowfSwidHlwZSI6ImJlYXIifSwiLTJ4LTQiOnsidGlja3NEb25lIjowLCJkaXJlY3Rpb24iOiJSSUdIVCIsInR5cGUiOiJjb252ZXlvciJ9LCItMngtNSI6eyJ0aWNrc0RvbmUiOjAsImRpcmVjdGlvbiI6IlJJR0hUIiwidHlwZSI6ImNvbnZleW9yIn0sIjB4LTUiOnsidGlja3NEb25lIjowLCJkaXJlY3Rpb24iOiJMRUZUIiwidHlwZSI6ImNvbnZleW9yIn0sIjB4LTQiOnsidGlja3NEb25lIjowLCJkaXJlY3Rpb24iOiJMRUZUIiwidHlwZSI6ImNvbnZleW9yIn0sIi0xeC01Ijp7InRpY2tzRG9uZSI6MCwiZGlyZWN0aW9uIjoiRE9XTiIsInR5cGUiOiJjb252ZXlvciJ9LCItMXgtMiI6eyJ0aWNrc0RvbmUiOjAuNDM5NjY0Mjg5MTk3MTM5ODUsImRpcmVjdGlvbiI6IkRPV04iLCJvdXRwdXRTdG9jayI6eyJkeWUiOjk2Mzh9LCJ0eXBlIjoiZHllIn0sIi0xeC0zIjp7InRpY2tzRG9uZSI6MCwiZGlyZWN0aW9uIjoiVVAiLCJ0eXBlIjoiY29udmV5b3IifSwiNHgtNSI6eyJ0aWNrc0RvbmUiOjAsImRpcmVjdGlvbiI6IlJJR0hUIiwidHlwZSI6ImNvbnZleW9yIn0sIjV4LTIiOnsidGlja3NEb25lIjoxLjgwMjYwODk3MTg5ODg4MzEsImRpcmVjdGlvbiI6IkRPV04iLCJpbnB1dFN0b2NrIjp7InBsYXN0aWMiOjF9LCJvdXRwdXRTdG9jayI6eyJidWNrZXQiOjB9LCJ0eXBlIjoiYnVja2V0In0sIjV4LTUiOnsidGlja3NEb25lIjowLCJkaXJlY3Rpb24iOiJET1dOIiwidHlwZSI6ImNvbnZleW9yIn0sIjV4LTQiOnsidGlja3NEb25lIjowLCJkaXJlY3Rpb24iOiJET1dOIiwidHlwZSI6ImNvbnZleW9yIn0sIjV4LTMiOnsidGlja3NEb25lIjowLCJkaXJlY3Rpb24iOiJET1dOIiwidHlwZSI6ImNvbnZleW9yIn0sIjV4MCI6eyJ0aWNrc0RvbmUiOjAuNzQzMzU1NzU0MjEyODU5NywiZGlyZWN0aW9uIjoiRE9XTiIsIm91dHB1dFN0b2NrIjp7InBsYXN0aWMiOjc5MDF9LCJ0eXBlIjoicGxhc3RpYyJ9LCIzeDAiOnsidGlja3NEb25lIjowLjA4ODY4ODI2ODIwOTA5MjE1LCJkaXJlY3Rpb24iOiJMRUZUIiwiaW5wdXRTdG9jayI6eyJwbGFzdGljIjowfSwib3V0cHV0U3RvY2siOnsic2hvdmVsIjowfSwidHlwZSI6InNob3ZlbCJ9LCI0eDAiOnsidGlja3NEb25lIjowLCJkaXJlY3Rpb24iOiJMRUZUIiwidHlwZSI6ImNvbnZleW9yIn0sIjV4LTEiOnsidGlja3NEb25lIjowLCJkaXJlY3Rpb24iOiJVUCIsInR5cGUiOiJjb252ZXlvciJ9LCI0eC0yIjp7InRpY2tzRG9uZSI6MCwiZGlyZWN0aW9uIjoiTEVGVCIsInR5cGUiOiJjb252ZXlvciJ9LCIzeC0xIjp7InRpY2tzRG9uZSI6MCwiZGlyZWN0aW9uIjoiVVAiLCJ0eXBlIjoiY29udmV5b3IifSwiM3gtMiI6eyJ0aWNrc0RvbmUiOjIuMTAyNjIzMzI0MTA3NjA3LCJkaXJlY3Rpb24iOiJMRUZUIiwiaW5wdXRTdG9jayI6eyJidWNrZXQiOjI0Nywic2hvdmVsIjowfSwib3V0cHV0U3RvY2siOnsic2hvdmVsQnVja2V0IjowfSwidHlwZSI6ImJ1Y2tldFNob3ZlbCJ9LCItM3gtMSI6eyJ0aWNrc0RvbmUiOjAuNDY5NTI0MDc2NTcwODY2MTQsImRpcmVjdGlvbiI6IlJJR0hUIiwib3V0cHV0U3RvY2siOnsicGxhc3RpYyI6NzI2Nn0sInR5cGUiOiJwbGFzdGljIn0sIi0xeC0xIjp7InRpY2tzRG9uZSI6MS43NzA3Mzg1NTA2NTcwNTYzLCJkaXJlY3Rpb24iOiJSSUdIVCIsImlucHV0U3RvY2siOnsibWV0YWwiOjE0NzgsInBsYXN0aWMiOjB9LCJvdXRwdXRTdG9jayI6eyJjaXJjdWl0Qm9hcmQiOjB9LCJ0eXBlIjoiY2lyY3VpdEJvYXJkIn0sIjF4LTEiOnsidGlja3NEb25lIjoxLjMxMDI0NjQzMDM4NDcyMDYsImRpcmVjdGlvbiI6IlJJR0hUIiwib3V0cHV0U3RvY2siOnsibWV0YWwiOjB9LCJ0eXBlIjoibWV0YWwifSwiLTF4MSI6eyJ0aWNrc0RvbmUiOjEuMTgyODg1MDk1NTg2MjM1LCJkaXJlY3Rpb24iOiJSSUdIVCIsImlucHV0U3RvY2siOnsibWV0YWwiOjEwNTEsInBsYXN0aWMiOjIsImNpcmN1aXRCb2FyZCI6MTI2MH0sIm91dHB1dFN0b2NrIjp7ImNvbnNvbGUiOjB9LCJ0eXBlIjoiY29uc29sZSJ9LCItMngtMSI6eyJ0aWNrc0RvbmUiOjAsImRpcmVjdGlvbiI6IlJJR0hUIiwidHlwZSI6ImNvbnZleW9yIn0sIi0zeC0yIjp7InRpY2tzRG9uZSI6MCwiZGlyZWN0aW9uIjoiVVAiLCJ0eXBlIjoiY29udmV5b3IifSwiLTN4LTMiOnsidGlja3NEb25lIjowLCJkaXJlY3Rpb24iOiJMRUZUIiwidHlwZSI6ImNvbnZleW9yIn0sIi00eC0zIjp7InRpY2tzRG9uZSI6MCwiZGlyZWN0aW9uIjoiRE9XTiIsInR5cGUiOiJjb252ZXlvciJ9LCItNHgtMiI6eyJ0aWNrc0RvbmUiOjAsImRpcmVjdGlvbiI6IkRPV04iLCJ0eXBlIjoiY29udmV5b3IifSwiLTR4LTEiOnsidGlja3NEb25lIjowLCJkaXJlY3Rpb24iOiJMRUZUIiwidHlwZSI6ImNvbnZleW9yIn0sIi01eC0xIjp7InRpY2tzRG9uZSI6MCwiZGlyZWN0aW9uIjoiRE9XTiIsInR5cGUiOiJjb252ZXlvciJ9LCItNXgwIjp7InRpY2tzRG9uZSI6MCwiZGlyZWN0aW9uIjoiUklHSFQiLCJ0eXBlIjoiY29udmV5b3IifSwiLTR4MCI6eyJ0aWNrc0RvbmUiOjAsImRpcmVjdGlvbiI6IlJJR0hUIiwidHlwZSI6ImNvbnZleW9yIn0sIi0zeDAiOnsidGlja3NEb25lIjowLCJkaXJlY3Rpb24iOiJSSUdIVCIsInR5cGUiOiJjb252ZXlvciJ9LCItMngwIjp7InRpY2tzRG9uZSI6MCwiZGlyZWN0aW9uIjoiUklHSFQiLCJ0eXBlIjoiY29udmV5b3IifSwiLTF4MCI6eyJ0aWNrc0RvbmUiOjAsImRpcmVjdGlvbiI6IkRPV04iLCJ0eXBlIjoiY29udmV5b3IifSwiMHgtMSI6eyJ0aWNrc0RvbmUiOjAsImRpcmVjdGlvbiI6IkxFRlQiLCJ0eXBlIjoiY29udmV5b3IifSwiMHgwIjp7InRpY2tzRG9uZSI6MCwiZGlyZWN0aW9uIjoiTEVGVCIsInR5cGUiOiJjb252ZXlvciJ9LCIxeDAiOnsidGlja3NEb25lIjowLjc0NTMzODg0NzA1NDcyMTEsImRpcmVjdGlvbiI6IlVQIiwib3V0cHV0U3RvY2siOnsibWV0YWwiOjB9LCJ0eXBlIjoibWV0YWwifSwiLTV4MyI6eyJ0aWNrc0RvbmUiOjAuNzc5NzI4MDkzNTA3NjkyOSwiZGlyZWN0aW9uIjoiVVAiLCJvdXRwdXRTdG9jayI6eyJjbG90aCI6MH0sInR5cGUiOiJjbG90aCJ9LCItNXg0Ijp7InRpY2tzRG9uZSI6MS4zMTc0NjMwNDY3Mjc0NzY2LCJkaXJlY3Rpb24iOiJMRUZUIiwib3V0cHV0U3RvY2siOnsiY2xvdGgiOjB9LCJ0eXBlIjoiY2xvdGgifSwiLTV4NSI6eyJ0aWNrc0RvbmUiOjAuNzc4NjQzNzU2NDc5ODY2MywiZGlyZWN0aW9uIjoiRE9XTiIsIm91dHB1dFN0b2NrIjp7ImNsb3RoIjowfSwidHlwZSI6ImNsb3RoIn0sIi01eDIiOnsidGlja3NEb25lIjoxLjMxNzEzMTc3MTM5MTEzMzUsImRpcmVjdGlvbiI6IkRPV04iLCJvdXRwdXRTdG9jayI6eyJjbG90aCI6MH0sInR5cGUiOiJjbG90aCJ9LCItNXgxIjp7InRpY2tzRG9uZSI6MS4zMDg3MTIyNjM5MjQ2MzEsImRpcmVjdGlvbiI6IlJJR0hUIiwib3V0cHV0U3RvY2siOnsiY2xvdGgiOjB9LCJ0eXBlIjoiY2xvdGgifSwiLTN4NCI6eyJ0aWNrc0RvbmUiOjAuNzQ0NzkwMDg2NzQ4NTg5LCJkaXJlY3Rpb24iOiJMRUZUIiwiaW5wdXRTdG9jayI6eyJjbG90aCI6MzI3fSwib3V0cHV0U3RvY2siOnsidGhyZWFkIjoxNTg0fSwidHlwZSI6InRocmVhZCJ9LCItM3g1Ijp7InRpY2tzRG9uZSI6MC40NzAyNzA0NjE5MDUxOTAwNiwiZGlyZWN0aW9uIjoiRE9XTiIsImlucHV0U3RvY2siOnsiY2xvdGgiOjE3MH0sIm91dHB1dFN0b2NrIjp7InRocmVhZCI6MH0sInR5cGUiOiJ0aHJlYWQifSwiLTF4NSI6eyJ0aWNrc0RvbmUiOjAuNzg2OTUwMDAxOTgzMTIwNiwiZGlyZWN0aW9uIjoiVVAiLCJpbnB1dFN0b2NrIjp7InRocmVhZCI6MywiY2xvdGgiOjE4NzIsImR5ZSI6MjI2OH0sIm91dHB1dFN0b2NrIjp7ImNsb3RoZXMiOjB9LCJ0eXBlIjoiY2xvdGhlcyJ9LCItMngxIjp7InRpY2tzRG9uZSI6MC43ODM0MjQyNzcyNjk3MzQ2LCJkaXJlY3Rpb24iOiJMRUZUIiwib3V0cHV0U3RvY2siOnsiZHllIjozODA2fSwidHlwZSI6ImR5ZSJ9LCItNHg1Ijp7InRpY2tzRG9uZSI6MCwiZGlyZWN0aW9uIjoiUklHSFQiLCJ0eXBlIjoiY29udmV5b3IifSwiLTJ4NSI6eyJ0aWNrc0RvbmUiOjAsImRpcmVjdGlvbiI6IlJJR0hUIiwidHlwZSI6ImNvbnZleW9yIn0sIi00eDQiOnsidGlja3NEb25lIjowLCJkaXJlY3Rpb24iOiJSSUdIVCIsInR5cGUiOiJjb252ZXlvciJ9LCItMng0Ijp7InRpY2tzRG9uZSI6MCwiZGlyZWN0aW9uIjoiRE9XTiIsInR5cGUiOiJjb252ZXlvciJ9LCItNHgzIjp7InRpY2tzRG9uZSI6MCwiZGlyZWN0aW9uIjoiUklHSFQiLCJ0eXBlIjoiY29udmV5b3IifSwiLTR4MiI6eyJ0aWNrc0RvbmUiOjAsImRpcmVjdGlvbiI6IlJJR0hUIiwidHlwZSI6ImNvbnZleW9yIn0sIi00eDEiOnsidGlja3NEb25lIjowLCJkaXJlY3Rpb24iOiJSSUdIVCIsInR5cGUiOiJjb252ZXlvciJ9LCItM3gxIjp7InRpY2tzRG9uZSI6MCwiZGlyZWN0aW9uIjoiRE9XTiIsInR5cGUiOiJjb252ZXlvciJ9LCItM3gyIjp7InRpY2tzRG9uZSI6MCwiZGlyZWN0aW9uIjoiRE9XTiIsInR5cGUiOiJjb252ZXlvciJ9LCItM3gzIjp7InRpY2tzRG9uZSI6MCwiZGlyZWN0aW9uIjoiUklHSFQiLCJ0eXBlIjoiY29udmV5b3IifSwiLTJ4MiI6eyJ0aWNrc0RvbmUiOjAsImRpcmVjdGlvbiI6IkRPV04iLCJ0eXBlIjoiY29udmV5b3IifSwiLTJ4MyI6eyJ0aWNrc0RvbmUiOjAsImRpcmVjdGlvbiI6IkRPV04iLCJ0eXBlIjoiY29udmV5b3IifSwiM3g1Ijp7InRpY2tzRG9uZSI6MC41NTEwNjI5ODU4Mzk5MTQ4LCJkaXJlY3Rpb24iOiJSSUdIVCIsIm91dHB1dFN0b2NrIjp7ImNsb3RoIjowfSwidHlwZSI6ImNsb3RoIn0sIjF4NSI6eyJ0aWNrc0RvbmUiOjAuNTQyMTYwMDA3OTM5NjQ5MSwiZGlyZWN0aW9uIjoiUklHSFQiLCJpbnB1dFN0b2NrIjp7ImNsb3RoIjo2NX0sIm91dHB1dFN0b2NrIjp7InRocmVhZCI6MH0sInR5cGUiOiJ0aHJlYWQifSwiMHg1Ijp7InRpY2tzRG9uZSI6MCwiZGlyZWN0aW9uIjoiTEVGVCIsInR5cGUiOiJjb252ZXlvciJ9LCIyeDUiOnsidGlja3NEb25lIjowLCJkaXJlY3Rpb24iOiJMRUZUIiwidHlwZSI6ImNvbnZleW9yIn19LCJlbGZCdXlhYmxlcyI6eyJjbG90aGVzQnV5YWJsZSI6eyJhbW91bnQiOiI1In0sImJsb2Nrc0J1eWFibGUiOnsiYW1vdW50IjoiOCJ9LCJ0cnVja3NCdXlhYmxlIjp7ImFtb3VudCI6IjYifSwiYmVhcnNCdXlhYmxlIjp7InJlc291cmNlIjoiODU1OCIsImFtb3VudCI6IjUifSwiYnVja2V0QnV5YWJsZSI6eyJyZXNvdXJjZSI6IjMxMjAiLCJhbW91bnQiOiI0In0sImNvbnNvbGVzQnV5YWJsZSI6eyJyZXNvdXJjZSI6IjI3ODEiLCJhbW91bnQiOiI0In19LCJ0YWJzIjp7InNlbGVjdGVkIjoiZGFzaGJvYXJkIn0sImdlbmVyYWxUYWJDb2xsYXBzZWQiOnt9LCJiZWFycyI6Ijg1NTgiLCJidWNrZXRBbmRTaG92ZWxzIjoiMzEyMCIsImNvbnNvbGVzIjoiMjc4MSIsImZhY3RvcnlCdXlhYmxlcyI6eyJleHBhbmRGYWN0b3J5Ijp7ImFtb3VudCI6IjQifSwib2lsRnVlbCI6eyJhbW91bnQiOiIyIn0sImNhcnJ5VG95cyI6eyJhbW91bnQiOiI0In19LCJ1cGdyYWRlcyI6eyIwIjp7IjAiOnsiYm91Z2h0Ijp0cnVlfSwiMSI6eyJib3VnaHQiOnRydWV9LCIyIjp7ImJvdWdodCI6dHJ1ZX0sIjMiOnsiYm91Z2h0Ijp0cnVlfX0sIjEiOnsiMCI6eyJib3VnaHQiOnRydWV9LCIxIjp7ImJvdWdodCI6dHJ1ZX0sIjIiOnsiYm91Z2h0Ijp0cnVlfSwiMyI6eyJib3VnaHQiOnRydWV9fSwiMiI6eyIwIjp7ImJvdWdodCI6dHJ1ZX0sIjEiOnsiYm91Z2h0Ijp0cnVlfSwiMiI6eyJib3VnaHQiOnRydWV9LCIzIjp7ImJvdWdodCI6dHJ1ZX19fX19LCJhdXRvUGF1c2UiOnRydWUsInVzaW5nTG9nIjpmYWxzZX0= \ No newline at end of file diff --git a/src/data/layers/boxes.tsx b/src/data/layers/boxes.tsx index 98b8b8b..2abf605 100644 --- a/src/data/layers/boxes.tsx +++ b/src/data/layers/boxes.tsx @@ -28,6 +28,7 @@ import { render, renderGrid } from "util/vue"; import { computed, ComputedRef, ref, unref } from "vue"; import dyes from "./dyes"; import elves, { ElfBuyable } from "./elves"; +import factory from "./factory"; import management from "./management"; import paper from "./paper"; import plastic from "./plastic"; @@ -587,7 +588,36 @@ const layer = createLayer(id, function (this: BaseLayer) { Decimal.add(plasticBoxesBuyable.amount.value, plasticBoxesBuyable.freeLevels.value) ) })) as BoxesBuyable; + const presentBuyable = createBuyable(() => ({ + display: { + title: "Carry presents in boxes", + description: jsx(() => ( + <> + Use boxes to carry presents, boosting its gain +
+
+
Amount: {formatWhole(presentBuyable.amount.value)} boxes
+ + )), + effectDisplay: jsx(() => ( + <>{format(Decimal.div(presentBuyable.amount.value, 10).add(1).pow(2))}x + )), + showAmount: false + }, + resource: noPersist(boxes), + cost() { + return Decimal.pow(2, presentBuyable.amount.value).mul(1e87); + }, + inverseCost(x: DecimalSource) { + const amt = Decimal.div(x, 1e87).log2(); + return Decimal.isNaN(amt) ? Decimal.dZero : amt.floor().max(0); + }, + freeLevels: computed(() => 0), + totalAmount: computed(() => presentBuyable.amount.value), + visibility: () => showIf(factory.upgrades[3][3].bought.value) + })) as BoxesBuyable; const buyables2 = { oreBoxesBuyable, metalBoxesBuyable, plasticBoxesBuyable }; + const buyables3 = { presentBuyable }; globalBus.on("update", diff => { if (Decimal.lt(main.day.value, day)) { return; @@ -677,6 +707,7 @@ const layer = createLayer(id, function (this: BaseLayer) { row3Upgrades, buyables, buyables2, + buyables3, minWidth: 700, generalTabCollapsed, display: jsx(() => ( @@ -703,7 +734,11 @@ const layer = createLayer(id, function (this: BaseLayer) { Object.values(row3Upgrades) )} - {renderGrid(Object.values(buyables), Object.values(buyables2))} + {renderGrid( + Object.values(buyables), + Object.values(buyables2), + Object.values(buyables3) + )} )), minimizedDisplay: jsx(() => ( diff --git a/src/data/layers/elves.tsx b/src/data/layers/elves.tsx index e2ad2d9..47378a4 100644 --- a/src/data/layers/elves.tsx +++ b/src/data/layers/elves.tsx @@ -876,7 +876,11 @@ const layer = createLayer(id, function (this: BaseLayer) { name: "Bell", description: "Bell will automatically purchase all box buyables you can afford, without actually spending any boxes.", - buyable: [...Object.values(boxes.buyables), ...Object.values(boxes.buyables2)], + buyable: [ + ...Object.values(boxes.buyables), + ...Object.values(boxes.buyables2), + ...Object.values(boxes.buyables3) + ], cooldownModifier: boxCooldown, visibility: () => showIf(plastic.elfUpgrades.boxElf.bought.value) }); diff --git a/src/data/layers/factory-components/boxmaker.svg b/src/data/layers/factory-components/boxmaker.svg new file mode 100644 index 0000000..70da472 --- /dev/null +++ b/src/data/layers/factory-components/boxmaker.svg @@ -0,0 +1,123 @@ + + + + \ No newline at end of file diff --git a/src/data/layers/factory.tsx b/src/data/layers/factory.tsx index db463b3..85c0ff9 100644 --- a/src/data/layers/factory.tsx +++ b/src/data/layers/factory.tsx @@ -40,9 +40,11 @@ import _plastic from "../symbols/plastic.png"; import boxes from "./boxes"; import coal from "./coal"; import dyes from "./dyes"; +import _box from "../symbols/cardboardBox.png"; import _bear from "./factory-components/bear.svg"; import _bearMaker from "./factory-components/bearmaker.svg"; import _block from "./factory-components/block.svg"; +import _boxMaker from "./factory-components/boxmaker.svg"; import _blockMaker from "./factory-components/blockmaker.svg"; import _bucket from "./factory-components/bucket.svg"; import _bucketMaker from "./factory-components/bucketmaker.svg"; @@ -75,6 +77,7 @@ import _truck from "./factory-components/truck.svg"; import _truckMaker from "./factory-components/truckmaker.svg"; import _wheel from "./factory-components/wheel.svg"; import _wheelMaker from "./factory-components/wheelmaker.svg"; +import _present from "./factory-components/presentmaker.svg"; import Factory from "./Factory.vue"; import metal from "./metal"; import oil from "./oil"; @@ -94,6 +97,7 @@ const presentsDay = 20; const toyGoal = 750; const advancedToyGoal = 1500; +const presentsGoal = 8e9; // 20x20 block size // TODO: unhardcode stuff @@ -138,6 +142,16 @@ const factory = createLayer(id, () => { const bears = createResource(0, "teddy bears"); const bucketAndShovels = createResource(0, "shovel and pails"); const consoles = createResource(0, "consoles"); + const presents = createResource(0, "presents"); + + const allToys = { + clothes: toys.clothes, + woodenBlocks: toys.woodenBlocks, + trucks: toys.trucks, + bears, + bucketAndShovels, + consoles + }; function getRelativeCoords(e: MouseEvent) { const rect = (e.target as HTMLElement).getBoundingClientRect(); @@ -172,6 +186,11 @@ const factory = createLayer(id, () => { multiplier: 1.4, description: "6000 toys", enabled: toys.milestones.milestone6.earned + })), + createMultiplicativeModifier(() => ({ + multiplier: () => Decimal.log10(trees.logs.value).div(100).add(1), + description: "Burn some logs", + enabled: betterLighting.bought })) ]) as WithRequired; const computedEnergy = computed(() => energy.apply(0)); @@ -227,9 +246,27 @@ const factory = createLayer(id, () => { addend: expandFactory.amount, description: "Expand Factory", enabled: () => Decimal.gt(expandFactory.amount.value, 0) + })), + createAdditiveModifier(() => ({ + addend: 5, + description: "Factory eXPerience", + enabled: betterFactory.bought })) ]); const computedFactorySize = computed(() => new Decimal(factorySize.apply(7)).toNumber()); + const presentMultipliers = createSequentialModifier(() => [ + createMultiplicativeModifier(() => ({ + multiplier: computedToyMultiplier, + description: "Tickspeed overflow", + enabled: () => computedToyMultiplier.value.gt(1) + })), + createMultiplicativeModifier(() => ({ + multiplier: Decimal.div(boxes.buyables3.presentBuyable.amount.value, 10).add(1).pow(2), + description: "Carry boxes in... presents?", + enabled: carryPresents.bought + })) + ]); + const computedPresentMultipliers = computed(() => presentMultipliers.apply(1)); const energyBar = createBar(() => ({ width: 680, @@ -317,6 +354,10 @@ const factory = createLayer(id, () => { return str; } + // this keeps track of which toy the present factory has consumed + // it cycles around, so each toy is used evenly + let toysIndex = 0; + const FACTORY_COMPONENTS = { cursor: { imageSrc: _cursor, @@ -459,6 +500,26 @@ const factory = createLayer(id, () => { plank: { amount: computed(() => (upgrades[0][0].bought.value ? 2 : 1)) } + }, + visible: main.days[presentsDay - 1].opened + } as FactoryComponentDeclaration, + boxMaker: { + imageSrc: _boxMaker, + key: "ctrl+8", + name: "Box Maker", + type: "processor", + description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.boxMaker)), + energyCost: 3, + tick: 1, + inputs: { + plank: { + amount: 2 + } + }, + outputs: { + box: { + amount: 2 + } } } as FactoryComponentDeclaration, thread: { @@ -755,6 +816,57 @@ const factory = createLayer(id, () => { } }, visible: main.days[advancedDay - 1].opened + } as FactoryComponentDeclaration, + present: { + imageSrc: _present, + type: "processor", + // idk about this + key: "ctrl+7", + name: "Present Wrapper", + description: computed( + () => + `Takes in 4 dye, 4 plastic, 1 cloth, 2 boxes, and ${formatWhole( + computedToyMultiplier.value + )} toys of any type (from storage) to produce ${formatWhole( + computedPresentMultipliers.value + )} presents every tick.` + ), + tick: 1, + energyCost: 20, + inputs: { + dye: { + amount: 4 + }, + plastic: { + amount: 4 + }, + cloth: { + amount: 1 + }, + box: { + amount: 2 + } + }, + canProduce: computed(() => { + return Object.values(allToys).some(i => + Decimal.gte(i.value, computedToyMultiplier.value) + ); + }), + onProduce(times, stock) { + const value = Object.values(allToys); + + while (times > 0) { + while (Decimal.lt(value[toysIndex].value, computedToyMultiplier.value)) { + toysIndex = (toysIndex + 1) % value.length; + } + const toyToPick = Object.values(allToys)[toysIndex]; + toysIndex = (toysIndex + 1) % value.length; + toyToPick.value = Decimal.sub(toyToPick.value, computedToyMultiplier.value); + times--; + presents.value = Decimal.add(presents.value, computedPresentMultipliers.value); + } + }, + visible: main.days[presentsDay - 1].opened } as FactoryComponentDeclaration } as Record; const RESOURCES = { @@ -784,6 +896,10 @@ const factory = createLayer(id, () => { name: "Planks", imageSrc: _plank }, + box: { + name: "Boxes", + imageSrc: _box + }, thread: { name: "Thread", imageSrc: _thread @@ -903,7 +1019,7 @@ const factory = createLayer(id, () => { outputs?: Stock; /** on produce, do something */ - onProduce?: (times: number) => void; + onProduce?: (times: number, stock: Stock | undefined) => void; /** can it produce? (in addtion to the stock check) */ canProduce?: ComputedRef; } @@ -956,10 +1072,21 @@ const factory = createLayer(id, () => { // trained elves + const costCheapener = createSequentialModifier(() => [ + createMultiplicativeModifier(() => ({ + multiplier: () => Decimal.add(presents.value, 1).log10().add(1), + description: "Excitment Upgrade", + enabled: excitmentUpgrade.bought + })) + ]); + const computedCostCheapeners = computed(() => costCheapener.apply(1)); + const clothesBuyable = createBuyable(() => ({ resource: toys.clothes, cost() { - return Decimal.pow(2, Decimal.add(this.amount.value, 5)); + return Decimal.pow(2, Decimal.add(this.amount.value, 5)).div( + computedCostCheapeners.value + ); }, display: { title: "Train elves to make clothes", @@ -970,7 +1097,9 @@ const factory = createLayer(id, () => { const blocksBuyable = createBuyable(() => ({ resource: toys.woodenBlocks, cost() { - return Decimal.pow(2, Decimal.add(this.amount.value, 5)); + return Decimal.pow(2, Decimal.add(this.amount.value, 5)).div( + computedCostCheapeners.value + ); }, display: { title: "Train elves to make wooden blocks", @@ -981,7 +1110,9 @@ const factory = createLayer(id, () => { const trucksBuyable = createBuyable(() => ({ resource: toys.trucks, cost() { - return Decimal.pow(2, Decimal.add(this.amount.value, 5)); + return Decimal.pow(2, Decimal.add(this.amount.value, 5)).div( + computedCostCheapeners.value + ); }, display: { title: "Train elves to make toy trucks", @@ -992,7 +1123,9 @@ const factory = createLayer(id, () => { const bearsBuyable = createBuyable(() => ({ resource: noPersist(bears), cost() { - return Decimal.pow(2, Decimal.add(this.amount.value, 5)); + return Decimal.pow(2, Decimal.add(this.amount.value, 5)).div( + computedCostCheapeners.value + ); }, display: { title: "Train elves to make bears", @@ -1004,7 +1137,9 @@ const factory = createLayer(id, () => { const bucketBuyable = createBuyable(() => ({ resource: noPersist(bucketAndShovels), cost() { - return Decimal.pow(2, Decimal.add(this.amount.value, 5)); + return Decimal.pow(2, Decimal.add(this.amount.value, 5)).div( + computedCostCheapeners.value + ); }, display: { title: "Train elves to make shovel and pails", @@ -1016,7 +1151,9 @@ const factory = createLayer(id, () => { const consolesBuyable = createBuyable(() => ({ resource: noPersist(consoles), cost() { - return Decimal.pow(2, Decimal.add(this.amount.value, 5)); + return Decimal.pow(2, Decimal.add(this.amount.value, 5)).div( + computedCostCheapeners.value + ); }, display: { title: "Train elves to make consoles", @@ -1089,7 +1226,63 @@ const factory = createLayer(id, () => { style: "width: 200px", visibility: () => showIf(main.days[advancedDay - 1].opened.value) })) as GenericBuyable; - const factoryBuyables = { expandFactory, oilFuel, carryToys }; + + const betterFactory = createUpgrade(() => ({ + resource: noPersist(presents), + cost: 100, + display: { + title: "Factory eXPerience", + description: "Factory size is increased by 5." + }, + visibility: () => showIf(main.days[presentsDay - 1].opened.value) + })); + const betterLighting = createUpgrade(() => ({ + resource: noPersist(presents), + cost: 300, + display: { + title: "Burn some logs", + description: "More energy needed? Let's burn some logs! Logs boosts maximum energy.", + effectDisplay: jsx(() => ( + <>x{format(Decimal.log10(trees.logs.value).div(100).add(1))} + )) + }, + visibility: () => showIf(betterFactory.bought.value) + })); + const excitmentUpgrade = createUpgrade(() => ({ + resource: noPersist(presents), + cost: 1000, + display: { + title: "Faster Elf Training", + description: + "Apparently elves like presents. Let's use it to train them to work on the factory faster! Presents divides the requirement for factory elf training.", + effectDisplay: jsx(() => <>/{format(Decimal.add(presents.value, 1).log10().add(1))}) + }, + visibility: () => showIf(betterLighting.bought.value) + })); + const carryPresents = createUpgrade(() => ({ + resource: noPersist(presents), + cost: 5000, + display: { + title: "Carrying more stuff in boxes", + description: + "Boxes seem really useful for carrying stuff. Why don't we use them to carry presents as well? Unlocks 2 new rebuyables (one of them is in the boxes layer)." + } + })); + const carryBoxes = createBuyable(() => ({ + resource: noPersist(presents), + cost() { + return Decimal.add(carryBoxes.amount.value, 1).pow(1.5) + .mul(Decimal.pow(2, carryBoxes.amount.value)) + .mul(1000); + }, + display: { + title: "Carry boxes in... presents?", + description: + "Presents are made out of boxes, so shouldn't they be able to hold boxes as well? Apparently it makes the boxes more durable. Each level multiplies boxes gain by 1.5.", + effectDisplay: jsx(() => <>x{format(Decimal.pow(1.5, carryBoxes.amount.value))}) + } + })) as GenericBuyable; + const factoryBuyables = { expandFactory, oilFuel, carryToys, carryBoxes }; const upgrades = [ [ createUpgrade(() => ({ @@ -1205,7 +1398,8 @@ const factory = createLayer(id, () => { }, visibility: () => showIf(main.days[advancedDay - 1].opened.value) })) - ] + ], + [betterFactory, betterLighting, excitmentUpgrade, carryPresents] ]; // pixi @@ -1378,7 +1572,7 @@ const factory = createLayer(id, () => { if (data.ticksDone >= factoryData.tick) { if (compData.canProduce.value) { const cyclesDone = Math.floor(data.ticksDone / factoryData.tick); - factoryData.onProduce?.(cyclesDone); + factoryData.onProduce?.(cyclesDone, factoryData.inputs); if (factoryData.inputs !== undefined) { if (data.inputStock === undefined) data.inputStock = {}; for (const [key, val] of Object.entries(factoryData.inputs)) { @@ -1825,6 +2019,20 @@ const factory = createLayer(id, () => { function togglePaused() { paused.value = !paused.value; } + function handleDrag(drag: DragEvent, name: FactoryCompNames) { + drag.dataTransfer!.setData("name", name); + } + function handleDrop(drag: DragEvent) { + drag.preventDefault(); + const { tx, ty } = spriteContainer.localTransform; + let { x, y } = getRelativeCoords(drag); + x = roundDownTo(x - tx, blockSize) / blockSize; + y = roundDownTo(y - ty, blockSize) / blockSize; + const name = drag.dataTransfer!.getData("name"); + if (components.value[x + "x" + y] == null) { + addFactoryComp(x, y, { type: name }); + } + } // ------------------------------------------------------------------------------- Tabs @@ -1850,6 +2058,8 @@ const factory = createLayer(id, () => { src={item.imageSrc} class={{ selected: compSelected.value === key }} onClick={() => onCompClick(key)} + draggable="true" + onDragstart={drag => handleDrag(drag, key)} /> {item.extraImage == null ? null : ( @@ -2002,6 +2212,8 @@ const factory = createLayer(id, () => { ? `Reach ${format( advancedToyGoal )} for each toy to complete the day` + : main.day.value === presentsDay + ? `Reach ${format(presentsGoal)} presents` : `${name} Complete!`}{" "} -{" "}
@@ -93,6 +94,7 @@ import ribbons from "./symbols/ribbons.png"; import toys from "./symbols/truck.png"; import factory from "./symbols/gears.png"; import advFactory from "./symbols/teddyBear.png"; +import presents from "./symbols/presents.png"; defineProps<{ day: number; diff --git a/src/data/projEntry.tsx b/src/data/projEntry.tsx index f0a820e..bc00ccc 100644 --- a/src/data/projEntry.tsx +++ b/src/data/projEntry.tsx @@ -48,11 +48,12 @@ import metalSymbol from "./symbols/metal.png"; import oilSymbol from "./symbols/oil.png"; import paperSymbol from "./symbols/paperStacks.png"; import plasticSymbol from "./symbols/plastic.png"; +import presentsSymbol from "./symbols/presents.png"; import ribbonsSymbol from "./symbols/ribbons.png"; import workshopSymbol from "./symbols/sws.png"; +import advFactorySymbol from "./symbols/teddyBear.png"; import treeSymbol from "./symbols/tree.png"; import toysSymbol from "./symbols/truck.png"; -import advFactorySymbol from "./symbols/teddyBear.png"; import advManagementSymbol from "./symbols/workshopMansion.png"; import wrappingPaperSymbol from "./symbols/wrappingPaper.png"; @@ -464,10 +465,11 @@ export const main = createLayer("main", function (this: BaseLayer) { createDay(() => ({ day: 20, shouldNotify: false, - layer: "factory", // "presents" - symbol: wrappingPaperSymbol, + layer: "factory", + symbol: presentsSymbol, story: "Santa comes by again, and tells you that just toys may not be appealing enough. He tells you that you should probably wrap them in some wrapping paper so that it's more of a surprise. You try to argue that you've already done too much for him and deserve a day off, but Santa argues that it's for the benefit of everyone and that you'll get your vacation soon. Oh well, time to get back to the factory and expand it even more. Here we go again!", - completedStory: "", + completedStory: + "That was a lot of work, but it certainly felt worth actually using all those decorative supplies you'd previously made. One more sleepless night down, just a handful more to go. Good Job!", masteredStory: "" })), createDay(() => ({ diff --git a/src/data/symbols/presents.png b/src/data/symbols/presents.png new file mode 100644 index 0000000000000000000000000000000000000000..1d09e6f2e2dce505396616db2f8a024fa2baf2c0 GIT binary patch literal 5476 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 DG%U)4 literal 0 HcmV?d00001 From 2a2790e13e4ca2f47b7715740e456275996edd7a Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Fri, 23 Dec 2022 21:24:27 -0600 Subject: [PATCH 37/48] Begone side effects --- src/data/layers/workshop.tsx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/data/layers/workshop.tsx b/src/data/layers/workshop.tsx index b550e2e..4a0401a 100644 --- a/src/data/layers/workshop.tsx +++ b/src/data/layers/workshop.tsx @@ -123,9 +123,6 @@ const layer = createLayer(id, function (this: BaseLayer) { )), visibility: () => showIf(Decimal.lt(foundationProgress.value, computedMaxFoundation.value)), canClick: () => { - if (Decimal.gt(computedMaxFoundation.value, foundationProgress.value)){ - foundationProgress.value = Decimal.min(0, computedMaxFoundation.value) - } if (Decimal.lt(trees.logs.value, foundationConversion.nextAt.value)) { return false; } @@ -146,6 +143,12 @@ const layer = createLayer(id, function (this: BaseLayer) { style: "width: 600px; min-height: unset" })); + watchEffect(() => { + if (Decimal.lt(computedMaxFoundation.value, foundationProgress.value)) { + foundationProgress.value = Decimal.min(0, computedMaxFoundation.value); + } + }); + const buildFoundationHK = createHotkey(() => ({ key: "w", description: "Build foundation", From 1d2c61409c17f1810c18a5cd9f2f767b46763bf9 Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Fri, 23 Dec 2022 21:56:36 -0600 Subject: [PATCH 38/48] Presents polish --- src/data/layers/factory.tsx | 59 +++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/src/data/layers/factory.tsx b/src/data/layers/factory.tsx index 2fe3d13..dd4f36c 100644 --- a/src/data/layers/factory.tsx +++ b/src/data/layers/factory.tsx @@ -77,7 +77,8 @@ import _truck from "./factory-components/truck.svg"; import _truckMaker from "./factory-components/truckmaker.svg"; import _wheel from "./factory-components/wheel.svg"; import _wheelMaker from "./factory-components/wheelmaker.svg"; -import _present from "./factory-components/presentmaker.svg"; +import _present from "./factory-components/present.svg"; +import _presentMaker from "./factory-components/presentmaker.svg"; import Factory from "./Factory.vue"; import metal from "./metal"; import oil from "./oil"; @@ -503,25 +504,6 @@ const factory = createLayer(id, () => { }, visible: main.days[presentsDay - 1].opened } as FactoryComponentDeclaration, - boxMaker: { - imageSrc: _boxMaker, - key: "ctrl+8", - name: "Box Maker", - type: "processor", - description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.boxMaker)), - energyCost: 3, - tick: 1, - inputs: { - plank: { - amount: 2 - } - }, - outputs: { - box: { - amount: 2 - } - } - } as FactoryComponentDeclaration, thread: { imageSrc: _threadMaker, key: "shift+2", @@ -665,6 +647,25 @@ const factory = createLayer(id, () => { }, visible: main.days[advancedDay - 1].opened } as FactoryComponentDeclaration, + boxMaker: { + imageSrc: _boxMaker, + key: "shift+9", + name: "Box Maker", + type: "processor", + description: computed(() => generateComponentDescription(FACTORY_COMPONENTS.boxMaker)), + energyCost: 3, + tick: 1, + inputs: { + plank: { + amount: 2 + } + }, + outputs: { + box: { + amount: 2 + } + } + } as FactoryComponentDeclaration, blocks: { imageSrc: _blockMaker, key: "ctrl+1", @@ -818,7 +819,7 @@ const factory = createLayer(id, () => { visible: main.days[advancedDay - 1].opened } as FactoryComponentDeclaration, present: { - imageSrc: _present, + imageSrc: _presentMaker, type: "processor", // idk about this key: "ctrl+7", @@ -832,7 +833,7 @@ const factory = createLayer(id, () => { )} presents every tick.` ), tick: 1, - energyCost: 20, + energyCost: 50, inputs: { dye: { amount: 4 @@ -1276,7 +1277,7 @@ const factory = createLayer(id, () => { display: { title: "Carrying more stuff in boxes", description: - "Boxes seem really useful for carrying stuff. Why don't we use them to carry presents as well? Unlocks 2 new rebuyables (one of them is in the boxes layer)." + "Boxes seem really useful for carrying stuff. Why don't we use them to carry presents as well? Unlocks 2 new buyables (one of them is in the boxes layer)." }, visibility: () => showIf(excitmentUpgrade.bought.value) })); @@ -1288,13 +1289,14 @@ const factory = createLayer(id, () => { .mul(Decimal.pow(2, carryBoxes.amount.value)) .mul(1000); }, + style: "width: 400px", display: { title: "Carry boxes in... presents?", description: "Presents are made out of boxes, so shouldn't they be able to hold boxes as well? Apparently it makes the boxes more durable. Each level multiplies boxes gain by 1.5.", effectDisplay: jsx(() => <>x{format(Decimal.pow(1.5, carryBoxes.amount.value))}) }, - visbility: () => showIf(carryPresents.bought.value) + visibility: () => showIf(carryPresents.bought.value) })) as GenericBuyable; const catalysts = createUpgrade(() => ({ resource: noPersist(presents), @@ -1306,7 +1308,8 @@ const factory = createLayer(id, () => { }, visibility: () => showIf(carryPresents.bought.value) })); - const factoryBuyables = { expandFactory, oilFuel, carryToys, carryBoxes }; + const factoryBuyables = { expandFactory, oilFuel, carryToys }; + const factoryBuyables2 = { carryBoxes }; const upgrades = [ [ createUpgrade(() => ({ @@ -2291,7 +2294,10 @@ const factory = createLayer(id, () => { /> {renderRow(...Object.values(elfBuyables))} - {renderRow(...Object.values(factoryBuyables))} + {renderGrid( + Object.values(factoryBuyables), + Object.values(factoryBuyables2) + )} {renderGrid(...(upgrades as VueFeature[][]))} @@ -2471,6 +2477,7 @@ const factory = createLayer(id, () => { presents, tabs, factoryBuyables, + factoryBuyables2, carryBoxes, generalTabCollapsed, hotkeys, From 8a90cd45f7fb99f11b571f2aff9866d5aaab93ef Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Fri, 23 Dec 2022 22:24:13 -0600 Subject: [PATCH 39/48] Finished balancing --- src/data/layers/factory.tsx | 67 +++++++++++++++++++++++++++++++------ 1 file changed, 57 insertions(+), 10 deletions(-) diff --git a/src/data/layers/factory.tsx b/src/data/layers/factory.tsx index dd4f36c..39d2e7d 100644 --- a/src/data/layers/factory.tsx +++ b/src/data/layers/factory.tsx @@ -89,6 +89,7 @@ import Toy from "./Toy.vue"; import toys from "./toys"; import trees from "./trees"; import workshop from "./workshop"; +import ribbon from "./ribbon"; const id = "factory"; @@ -262,9 +263,15 @@ const factory = createLayer(id, () => { enabled: () => computedToyMultiplier.value.gt(1) })), createMultiplicativeModifier(() => ({ - multiplier: Decimal.div(boxes.buyables3.presentBuyable.amount.value, 10).add(1).pow(2), - description: "Carry boxes in... presents?", + multiplier: () => + Decimal.div(boxes.buyables3.presentBuyable.amount.value, 10).add(1).pow(2), + description: "Carry presents in boxes", enabled: carryPresents.bought + })), + createMultiplicativeModifier(() => ({ + multiplier: () => Decimal.add(ribbon.ribbon.value, 1), + description: "With a bow", + enabled: bowUpgrade.bought })) ]); const computedPresentMultipliers = computed(() => presentMultipliers.apply(1)); @@ -830,7 +837,10 @@ const factory = createLayer(id, () => { computedToyMultiplier.value )} toys of any type (from storage) to produce ${formatWhole( computedPresentMultipliers.value - )} presents every tick.` + )} presents every tick.` + + (catalysts.bought.value + ? " You can feed it wheels, buttons, stuffing, and circuit boards to increase its output." + : "") ), tick: 1, energyCost: 50, @@ -850,7 +860,20 @@ const factory = createLayer(id, () => { }, catalysts: computed(() => { if (!catalysts.bought.value) return [] as ResourceNames[]; - return ["block", "clothes", "trucks", "bear", "shovelBucket", "console"]; + return { + wheel: { + amount: 1 + }, + buttons: { + amount: 1 + }, + stuffing: { + amount: 1 + }, + circuitBoard: { + amount: 1 + } + }; }), canProduce: computed(() => { return Object.values(allToys).some(i => @@ -860,8 +883,17 @@ const factory = createLayer(id, () => { onProduce(times, stock) { const value = Object.values(allToys); - // TODO: use catalysts to multiply present gain - // catalysts are essentally excess inputs + let sumCatalysts: DecimalSource = catalysts.bought.value + ? (["wheel", "buttons", "stuffing", "circuitBoard"] as const) + .map(c => stock?.[c] ?? 0) + .reduce(Decimal.add, Decimal.dZero) + .add(1) + : 1; + if (stock) { + (["wheel", "buttons", "stuffing", "circuitBoard"] as const).forEach( + c => delete stock[c] + ); + } while (times > 0) { while (Decimal.lt(value[toysIndex].value, computedToyMultiplier.value)) { @@ -871,7 +903,11 @@ const factory = createLayer(id, () => { toysIndex = (toysIndex + 1) % value.length; toyToPick.value = Decimal.sub(toyToPick.value, computedToyMultiplier.value); times--; - presents.value = Decimal.add(presents.value, computedPresentMultipliers.value); + presents.value = Decimal.add( + presents.value, + Decimal.times(computedPresentMultipliers.value, sumCatalysts) + ); + sumCatalysts = 1; } }, visible: main.days[presentsDay - 1].opened @@ -1025,7 +1061,7 @@ const factory = createLayer(id, () => { inputs?: Stock; /** amount it produces */ outputs?: Stock; - catalysts?: ProcessedComputable; + catalysts?: ProcessedComputable; /** on produce, do something */ onProduce?: ( @@ -1308,6 +1344,16 @@ const factory = createLayer(id, () => { }, visibility: () => showIf(carryPresents.bought.value) })); + const bowUpgrade = createUpgrade(() => ({ + resource: noPersist(presents), + cost: 1e7, + display: { + title: "With a bow", + description: + "These presents need ribbon to make the bows, right? Multiply present gain by the amount of ribbon you have" + }, + visibility: () => showIf(catalysts.bought.value) + })); const factoryBuyables = { expandFactory, oilFuel, carryToys }; const factoryBuyables2 = { carryBoxes }; const upgrades = [ @@ -1427,7 +1473,7 @@ const factory = createLayer(id, () => { })) ], [betterFactory, betterLighting, excitmentUpgrade, carryPresents], - [catalysts] + [catalysts, bowUpgrade] ]; // pixi @@ -2182,7 +2228,8 @@ const factory = createLayer(id, () => { (compHovered.value as FactoryComponentProcessor).inputStock, { ...(FACTORY_COMPONENTS[compHovered.value.type].inputs ?? {}), - ...(FACTORY_COMPONENTS[compHovered.value.type].catalysts ?? {}) + ...(unref(FACTORY_COMPONENTS[compHovered.value.type].catalysts) ?? + {}) }, "Inputs:" )} From 081ad4fd860c10d9c8a4d7f3494d71dd7b195739 Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Fri, 23 Dec 2022 22:27:00 -0600 Subject: [PATCH 40/48] Potential fix for letters bug? --- src/data/layers/letters.tsx | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/data/layers/letters.tsx b/src/data/layers/letters.tsx index 6f27eb6..a086407 100644 --- a/src/data/layers/letters.tsx +++ b/src/data/layers/letters.tsx @@ -76,10 +76,9 @@ const layer = createLayer(id, function (this: BaseLayer) { if (Decimal.lt(processingProgress.value, computedProcessingCooldown.value)) { return; } - const amount = Decimal.div( - processingProgress.value, - computedProcessingCooldown.value - ).floor(); + const amount = Decimal.div(processingProgress.value, computedProcessingCooldown.value) + .floor() + .max(1); letters.value = Decimal.times(amount, computedLettersGain.value) .add(letters.value) .min(8e9); @@ -339,7 +338,6 @@ const layer = createLayer(id, function (this: BaseLayer) { ) : null} {render(process)} - If your letters are stuck, try holding L {Decimal.lt(totalLetters.value, 8e9) ? (
The more letters you process, the more you'll improve at processing letters. From f861787a27b07a99cd464eb76275abf5a5b1aa4e Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Fri, 23 Dec 2022 22:30:37 -0600 Subject: [PATCH 41/48] Fixed trying to write to computed ref --- src/data/layers/ribbon.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/data/layers/ribbon.tsx b/src/data/layers/ribbon.tsx index 0932a76..0c091dc 100644 --- a/src/data/layers/ribbon.tsx +++ b/src/data/layers/ribbon.tsx @@ -93,7 +93,6 @@ const layer = createLayer(id, () => { if (!unref(makeRibbon.canClick)) { return; } - currentDyeType.value.amount.value = 0; currentDyeType.value.buyable.amount.value = 0; cloth.cloth.value = Decimal.sub(cloth.cloth.value, 1e9); ribbon.value = Decimal.add(ribbon.value, 1); From e4f50326327fb51995a2344466982c32e0bb37e4 Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Fri, 23 Dec 2022 22:55:12 -0600 Subject: [PATCH 42/48] Balancing --- src/data/layers/reindeer.tsx | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/data/layers/reindeer.tsx b/src/data/layers/reindeer.tsx index a5f2ed2..74795a4 100644 --- a/src/data/layers/reindeer.tsx +++ b/src/data/layers/reindeer.tsx @@ -41,7 +41,7 @@ const layer = createLayer(id, function (this: BaseLayer) { const name = "Reindeer"; const color = "saddlebrown"; - const feedGoal = 2.5e3; + const feedGoal = 1.5e3; const timeSinceFocus = persistent(0); @@ -84,6 +84,9 @@ const layer = createLayer(id, function (this: BaseLayer) { if (!currTargets.value[roll]) { currTargets.value[roll] = true; targetsSelected++; + if (upgrade8.bought.value) { + selectedReindeer.onClick(); + } } } } @@ -327,7 +330,7 @@ const layer = createLayer(id, function (this: BaseLayer) { const upgrade1 = createUpgrade(() => ({ resource: trees.logs, - cost: 0, + cost: 1e97, style: { width: "160px" }, @@ -339,7 +342,7 @@ const layer = createLayer(id, function (this: BaseLayer) { })); const upgrade2 = createUpgrade(() => ({ resource: coal.coal, - cost: 0, + cost: 1e167, style: { width: "160px" }, @@ -351,7 +354,7 @@ const layer = createLayer(id, function (this: BaseLayer) { })); const upgrade3 = createUpgrade(() => ({ resource: paper.paper, - cost: 0, + cost: 1e117, style: { width: "160px" }, @@ -363,7 +366,7 @@ const layer = createLayer(id, function (this: BaseLayer) { })); const upgrade4 = createUpgrade(() => ({ resource: boxes.boxes, - cost: 0, + cost: 1e102, style: { width: "160px" }, @@ -375,7 +378,7 @@ const layer = createLayer(id, function (this: BaseLayer) { })); const upgrade5 = createUpgrade(() => ({ resource: metal.metal, - cost: 0, + cost: 1e67, style: { width: "160px" }, @@ -387,7 +390,7 @@ const layer = createLayer(id, function (this: BaseLayer) { })); const upgrade6 = createUpgrade(() => ({ resource: cloth.cloth, - cost: 0, + cost: 1e20, style: { width: "160px" }, @@ -399,7 +402,7 @@ const layer = createLayer(id, function (this: BaseLayer) { })); const upgrade7 = createUpgrade(() => ({ resource: oil.oil, - cost: 0, + cost: 4e25, style: { width: "160px" }, @@ -411,7 +414,7 @@ const layer = createLayer(id, function (this: BaseLayer) { })); const upgrade8 = createUpgrade(() => ({ resource: plastic.plastic, - cost: 0, + cost: 1e22, style: { width: "160px" }, @@ -422,7 +425,7 @@ const layer = createLayer(id, function (this: BaseLayer) { })); const upgrade9 = createUpgrade(() => ({ resource: dyes.dyes.white.amount, - cost: 0, + cost: 7.5e7, style: { width: "160px" }, From 0bcd920f4d64859e0c217ae0ff77d3fb7d52db05 Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Fri, 23 Dec 2022 23:29:52 -0600 Subject: [PATCH 43/48] Art! --- src/data/Scene.vue | 9 ++++++++- src/data/projEntry.tsx | 3 ++- src/data/symbols/reindeer.png | Bin 0 -> 58589 bytes 3 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 src/data/symbols/reindeer.png diff --git a/src/data/Scene.vue b/src/data/Scene.vue index 149926f..8dc001f 100644 --- a/src/data/Scene.vue +++ b/src/data/Scene.vue @@ -6,7 +6,13 @@ class="scene-item" style="left: 4%; bottom: 3%; width: 40px; height: 40px" /> - + + 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 literal 0 HcmV?d00001 From 53e8669061a146c941ec1b8aace67a2bfa3b847e Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Fri, 23 Dec 2022 23:34:49 -0600 Subject: [PATCH 44/48] Potential fix for some tab weirdness --- src/components/Game.vue | 5 ++--- src/components/Layer.vue | 46 +++------------------------------------- src/game/layers.tsx | 32 +++++++++++++++++++++++++++- 3 files changed, 36 insertions(+), 47 deletions(-) diff --git a/src/components/Game.vue b/src/components/Game.vue index 238a17a..7ba0d18 100644 --- a/src/components/Game.vue +++ b/src/components/Game.vue @@ -66,9 +66,8 @@ const useHeader = projInfo.useHeader; const loreBody = computeOptionalComponent(main.loreBody); function gatherLayerProps(layer: GenericLayer) { - const { display, minimized, minWidth, name, color, minimizable, nodes, minimizedDisplay } = - layer; - return { display, minimized, minWidth, name, color, minimizable, nodes, minimizedDisplay }; + const { display, minimized, name, color, minimizable, nodes, minimizedDisplay } = layer; + return { display, minimized, name, color, minimizable, nodes, minimizedDisplay }; } diff --git a/src/components/Layer.vue b/src/components/Layer.vue index a160a0b..f599543 100644 --- a/src/components/Layer.vue +++ b/src/components/Layer.vue @@ -2,7 +2,7 @@

- @@ -34,10 +34,6 @@ export default defineComponent({ type: Number, required: true }, - tab: { - type: Function as PropType<() => HTMLElement | undefined>, - required: true - }, display: { type: processedPropType(Object, String, Function), required: true @@ -47,10 +43,6 @@ export default defineComponent({ type: Object as PropType>, required: true }, - minWidth: { - type: processedPropType(Number, String), - required: true - }, name: { type: processedPropType(String), required: true @@ -63,7 +55,7 @@ export default defineComponent({ } }, setup(props) { - const { display, index, minimized, minWidth, tab, minimizedDisplay, name } = toRefs(props); + const { display, index, minimized, minimizedDisplay } = toRefs(props); const component = computeComponent(display); const minimizedComponent = computeOptionalComponent(minimizedDisplay); @@ -79,39 +71,10 @@ export default defineComponent({ minimized.value = min; } - nextTick(() => updateTab(minimized.value, unref(minWidth.value))); - watch([name, minimized, wrapRef(minWidth)], ([name, minimized, minWidth]) => { - updateTab(minimized, minWidth); - }); - function updateNodes(nodes: Record) { props.nodes.value = nodes; } - function updateTab(min: boolean, minWidth: number | string) { - minimized.value = min; - const width = - typeof minWidth === "number" || Number.isNaN(parseInt(minWidth)) - ? minWidth + "px" - : minWidth; - const tabValue = tab.value(); - if (tabValue != undefined) { - if (min) { - tabValue.style.flexGrow = "0"; - tabValue.style.flexShrink = "0"; - tabValue.style.width = "60px"; - tabValue.style.minWidth = tabValue.style.flexBasis = ""; - tabValue.style.margin = "0"; - } else { - tabValue.style.flexGrow = ""; - tabValue.style.flexShrink = ""; - tabValue.style.width = ""; - tabValue.style.minWidth = tabValue.style.flexBasis = width; - tabValue.style.margin = ""; - } - } - } - return { component, minimizedComponent, @@ -119,16 +82,13 @@ export default defineComponent({ updateNodes, unref, goBack, - setMinimized, - minimized, - minWidth + setMinimized }; } });