This commit is contained in:
Chunkybanana 2022-12-06 05:22:53 +00:00
commit 14cf9f81bb
18 changed files with 299 additions and 7645 deletions

7406
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -7,6 +7,8 @@
"dev": "vite --host",
"build": "vue-tsc --noEmit && vite build",
"preview": "vite preview",
"typecheck": "vue-tsc --noEmit",
"lint": "eslint --ext .ts,.tsx,.vue --ignore-path .gitignore --fix src",
"test": "vitest run",
"testw": "vitest",
"serve": "vite preview --host"

View file

@ -32,7 +32,11 @@
<Scene :day="main.loreScene.value" />
<br />
You can help continue the <i>advent</i>ure at:
<a href="https://discord.gg/WzejVAx" class="info-modal-discord-link" target="_blank">
<a
href="https://discord.gg/WzejVAx"
class="info-modal-discord-link"
target="_blank"
>
<span class="material-icons info-modal-discord">discord</span>
The Paper Pilot Community
</a>

View file

@ -21,19 +21,32 @@
<div class="link" @click="openChangelog">Changelog</div>
<br />
<div>
<a :href="discordLink" v-if="discordLink" class="info-modal-discord-link">
<a
:href="discordLink"
v-if="discordLink"
class="info-modal-discord-link"
target="_blank"
>
<span class="material-icons info-modal-discord">discord</span>
{{ discordName }}
</a>
</div>
<div>
<a href="https://discord.gg/WzejVAx" class="info-modal-discord-link">
<a
href="https://discord.gg/WzejVAx"
class="info-modal-discord-link"
target="_blank"
>
<span class="material-icons info-modal-discord">discord</span>
The Paper Pilot Community
</a>
</div>
<div>
<a href="https://discord.gg/F3xveHV" class="info-modal-discord-link">
<a
href="https://discord.gg/F3xveHV"
class="info-modal-discord-link"
target="_blank"
>
<span class="material-icons info-modal-discord">discord</span>
The Modding Tree
</a>

View file

@ -12,6 +12,7 @@
<hr />
<Toggle :title="autosaveTitle" v-model="autosave" />
<Toggle v-if="projInfo.enablePausing" :title="isPausedTitle" v-model="isPaused" />
<Toggle :title="progressMethodTitle" v-model="usingLog" />
</template>
</Modal>
</template>
@ -47,8 +48,8 @@ const settingFieldsComponent = computed(() => {
return coerceComponent(jsx(() => <>{settingFields.map(render)}</>));
});
const { showTPS, theme, unthrottled } = toRefs(settings);
const { autosave, offlineProd } = toRefs(player);
const { showTPS, theme } = toRefs(settings);
const { autosave, usingLog } = toRefs(player);
const isPaused = computed({
get() {
return player.devSpeed === 0;
@ -58,11 +59,6 @@ const isPaused = computed({
}
});
const offlineProdTitle = jsx(() => (
<span>
Offline Production<Tooltip display="Save-specific">*</Tooltip>
</span>
));
const autosaveTitle = jsx(() => (
<span>
Autosave<Tooltip display="Save-specific">*</Tooltip>
@ -73,6 +69,11 @@ const isPausedTitle = jsx(() => (
Pause game<Tooltip display="Save-specific">*</Tooltip>
</span>
));
const progressMethodTitle = jsx(() => (
<span>
Use log for progress bar<Tooltip display="Save-specific">*</Tooltip>
</span>
));
</script>
<style scoped>

View file

@ -1,11 +1,12 @@
import Collapsible from "components/layout/Collapsible.vue";
import { createBar } from "features/bars/bar";
import type { Clickable, ClickableOptions, GenericClickable } from "features/clickables/clickable";
import { createClickable } from "features/clickables/clickable";
import type { GenericConversion } from "features/conversion";
import type { CoercableComponent, JSXFunction, OptionsFunc, Replace } from "features/feature";
import { jsx, setDefault } from "features/feature";
import { GenericMilestone } from "features/milestones/milestone";
import { displayResource } from "features/resources/resource";
import { displayResource, Resource, trackTotal } from "features/resources/resource";
import type { GenericTree, GenericTreeNode, TreeNode, TreeNodeOptions } from "features/trees/tree";
import { createTreeNode } from "features/trees/tree";
import type { Modifier } from "game/modifiers";
@ -14,7 +15,8 @@ import { DefaultValue, persistent } from "game/persistence";
import player from "game/player";
import type { DecimalSource } from "util/bignum";
import Decimal, { format } from "util/bignum";
import type { WithRequired } from "util/common";
import { formatWhole } from "util/break_eternity";
import { Direction, WithRequired } from "util/common";
import type {
Computable,
GetComputableType,
@ -22,10 +24,11 @@ import type {
ProcessedComputable
} from "util/computed";
import { convertComputable, processComputable } from "util/computed";
import { getFirstFeature, renderColJSX, renderJSX } from "util/vue";
import type { Ref } from "vue";
import { getFirstFeature, render, renderColJSX, renderJSX, VueFeature } from "util/vue";
import { Ref, watchEffect } from "vue";
import { computed, unref } from "vue";
import "./common.css";
import { main } from "./projEntry";
/** An object that configures a {@link ResetButton} */
export interface ResetButtonOptions extends ClickableOptions {
@ -389,3 +392,87 @@ export function createCollapsibleMilestones(milestones: Record<string, GenericMi
display
};
}
export function setUpDailyProgressTracker(options: {
resource: Resource;
goal: DecimalSource;
name: string;
day: number;
color: string;
textColor?: string;
modal?: {
show: Ref<boolean>;
display: VueFeature | CoercableComponent;
};
usingLog?: Ref<boolean>;
}) {
const total = trackTotal(options.resource);
const progressFunc = () => {
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) {
progress = progress.log10();
requirement = Decimal.log10(requirement);
}
return Decimal.div(progress, requirement);
};
const dayProgress = createBar(() => ({
direction: Direction.Right,
width: 600,
height: 25,
fillStyle: { backgroundColor: options.color },
textStyle: options.textColor ? { color: options.textColor } : undefined,
progress: progressFunc,
display: jsx(() =>
main.day.value === options.day ? (
<>
{formatWhole(total.value)}/{formatWhole(options.goal)}
</>
) : (
""
)
)
}));
const trackerDisplay = jsx(() => (
<>
<div>
{main.day.value === options.day ? (
<>
Reach {formatWhole(options.goal)} total {options.resource.displayName} to
complete the day
</>
) : (
<>{options.name} Complete!</>
)}
{options.modal ? (
<>
{" "}
-{" "}
<button
class="button"
style="display: inline-block;"
onClick={() => (options.modal!.show.value = true)}
>
Check Modifiers
</button>
</>
) : undefined}
</div>
{render(dayProgress)}
{options.modal ? render(options.modal.display) : undefined}
</>
));
watchEffect(() => {
if (main.day.value === options.day && Decimal.gte(total.value, options.goal)) {
main.completeDay();
}
});
return {
total,
trackerDisplay
};
}

View file

@ -3,20 +3,19 @@
* @hidden
*/
import Spacer from "components/layout/Spacer.vue";
import { setUpDailyProgressTracker } from "data/common";
import { main } from "data/projEntry";
import { createBar } from "features/bars/bar";
import { createBuyable, GenericBuyable } from "features/buyable";
import { createClickable } from "features/clickables/clickable";
import { createCumulativeConversion, createPolynomialScaling } from "features/conversion";
import { jsx, showIf } from "features/feature";
import MainDisplay from "features/resources/MainDisplay.vue";
import { createResource, displayResource, trackTotal } from "features/resources/resource";
import { createResource, displayResource } from "features/resources/resource";
import { createUpgrade } from "features/upgrades/upgrade";
import { BaseLayer, createLayer } from "game/layers";
import Decimal, { DecimalSource, format, formatWhole } from "util/bignum";
import { Direction } from "util/common";
import { render, renderRow } from "util/vue";
import { unref, watchEffect } from "vue";
import { unref } from "vue";
import trees from "./trees";
const id = "boxes";
@ -24,12 +23,8 @@ const day = 6;
const layer = createLayer(id, function (this: BaseLayer) {
const name = "Boxes";
const color = "#964B00";
const colorDark = "#964B00";
const totalBoxesGoal = 5e4;
const boxes = createResource<DecimalSource>(0, "boxes");
const totalBoxes = trackTotal(boxes);
const boxesConversion = createCumulativeConversion(() => ({
scaling: createPolynomialScaling(1e10, 1),
@ -148,34 +143,12 @@ const layer = createLayer(id, function (this: BaseLayer) {
})) as GenericBuyable;
const buyables = { logBoxesBuyable, ashBoxesBuyable, coalBoxesBuyable };
const dayProgress = createBar(() => ({
direction: Direction.Right,
width: 600,
height: 25,
fillStyle: `backgroundColor: ${colorDark}`,
textStyle: "color: var(--feature-foreground)",
progress: () =>
main.day.value === day
? Decimal.div(
Decimal.log10(Decimal.add(totalBoxes.value, 1)),
Decimal.log10(totalBoxesGoal)
)
: 1,
display: jsx(() =>
main.day.value === day ? (
<>
{formatWhole(totalBoxes.value)}/{formatWhole(totalBoxesGoal)}
</>
) : (
""
)
)
}));
watchEffect(() => {
if (main.day.value === day && Decimal.gte(totalBoxes.value, totalBoxesGoal)) {
main.completeDay();
}
const { total: totalBoxes, trackerDisplay } = setUpDailyProgressTracker({
resource: boxes,
goal: 5e4,
name,
day,
color
});
return {
@ -190,14 +163,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
minWidth: 700,
display: jsx(() => (
<>
<div>
{main.day.value === day
? `Reach ${formatWhole(totalBoxesGoal)} total ${
boxes.displayName
} to complete the day`
: `${name} Complete!`}
</div>
{render(dayProgress)}
{render(trackerDisplay)}
<Spacer />
<MainDisplay resource={boxes} color={color} style="margin-bottom: 0" />
<Spacer />

View file

@ -7,20 +7,18 @@ import Modal from "components/Modal.vue";
import MainDisplay from "features/resources/MainDisplay.vue";
import Row from "components/layout/Row.vue";
import Column from "components/layout/Column.vue";
import { createCollapsibleModifierSections } from "data/common";
import { createCollapsibleModifierSections, setUpDailyProgressTracker } from "data/common";
import { main } from "data/projEntry";
import { createBar } from "features/bars/bar";
import { createBuyable, GenericBuyable } from "features/buyable";
import { createClickable } from "features/clickables/clickable";
import { jsx, JSXFunction, showIf, StyleValue, Visibility } from "features/feature";
import { createResource, Resource, trackTotal } from "features/resources/resource";
import { createResource, Resource } from "features/resources/resource";
import { globalBus } from "game/events";
import { BaseLayer, createLayer } from "game/layers";
import { persistent } from "game/persistence";
import Decimal, { DecimalSource, format, formatWhole } from "util/bignum";
import { Direction } from "util/common";
import { render, renderRow } from "util/vue";
import { computed, ref, unref, watchEffect } from "vue";
import { computed, ref, unref } from "vue";
import trees from "./trees";
import {
createAdditiveModifier,
@ -60,31 +58,8 @@ const layer = createLayer(id, function (this: BaseLayer) {
const colorText = "var(--foreground)";
const coal = createResource<DecimalSource>(0, "coal");
const totalCoal = trackTotal(coal);
const ash = createResource<DecimalSource>(0, "ash");
const totalCoalGoal = 1e7;
const dayProgress = createBar(() => ({
direction: Direction.Right,
width: 600,
height: 25,
fillStyle: `backgroundColor: ${colorCoal}`,
progress: () =>
main.day.value === day
? Decimal.log10(Decimal.add(totalCoal.value, 1)).div(Math.log10(totalCoalGoal))
: 1,
display: jsx(() =>
main.day.value === day ? (
<>
{formatWhole(totalCoal.value)}/{formatWhole(totalCoalGoal)}
</>
) : (
""
)
)
}));
const activeFires = persistent<DecimalSource>(0);
const fireLogs = computed(() => Decimal.times(activeFires.value, 1000));
const fireCoal = computed(() => Decimal.times(activeFires.value, 0.1));
@ -92,7 +67,9 @@ const layer = createLayer(id, function (this: BaseLayer) {
const buildFire = createBuyable(() => ({
resource: trees.logs,
cost() {
let v = Decimal.times(buildBonfire.amount.value, unref(buildBonfire.cost!)).plus(this.amount.value);
let v = Decimal.times(buildBonfire.amount.value, unref(buildBonfire.cost!)).plus(
this.amount.value
);
if (Decimal.gte(v, 100)) v = Decimal.pow(v, 2).div(100);
if (Decimal.gte(v, 10000)) v = Decimal.pow(v, 2).div(10000);
v = Decimal.pow(0.95, paper.books.smallFireBook.amount.value).times(v);
@ -586,9 +563,8 @@ const layer = createLayer(id, function (this: BaseLayer) {
createExponentialModifier(() => ({
exponent: 1.25,
description: "3 Elves Trained",
enabled () {
return elves.milestones[2].earned.value && Decimal.gte(coal.value, 1)
}
enabled: elves.milestones[2].earned,
supportLowNumbers: true
}))
]);
const computedCoalGain = computed(() => coalGain.apply(0));
@ -743,9 +719,15 @@ const layer = createLayer(id, function (this: BaseLayer) {
ash.value = Decimal.times(diff, computedAshGain.value).plus(ash.value);
});
watchEffect(() => {
if (main.day.value === day && Decimal.gte(totalCoal.value, totalCoalGoal)) {
main.completeDay();
const { total: totalCoal, trackerDisplay } = setUpDailyProgressTracker({
resource: coal,
goal: 1e7,
name,
day,
color: colorCoal,
modal: {
show: showModifiersModal,
display: modifiersModal
}
});
@ -779,23 +761,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
minWidth: 700,
display: jsx(() => (
<>
<div>
{main.day.value === day
? `Reach ${formatWhole(totalCoalGoal)} ${
coal.displayName
} to complete the day`
: `${name} Complete!`}{" "}
-{" "}
<button
class="button"
style="display: inline-block;"
onClick={() => (showModifiersModal.value = true)}
>
Check Modifiers
</button>
</div>
{render(dayProgress)}
{render(modifiersModal)}
{render(trackerDisplay)}
<Spacer />
<MainDisplay
resource={coal}
@ -823,7 +789,8 @@ const layer = createLayer(id, function (this: BaseLayer) {
<Column>
{render(buildFire)}
<div>
{formatWhole(activeFires.value)}/{formatWhole(buildFire.amount.value)}
{formatWhole(Decimal.floor(activeFires.value))}/
{formatWhole(Decimal.floor(buildFire.amount.value))}
</div>
{renderRow(minFire, removeFire, addFire, maxFire)}
</Column>

View file

@ -22,7 +22,7 @@ import { persistent } from "game/persistence";
import Decimal, { DecimalSource, formatWhole } from "util/bignum";
import { Direction } from "util/common";
import { Computable, convertComputable } from "util/computed";
import { render, renderCol, renderRow } from "util/vue";
import { render, renderRow } from "util/vue";
import { computed, ref, Ref, unref, watchEffect } from "vue";
import boxes from "./boxes";
import coal from "./coal";
@ -439,15 +439,19 @@ const layer = createLayer(id, function (this: BaseLayer) {
buyable: coal.buildBonfire,
cooldownModifier: bonfireCooldown,
visibility: () => showIf(boxes.upgrades.ashUpgrade.bought.value),
customCost: amount =>
Decimal.times(amount, 10)
.plus(10)
.times(Decimal.pow(0.95, paper.books.bonfireBook.amount.value)),
hasToggle: true,
toggleDesc: "Activate auto-purchased bonfires",
onAutoPurchase() {
if (bonfireElf.toggle.value) {
coal.activeBonfires.value = Decimal.add(coal.activeBonfires.value, 1);
coal.buildFire.amount.value = Decimal.sub(
coal.buildFire.amount.value,
unref(this.buyable.cost!)
);
coal.activeFires.value = Decimal.sub(
coal.activeFires.value,
unref(this.buyable.cost!)
);
}
},
onPurchase() {

View file

@ -3,19 +3,17 @@
* @hidden
*/
import Spacer from "components/layout/Spacer.vue";
import { main } from "data/projEntry";
import { createBar } from "features/bars/bar";
import { setUpDailyProgressTracker } from "data/common";
import { BuyableOptions, createBuyable, GenericBuyable } from "features/buyable";
import { createClickable } from "features/clickables/clickable";
import { createCumulativeConversion, createPolynomialScaling } from "features/conversion";
import { jsx, showIf } from "features/feature";
import MainDisplay from "features/resources/MainDisplay.vue";
import { createResource, displayResource, trackTotal } from "features/resources/resource";
import { createResource, displayResource } from "features/resources/resource";
import { BaseLayer, createLayer } from "game/layers";
import Decimal, { DecimalSource, format, formatWhole } from "util/bignum";
import { Direction } from "util/common";
import { render, renderCol } from "util/vue";
import { computed, unref, watchEffect } from "vue";
import { computed, unref } from "vue";
import coal from "./coal";
import elves from "./elves";
import trees from "./trees";
@ -25,12 +23,8 @@ const day = 5;
const layer = createLayer(id, function (this: BaseLayer) {
const name = "Paper";
const color = "#E8DCB8";
const colorDark = "#E8DCB8";
const totalPaperGoal = 5e3;
const paper = createResource<DecimalSource>(0, "paper");
const totalPaper = trackTotal(paper);
const pulp = createResource<DecimalSource>(
computed(() =>
@ -162,34 +156,13 @@ const layer = createLayer(id, function (this: BaseLayer) {
kilnBook
};
const dayProgress = createBar(() => ({
direction: Direction.Right,
width: 600,
height: 25,
fillStyle: `backgroundColor: ${colorDark}`,
textStyle: "color: var(--feature-foreground)",
progress: () =>
main.day.value === day
? Decimal.div(
Decimal.log10(Decimal.add(totalPaper.value, 1)),
Decimal.log10(totalPaperGoal)
)
: 1,
display: jsx(() =>
main.day.value === day ? (
<>
{formatWhole(totalPaper.value)}/{formatWhole(totalPaperGoal)}
</>
) : (
""
)
)
}));
watchEffect(() => {
if (main.day.value === day && Decimal.gte(totalPaper.value, totalPaperGoal)) {
main.completeDay();
}
const { total: totalPaper, trackerDisplay } = setUpDailyProgressTracker({
resource: paper,
goal: 5e3,
name,
day,
color,
textColor: "var(--feature-foreground)"
});
return {
@ -203,14 +176,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
minWidth: 700,
display: jsx(() => (
<>
<div>
{main.day.value === day
? `Reach ${formatWhole(totalPaperGoal)} total ${
paper.displayName
} to complete the day`
: `${name} Complete!`}
</div>
{render(dayProgress)}
{render(trackerDisplay)}
<Spacer />
<MainDisplay resource={paper} color={color} style="margin-bottom: 0" />
<Spacer />

View file

@ -4,7 +4,7 @@
*/
import Spacer from "components/layout/Spacer.vue";
import Modal from "components/Modal.vue";
import { createCollapsibleModifierSections } from "data/common";
import { createCollapsibleModifierSections, setUpDailyProgressTracker } from "data/common";
import { main } from "data/projEntry";
import { createBar } from "features/bars/bar";
import { createBuyable, GenericBuyable } from "features/buyable";
@ -12,7 +12,7 @@ import { createClickable } from "features/clickables/clickable";
import { jsx, showIf } from "features/feature";
import { createHotkey } from "features/hotkey";
import MainDisplay from "features/resources/MainDisplay.vue";
import { createResource, Resource, trackTotal } from "features/resources/resource";
import { createResource, Resource } from "features/resources/resource";
import { createUpgrade } from "features/upgrades/upgrade";
import { globalBus } from "game/events";
import { BaseLayer, createLayer } from "game/layers";
@ -24,33 +24,30 @@ import {
Modifier
} from "game/modifiers";
import { persistent } from "game/persistence";
import Decimal, { DecimalSource, format, formatWhole } from "util/bignum";
import Decimal, { DecimalSource, format, formatWhole, formatLimit } from "util/bignum";
import { Direction, WithRequired } from "util/common";
import { render, renderRow } from "util/vue";
import { computed, ref, watchEffect } from "vue";
import { computed, ref } from "vue";
import boxes from "./boxes";
import coal from "./coal";
import elves from "./elves";
import paper from "./paper";
import workshop from "./workshop";
const id = "trees";
const day = 1;
// how much to prioritize this' income
// vs the previous ones
const SMOOTHING_FACTOR = 0.5;
const SMOOTHING_FACTOR = 0.1;
const layer = createLayer(id, function (this: BaseLayer) {
const name = "Trees";
const colorBright = "#4BDC13";
const colorDark = "green";
const logs = createResource<DecimalSource>(0, "logs");
const totalLogs = trackTotal(logs);
// Think of saplings as spent trees
const saplings = createResource<DecimalSource>(0, "saplings");
const totalLogGoal = 1e4;
const ema = ref<DecimalSource>(0);
const totalTrees = createSequentialModifier(() => [
@ -79,6 +76,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
computed(() => Decimal.sub(totalTrees.apply(10), saplings.value)),
"trees"
);
const computedTotalTrees = computed(() => totalTrees.apply(10));
const manualCutUpgrade1 = createUpgrade(() => ({
resource: logs,
@ -232,26 +230,6 @@ const layer = createLayer(id, function (this: BaseLayer) {
})) as GenericBuyable & { display: { title: string }; resource: Resource };
const row1Buyables = [autoCuttingBuyable1, autoPlantingBuyable1, expandingForestBuyable];
const dayProgress = createBar(() => ({
direction: Direction.Right,
width: 600,
height: 25,
fillStyle: `backgroundColor: ${colorDark}`,
progress: () =>
main.day.value === day
? Decimal.log10(Decimal.add(totalLogs.value, 1)).div(Math.log10(totalLogGoal))
: 1,
display: jsx(() =>
main.day.value === day ? (
<>
{formatWhole(totalLogs.value)}/{formatWhole(totalLogGoal)}
</>
) : (
""
)
)
}));
const manualCuttingAmount = createSequentialModifier(() => [
createAdditiveModifier(() => ({
addend: 1,
@ -421,7 +399,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
enabled: boxes.upgrades.logsUpgrade.bought
})),
createExponentialModifier(() => ({
exponent: 1.1,
exponent: 1.2,
description: "100% Foundation Completed",
enabled: workshop.milestones.logGainMilestone3.earned
}))
@ -623,7 +601,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
trees.value,
Decimal.times(computedAutoCuttingAmount.value, diff)
);
const logsGained = logGain.apply(amountCut);
const logsGained = Decimal.mul(logGain.apply(1), amountCut);
const effectiveLogsGained = Decimal.div(logsGained, diff);
ema.value = Decimal.mul(effectiveLogsGained, SMOOTHING_FACTOR).add(
@ -640,12 +618,6 @@ const layer = createLayer(id, function (this: BaseLayer) {
saplings.value = Decimal.sub(saplings.value, amountPlanted);
});
watchEffect(() => {
if (main.day.value === day && Decimal.gte(totalLogs.value, totalLogGoal)) {
main.completeDay();
}
});
const netSaplingGain = computed(() =>
Decimal.sub(computedAutoCuttingAmount.value, computedAutoPlantingAmount.value)
);
@ -668,6 +640,18 @@ const layer = createLayer(id, function (this: BaseLayer) {
}
}));
const { total: totalLogs, trackerDisplay } = setUpDailyProgressTracker({
resource: logs,
goal: 1e4,
name,
day,
color: colorDark,
modal: {
show: showModifiersModal,
display: modifiersModal
}
});
return {
name,
color: colorBright,
@ -688,36 +672,40 @@ const layer = createLayer(id, function (this: BaseLayer) {
minWidth: 700,
display: jsx(() => (
<>
<div>
{main.day.value === day
? `Reach ${formatWhole(1e4)} ${logs.displayName} to complete the day`
: `${name} Complete!`}{" "}
-{" "}
<button
class="button"
style="display: inline-block;"
onClick={() => (showModifiersModal.value = true)}
>
Check Modifiers
</button>
</div>
{render(dayProgress)}
{render(modifiersModal)}
{render(trackerDisplay)}
<Spacer />
<MainDisplay
resource={logs}
color={colorBright}
style="margin-bottom: 0"
effectDisplay={
productionDisplay={
Decimal.gt(computedAutoCuttingAmount.value, 0)
? `expected: +${format(
logGain.apply(computedAutoCuttingAmount.value)
)}/s, average: +${format(ema.value)}/s (${format(
Decimal.div(
ema.value,
logGain.apply(computedAutoCuttingAmount.value)
).mul(100)
)}% efficent)`
? `+${format(ema.value)}/s average<br/>equilibrium: +${formatLimit(
[
[
Decimal.mul(
logGain.apply(1),
computedAutoCuttingAmount.value
),
"cutting speed"
],
[
Decimal.mul(
logGain.apply(1),
computedAutoPlantingAmount.value
),
"planting speed"
],
[
Decimal.mul(
logGain.apply(1),
Decimal.mul(computedTotalTrees.value, 20)
),
"forest cap"
]
],
"/s"
)}`
: undefined
}
/>
@ -725,7 +713,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
resource={saplings}
color={colorDark}
style="margin-bottom: 0"
effectDisplay={
productionDisplay={
{
[-1]: `${formatWhole(netSaplingGain.value)}/s`,
0: undefined,
@ -737,7 +725,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
resource={trees}
color={colorDark}
style="margin-bottom: 0"
effectDisplay={
productionDisplay={
{
[-1]: `${formatWhole(netTreeGain.value)}/s`,
0: undefined,
@ -748,10 +736,6 @@ const layer = createLayer(id, function (this: BaseLayer) {
<Spacer />
{renderRow(cutTree, plantTree)}
<div>Tip: You can hold down on actions to perform them automatically</div>
<div>
Note: your average log gain will be equal to your expected log gain if you have
enough trees to support your chopping
</div>
<Spacer />
{renderRow(...row1Upgrades)}
{renderRow(...row2Upgrades)}

View file

@ -161,7 +161,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
const logGainMilestone3 = createMilestone(() => ({
display: {
requirement: "100% Foundation Completed",
effectDisplay: "Trees' log gain is now raised to the 1.1th power"
effectDisplay: "Log per tree is raised to the 1.2th power"
},
shouldEarn: () => Decimal.gte(foundationProgress.value, 100),
visibility: () => showIf(morePlantsMilestone1.earned.value),
@ -216,10 +216,15 @@ const layer = createLayer(id, function (this: BaseLayer) {
</div>
{render(dayProgress)}
<Spacer />
<div>
<span>The foundation is </span>
<h2 style={`color: ${color}; text-shadow: 0 0 10px ${color}`}>
{formatWhole(foundationProgress.value)}
</h2>
% completed
</div>
{Decimal.lt(foundationProgress.value, 100) ? <Spacer /> : null}
{render(buildFoundation)}
{Decimal.lt(foundationProgress.value, 100) ? (
<div>You have {formatWhole(foundationProgress.value)}% completed</div>
) : null}
<Spacer />
{milestonesDisplay()}
</>

View file

@ -11,7 +11,7 @@ import { persistent } from "game/persistence";
import type { PlayerData } from "game/player";
import player from "game/player";
import { format, formatTime } from "util/bignum";
import { Computable, convertComputable, processComputable, ProcessedComputable } from "util/computed";
import { Computable, convertComputable, ProcessedComputable } from "util/computed";
import { createLazyProxy } from "util/proxies";
import { renderRow, VueFeature } from "util/vue";
import type { Ref } from "vue";
@ -66,8 +66,10 @@ export const main = createLayer("main", function (this: BaseLayer) {
return createLazyProxy(() => {
const day = optionsFunc();
// There's got to be a better way to do this
const shouldNotify = convertComputable(() => unref(convertComputable(day.shouldNotify)) || unref(recentlyUpdated))
const optionsShouldNotify = convertComputable(day.shouldNotify);
const shouldNotify = convertComputable(
() => unref(optionsShouldNotify) || unref(recentlyUpdated)
);
return {
...day,
@ -76,8 +78,16 @@ export const main = createLayer("main", function (this: BaseLayer) {
recentlyUpdated,
[Component]: Day as GenericComponent,
[GatherProps]: function (this: Day) {
const { day, layer, symbol, opened, shouldNotify, story, completedStory, recentlyUpdated } =
this;
const {
day,
layer,
symbol,
opened,
shouldNotify,
story,
completedStory,
recentlyUpdated
} = this;
return {
day,
@ -162,16 +172,16 @@ export const main = createLayer("main", function (this: BaseLayer) {
shouldNotify: false,
layer: "elves",
symbol: elfSymbol,
story: "Alright, it seems you finally have enough things setup to start bringing in the elves! Unfortunately, it seems they'll need to be retrained on how to help, since they're out of practice by 11 months!",
story: "Alright, it seems you finally have enough things set up to start bringing in the elves! Unfortunately, it seems they'll need to be retrained on how to help, since they've stopped practicing for 11 months!",
completedStory:
"The workshop now hums with the bustling elves working everything. They can take it from here - you deserve a break after such a long day! Good Job!"
"The workshop now hums with the bustling elves working on everything. They can take it from here - you deserve a break after such a long day! Good Job!"
})),
createDay(() => ({
day: 5,
shouldNotify: false,
layer: "paper",
symbol: paperSymbol,
story: "With the elves trained, we're almost ready to start working on these presents! Just a couple more pre-reqs first, starting with turning all this wood into wood pulp and finally into paper, which will be required for wrapping paper later on but in the meantime can be used to help write guides to help these elves continue their education!",
story: "With the elves trained, we're almost ready to start working on these presents! Just a couple more pre-reqs first, starting with turning all this wood into wood pulp and finally into paper, which will be required for wrapping paper later on but in the meantime can be used to help write guides which will help these elves continue their education!",
completedStory:
"You look upon your rivers of book pulp as you hand out stacks of papers to elves to read through. You've continued getting closer and closer to preparing for Christmas, and can go to bed satisfied with your progress. Good Job!"
})),
@ -182,7 +192,7 @@ export const main = createLayer("main", function (this: BaseLayer) {
symbol: boxesSymbol,
story: "You watch all these elves carrying incredibly large loads just in their open elf-sized hands, and realize there's probably a better way. You need to put the toys in boxes anyways, so why don't we get started working on those so the workers can take advantage as well?",
completedStory:
"Wow, those boxes are really convenient! The workshop feels more and more proper with every day. You tick another requirement of your list and start looking towards tomorrow. Good Job!"
"Wow, those boxes are really convenient! The workshop feels more and more proper with every day. You tick another requirement on your list and start looking towards tomorrow. Good Job!"
})),
createDay(() => ({
day: 7,

View file

@ -14,7 +14,7 @@ import { globalBus } from "game/events";
import "lib/pixi";
import { processedPropType } from "util/vue";
import type { PropType } from "vue";
import { defineComponent, nextTick, onBeforeUnmount, onMounted, ref, shallowRef, unref } from "vue";
import { defineComponent, nextTick, onBeforeUnmount, onMounted, shallowRef, unref } from "vue";
// TODO get typing support on the Particles component
export default defineComponent({

View file

@ -13,6 +13,10 @@
<span v-if="effectComponent"
>, <component :is="effectComponent" ref="effectRef"
/></span>
<span v-if="productionComponent">
<br />
<component :is="productionComponent" ref="effectRef"
/></span>
</div>
</div>
</Sticky>
@ -34,6 +38,7 @@ const _props = defineProps<{
classes?: Record<string, boolean>;
style?: StyleValue;
effectDisplay?: CoercableComponent;
productionDisplay?: CoercableComponent;
}>();
const props = toRefs(_props);
@ -43,6 +48,10 @@ const effectComponent = computeOptionalComponent(
props.effectDisplay as Ref<CoercableComponent | undefined>
);
const productionComponent = computeOptionalComponent(
props.productionDisplay as Ref<CoercableComponent | undefined>
);
const showPrefix = computed(() => {
return Decimal.lt(props.resource.value, "1e1000");
});

View file

@ -34,6 +34,8 @@ export interface PlayerData {
modVersion: string;
/** A dictionary of layer save data. */
layers: Record<string, LayerData<unknown>>;
/** Whether to use log for progress toward finishing the day, or use linear. */
usingLog: boolean;
}
/** The proxied player that is used to track NaN values. */
@ -65,7 +67,8 @@ const state = reactive<PlayerData>({
keepGoing: false,
modID: "",
modVersion: "",
layers: {}
layers: {},
usingLog: false
});
/** Convert a player save data object into a JSON string. Unwraps refs. */

View file

@ -12,6 +12,7 @@ export const {
formatTime,
toPlaces,
formatSmall,
formatLimit,
invertOOM
} = numberUtils;
@ -29,6 +30,7 @@ declare global {
formatTime: (s: number) => string;
toPlaces: (x: DecimalSource, precision: number, maxAccepted: DecimalSource) => string;
formatSmall: (x: DecimalSource, precision?: number) => string;
formatLimit: (list: [DecimalSource, string][], unit: string) => string;
invertOOM: (x: DecimalSource) => Decimal;
}
}
@ -41,6 +43,7 @@ window.formatWhole = formatWhole;
window.formatTime = formatTime;
window.toPlaces = toPlaces;
window.formatSmall = formatSmall;
window.formatLimit = formatLimit;
window.invertOOM = invertOOM;
export default Decimal;

View file

@ -194,3 +194,15 @@ export function invertOOM(x: DecimalSource): Decimal {
return x;
}
export function formatLimit(list: [DecimalSource, string][], unit: string): string {
let num = list[0][0];
let str = list[0][1];
for (let i = 1; i < list.length; i++) {
if (Decimal.lt(list[i][0], num)) {
num = list[i][0];
str = list[i][1];
}
}
return format(num) + unit + ", limited by " + str;
}