From bacac4e72c57ed207bc4b82920344e5607995e48 Mon Sep 17 00:00:00 2001 From: Seth Posner <smartseth@hotmail.com> Date: Sun, 18 Dec 2022 17:07:09 -0800 Subject: [PATCH] Get dye elf functional and into management --- src/data/layers/dyes.tsx | 73 +++++++++++++++++++------- src/data/layers/elves.tsx | 22 +++++--- src/data/layers/management.tsx | 74 +++++++++++++++++++++++---- src/data/layers/paper.tsx | 16 ++++-- src/data/layers/wrapping-paper.tsx | 69 +++---------------------- src/features/milestones/milestone.tsx | 6 +-- 6 files changed, 153 insertions(+), 107 deletions(-) diff --git a/src/data/layers/dyes.tsx b/src/data/layers/dyes.tsx index 7eeb7c1..1bfd305 100644 --- a/src/data/layers/dyes.tsx +++ b/src/data/layers/dyes.tsx @@ -112,7 +112,7 @@ const layer = createLayer(id, function (this: BaseLayer) { })) ); } - if (options.color === "red" || options.color === "yellow") { + if (["red", "yellow"].includes(options.color)) { modifiers.push( createMultiplicativeModifier(() => ({ multiplier: boosts.orange1, @@ -120,7 +120,7 @@ const layer = createLayer(id, function (this: BaseLayer) { })) ); } - if (options.color == "yellow" || options.color == "blue") { + if (["yellow", "blue"].includes(options.color)) { modifiers.push( createMultiplicativeModifier(() => ({ multiplier: boosts.green1, @@ -128,7 +128,7 @@ const layer = createLayer(id, function (this: BaseLayer) { })) ); } - if (options.color == "red" || options.color == "blue") { + if (["red", "blue"].includes(options.color)) { modifiers.push( createMultiplicativeModifier(() => ({ multiplier: boosts.purple1, @@ -136,7 +136,7 @@ const layer = createLayer(id, function (this: BaseLayer) { })) ); } - if (options.color == "red" || options.color == "yellow" || options.color == "blue") { + if (["red", "yellow", "blue"].includes(options.color)) { modifiers.push( createMultiplicativeModifier(() => ({ multiplier: 2, @@ -156,21 +156,17 @@ const layer = createLayer(id, function (this: BaseLayer) { modifiers.push( createMultiplicativeModifier(() => ({ multiplier: 2, - description: "Wrapping Paper Milestone 1", - enabled: wrappingPaper.milestones.primaryBoost.earned + description: "Carol Level 1", + enabled: management.elfTraining.dyeElfTraining.milestones[0].earned })) ); } - if ( - options.color == "orange" || - options.color == "green" || - options.color == "purple" - ) { + if (["orange", "green", "purple"].includes(options.color)) { modifiers.push( createMultiplicativeModifier(() => ({ multiplier: 2, - description: "Wrapping Paper Milestone 2", - enabled: wrappingPaper.milestones.secondaryBoost.earned + description: "Carol Level 2", + enabled: management.elfTraining.dyeElfTraining.milestones[1].earned })) ); } @@ -194,6 +190,24 @@ const layer = createLayer(id, function (this: BaseLayer) { }) as WithRequired<Modifier, "description" | "revert">; const computedToGenerate = computed(() => toGenerate.apply(0)); + let dyeBook: ElfBuyable & { + resource: Resource; + freeLevels: ComputedRef<DecimalSource>; + totalAmount: ComputedRef<DecimalSource>; + }; + switch (options.color) { + case 'red': + case 'yellow': + case 'blue': + dyeBook = paper.books.primaryDyeBook; + break; + case 'orange': + case 'green': + case 'purple': + dyeBook = paper.books.secondaryDyeBook; + break; + } + const buyable: ElfBuyable = createBuyable(() => { const costs = convertComputable(options.costs); return { @@ -250,12 +264,12 @@ const layer = createLayer(id, function (this: BaseLayer) { let v = buyable.amount.value; if (Decimal.gte(v, 25)) v = Decimal.pow(v, 2).div(20); // intentional price jump #2 if (Decimal.gte(v, 10)) v = Decimal.pow(v, 2).div(5); // intentional price jump - v = Decimal.mul(v, Decimal.pow(0.95, paper.books.dyeBook.totalAmount.value)); + v = Decimal.mul(v, Decimal.pow(0.95, dyeBook.totalAmount.value)); return Decimal.div(v, 10).plus(1); }, inverseCostPre(x: DecimalSource) { let v = Decimal.sub(x, 1).mul(10); - v = v.div(Decimal.pow(0.95, paper.books.dyeBook.totalAmount.value)); + v = v.div(Decimal.pow(0.95, dyeBook.totalAmount.value)); if (Decimal.gte(v, 10)) v = Decimal.mul(v, 5).root(2); if (Decimal.gte(v, 25)) v = Decimal.mul(v, 20).root(2); return Decimal.isNaN(v) ? Decimal.dZero : v.floor().max(0); @@ -283,12 +297,33 @@ const layer = createLayer(id, function (this: BaseLayer) { ); }), onPurchase(cost?: DecimalSource) { - const trueCost = cost ?? unref(buyable.cost) ?? Decimal.dInf; + let buyMax = false; + switch (options.color) { + case 'red': + case 'yellow': + case 'blue': + buyMax = management.elfTraining.dyeElfTraining.milestones[2].earned.value; + break; + case 'orange': + case 'green': + case 'purple': + buyMax = management.elfTraining.dyeElfTraining.milestones[4].earned.value; + break; + } - amount.value = Decimal.add(amount.value, computedToGenerate.value); - buyable.amount.value = Decimal.add(buyable.amount.value, 1); + if (buyMax) { + const buyAmount = this.inverseCost().sub(this.amount.value).plus(1); + if (buyAmount.lte(0)) return; - if (!wrappingPaper.milestones.secondaryNoReset.earned.value) { + amount.value = Decimal.times(computedToGenerate.value, buyAmount).add(amount.value); + buyable.amount.value = Decimal.add(buyable.amount.value, buyAmount); + } + else { + amount.value = Decimal.add(amount.value, computedToGenerate.value); + buyable.amount.value = Decimal.add(buyable.amount.value, 1); + } + if (!management.elfTraining.dyeElfTraining.milestones[3].earned.value) { + const trueCost = cost ?? unref(buyable.cost) ?? Decimal.dInf; unref(costs).forEach(c => { c.res.value = Decimal.sub( c.res.value, diff --git a/src/data/layers/elves.tsx b/src/data/layers/elves.tsx index 4474603..f511ff9 100644 --- a/src/data/layers/elves.tsx +++ b/src/data/layers/elves.tsx @@ -36,7 +36,7 @@ import plastic from "./plastic"; import trees from "./trees"; import workshop from "./workshop"; import wrappingPaper from "./wrapping-paper"; -import dyes from "./dyes"; +import dyes, { enumColor } from "./dyes"; export interface ElfBuyable extends GenericBuyable { /** The inverse function of the cost formula, used to calculate the maximum amount that can be bought by elves. */ @@ -902,14 +902,25 @@ const layer = createLayer(id, function (this: BaseLayer) { showIf(management.elfTraining.fertilizerElfTraining.milestones[4].earned.value) }); const managementElves2 = [metalElf]; + + const dyeColors = Object.fromEntries((["red", "yellow", "blue", "orange", "green", "purple"] as enumColor[]) + .map(color => [dyes.dyes[color].buyable.id, color])) as Record<string, enumColor>; const dyeElf = createElf({ name: "Carol", description: "Carol will automatically purchase all dyes you can afford, without actually spending any resources.", buyable: Object.values(dyes.dyes).map(dye => dye.buyable), cooldownModifier: dyeCooldown, // Note: Buy max will be unlocked at this point - visibility: () => showIf(wrappingPaper.milestones.unlockDyeElf.earned.value), - buyMax: true + visibility: () => showIf(wrappingPaper.unlockDyeElfMilestone.earned.value), + buyMax: management.elfTraining.dyeElfTraining.milestones[2].earned, + onAutoPurchase(buyable, amount) { + if (["orange", "green", "purple"].includes(dyeColors[buyable.id])) { + if (false) { // does not have ribbon milestone 1 + buyable.amount.value = Decimal.sub(buyable.amount.value, amount) + return; + } + } + } }); const wrappingPaperElves = [dyeElf]; const elves = { @@ -1076,11 +1087,6 @@ const layer = createLayer(id, function (this: BaseLayer) { Decimal.gte(coal.coal.value, coalGoal) ) { main.completeDay(); - } else if ( - main.currentlyMastering.value?.name === name && - Decimal.gte(coal.coal.value, options.masteryGoal ?? options.goal) - ) { - main.completeMastery(); } }); diff --git a/src/data/layers/management.tsx b/src/data/layers/management.tsx index 342f427..7eb06f3 100644 --- a/src/data/layers/management.tsx +++ b/src/data/layers/management.tsx @@ -1056,6 +1056,47 @@ const layer = createLayer(id, () => { } })) ] as Array<GenericMilestone>; + const dyeElfMilestones = [ + createMilestone(() => ({ + display: { + requirement: "Carol Level 1", + effectDisplay: "Double primary dye gain" + }, + shouldEarn: () => dyeElfTraining.level.value >= 1 + })), + createMilestone(() => ({ + display: { + requirement: "Carol Level 2", + effectDisplay: "Double secondary dye gain" + }, + shouldEarn: () => dyeElfTraining.level.value >= 2, + visibility: () => showIf(dyeElfMilestones[0].earned.value) + })), + createMilestone(() => ({ + display: { + requirement: "Carol Level 3", + effectDisplay: "Buy maximum primary dyes" + }, + shouldEarn: () => dyeElfTraining.level.value >= 3, + visibility: () => showIf(dyeElfMilestones[1].earned.value) + })), + createMilestone(() => ({ + display: { + requirement: "Carol Level 4", + effectDisplay: "Secondary dyes don't spend primary dyes" + }, + shouldEarn: () => dyeElfTraining.level.value >= 4, + visibility: () => showIf(dyeElfMilestones[2].earned.value && main.day.value >= 16) + })), + createMilestone(() => ({ + display: { + requirement: "Carol Level 5", + effectDisplay: "Buy maximum secondary dyes" + }, + shouldEarn: () => dyeElfTraining.level.value >= 5, + visibility: () => showIf(dyeElfMilestones[3].earned.value && main.day.value >= 16) + })) + ] as Array<GenericMilestone>; // ------------------------------------------------------------------------------- Milestone display const currentShown = persistent<string>("Holly"); @@ -1132,10 +1173,10 @@ const layer = createLayer(id, () => { const oilElfTraining = createElfTraining(elves.elves.oilElf, oilElfMilestones); const heavyDrillElfTraining = createElfTraining( elves.elves.heavyDrillElf, - heavyDrillElfMilestones - ); + heavyDrillElfMilestones); + const dyeElfTraining = createElfTraining(elves.elves.dyeElf, dyeElfMilestones); const row5Elves = [coalDrillElfTraining, heavyDrillElfTraining, oilElfTraining]; - const row6Elves = [metalElfTraining]; + const row6Elves = [metalElfTraining, dyeElfTraining]; const elfTraining = { cutterElfTraining, planterElfTraining, @@ -1152,7 +1193,8 @@ const layer = createLayer(id, () => { coalDrillElfTraining, metalElfTraining, oilElfTraining, - heavyDrillElfTraining + heavyDrillElfTraining, + dyeElfTraining }; const day12Elves = [ cutterElfTraining, @@ -1637,6 +1679,7 @@ const layer = createLayer(id, () => { main.completeDay(); } else if ( main.day.value === advancedDay && + day12Elves.every(elf => elf.level.value >= 5) && day13Elves.every(elf => elf.level.value >= 5) ) { main.completeDay(); @@ -1804,6 +1847,16 @@ const layer = createLayer(id, () => { { earned: persistent<boolean>(false) }, { earned: persistent<boolean>(false) } ] + }, + dyeElfTraining: { + exp: persistent<DecimalSource>(0), + milestones: [ + { earned: persistent<boolean>(false) }, + { earned: persistent<boolean>(false) }, + { earned: persistent<boolean>(false) }, + { earned: persistent<boolean>(false) }, + { earned: persistent<boolean>(false) } + ] } }, teaching: { bought: persistent<boolean>(false) }, @@ -1860,8 +1913,9 @@ const layer = createLayer(id, () => { {main.day.value === day ? `Get all elves to level 3.` : main.day.value === advancedDay && main.days[advancedDay - 1].opened.value - ? `Get all elves to level 5.` - : `${name} Complete!`}{" "} + ? `Get all elves to level 5.` + : `${name} Complete!` + }{" "} - <button class="button" @@ -1878,13 +1932,13 @@ const layer = createLayer(id, () => { <Spacer /> {Decimal.gt(schools.amount.value, 0) ? ( <> - <br /> + <Spacer /> Click on an elf to see their milestones. - <br /> - <br /> + <Spacer /> + <Spacer /> {render(focusButton)} {renderGrid(upgrades, upgrades2)} - <br /> + <Spacer /> {renderGrid( [focusMeter], treeElfTraining, diff --git a/src/data/layers/paper.tsx b/src/data/layers/paper.tsx index e8ed248..4a0db7b 100644 --- a/src/data/layers/paper.tsx +++ b/src/data/layers/paper.tsx @@ -283,12 +283,18 @@ const layer = createLayer(id, function (this: BaseLayer) { buyableName: "Metal Machines", visibility: () => showIf(elves.elves.metalElf.bought.value) }); - const dyeBook = createBook({ + const primaryDyeBook = createBook({ name: "Arts and Crafts", elfName: "Carol", - buyableName: "Dyes", + buyableName: "Primary Dyes", visibility: () => showIf(elves.elves.dyeElf.bought.value) }); + const secondaryDyeBook = createBook({ + name: "", + elfName: "Carol", + buyableName: "Secondary Dyes", + visibility: () => showIf(elves.elves.dyeElf.bought.value && true) // ribbons secondary dye book milestone + }); const books = { cuttersBook, plantersBook, @@ -306,7 +312,8 @@ const layer = createLayer(id, function (this: BaseLayer) { heavyDrillBook, oilBook, metalBook, - dyeBook + primaryDyeBook, + secondaryDyeBook }; const sumBooks = computed(() => Object.values(books).reduce((acc, curr) => acc.add(curr.amount.value), new Decimal(0)) @@ -488,7 +495,8 @@ const layer = createLayer(id, function (this: BaseLayer) { heavyDrillBook: { amount: persistent<DecimalSource>(0) }, oilBook: { amount: persistent<DecimalSource>(0) }, metalBook: { amount: persistent<DecimalSource>(0) }, - dyeBook: { amount: persistent<DecimalSource>(0) } + primaryDyeBook: { amount: persistent<DecimalSource>(0) }, + secondaryDyeBook: { amount: persistent<DecimalSource>(0) } }, upgrades: { clothUpgrade: { bought: persistent<boolean>(false) }, diff --git a/src/data/layers/wrapping-paper.tsx b/src/data/layers/wrapping-paper.tsx index 698c9da..b5a9f6f 100644 --- a/src/data/layers/wrapping-paper.tsx +++ b/src/data/layers/wrapping-paper.tsx @@ -1,9 +1,8 @@ import Spacer from "components/layout/Spacer.vue"; -import { createCollapsibleMilestones } from "data/common"; import { createBar, GenericBar } from "features/bars/bar"; import { BuyableOptions, createBuyable, GenericBuyable } from "features/buyable"; import { createClickable } from "features/clickables/clickable"; -import { jsx, JSXFunction, showIf } from "features/feature"; +import { jsx, JSXFunction } from "features/feature"; import { createMilestone } from "features/milestones/milestone"; import MainDisplay from "features/resources/MainDisplay.vue"; import { createResource, Resource } from "features/resources/resource"; @@ -16,7 +15,6 @@ import { render, renderRow } from "util/vue"; import { computed, Ref, unref, watchEffect } from "vue"; import { main } from "../projEntry"; import { default as dyes, type enumColor } from "./dyes"; -import metal from "./metal"; const id = "wrappingPaper"; const day = 15; @@ -270,70 +268,16 @@ const layer = createLayer(id, () => { "Total Wrapping Paper" ); - const milestoneCosts = [10, 30, 90, 270, 810, 2430]; - - const primaryBoostMilestone = createMilestone(() => ({ - display: { - requirement: milestoneCosts[0] + " Total Wrapping Paper", - effectDisplay: "Double primary colour dye gain" - }, - shouldEarn: () => Decimal.gte(wrappingPaperSum.value, milestoneCosts[0]), - visibility: () => showIf(true) - })); - const secondaryBoostMilestone = createMilestone(() => ({ - display: { - requirement: milestoneCosts[1] + " Total Wrapping Paper", - effectDisplay: "Double secondary colour dye gain" - }, - shouldEarn: () => Decimal.gte(wrappingPaperSum.value, milestoneCosts[1]), - visibility: () => showIf(primaryBoostMilestone.earned.value) - })); - const buyMaxPrimaryMilestone = createMilestone(() => ({ - display: { - requirement: milestoneCosts[2] + " Total Wrapping Paper", - effectDisplay: "Buy maximum primary colour dyes" - }, - shouldEarn: () => Decimal.gte(wrappingPaperSum.value, milestoneCosts[2]), - visibility: () => showIf(secondaryBoostMilestone.earned.value) - })); - const secondaryNoResetMilestone = createMilestone(() => ({ - display: { - requirement: milestoneCosts[3] + " Total Wrapping Paper", - effectDisplay: "Secondary colour dyes don't spend primary colour dyes" - }, - shouldEarn: () => Decimal.gte(wrappingPaperSum.value, milestoneCosts[3]), - visibility: () => showIf(buyMaxPrimaryMilestone.earned.value) - })); - const buyMaxSecondaryMilestone = createMilestone(() => ({ - display: { - requirement: milestoneCosts[4] + " Total Wrapping Paper", - effectDisplay: "Buy maximum secondary colour dyes" - }, - shouldEarn: () => Decimal.gte(wrappingPaperSum.value, milestoneCosts[4]), - visibility: () => showIf(secondaryNoResetMilestone.earned.value) - })); const unlockDyeElfMilestone = createMilestone(() => ({ display: { - requirement: milestoneCosts[5] + " Total Wrapping Paper", + requirement: "10 Total Wrapping Paper", effectDisplay: "Unlock a new elf to help with dyes" }, - shouldEarn: () => Decimal.gte(wrappingPaperSum.value, milestoneCosts[5]), - visibility: () => showIf(buyMaxSecondaryMilestone.earned.value) + shouldEarn: () => Decimal.gte(wrappingPaperSum.value, 10) })); - const milestones = { - primaryBoost: primaryBoostMilestone, - secondaryBoost: secondaryBoostMilestone, - buyMaxPrimary: buyMaxPrimaryMilestone, - secondaryNoReset: secondaryNoResetMilestone, - buyMaxSecondary: buyMaxSecondaryMilestone, - unlockDyeElf: unlockDyeElfMilestone - }; - - const { collapseMilestones, display: milestonesDisplay } = - createCollapsibleMilestones(milestones); - const masteryReq = computed(() => Decimal.pow(2, masteredDays.value).times(30)); + const enterMasteryButton = createClickable(() => ({ display: () => ({ title: main.isMastery.value ? "Stop Decorating" : "Begin Decoration", @@ -444,14 +388,13 @@ const layer = createLayer(id, () => { <Spacer /> {render(enterMasteryButton)} <Spacer /> - {milestonesDisplay()} + {render(unlockDyeElfMilestone)} </div> ); }), wrappingPaper, boosts, - milestones, - collapseMilestones, + unlockDyeElfMilestone, minWidth: 700 }; }); diff --git a/src/features/milestones/milestone.tsx b/src/features/milestones/milestone.tsx index d70d6ec..e016e64 100644 --- a/src/features/milestones/milestone.tsx +++ b/src/features/milestones/milestone.tsx @@ -1,5 +1,5 @@ import Select from "components/fields/Select.vue"; -import type { CoercableComponent, OptionsFunc, Replace, StyleValue } from "features/feature"; +import type { CoercableComponent, GenericComponent, OptionsFunc, Replace, StyleValue } from "features/feature"; import { Component, GatherProps, getUniqueID, jsx, setDefault, Visibility } from "features/feature"; import MilestoneComponent from "features/milestones/Milestone.vue"; import { globalBus } from "game/events"; @@ -55,7 +55,7 @@ export interface BaseMilestone { earned: Persistent<boolean>; complete: VoidFunction; type: typeof MilestoneType; - [Component]: typeof MilestoneComponent; + [Component]: GenericComponent; [GatherProps]: () => Record<string, unknown>; } @@ -85,7 +85,7 @@ export function createMilestone<T extends MilestoneOptions>( const milestone = optionsFunc?.() ?? ({} as ReturnType<NonNullable<typeof optionsFunc>>); milestone.id = getUniqueID("milestone-"); milestone.type = MilestoneType; - milestone[Component] = MilestoneComponent; + milestone[Component] = MilestoneComponent as GenericComponent; milestone.earned = earned; milestone.complete = function () {