Merge branch 'main' into days-15-16

This commit is contained in:
thepaperpilot 2022-12-15 21:07:19 -06:00
parent 44f940d3a1
commit 80a74c13a2
18 changed files with 607 additions and 114 deletions

View file

@ -8,6 +8,7 @@
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
<link rel="alternate icon" type="image/png" sizes="48x48" href="/favicon.ico">
<link rel="preload" as="image" href="src/data/adventCalendarGameJamCalandar.png">
<meta name="theme-color" content="#2E3440">
<title>Advent Incremental</title>

File diff suppressed because one or more lines are too long

View file

@ -1,7 +1,8 @@
<template>
<div class="layer-container" :style="{ '--layer-color': unref(color) }">
<button v-if="showGoBack" class="goBack" @click="goBack"></button>
<button class="layer-tab minimized" v-if="minimized.value" @click="minimized.value = false">
<button class="layer-tab minimized" v-if="minimized" @click="setMinimized(false)">
<component v-if="minimizedComponent" :is="minimizedComponent" />
<div v-else>{{ unref(name) }}</div>
</button>
@ -10,7 +11,8 @@
<component :is="component" />
</Context>
</div>
<button v-if="unref(minimizable)" class="minimize" @click="minimized.value = true">
<button v-if="unref(minimizable)" class="minimize" @click="setMinimized(true)">
</button>
</div>
@ -63,7 +65,7 @@ export default defineComponent({
}
},
setup(props) {
const { display, index, minimized, minWidth, tab, minimizedDisplay } = toRefs(props);
const { display, index, minimized, minWidth, tab, minimizedDisplay, name } = toRefs(props);
const component = computeComponent(display);
const minimizedComponent = computeOptionalComponent(minimizedDisplay);
@ -75,23 +77,28 @@ export default defineComponent({
player.tabs.splice(unref(props.index), 1);
}
function setMinimized(min: boolean) {
minimized.value = min;
}
nextTick(() => updateTab(minimized.value, unref(minWidth.value)));
watch([minimized, wrapRef(minWidth)], ([minimized, minWidth]) =>
updateTab(minimized, minWidth)
);
watch([name, minimized, wrapRef(minWidth)], ([name, minimized, minWidth]) => {
updateTab(minimized, minWidth);
});
function updateNodes(nodes: Record<string, FeatureNode | undefined>) {
props.nodes.value = nodes;
}
function updateTab(minimized: boolean, minWidth: number | string) {
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 (minimized) {
if (min) {
tabValue.style.flexGrow = "0";
tabValue.style.flexShrink = "0";
tabValue.style.width = "60px";
@ -107,13 +114,17 @@ export default defineComponent({
}
}
return {
component,
minimizedComponent,
showGoBack,
updateNodes,
unref,
goBack
goBack,
setMinimized,
minimized,
minWidth,
};
}
});
@ -162,6 +173,7 @@ export default defineComponent({
.layer-tab.minimized > * {
margin: 0;
writing-mode: vertical-rl;
text-align: left;
padding-left: 10px;
width: 50px;
}

View file

@ -13,10 +13,15 @@
</template>
<template v-slot:body>
<div v-if="isTab('behaviour')">
<div v-if="canAutoSave">
<Toggle :title="autosaveTitle" v-model="autosave" />
<FeedbackButton v-if="!autosave" class="button save-button" @click="save()"
>Manually save</FeedbackButton
>
<FeedbackButton v-if="!autosave" class="button save-button" @click="save()">
Manually save
</FeedbackButton>
</div>
<div style="text-align: center" v-else>
Auto-saving is disabled while between days
</div>
<Toggle v-if="projInfo.enablePausing" :title="isPausedTitle" v-model="isPaused" />
</div>
<div v-if="isTab('appearance')">
@ -45,6 +50,7 @@ import { computed, ref, toRefs } from "vue";
import Select from "./fields/Select.vue";
import Toggle from "./fields/Toggle.vue";
import FeedbackButton from "./fields/FeedbackButton.vue";
import { layers } from "game/layers";
const isOpen = ref(false);
@ -91,6 +97,10 @@ const isPaused = computed({
}
});
const canAutoSave = computed(
() => (layers as any).main.days[(layers as any).main.day.value - 1].opened.value
);
const autosaveTitle = jsx(() => (
<span class="option-title">
Autosave<Tooltip display="Save-specific">*</Tooltip>

View file

@ -7,6 +7,12 @@
style="left: 4%; bottom: 3%; width: 40px; height: 40px"
/>
<img v-if="day >= 0" :src="tree" class="scene-item" style="left: 10%; bottom: 10%" />
<img
v-if="day >= 13"
:src="letters"
class="scene-item"
style="left: 26%; bottom: 12%; width: 40px; height: 40px"
/>
<img
v-if="day >= 12"
:src="advManagement"
@ -68,6 +74,7 @@ import plastic from "./symbols/plastic.png";
import dyes from "./symbols/dyes.png";
import management from "./symbols/elfManagement.png";
import advManagement from "./symbols/workshopMansion.png";
import letters from "./symbols/letterbox.png";
defineProps<{
day: number;

View file

@ -579,7 +579,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
inverseCost(x: DecimalSource) {
let v = Decimal.div(x, 50000).root(1.5).sub(1);
v = v.mul(wrappingPaper.boosts.rainbow1.value);
if (management.elfTraining.fertilizerElfTraining.milestones[0].earned.value) {
if (management.elfTraining.fertilizerElfTraining.milestones[1].earned.value) {
v = v.div(Decimal.pow(0.95, paper.books.fertilizerBook.totalAmount.value));
}
v = v.div(Decimal.pow(0.95, paper.books.fertilizerBook.totalAmount.value));

View file

@ -92,21 +92,25 @@ const layer = createLayer(id, function (this: BaseLayer) {
description: `${options.name} Chambers`
}))
];
if (options.color === "yellow" && oil.row3Upgrades[0].bought.value){
if (options.color === "yellow" && oil.row3Upgrades[0].bought.value) {
modifiers.push(
createMultiplicativeModifier(() => ({
multiplier(){return Decimal.add(dyes.red.amount.value,1).log10().pow(0.75)},
multiplier() {
return Decimal.add(dyes.red.amount.value, 1).log10().pow(0.75);
},
description: "Dye Synergy I"
}))
)
);
}
if (options.color === "red" && oil.row3Upgrades[3].bought.value){
if (options.color === "red" && oil.row3Upgrades[3].bought.value) {
modifiers.push(
createMultiplicativeModifier(() => ({
multiplier(){return Decimal.add(dyes.blue.amount.value,1).log10()},
multiplier() {
return Decimal.add(dyes.blue.amount.value, 1).log10();
},
description: "Dye Synergy II"
}))
)
);
}
if (options.color === "red" || options.color === "yellow") {
modifiers.push(
@ -254,9 +258,16 @@ const layer = createLayer(id, function (this: BaseLayer) {
},
inverseCost() {
if (unref(buyable.visibility) != Visibility.Visible) return Decimal.dZero;
return unref(costs).reduce((pre, c) =>
Decimal.min(this.inverseCostPre(Decimal.div(c.res.value, unref(c.base)).root(unref(c.root ?? 1))), pre)
, Decimal.dInf);
return unref(costs).reduce(
(pre, c) =>
Decimal.min(
this.inverseCostPre(
Decimal.div(c.res.value, unref(c.base)).root(unref(c.root ?? 1))
),
pre
),
Decimal.dInf
);
},
canPurchase: computed((cost?: DecimalSource) => {
if (unref(buyable.visibility) != Visibility.Visible) return false;
@ -533,7 +544,12 @@ const layer = createLayer(id, function (this: BaseLayer) {
.pow(upgrades.coalUpg.bought.value ? 1.2 : 1)
.pow(management.elfTraining.clothElfTraining.milestones[3].earned.value ? 1.1 : 1)
),
orange2: computed(() => Decimal.add(dyes.orange.amount.value, 1).log2().plus(1).pow(oil.row3Upgrades[1].bought.value ? 2.5 : 1)),
orange2: computed(() =>
Decimal.add(dyes.orange.amount.value, 1)
.log2()
.plus(1)
.pow(oil.row3Upgrades[1].bought.value ? 2.5 : 1)
),
green1: computed(() =>
Decimal.pow(2, Decimal.add(dyes.green.amount.value, 1).log2().sqrt())
.pow(upgrades.coalUpg.bought.value ? 1.2 : 1)
@ -743,6 +759,12 @@ const layer = createLayer(id, function (this: BaseLayer) {
),
"Sum of Dyes"
);
const secondaryDyeSum = computed(() =>
[dyes.orange, dyes.green, dyes.purple].reduce(
(acc, curr) => acc.add(curr.amount.value),
new Decimal(0)
)
);
const { total: totalDyeSum, trackerDisplay } = setUpDailyProgressTracker({
resource: dyeSum,
@ -765,6 +787,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
dyeSum,
boosts,
totalDyeSum,
secondaryDyeSum,
minWidth: 700,
generalTabCollapsed,
upgrades,

View file

@ -895,7 +895,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
const metalElf = createElf({
name: "Twinkle",
description:
"Twinkle will automatically purchase all metal buyables you can afford, without actually spending any resources.",
"Twinkle will automatically purchase all metal machines you can afford, without actually spending any resources.",
buyable: [metal.oreDrill, metal.industrialCrucible, metal.hotterForge],
cooldownModifier: metalCooldown,
visibility: () =>

292
src/data/layers/letters.tsx Normal file
View file

@ -0,0 +1,292 @@
import Spacer from "components/layout/Spacer.vue";
import Modal from "components/Modal.vue";
import MainDisplay from "features/resources/MainDisplay.vue";
import Sqrt from "components/math/Sqrt.vue";
import {
createCollapsibleMilestones,
createCollapsibleModifierSections,
setUpDailyProgressTracker
} from "data/common";
import { createBar } from "features/bars/bar";
import { createClickable } from "features/clickables/clickable";
import { jsx, showIf } from "features/feature";
import { createMilestone } from "features/milestones/milestone";
import { createResource } from "features/resources/resource";
import { BaseLayer, createLayer } from "game/layers";
import { createMultiplicativeModifier, createSequentialModifier } from "game/modifiers";
import { persistent } from "game/persistence";
import Decimal, { DecimalSource, format, formatWhole } from "util/bignum";
import { Direction } from "util/common";
import { render, renderRow } from "util/vue";
import { computed, ref } from "vue";
import { createBuyable, GenericBuyable } from "features/buyable";
import metal from "./metal";
import plastic from "./plastic";
import paper from "./paper";
import SqrtVue from "components/math/Sqrt.vue";
import { globalBus } from "game/events";
import { main } from "data/projEntry";
const id = "letters";
const day = 14;
const layer = createLayer(id, function (this: BaseLayer) {
const name = "Letters";
const color = "antiquewhite";
const letters = createResource<DecimalSource>(0, "letters processed");
const processingProgress = persistent<DecimalSource>(0);
const processingProgressBar = createBar(() => ({
direction: Direction.Right,
width: 100,
height: 10,
style: "margin-top: 8px",
borderStyle: "border-color: black",
baseStyle: "margin-top: 0",
fillStyle: "margin-top: 0; transition-duration: 0s; background: black",
progress: () => Decimal.div(processingProgress.value, computedProcessingCooldown.value)
}));
const process = createClickable(() => ({
display: {
title: "Process Letters",
description: jsx(() => (
<>
Process {format(computedLettersGain.value, 1)} letters
<br />
{render(processingProgressBar)}
</>
))
},
style: {
minHeight: "80px"
},
canClick: () => Decimal.gte(processingProgress.value, computedProcessingCooldown.value),
onClick() {
if (Decimal.lt(processingProgress.value, computedProcessingCooldown.value)) {
return;
}
const amount = Decimal.div(
processingProgress.value,
computedProcessingCooldown.value
).floor();
letters.value = Decimal.times(amount, computedLettersGain.value).add(letters.value);
processingProgress.value = 0;
}
}));
const metalBuyable = createBuyable(() => ({
display: {
title: "Sorting Machine",
description:
"Use a mechanic sorting machine to speed up how quickly you process letters",
effectDisplay: jsx(() => (
<>{format(Decimal.div(metalBuyable.amount.value, 2).add(1))}x</>
))
},
resource: metal.metal,
cost() {
return Decimal.pow(10, metalBuyable.amount.value).times(1e21);
}
})) as GenericBuyable;
const plasticBuyable = createBuyable(() => ({
display: {
title: "Plastic Bins",
description:
"Use various plastic bins to allow you to process larger quantities of letters at once",
effectDisplay: jsx(() => (
<>{format(Decimal.div(plasticBuyable.amount.value, 2).add(1))}x</>
))
},
resource: plastic.plastic,
cost() {
return Decimal.pow(1.5, plasticBuyable.amount.value).times(1e9);
}
})) as GenericBuyable;
const paperBuyable = createBuyable(() => ({
display: {
title: "Printed Labels",
description: "Use printed labels to improve how many letters you can process at once",
effectDisplay: jsx(() => (
<>{format(Decimal.div(paperBuyable.amount.value, 2).add(1))}x</>
))
},
resource: paper.paper,
cost() {
return Decimal.pow(3, paperBuyable.amount.value).times(1e38);
}
})) as GenericBuyable;
const buyables = { metalBuyable, plasticBuyable, paperBuyable };
const autoSmeltingMilestone = createMilestone(() => ({
display: {
requirement: "100 Letters Processed",
effectDisplay: "Double mining speed for every letters processed milestone"
},
shouldEarn: () => Decimal.gte(totalLetters.value, 100)
}));
const miningMilestone = createMilestone(() => ({
display: {
requirement: "1000 Letters Processed",
effectDisplay: jsx(() => (
<>
Mine <SqrtVue>Blue Dye</SqrtVue> additional ore each operation
</>
))
},
shouldEarn: () => Decimal.gte(totalLetters.value, 1000),
visibility: () => showIf(autoSmeltingMilestone.earned.value)
}));
const synergyMilestone = createMilestone(() => ({
display: {
requirement: "10,000 Letters Processed",
effectDisplay:
"Improve how much your experience processing letters allows you to process more letters"
},
shouldEarn: () => Decimal.gte(totalLetters.value, 10000),
visibility: () => showIf(miningMilestone.earned.value)
}));
const industrialCrucibleMilestone = createMilestone(() => ({
display: {
requirement: "100,000 Letters Processed",
effectDisplay: jsx(() => (
<>
"Industrial Crucible" also multiplies the auto smelting multi by{" "}
<Sqrt>amount</Sqrt>
</>
))
},
shouldEarn: () => Decimal.gte(totalLetters.value, 100000),
visibility: () => showIf(synergyMilestone.earned.value)
}));
const milestones = {
autoSmeltingMilestone,
miningMilestone,
synergyMilestone,
industrialCrucibleMilestone
};
const { collapseMilestones, display: milestonesDisplay } =
createCollapsibleMilestones(milestones);
const synergy = computed(() => {
const amount = Decimal.add(totalLetters.value, 1);
if (synergyMilestone.earned.value) {
const preSoftcap = Decimal.log2(10001).add(1);
return preSoftcap.add(amount.sub(9999).sqrt());
} else {
return Decimal.log2(amount).add(1);
}
});
const lettersGain = createSequentialModifier(() => [
createMultiplicativeModifier(() => ({
multiplier: synergy,
description: "Processing Letters Experience"
})),
createMultiplicativeModifier(() => ({
multiplier: () => Decimal.div(plasticBuyable.amount.value, 2).add(1),
description: "Plastic Bins"
})),
createMultiplicativeModifier(() => ({
multiplier: () => Decimal.div(paperBuyable.amount.value, 2).add(1),
description: "Printed Labels"
}))
]);
const computedLettersGain = computed(() => lettersGain.apply(1));
const processingCooldown = createSequentialModifier(() => [
createMultiplicativeModifier(() => ({
multiplier: () => Decimal.div(metalBuyable.amount.value, 2).add(1).recip(),
description: "Sorting Machine"
}))
]);
const computedProcessingCooldown = computed(() => processingCooldown.apply(5));
const [generalTab, generalTabCollapsed] = createCollapsibleModifierSections(() => [
{
title: "Processed Letters Amount",
modifier: lettersGain,
base: 1
},
{
title: "Processed Letters Cooldown",
modifier: processingCooldown,
base: 5
}
]);
const showModifiersModal = ref(false);
const modifiersModal = jsx(() => (
<Modal
modelValue={showModifiersModal.value}
onUpdate:modelValue={(value: boolean) => (showModifiersModal.value = value)}
v-slots={{
header: () => <h2>{name} Modifiers</h2>,
body: generalTab
}}
/>
));
globalBus.on("update", diff => {
if (Decimal.lt(main.day.value, day)) {
return;
}
if (Decimal.gte(processingProgress.value, computedProcessingCooldown.value)) {
processingProgress.value = computedProcessingCooldown.value;
} else {
processingProgress.value = Decimal.add(processingProgress.value, diff);
if (process.isHolding.value) {
process.onClick();
}
}
});
const { total: totalLetters, trackerDisplay } = setUpDailyProgressTracker({
resource: letters,
goal: 1e6,
name,
day,
color,
textColor: "var(--feature-foreground)",
modal: {
show: showModifiersModal,
display: modifiersModal
}
});
return {
name,
day,
color,
letters,
totalLetters,
processingProgress,
buyables,
milestones,
minWidth: 700,
generalTabCollapsed,
collapseMilestones,
display: jsx(() => (
<>
{render(trackerDisplay)}
<Spacer />
<MainDisplay resource={letters} color={color} />
{render(process)}
<div>
The more letters you process, the more you'll improve at processing letters.
</div>
<div>Currently: {format(synergy.value)}x</div>
<Spacer />
{renderRow(...Object.values(buyables))}
<Spacer />
{milestonesDisplay()}
</>
)),
minimizedDisplay: jsx(() => (
<div>
{name} - {format(letters.value)} {letters.displayName}
</div>
))
};
});
export default layer;

View file

@ -426,7 +426,10 @@ const layer = createLayer(id, () => {
effectDisplay: "Unlock an elf that autobuys coal drills."
},
visibility: () => showIf(expanderElfMilestones[2].earned.value && main.day.value >= 13),
shouldEarn: () => expandersElfTraining.level.value >= 4
shouldEarn: () => expandersElfTraining.level.value >= 4,
onComplete() {
main.days[3].recentlyUpdated.value = true;
}
})),
createMilestone(() => ({
display: {
@ -481,7 +484,10 @@ const layer = createLayer(id, () => {
},
visibility: () =>
showIf(heatedCutterElfMilestones[3].earned.value && main.day.value >= 13),
shouldEarn: () => heatedCutterElfTraining.level.value >= 5
shouldEarn: () => heatedCutterElfTraining.level.value >= 5,
onComplete() {
main.days[3].recentlyUpdated.value = true;
}
}))
] as Array<GenericMilestone>;
const heatedPlanterElfMilestones = [
@ -575,11 +581,14 @@ const layer = createLayer(id, () => {
createMilestone(() => ({
display: {
requirement: "Noel Level 5",
effectDisplay: "Unlock an elf that autobuys metal buyables"
effectDisplay: "Unlock an elf that autobuys metal machines"
},
visibility: () =>
showIf(fertilizerElfMilestones[3].earned.value && main.day.value >= 13),
shouldEarn: () => fertilizerElfTraining.level.value >= 5
shouldEarn: () => fertilizerElfTraining.level.value >= 5,
onComplete() {
main.days[3].recentlyUpdated.value = true;
}
}))
] as Array<GenericMilestone>;
const smallfireElfMilestones = [
@ -782,7 +791,10 @@ const layer = createLayer(id, () => {
effectDisplay: "Unlock a second row of box buyables"
},
visibility: () => showIf(boxElfMilestones[2].earned.value && main.day.value >= 13),
shouldEarn: () => boxElfTraining.level.value >= 4
shouldEarn: () => boxElfTraining.level.value >= 4,
onComplete() {
main.days[5].recentlyUpdated.value = true;
}
})),
createMilestone(() => ({
display: {
@ -790,7 +802,10 @@ const layer = createLayer(id, () => {
effectDisplay: "Unlock another row of box upgrades"
},
visibility: () => showIf(boxElfMilestones[3].earned.value && main.day.value >= 13),
shouldEarn: () => boxElfTraining.level.value >= 5
shouldEarn: () => boxElfTraining.level.value >= 5,
onComplete() {
main.days[5].recentlyUpdated.value = true;
}
}))
] as Array<GenericMilestone>;
const clothElfMilestones = [
@ -850,7 +865,10 @@ const layer = createLayer(id, () => {
effectDisplay: "Unlock another row of focus upgrades"
},
visibility: () => showIf(clothElfMilestones[3].earned.value && main.day.value >= 13),
shouldEarn: () => clothElfTraining.level.value >= 5
shouldEarn: () => clothElfTraining.level.value >= 5,
onComplete() {
main.days[12].recentlyUpdated.value = true;
}
}))
] as Array<GenericMilestone>;
const coalDrillElfMilestones = [
@ -884,7 +902,10 @@ const layer = createLayer(id, () => {
},
visibility: () =>
showIf(coalDrillElfMilestones[2].earned.value && main.day.value >= 13),
shouldEarn: () => coalDrillElfTraining.level.value >= 4
shouldEarn: () => coalDrillElfTraining.level.value >= 4,
onComplete() {
main.days[2].recentlyUpdated.value = true;
}
})),
createMilestone(() => ({
display: {
@ -979,7 +1000,10 @@ const layer = createLayer(id, () => {
effectDisplay: "Unlock another row of oil upgrades"
},
visibility: () => showIf(oilElfMilestones[3].earned.value && main.day.value >= 13),
shouldEarn: () => oilElfTraining.level.value >= 5
shouldEarn: () => oilElfTraining.level.value >= 5,
onComplete() {
main.days[8].recentlyUpdated.value = true;
}
}))
] as Array<GenericMilestone>;
const heavyDrillElfMilestones = [
@ -1026,7 +1050,10 @@ const layer = createLayer(id, () => {
},
visibility: () =>
showIf(heavyDrillElfMilestones[3].earned.value && main.day.value >= 13),
shouldEarn: () => heavyDrillElfTraining.level.value >= 5
shouldEarn: () => heavyDrillElfTraining.level.value >= 5,
onComplete() {
main.days[4].recentlyUpdated.value = true;
}
}))
] as Array<GenericMilestone>;
// ------------------------------------------------------------------------------- Milestone display
@ -1363,7 +1390,7 @@ const layer = createLayer(id, () => {
const focusUpgrade6 = createUpgrade(() => ({
display: {
title: "Focus Doubler",
description: "Focus now applies to 6 elves."
description: "Focus applies to an additional elf."
},
resource: trees.logs,
visibility: () => showIf(elfTraining.clothElfTraining.milestones[4].earned.value),
@ -1465,9 +1492,7 @@ const layer = createLayer(id, () => {
});
const classroomEffect = computed(() => {
return Decimal.add(classrooms.amount.value, 1)
.pow(0.9)
.pow(paper.upgrades2.classroomUpgrade.bought.value ? 1.1 : 1);
return Decimal.add(classrooms.amount.value, 1).pow(0.9);
});
const classrooms = createBuyable(() => ({

View file

@ -1,40 +1,40 @@
import Spacer from "components/layout/Spacer.vue";
import MainDisplay from "features/resources/MainDisplay.vue";
import Toggle from "components/fields/Toggle.vue";
import Spacer from "components/layout/Spacer.vue";
import Modal from "components/Modal.vue";
import { createCollapsibleModifierSections, setUpDailyProgressTracker } from "data/common";
import { createBar } from "features/bars/bar";
import { createBuyable } from "features/buyable";
import { createClickable } from "features/clickables/clickable";
import { jsx, showIf } from "features/feature";
import MainDisplay from "features/resources/MainDisplay.vue";
import { createResource, Resource, trackBest } from "features/resources/resource";
import { BaseLayer, createLayer } from "game/layers";
import Decimal, { DecimalSource } from "lib/break_eternity";
import { render, renderRow } from "util/vue";
import { persistent } from "game/persistence";
import { createUpgrade, GenericUpgrade } from "features/upgrades/upgrade";
import { globalBus } from "game/events";
import { BaseLayer, createLayer } from "game/layers";
import {
createAdditiveModifier,
createExponentialModifier,
createMultiplicativeModifier,
createSequentialModifier
} from "game/modifiers";
import { computed, ref, unref } from "vue";
import { createBar } from "features/bars/bar";
import { Direction } from "util/common";
import { noPersist, persistent } from "game/persistence";
import Decimal, { DecimalSource } from "lib/break_eternity";
import { format, formatGain, formatLimit, formatWhole } from "util/break_eternity";
import { createClickable } from "features/clickables/clickable";
import coal from "./coal";
import { createUpgrade, GenericUpgrade } from "features/upgrades/upgrade";
import { noPersist } from "game/persistence";
import { createBuyable, GenericBuyable } from "features/buyable";
import { Direction } from "util/common";
import { render, renderRow } from "util/vue";
import { computed, ref, unref } from "vue";
import { main } from "../projEntry";
import oil from "./oil";
import boxes from "./boxes";
import cloth from "./cloth";
import plastic from "./plastic";
import coal from "./coal";
import dyes from "./dyes";
import management from "./management";
import workshop from "./workshop";
import paper from "./paper";
import { ElfBuyable } from "./elves";
import letters from "./letters";
import management from "./management";
import oil from "./oil";
import paper from "./paper";
import plastic from "./plastic";
import workshop from "./workshop";
const id = "metal";
const day = 7;
@ -188,6 +188,11 @@ const layer = createLayer(id, function (this: BaseLayer) {
multiplier: 3,
description: "Twinkle Level 3",
enabled: () => management.elfTraining.metalElfTraining.milestones[2].earned.value && !main.isMastery.value
})),
createMultiplicativeModifier(() => ({
multiplier: () => Decimal.add(industrialCrucible.amount.value, 1).sqrt(),
description: "100,000 Letters Processed",
enabled: letters.milestones.industrialCrucibleMilestone.earned
}))
]);
const computedAutoSmeltMulti = computed(() => autoSmeltMulti.apply(1));
@ -258,6 +263,11 @@ const layer = createLayer(id, function (this: BaseLayer) {
multiplier: 2,
description: "Carry ore in boxes",
enabled: boxes.row2Upgrades.oreUpgrade.bought
})),
createMultiplicativeModifier(() => ({
multiplier: () => Decimal.add(dyes.dyes.blue.amount.value, 1).sqrt(),
description: "1000 Letters Processed",
enabled: letters.milestones.miningMilestone.earned
}))
]);
const computedOreAmount = computed(() => oreAmount.apply(1));
@ -286,6 +296,15 @@ const layer = createLayer(id, function (this: BaseLayer) {
multiplier: 2,
description: "Oil the Metal Drills",
enabled: oil.row2Upgrades[1].bought
})),
createMultiplicativeModifier(() => ({
multiplier: () =>
Decimal.pow(
2,
Object.values(letters.milestones).filter(m => m.earned.value).length
),
description: "100 Letters Processed",
enabled: letters.milestones.autoSmeltingMilestone.earned
}))
]);
const computedOreSpeed = computed(() => oreSpeed.apply(Decimal.recip(maxOreProgress)));

View file

@ -450,7 +450,9 @@ const layer = createLayer(id, function (this: BaseLayer) {
}
let v = Decimal.div(x, 1e7).log(10);
v = v.div(Decimal.pow(0.95, paper.books.oilBook.totalAmount.value));
if (Decimal.gte(v, 100)) v = Decimal.mul(v, 100).root(4);
if (Decimal.gte(v, 1e4)) v = Decimal.mul(v, 1e4).root(2);
if (Decimal.gte(v, 200)) v = Decimal.mul(v, 200).root(2);
if (Decimal.gte(v, 50)) v = Decimal.mul(v, 50).root(2);
return Decimal.isNaN(v) ? Decimal.dZero : v.floor().max(0);
},
display: jsx(() => (
@ -739,7 +741,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
cost: 1e13,
display: {
title: "Dye Synergy I",
description: "Red dye boosts yellow dye gain *(log(x)^0.75)"
description: "Red dye boosts yellow dye gain by (log(x)^0.75)"
},
visibility: () =>
showIf(management.elfTraining.oilElfTraining.milestones[4].earned.value),
@ -760,8 +762,13 @@ const layer = createLayer(id, function (this: BaseLayer) {
resource: noPersist(oil),
cost: 1e15,
display: {
title: "Colorful Focus",
description: "Sum of secondary dyes increases max focus multiplier by cbrt(x)"
title: "Colorful Plastic",
description: jsx(() => (
<>
Sum of secondary dyes increases plastic gain by <sup>3</sup>
<Sqrt>x</Sqrt>
</>
))
},
visibility: () =>
showIf(management.elfTraining.oilElfTraining.milestones[4].earned.value),
@ -772,7 +779,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
cost: 1e16,
display: {
title: "Dye Synergy II",
description: "Blue dye boosts red dye gain *log(x)"
description: "Blue dye boosts red dye gain by log(x)"
},
visibility: () =>
showIf(management.elfTraining.oilElfTraining.milestones[4].earned.value),

View file

@ -6,7 +6,7 @@ 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 { BuyableOptions, createBuyable, GenericBuyable } from "features/buyable";
import { BuyableOptions, createBuyable } from "features/buyable";
import { createClickable } from "features/clickables/clickable";
import { createCumulativeConversion, createPolynomialScaling } from "features/conversion";
import { jsx, showIf } from "features/feature";
@ -19,15 +19,15 @@ import { createMultiplicativeModifier, createSequentialModifier, Modifier } from
import { noPersist } from "game/persistence";
import Decimal, { DecimalSource, format, formatSmall, formatWhole } from "util/bignum";
import { WithRequired } from "util/common";
import { render, renderCol, renderGrid, renderRow } from "util/vue";
import { render, renderCol, renderGrid } from "util/vue";
import { computed, ComputedRef, ref, unref } from "vue";
import cloth from "./cloth";
import coal from "./coal";
import dyes from "./dyes";
import elves, { ElfBuyable } from "./elves";
import management from "./management";
import plastic from "./plastic";
import trees from "./trees";
import dyes from "./dyes";
import management from "./management";
import workshop from "./workshop";
import wrappingPaper from "./wrapping-paper";
@ -244,7 +244,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
const paperBook = createBook({
name: "The Book Thief",
elfName: "Star",
buyableName: "Paper Buyables",
buyableName: "Books",
visibility: () => showIf(elves.elves.paperElf.bought.value)
});
const boxBook = createBook({
@ -280,13 +280,13 @@ const layer = createLayer(id, function (this: BaseLayer) {
const metalBook = createBook({
name: "Physical Metallurgy",
elfName: "Twinkle",
buyableName: "Metal Buyables",
buyableName: "Metal Machines",
visibility: () => showIf(elves.elves.metalElf.bought.value)
});
const dyeBook = createBook({
name: "Arts and Crafts",
elfName: "Carol",
buyableName: "Dye Buyables",
buyableName: "Dyes",
visibility: () => showIf(elves.elves.dyeElf.bought.value)
});
const books = {
@ -360,17 +360,17 @@ const layer = createLayer(id, function (this: BaseLayer) {
description: "Books are less expensive"
}
}));
const classroomUpgrade = createUpgrade(() => ({
const treeUpgrade = createUpgrade(() => ({
resource: noPersist(paper),
cost: 1e40,
visibility: () =>
showIf(management.elfTraining.heavyDrillElfTraining.milestones[4].earned.value),
display: {
title: "Classroom Supplies",
description: "Classrooms' effect is raised to the 1.1"
title: "Un-Processing",
description: "Log gain is raised to the ^1.05"
}
}));
const upgrades2 = { ashUpgrade, bookUpgrade, classroomUpgrade };
const upgrades2 = { ashUpgrade, bookUpgrade, treeUpgrade };
const paperGain = createSequentialModifier(() => [
createMultiplicativeModifier(() => ({
multiplier: 2,

View file

@ -281,6 +281,11 @@ const layer = createLayer(id, function (this: BaseLayer) {
multiplier: () => Decimal.add(oil.buildExtractor.amount.value, 1).pow(1.25),
description: "Snowball Level 4",
enabled: () => management.elfTraining.kilnElfTraining.milestones[3].earned.value && !main.isMastery.value
})),
createMultiplicativeModifier(() => ({
multiplier: () => Decimal.add(dyes.secondaryDyeSum.value, 1).cbrt(),
description: "Colorful Plastic",
enabled: oil.row3Upgrades[2].bought
}))
]);
const computedPlasticGain = computed(() => plasticGain.apply(0));

View file

@ -538,6 +538,11 @@ const layer = createLayer(id, function (this: BaseLayer) {
exponent: 1.2,
description: "100% Foundation Completed",
enabled: workshop.milestones.logGainMilestone3.earned
})),
createExponentialModifier(() => ({
exponent: 1.05,
description: "Un-Processing",
enabled: paper.upgrades2.treeUpgrade.bought
}))
]);

View file

@ -8,6 +8,7 @@ import { main } from "data/projEntry";
import { createBar } from "features/bars/bar";
import { createClickable } from "features/clickables/clickable";
import {
addHardcap,
addSoftcap,
createIndependentConversion,
createPolynomialScaling
@ -51,19 +52,30 @@ const layer = createLayer(id, function (this: BaseLayer) {
createExponentialModifier(() => ({
exponent: 0.99,
description: "Holly Level 5",
enabled: () => management.elfTraining.cutterElfTraining.milestones[4].earned.value && !main.isMastery.value
enabled: () =>
management.elfTraining.cutterElfTraining.milestones[4].earned.value &&
!main.isMastery.value
}))
])
]);
const addScaling = (value: DecimalSource) => computed(() => costDecrease.apply(value));
const foundationConversion = createIndependentConversion(() => ({
scaling: addSoftcap(
addSoftcap(createPolynomialScaling(
addScaling(250), 1.5), addScaling(5423), 1 / 1e10),
// note: 5423 is a magic number. Don't touch this or it'll self-destruct.
scaling: addHardcap(
addSoftcap(
addSoftcap(
createPolynomialScaling(addScaling(250), 1.5),
addScaling(5423),
1 / 1e10
),
addScaling(1e20),
3e8
),
computed(() =>
management.elfTraining.expandersElfTraining.milestones[2].earned.value ? 1000 : 100
)
),
baseResource: trees.logs,
gainResource: noPersist(foundationProgress),
roundUpCost: true,
@ -77,7 +89,12 @@ const layer = createLayer(id, function (this: BaseLayer) {
display: jsx(() => (
<>
<b style="font-size: x-large">
Build {formatWhole((main.isMastery.value ? mastery.foundationConversion : foundationConversion).actualGain.value)}% of the foundation
Build{" "}
{formatWhole(
(main.isMastery.value ? mastery.foundationConversion : foundationConversion)
.actualGain.value
)}
% of the foundation
</b>
<br />
<br />
@ -85,9 +102,21 @@ const layer = createLayer(id, function (this: BaseLayer) {
{main.isMastery.value || mastered ? "Requirement" : "Cost"}:{" "}
{displayResource(
main.isMastery.value ? trees.mastery.logs : trees.logs,
Decimal.gte((main.isMastery.value ? mastery.foundationConversion : foundationConversion).actualGain.value, 1)
? (main.isMastery.value ? mastery.foundationConversion : foundationConversion).currentAt.value
: (main.isMastery.value ? mastery.foundationConversion : foundationConversion).nextAt.value
Decimal.gte(
(main.isMastery.value
? mastery.foundationConversion
: foundationConversion
).actualGain.value,
1
)
? (main.isMastery.value
? mastery.foundationConversion
: foundationConversion
).currentAt.value
: (main.isMastery.value
? mastery.foundationConversion
: foundationConversion
).nextAt.value
)}{" "}
{trees.logs.displayName}
</span>
@ -95,13 +124,42 @@ const layer = createLayer(id, function (this: BaseLayer) {
)),
visibility: () =>
showIf(
Decimal.lt(main.isMastery.value ? mastery.foundationProgress.value : foundationProgress.value, 100) ||
main.isMastery.value
? Decimal.lt(mastery.foundationProgress.value, 100)
: Decimal.lt(
foundationProgress.value,
management.elfTraining.expandersElfTraining.milestones[2].earned.value
? 1000
: 100
)
),
canClick: () =>
Decimal.gte((main.isMastery.value ? trees.mastery.logs.value : trees.logs.value), (main.isMastery.value ? mastery.foundationConversion : foundationConversion).nextAt.value) &&
(Decimal.lt(foundationProgress.value, 100) ||
management.elfTraining.expandersElfTraining.milestones[2].earned.value),
canClick: () => {
if (main.isMastery.value) {
if (
Decimal.lt(trees.mastery.logs.value, mastery.foundationConversion.nextAt.value)
) {
return false;
}
if (Decimal.gte(foundationProgress.value, 100)) {
return false;
}
} else {
if (Decimal.lt(trees.logs.value, foundationConversion.nextAt.value)) {
return false;
}
if (
Decimal.gte(
foundationProgress.value,
management.elfTraining.expandersElfTraining.milestones[2].earned.value
? 1000
: 100
)
) {
return false;
}
}
return true;
},
onClick() {
if (!unref(this.canClick)) {
return;
@ -286,7 +344,6 @@ const layer = createLayer(id, function (this: BaseLayer) {
)
}));
watchEffect(() => {
if (main.day.value === day && Decimal.gte(foundationProgress.value, 100)) {
main.completeDay();
@ -297,8 +354,11 @@ const layer = createLayer(id, function (this: BaseLayer) {
const foundationProgress = createResource<DecimalSource>(0, "foundation progress");
const foundationConversion = createIndependentConversion(() => ({
scaling: addSoftcap(
addSoftcap(createPolynomialScaling(
addScaling(250), 1.5), addScaling(5423), 1 / 1e10),
addSoftcap(
createPolynomialScaling(addScaling(250), 1.5),
addScaling(5423),
1 / 1e10
),
addScaling(1e20),
3e8
),
@ -319,7 +379,8 @@ const layer = createLayer(id, function (this: BaseLayer) {
const autoCutMilestone1 = createMilestone(() => ({
display: {
requirement: "10% Foundation Completed",
effectDisplay: "Cut an additional tree per second for each 5% of foundation completed"
effectDisplay:
"Cut an additional tree per second for each 5% of foundation completed"
},
shouldEarn: () => Decimal.gte(foundationProgress.value, 10),
visibility: () => showIf(logGainMilestone1.earned.value),
@ -481,8 +542,8 @@ const layer = createLayer(id, function (this: BaseLayer) {
extraExpansionMilestone3,
extraExpansionMilestone4,
extraExpansionMilestone5
}
})()
};
})();
return {
name,
@ -508,7 +569,11 @@ const layer = createLayer(id, function (this: BaseLayer) {
<div>
<span>The foundation is </span>
<h2 style={`color: ${color}; text-shadow: 0 0 10px ${color}`}>
{formatWhole(main.isMastery.value ? mastery.foundationProgress.value : foundationProgress.value)}
{formatWhole(
main.isMastery.value
? mastery.foundationProgress.value
: foundationProgress.value
)}
</h2>
% completed
</div>
@ -523,7 +588,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
)),
minimizedDisplay: jsx(() => (
<div>
{name} - {format(foundationProgress.value)} {foundationProgress.displayName}
{name} - {format(foundationProgress.value)}% {foundationProgress.displayName}
</div>
))
};

View file

@ -8,11 +8,12 @@ import {
} from "features/feature";
import { BaseLayer, createLayer, GenericLayer, layers } from "game/layers";
import { persistent } from "game/persistence";
import type { PlayerData } from "game/player";
import type { LayerData, PlayerData } from "game/player";
import player from "game/player";
import { format, formatTime } from "util/bignum";
import Decimal, { format, formatTime } from "util/bignum";
import { Computable, convertComputable, ProcessedComputable } from "util/computed";
import { createLazyProxy } from "util/proxies";
import { save } from "util/save";
import { renderRow, VueFeature } from "util/vue";
import type { Ref } from "vue";
import { computed, ref, unref } from "vue";
@ -24,6 +25,7 @@ import coalSymbol from "./symbols/coal.png";
import dyesSymbol from "./symbols/dyes.png";
import elfSymbol from "./symbols/elf.png";
import managementSymbol from "./symbols/elfManagement.png";
import lettersSymbol from "./symbols/letterbox.png";
import metalSymbol from "./symbols/metal.png";
import oilSymbol from "./symbols/oil.png";
import paperSymbol from "./symbols/paperStacks.png";
@ -43,6 +45,7 @@ import cloth from "./layers/cloth";
import oil from "./layers/oil";
import plastic from "./layers/plastic";
import dyes from "./layers/dyes";
import letters from "./layers/letters";
import management from "./layers/management";
import wrappingPaper from "./layers/wrapping-paper";
import { createReset } from "features/reset";
@ -279,7 +282,7 @@ export const main = createLayer("main", function (this: BaseLayer) {
symbol: dyesSymbol,
story: "To make toys, we're going to need some color to make them look nice and enticing! We can't just give kids clear toys after all! To add some color to our toys, we'll need some dyes!",
completedStory:
"After all that effort, you finally have a rainbow of dyes to choose from! Now the children won't be able to resist the toys you have to offer, once you get them made of course..."
"After all that effort, you finally have a rainbow of dyes to choose from! Now the children won't be able to resist the toys you have to offer, once you get them made of course... Good Job!"
})),
createDay(() => ({
day: 12,
@ -302,10 +305,11 @@ export const main = createLayer("main", function (this: BaseLayer) {
createDay(() => ({
day: 14,
shouldNotify: false,
layer: null, // "letters to santa"
symbol: "",
story: "",
completedStory: ""
layer: "letters",
symbol: lettersSymbol,
story: "Fully prepared to start working on presents, you realize you don't actually know what to make! You ask Santa and he points at a massive pile of letters hiding just off-camera. Those are all the letters to Santa that need to be processed, sorted, and categorized appropriately so every kid gets what they need!",
completedStory:
"The letters are sorted! You have a slight feeling you may have rushed a little, and suddenly understand why sometimes you don't get everything you asked Santa for every year, or even the occasional bad gift. You sympathetically pat Santa on the back as you head to bed for the day. Good Job!"
})),
createDay(() => ({
day: 15,
@ -398,6 +402,7 @@ export const main = createLayer("main", function (this: BaseLayer) {
day.value++;
main.minimized.value = false;
if (player.autoPause) player.devSpeed = 0;
save();
}
return {
@ -463,7 +468,8 @@ export const getInitialLayers = (
plastic,
dyes,
wrappingPaper,
management
management,
letters
];
/**
@ -487,6 +493,14 @@ export function fixOldSave(
if (!["0.0", "0.1", "0.2", "0.3", "0.4"].includes(oldVersion ?? "")) {
return;
}
if ((player.layers?.workshop as LayerData<typeof workshop> | undefined)?.foundationProgress) {
(player.layers?.workshop as LayerData<typeof workshop> | undefined)!.foundationProgress =
Decimal.min(
(player.layers!.workshop as LayerData<typeof workshop> | undefined)!
.foundationProgress!,
1000
);
}
/*player.offlineProd = false;
delete player.layers?.management;
if ((player.layers?.main as LayerData<typeof main> | undefined)?.days?.[11]) {

View file

@ -1,5 +1,6 @@
import projInfo from "data/projInfo.json";
import { globalBus } from "game/events";
import { layers } from "game/layers";
import type { Player, PlayerData } from "game/player";
import player, { stringifySave } from "game/player";
import settings, { loadSettings } from "game/settings";
@ -126,12 +127,18 @@ export async function loadSave(playerObj: Partial<PlayerData>): Promise<void> {
}
setInterval(() => {
if (player.autosave) {
if (
player.autosave &&
(layers as any).main.days[(layers as any).main.day.value - 1].opened.value
) {
save();
}
}, 1000);
window.onbeforeunload = () => {
if (player.autosave) {
if (
player.autosave &&
(layers as any).main.days[(layers as any).main.day.value - 1].opened.value
) {
save();
}
};