Complete packing elf and book

This commit is contained in:
Seth Posner 2022-12-24 00:57:10 -08:00
parent 8d3dd4f339
commit bcdd2e55f8
4 changed files with 233 additions and 21 deletions

View file

@ -39,6 +39,7 @@ import wrappingPaper from "./wrapping-paper";
import dyes, { enumColor } from "./dyes";
import ribbon from "./ribbon";
import letters from "./letters";
import packing from "./packing";
export interface ElfBuyable extends GenericBuyable {
/** The inverse function of the cost formula, used to calculate the maximum amount that can be bought by elves. */
@ -455,6 +456,23 @@ const layer = createLayer(id, function (this: BaseLayer) {
enabled: elvesMilestone2.earned
}))
]);
const packingCooldown = createSequentialModifier(() => [
createMultiplicativeModifier(() => ({
multiplier: 2,
description: "6 Elves Trained",
enabled: elvesMilestone.earned
})),
createMultiplicativeModifier(() => ({
multiplier: () => Decimal.times(paper.books.packingBook.totalAmount.value, 0.1).add(1),
description: "The Tetris Effect",
enabled: () => Decimal.gt(paper.books.packingBook.totalAmount.value, 0)
})),
createMultiplicativeModifier(() => ({
multiplier: 2,
description: "10 Elves Trained",
enabled: elvesMilestone2.earned
}))
]);
const [generalTab, generalTabCollapsed] = createCollapsibleModifierSections(() => [
{
@ -590,6 +608,13 @@ const layer = createLayer(id, function (this: BaseLayer) {
base: 10,
unit: "/s",
visible: plastic.masteryEffectActive
},
{
title: "Jingle Auto-Buy Frequency",
modifier: packingCooldown,
base: 10,
unit: "/s",
visible: packing.upgrades.packingElf.bought
}
]);
const showModifiersModal = ref(false);
@ -1012,6 +1037,20 @@ const layer = createLayer(id, function (this: BaseLayer) {
buyMax: () => management.elfTraining.plasticElfTraining.milestones[4].earned.value
});
const wrappingPaperElves = [dyeElf, plasticElf];
const packingElf = createElf({
name: "Jingle",
description: "Jingle will automatically hire more elves to help out with packing the sleigh.",
buyable: [packing.helpers.elf, packing.helpers.loader],
cooldownModifier: packingCooldown,
visibility: () => showIf(packing.upgrades.packingElf.bought.value),
buyMax: true,
onAutoPurchase(buyable, amount) {
if (buyable === packing.helpers.loader && !management.elfTraining.packingElfTraining.milestones[3].earned.value) {
buyable.amount.value = Decimal.sub(buyable.amount.value, amount);
}
}
});
const elves = {
cuttersElf,
plantersElf,
@ -1030,7 +1069,8 @@ const layer = createLayer(id, function (this: BaseLayer) {
oilElf,
metalElf,
dyeElf,
plasticElf
plasticElf,
packingElf
};
const totalElves = computed(() => Object.values(elves).filter(elf => elf.bought.value).length);
@ -1277,6 +1317,11 @@ const layer = createLayer(id, function (this: BaseLayer) {
buyProgress: persistent<DecimalSource>(0),
amountOfTimesDone: persistent<number>(0),
bought: persistent<boolean>(false)
},
packingElf: {
buyProgress: persistent<DecimalSource>(0),
amountOftimesDone: persistent<number>(0),
bought: persistent<boolean>(false)
}
},
milestones: [
@ -1332,7 +1377,8 @@ const layer = createLayer(id, function (this: BaseLayer) {
fireElves,
plasticElves,
managementElves,
managementElves2.concat(wrappingPaperElves)
managementElves2.concat(wrappingPaperElves),
[packingElf]
)}
</div>
{milestonesDisplay()}

View file

@ -26,7 +26,6 @@ import boxes from "./boxes";
import cloth from "./cloth";
import coal from "./coal";
import dyes from "./dyes";
import elves from "./elves";
import metal from "./metal";
import oil from "./oil";
import paper from "./paper";
@ -37,6 +36,8 @@ import "./styles/management.css";
import { Resource } from "features/resources/resource";
import { isArray } from "@vue/shared";
import { createTab } from "features/tabs/tab";
import packing from "./packing";
import elves from "./elves";
const id = "management";
const day = 12;
@ -189,11 +190,15 @@ const layer = createLayer(id, () => {
"Cocoa",
"Twinkle",
"Carol",
"Tinsel"
"Tinsel",
"Jingle"
].indexOf(elf.name) + 1;
if (elf.name == "Star" || elf.name == "Bell") {
costMulti /= 3;
}
if (elf.name == "Jingle") {
costMulti *= 30;
}
const costBase = 4000 * costMulti;
const expRequiredForNextLevel = computed(() => Decimal.pow(5, level.value).mul(costBase));
const level = computed(() =>
@ -1139,6 +1144,57 @@ const layer = createLayer(id, () => {
visibility: () => showIf(plasticElfMilestones[3].earned.value && main.day.value >= 16)
}))
] as Array<GenericMilestone>;
const packingElfMilestones = [
createMilestone(() => ({
display: {
requirement: "Jingle Level 1",
effectDisplay: "Double elf packing speed"
},
shouldEarn: () => packingElfTraining.level.value >= 1
})),
createMilestone(() => ({
display: {
requirement: "Jingle Level 2",
effectDisplay: jsx(() => (
<>
Each elf assistant increases packing speed by 10%<br />
Currently: +{formatWhole(Decimal.times(packing.helpers.elf.amount.value, 0.1).times(100))}%
</>
))
},
shouldEarn: () => packingElfTraining.level.value >= 2,
visibility: () => showIf(packingElfMilestones[0].earned.value)
})),
createMilestone(() => ({
display: {
requirement: "Jingle Level 3",
effectDisplay: jsx(() => (
<>
Multiply packing speed by the number of completed packing milestones<br />
Currently: {formatWhole(Object.values(packing.packingMilestones).filter(milestone => milestone.earned.value).length+1)}x
</>
))
},
shouldEarn: () => packingElfTraining.level.value >= 3,
visibility: () => showIf(packingElfMilestones[1].earned.value)
})),
createMilestone(() => ({
display: {
requirement: "Jingle Level 4",
effectDisplay: "Jingle will now also buy loaders"
},
shouldEarn: () => packingElfTraining.level.value >= 4,
visibility: () => showIf(packingElfMilestones[2].earned.value && main.day.value >= 16)
})),
createMilestone(() => ({
display: {
requirement: "Jingle Level 5",
effectDisplay: "Multipliers to elf packing speed also apply to loaders"
},
shouldEarn: () => packingElfTraining.level.value >= 5,
visibility: () => showIf(packingElfMilestones[3].earned.value && main.day.value >= 16)
}))
] as Array<GenericMilestone>;
// ------------------------------------------------------------------------------- Milestone display
const currentShown = persistent<string>("Holly");
@ -1219,8 +1275,10 @@ const layer = createLayer(id, () => {
);
const dyeElfTraining = createElfTraining(elves.elves.dyeElf, dyeElfMilestones);
const plasticElfTraining = createElfTraining(elves.elves.plasticElf, plasticElfMilestones);
const packingElfTraining = createElfTraining(elves.elves.packingElf, packingElfMilestones);
const row5Elves = [coalDrillElfTraining, heavyDrillElfTraining, oilElfTraining];
const row6Elves = [metalElfTraining, dyeElfTraining, plasticElfTraining];
const row7Elves = [packingElfTraining]
const elfTraining = {
cutterElfTraining,
planterElfTraining,
@ -1239,7 +1297,8 @@ const layer = createLayer(id, () => {
oilElfTraining,
heavyDrillElfTraining,
dyeElfTraining,
plasticElfTraining
plasticElfTraining,
packingElfTraining
};
const day12Elves = [
cutterElfTraining,
@ -1761,6 +1820,12 @@ const layer = createLayer(id, () => {
modifier: plasticElfTraining.elfXPGain,
base: 0.1,
unit: " XP"
},
{
title: "Jingle XP Gain per Action",
modifier: packingElfTraining.elfXPGain,
base: 0.1,
unit: " XP"
}
]);
const showModifiersModal = ref(false);
@ -2056,7 +2121,8 @@ const layer = createLayer(id, () => {
fireElfTraining,
plasticElvesTraining,
row5Elves,
row6Elves
row6Elves,
row7Elves
)}
<Spacer />
{currentElfDisplay()}

View file

@ -10,7 +10,7 @@ import { createMilestone, GenericMilestone } from "features/milestones/milestone
import MainDisplayVue from "features/resources/MainDisplay.vue";
import { createResource, trackBest, trackTotal, Resource } from "features/resources/resource";
import { createLayer, BaseLayer } from "game/layers";
import { createSequentialModifier } from "game/modifiers";
import { createMultiplicativeModifier, createSequentialModifier } from "game/modifiers";
import { persistent } from "game/persistence";
import Decimal, { DecimalSource, format, formatWhole } from "util/bignum";
import { Direction } from "util/common";
@ -20,6 +20,10 @@ import metal from "./metal";
import oil from "./oil";
import { createCollapsibleMilestones } from "data/common"
import { globalBus } from "game/events";
import { createUpgrade } from "features/upgrades/upgrade";
import { ElfBuyable } from "./elves";
import management from "./management";
import paper from "./paper";
const id = "packing"
const day = 24;
@ -92,18 +96,65 @@ const layer = createLayer(id, function (this: BaseLayer) {
const remainingSize = computed(() => Decimal.sub(sledSpace, packedPresentsSize.value));
const elfPackingSpeed = createSequentialModifier(() => [
createMultiplicativeModifier(() => ({
multiplier: () => Decimal.pow(0.5, packingResets.value),
description: "Better Organization",
enabled: () => packingResets.value >= 1
})),
createMultiplicativeModifier(() => ({
multiplier: 2,
description: "Jingle Level 1",
enabled: management.elfTraining.packingElfTraining.milestones[0].earned
})),
createMultiplicativeModifier(() => ({
multiplier: () => Decimal.times(helpers.elf.amount.value, 0.1).plus(1),
description: "Jingle Level 2",
enabled: management.elfTraining.packingElfTraining.milestones[1].earned
})),
createMultiplicativeModifier(() => ({
multiplier: () => 1 + Object.values(packingMilestones).filter(milestone => milestone.earned).length,
description: "Jingle Level 3",
enabled: management.elfTraining.packingElfTraining.milestones[2].earned
}))
]);
const computedElfPackingSpeed = computed(() => elfPackingSpeed.apply(1));
const loaderPackingSpeed = createSequentialModifier(() => [
createMultiplicativeModifier(() => ({
multiplier: () => Decimal.pow(0.5, packingResets.value),
description: "Better Organization",
enabled: () => packingResets.value >= 1
})),
createMultiplicativeModifier(() => ({
multiplier: 2,
description: "Jingle Level 1",
enabled: management.elfTraining.packingElfTraining.milestones[4].earned
})),
createMultiplicativeModifier(() => ({
multiplier: () => Decimal.times(helpers.elf.amount.value, 0.1).plus(1),
description: "Jingle Level 2",
enabled: management.elfTraining.packingElfTraining.milestones[4].earned
})),
createMultiplicativeModifier(() => ({
multiplier: () => 1 + Object.values(packingMilestones).filter(milestone => milestone.earned).length,
description: "Jingle Level 3",
enabled: management.elfTraining.packingElfTraining.milestones[4].earned
}))
]);
const computedLoaderPackingSpeed = computed(() => loaderPackingSpeed.apply(1000));
const helpers = {
elf: createBuyable(() => ({
visibility: () => showIf(Decimal.gte(totalPresents.value, 10)),
cost() { return Decimal.pow(1.2, this.amount.value).times(10).floor() },
cost() {
let v = this.amount.value;
v = Decimal.pow(0.95, paper.books.packingBook.totalAmount.value).times(v);
return Decimal.pow(1.2, v).times(10).floor()
},
inverseCost(cost: DecimalSource) {
let amount = Decimal.div(cost, 10).log(1.2);
amount = amount.div(Decimal.pow(0.95, paper.books.packingBook.totalAmount.value));
return Decimal.isNaN(amount) ? Decimal.dZero : amount.floor().max(0);
},
resource: totalPresentsResource,
display: jsx(() => (
<>
@ -121,13 +172,19 @@ const layer = createLayer(id, function (this: BaseLayer) {
}
})),
loader: createBuyable(() => ({
visibility: () => showIf(false),
metalCost: computed(() => Decimal.pow(1.5, helpers.loader.amount.value).times(1e40) ),
oilCost: computed(() => Decimal.pow(1.5, helpers.loader.amount.value).times(1e20) ),
visibility: () => showIf(upgrades.loaderUnlock.bought.value),
metalCost: computed(() => Decimal.pow(1.2, helpers.loader.amount.value).times(1e70) ),
oilCost: computed(() => Decimal.pow(1.2, helpers.loader.amount.value).times(1e25) ),
canPurchase(this: GenericBuyable & {metalCost: ComputedRef<DecimalSource>, oilCost: ComputedRef<DecimalSource>}) {
return Decimal.gte(metal.metal.value, this.metalCost.value)
&& Decimal.gte(oil.oil.value, this.oilCost.value)
},
inverseCost() {
let metalAmount = Decimal.div(metal.metal.value, 1e40).log(1.5);
let oilAmount = Decimal.div(oil.oil.value, 1e20).log(1.5);
if (Decimal.isNaN(metalAmount) || Decimal.isNaN(oilAmount)) return Decimal.dZero;
return Decimal.min(metalAmount, oilAmount).floor().max(0);
},
display: jsx(() => (
<>
<div><h3>Build a loader</h3></div>
@ -140,13 +197,41 @@ const layer = createLayer(id, function (this: BaseLayer) {
Cost: {displayCost(metal.metal, helpers.loader.metalCost.value, metal.metal.displayName)},
{displayCost(oil.oil, helpers.loader.oilCost.value, oil.oil.displayName)}</div>
</>
))
)),
style: {
width: "200px"
}
}))
} as {
elf: GenericBuyable,
loader: GenericBuyable & {metalCost: ComputedRef<DecimalSource>, oilCost: ComputedRef<DecimalSource>}
elf: ElfBuyable,
loader: ElfBuyable & {metalCost: ComputedRef<DecimalSource>, oilCost: ComputedRef<DecimalSource>}
};
const upgrades = {
packingElf: createUpgrade(() => ({
display: {
title: "An Elf's Elf",
description: "Hire an Elf to help you hire more Elves"
},
cost: 1000,
resource: totalPresentsResource,
style: {
width: "200px"
}
})),
loaderUnlock: createUpgrade(() => ({
display: {
title: "Heavy Machinery",
description: "Those construction vehicles you have from building the workshop should be useful for loading presents too"
},
cost: 100000,
resource: totalPresentsResource,
style: {
width: "200px"
}
}))
}
const packingMilestones: Record<string, GenericMilestone> = {
logBoost: createMilestone(() => ({
display: {
@ -353,7 +438,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
gradient: "packing-bar",
duration: "15s"
},
textColor: "var(--feature-foreground)",
textColor: "var(--bought)",
});
globalBus.on("update", diff => {
@ -378,7 +463,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
Decimal.times(helpers.elf.amount.value, computedElfPackingSpeed.value),
Decimal.times(helpers.loader.amount.value, computedLoaderPackingSpeed.value)
).times(diff).plus(packedPresents.value).min(8e9);
})
});
return {
name,
@ -390,19 +475,22 @@ const layer = createLayer(id, function (this: BaseLayer) {
packingResets,
packingProgress,
helpers,
upgrades,
packingMilestones,
collapseMilestones,
display: jsx(() => (
<>
{render(trackerDisplay)}
<SpacerVue />
<MainDisplayVue resource={packedPresents} color={color} />
<MainDisplayVue resource={packedPresents} color={color}/>
<SpacerVue />
{render(resetPacking)}
{render(packPresent)}
<SpacerVue />
{renderRow(...Object.values(helpers))}
<SpacerVue />
{renderRow(...Object.values(upgrades))}
<SpacerVue />
{milestonesDisplay()}
</>
)),

View file

@ -26,6 +26,7 @@ import coal from "./coal";
import dyes from "./dyes";
import elves, { ElfBuyable } from "./elves";
import management from "./management";
import packing from "./packing";
import plastic from "./plastic";
import reindeer from "./reindeer";
import ribbon from "./ribbon";
@ -131,6 +132,9 @@ const layer = createLayer(id, function (this: BaseLayer) {
if (["Peppermint", "Twinkle", "Cocoa", "Frosty"].includes(options.elfName)) {
cost = cost.mul(1e31);
}
if (["Jingle"].includes(options.elfName)) {
cost = cost.mul(1e120);
}
if (management.elfTraining.paperElfTraining.milestones[0].earned.value) {
cost = Decimal.div(cost, sumBooks.value.max(1));
}
@ -305,6 +309,12 @@ const layer = createLayer(id, function (this: BaseLayer) {
buyableName: "Plastic Buyables",
visibility: () => showIf(plastic.masteryEffectActive.value)
});
const packingBook = createBook({
name: "The Tetris Effect",
elfName: "Jingle",
buyableName: "Elf Assistants",
visibility: () => showIf(packing.upgrades.packingElf.bought.value)
})
const books = {
cuttersBook,
plantersBook,
@ -324,7 +334,8 @@ const layer = createLayer(id, function (this: BaseLayer) {
metalBook,
primaryDyeBook,
secondaryDyeBook,
plasticBook
plasticBook,
packingBook
};
const sumBooks = computed(() =>
Object.values(books).reduce((acc, curr) => acc.add(curr.amount.value), new Decimal(0))
@ -513,7 +524,8 @@ const layer = createLayer(id, function (this: BaseLayer) {
metalBook: { amount: persistent<DecimalSource>(0) },
primaryDyeBook: { amount: persistent<DecimalSource>(0) },
secondaryDyeBook: { amount: persistent<DecimalSource>(0) },
plasticBook: { amount: persistent<DecimalSource>(0) }
plasticBook: { amount: persistent<DecimalSource>(0) },
packingBook: { amount: persistent<DecimalSource>(0) }
},
upgrades: {
clothUpgrade: { bought: persistent<boolean>(false) },