Get dye elf functional and into management

This commit is contained in:
Seth Posner 2022-12-18 17:07:09 -08:00
parent 507cf0f081
commit bacac4e72c
6 changed files with 153 additions and 107 deletions

View file

@ -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,

View file

@ -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();
}
});

View file

@ -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,

View file

@ -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) },

View file

@ -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
};
});

View file

@ -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 () {