diff --git a/.vscode/settings.json b/.vscode/settings.json index ddcd19b..25708ee 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -6,7 +6,7 @@ "editor.defaultFormatter": "esbenp.prettier-vscode", "git.ignoreLimitWarning": true, "[typescriptreact]": { - "editor.defaultFormatter": "vscode.typescript-language-features" + "editor.defaultFormatter": "esbenp.prettier-vscode" }, "typescript.tsdk": "node_modules/typescript/lib" } \ No newline at end of file diff --git a/src/components/Game.vue b/src/components/Game.vue index 7d7e531..238a17a 100644 --- a/src/components/Game.vue +++ b/src/components/Game.vue @@ -66,8 +66,9 @@ const useHeader = projInfo.useHeader; const loreBody = computeOptionalComponent(main.loreBody); function gatherLayerProps(layer: GenericLayer) { - const { display, minimized, minWidth, name, color, minimizable, nodes } = layer; - return { display, minimized, minWidth, name, color, minimizable, nodes }; + const { display, minimized, minWidth, name, color, minimizable, nodes, minimizedDisplay } = + layer; + return { display, minimized, minWidth, name, color, minimizable, nodes, minimizedDisplay }; } diff --git a/src/components/Layer.vue b/src/components/Layer.vue index 8a6e7b1..62cca55 100644 --- a/src/components/Layer.vue +++ b/src/components/Layer.vue @@ -2,7 +2,8 @@
@@ -21,7 +22,7 @@ import type { CoercableComponent } from "features/feature"; import type { FeatureNode } from "game/layers"; import type { Persistent } from "game/persistence"; import player from "game/player"; -import { computeComponent, processedPropType, wrapRef } from "util/vue"; +import { computeComponent, computeOptionalComponent, processedPropType, wrapRef } from "util/vue"; import type { PropType, Ref } from "vue"; import { computed, defineComponent, nextTick, toRefs, unref, watch } from "vue"; import Context from "./Context.vue"; @@ -41,6 +42,7 @@ export default defineComponent({ type: processedPropType(Object, String, Function), required: true }, + minimizedDisplay: processedPropType(Object, String, Function), minimized: { type: Object as PropType>, required: true @@ -61,9 +63,10 @@ export default defineComponent({ } }, setup(props) { - const { display, index, minimized, minWidth, tab } = toRefs(props); + const { display, index, minimized, minWidth, tab, minimizedDisplay } = toRefs(props); const component = computeComponent(display); + const minimizedComponent = computeOptionalComponent(minimizedDisplay); const showGoBack = computed( () => projInfo.allowGoBack && index.value > 0 && !minimized.value ); @@ -106,6 +109,7 @@ export default defineComponent({ return { component, + minimizedComponent, showGoBack, updateNodes, unref, @@ -155,7 +159,7 @@ export default defineComponent({ background-color: transparent; } -.layer-tab.minimized div { +.layer-tab.minimized > * { margin: 0; writing-mode: vertical-rl; padding-left: 10px; diff --git a/src/components/Options.vue b/src/components/Options.vue index b8be08b..f61e2b6 100644 --- a/src/components/Options.vue +++ b/src/components/Options.vue @@ -1,16 +1,31 @@ @@ -24,19 +39,36 @@ import Tooltip from "features/tooltips/Tooltip.vue"; import player from "game/player"; import settings, { settingFields } from "game/settings"; import { camelToTitle } from "util/common"; +import { save } from "util/save"; import { coerceComponent, render } from "util/vue"; import { computed, ref, toRefs } from "vue"; import Select from "./fields/Select.vue"; import Toggle from "./fields/Toggle.vue"; +import FeedbackButton from "./fields/FeedbackButton.vue"; const isOpen = ref(false); +const currentTab = ref("behaviour"); + defineExpose({ + isTab, + setTab, + save() { + save(); + }, open() { isOpen.value = true; } }); +function isTab(tab: string): boolean { + return tab == currentTab.value; +} + +function setTab(tab: string) { + currentTab.value = tab; +} + const themes = Object.keys(rawThemes).map(theme => ({ label: camelToTitle(theme), value: theme @@ -46,8 +78,10 @@ const settingFieldsComponent = computed(() => { return coerceComponent(jsx(() => <>{settingFields.map(render)})); }); -const { showTPS, theme } = toRefs(settings); -const { autosave, usingLog } = toRefs(player); +const { showTPS, theme, usingLog, alignUnits } = toRefs(settings); + +const { autosave, autoPause } = toRefs(player); + const isPaused = computed({ get() { return player.devSpeed === 0; @@ -58,26 +92,86 @@ const isPaused = computed({ }); const autosaveTitle = jsx(() => ( - + Autosave* + Automatically save the game every second or when the game is closed. )); const isPausedTitle = jsx(() => ( - + Pause game* + Stop everything from moving. + +)); +const autoPauseTitle = jsx(() => ( + + Auto-pause* + + Automatically pause the game when a day is completed. It is best to keep this on to + avoid over-grinding. + + +)); + +const themeTitle = jsx(() => ( + + Theme + How the game looks. + +)); +const showTPSTitle = jsx(() => ( + + Show TPS + Show TPS meter at the bottom-left corner of the page. )); const progressMethodTitle = jsx(() => ( - - Use log for progress bar* + + Logarithmic progress bars + Whether progress bars should be normalized for exponential growth. + +)); +const alignModifierUnitsTitle = jsx(() => ( + + Align modifier units + Align numbers to the beginning of the unit in modifier view. )); - diff --git a/src/components/common/modifiers.css b/src/components/common/modifiers.css index 6842e0c..dc9e66d 100644 --- a/src/components/common/modifiers.css +++ b/src/components/common/modifiers.css @@ -8,10 +8,13 @@ } .modifier-amount { - flex-basis: 100px; flex-shrink: 0; text-align: right; } +:not(:first-of-type, :last-of-type) > .modifier-amount::after { + content: var(--unit); + opacity: 0; +} .modifier-description { flex-grow: 1; diff --git a/src/components/fields/Select.vue b/src/components/fields/Select.vue index f08c40f..72a31b2 100644 --- a/src/components/fields/Select.vue +++ b/src/components/fields/Select.vue @@ -87,6 +87,10 @@ function onUpdate(value: SelectOption) { background-color: var(--bought); } +.vue-input input { + font-size: inherit; +} + .vue-input input::placeholder { color: var(--link); } diff --git a/src/components/fields/Toggle.vue b/src/components/fields/Toggle.vue index 0db8bd1..a1eeff3 100644 --- a/src/components/fields/Toggle.vue +++ b/src/components/fields/Toggle.vue @@ -44,14 +44,16 @@ input { span { width: 100%; + padding-right: 41px; position: relative; } /* track */ input + span::before { content: ""; - float: right; - margin: 5px 0 5px 10px; + position: absolute; + top: calc(50% - 7px); + right: 0px; border-radius: 7px; width: 36px; height: 14px; @@ -66,7 +68,7 @@ input + span::before { input + span::after { content: ""; position: absolute; - top: 2px; + top: calc(50% - 10px); right: 16px; border-radius: 50%; width: 20px; diff --git a/src/data/Scene.vue b/src/data/Scene.vue index 9b41ba0..0f63ccd 100644 --- a/src/data/Scene.vue +++ b/src/data/Scene.vue @@ -7,7 +7,27 @@ style="left: 4%; bottom: 3%; width: 40px; height: 40px" /> - + + - -
+
@@ -43,6 +66,8 @@ import cloth from "./symbols/cloth.png"; import oil from "./symbols/oil.png"; import plastic from "./symbols/plastic.png"; import dyes from "./symbols/dyes.png"; +import management from "./symbols/elfManagement.png"; +import advManagement from "./symbols/workshopMansion.png"; defineProps<{ day: number; @@ -52,8 +77,9 @@ defineProps<{ diff --git a/src/data/common.tsx b/src/data/common.tsx index 5c1db03..be75f9b 100644 --- a/src/data/common.tsx +++ b/src/data/common.tsx @@ -20,6 +20,7 @@ import type { Modifier } from "game/modifiers"; import type { Persistent } from "game/persistence"; import { DefaultValue, persistent } from "game/persistence"; import player from "game/player"; +import settings from "game/settings"; import type { DecimalSource } from "util/bignum"; import Decimal, { format } from "util/bignum"; import { formatWhole } from "util/break_eternity"; @@ -333,7 +334,7 @@ export function createCollapsibleModifierSections( return ( <> {hasPreviousSection ?
: null} -
+
{header}
{modifiers} @@ -424,7 +425,7 @@ export function setUpDailyProgressTracker(options: { if (main.day.value !== options.day) return 1; let progress = Decimal.add(total.value, 1); let requirement = options.goal; - if (options.usingLog?.value ?? player.usingLog) { + if (options.usingLog?.value ?? settings.usingLog) { progress = progress.log10(); requirement = Decimal.log10(requirement); } diff --git a/src/data/layers/boxes.tsx b/src/data/layers/boxes.tsx index d6ffc74..e5cff9a 100644 --- a/src/data/layers/boxes.tsx +++ b/src/data/layers/boxes.tsx @@ -15,7 +15,12 @@ import { createResource, displayResource, Resource } from "features/resources/re import { createUpgrade, GenericUpgrade } from "features/upgrades/upgrade"; import { globalBus } from "game/events"; import { BaseLayer, createLayer } from "game/layers"; -import { createExponentialModifier, createSequentialModifier, Modifier } from "game/modifiers"; +import { + createExponentialModifier, + createMultiplicativeModifier, + createSequentialModifier, + Modifier +} from "game/modifiers"; import { noPersist } from "game/persistence"; import Decimal, { DecimalSource, format, formatWhole } from "util/bignum"; import { WithRequired } from "util/common"; @@ -26,8 +31,13 @@ import management from "./management"; import paper from "./paper"; import plastic from "./plastic"; import trees from "./trees"; +import workshop from "./workshop"; -export type BoxesBuyable = GenericBuyable & { resource: Resource; freeLevels: ComputedRef; totalAmount: ComputedRef }; +export type BoxesBuyable = GenericBuyable & { + resource: Resource; + freeLevels: ComputedRef; + totalAmount: ComputedRef; +}; const id = "boxes"; const day = 6; @@ -38,6 +48,11 @@ const layer = createLayer(id, function (this: BaseLayer) { const boxes = createResource(0, "boxes"); const boxGain = createSequentialModifier(() => [ + createMultiplicativeModifier(() => ({ + multiplier: 2, + description: "1000% Foundation Completed", + enabled: workshop.milestones.extraExpansionMilestone5.earned + })), createExponentialModifier(() => ({ exponent: 1.1, description: "Bell Level 2", @@ -164,7 +179,7 @@ const layer = createLayer(id, function (this: BaseLayer) { title: "Carry dye in boxes", description: "Double all dye gain" } - })) as GenericUpgrade; + })) as GenericUpgrade; const xpUpgrade = createUpgrade(() => ({ resource: noPersist(boxes), cost: 1e18, @@ -178,7 +193,19 @@ const layer = createLayer(id, function (this: BaseLayer) { const logBoxesBuyable = createBuyable(() => ({ display: { title: "Carry more logs", - description: jsx(() => <>Use boxes to carry even more logs, boosting their gain

Amount: {formatWhole(logBoxesBuyable.amount.value)}{Decimal.gt(logBoxesBuyable.freeLevels.value, 0) ? <> (+{formatWhole(logBoxesBuyable.freeLevels.value)}) : null}
), + description: jsx(() => ( + <> + Use boxes to carry even more logs, boosting their gain +
+
+
+ Amount: {formatWhole(logBoxesBuyable.amount.value)} + {Decimal.gt(logBoxesBuyable.freeLevels.value, 0) ? ( + <> (+{formatWhole(logBoxesBuyable.freeLevels.value)}) + ) : null} +
+ + )), effectDisplay: jsx(() => ( <>{format(Decimal.div(logBoxesBuyable.totalAmount.value, 2).add(1))}x )), @@ -195,13 +222,34 @@ const layer = createLayer(id, function (this: BaseLayer) { return Decimal.pow(scaling, v).times(100).div(dyes.boosts.orange2.value); }, visibility: () => showIf(logsUpgrade.bought.value), - freeLevels: computed(() => management.elfTraining.boxElfTraining.milestones[0].earned.value ? Decimal.max(ashBoxesBuyable.amount.value, 1).sqrt().floor().add(Decimal.max(coalBoxesBuyable.amount.value, 1).sqrt().floor()) : 0), - totalAmount: computed(() => Decimal.add(logBoxesBuyable.amount.value, logBoxesBuyable.freeLevels.value)) + freeLevels: computed(() => + management.elfTraining.boxElfTraining.milestones[0].earned.value + ? Decimal.max(ashBoxesBuyable.amount.value, 1) + .sqrt() + .floor() + .add(Decimal.max(coalBoxesBuyable.amount.value, 1).sqrt().floor()) + : 0 + ), + totalAmount: computed(() => + Decimal.add(logBoxesBuyable.amount.value, logBoxesBuyable.freeLevels.value) + ) })) as BoxesBuyable; const ashBoxesBuyable = createBuyable(() => ({ display: { title: "Carry more ash", - description: jsx(() => <>Use boxes to carry even more ash, boosting its gain

Amount: {formatWhole(ashBoxesBuyable.amount.value)}{Decimal.gt(ashBoxesBuyable.freeLevels.value, 0) ? <> (+{formatWhole(ashBoxesBuyable.freeLevels.value)}) : null}
), + description: jsx(() => ( + <> + Use boxes to carry even more ash, boosting its gain +
+
+
+ Amount: {formatWhole(ashBoxesBuyable.amount.value)} + {Decimal.gt(ashBoxesBuyable.freeLevels.value, 0) ? ( + <> (+{formatWhole(ashBoxesBuyable.freeLevels.value)}) + ) : null} +
+ + )), effectDisplay: jsx(() => ( <>{format(Decimal.div(ashBoxesBuyable.totalAmount.value, 2).add(1))}x )), @@ -218,13 +266,34 @@ const layer = createLayer(id, function (this: BaseLayer) { return Decimal.pow(scaling, v).times(1000).div(dyes.boosts.orange2.value); }, visibility: () => showIf(ashUpgrade.bought.value), - freeLevels: computed(() => management.elfTraining.boxElfTraining.milestones[0].earned.value ? Decimal.max(logBoxesBuyable.amount.value, 1).sqrt().floor().add(Decimal.max(coalBoxesBuyable.amount.value, 1).sqrt().floor()) : 0), - totalAmount: computed(() => Decimal.add(ashBoxesBuyable.amount.value, ashBoxesBuyable.freeLevels.value)) + freeLevels: computed(() => + management.elfTraining.boxElfTraining.milestones[0].earned.value + ? Decimal.max(logBoxesBuyable.amount.value, 1) + .sqrt() + .floor() + .add(Decimal.max(coalBoxesBuyable.amount.value, 1).sqrt().floor()) + : 0 + ), + totalAmount: computed(() => + Decimal.add(ashBoxesBuyable.amount.value, ashBoxesBuyable.freeLevels.value) + ) })) as BoxesBuyable; const coalBoxesBuyable = createBuyable(() => ({ display: { title: "Carry more coal", - description: jsx(() => <>Use boxes to carry even more coal, boosting its gain

Amount: {formatWhole(coalBoxesBuyable.amount.value)}{Decimal.gt(coalBoxesBuyable.freeLevels.value, 0) ? <> (+{formatWhole(coalBoxesBuyable.freeLevels.value)}) : null}
), + description: jsx(() => ( + <> + Use boxes to carry even more coal, boosting its gain +
+
+
+ Amount: {formatWhole(coalBoxesBuyable.amount.value)} + {Decimal.gt(coalBoxesBuyable.freeLevels.value, 0) ? ( + <> (+{formatWhole(coalBoxesBuyable.freeLevels.value)}) + ) : null} +
+ + )), effectDisplay: jsx(() => ( <>{format(Decimal.div(coalBoxesBuyable.totalAmount.value, 2).add(1))}x )), @@ -241,8 +310,17 @@ const layer = createLayer(id, function (this: BaseLayer) { return Decimal.pow(scaling, v).times(1000).div(dyes.boosts.orange2.value); }, visibility: () => showIf(coalUpgrade.bought.value), - freeLevels: computed(() => management.elfTraining.boxElfTraining.milestones[0].earned.value ? Decimal.max(logBoxesBuyable.amount.value, 1).sqrt().floor().add(Decimal.max(ashBoxesBuyable.amount.value, 1).sqrt().floor()) : 0), - totalAmount: computed(() => Decimal.add(coalBoxesBuyable.amount.value, coalBoxesBuyable.freeLevels.value)) + freeLevels: computed(() => + management.elfTraining.boxElfTraining.milestones[0].earned.value + ? Decimal.max(logBoxesBuyable.amount.value, 1) + .sqrt() + .floor() + .add(Decimal.max(ashBoxesBuyable.amount.value, 1).sqrt().floor()) + : 0 + ), + totalAmount: computed(() => + Decimal.add(coalBoxesBuyable.amount.value, coalBoxesBuyable.freeLevels.value) + ) })) as BoxesBuyable; const buyables = { logBoxesBuyable, ashBoxesBuyable, coalBoxesBuyable }; @@ -261,7 +339,7 @@ const layer = createLayer(id, function (this: BaseLayer) { { title: "Boxes Gain", modifier: boxGain, - base: 1 + base: () => boxesConversion.scaling.currentGain(boxesConversion) } ]); const showModifiersModal = ref(false); @@ -300,6 +378,7 @@ const layer = createLayer(id, function (this: BaseLayer) { row3Upgrades, buyables, minWidth: 700, + generalTabCollapsed, display: jsx(() => ( <> {render(trackerDisplay)} @@ -308,10 +387,19 @@ const layer = createLayer(id, function (this: BaseLayer) { {render(makeBoxes)} - {renderGrid(Object.values(upgrades), Object.values(row2Upgrades), Object.values(row3Upgrades))} + {renderGrid( + Object.values(upgrades), + Object.values(row2Upgrades), + Object.values(row3Upgrades) + )} {renderRow(...Object.values(buyables))} + )), + minimizedDisplay: jsx(() => ( +
+ {name} - {format(boxes.value)} {boxes.displayName} +
)) }; }); diff --git a/src/data/layers/cloth.tsx b/src/data/layers/cloth.tsx index e3f4208..3f28d96 100644 --- a/src/data/layers/cloth.tsx +++ b/src/data/layers/cloth.tsx @@ -23,7 +23,7 @@ import { createSequentialModifier } from "game/modifiers"; import { noPersist, persistent } from "game/persistence"; -import Decimal, { DecimalSource } from "util/bignum"; +import Decimal, { DecimalSource, format } from "util/bignum"; import { formatWhole } from "util/break_eternity"; import { Direction } from "util/common"; import { render, renderCol, renderRow } from "util/vue"; @@ -34,6 +34,7 @@ import metal from "./metal"; import paper from "./paper"; import plastic from "./plastic"; import trees from "./trees"; +import workshop from "./workshop"; const id = "cloth"; const day = 8; @@ -331,7 +332,9 @@ const layer = createLayer(id, function (this: BaseLayer) { })); const paperUpgrades = { paperUpgrade4, paperUpgrade3, paperUpgrade2, paperUpgrade1 }; - const hollyEffect = computed(() => Decimal.add(trees.computedAutoCuttingAmount.value, 1).log10().add(1)); + const hollyEffect = computed(() => + Decimal.add(trees.computedAutoCuttingAmount.value, 1).root(9) + ); const gingersnapEffect = computed(() => Decimal.add(dyes.dyeSum.value, 10).log10()); const sheepGain = createSequentialModifier(() => [ @@ -358,6 +361,11 @@ const layer = createLayer(id, function (this: BaseLayer) { multiplier: hollyEffect, description: "Holly Level 3", enabled: management.elfTraining.cutterElfTraining.milestones[2].earned + })), + createMultiplicativeModifier(() => ({ + multiplier: 2, + description: "1000% Foundation Completed", + enabled: workshop.milestones.extraExpansionMilestone5.earned })) ]); const computedSheepGain = computed(() => sheepGain.apply(1)); @@ -388,6 +396,11 @@ const layer = createLayer(id, function (this: BaseLayer) { multiplier: hollyEffect, description: "Holly Level 3", enabled: management.elfTraining.cutterElfTraining.milestones[2].earned + })), + createMultiplicativeModifier(() => ({ + multiplier: 2, + description: "1000% Foundation Completed", + enabled: workshop.milestones.extraExpansionMilestone5.earned })) ]); const computedShearingAmount = computed(() => shearingAmount.apply(1)); @@ -418,6 +431,11 @@ const layer = createLayer(id, function (this: BaseLayer) { multiplier: hollyEffect, description: "Holly Level 3", enabled: management.elfTraining.cutterElfTraining.milestones[2].earned + })), + createMultiplicativeModifier(() => ({ + multiplier: 2, + description: "1000% Foundation Completed", + enabled: workshop.milestones.extraExpansionMilestone5.earned })) ]); const computedSpinningAmount = computed(() => spinningAmount.apply(1)); @@ -557,6 +575,11 @@ const layer = createLayer(id, function (this: BaseLayer) { {renderCol(...Object.values(paperUpgrades))} + )), + minimizedDisplay: jsx(() => ( +
+ {name} - {format(cloth.value)} {cloth.displayName} +
)) }; }); diff --git a/src/data/layers/coal.tsx b/src/data/layers/coal.tsx index 32fd930..5632b1a 100644 --- a/src/data/layers/coal.tsx +++ b/src/data/layers/coal.tsx @@ -82,13 +82,7 @@ const layer = createLayer(id, function (this: BaseLayer) { const activeFires = persistent(0); const fireLogs = computed(() => Decimal.times(activeFires.value, 1000)); - const fireCoal = computed(() => { - let gain = Decimal.times(activeFires.value, 0.1); - if (management.elfTraining.smallfireElfTraining.milestones[0].earned.value) { - gain = gain.times(5); - } - return gain; - }); + const fireCoal = computed(() => Decimal.times(activeFires.value, 0.1)); const fireAsh = computed(() => { let gain = Decimal.times(activeFires.value, 50); if (management.elfTraining.smallfireElfTraining.milestones[0].earned.value) { @@ -263,10 +257,11 @@ const layer = createLayer(id, function (this: BaseLayer) { Decimal.times( Decimal.pow(activeDrills.value, oil.row2Upgrades[1].bought.value ? 2 : 1), 5e7 - ).times(metal.efficientDrill.bought.value ? 2 : 1) - .times(management.elfTraining.smallfireElfTraining.milestones[2].earned.value ? 2 : 1) - .times(management.elfTraining.bonfireElfTraining.milestones[2].earned.value ? 2 : 1) - .times(management.elfTraining.kilnElfTraining.milestones[2].earned.value ? 2 : 1) + ) + .times(metal.efficientDrill.bought.value ? 2 : 1) + .times(management.elfTraining.smallfireElfTraining.milestones[2].earned.value ? 2 : 1) + .times(management.elfTraining.bonfireElfTraining.milestones[2].earned.value ? 2 : 1) + .times(management.elfTraining.kilnElfTraining.milestones[2].earned.value ? 2 : 1) ); const buildDrill = createBuyable(() => ({ resource: metal.metal, @@ -431,6 +426,9 @@ const layer = createLayer(id, function (this: BaseLayer) { if (Decimal.gte(v, 200)) v = Decimal.pow(v, 2).div(200); if (Decimal.gte(v, 2e6)) v = Decimal.pow(v, 2).div(2e6); v = Decimal.pow(0.95, paper.books.heatedCuttersBook.amount.value).times(v); + if (management.elfTraining.heatedCutterElfTraining.milestones[0].earned.value) { + v = Decimal.pow(0.95, paper.books.heatedCuttersBook.amount.value).times(v); + } return Decimal.add(v, 1).pow(2.5).times(10); }, display: { @@ -451,7 +449,7 @@ const layer = createLayer(id, function (this: BaseLayer) { if (Decimal.gte(v, 200)) v = Decimal.pow(v, 2).div(200); if (Decimal.gte(v, 2e6)) v = Decimal.pow(v, 2).div(2e6); v = Decimal.pow(0.95, paper.books.heatedPlantersBook.amount.value).times(v); - if (management.elfTraining.heatedPlantersElfTraining.milestones[0].earned.value) { + if (management.elfTraining.heatedPlanterElfTraining.milestones[0].earned.value) { v = Decimal.pow(0.95, paper.books.heatedPlantersBook.amount.value).times(v); } return Decimal.add(v, 1).pow(2.5).times(10); @@ -593,7 +591,13 @@ const layer = createLayer(id, function (this: BaseLayer) { enabled: boxes.upgrades.coalUpgrade.bought })), createMultiplicativeModifier(() => ({ - multiplier: () => Decimal.div(buildFire.amount.value, 10000).add(1), + multiplier: () => { + let v = buildFire.amount.value; + if (management.elfTraining.smallfireElfTraining.milestones[0].earned.value) { + v = Decimal.div(buildBonfire.amount.value, 10).add(v); + } + return Decimal.div(v, 10000).add(1); + }, description: "Small Fires Synergy", enabled: elves.elves.smallFireElf.bought })), @@ -643,6 +647,11 @@ const layer = createLayer(id, function (this: BaseLayer) { multiplier: oil.extractorCoal, description: "Heavy Extractor", enabled: () => Decimal.gt(oil.activeExtractor.value, 0) + })), + createExponentialModifier(() => ({ + exponent: 1.05, + description: "Jack Level 2", + enabled: management.elfTraining.heatedCutterElfTraining.milestones[1].earned })) ]) as WithRequired; const computedCoalGain = computed(() => coalGain.apply(0)); @@ -686,7 +695,13 @@ const layer = createLayer(id, function (this: BaseLayer) { enabled: boxes.upgrades.ashUpgrade.bought })), createMultiplicativeModifier(() => ({ - multiplier: () => Decimal.div(buildFire.amount.value, 1000).add(1), + multiplier: () => { + let v = buildFire.amount.value; + if (management.elfTraining.smallfireElfTraining.milestones[0].earned.value) { + v = Decimal.div(buildBonfire.amount.value, 100).add(v); + } + return Decimal.div(v, 1000).add(1); + }, description: "Small Fires Synergy", enabled: elves.elves.smallFireElf.bought })), @@ -870,7 +885,8 @@ const layer = createLayer(id, function (this: BaseLayer) { + )), + minimizedDisplay: jsx(() => ( +
+ {name} - {format(coal.value)} {coal.displayName} +
)) }; }); diff --git a/src/data/layers/elves.tsx b/src/data/layers/elves.tsx index 0030238..d165c4c 100644 --- a/src/data/layers/elves.tsx +++ b/src/data/layers/elves.tsx @@ -29,6 +29,8 @@ import boxes from "./boxes"; import cloth from "./cloth"; import coal from "./coal"; import management from "./management"; +import metal from "./metal"; +import oil from "./oil"; import paper from "./paper"; import plastic from "./plastic"; import trees from "./trees"; @@ -310,6 +312,74 @@ const layer = createLayer(id, function (this: BaseLayer) { enabled: elvesMilestone2.earned })) ]); + const miningDrillCooldown = createSequentialModifier(() => [ + createMultiplicativeModifier(() => ({ + multiplier: 2, + description: "6 Elves Trained", + enabled: elvesMilestone.earned + })), + createMultiplicativeModifier(() => ({ + multiplier: () => Decimal.times(paper.books.miningDrillBook.amount.value, 0.1).add(1), + description: "Drills and Mills", + enabled: () => Decimal.gt(paper.books.miningDrillBook.amount.value, 0) + })), + createMultiplicativeModifier(() => ({ + multiplier: 2, + description: "10 Elves Trained", + enabled: elvesMilestone2.earned + })) + ]); + const heavyDrillCooldown = createSequentialModifier(() => [ + createMultiplicativeModifier(() => ({ + multiplier: 2, + description: "6 Elves Trained", + enabled: elvesMilestone.earned + })), + createMultiplicativeModifier(() => ({ + multiplier: () => Decimal.times(paper.books.heavyDrillBook.amount.value, 0.1).add(1), + description: "Deep in the Earth", + enabled: () => Decimal.gt(paper.books.heavyDrillBook.amount.value, 0) + })), + createMultiplicativeModifier(() => ({ + multiplier: 2, + description: "10 Elves Trained", + enabled: elvesMilestone2.earned + })) + ]); + const oilCooldown = createSequentialModifier(() => [ + createMultiplicativeModifier(() => ({ + multiplier: 2, + description: "6 Elves Trained", + enabled: elvesMilestone.earned + })), + createMultiplicativeModifier(() => ({ + multiplier: () => Decimal.times(paper.books.oilBook.amount.value, 0.1).add(1), + description: "Burning the Midnight Oil", + enabled: () => Decimal.gt(paper.books.oilBook.amount.value, 0) + })), + createMultiplicativeModifier(() => ({ + multiplier: 2, + description: "10 Elves Trained", + enabled: elvesMilestone2.earned + })) + ]); + const metalCooldown = createSequentialModifier(() => [ + createMultiplicativeModifier(() => ({ + multiplier: 2, + description: "6 Elves Trained", + enabled: elvesMilestone.earned + })), + createMultiplicativeModifier(() => ({ + multiplier: () => Decimal.times(paper.books.metalBook.amount.value, 0.1).add(1), + description: "Physical Metallurgy", + enabled: () => Decimal.gt(paper.books.metalBook.amount.value, 0) + })), + createMultiplicativeModifier(() => ({ + multiplier: 2, + description: "10 Elves Trained", + enabled: elvesMilestone2.earned + })) + ]); const [generalTab, generalTabCollapsed] = createCollapsibleModifierSections(() => [ { @@ -395,6 +465,34 @@ const layer = createLayer(id, function (this: BaseLayer) { base: 10, unit: "/s", visible: elves.clothElf.bought + }, + { + title: "Peppermint Auto-Buy Frequency", + modifier: miningDrillCooldown, + base: 10, + unit: "/s", + visible: management.elfTraining.expandersElfTraining.milestones[3].earned + }, + { + title: "Frosty Auto-Buy Frequency", + modifier: heavyDrillCooldown, + base: 10, + unit: "/s", + visible: management.elfTraining.fertilizerElfTraining.milestones[4].earned.value + }, + { + title: "Cocoa Auto-Buy Frequency", + modifier: oilCooldown, + base: 10, + unit: "/s", + visible: management.elfTraining.heatedCutterElfTraining.milestones[4].earned.value + }, + { + title: "Twinkle Auto-Buy Frequency", + modifier: metalCooldown, + base: 10, + unit: "/s", + visible: management.elfTraining.expandersElfTraining.milestones[4].earned } ]); const showModifiersModal = ref(false); @@ -428,7 +526,7 @@ const layer = createLayer(id, function (this: BaseLayer) { customCost?: (amount: DecimalSource) => DecimalSource; hasToggle?: boolean; toggleDesc?: string; - onAutoPurchase?: VoidFunction; + onAutoPurchase?: (buyable: GenericBuyable & { resource: Resource }) => void; onPurchase?: VoidFunction; // Will get overriden by the custom onpurchase, but that's fine canBuy?: Computable; buyMax?: Computable; @@ -461,7 +559,7 @@ const layer = createLayer(id, function (this: BaseLayer) { ) { buyable.amount.value = Decimal.add(buyable.amount.value, 1); buyProgress.value = Decimal.sub(buyProgress.value, cooldown); - options.onAutoPurchase?.(); + options.onAutoPurchase?.(buyable); } else { buyProgress.value = cooldown; break; @@ -532,21 +630,24 @@ const layer = createLayer(id, function (this: BaseLayer) { description: "Holly will automatically purchase cutters you can afford, without actually spending any logs.", buyable: trees.row1Buyables[0], - cooldownModifier: cutterCooldown + cooldownModifier: cutterCooldown, + buyMax: () => management.elfTraining.cutterElfTraining.milestones[1].earned.value }); const plantersElf = createElf({ name: "Ivy", description: "Ivy will automatically purchase planters you can afford, without actually spending any logs.", buyable: trees.row1Buyables[1], - cooldownModifier: planterCooldown + cooldownModifier: planterCooldown, + buyMax: () => management.elfTraining.planterElfTraining.milestones[1].earned.value }); const expandersElf = createElf({ name: "Hope", description: "Hope will automatically purchase forest expanders you can afford, without actually spending any logs.", buyable: trees.row1Buyables[2], - cooldownModifier: expanderCooldown + cooldownModifier: expanderCooldown, + buyMax: () => management.elfTraining.expandersElfTraining.milestones[1].earned.value }); const treesElves = [cuttersElf, plantersElf, expandersElf]; const heatedCuttersElf = createElf({ @@ -554,7 +655,8 @@ const layer = createLayer(id, function (this: BaseLayer) { description: "Jack will automatically purchase heated cutters you can afford, without actually spending any coal.", buyable: coal.heatedCutters, - cooldownModifier: heatedCutterCooldown + cooldownModifier: heatedCutterCooldown, + buyMax: () => management.elfTraining.heatedCutterElfTraining.milestones[2].earned.value }); const heatedPlantersElf = createElf({ name: "Mary", @@ -657,6 +759,77 @@ const layer = createLayer(id, function (this: BaseLayer) { visibility: () => showIf(plastic.elfUpgrades.clothElf.bought.value) }); const plasticElves = [paperElf, boxElf, clothElf]; + const miningDrillElf = createElf({ + name: "Peppermint", + description: + "Peppermint will automatically purchase all mining drills you can afford, without actually spending any resources.", + buyable: coal.buildDrill, + cooldownModifier: miningDrillCooldown, + visibility: () => + showIf(management.elfTraining.expandersElfTraining.milestones[3].earned.value), + hasToggle: true, + toggleDesc: "Activate auto-purchased mining drills", + onAutoPurchase() { + if (miningDrillElf.toggle.value) { + coal.activeDrills.value = Decimal.add(coal.activeDrills.value, 1); + } + } + }); + const heavyDrillElf = createElf({ + name: "Frosty", + description: + "Frosty will automatically purchase all drill types in the oil section, without actually spending any resources.", + buyable: [oil.buildHeavy, oil.buildHeavy2, oil.buildExtractor], + cooldownModifier: heavyDrillCooldown, + visibility: () => + showIf(management.elfTraining.fertilizerElfTraining.milestones[4].earned.value), + hasToggle: true, + toggleDesc: "Activate auto-purchased oil drills", + onAutoPurchase(buyable) { + if (heavyDrillElf.toggle.value) { + if (buyable === oil.buildHeavy) { + oil.activeHeavy.value = Decimal.add(oil.activeHeavy.value, 1); + } else if (buyable === oil.buildHeavy) { + oil.activeHeavy.value = Decimal.add(oil.activeHeavy.value, 1); + } else if (buyable === oil.buildHeavy) { + oil.activeHeavy.value = Decimal.add(oil.activeHeavy.value, 1); + } + } + } + }); + const oilElf = createElf({ + name: "Cocoa", + description: + "Cocoa will automatically purchase all oil-using machines you can afford, without actually spending any resources.", + buyable: [oil.buildPump, oil.buildBurner, oil.buildSmelter], + cooldownModifier: oilCooldown, + visibility: () => + showIf(management.elfTraining.heatedCutterElfTraining.milestones[4].earned.value), + hasToggle: true, + toggleDesc: "Activate auto-purchased oil-using machines", + onAutoPurchase(buyable) { + if (heavyDrillElf.toggle.value) { + if (buyable === oil.buildPump) { + oil.activePump.value = Decimal.add(oil.activePump.value, 1); + } else if (buyable === oil.buildBurner) { + oil.activeBurner.value = Decimal.add(oil.activeBurner.value, 1); + } else if (buyable === oil.buildSmelter) { + oil.activeSmelter.value = Decimal.add(oil.activeSmelter.value, 1); + } + } + } + }); + const managementElves = [miningDrillElf, heavyDrillElf, oilElf]; + const metalElf = createElf({ + name: "Twinkle", + description: + "Twinkle will automatically purchase all metal buyables you can afford, without actually spending any resources.", + buyable: [metal.oreDrill, metal.industrialCrucible, metal.hotterForge], + cooldownModifier: metalCooldown, + visibility: () => + showIf(management.elfTraining.expandersElfTraining.milestones[4].earned.value) + }); + const managementElves2 = [metalElf]; const elves = { cuttersElf, plantersElf, @@ -669,7 +842,11 @@ const layer = createLayer(id, function (this: BaseLayer) { kilnElf, paperElf, boxElf, - clothElf + clothElf, + miningDrillElf, + heavyDrillElf, + oilElf, + metalElf }; const totalElves = computed(() => Object.values(elves).filter(elf => elf.bought.value).length); @@ -849,7 +1026,14 @@ const layer = createLayer(id, function (this: BaseLayer) { {render(modifiersModal)}
- {renderGrid(treesElves, coalElves, fireElves, plasticElves)} + {renderGrid( + treesElves, + coalElves, + fireElves, + plasticElves, + managementElves, + managementElves2 + )}
{milestonesDisplay()} diff --git a/src/data/layers/management.tsx b/src/data/layers/management.tsx index d1988b6..8ecdd39 100644 --- a/src/data/layers/management.tsx +++ b/src/data/layers/management.tsx @@ -1,50 +1,41 @@ import Spacer from "components/layout/Spacer.vue"; -import Sqrt from "components/math/Sqrt.vue"; import Fraction from "components/math/Fraction.vue"; +import Sqrt from "components/math/Sqrt.vue"; +import Modal from "components/Modal.vue"; import { createCollapsibleMilestones, createCollapsibleModifierSections } from "data/common"; import { main } from "data/projEntry"; import { createBar, GenericBar } from "features/bars/bar"; -import { createClickable, GenericClickable } from "features/clickables/clickable"; -import { jsx, JSXFunction, showIf } from "features/feature"; +import { createBuyable } from "features/buyable"; +import { createClickable } from "features/clickables/clickable"; +import { jsx, showIf } from "features/feature"; import { createMilestone, GenericMilestone } from "features/milestones/milestone"; +import { createUpgrade } from "features/upgrades/upgrade"; +import { globalBus } from "game/events"; import { createLayer } from "game/layers"; -import { Persistent, persistent } from "game/persistence"; +import { + createAdditiveModifier, + createMultiplicativeModifier, + createSequentialModifier, + Modifier +} from "game/modifiers"; +import { persistent } from "game/persistence"; import Decimal, { DecimalSource, format, formatTime, formatWhole } from "util/bignum"; import { Direction } from "util/common"; -import { render, renderCol, renderGrid, renderRow } from "util/vue"; -import { computed, ComputedRef, ref, Ref } from "vue"; -import { createTabFamily } from "features/tabs/tabFamily"; -import { createTab } from "features/tabs/tab"; -import elves from "./elves"; -import trees from "./trees"; -import { globalBus } from "game/events"; -import { createMultiplicativeModifier, createSequentialModifier, Modifier } from "game/modifiers"; -import Modal from "components/Modal.vue"; -import { createBuyable, GenericBuyable } from "features/buyable"; -import { createUpgrade } from "features/upgrades/upgrade"; -import coal from "./coal"; -import paper from "./paper"; +import { render, renderCol, renderGrid } from "util/vue"; +import { computed, ComputedRef, ref, Ref, unref, watchEffect } from "vue"; import boxes from "./boxes"; -import metal from "./metal"; import cloth from "./cloth"; -import plastic from "./plastic"; +import coal from "./coal"; import dyes from "./dyes"; +import elves from "./elves"; +import metal from "./metal"; +import paper from "./paper"; +import plastic from "./plastic"; +import trees from "./trees"; const id = "management"; const day = 12; - -interface ElfTrainingClickable extends GenericClickable { - name: string, - state: Persistent, - displayMilestone: JSXFunction, - level: ComputedRef, - exp: Persistent, - milestones: GenericMilestone[], - timeForExp: ComputedRef, - amountOfTimesDone: Ref, - elfXPGainComputed: ComputedRef, - elfXPGain: Modifier, -} +const advancedDay = 13; const layer = createLayer(id, () => { const name = "Management"; @@ -58,12 +49,24 @@ const layer = createLayer(id, () => { height: 25, fillStyle: `backgroundColor: ${color}`, progress: () => - main.day.value === day ? totalElfLevels.value / (elves.totalElves.value * 5) : 1, + main.day.value === day + ? day12Elves.reduce((acc, curr) => acc + Math.min(1, curr.level.value / 3), 0) / + day12Elves.length + : main.day.value === advancedDay && main.days[advancedDay - 1].opened.value + ? day13Elves.reduce((acc, curr) => acc + Math.min(1, curr.level.value / 5), 0) / + day13Elves.length + : 1, display: jsx(() => - main.day.value === day ? ( + main.day.value === day || + (main.day.value === advancedDay && main.days[advancedDay - 1].opened.value) ? ( <> - {formatWhole(totalElfLevels.value)}/{formatWhole(elves.totalElves.value * 5)}{" "} - elf levels + {formatWhole( + Decimal.times( + unref(dayProgress.progress), + main.day.value === advancedDay ? 80 : 36 + ) + )} + /{main.day.value === advancedDay ? 80 : 36} elf levels ) : ( "" @@ -78,8 +81,10 @@ const layer = createLayer(id, () => { } return elfLevel; }); + const totalElfExp = computed(() => + Object.values(elfTraining).reduce((acc, curr) => acc.add(curr.exp.value), new Decimal(0)) + ); - // ------------------------------------------------------------------------------- Upgrades const teaching = createUpgrade(() => ({ @@ -105,12 +110,12 @@ const layer = createLayer(id, () => { })); const globalXPModifier = createSequentialModifier(() => [ createMultiplicativeModifier(() => ({ - multiplier: () => classroomEffect.value, + multiplier: classroomEffect, description: "Classroom Effect", - enabled: () => classroomUpgrade.bought.value + enabled: classroomUpgrade.bought })) ]); - const globalXPModifierComputed = globalXPModifier.apply(1); + const globalXPModifierComputed = computed(() => globalXPModifier.apply(1)); // ------------------------------------------------------------------------------- Training core function @@ -124,15 +129,33 @@ const layer = createLayer(id, () => { ...modifiers: Modifier[] ) { const exp = persistent(0); - const expRequiredForNextLevel = computed(() => Decimal.pow(10, level.value).mul(1e4)); + let costMulti = + [ + "Holly", + "Ivy", + "Hope", + "Jack", + "Mary", + "Noel", + "Joy", + "Faith", + "Snowball", + "Star", + "Bell", + "Gingersnap" + ].indexOf(elf.name) + 1; + if (elf.name == "Star" || elf.name == "Bell") { + costMulti /= 3; + } + const costBase = Decimal.mul(4000, costMulti); + const expRequiredForNextLevel = computed(() => Decimal.pow(5, level.value).mul(costBase)); const level = computed(() => - Decimal.min( - Decimal.mul(9, exp.value).div(1e4).add(1).log10().floor(), - schools.amount.value - ).toNumber() + Decimal.affordGeometricSeries(exp.value, costBase, 5, 0) + .min(schools.amount.value) + .toNumber() ); const expToNextLevel = computed(() => - Decimal.sub(exp.value, Decimal.pow(10, level.value).sub(1).div(9).mul(1e4)) + Decimal.sub(exp.value, Decimal.sumGeometricSeries(level.value, costBase, 5, 0)) ); const bar = createBar(() => ({ direction: Direction.Right, @@ -140,17 +163,24 @@ const layer = createLayer(id, () => { height: 12, style: () => ({ "margin-top": "8px", - "box-shadow": focusTargets.value[elf.name] + "box-shadow": focusTargets.value[elf.name] ? "0 0 12px " + (currentShown.value == elf.name ? "black" : "white") - : "", + : "" }), baseStyle: "margin-top: 0", fillStyle: "margin-top: 0; transition-duration: 0s", - borderStyle: () => Decimal.gte(level.value, schools.amount.value) ? "border-color: red" : "", + borderStyle: () => + Decimal.gte(level.value, schools.amount.value) ? "border-color: red" : "", progress: () => Decimal.div(expToNextLevel.value, expRequiredForNextLevel.value), - display: jsx(() => Decimal.gte(level.value, schools.amount.value) - ? <>Limit reached - : <>{format(expToNextLevel.value)}/{format(expRequiredForNextLevel.value)} XP) + display: jsx(() => + Decimal.gte(level.value, schools.amount.value) ? ( + <>Limit reached + ) : ( + <> + {format(expToNextLevel.value)}/{format(expRequiredForNextLevel.value)} XP + + ) + ) })); const { collapseMilestones: state, display: displayMilestone } = createCollapsibleMilestones(milestones as Record); @@ -162,20 +192,23 @@ const layer = createLayer(id, () => { createMultiplicativeModifier(() => ({ multiplier: focusMulti, description: "Focus Multiplier", - enabled: () => focusRolling.value <= 0 && focusTargets.value[elf.name] == true + enabled: () => + Decimal.gt(focusTime.value, 0) && focusTargets.value[elf.name] == true })), ...modifiers ]); const elfXPGainComputed = computed(() => elfXPGain.apply(0.1)); const click = createClickable(() => ({ display: { - title: elf.name, + title: jsx(() => ( + <> + {elf.name} - LV {formatWhole(level.value)} + + )), description: jsx(() => ( <> - {elf.name} is currently at level {formatWhole(level.value)}, and - achieved a total of {format(exp.value)} XP. - They buy buyables {formatWhole(elf.computedAutoBuyCooldown.value)} times per - second, gaining{" "} + {elf.name} can buy buyables {formatWhole(elf.computedAutoBuyCooldown.value)}{" "} + times per second, gaining{" "} {Decimal.gte(level.value, schools.amount.value) ? 0 : format( @@ -191,7 +224,7 @@ const layer = createLayer(id, () => { }, style: () => ({ width: "190px", - background: currentShown.value == elf.name ? "var(--foreground)" : "", + background: currentShown.value == elf.name ? "var(--foreground)" : "" }), onClick() { currentShown.value = elf.name; @@ -219,7 +252,12 @@ const layer = createLayer(id, () => { createMilestone(() => ({ display: { requirement: "Holly Level 1", - effectDisplay: jsx(() => <>Multiply log gain by (Cutter amount)3.) + effectDisplay: jsx(() => ( + <> + Multiply log gain by 9 + Cutter amount. + + )) }, shouldEarn: () => cutterElfTraining.level.value >= 1 })), @@ -234,7 +272,12 @@ const layer = createLayer(id, () => { createMilestone(() => ({ display: { requirement: "Holly Level 3", - effectDisplay: jsx(() => <>Multiply all cloth actions' effectiveness by (Cutter amount)3.) + effectDisplay: jsx(() => ( + <> + Multiply all cloth actions' effectiveness by log10(Cutter + amount). + + )) }, visibility: () => showIf(cutterElfMilestones[1].earned.value), shouldEarn: () => cutterElfTraining.level.value >= 3 @@ -242,7 +285,7 @@ const layer = createLayer(id, () => { createMilestone(() => ({ display: { requirement: "Holly Level 4", - effectDisplay: "Multiply cutting speed by 1.1 per day completed" + effectDisplay: "Multiply auto cutting amount by 1.1 per day completed" }, visibility: () => showIf(cutterElfMilestones[2].earned.value && main.day.value >= 13), shouldEarn: () => cutterElfTraining.level.value >= 4 @@ -275,7 +318,14 @@ const layer = createLayer(id, () => { createMilestone(() => ({ display: { requirement: "Ivy Level 3", - effectDisplay: jsx(() => <>Planting speed is multiplied by 2(log10(logs)0.2)) + effectDisplay: jsx(() => ( + <> + Auto planting speed is multiplied by 2 + + (log10(logs)0.2) + + + )) }, visibility: () => showIf(planterElfMilestones[1].earned.value), shouldEarn: () => planterElfTraining.level.value >= 3 @@ -291,7 +341,8 @@ const layer = createLayer(id, () => { createMilestone(() => ({ display: { requirement: "Ivy Level 5", - effectDisplay: "Boost planting/cutting speed based on which is falling behind" + effectDisplay: + "The lesser of auto planting and cutting amounts is increased to match the greater" }, visibility: () => showIf(planterElfMilestones[3].earned.value && main.day.value >= 13), shouldEarn: () => planterElfTraining.level.value >= 5 @@ -301,7 +352,7 @@ const layer = createLayer(id, () => { createMilestone(() => ({ display: { requirement: "Hope Level 1", - effectDisplay: "Planting speed boosts forest size" + effectDisplay: "Forest size grows by trees planted per second raised to ^0.99" }, shouldEarn: () => expandersElfTraining.level.value >= 1 })), @@ -316,7 +367,8 @@ const layer = createLayer(id, () => { createMilestone(() => ({ display: { requirement: "Hope Level 3", - effectDisplay: "The workshop can be expanded past 100%, but costs scale faster." + effectDisplay: + "The workshop can be expanded past 100%, but costs scale faster. It also buys max now." }, visibility: () => showIf(expanderElfMilestones[1].earned.value), shouldEarn: () => expandersElfTraining.level.value >= 3 @@ -342,7 +394,7 @@ const layer = createLayer(id, () => { createMilestone(() => ({ display: { requirement: "Jack Level 1", - effectDisplay: "Heated cutters are less expensive." + effectDisplay: '"Fahrenheit 451" affects "Heated Cutters" twice.' }, shouldEarn: () => heatedCutterElfTraining.level.value >= 1 })), @@ -365,7 +417,11 @@ const layer = createLayer(id, () => { createMilestone(() => ({ display: { requirement: "Jack Level 4", - effectDisplay: "Oil gain is multiplied based on total elf levels." + effectDisplay: jsx(() => ( + <> + Oil gain is multiplied by total elf levels. + + )) }, visibility: () => showIf(heatedCutterElfMilestones[2].earned.value && main.day.value >= 13), @@ -374,7 +430,7 @@ const layer = createLayer(id, () => { createMilestone(() => ({ display: { requirement: "Jack Level 5", - effectDisplay: "Unlock an elf that autobuys oil buyables." + effectDisplay: "Unlock an elf that autobuys oil-using machines." }, visibility: () => showIf(heatedCutterElfMilestones[3].earned.value && main.day.value >= 13), @@ -392,7 +448,7 @@ const layer = createLayer(id, () => { createMilestone(() => ({ display: { requirement: "Mary Level 2", - effectDisplay: "Double automatic tree planting speed" + effectDisplay: "Metal gain is raised to the 1.1." }, visibility: () => showIf(heatedPlanterElfMilestones[0].earned.value), shouldEarn: () => heatedPlanterElfTraining.level.value >= 2 @@ -408,7 +464,7 @@ const layer = createLayer(id, () => { createMilestone(() => ({ display: { requirement: "Mary Level 4", - effectDisplay: "Metal gain is raised to the 1.1." + effectDisplay: "Double automatic tree planting speed" }, visibility: () => showIf(heatedPlanterElfMilestones[2].earned.value && main.day.value >= 13), @@ -417,7 +473,11 @@ const layer = createLayer(id, () => { createMilestone(() => ({ display: { requirement: "Mary Level 5", - effectDisplay: jsx(() => <>Auto smelting speed is multiplied by total XP/1000.) + effectDisplay: jsx(() => ( + <> + Auto smelting speed is multiplied by total XP/1000. + + )) }, visibility: () => showIf(heatedPlanterElfMilestones[3].earned.value && main.day.value >= 13), @@ -428,9 +488,13 @@ const layer = createLayer(id, () => { createMilestone(() => ({ display: { requirement: "Noel Level 1", - effectDisplay: jsx(() => <>Log gain is multiplied by total elf levels.) + effectDisplay: jsx(() => ( + <> + Log gain is multiplied by total elf levels. + + )) }, - shouldEarn: () => heatedPlanterElfTraining.level.value >= 1 + shouldEarn: () => fertilizerElfTraining.level.value >= 1 })), createMilestone(() => ({ display: { @@ -438,7 +502,7 @@ const layer = createLayer(id, () => { effectDisplay: `"The Garden Tree's Handbook" affects "Fertilized Soil" twice` }, visibility: () => showIf(fertilizerElfMilestones[0].earned.value), - shouldEarn: () => heatedPlanterElfTraining.level.value >= 2 + shouldEarn: () => fertilizerElfTraining.level.value >= 2 })), createMilestone(() => ({ display: { @@ -446,16 +510,20 @@ const layer = createLayer(id, () => { effectDisplay: "Divide the mining drill cost by ln(Total logs + e)" }, visibility: () => showIf(fertilizerElfMilestones[1].earned.value), - shouldEarn: () => heatedPlanterElfTraining.level.value >= 3 + shouldEarn: () => fertilizerElfTraining.level.value >= 3 })), createMilestone(() => ({ display: { requirement: "Noel Level 4", - effectDisplay: jsx(() => <>Reduce oil refinery cost by (Plastic amount)2) + effectDisplay: jsx(() => ( + <> + Reduce oil refinery cost by (Plastic amount)2 + + )) }, visibility: () => showIf(fertilizerElfMilestones[2].earned.value && main.day.value >= 13), - shouldEarn: () => heatedPlanterElfTraining.level.value >= 4 + shouldEarn: () => fertilizerElfTraining.level.value >= 4 })), createMilestone(() => ({ display: { @@ -471,7 +539,7 @@ const layer = createLayer(id, () => { createMilestone(() => ({ display: { requirement: "Joy Level 1", - effectDisplay: "Multiply small fire efficiency by 5." + effectDisplay: "Small Fire synergy counts bonfires at reduced rate." }, shouldEarn: () => smallfireElfTraining.level.value >= 1 })), @@ -619,7 +687,11 @@ const layer = createLayer(id, () => { createMilestone(() => ({ display: { requirement: "Star Level 4", - effectDisplay: jsx(() => <>Multiply XP requirements by 0.95(total books)) + effectDisplay: jsx(() => ( + <> + Multiply XP requirements by 0.95(total books) + + )) }, visibility: () => showIf(paperElfMilestones[2].earned.value && main.day.value >= 13), shouldEarn: () => paperElfTraining.level.value >= 4 @@ -637,7 +709,11 @@ const layer = createLayer(id, () => { createMilestone(() => ({ display: { requirement: "Bell Level 1", - effectDisplay: jsx(() => <>Every box buyable adds level levels to same-row box buyables.) + effectDisplay: jsx(() => ( + <> + Every box buyable adds level levels to same-row box buyables. + + )) }, shouldEarn: () => boxElfTraining.level.value >= 1 })), @@ -685,7 +761,11 @@ const layer = createLayer(id, () => { createMilestone(() => ({ display: { requirement: "Gingersnap Level 2", - effectDisplay: jsx(() => <>Multiply all cloth actions' effectiveness by log10(dye sum + 10)) + effectDisplay: jsx(() => ( + <> + Multiply all cloth actions' effectiveness by log10(dye sum + 10) + + )) }, visibility: () => showIf(clothElfMilestones[0].earned.value), shouldEarn: () => clothElfTraining.level.value >= 2 @@ -698,26 +778,39 @@ const layer = createLayer(id, () => { visibility: () => showIf(clothElfMilestones[1].earned.value), shouldEarn: () => clothElfTraining.level.value >= 3, onComplete() { - (["red", "yellow", "blue", "orange", "green", "purple"] as const).forEach(dyeColor => { - dyes.dyes[dyeColor].amount.value = 0; - dyes.dyes[dyeColor].buyable.amount.value = 0; - }); + (["red", "yellow", "blue", "orange", "green", "purple"] as const).forEach( + dyeColor => { + dyes.dyes[dyeColor].amount.value = 0; + dyes.dyes[dyeColor].buyable.amount.value = 0; + } + ); } })), createMilestone(() => ({ display: { requirement: "Gingersnap Level 4", - effectDisplay: jsx(() => <>Multiply ALL dye gain by{" "} -
classrooms
2
+1, - but reset all dyes.) + effectDisplay: jsx(() => ( + <> + Multiply ALL dye gain by{" "} + +
+ classrooms +
+
2
+
+ +1, but reset all dyes. + + )) }, visibility: () => showIf(clothElfMilestones[2].earned.value && main.day.value >= 13), shouldEarn: () => clothElfTraining.level.value >= 4, onComplete() { - (["red", "yellow", "blue", "orange", "green", "purple"] as const).forEach(dyeColor => { - dyes.dyes[dyeColor].amount.value = 0; - dyes.dyes[dyeColor].buyable.amount.value = 0; - }); + (["red", "yellow", "blue", "orange", "green", "purple"] as const).forEach( + dyeColor => { + dyes.dyes[dyeColor].amount.value = 0; + dyes.dyes[dyeColor].buyable.amount.value = 0; + } + ); } })), createMilestone(() => ({ @@ -796,7 +889,35 @@ const layer = createLayer(id, () => { paperElfTraining, boxElfTraining, clothElfTraining - } as Record; + }; + const day12Elves = [ + cutterElfTraining, + planterElfTraining, + expandersElfTraining, + heatedCutterElfTraining, + heatedPlanterElfTraining, + fertilizerElfTraining, + smallfireElfTraining, + bonfireElfTraining, + kilnElfTraining, + paperElfTraining, + boxElfTraining, + clothElfTraining + ]; + const day13Elves = [ + cutterElfTraining, + planterElfTraining, + expandersElfTraining, + heatedCutterElfTraining, + heatedPlanterElfTraining, + fertilizerElfTraining, + smallfireElfTraining, + bonfireElfTraining, + kilnElfTraining, + paperElfTraining, + boxElfTraining, + clothElfTraining + ]; // ------------------------------------------------------------------------------- Update @@ -813,69 +934,115 @@ const layer = createLayer(id, () => { ); } } + focusTime.value = Math.max(focusTime.value - diff, 0); + focusCooldown.value = Math.max(focusCooldown.value - diff, 0); - if (focusRolling.value > 0) { - focusRolling.value += diff; - focusMulti.value = Decimal.pow(focusMaxMulti.value, 1 - Math.abs(Math.sin((focusRolling.value - 1) * 3))); - rerollFocusTargets(12, 3); - } else { - focusRolling.value = Math.min(focusRolling.value + diff, 0); + if (Decimal.eq(focusTime.value, 0)) { + focusTargets.value = {}; + focusMulti.value = Decimal.pow( + focusMaxMulti.value, + 1 - Math.abs(Math.sin((Date.now() / 1000) * 2)) + ); } }); - + // ------------------------------------------------------------------------------- Focus const focusMulti = persistent(1); const focusTargets = persistent>({}); - const focusRolling = persistent(0); + const focusCooldown = persistent(0); + const focusTime = persistent(0); + + const focusMaxMultiModifiers = createSequentialModifier(() => [ + createMultiplicativeModifier(() => ({ + multiplier: 2, + description: "Focus Upgrade 1", + enabled: focusUpgrade1.bought + })) + ]); + const maximumElvesModifier = createSequentialModifier(() => [ + createAdditiveModifier(() => ({ + addend: 1, + description: "Focus Upgrade 2", + enabled: focusUpgrade2.bought + })) + ]); + + const cooldownModifiers = createSequentialModifier(() => [ + createAdditiveModifier(() => ({ + addend: -5, + description: "Focus Upgrade 3", + enabled: focusUpgrade3.bought + })) + ]); + + const focusMaxMulti = computed(() => focusMaxMultiModifiers.apply(10)); + const maximumElves = computed(() => maximumElvesModifier.apply(3)); + const cooldown = computed(() => cooldownModifiers.apply(15)); - const focusMaxMulti = computed(() => 10); - const focusMeter = createBar(() => ({ direction: Direction.Right, width: 566, height: 25, style: `border-radius: 4px 4px 0 0`, borderStyle: `border-radius: 4px 4px 0 0`, - fillStyle: `background: ${color}; transition: none`, - progress: () => Decimal.sub(focusMulti.value, 1).div(Decimal.sub(focusMaxMulti.value, 1)).toNumber(), - display: jsx(() => <>{format(focusMulti.value)}x) + fillStyle: () => ({ + background: focusTime.value > 0 ? color : "#7f7f00", + opacity: focusTime.value > 0 ? focusTime.value / 10 : 1, + transition: "none" + }), + progress: () => + Decimal.sub(focusMulti.value, 1).div(Decimal.sub(focusMaxMulti.value, 1)).toNumber(), + display: jsx(() => ( + <> + {format(focusMulti.value)}x + {focusTime.value > 0 ? ( + <> + {" "} + to {Object.keys(focusTargets.value).join(", ")} for{" "} + {formatTime(focusTime.value)} + + ) : ( + "" + )} + + )) })) as GenericBar; - + const focusButton = createClickable(() => ({ display: { title: "Focus", description: jsx(() => ( <> - {focusRolling.value <= 0 - ? <>Motivate elves to focus, multiplying 3 random elves' XP gain by up to {format(focusMaxMulti.value)}x - : "Click to stop the focus bar" - } - {focusRolling.value < 0 - ? <>
Reroll cooldown: {formatTime(-focusRolling.value)} - : "" - } + Motivate elves to focus, multiplying 3 random elves' XP gain by up to{" "} + {format(focusMaxMulti.value)}x for 10 seconds, equal to the focus bar's effect. + {Decimal.gte(focusCooldown.value, 0) ? ( + <> +
+ Reroll cooldown: {formatTime(focusCooldown.value)} + + ) : ( + "" + )} )) }, style: { width: "300px" }, - canClick: () => focusRolling.value >= 0, + canClick: () => Decimal.eq(focusCooldown.value, 0), onClick() { - if (focusRolling.value == 0) { - focusRolling.value = 1; - } else if (focusRolling.value > 0) { - focusRolling.value = -30; - } + focusCooldown.value = Decimal.fromValue(cooldown.value).toNumber(); + focusTime.value = 10; + rerollFocusTargets(12, maximumElves.value); } })); - function rerollFocusTargets(range: number, count: number) { + function rerollFocusTargets(range: number, count: DecimalSource) { let x = 0; focusTargets.value = {}; - count = Math.min(count, range); - while (x < count) { + const newCount = Decimal.min(count, range); + while (newCount.gt(x)) { const roll = Object.values(elfTraining)[Math.floor(Math.random() * range)]?.name ?? ""; if (!focusTargets.value[roll]) { focusTargets.value[roll] = true; @@ -883,19 +1050,46 @@ const layer = createLayer(id, () => { } } } - + const focusUpgrade1 = createUpgrade(() => ({ + display: { + title: "Focus Booster", + description: "Multiplies the maximum experience multiplier from focus by 2" + }, + resource: trees.logs, + cost: 1e25 + })); + const focusUpgrade2 = createUpgrade(() => ({ + display: { + title: "Focus Buffer", + description: "Increase elves affected by focus by 1" + }, + resource: trees.logs, + cost: 1e30 + })); + const focusUpgrade3 = createUpgrade(() => ({ + display: { + title: "Focus Upgrader", + description: "Focus can now be rerolled every 10 seconds" + }, + resource: trees.logs, + cost: 1e35 + })); + const upgrades = [focusUpgrade1, focusUpgrade2, focusUpgrade3]; // ------------------------------------------------------------------------------- Schools const schoolCost = computed(() => { const schoolFactor = Decimal.pow(10, schools.amount.value); + const nerfedSchoolFactor = Decimal.pow(5, schools.amount.value); + const woodFactor = Decimal.pow(2e4, Decimal.pow(schools.amount.value, 0.75)); + const coalFactor = Decimal.pow(2000, schools.amount.value); return { - wood: schoolFactor.mul(1e21), - coal: schoolFactor.mul(1e32), - paper: schoolFactor.mul(1e19), - boxes: schoolFactor.mul(1e13), - metalIngots: schoolFactor.mul(1e12), + wood: woodFactor.mul(1e21), + coal: coalFactor.mul(1e32), + paper: coalFactor.mul(1e18), + boxes: woodFactor.mul(1e13), + metalIngots: nerfedSchoolFactor.mul(1e12), cloth: schoolFactor.mul(1e4), - plastic: schoolFactor.mul(1e6), + plastic: nerfedSchoolFactor.mul(1e6), dye: Decimal.add(schools.amount.value, 1).mul(10000) }; }); @@ -906,11 +1100,11 @@ const layer = createLayer(id, () => {

Build a School

You gotta start somewhere, right? Each school increases the maximum level for - elves by 1, up to 5. + elves by 1, maximum of {main.day.value === 12 ? 3 : 5} schools.
-
You have {formatWhole(schools.amount.value)} schools, - which are currently letting elves learn up to level{" "} - {formatWhole(schools.amount.value)}. +
+ You have {formatWhole(schools.amount.value)} schools, which are currently + letting elves learn up to level {formatWhole(schools.amount.value)}.
Costs {format(schoolCost.value.wood)} logs, {format(schoolCost.value.coal)}{" "} @@ -946,27 +1140,26 @@ const layer = createLayer(id, () => { plastic.plastic.value = Decimal.sub(plastic.plastic.value, schoolCost.value.plastic); this.amount.value = Decimal.add(this.amount.value, 1); }, - purchaseLimit: 5, + purchaseLimit() { + if (main.days[advancedDay - 1].opened.value) return 5 + return 3 + }, visibility: computed(() => showIf(teaching.bought.value)), style: "width: 600px" })); const classroomCost = computed(() => { - const classroomFactor = Decimal.add(schools.amount.value, 1).pow(1.5); + const classroomFactor = Decimal.add(classrooms.amount.value, 1).pow(1.5); return { wood: classroomFactor.mul(1e21), - coal: classroomFactor.mul(1e32), - paper: classroomFactor.mul(1e19), + paper: classroomFactor.mul(1e18), boxes: classroomFactor.mul(1e13), - metalIngots: classroomFactor.mul(1e12), - cloth: classroomFactor.mul(1e4), - plastic: classroomFactor.mul(1e6), - dye: classroomFactor.mul(10000) + metalIngots: classroomFactor.mul(1e12) }; }); const classroomEffect = computed(() => { - return Decimal.add(classrooms.amount.value, 1).sqrt(); + return Decimal.add(classrooms.amount.value, 1).pow(0.9); }); const classrooms = createBuyable(() => ({ @@ -975,44 +1168,32 @@ const layer = createLayer(id, () => {

Build a Classroom

Hopefully it makes the school a bit less boring. Multiplies elves' XP gain by{" "} - Classrooms + 1. -
-
You have {formatWhole(schools.amount.value)} classrooms, - which are currently multiplying elves' XP gain by {format(classroomEffect.value)} + (Classrooms + 1)0.9.
- Costs {format(classroomCost.value.wood)} logs,{" "} - {format(classroomCost.value.coal)} coal, {format(classroomCost.value.paper)}{" "} - paper, {format(classroomCost.value.boxes)} boxes,{" "} - {format(classroomCost.value.metalIngots)} metal ingots,{" "} - {format(classroomCost.value.cloth)} cloth, {format(classroomCost.value.plastic)}{" "} - plastic, and requires {format(classroomCost.value.dye)} of red, yellow, and blue - dye + You have {formatWhole(classrooms.amount.value)} classrooms, which are currently + multiplying elves' XP gain by {format(classroomEffect.value)} +
+
+ Costs {format(classroomCost.value.wood)} logs, + {format(classroomCost.value.paper)} paper, {format(classroomCost.value.boxes)}{" "} + boxes, {format(classroomCost.value.metalIngots)} metal ingots
)), canPurchase(): boolean { return ( classroomCost.value.wood.lte(trees.logs.value) && - classroomCost.value.coal.lte(coal.coal.value) && classroomCost.value.paper.lte(paper.paper.value) && classroomCost.value.boxes.lte(boxes.boxes.value) && - classroomCost.value.metalIngots.lte(metal.metal.value) && - classroomCost.value.cloth.lte(cloth.cloth.value) && - classroomCost.value.plastic.lte(plastic.plastic.value) && - classroomCost.value.dye.lte(dyes.dyes.blue.amount.value) && - classroomCost.value.dye.lte(dyes.dyes.red.amount.value) && - classroomCost.value.dye.lte(dyes.dyes.yellow.amount.value) + classroomCost.value.metalIngots.lte(metal.metal.value) ); }, onPurchase() { trees.logs.value = Decimal.sub(trees.logs.value, classroomCost.value.wood); - coal.coal.value = Decimal.sub(coal.coal.value, classroomCost.value.coal); paper.paper.value = Decimal.sub(paper.paper.value, classroomCost.value.paper); boxes.boxes.value = Decimal.sub(boxes.boxes.value, classroomCost.value.boxes); metal.metal.value = Decimal.sub(metal.metal.value, classroomCost.value.metalIngots); - cloth.cloth.value = Decimal.sub(cloth.cloth.value, classroomCost.value.cloth); - plastic.plastic.value = Decimal.sub(plastic.plastic.value, classroomCost.value.plastic); this.amount.value = Decimal.add(this.amount.value, 1); }, visibility: computed(() => showIf(classroomUpgrade.bought.value)), @@ -1022,6 +1203,22 @@ const layer = createLayer(id, () => { // ------------------------------------------------------------------------------- Modifiers const [generalTab, generalTabCollapsed] = createCollapsibleModifierSections(() => [ + { + title: "Elves affected by Focus", + modifier: maximumElvesModifier, + base: 3 + }, + { + title: "Maximum Focus Effect", + modifier: focusMaxMultiModifiers, + base: 10 + }, + { + title: "Focus Cooldown", + modifier: cooldownModifiers, + unit: " secs", + base: 15 + }, { title: "Global XP Gain", modifier: globalXPModifier, @@ -1112,7 +1309,17 @@ const layer = createLayer(id, () => { /> )); - + watchEffect(() => { + if (main.day.value === day && day12Elves.every(elf => elf.level.value >= 3)) { + main.completeDay(); + } else if ( + main.day.value === advancedDay && + day13Elves.every(elf => elf.level.value >= 5) + ) { + main.completeDay(); + } + }); + // ------------------------------------------------------------------------------- Return return { @@ -1123,6 +1330,7 @@ const layer = createLayer(id, () => { elfTraining, totalElfLevels, + totalElfExp, currentShown, generalTabCollapsed, @@ -1132,12 +1340,19 @@ const layer = createLayer(id, () => { classroomUpgrade, focusMultiplier: focusMulti, + upgrades, focusTargets, - focusRolling, + focusCooldown, + focusTime, display: jsx(() => ( <> - {main.day.value === day ? `Get all elves to level 5.` : `${name} Complete!`} - + {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!`}{" "} + - {render(modifiersModal)} {render(dayProgress)} -
- {renderCol(schools, classrooms)}{" "} +
+ {renderCol(schools, classrooms)} {renderGrid([teaching, classroomUpgrade])} - { - Decimal.gt(schools.amount.value, 0) ? <> -
+ + {Decimal.gt(schools.amount.value, 0) ? ( + <> +
Click on an elf to see their milestones. -

+
+
{render(focusButton)} -
+ {renderGrid(upgrades)} +
{renderGrid( [focusMeter], treeElfTraining, @@ -1166,8 +1384,10 @@ const layer = createLayer(id, () => { )} {currentElfDisplay()} - : "" - } + + ) : ( + "" + )} )) }; diff --git a/src/data/layers/metal.tsx b/src/data/layers/metal.tsx index 84a9c2a..586deea 100644 --- a/src/data/layers/metal.tsx +++ b/src/data/layers/metal.tsx @@ -4,7 +4,7 @@ import Toggle from "components/fields/Toggle.vue"; import Modal from "components/Modal.vue"; import { createCollapsibleModifierSections, setUpDailyProgressTracker } from "data/common"; import { jsx, showIf } from "features/feature"; -import { createResource, trackBest } from "features/resources/resource"; +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"; @@ -12,6 +12,7 @@ import { persistent } from "game/persistence"; import { globalBus } from "game/events"; import { createAdditiveModifier, + createExponentialModifier, createMultiplicativeModifier, createSequentialModifier } from "game/modifiers"; @@ -30,6 +31,8 @@ import boxes from "./boxes"; import cloth from "./cloth"; import plastic from "./plastic"; import dyes from "./dyes"; +import management from "./management"; +import workshop from "./workshop"; const id = "metal"; const day = 7; @@ -78,6 +81,17 @@ const layer = createLayer(id, function (this: BaseLayer) { multiplier: () => Decimal.add(cloth.cloth.value, 1).log10().plus(1), description: "Glistening Paint", enabled: dyes.upgrades.redDyeUpg.bought + })), + createMultiplicativeModifier(() => ({ + multiplier: () => + Decimal.div(workshop.foundationProgress.value, 10).floor().div(10).add(1), + description: "400% Foundation Completed", + enabled: workshop.milestones.extraExpansionMilestone2.earned + })), + createExponentialModifier(() => ({ + exponent: 1.1, + description: "Mary Level 2", + enabled: management.elfTraining.heatedPlanterElfTraining.milestones[1].earned })) ]); const computedOrePurity = computed(() => orePurity.apply(0.1)); @@ -108,6 +122,11 @@ const layer = createLayer(id, function (this: BaseLayer) { multiplier: () => Decimal.add(plastic.activeRefinery.value, 1).sqrt(), description: "De Louvre", enabled: dyes.upgrades.redDyeUpg2.bought + })), + createMultiplicativeModifier(() => ({ + multiplier: () => Decimal.div(management.totalElfExp.value, 1000).add(1).sqrt(), + description: "Mary Level 5", + enabled: management.elfTraining.heatedPlanterElfTraining.milestones[4].earned })) ]); const computedAutoSmeltSpeed = computed(() => autoSmeltSpeed.apply(0)); @@ -359,7 +378,7 @@ const layer = createLayer(id, function (this: BaseLayer) { .gte(10) ), style: { width: "200px" } - })) as GenericBuyable; + })) as GenericBuyable & { resource: Resource }; const industrialCrucible = createBuyable(() => ({ resource: noPersist(metal), cost() { @@ -382,7 +401,7 @@ const layer = createLayer(id, function (this: BaseLayer) { Decimal.gte(bestOre.value, 50) ), style: { width: "200px" } - })) as GenericBuyable; + })) as GenericBuyable & { resource: Resource }; const autoSmeltEnabled = persistent(true); const hotterForge = createBuyable(() => ({ resource: coal.coal, @@ -403,7 +422,7 @@ const layer = createLayer(id, function (this: BaseLayer) { visibility: () => showIf(Decimal.gte(hotterForge.amount.value, 1) || industrialFurnace.bought.value), style: { width: "200px" } - })) as GenericBuyable; + })) as GenericBuyable & { resource: Resource }; const hotterForgeEffect = computed(() => Decimal.times(hotterForge.amount.value, 0.25)); globalBus.on("update", diff => { @@ -573,6 +592,11 @@ const layer = createLayer(id, function (this: BaseLayer) { )} {renderRow(oreDrill, industrialCrucible, hotterForge)} + )), + minimizedDisplay: jsx(() => ( +
+ {name} - {format(metal.value)} {metal.displayName} +
)) }; }); diff --git a/src/data/layers/oil.tsx b/src/data/layers/oil.tsx index aa7a515..2866b02 100644 --- a/src/data/layers/oil.tsx +++ b/src/data/layers/oil.tsx @@ -35,6 +35,8 @@ import { formatGain } from "util/bignum"; import plastic from "./plastic"; import paper from "./paper"; import dyes from "./dyes"; +import management from "./management"; +import workshop from "./workshop"; const id = "oil"; const day = 9; @@ -247,8 +249,8 @@ const layer = createLayer(id, function (this: BaseLayer) {
Pump that oil from the ground.
- Gain oil based on the number of Heavy buildings active and well - depth, but coal usage is multiplied by {row2Upgrades[3].bought.value ? 4 : 5}×. + Gain oil based on the number of Heavy buildings active and well depth, but coal + usage is multiplied by {row2Upgrades[3].bought.value ? 4 : 5}×.

Currently: @@ -718,6 +720,17 @@ const layer = createLayer(id, function (this: BaseLayer) { multiplier: () => coalEffectiveness.value, description: "Effectiveness", enabled: () => Decimal.lt(coalEffectiveness.value, 1) + })), + createMultiplicativeModifier(() => ({ + multiplier: () => + Decimal.div(workshop.foundationProgress.value, 10).floor().div(10).add(1), + description: "600% Foundation Completed", + enabled: workshop.milestones.extraExpansionMilestone3.earned + })), + createMultiplicativeModifier(() => ({ + multiplier: () => Decimal.sqrt(management.totalElfLevels.value), + description: "Jack Level 4", + enabled: management.elfTraining.heatedCutterElfTraining.milestones[3].earned })) ]); const computedOilSpeed = computed(() => oilSpeed.apply(0)); @@ -947,6 +960,7 @@ const layer = createLayer(id, function (this: BaseLayer) { ( <> @@ -1068,7 +1082,12 @@ const layer = createLayer(id, function (this: BaseLayer) { {Decimal.gte(totalOil.value, 50) ? oilMilestonesDisplay() : ""} ); - }) + }), + minimizedDisplay: jsx(() => ( +
+ {name} - {format(oil.value)} {oil.displayName} +
+ )) }; }); diff --git a/src/data/layers/paper.tsx b/src/data/layers/paper.tsx index 94022e3..06d0223 100644 --- a/src/data/layers/paper.tsx +++ b/src/data/layers/paper.tsx @@ -28,6 +28,7 @@ import plastic from "./plastic"; import trees from "./trees"; import dyes from "./dyes"; import management from "./management"; +import workshop from "./workshop"; const id = "paper"; const day = 5; @@ -38,7 +39,12 @@ const layer = createLayer(id, function (this: BaseLayer) { const paper = createResource(0, "paper"); const pulp = createResource( - computed(() => Decimal.min(Decimal.div(trees.logs.value, 1e9), Decimal.div(coal.ash.value, computedAshCost.value))), + computed(() => + Decimal.min( + Decimal.div(trees.logs.value, 1e9), + Decimal.div(coal.ash.value, computedAshCost.value) + ) + ), "pulp" ); @@ -49,7 +55,10 @@ const layer = createLayer(id, function (this: BaseLayer) { roundUpCost: true, spend(gain, cost) { trees.logs.value = Decimal.sub(trees.logs.value, Decimal.times(cost, 1e9)); - coal.ash.value = Decimal.sub(coal.ash.value, Decimal.times(cost, computedAshCost.value)); + coal.ash.value = Decimal.sub( + coal.ash.value, + Decimal.times(cost, computedAshCost.value) + ); }, gainModifier: paperGain })); @@ -68,7 +77,8 @@ const layer = createLayer(id, function (this: BaseLayer) { Cost: {displayResource(trees.logs, cost)} {pulp.displayName} ( {formatWhole(Decimal.times(cost, 1e9))} {trees.logs.displayName};{" "} - {formatWhole(Decimal.times(cost, computedAshCost.value))} {coal.ash.displayName}) + {formatWhole(Decimal.times(cost, computedAshCost.value))}{" "} + {coal.ash.displayName}) ); @@ -187,6 +197,34 @@ const layer = createLayer(id, function (this: BaseLayer) { buyableName: "Cloth Buyables", visibility: () => showIf(elves.elves.clothElf.bought.value) }); + const miningDrillBook = createBook({ + name: "Drills and Mills", + elfName: "Peppermint", + buyableName: "Mining Drill", + visibility: () => + showIf(management.elfTraining.expandersElfTraining.milestones[3].earned.value) + }); + const heavyDrillBook = createBook({ + name: "Deep in the Earth", + elfName: "Frosty", + buyableName: "Oil Drills", + visibility: () => + showIf(management.elfTraining.fertilizerElfTraining.milestones[4].earned.value) + }); + const oilBook = createBook({ + name: "Burning the Midnight Oil", + elfName: "Cocoa", + buyableName: "Oil-Consuming Machines", + visibility: () => + showIf(management.elfTraining.heatedCutterElfTraining.milestones[4].earned.value) + }); + const metalBook = createBook({ + name: "Physical Metallurgy", + elfName: "Twinkle", + buyableName: "Metal Buyables", + visibility: () => + showIf(management.elfTraining.expandersElfTraining.milestones[4].earned.value) + }); const books = { cuttersBook, plantersBook, @@ -199,9 +237,15 @@ const layer = createLayer(id, function (this: BaseLayer) { kilnBook, paperBook, boxBook, - clothBook + clothBook, + miningDrillBook, + heavyDrillBook, + oilBook, + metalBook }; - const sumBooks = computed(() => Object.values(books).reduce((acc, curr) => acc.add(curr.amount.value), new Decimal(0))); + const sumBooks = computed(() => + Object.values(books).reduce((acc, curr) => acc.add(curr.amount.value), new Decimal(0)) + ); const clothUpgrade = createUpgrade(() => ({ resource: noPersist(paper), @@ -257,11 +301,16 @@ const layer = createLayer(id, function (this: BaseLayer) { multiplier: dyes.boosts.yellow1, description: "Yellow Dye Boost 1", enabled: () => Decimal.gte(dyes.dyes.yellow.amount.value, 1) + })), + createMultiplicativeModifier(() => ({ + multiplier: 2, + description: "1000% Foundation Completed", + enabled: workshop.milestones.extraExpansionMilestone5.earned })) ]) as WithRequired; const ashCost = createSequentialModifier(() => [ createMultiplicativeModifier(() => ({ - multiplier: .1, + multiplier: 0.1, description: "Star Level 2", enabled: management.elfTraining.paperElfTraining.milestones[1].earned })) @@ -340,6 +389,11 @@ const layer = createLayer(id, function (this: BaseLayer) { {renderCol(...Object.values(books))} + )), + minimizedDisplay: jsx(() => ( +
+ {name} - {format(paper.value)} {paper.displayName} +
)) }; }); diff --git a/src/data/layers/plastic.tsx b/src/data/layers/plastic.tsx index 3e3717e..917f24c 100644 --- a/src/data/layers/plastic.tsx +++ b/src/data/layers/plastic.tsx @@ -32,6 +32,8 @@ import boxes from "./boxes"; import metal from "./metal"; import oil from "./oil"; import dyes from "./dyes"; +import management from "./management"; +import workshop from "./workshop"; const id = "plastic"; const day = 10; @@ -66,7 +68,11 @@ const layer = createLayer(id, function (this: BaseLayer) { resource: metal.metal, cost() { const v = new Decimal(this.amount.value); - return Decimal.pow(1.2, v).times(1e7); + let cost = Decimal.pow(1.2, v).times(1e7); + if (management.elfTraining.fertilizerElfTraining.milestones[3].earned.value) { + cost = Decimal.sub(cost, Decimal.pow(plastic.value, 2)).max(0); + } + return cost; }, display: jsx(() => ( <> @@ -257,6 +263,12 @@ const layer = createLayer(id, function (this: BaseLayer) { multiplier: dyes.boosts.yellow1, description: "Yellow Dye Boost 1", enabled: () => Decimal.gte(dyes.dyes.yellow.amount.value, 1) + })), + createMultiplicativeModifier(() => ({ + multiplier: () => + Decimal.div(workshop.foundationProgress.value, 10).floor().div(10).add(1), + description: "800% Foundation Completed", + enabled: workshop.milestones.extraExpansionMilestone4.earned })) ]); const computedPlasticGain = computed(() => plasticGain.apply(0)); @@ -299,11 +311,16 @@ const layer = createLayer(id, function (this: BaseLayer) { <> {render(trackerDisplay)} - + } + /> {render(buildRefinery)} @@ -319,6 +336,11 @@ const layer = createLayer(id, function (this: BaseLayer) { {renderCol(clothTools, clothElf, clothGains)} + )), + minimizedDisplay: jsx(() => ( +
+ {name} - {format(plastic.value)} {plastic.displayName} +
)) }; }); diff --git a/src/data/layers/trees.tsx b/src/data/layers/trees.tsx index 0c6ef6c..478931e 100644 --- a/src/data/layers/trees.tsx +++ b/src/data/layers/trees.tsx @@ -27,7 +27,7 @@ import { noPersist, persistent } from "game/persistence"; import Decimal, { DecimalSource, format, formatGain, formatLimit, formatWhole } from "util/bignum"; import { Direction, WithRequired } from "util/common"; import { render, renderGrid, renderRow } from "util/vue"; -import { computed, ref } from "vue"; +import { computed, ref, watch } from "vue"; import boxes from "./boxes"; import cloth from "./cloth"; import coal from "./coal"; @@ -83,6 +83,11 @@ const layer = createLayer(id, function (this: BaseLayer) { addend: dyes.boosts.blue1, description: "Blue Dye Boost 1", enabled: () => Decimal.gte(dyes.dyes.blue.amount.value, 1) + })), + createAdditiveModifier(() => ({ + addend: () => Decimal.pow(computedManualCuttingAmount.value, 0.99), + description: "Hope Level 1", + enabled: management.elfTraining.expandersElfTraining.milestones[0].earned })) ]) as WithRequired; const trees = createResource( @@ -201,6 +206,7 @@ const layer = createLayer(id, function (this: BaseLayer) { if (Decimal.gte(v, 50)) v = Decimal.pow(v, 2).div(50); if (Decimal.gte(v, 200)) v = Decimal.pow(v, 2).div(200); if (Decimal.gte(v, 2e6)) v = Decimal.pow(v, 2).div(2e6); + if (Decimal.gte(v, 2e30)) v = Decimal.pow(v,10000).div(Decimal.pow(2e30,9999)); v = Decimal.pow(0.95, paper.books.cuttersBook.amount.value).times(v); return Decimal.times(100, v).add(200); }, @@ -217,8 +223,13 @@ const layer = createLayer(id, function (this: BaseLayer) { if (Decimal.gte(v, 50)) v = Decimal.pow(v, 2).div(50); if (Decimal.gte(v, 200)) v = Decimal.pow(v, 2).div(200); if (Decimal.gte(v, 2e6)) v = Decimal.pow(v, 2).div(2e6); + if (Decimal.gte(v, 2e30)) v = Decimal.pow(v,10000).div(Decimal.pow(2e30,9999)); v = Decimal.pow(0.95, paper.books.plantersBook.amount.value).times(v); - return Decimal.times(100, v).add(200); + let cost = Decimal.times(100, v).add(200); + if (management.elfTraining.planterElfTraining.milestones[3].earned.value) { + cost = Decimal.div(cost, 10); + } + return cost; }, display: { title: "Generic Planters", @@ -232,6 +243,7 @@ const layer = createLayer(id, function (this: BaseLayer) { let v = this.amount.value; if (Decimal.gte(v, 100)) v = Decimal.pow(v, 2).div(100); if (Decimal.gte(v, 1e5)) v = Decimal.pow(v, 2).div(1e5); + if (Decimal.gte(v, 1e15)) v = Decimal.pow(v, 10).div(1e135); v = Decimal.pow(0.95, paper.books.expandersBook.amount.value).times(v); return Decimal.pow(Decimal.add(v, 1), 1.5).times(500); }, @@ -282,7 +294,8 @@ const layer = createLayer(id, function (this: BaseLayer) { enabled: researchUpgrade2.bought })), createAdditiveModifier(() => ({ - addend: () => Decimal.div(workshop.foundationProgress.value, 5).floor(), + addend: () => + Decimal.div(workshop.foundationProgress.value, 5).floor(), description: "10% Foundation Completed", enabled: workshop.milestones.autoCutMilestone1.earned })), @@ -305,9 +318,28 @@ const layer = createLayer(id, function (this: BaseLayer) { multiplier: 4, description: "Lumberjack Jeans", enabled: cloth.treesUpgrades.treesUpgrade2.bought + })), + createMultiplicativeModifier(() => ({ + multiplier: () => Decimal.pow(1.1, main.day.value), + description: "Holly Level 4", + enabled: management.elfTraining.cutterElfTraining.milestones[3].earned + })), + createAdditiveModifier(() => ({ + addend: () => + Decimal.sub(lastAutoCuttingAmount.value, lastAutoPlantedAmount.value).max(0), + description: "Ivy Level 5", + enabled: management.elfTraining.planterElfTraining.milestones[4].earned })) ]) as WithRequired; const computedAutoCuttingAmount = computed(() => autoCuttingAmount.apply(0)); + const lastAutoCuttingAmount = ref(0); + setInterval( + () => + watch(computedAutoCuttingAmount, cut => { + lastAutoCuttingAmount.value = cut; + }), + 0 + ); const manualPlantingAmount = createSequentialModifier(() => [ createAdditiveModifier(() => ({ @@ -377,13 +409,32 @@ const layer = createLayer(id, function (this: BaseLayer) { description: "Ivy Level 1", enabled: management.elfTraining.planterElfTraining.milestones[0].earned })), + createMultiplicativeModifier(() => ({ + multiplier: () => Decimal.pow(trees.value, 0.2).log10().pow_base(2), + description: "Ivy Level 3", + enabled: management.elfTraining.planterElfTraining.milestones[2].earned + })), createMultiplicativeModifier(() => ({ multiplier: 2, - description: "Mary Level 2", - enabled: management.elfTraining.planterElfTraining.milestones[1].earned + description: "Mary Level 4", + enabled: management.elfTraining.heatedPlanterElfTraining.milestones[3].earned + })), + createAdditiveModifier(() => ({ + addend: () => + Decimal.sub(lastAutoPlantedAmount.value, lastAutoCuttingAmount.value).max(0), + description: "Ivy Level 5", + enabled: management.elfTraining.planterElfTraining.milestones[4].earned })) ]) as WithRequired; const computedAutoPlantingAmount = computed(() => autoPlantingAmount.apply(0)); + const lastAutoPlantedAmount = ref(0); + setInterval( + () => + watch(computedAutoPlantingAmount, planted => { + lastAutoPlantedAmount.value = planted; + }), + 0 + ); const logGain = createSequentialModifier(() => [ createMultiplicativeModifier(() => ({ @@ -397,7 +448,8 @@ const layer = createLayer(id, function (this: BaseLayer) { enabled: researchUpgrade2.bought })), createMultiplicativeModifier(() => ({ - multiplier: () => Decimal.div(workshop.foundationProgress.value, 20).add(1), + multiplier: () => workshop.milestones.extraExpansionMilestone1.earned.value + ? Decimal.pow(1.02, workshop.foundationProgress.value) : Decimal.div(workshop.foundationProgress.value, 20).add(1), description: "1% Foundation Completed", enabled: workshop.milestones.logGainMilestone1.earned })), @@ -444,9 +496,7 @@ const layer = createLayer(id, function (this: BaseLayer) { enabled: dyes.upgrades.blueDyeUpg.bought })), createMultiplicativeModifier(() => ({ - multiplier: computed(() => - Decimal.add(computedAutoCuttingAmount.value, 1).log10().plus(1) - ), + multiplier: computed(() => Decimal.add(computedAutoCuttingAmount.value, 1).root(9)), description: "Holly Level 1", enabled: management.elfTraining.cutterElfTraining.milestones[0].earned })), @@ -770,6 +820,11 @@ const layer = createLayer(id, function (this: BaseLayer) { {renderRow(...row1Buyables)} + )), + minimizedDisplay: jsx(() => ( +
+ {name} - {format(logs.value)} {logs.displayName} +
)) }; }); diff --git a/src/data/layers/workshop.tsx b/src/data/layers/workshop.tsx index b026eea..e6f5e3a 100644 --- a/src/data/layers/workshop.tsx +++ b/src/data/layers/workshop.tsx @@ -8,33 +8,24 @@ import { main } from "data/projEntry"; import { createBar } from "features/bars/bar"; import { createClickable } from "features/clickables/clickable"; import { - Conversion, + addSoftcap, createIndependentConversion, - createPolynomialScaling, - ScalingFunction + createPolynomialScaling } from "features/conversion"; import { jsx, showIf } from "features/feature"; import { createHotkey } from "features/hotkey"; import { createMilestone } from "features/milestones/milestone"; -import { createResource, displayResource, Resource } from "features/resources/resource"; +import { createResource, displayResource } from "features/resources/resource"; import { BaseLayer, createLayer } from "game/layers"; +import { createExponentialModifier, createSequentialModifier } from "game/modifiers"; import { noPersist } from "game/persistence"; -import Decimal, { DecimalSource, formatWhole } from "util/bignum"; +import Decimal, { DecimalSource, format, formatWhole } from "util/bignum"; import { Direction } from "util/common"; import { render } from "util/vue"; import { computed, unref, watchEffect } from "vue"; import elves from "./elves"; -import trees from "./trees"; import management from "./management"; - -interface FoundationConversionOptions { - scaling: ScalingFunction; - baseResource: Resource; - gainResource: Resource; - roundUpCost: boolean; - buyMax: boolean; - spend: (gain: DecimalSource, spent: DecimalSource) => void; -} +import trees from "./trees"; const id = "workshop"; const day = 2; @@ -45,22 +36,34 @@ const layer = createLayer(id, function (this: BaseLayer) { const foundationProgress = createResource(0, "foundation progress"); - const foundationConversion: Conversion = - createIndependentConversion(() => ({ - scaling: createPolynomialScaling(250, 1.5), - baseResource: trees.logs, - gainResource: noPersist(foundationProgress), - roundUpCost: true, - buyMax: false, - spend(gain, spent) { - trees.logs.value = Decimal.sub(trees.logs.value, spent); - } - })); + const foundationConversion = createIndependentConversion(() => ({ + scaling: addSoftcap( + addSoftcap(createPolynomialScaling(250, 1.5), 5387, 1 / 1e10), + 1e20, + 3e8 + ), + baseResource: trees.logs, + gainResource: noPersist(foundationProgress), + roundUpCost: true, + // buyMax: management.elfTraining.expandersElfTraining.milestones[2].earned, + spend(gain, spent) { + trees.logs.value = Decimal.sub(trees.logs.value, spent); + }, + costModifier: createSequentialModifier(() => [ + createExponentialModifier(() => ({ + exponent: 0.95, + description: "Holly Level 5", + enabled: management.elfTraining.cutterElfTraining.milestones[4].earned + })) + ]) + })); const buildFoundation = createClickable(() => ({ display: jsx(() => ( <> - Build part of the foundation + + Build {formatWhole(foundationConversion.actualGain.value)}% of the foundation +

@@ -75,10 +78,15 @@ const layer = createLayer(id, function (this: BaseLayer) { )), - visibility: () => showIf(Decimal.lt(foundationProgress.value, 100)), + visibility: () => + showIf( + Decimal.lt(foundationProgress.value, 100) || + management.elfTraining.expandersElfTraining.milestones[2].earned.value + ), canClick: () => - Decimal.gte(foundationConversion.actualGain.value, 1) && - Decimal.lt(foundationProgress.value, 100), + Decimal.gte(trees.logs.value, foundationConversion.currentAt.value) && + (Decimal.lt(foundationProgress.value, 100) || + management.elfTraining.expandersElfTraining.milestones[2].earned.value), onClick() { if (!unref(this.canClick)) { return; @@ -171,52 +179,67 @@ const layer = createLayer(id, function (this: BaseLayer) { })); const extraExpansionMilestone1 = createMilestone(() => ({ display: { - requirement: "120% Foundation Completed", + requirement: "200% Foundation Completed", effectDisplay: "The 1% milestone is now +2% and multiplicative" }, - shouldEarn: () => Decimal.gte(foundationProgress.value, 120), + shouldEarn: () => Decimal.gte(foundationProgress.value, 200), visibility: () => - showIf(management.elfTraining.expandersElfTraining.milestones[2].earned.value), + showIf( + logGainMilestone3.earned.value && + management.elfTraining.expandersElfTraining.milestones[2].earned.value + ), showPopups: shouldShowPopups })); const extraExpansionMilestone2 = createMilestone(() => ({ display: { - requirement: "140% Foundation Completed", + requirement: "400% Foundation Completed", effectDisplay: "Gain +10% metal for every 10% foundation completed" }, - shouldEarn: () => Decimal.gte(foundationProgress.value, 140), + shouldEarn: () => Decimal.gte(foundationProgress.value, 400), visibility: () => - showIf(management.elfTraining.expandersElfTraining.milestones[2].earned.value), + showIf( + extraExpansionMilestone1.earned.value && + management.elfTraining.expandersElfTraining.milestones[2].earned.value + ), showPopups: shouldShowPopups })); const extraExpansionMilestone3 = createMilestone(() => ({ display: { - requirement: "160% Foundation Completed", + requirement: "600% Foundation Completed", effectDisplay: "Gain +10% oil for every 10% foundation completed" }, - shouldEarn: () => Decimal.gte(foundationProgress.value, 160), + shouldEarn: () => Decimal.gte(foundationProgress.value, 600), visibility: () => - showIf(management.elfTraining.expandersElfTraining.milestones[2].earned.value), + showIf( + extraExpansionMilestone2.earned.value && + management.elfTraining.expandersElfTraining.milestones[2].earned.value + ), showPopups: shouldShowPopups })); const extraExpansionMilestone4 = createMilestone(() => ({ display: { - requirement: "180% Foundation Completed", + requirement: "800% Foundation Completed", effectDisplay: "Gain +10% plastic for every 10% foundation completed" }, - shouldEarn: () => Decimal.gte(foundationProgress.value, 180), + shouldEarn: () => Decimal.gte(foundationProgress.value, 800), visibility: () => - showIf(management.elfTraining.expandersElfTraining.milestones[2].earned.value), + showIf( + extraExpansionMilestone3.earned.value && + management.elfTraining.expandersElfTraining.milestones[2].earned.value + ), showPopups: shouldShowPopups })); const extraExpansionMilestone5 = createMilestone(() => ({ display: { - requirement: "200% Foundation Completed", + requirement: "1000% Foundation Completed", effectDisplay: "Double paper, boxes, and all cloth actions" }, - shouldEarn: () => Decimal.gte(foundationProgress.value, 200), + shouldEarn: () => Decimal.gte(foundationProgress.value, 1000), visibility: () => - showIf(management.elfTraining.expandersElfTraining.milestones[2].earned.value), + showIf( + extraExpansionMilestone4.earned.value && + management.elfTraining.expandersElfTraining.milestones[2].earned.value + ), showPopups: shouldShowPopups })); const milestones = { @@ -280,11 +303,19 @@ const layer = createLayer(id, function (this: BaseLayer) { % completed
- {Decimal.lt(foundationProgress.value, 100) ? : null} + {Decimal.lt(foundationProgress.value, 100) || + management.elfTraining.expandersElfTraining.milestones[2].earned.value ? ( + + ) : null} {render(buildFoundation)} {milestonesDisplay()} + )), + minimizedDisplay: jsx(() => ( +
+ {name} - {format(foundationProgress.value)} {foundationProgress.displayName} +
)) }; }); diff --git a/src/data/projEntry.tsx b/src/data/projEntry.tsx index 98f99c5..de4db37 100644 --- a/src/data/projEntry.tsx +++ b/src/data/projEntry.tsx @@ -148,7 +148,7 @@ export const main = createLayer("main", function (this: BaseLayer) { loreScene.value = -1; loreTitle.value = unref(layers[layer ?? "trees"]?.name ?? ""); loreBody.value = story; - player.devSpeed = null; + if (player.autoPause) player.devSpeed = null; showLoreModal.value = true; }, 1000); } @@ -262,23 +262,25 @@ export const main = createLayer("main", function (this: BaseLayer) { createDay(() => ({ day: 12, shouldNotify: false, - layer: null, + layer: "management", symbol: managementSymbol, story: "You watch as the elves work, and you realize that they could probably be trained to help out better. Just then, Santa comes over to check on your progress. You reply that you're doing fine, except that the elves may need a bit of behavior management. Santa offers to help, saying that he doesn't want to leave you to do everything. Unfortunately for you, the behavior problems won't fix themselves, so let's get to work!", - completedStory: "" + completedStory: + "Woo! You are exhausted - this layer felt really long to you. It's great seeing the elves so productive, although you worry a bit about your own job security now! Good Job!" })), createDay(() => ({ day: 13, shouldNotify: false, - layer: null, // "" + layer: null, // "management" (advanced) symbol: "", - story: "", - completedStory: "" + story: "So after a good night's rest you decide that maybe making these elves able to do all the work for you isn't something to be scared of, but rather encouraged. Let's spend another day continuing to train them up and really get this place spinning. They are Santa's elves after all, they're supposed to be able to run everything without you!", + completedStory: + "The elves are doing an incredible job, and Santa does not seem keen on firing you - Score! Now you can get to work on guiding this properly trained highly functional group of hard workers to make Christmas as great as possible. Good Job!" })), createDay(() => ({ day: 14, shouldNotify: false, - layer: null, // "" + layer: null, // "letters to santa" symbol: "", story: "", completedStory: "" @@ -372,7 +374,7 @@ export const main = createLayer("main", function (this: BaseLayer) { showLoreModal.value = true; day.value++; main.minimized.value = false; - player.devSpeed = 0; + if (player.autoPause) player.devSpeed = 0; } return { @@ -436,6 +438,7 @@ export const getInitialLayers = ( plastic, dyes, wrappingPaper, + management ]; /** @@ -459,7 +462,7 @@ export function fixOldSave( if (!["0.0", "0.1", "0.2", "0.3", "0.4"].includes(oldVersion ?? "")) { return; } - player.offlineProd = false; + /*player.offlineProd = false; delete player.layers?.management; if ((player.layers?.main as LayerData | undefined)?.days?.[11]) { (player.layers!.main as LayerData).days![11].opened = false; @@ -470,6 +473,6 @@ export function fixOldSave( } if (player.tabs) { player.tabs = player.tabs.filter(l => l !== "management"); - } + }*/ } /* eslint-enable @typescript-eslint/no-unused-vars */ diff --git a/src/data/symbols/letterbox.png b/src/data/symbols/letterbox.png new file mode 100644 index 0000000..d7552b5 Binary files /dev/null and b/src/data/symbols/letterbox.png differ diff --git a/src/data/symbols/workshopMansion.png b/src/data/symbols/workshopMansion.png new file mode 100644 index 0000000..6414191 Binary files /dev/null and b/src/data/symbols/workshopMansion.png differ diff --git a/src/features/challenges/challenge.tsx b/src/features/challenges/challenge.tsx index 469d34a..8128ab2 100644 --- a/src/features/challenges/challenge.tsx +++ b/src/features/challenges/challenge.tsx @@ -299,7 +299,12 @@ globalBus.on("loadSettings", settings => { registerSettingField( jsx(() => ( ( + + Hide maxed challenges + Hide challenges that have been fully completed. + + ))} onUpdate:modelValue={value => (settings.hideChallenges = value)} modelValue={settings.hideChallenges} /> diff --git a/src/features/conversion.ts b/src/features/conversion.ts index 91636c1..6c95c1e 100644 --- a/src/features/conversion.ts +++ b/src/features/conversion.ts @@ -511,6 +511,8 @@ export function addSoftcap( ): ScalingFunction { return { ...scaling, + currentAt: conversion => softcap(scaling.currentAt(conversion), unref(cap), Decimal.recip(unref(power))), + nextAt: conversion => softcap(scaling.nextAt(conversion), unref(cap), Decimal.recip(unref(power))), currentGain: conversion => softcap(scaling.currentGain(conversion), unref(cap), unref(power)) }; diff --git a/src/features/milestones/milestone.tsx b/src/features/milestones/milestone.tsx index 2671e21..d70d6ec 100644 --- a/src/features/milestones/milestone.tsx +++ b/src/features/milestones/milestone.tsx @@ -204,7 +204,12 @@ const msDisplayOptions = Object.values(MilestoneDisplay).map(option => ({ registerSettingField( jsx(() => (