Merge branch 'day-20-factory' of https://github.com/thepaperpilot/Advent-Incremental into day-20-factory

This commit is contained in:
circle-gon 2022-12-21 12:57:04 +00:00
commit 4d4c15cdf0
60 changed files with 8121 additions and 494 deletions

View file

@ -11,7 +11,8 @@ module.exports = {
"@vue/eslint-config-prettier"
],
parserOptions: {
ecmaVersion: 2020
ecmaVersion: 2020,
project: "tsconfig.json"
},
ignorePatterns: ["src/lib"],
rules: {
@ -19,7 +20,14 @@ module.exports = {
"no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off",
"vue/script-setup-uses-vars": "warn",
"vue/no-mutating-props": "off",
"vue/multi-word-component-names": "off"
"vue/multi-word-component-names": "off",
"@typescript-eslint/strict-boolean-expressions": [
"error",
{
allowNullableObject: true,
allowNullableBoolean: true
}
]
},
globals: {
defineProps: "readonly",

7587
package-lock.json generated

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -32,7 +32,7 @@ const theme = computed(() => themes[settings.theme].variables as CSSProperties);
const showTPS = toRef(settings, "showTPS");
const gameComponent = computed(() => {
return coerceComponent(jsx(() => <>{gameComponents.map(render)}</>));
return coerceComponent(jsx(() => (<>{gameComponents.map(render)}</>)));
});
</script>

View file

@ -80,7 +80,7 @@ const isOpen = ref(false);
const timePlayed = computed(() => formatTime(player.timePlayed));
const infoComponent = computed(() => {
return coerceComponent(jsx(() => <>{infoComponents.map(render)}</>));
return coerceComponent(jsx(() => (<>{infoComponents.map(render)}</>)));
});
defineExpose({

View file

@ -12,9 +12,7 @@
</Context>
</div>
<button v-if="unref(minimizable)" class="minimize" @click="setMinimized(true)">
</button>
<button v-if="unref(minimizable)" class="minimize" @click="setMinimized(true)"></button>
</div>
</template>
@ -114,7 +112,6 @@ export default defineComponent({
}
}
return {
component,
minimizedComponent,
@ -124,7 +121,7 @@ export default defineComponent({
goBack,
setMinimized,
minimized,
minWidth,
minWidth
};
}
});
@ -207,7 +204,7 @@ export default defineComponent({
pointer-events: none;
}
</style>
<style>
<style>
.layer-tab.minimized > * > .desc {
color: var(--accent1);
font-size: 30px;

View file

@ -40,7 +40,7 @@
<script setup lang="ts">
import type { FeatureNode } from "game/layers";
import { computed, ref, toRefs } from "vue";
import { computed, ref, toRefs, unref } from "vue";
import Context from "./Context.vue";
const _props = defineProps<{
@ -51,7 +51,7 @@ const emit = defineEmits<{
(e: "update:modelValue", value: boolean): void;
}>();
const isOpen = computed(() => props.modelValue || isAnimating.value);
const isOpen = computed(() => unref(props.modelValue) || isAnimating.value);
function close() {
emit("update:modelValue", false);
}

View file

@ -62,7 +62,7 @@ const savesManager = ref<ComponentPublicInstance<typeof SavesManager> | null>(nu
const path = computed(() => state.NaNPath?.join("."));
const property = computed(() => state.NaNPath?.slice(-1)[0]);
const previous = computed<DecimalSource | null>(() => {
if (state.NaNReceiver && property.value) {
if (state.NaNReceiver && property.value != null) {
return state.NaNReceiver[property.value] as DecimalSource;
}
return null;
@ -77,21 +77,21 @@ const isPaused = computed({
});
function setZero() {
if (state.NaNReceiver && property.value) {
if (state.NaNReceiver && property.value != null) {
state.NaNReceiver[property.value] = new Decimal(0);
state.hasNaN = false;
}
}
function setOne() {
if (state.NaNReceiver && property.value) {
if (state.NaNReceiver && property.value != null) {
state.NaNReceiver[property.value] = new Decimal(1);
state.hasNaN = false;
}
}
function ignore() {
if (state.NaNReceiver && property.value) {
if (state.NaNReceiver && property.value != null) {
state.NaNReceiver[property.value] = new Decimal(NaN);
state.hasNaN = false;
}

View file

@ -81,7 +81,7 @@ const themes = Object.keys(rawThemes).map(theme => ({
}));
const settingFieldsComponent = computed(() => {
return coerceComponent(jsx(() => <>{settingFields.map(render)}</>));
return coerceComponent(jsx(() => (<>{settingFields.map(render)}</>)));
});
const { showTPS, theme, usingLog, alignUnits } = toRefs(settings);

View file

@ -107,11 +107,11 @@ const isEditing = ref(false);
const isConfirming = ref(false);
const newName = ref("");
watch(isEditing, () => (newName.value = save.value.name || ""));
watch(isEditing, () => (newName.value = save.value.name ?? ""));
const isActive = computed(() => save.value && save.value.id === player.id);
const isActive = computed(() => save.value != null && save.value.id === player.id);
const currentTime = computed(() =>
isActive.value ? player.time : (save.value && save.value.time) || 0
isActive.value ? player.time : (save.value != null && save.value.time) ?? 0
);
const progressDisplay = computeComponent(

View file

@ -281,7 +281,7 @@ function newFromPreset(preset: string) {
function editSave(id: string, newName: string) {
const currSave = saves.value[id];
if (currSave) {
if (currSave != null) {
currSave.name = newName;
if (player.id === id) {
player.name = newName;

View file

@ -26,7 +26,7 @@ const emit = defineEmits<{
const value = computed({
get() {
return String(unref(props.modelValue) || 0);
return String(unref(props.modelValue) ?? 0);
},
set(value: string) {
emit("update:modelValue", Number(value));

View file

@ -55,7 +55,7 @@ onMounted(() => {
const value = computed({
get() {
return unref(props.modelValue) || "";
return unref(props.modelValue) ?? "";
},
set(value: string) {
emit("update:modelValue", value);

View file

@ -19,7 +19,7 @@ const emit = defineEmits<{
(e: "update:modelValue", value: boolean): void;
}>();
const component = computed(() => coerceComponent(unref(props.title) || "<span></span>", "span"));
const component = computed(() => coerceComponent(unref(props.title) ?? "<span></span>", "span"));
const value = computed({
get() {

View file

@ -19,4 +19,4 @@
.fraction > :last-child {
border-top: 1px solid;
}
</style>
</style>

View file

@ -1,6 +1,8 @@
<template>
<span style="white-space: nowrap">
<span style="font-size: larger; font-family: initial">&radic;</span
><div style="display: inline-block; border-top: 1px solid; padding-left: .2em"><slot /></div>
<span style="font-size: larger; font-family: initial">&radic;</span>
<div style="display: inline-block; border-top: 1px solid; padding-left: 0.2em">
<slot />
</div>
</span>
</template>

View file

@ -48,16 +48,15 @@
<script setup lang="ts">
import Notif from "components/Notif.vue";
import Tooltip from "features/tooltips/Tooltip.vue";
import Decimal from "util/bignum";
import { layers } from "game/layers";
import { Direction } from "util/common";
import Decimal from "util/bignum";
import { formatTime } from "util/break_eternity";
import { Direction } from "util/common";
import { ProcessedComputable } from "util/computed";
import { Ref, Transition } from "vue";
import { computed, unref } from "vue";
import { main } from "./projEntry";
import { computed, Ref, Transition, unref } from "vue";
import coal from "./layers/coal";
import dyes from "./layers/dyes";
import { main } from "./projEntry";
const props = defineProps<{
day: number;
@ -77,7 +76,7 @@ const emit = defineEmits<{
const canOpen = computed(
() =>
props.layer &&
props.layer != null &&
Decimal.gte(main.day.value, props.day) &&
new Date().getMonth() === 11 &&
new Date().getDate() >= props.day
@ -88,14 +87,14 @@ const includeMastery = computed(
() =>
props.mastered.value ||
main.currentlyMastering.value == layers[props.layer ?? ""] ||
["wrappingPaper", "ribbon"].includes(props.layer || "") ||
["wrappingPaper", "ribbon"].includes(props.layer ?? "") ||
(coal.mastered.value && props.layer == "elves") ||
(dyes.mastered.value && props.layer == "elves")
);
const masteryLock = computed(() => isMastering.value && !includeMastery.value);
function tryUnlock() {
if (canOpen.value) {
if (canOpen.value === true) {
emit("unlockLayer");
}
}

View file

@ -58,6 +58,7 @@
<img v-if="day >= 10" :src="dyes" class="scene-item" />
<img v-if="day >= 14" :src="wrappingPaper" class="scene-item" />
<img v-if="day >= 15" :src="ribbons" class="scene-item" />
<img v-if="day >= 16" :src="toys" class="scene-item" />
</div>
</div>
</template>
@ -79,6 +80,7 @@ import advManagement from "./symbols/workshopMansion.png";
import letters from "./symbols/letterbox.png";
import wrappingPaper from "./symbols/wrappingPaper.png";
import ribbons from "./symbols/ribbons.png";
import toys from "./symbols/truck.png";
defineProps<{
day: number;

View file

@ -1,4 +1,5 @@
import Collapsible from "components/layout/Collapsible.vue";
import "data/layers/styles/day-gradients.css";
import { createBar } from "features/bars/bar";
import { GenericBuyable } from "features/buyable";
import type { Clickable, ClickableOptions, GenericClickable } from "features/clickables/clickable";
@ -16,14 +17,12 @@ import { GenericMilestone } from "features/milestones/milestone";
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 { BaseLayer, Layer } from "game/layers";
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 { DecimalSource, formatSmall } from "util/bignum";
import Decimal, { format } from "util/bignum";
import Decimal, { DecimalSource, format, formatSmall } from "util/bignum";
import { formatWhole } from "util/break_eternity";
import { Direction, WithRequired } from "util/common";
import type {
@ -34,10 +33,8 @@ import type {
} from "util/computed";
import { convertComputable, processComputable } from "util/computed";
import { getFirstFeature, render, renderColJSX, renderJSX, VueFeature } from "util/vue";
import { Ref, watchEffect } from "vue";
import { computed, unref } from "vue";
import { computed, Ref, unref, watchEffect } from "vue";
import "./common.css";
import "data/layers/styles/day-gradients.css";
import { main } from "./projEntry";
/** An object that configures a {@link ResetButton} */
@ -138,7 +135,7 @@ export function createResetButton<T extends ClickableOptions & ResetButtonOption
)}
</b>{" "}
{resetButton.conversion.gainResource.displayName}
{unref(resetButton.showNextAt) ? (
{unref(resetButton.showNextAt) != null ? (
<div>
<br />
{unref(resetButton.conversion.buyMax) ? "Next:" : "Req:"}{" "}
@ -167,7 +164,7 @@ export function createResetButton<T extends ClickableOptions & ResetButtonOption
const onClick = resetButton.onClick;
resetButton.onClick = function () {
if (!unref(resetButton.canClick)) {
if (unref(resetButton.canClick) === false) {
return;
}
resetButton.conversion.convert();
@ -311,7 +308,7 @@ export function createCollapsibleModifierSections(
</span>
{s.title}
{s.subtitle ? <span class="subtitle"> ({s.subtitle})</span> : null}
{s.subtitle != null ? <span class="subtitle"> ({s.subtitle})</span> : null}
</h3>
);
@ -338,7 +335,8 @@ export function createCollapsibleModifierSections(
{hasPreviousSection ? <br /> : null}
<div
style={{
"--unit": settings.alignUnits && s.unit ? "'" + s.unit + "'" : ""
"--unit":
settings.alignUnits && s.unit != null ? "'" + s.unit + "'" : ""
}}
>
{header}
@ -455,7 +453,7 @@ export function setUpDailyProgressTracker(options: {
animation: options.background.duration + " " + options.background.gradient + " linear infinite",
},
/* eslint-enable prettier/prettier */
textStyle: options.textColor ? { color: options.textColor } : undefined,
textStyle: options.textColor != null ? { color: options.textColor } : undefined,
progress: progressFunc,
display: jsx(() =>
main.day.value === options.day ||

View file

@ -35,6 +35,7 @@ import management from "./management";
import oil from "./oil";
import paper from "./paper";
import trees from "./trees";
import toys from "./toys";
interface Dye {
name: string;
@ -373,6 +374,8 @@ const layer = createLayer(id, function (this: BaseLayer) {
enabled: main.days[day - 1].opened
}));
const visibility = convertComputable(options.visibility ?? Visibility.Visible);
return {
name: options.name,
amount,
@ -380,15 +383,19 @@ const layer = createLayer(id, function (this: BaseLayer) {
hotkey,
toGenerate,
computedToGenerate,
display: jsx(() => (
<MainDisplay
resource={amount}
color={options.color}
shadowColor={options.shadowColor ?? options.color}
style="margin: 0; width: 200px; width: 180px; padding: 10px;"
sticky={false}
/>
))
display: jsx(() =>
unref(visibility) === Visibility.Visible ? (
<MainDisplay
resource={amount}
color={options.color}
shadowColor={options.shadowColor ?? options.color}
style="margin: 0; width: 200px; width: 180px; padding: 10px;"
sticky={false}
/>
) : (
""
)
)
};
}
@ -494,12 +501,12 @@ const layer = createLayer(id, function (this: BaseLayer) {
key: "a",
costs: () => [
{
base: "1e42",
base: "1e60",
root: 5,
res: trees.logs
},
{
base: computed(() => (upgrades.yellowDyeUpg2.bought.value ? "1e15" : "2e15")),
base: computed(() => (upgrades.yellowDyeUpg2.bought.value ? "1e17" : "2e17")),
root: 2,
res: oil.oil
}
@ -507,10 +514,11 @@ const layer = createLayer(id, function (this: BaseLayer) {
listedBoosts: [
{
visible: true,
desc: computed(() => `*${format(boosts.black1.value)} letters processed.`)
desc: computed(() => `*${format(boosts.black1.value)} oil gain.`)
}
],
dyesToReset: []
dyesToReset: [],
visibility: () => showIf(toys.milestones.milestone2.earned.value)
}),
orange: createDye({
name: "Orange Dye",

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

View file

@ -1,20 +1,23 @@
import { jsx } from "features/feature";
import { createLayer } from "game/layers";
import { Application } from "@pixi/app";
import { Sprite } from "@pixi/sprite";
import { Graphics } from "@pixi/graphics";
import { Assets } from "@pixi/assets";
import Factory from "./Factory.vue";
import conveyor from "./factory-components/conveyor.png";
import cursor from "./factory-components/cursor.jpg";
import square from "./factory-components/square.jpg";
import { computed, ComputedRef, reactive, Ref, ref, watchEffect } from "vue";
import { Direction } from "util/common";
import { Resource, Texture } from "@pixi/core";
import { Container } from "@pixi/display";
import { Graphics } from "@pixi/graphics";
import { Matrix } from "@pixi/math";
import { Sprite } from "@pixi/sprite";
import { jsx } from "features/feature";
import { globalBus } from "game/events";
import { createLayer } from "game/layers";
import { Persistent, persistent, State } from "game/persistence";
import player from "game/player";
import { Direction } from "util/common";
import { computed, ComputedRef, reactive, ref, watchEffect } from "vue";
import conveyor from "./factory-components/conveyor.png";
import cursor from "./factory-components/cursor.jpg";
import rotate from "./factory-components/rotate_rectangle.png";
import square from "./factory-components/square.jpg";
import Factory from "./Factory.vue";
import "./styles/factory.css";
import { globalBus } from "game/events";
import { Container } from "@pixi/display";
const id = "factory";
@ -31,7 +34,7 @@ enum FactoryDirections {
type FactoryDirection = FactoryDirections | Direction;
function roundDownTo(num: number, multiple: number) {
return Math.floor(num / multiple) * multiple;
return Math.floor((num + multiple / 2) / multiple) * multiple;
}
function getRelativeCoords(e: MouseEvent) {
const rect = (e.target as HTMLElement).getBoundingClientRect();
@ -54,6 +57,13 @@ function iterateDirection(dir: FactoryDirection, func: (dir: FactoryDirection) =
func(dir);
}
}
function rotateDir(dir: Direction, relative = Direction.Right) {
const directions = [Direction.Up, Direction.Right, Direction.Down, Direction.Left];
let index = directions.indexOf(dir);
index += directions.indexOf(relative);
index = index % directions.length;
return directions[index];
}
function directionToNum(dir: Direction) {
switch (dir) {
case Direction.Left:
@ -86,6 +96,8 @@ const factory = createLayer(id, () => {
const name = "The Factory";
const color = "grey";
// ---------------------------------------------- Components
const FACTORY_COMPONENTS = {
cursor: {
imageSrc: cursor,
@ -97,6 +109,16 @@ const factory = createLayer(id, () => {
production: {},
productionStock: {}
},
rotate: {
imageSrc: rotate,
name: "Rotate",
description: "Use this to rotate components.",
tick: 0,
consumption: {},
consumptionStock: {},
production: {},
productionStock: {}
},
conveyor: {
imageSrc: conveyor,
name: "Conveyor",
@ -105,7 +127,15 @@ const factory = createLayer(id, () => {
consumption: {},
consumptionStock: {},
production: {},
productionStock: {}
productionStock: {},
ports: {
[Direction.Left]: {
type: "input"
},
[Direction.Right]: {
type: "output"
}
}
},
square: {
imageSrc: square,
@ -121,14 +151,19 @@ const factory = createLayer(id, () => {
consumption: {},
consumptionStock: {}
}
} as Record<"cursor" | "conveyor" | "square", FactoryComponentDeclaration>;
} as Record<string, FactoryComponentDeclaration>;
const RESOURCES = {
square: square
} as Record<string, string>;
type FactoryCompNames = keyof typeof FACTORY_COMPONENTS;
type BuildableCompName = Exclude<FactoryCompNames, "cursor">;
interface FactoryComponentProducers extends Record<string, State> {
interface FactoryComponentBase extends Record<string, State> {
direction: Direction;
}
interface FactoryComponentProducer extends FactoryComponentBase {
type: Exclude<BuildableCompName, "conveyor">;
consumptionStock: Record<string, number>;
@ -136,11 +171,14 @@ const factory = createLayer(id, () => {
productionStock: Record<string, number>;
ticksDone: number;
}
interface FactoryComponentConveyor extends Record<string, State> {
interface FactoryComponentConveyor extends FactoryComponentBase {
type: "conveyor";
directionOut: Direction;
}
type FactoryComponent = FactoryComponentConveyor | FactoryComponentProducers;
type FactoryComponent = FactoryComponentBase &
(FactoryComponentConveyor | FactoryComponentProducer);
interface FactoryComponentDeclaration {
tick: number;
imageSrc: string;
@ -176,7 +214,6 @@ const factory = createLayer(id, () => {
}
interface FactoryInternalProducer extends FactoryInternalBase {
type: Exclude<BuildableCompName, "conveyor">;
startingFrom: "up" | "right" | "down" | "left";
}
type FactoryInternal = FactoryInternalConveyor | FactoryInternalProducer;
@ -200,7 +237,10 @@ const factory = createLayer(id, () => {
y: 0
});
const isMouseHoverShown = ref(false);
const isComponentHover = ref(false);
const whatIsHovered = ref<FactoryCompNames | "">("");
const compSelected = ref<FactoryCompNames>("cursor");
const components: Persistent<{ [key: string]: FactoryComponent }> = persistent({});
const compInternalData: Record<string, FactoryInternal> = {};
@ -246,8 +286,8 @@ const factory = createLayer(id, () => {
const floorGraphics = new Graphics();
floorGraphics.beginFill(0x70645d);
floorGraphics.drawRect(
-factorySize.width * blockSize,
-factorySize.height * blockSize,
(-factorySize.width - 0.5) * blockSize,
(-factorySize.height - 0.5) * blockSize,
factorySize.width * 2 * blockSize,
factorySize.height * 2 * blockSize
);
@ -257,18 +297,19 @@ const factory = createLayer(id, () => {
// load every sprite here so pixi doesn't complain about loading multiple times
await Assets.load(Object.values(FACTORY_COMPONENTS).map(x => x.imageSrc));
if (Array.isArray(components.value)) components.value = {};
else
if (Array.isArray(components.value)) {
components.value = {};
} else {
for (const id in components.value) {
const data = components.value[id];
console.log(id, data);
if (data?.type === undefined) {
delete components.value[id];
continue;
}
const [x, y] = id.split("x").map(p => +p);
addFactoryComp(x, y, data.type);
addFactoryComp(x, y, data);
}
}
loaded = true;
});
@ -277,31 +318,31 @@ const factory = createLayer(id, () => {
(window as any).blocks = movingBlocks;
let taskIsRunning = false;
globalBus.on("update", async diff => {
globalBus.on("update", diff => {
if (taskIsRunning || !loaded) return;
taskIsRunning = true;
//debugger
// will change soon:tm:
const tick = diff;
// make them produce
for (const id in components.value) {
const [x, y] = id.split("x").map(p => +p);
const data = components.value[id];
const compData = compInternalData[id];
//console.log(compData, data)
if (data === undefined || compData === undefined) continue;
const factoryData = FACTORY_COMPONENTS[data.type];
//debugger;
if (data.type === "conveyor") {
const _data = components.value[id];
const _compData = compInternalData[id];
if (_data === undefined || _compData === undefined) continue;
const factoryData = FACTORY_COMPONENTS[_data.type];
// debugger;
if (_data.type === "conveyor") {
const data = _data as FactoryComponentConveyor;
const compData = _compData as FactoryInternalConveyor;
if (compData.type !== "conveyor") throw new TypeError("this should not happen");
// conveyor part
// use a copy
//console.log(compData);
compData.packages = compData.packages.concat(compData.nextPackages);
compData.nextPackages = [];
for (const [key, block] of [...compData.packages].entries()) {
const dirType = getDirection(data.directionOut);
const dirAmt = directionToNum(data.directionOut);
const inputDirection = rotateDir(data.direction, Direction.Left);
const dirType = getDirection(inputDirection);
const dirAmt = directionToNum(inputDirection);
if (dirType === "h") {
if (block.x <= block.lastX + dirAmt) {
const compBehind = compInternalData[x + dirAmt + "x" + y];
@ -316,14 +357,13 @@ const factory = createLayer(id, () => {
// push it to the next conveyor, kill it from the
// curent conveyor
block.lastX += dirAmt;
compBehind.nextPackages.push(block);
(compBehind as FactoryInternalConveyor).nextPackages.push(block);
compData.packages.splice(key, 1);
} else {
// send it to the factory
// destory its sprite and data
(storedComp as FactoryComponentProducers).consumptionStock[
block.type
]++;
const factoryData = storedComp as FactoryComponentProducer;
factoryData.consumptionStock[block.type]++;
movingBlocks.removeChild(block.sprite);
compData.packages.splice(key, 1);
}
@ -347,12 +387,12 @@ const factory = createLayer(id, () => {
// push it to the next conveyor, kill it from the
// curent conveyor
block.lastY += dirAmt;
compBehind.nextPackages.push(block);
(compBehind as FactoryInternalConveyor).nextPackages.push(block);
compData.packages.splice(key, 1);
} else {
// send it to the factory
// destory its sprite and data
const factoryData = storedComp as FactoryComponentProducers;
const factoryData = storedComp as FactoryComponentProducer;
factoryData.consumptionStock[block.type]++;
movingBlocks.removeChild(block.sprite);
compData.packages.splice(key, 1);
@ -365,6 +405,8 @@ const factory = createLayer(id, () => {
}
}
} else {
const data = _data as FactoryComponentProducer;
const compData = _compData as FactoryInternalProducer;
// factory part
// PRODUCTION
if (data.ticksDone >= factoryData.tick) {
@ -386,35 +428,30 @@ const factory = createLayer(id, () => {
let yInc = 0;
let xInc = 0;
//debugger;
if (
components.value[x + "x" + (y + 1)]?.type === "conveyor" &&
(compInternalData[x + "x" + (y + 1)] as FactoryInternalProducer)
.startingFrom === "up"
components.value[x + "x" + (y + 1)].direction === Direction.Up
) {
yInc = 1;
} else if (
components.value[x + "x" + (y - 1)]?.type === "conveyor" &&
(compInternalData[x + "x" + (y - 1)] as FactoryInternalProducer)
.startingFrom === "down"
components.value[x + "x" + (y - 1)].direction === Direction.Down
) {
yInc = -1;
} else if (
components.value[x + 1 + "x" + y]?.type === "conveyor" &&
(compInternalData[x + 1 + "x" + y] as FactoryInternalProducer).startingFrom ===
"right"
components.value[x + 1 + "x" + y].direction === Direction.Right
) {
xInc = 1;
} else if (
components.value[x - 1 + "x" + y]?.type === "conveyor" &&
(compInternalData[x - 1 + "x" + y] as FactoryInternalProducer).startingFrom ===
"left"
components.value[x - 1 + "x" + y].direction === Direction.Left
) {
xInc = -1;
}
// no suitable location to dump stuff in
//console.log(x, y)
//debugger;
// console.log(x, y);
// debugger;
if (xInc === 0 && yInc === 0) continue;
let itemToMove: [string, number] | undefined = undefined;
for (const [name, amt] of Object.entries(data.productionStock)) {
@ -468,11 +505,15 @@ const factory = createLayer(id, () => {
taskIsRunning = false;
});
function addFactoryComp(x: number, y: number, type: BuildableCompName) {
function addFactoryComp(
x: number,
y: number,
data: Partial<FactoryComponent> & { type: BuildableCompName }
) {
if (x < -factorySize.width || x >= factorySize.width) return;
if (y < -factorySize.height || y >= factorySize.height) return;
const factoryBaseData = FACTORY_COMPONENTS[type];
const factoryBaseData = FACTORY_COMPONENTS[data.type];
const sheet = Assets.get(factoryBaseData.imageSrc);
const sprite = new Sprite(sheet);
@ -480,35 +521,42 @@ const factory = createLayer(id, () => {
sprite.y = y * blockSize;
sprite.width = blockSize;
sprite.height = blockSize;
sprite.anchor.x = 0.5;
sprite.anchor.y = 0.5;
sprite.rotation =
([Direction.Right, Direction.Down, Direction.Left, Direction.Up].indexOf(
data.direction ?? Direction.Right
) *
Math.PI) /
2;
console.log("!!", data, sprite);
components.value[x + "x" + y] = {
type,
ticksDone: 0,
directionIn: type === "conveyor" ? Direction.Right : undefined,
directionOut: type === "conveyor" ? Direction.Left : undefined,
direction: Direction.Right,
consumptionStock:
type === "conveyor"
data.type === "conveyor"
? undefined
: Object.fromEntries(
Object.keys(factoryBaseData.consumptionStock).map(i => [i, 0])
),
productionStock:
type === "conveyor"
data.type === "conveyor"
? undefined
: Object.fromEntries(
Object.keys(factoryBaseData.productionStock).map(i => [i, 0])
)
),
...data
} as FactoryComponent;
const isConveyor = type === "conveyor";
const isConveyor = data.type === "conveyor";
compInternalData[x + "x" + y] = {
type,
type: data.type,
packages: isConveyor ? [] : undefined,
nextPackages: isConveyor ? [] : undefined,
startingFrom: "left",
canProduce: computed(() => {
if (type === "conveyor") return true;
if (data.type === "conveyor") return true;
if (!(factoryBaseData.canProduce?.value ?? true)) return false;
// this should NEVER be null
const compData = components.value[x + "x" + y] as FactoryComponentProducers;
const compData = components.value[x + "x" + y] as FactoryComponentProducer;
for (const [key, res] of Object.entries(compData.productionStock)) {
// if the current stock + production is more than you can handle
if (
@ -524,7 +572,7 @@ const factory = createLayer(id, () => {
return true;
}),
sprite
} as FactoryInternal;
} as FactoryInternalProducer;
spriteContainer.addChild(sprite);
}
@ -539,12 +587,16 @@ const factory = createLayer(id, () => {
spriteContainer.x = movingBlocks.x = calculatedX;
spriteContainer.y = movingBlocks.y = calculatedY;
if (isMouseHoverShown.value && compSelected.value !== "cursor") {
if (
isMouseHoverShown.value &&
compSelected.value !== "cursor" &&
compSelected.value !== "rotate"
) {
const { tx, ty } = spriteContainer.localTransform;
graphicContainer.beginFill(0x808080);
graphicContainer.lineStyle(4, 0x808080, 1);
graphicContainer.drawRect(
roundDownTo(mouseCoords.x - tx, blockSize) + tx,
roundDownTo(mouseCoords.y - ty, blockSize) + ty,
roundDownTo(mouseCoords.x - tx, blockSize) + tx - blockSize / 2,
roundDownTo(mouseCoords.y - ty, blockSize) + ty - blockSize / 2,
blockSize,
blockSize
);
@ -563,18 +615,25 @@ const factory = createLayer(id, () => {
if (
pointerDown.value &&
compSelected.value === "cursor" &&
(pointerDrag.value || Math.abs(e.movementX) > 2 || Math.abs(e.movementY) > 2)
(pointerDrag.value ||
(compSelected.value === "cursor" &&
(Math.abs(e.movementX) > 2 || Math.abs(e.movementY) > 2)))
) {
pointerDrag.value = true;
mapOffset.x += e.movementX / blockSize;
mapOffset.y += e.movementY / blockSize;
// the maximum you can see currently
// total size of blocks - current size = amount you should move
mapOffset.x = Math.min(Math.max(mapOffset.x, -factorySize.width), factorySize.width);
mapOffset.y = Math.min(Math.max(mapOffset.y, -factorySize.height), factorySize.height);
mapOffset.x = Math.min(
Math.max(mapOffset.x, -factorySize.width + 0.5),
factorySize.width + 0.5
);
mapOffset.y = Math.min(
Math.max(mapOffset.y, -factorySize.height + 0.5),
factorySize.height + 0.5
);
}
if (!pointerDown.value && !pointerDrag.value && compSelected.value === "cursor") {
if (!pointerDown.value && !pointerDrag.value) {
const { tx, ty } = spriteContainer.localTransform;
compHovered.value =
components.value[
@ -584,9 +643,12 @@ const factory = createLayer(id, () => {
];
}
}
function onFactoryPointerDown() {
function onFactoryPointerDown(e: PointerEvent) {
window.addEventListener("pointerup", onFactoryPointerUp);
pointerDown.value = true;
if (e.button === 1) {
pointerDrag.value = true;
}
}
function onFactoryPointerUp(e: PointerEvent) {
// make sure they're not dragging and that
@ -597,14 +659,29 @@ const factory = createLayer(id, () => {
x = roundDownTo(x - tx, blockSize) / blockSize;
y = roundDownTo(y - ty, blockSize) / blockSize;
if (e.button === 0) {
if (compSelected.value !== "cursor") {
if (!components.value[x + "x" + y]) addFactoryComp(x, y, compSelected.value);
if (compSelected.value === "rotate") {
if (
components.value[x + "x" + y] != null &&
components.value[x + "x" + y].direction != null
) {
components.value[x + "x" + y] = {
...components.value[x + "x" + y],
direction: rotateDir(
(components.value[x + "x" + y] as FactoryComponentConveyor)
.direction
)
};
compInternalData[x + "x" + y].sprite.rotation += Math.PI / 2;
}
} else if (compSelected.value !== "cursor") {
if (components.value[x + "x" + y] == null) {
addFactoryComp(x, y, { type: compSelected.value });
}
}
} else if (e.button === 2) {
const data = compInternalData[x + "x" + y];
if (data === undefined) return;
delete components.value[x + "x" + y];
delete compInternalData[x + "x" + y];
spriteContainer.removeChild(data.sprite);
}
}
@ -619,15 +696,20 @@ const factory = createLayer(id, () => {
isMouseHoverShown.value = false;
}
function goBack() {
player.tabs.splice(0, Infinity, "main");
}
function onComponentHover(name: FactoryCompNames | "") {
function onComponentMouseEnter(name: FactoryCompNames | "") {
whatIsHovered.value = name;
isComponentHover.value = true;
}
function onComponentMouseLeave() {
isComponentHover.value = false;
}
function onCompClick(name: FactoryCompNames) {
compSelected.value = name;
}
function goBack() {
player.tabs.splice(0, Infinity, "main");
}
return {
name,
day,
@ -649,54 +731,83 @@ const factory = createLayer(id, () => {
onPointerleave={onFactoryMouseLeave}
onContextmenu={(e: MouseEvent) => e.preventDefault()}
/>
<div class="info-container">
{compHovered.value !== undefined ? (
<>
<b>{FACTORY_COMPONENTS[compHovered.value.type].name}</b>
<br />
{FACTORY_COMPONENTS[compHovered.value.type].description}
<br />
{compHovered.value.type !== "conveyor" ? (
<>
Stock:{" "}
{Object.entries({
...compHovered.value.productionStock,
...compHovered.value.consumptionStock
}).map(i => {
return `${i[0]}: ${i[1]}/${
FACTORY_COMPONENTS[compHovered.value?.type ?? "cursor"]
.consumptionStock[i[0]] ??
FACTORY_COMPONENTS[compHovered.value?.type ?? "cursor"]
.productionStock[i[0]]
}`;
})}
</>
) : undefined}
</>
) : undefined}
</div>
<div class="container">
<div style="line-height: 2.5em; min-height: 2.5em">
{whatIsHovered.value === ""
? undefined
: FACTORY_COMPONENTS[whatIsHovered.value].description}
{compHovered.value !== undefined ? (
<div
class="info-container"
style={{
left: mouseCoords.x + "px",
top: mouseCoords.y + "px"
}}
>
<h3>{FACTORY_COMPONENTS[compHovered.value.type].name}</h3>
<br />
{FACTORY_COMPONENTS[compHovered.value.type].description}
<br />
{compHovered.value.type !== "conveyor" ? (
<>
Stock:{" "}
{Object.entries({
...(compHovered.value.productionStock as Record<
string,
number
>),
...(compHovered.value.consumptionStock as Record<
string,
number
>)
}).map(i => {
return `${i[0]}: ${i[1]}/${
FACTORY_COMPONENTS[compHovered.value?.type ?? "cursor"]
.consumptionStock[i[0]] ??
FACTORY_COMPONENTS[compHovered.value?.type ?? "cursor"]
.productionStock[i[0]]
}`;
})}
</>
) : undefined}
</div>
<div class="comps">
<div>
{Object.entries(FACTORY_COMPONENTS).map(value => {
const key = value[0] as FactoryCompNames;
const item = value[1];
return (
<img
src={item.imageSrc}
class={{ selected: compSelected.value === key }}
onMouseenter={() => onComponentHover(key)}
onMouseleave={() => onComponentHover("")}
onClick={() => onCompClick(key)}
></img>
);
})}
</div>
) : undefined}
<div class="factory-container">
<div
class={{
"comp-info": true,
active: isComponentHover.value
}}
style={{
top:
Math.max(
Object.keys(FACTORY_COMPONENTS).indexOf(whatIsHovered.value),
0
) *
50 +
10 +
"px"
}}
>
{whatIsHovered.value === "" ? undefined : (
<>
<h3>{FACTORY_COMPONENTS[whatIsHovered.value].name}</h3>
<br />
{FACTORY_COMPONENTS[whatIsHovered.value].description}
</>
)}
</div>
<div class="comp-list">
{Object.entries(FACTORY_COMPONENTS).map(value => {
const key = value[0] as FactoryCompNames;
const item = value[1];
return (
<img
src={item.imageSrc}
class={{ selected: compSelected.value === key }}
onMouseenter={() => onComponentMouseEnter(key)}
onMouseleave={() => onComponentMouseLeave()}
onClick={() => onCompClick(key)}
></img>
);
})}
</div>
</div>
</div>

View file

@ -79,7 +79,9 @@ const layer = createLayer(id, function (this: BaseLayer) {
processingProgress.value,
computedProcessingCooldown.value
).floor();
letters.value = Decimal.times(amount, computedLettersGain.value).add(letters.value);
letters.value = Decimal.times(amount, computedLettersGain.value)
.add(letters.value)
.min(8e9);
processingProgress.value = 0;
}
}));
@ -215,12 +217,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
createMultiplicativeModifier(() => ({
multiplier: () => Decimal.div(paperBuyable.amount.value, 2).add(1),
description: "Printed Labels"
})),
createMultiplicativeModifier(() => ({
multiplier: () => dyes.boosts.black1.value,
description: "Black Dye Boost"
}))
]);
const computedLettersGain = computed(() => lettersGain.apply(1));
const processingCooldown = createSequentialModifier(() => [

View file

@ -40,6 +40,7 @@ import management from "./management";
import workshop from "./workshop";
import { WithRequired } from "util/common";
import { ElfBuyable } from "./elves";
import toys from "./toys";
const id = "oil";
const day = 9;
@ -947,6 +948,15 @@ const layer = createLayer(id, function (this: BaseLayer) {
multiplier: 2,
description: "Cocoa Level 3",
enabled: management.elfTraining.oilElfTraining.milestones[2].earned
})),
createMultiplicativeModifier(() => ({
multiplier: () => dyes.boosts.black1.value,
description: "Black Dye Boost"
})),
createMultiplicativeModifier(() => ({
multiplier: 50,
description: "350 toys",
enabled: toys.milestones.milestone4.earned
}))
]) as WithRequired<Modifier, "description" | "revert">;
const computedOilSpeed = computed(() => oilSpeed.apply(0));

View file

@ -36,6 +36,7 @@ import metal from "./metal";
import oil from "./oil";
import paper from "./paper";
import workshop from "./workshop";
import toys from "./toys";
const id = "plastic";
const day = 10;
@ -373,6 +374,11 @@ const layer = createLayer(id, function (this: BaseLayer) {
multiplier: () => Decimal.div(buildRefinery.amount.value, 100).add(1),
description: "Tinsel Level 4",
enabled: management.elfTraining.plasticElfTraining.milestones[3].earned
})),
createMultiplicativeModifier(() => ({
multiplier: 50,
description: "350 toys",
enabled: toys.milestones.milestone4.earned
}))
]);
const computedPlasticGain = computed(() => plasticGain.apply(0));

View file

@ -41,7 +41,10 @@ const layer = createLayer(id, () => {
)
);
const currentDyeType = computed(
() => Object.values(dyes.dyes)[new Decimal(ribbon.value).toNumber() % 6]
() =>
Object.values(dyes.dyes).filter(d => d !== dyes.dyes.black)[
new Decimal(ribbon.value).toNumber() % 6
]
);
const ribbonProgress = persistent<DecimalSource>(0);
@ -60,8 +63,20 @@ const layer = createLayer(id, () => {
title: "Make Ribbon",
description: jsx(() => (
<>
Create another ribbon with {format(currentDyeCost.value)}{" "}
{currentDyeType.value.name} and {format(1e9)} {cloth.cloth.displayName}
Create another ribbon with{" "}
<span
class={
Decimal.lt(currentDyeType.value.amount.value, currentDyeCost.value)
? "unaffordable"
: ""
}
>
{format(currentDyeCost.value)} {currentDyeType.value.name}
</span>{" "}
and{" "}
<span class={Decimal.lt(cloth.cloth.value, 1e9) ? "unaffordable" : ""}>
{format(1e9)} {cloth.cloth.displayName}
</span>
<br />
{render(ribbonProgressBar)}
</>

View file

@ -17,38 +17,71 @@
.info-container {
position: absolute;
height: 100px;
top: 0;
left: 10%;
right: 10%;
transition: height ease 1s;
background: var(--raised-background);
border-radius: 0 0 var(--border-radius) var(--border-radius);
box-shadow: 0 2px 10px black;
margin: 0;
padding: 0;
width: max-content;
max-width: 300px;
margin: 20px 0 0 10px;
padding: 5px 10px;
background: var(--background);
border-radius: var(--border-radius);
box-shadow: 0 1px 5px black;
text-align: left;
font-size: smaller;
pointer-events: none;
transition: height .3s;
}
.container {
.factory-container {
position: absolute;
bottom: -5px;
height: 100px;
left: 10%;
right: 10%;
background: var(--raised-background);
border-radius: var(--border-radius) var(--border-radius) 0 0;
box-shadow: 0 2px 10px black;
top: calc(5% + 30px);
bottom: 5%;
left: 0%;
width: 70px;
margin: 0;
padding: 0;
}
.comps > div > img {
.comp-info {
position: absolute;
right: 10px;
padding: 5px 10px;
width: max-content;
max-width: 300px;
background: var(--background);
border-radius: var(--border-radius);
box-shadow: 0 1px 5px #0007;
text-align: left;
font-size: smaller;
pointer-events: none;
transition: transform 0.3s;
}
.comp-info.active {
transform: translateX(calc(20px + 100%));
}
.comp-list {
position: relative;
height: 100%;
padding: 10px;
background: var(--raised-background);
border-radius: 0 var(--border-radius) var(--border-radius) 0;
box-shadow: 0 2px 10px black;
}
.comp-list > img {
display: block;
width: 50px;
height: 50px;
}
.comps > div > img.selected {
transform: translateY(-5px);
filter: drop-shadow(0 5px 5px #0007);
.comp-list > img.selected {
transform: translate(-5px, -5px);
filter: drop-shadow(2px 2px 0 var(--foreground)) drop-shadow(5px 5px 5px #0007);
}

View file

@ -4,49 +4,38 @@
*/
import Spacer from "components/layout/Spacer.vue";
import Modal from "components/Modal.vue";
import { main } from "data/projEntry";
import { createBar } from "features/bars/bar";
import {
createCollapsibleMilestones,
createCollapsibleModifierSections,
setUpDailyProgressTracker
} from "data/common";
import { main } from "data/projEntry";
import { createBuyable, GenericBuyable } from "features/buyable";
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 { createMilestone } from "features/milestones/milestone";
import { createResource, Resource } from "features/resources/resource";
import MainDisplay from "features/resources/MainDisplay.vue";
import { createResource } from "features/resources/resource";
import { createUpgrade } from "features/upgrades/upgrade";
import { globalBus } from "game/events";
import { BaseLayer, createLayer } from "game/layers";
import {
createAdditiveModifier,
createExponentialModifier,
createMultiplicativeModifier,
createSequentialModifier,
Modifier
} from "game/modifiers";
import { noPersist, persistent } from "game/persistence";
import Decimal, { DecimalSource, format, formatGain, formatLimit, formatWhole } from "util/bignum";
import { Direction, WithRequired } from "util/common";
import { createSequentialModifier } from "game/modifiers";
import { noPersist } from "game/persistence";
import Decimal, { DecimalSource, format, formatWhole } from "util/bignum";
import { render, renderGrid, renderRow } from "util/vue";
import { computed, ref } from "vue";
import cloth from "./cloth";
import dyes from "./dyes";
import metal from "./metal";
import plastic from "./plastic";
import cloth from "./cloth";
import trees from "./trees";
import dyes from "./dyes";
import paper from "./paper";
import workshop from "./workshop";
const id = "toys";
const day = 17;
const layer = createLayer(id, function (this: BaseLayer) {
const name = "Toys";
const colorBright = "#4BDC13";
const colorDark = "green";
const color = "cornflowerblue";
const clothes = createResource<DecimalSource>(0, "clothes");
const woodenBlocks = createResource<DecimalSource>(0, " wooden blocks");
@ -59,14 +48,14 @@ const layer = createLayer(id, function (this: BaseLayer) {
const clothesCost = computed(() => {
let clothFactor = Decimal.add(1, clothesBuyable.amount.value);
if (milestones.milestone1.earned) {
if (milestones.milestone1.earned.value) {
clothFactor = clothFactor.div(
Decimal.div(workshop.foundationProgress.value, 100).floor()
);
}
return {
cloth: clothFactor.mul(1e8),
dye: clothFactor.mul(1e6)
cloth: clothFactor.mul(1e13),
dye: clothFactor.mul(2e14)
};
});
const clothesBuyable = createBuyable(() => ({
@ -79,8 +68,28 @@ const layer = createLayer(id, function (this: BaseLayer) {
<div>You have {formatWhole(clothes.value)} clothes.</div>
<div>
Costs {format(clothesCost.value.cloth)} cloth and requires{" "}
{format(clothesCost.value.dye)} of red, yellow, and blue dye
Costs{" "}
<span
class={
Decimal.lt(cloth.cloth.value, clothesCost.value.cloth)
? "unaffordable"
: ""
}
>
{format(clothesCost.value.cloth)} cloth
</span>{" "}
and requires{" "}
<span
class={
[dyes.dyes.red, dyes.dyes.yellow, dyes.dyes.blue].some(d =>
Decimal.lt(d.amount.value, clothesCost.value.dye)
)
? "unaffordable"
: ""
}
>
{format(clothesCost.value.dye)} of red, yellow, and blue dye
</span>
</div>
</>
)),
@ -100,13 +109,13 @@ const layer = createLayer(id, function (this: BaseLayer) {
})) as GenericBuyable;
const woodenBlocksCost = computed(() => {
let woodFactor = Decimal.add(1, woodenBlocksBuyable.amount.value).pow(5);
if (milestones.milestone1.earned) {
if (milestones.milestone1.earned.value) {
woodFactor = woodFactor.div(
Decimal.div(workshop.foundationProgress.value, 100).floor()
);
}
return {
wood: woodFactor.mul(1e40)
wood: woodFactor.mul(1e63)
};
});
const woodenBlocksBuyable = createBuyable(() => ({
@ -133,15 +142,15 @@ const layer = createLayer(id, function (this: BaseLayer) {
const trucksCost = computed(() => {
let factor = Decimal.add(1, trucksBuyable.amount.value).pow(3);
let plasticFactor = Decimal.add(1, trucksBuyable.amount.value);
if (milestones.milestone1.earned) {
if (milestones.milestone1.earned.value) {
factor = factor.div(Decimal.div(workshop.foundationProgress.value, 100).floor());
plasticFactor = plasticFactor.div(
Decimal.div(workshop.foundationProgress.value, 100).floor()
);
}
return {
metal: factor.mul(1e25),
plastic: plasticFactor.mul(1e10)
metal: factor.mul(1e43),
plastic: plasticFactor.mul(1e14)
};
});
const trucksBuyable = createBuyable(() => ({
@ -154,8 +163,26 @@ const layer = createLayer(id, function (this: BaseLayer) {
<div>You have {formatWhole(trucks.value)} trucks.</div>
<div>
Costs {format(trucksCost.value.metal)} metal and{" "}
{format(trucksCost.value.plastic)} plastic
Costs{" "}
<span
class={
Decimal.lt(metal.metal.value, trucksCost.value.metal)
? "unaffordable"
: ""
}
>
{format(trucksCost.value.metal)} metal
</span>{" "}
and{" "}
<span
class={
Decimal.lt(plastic.plastic.value, trucksCost.value.plastic)
? "unaffordable"
: ""
}
>
{format(trucksCost.value.plastic)} plastic
</span>
</div>
</>
)),
@ -213,9 +240,27 @@ const layer = createLayer(id, function (this: BaseLayer) {
requirement: "100 toys",
effectDisplay: "Unlock black dyes."
},
shouldEarn: () => Decimal.gte(toySum.value, 100)
shouldEarn: () => Decimal.gte(toySum.value, 100),
visibility: () => showIf(milestone1.earned.value)
}));
const milestones = { milestone1, milestone2 };
const milestone3 = createMilestone(() => ({
display: {
requirement: "200 toys",
effectDisplay: "Beach wrapping paper is much more powerful."
},
shouldEarn: () => Decimal.gte(toySum.value, 200),
visibility: () => showIf(milestone2.earned.value)
}));
const milestone4 = createMilestone(() => ({
display: {
requirement: "350 toys",
effectDisplay: "Gain 50x oil and plastic."
},
shouldEarn: () => Decimal.gte(toySum.value, 350),
visibility: () => showIf(milestone3.earned.value)
}));
const milestones = { milestone1, milestone2, milestone3, milestone4 };
const { collapseMilestones, display: milestonesDisplay } =
createCollapsibleMilestones(milestones);
@ -256,9 +301,10 @@ const layer = createLayer(id, function (this: BaseLayer) {
const { total: totalToys, trackerDisplay } = setUpDailyProgressTracker({
resource: toySum,
goal: 200,
goal: 500,
name,
day,
textColor: "var(--feature-foreground)",
background: {
gradient: "toys-bar",
duration: "15s"
@ -272,7 +318,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
return {
name,
day,
color: colorBright,
color,
clothes,
woodenBlocks,
trucks,
@ -290,19 +336,19 @@ const layer = createLayer(id, function (this: BaseLayer) {
<Spacer />
<MainDisplay
resource={clothes}
color={colorBright}
color="lightblue"
style="margin-bottom: 0"
productionDisplay={undefined}
/>
<MainDisplay
resource={woodenBlocks}
color={colorDark}
color="cornflowerblue"
style="margin-bottom: 0"
productionDisplay={undefined}
/>
<MainDisplay
resource={trucks}
color={colorDark}
color="cadetblue"
style="margin-bottom: 0"
productionDisplay={undefined}
/>
@ -311,6 +357,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
<Spacer />
{renderGrid(row1Upgrades)}
<Spacer />
<div>You have {formatWhole(toySum.value)} toys</div>
{milestonesDisplay()}
</>
)),

View file

@ -404,7 +404,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
createAdditiveModifier(() => ({
addend: 1,
description: "Automated Spade",
enabled: autoPlantUpgrade1.bought.value
enabled: autoPlantUpgrade1.bought
})),
createAdditiveModifier(() => ({
addend: () => Decimal.div(autoPlantingBuyable1.amount.value, 2),

View file

@ -49,7 +49,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
scaling: addHardcap(
addSoftcap(addSoftcap(createPolynomialScaling(250, 1.5), 5423, 1 / 1e10), 1e20, 3e8),
computed(() =>
toys.row1Upgrades[2].bought
toys.row1Upgrades[2].bought.value
? 1200
: management.elfTraining.expandersElfTraining.milestones[2].earned.value
? 1000
@ -74,6 +74,16 @@ const layer = createLayer(id, function (this: BaseLayer) {
exponent: 1 / 0.99,
description: "Holly Level 5",
enabled: management.elfTraining.cutterElfTraining.milestones[4].earned
})),
createExponentialModifier(() => ({
exponent: 0.1,
description: "Scaling Jump at 1000%",
enabled: computed(() => Decimal.gte(foundationProgress.value, 1000))
})),
createMultiplicativeModifier(() => ({
multiplier: 6969, // note: 6969 is a magic number. Don't touch this or it'll self-destruct.
description: "Scaling Jump at 1000%",
enabled: computed(() => Decimal.gte(foundationProgress.value, 1000))
}))
])
}));
@ -89,12 +99,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
<br />
<span style="font-size: large">
{masteryEffectActive.value ? "Requirement" : "Cost"}:{" "}
{displayResource(
trees.logs,
Decimal.gte(foundationConversion.actualGain.value, 1)
? foundationConversion.currentAt.value
: foundationConversion.nextAt.value
)}{" "}
{displayResource(trees.logs, foundationConversion.nextAt.value)}{" "}
{trees.logs.displayName}
</span>
</>

View file

@ -16,6 +16,7 @@ import { computed, Ref, unref, watchEffect } from "vue";
import { main } from "../projEntry";
import { default as dyes, type enumColor } from "./dyes";
import elves from "./elves";
import toys from "./toys";
const id = "wrappingPaper";
const day = 15;
@ -277,7 +278,10 @@ const layer = createLayer(id, () => {
beach1: computed(() =>
main.isMastery.value
? 1
: Decimal.add(wrappingPaper.beach.buyable.amount.value, 1).log10().add(1)
: Decimal.add(wrappingPaper.beach.buyable.amount.value, 1)
.log10()
.add(1)
.pow(toys.milestones.milestone3.earned.value ? 1.6 : 1)
)
};
const wrappingPaperSum = createResource(

View file

@ -49,6 +49,7 @@ import paperSymbol from "./symbols/paperStacks.png";
import plasticSymbol from "./symbols/plastic.png";
import ribbonsSymbol from "./symbols/ribbons.png";
import workshopSymbol from "./symbols/sws.png";
import toysSymbol from "./symbols/truck.png";
import treeSymbol from "./symbols/tree.png";
import advManagementSymbol from "./symbols/workshopMansion.png";
import wrappingPaperSymbol from "./symbols/wrappingPaper.png";
@ -244,7 +245,7 @@ export const main = createLayer("main", function (this: BaseLayer) {
}
},
onUnlockLayer() {
if (layer) {
if (layer != null) {
opened.value = true;
setTimeout(() => {
loreScene.value = -1;
@ -437,16 +438,17 @@ export const main = createLayer("main", function (this: BaseLayer) {
createDay(() => ({
day: 17,
shouldNotify: false,
layer: "toys", // "toys1"
symbol: "",
story: "",
completedStory: "",
layer: "toys",
symbol: toysSymbol,
story: "You've had enough of this running around and stalling - it is time to create some toys NOW! You have everything you need and then some, so let's finally just sit down and get this process started!",
completedStory:
"In your haste you may have been a bit wasteful with resources, but it feels really good to finally make some meaningful process on making toys for Santa. You already envision plans on how to get elves to help you out and start pumping out these toys, but for now... Good Job!",
masteredStory: ""
})),
createDay(() => ({
day: 18,
shouldNotify: false,
layer: null, // "toys2"
layer: "factory",
symbol: "",
story: "",
completedStory: "",
@ -558,10 +560,10 @@ export const main = createLayer("main", function (this: BaseLayer) {
display: jsx(() => (
<>
{player.devSpeed === 0 ? <div>Game Paused</div> : null}
{player.devSpeed && player.devSpeed !== 1 ? (
{player.devSpeed != null && player.devSpeed !== 0 && player.devSpeed !== 1 ? (
<div>Dev Speed: {format(player.devSpeed)}x</div>
) : null}
{player.offlineTime ? (
{player.offlineTime != null && player.offlineTime !== 0 ? (
<div>Offline Time: {formatTime(player.offlineTime)}</div>
) : null}
<Spacer />
@ -635,29 +637,5 @@ export function fixOldSave(
oldVersion: string | undefined,
player: Partial<PlayerData>
// eslint-disable-next-line @typescript-eslint/no-empty-function
): void {
if (!["0.0", "0.1", "0.2", "0.3", "0.4"].includes(oldVersion ?? "")) {
return;
}
if ((player.layers?.workshop as LayerData<typeof workshop> | undefined)?.foundationProgress) {
(player.layers?.workshop as LayerData<typeof workshop> | undefined)!.foundationProgress =
Decimal.min(
(player.layers!.workshop as LayerData<typeof workshop> | undefined)!
.foundationProgress!,
1000
);
}
/*player.offlineProd = false;
delete player.layers?.management;
if ((player.layers?.main as LayerData<typeof main> | undefined)?.days?.[11]) {
(player.layers!.main as LayerData<typeof main>).days![11].opened = false;
}
if ((player.layers?.main as LayerData<typeof main> | undefined)?.day === 12) {
(player.layers!.main as LayerData<typeof main>).day === 11;
player.devSpeed = 0;
}
if (player.tabs) {
player.tabs = player.tabs.filter(l => l !== "management");
}*/
}
): void {}
/* eslint-enable @typescript-eslint/no-unused-vars */

BIN
src/data/symbols/truck.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View file

@ -109,7 +109,7 @@ export function createAchievement<T extends AchievementOptions>(
) {
genericAchievement.earned.value = true;
genericAchievement.onComplete?.();
if (genericAchievement.display) {
if (genericAchievement.display != null) {
const Display = coerceComponent(unref(genericAchievement.display));
toast.info(
<div>

View file

@ -1,5 +1,11 @@
import BarComponent from "features/bars/Bar.vue";
import type { CoercableComponent, GenericComponent, OptionsFunc, Replace, StyleValue } from "features/feature";
import type {
CoercableComponent,
GenericComponent,
OptionsFunc,
Replace,
StyleValue
} from "features/feature";
import { Component, GatherProps, getUniqueID, setDefault, Visibility } from "features/feature";
import type { DecimalSource } from "util/bignum";
import { Direction } from "util/common";

View file

@ -210,7 +210,7 @@ function drag(e: MouseEvent | TouchEvent) {
hasDragged.value = true;
}
if (dragging.value) {
if (dragging.value != null) {
e.preventDefault();
e.stopPropagation();
}

View file

@ -234,17 +234,17 @@ const title = computed(() => getNodeProperty(props.nodeType.value.title, unref(p
const label = computed(() => getNodeProperty(props.nodeType.value.label, unref(props.node)));
const size = computed(() => getNodeProperty(props.nodeType.value.size, unref(props.node)));
const progress = computed(
() => getNodeProperty(props.nodeType.value.progress, unref(props.node)) || 0
() => getNodeProperty(props.nodeType.value.progress, unref(props.node)) ?? 0
);
const backgroundColor = computed(() => themes[settings.theme].variables["--background"]);
const outlineColor = computed(
() =>
getNodeProperty(props.nodeType.value.outlineColor, unref(props.node)) ||
getNodeProperty(props.nodeType.value.outlineColor, unref(props.node)) ??
themes[settings.theme].variables["--outline"]
);
const fillColor = computed(
() =>
getNodeProperty(props.nodeType.value.fillColor, unref(props.node)) ||
getNodeProperty(props.nodeType.value.fillColor, unref(props.node)) ??
themes[settings.theme].variables["--raised-background"]
);
const progressColor = computed(() =>
@ -252,7 +252,7 @@ const progressColor = computed(() =>
);
const titleColor = computed(
() =>
getNodeProperty(props.nodeType.value.titleColor, unref(props.node)) ||
getNodeProperty(props.nodeType.value.titleColor, unref(props.node)) ??
themes[settings.theme].variables["--foreground"]
);
const progressDisplay = computed(() =>

View file

@ -1,5 +1,11 @@
import ClickableComponent from "features/clickables/Clickable.vue";
import type { CoercableComponent, GenericComponent, OptionsFunc, Replace, StyleValue } from "features/feature";
import type {
CoercableComponent,
GenericComponent,
OptionsFunc,
Replace,
StyleValue
} from "features/feature";
import { Component, GatherProps, getUniqueID, jsx, setDefault, Visibility } from "features/feature";
import type { Resource } from "features/resources/resource";
import { DefaultValue, Persistent } from "game/persistence";
@ -170,18 +176,18 @@ export function createBuyable<T extends BuyableOptions>(
}
if (currDisplay != null && buyable.cost != null && buyable.resource != null) {
const genericBuyable = buyable as GenericBuyable;
const Title = coerceComponent(currDisplay.title || "", "h3");
const Description = coerceComponent(currDisplay.description || "");
const EffectDisplay = coerceComponent(currDisplay.effectDisplay || "");
const Title = coerceComponent(currDisplay.title ?? "", "h3");
const Description = coerceComponent(currDisplay.description ?? "");
const EffectDisplay = coerceComponent(currDisplay.effectDisplay ?? "");
return (
<span>
{currDisplay.title ? (
{currDisplay.title == null ? null : (
<div>
<Title />
</div>
) : null}
{currDisplay.description ? <Description /> : null}
)}
{currDisplay.description == null ? null : <Description />}
{currDisplay.showAmount === false ? null : (
<div>
<br />
@ -195,15 +201,15 @@ export function createBuyable<T extends BuyableOptions>(
)}
</div>
)}
{currDisplay.effectDisplay ? (
{currDisplay.effectDisplay == null ? null : (
<div>
<br />
Currently: <EffectDisplay />
</div>
) : null}
{genericBuyable.cost && !genericBuyable.maxed.value ? (
)}
{genericBuyable.cost != null && !genericBuyable.maxed.value ? (
<div>
Cost: {format(unref(genericBuyable.cost) || 0)}{" "}
Cost: {format(unref(genericBuyable.cost))}{" "}
{buyable.resource.displayName}
</div>
) : null}

View file

@ -134,25 +134,25 @@ export default defineComponent({
comp.value = coerceComponent(
jsx(() => (
<span>
{currDisplay.title ? (
{currDisplay.title != null ? (
<div>
<Title />
</div>
) : null}
<Description />
{currDisplay.goal ? (
{currDisplay.goal != null ? (
<div>
<br />
Goal: <Goal />
</div>
) : null}
{currDisplay.reward ? (
{currDisplay.reward != null ? (
<div>
<br />
Reward: <Reward />
</div>
) : null}
{currDisplay.effectDisplay ? (
{currDisplay.effectDisplay != null ? (
<div>
Currently: <EffectDisplay />
</div>

View file

@ -126,7 +126,10 @@ export function createChallenge<T extends ChallengeOptions>(
challenge.toggle = function () {
const genericChallenge = challenge as GenericChallenge;
if (genericChallenge.active.value) {
if (unref(genericChallenge.canComplete) && !genericChallenge.maxed.value) {
if (
unref(genericChallenge.canComplete) !== false &&
!genericChallenge.maxed.value
) {
let completions: boolean | DecimalSource = unref(genericChallenge.canComplete);
if (typeof completions === "boolean") {
completions = 1;
@ -264,11 +267,14 @@ export function setupAutoComplete(
exitOnComplete = true
): WatchStopHandle {
const isActive = typeof autoActive === "function" ? computed(autoActive) : autoActive;
return watch([challenge.canComplete, isActive], ([canComplete, isActive]) => {
if (canComplete && isActive) {
challenge.complete(!exitOnComplete);
return watch(
[challenge.canComplete as Ref<boolean>, isActive as Ref<boolean>],
([canComplete, isActive]) => {
if (canComplete && isActive) {
challenge.complete(!exitOnComplete);
}
}
});
);
}
export function createActiveChallenge(

View file

@ -98,7 +98,7 @@ export default defineComponent({
comp.value = coerceComponent(
jsx(() => (
<span>
{currDisplay.title ? (
{currDisplay.title != null ? (
<div>
<Title />
</div>

View file

@ -1,5 +1,11 @@
import ClickableComponent from "features/clickables/Clickable.vue";
import type { CoercableComponent, GenericComponent, OptionsFunc, Replace, StyleValue } from "features/feature";
import type {
CoercableComponent,
GenericComponent,
OptionsFunc,
Replace,
StyleValue
} from "features/feature";
import { Component, GatherProps, getUniqueID, setDefault, Visibility } from "features/feature";
import type { BaseLayer } from "game/layers";
import type { Unsubscribe } from "nanoevents";
@ -84,7 +90,7 @@ export function createClickable<T extends ClickableOptions>(
if (clickable.onClick) {
const onClick = clickable.onClick.bind(clickable);
clickable.onClick = function (e) {
if (unref(clickable.canClick)) {
if (unref(clickable.canClick) !== false) {
onClick(e);
}
};
@ -92,7 +98,7 @@ export function createClickable<T extends ClickableOptions>(
if (clickable.onHold) {
const onHold = clickable.onHold.bind(clickable);
clickable.onHold = function () {
if (unref(clickable.canClick)) {
if (unref(clickable.canClick) !== false) {
onHold();
}
};
@ -136,7 +142,8 @@ export function setupAutoClick(
clickable: GenericClickable,
autoActive: Computable<boolean> = true
): Unsubscribe {
const isActive = typeof autoActive === "function" ? computed(autoActive) : autoActive;
const isActive: ProcessedComputable<boolean> =
typeof autoActive === "function" ? computed(autoActive) : autoActive;
return layer.on("update", () => {
if (unref(isActive) && unref(clickable.canClick)) {
clickable.onClick?.();

View file

@ -151,7 +151,7 @@ export function createConversion<T extends ConversionOptions>(
: conversion.scaling.currentGain(conversion as GenericConversion);
gain = Decimal.floor(gain).max(0);
if (!unref(conversion.buyMax)) {
if (unref(conversion.buyMax) === false) {
gain = gain.min(1);
}
return gain;
@ -163,14 +163,15 @@ export function createConversion<T extends ConversionOptions>(
if (conversion.currentAt == null) {
conversion.currentAt = computed(() => {
let current = conversion.scaling.currentAt(conversion as GenericConversion);
if (conversion.roundUpCost) current = Decimal.ceil(current);
if (unref((conversion as GenericConversion).roundUpCost))
current = Decimal.ceil(current);
return current;
});
}
if (conversion.nextAt == null) {
conversion.nextAt = computed(() => {
let next = conversion.scaling.nextAt(conversion as GenericConversion);
if (conversion.roundUpCost) next = Decimal.ceil(next);
if (unref((conversion as GenericConversion).roundUpCost)) next = Decimal.ceil(next);
return next;
});
}
@ -405,7 +406,7 @@ export function createIndependentConversion<S extends ConversionOptions>(
: conversion.scaling.currentGain(conversion as GenericConversion);
gain = Decimal.floor(gain).max(conversion.gainResource.value);
if (!unref(conversion.buyMax)) {
if (unref(conversion.buyMax) === false) {
gain = gain.min(Decimal.add(conversion.gainResource.value, 1));
}
return gain;
@ -418,7 +419,7 @@ export function createIndependentConversion<S extends ConversionOptions>(
conversion.gainResource.value
).max(0);
if (!unref(conversion.buyMax)) {
if (unref(conversion.buyMax) === false) {
gain = gain.min(1);
}
return gain;
@ -511,8 +512,10 @@ 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))),
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))
};

View file

@ -102,7 +102,7 @@ export function findFeatures(obj: Record<string, unknown>, ...types: symbol[]):
const handleObject = (obj: Record<string, unknown>) => {
Object.keys(obj).forEach(key => {
const value = obj[key];
if (value && typeof value === "object") {
if (value != null && typeof value === "object") {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
if (types.includes((value as Record<string, any>).type)) {
objects.push(value);
@ -127,7 +127,7 @@ export function excludeFeatures(obj: Record<string, unknown>, ...types: symbol[]
const handleObject = (obj: Record<string, unknown>) => {
Object.keys(obj).forEach(key => {
const value = obj[key];
if (value && typeof value === "object") {
if (value != null && typeof value === "object") {
if (
// eslint-disable-next-line @typescript-eslint/no-explicit-any
typeof (value as Record<string, any>).type == "symbol" &&

View file

@ -74,12 +74,12 @@ export default defineComponent({
jsx(() => (
<span>
<Requirement />
{currDisplay.effectDisplay ? (
{currDisplay.effectDisplay != null ? (
<div>
<EffectDisplay />
</div>
) : null}
{currDisplay.optionsDisplay ? (
{currDisplay.optionsDisplay != null ? (
<div class="equal-spaced">
<OptionsDisplay />
</div>

View file

@ -1,5 +1,11 @@
import Select from "components/fields/Select.vue";
import type { CoercableComponent, GenericComponent, OptionsFunc, Replace, StyleValue } from "features/feature";
import type {
CoercableComponent,
GenericComponent,
OptionsFunc,
Replace,
StyleValue
} from "features/feature";
import { Component, GatherProps, getUniqueID, jsx, setDefault, Visibility } from "features/feature";
import MilestoneComponent from "features/milestones/Milestone.vue";
import { globalBus } from "game/events";
@ -92,7 +98,7 @@ export function createMilestone<T extends MilestoneOptions>(
const genericMilestone = milestone as GenericMilestone;
earned.value = true;
genericMilestone.onComplete?.();
if (genericMilestone.display && unref(genericMilestone.showPopups) === true) {
if (genericMilestone.display != null && unref(genericMilestone.showPopups) === true) {
const display = unref(genericMilestone.display);
const Display = coerceComponent(
isCoercableComponent(display) ? display : display.requirement
@ -162,7 +168,10 @@ export function createMilestone<T extends MilestoneOptions>(
) {
genericMilestone.earned.value = true;
genericMilestone.onComplete?.();
if (genericMilestone.display && unref(genericMilestone.showPopups) === true) {
if (
genericMilestone.display != null &&
unref(genericMilestone.showPopups) === true
) {
const display = unref(genericMilestone.display);
const Display = coerceComponent(
isCoercableComponent(display) ? display : display.requirement

View file

@ -43,7 +43,7 @@ export function createReset<T extends ResetOptions>(
reset.reset = function () {
const handleObject = (obj: unknown) => {
if (obj && typeof obj === "object") {
if (obj != null && typeof obj === "object") {
if (DefaultValue in obj) {
const persistent = obj as NonPersistent;
persistent.value = persistent[DefaultValue];

View file

@ -88,7 +88,7 @@ export function createTreeNode<T extends TreeNodeOptions>(
if (treeNode.onClick) {
const onClick = treeNode.onClick.bind(treeNode);
treeNode.onClick = function () {
if (unref(treeNode.canClick)) {
if (unref(treeNode.canClick) !== false) {
onClick();
}
};
@ -96,7 +96,7 @@ export function createTreeNode<T extends TreeNodeOptions>(
if (treeNode.onHold) {
const onHold = treeNode.onHold.bind(treeNode);
treeNode.onHold = function () {
if (unref(treeNode.canClick)) {
if (unref(treeNode.canClick) !== false) {
onHold();
}
};

View file

@ -96,13 +96,13 @@ export default defineComponent({
component.value = coerceComponent(
jsx(() => (
<span>
{currDisplay.title ? (
{currDisplay.title != null ? (
<div>
<Title />
</div>
) : null}
<Description />
{currDisplay.effectDisplay ? (
{currDisplay.effectDisplay != null ? (
<div>
Currently: <EffectDisplay />
</div>

View file

@ -187,8 +187,11 @@ export function setupAutoPurchase(
autoActive: Computable<boolean>,
upgrades: GenericUpgrade[] = []
): void {
upgrades = upgrades || findFeatures(layer, UpgradeType);
const isAutoActive = isFunction(autoActive) ? computed(autoActive) : autoActive;
upgrades =
upgrades.length === 0 ? (findFeatures(layer, UpgradeType) as GenericUpgrade[]) : upgrades;
const isAutoActive: ProcessedComputable<boolean> = isFunction(autoActive)
? computed(autoActive)
: autoActive;
layer.on("update", () => {
if (unref(isAutoActive)) {
upgrades.forEach(upgrade => upgrade.purchase());

View file

@ -78,7 +78,7 @@ export function createAdditiveModifier<T extends AdditiveModifierOptions>(
? undefined
: jsx(() => (
<div class="modifier-container">
{unref(processedDescription) ? (
{unref(processedDescription) != null ? (
<span class="modifier-description">
{/* eslint-disable-next-line @typescript-eslint/no-non-null-assertion */}
{renderJSX(unref(processedDescription)!)}
@ -126,7 +126,7 @@ export function createMultiplicativeModifier<T extends MultiplicativeModifierOpt
? undefined
: jsx(() => (
<div class="modifier-container">
{unref(processedDescription) ? (
{unref(processedDescription) != null ? (
<span class="modifier-description">
{/* eslint-disable-next-line @typescript-eslint/no-non-null-assertion */}
{renderJSX(unref(processedDescription)!)}
@ -195,7 +195,7 @@ export function createExponentialModifier<T extends ExponentialModifierOptions>(
? undefined
: jsx(() => (
<div class="modifier-container">
{unref(processedDescription) ? (
{unref(processedDescription) != null ? (
<span class="modifier-description">
{/* eslint-disable-next-line @typescript-eslint/no-non-null-assertion */}
{renderJSX(unref(processedDescription)!)}

View file

@ -85,7 +85,7 @@ function getStackTrace() {
?.split("\n")
.slice(3, 5)
.map(line => line.trim())
.join("\n") || ""
.join("\n") ?? ""
);
}
@ -134,7 +134,7 @@ export function persistent<T extends State>(defaultValue: T | Ref<T>): Persisten
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function isPersistent(value: any): value is Persistent {
return value && typeof value === "object" && PersistentState in value;
return value != null && typeof value === "object" && PersistentState in value;
}
/**
@ -168,7 +168,7 @@ globalBus.on("addLayer", (layer: GenericLayer, saveData: Record<string, unknown>
let foundPersistent = false;
Object.keys(obj).forEach(key => {
let value = obj[key];
if (value && typeof value === "object") {
if (value != null && typeof value === "object") {
if (ProxyState in value) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
value = (value as any)[ProxyState] as object;

View file

@ -70,7 +70,7 @@ const state = reactive<PlayerData>({
modVersion: "",
layers: {},
autoPause: true,
autoPause: true
});
/** Convert a player save data object into a JSON string. Unwraps refs. */

View file

@ -33,9 +33,9 @@ const state = reactive<Partial<Settings>>({
showTPS: true,
theme: Themes.Nordic,
unthrottled: false,
usingLog: false,
alignUnits: false,
alignUnits: false
});
watch(
@ -68,9 +68,9 @@ export const hardResetSettings = (window.hardResetSettings = () => {
saves: [],
showTPS: true,
theme: Themes.Nordic,
usingLog: false,
alignUnits: false,
alignUnits: false
};
globalBus.emit("loadSettings", settings);
Object.assign(state, settings);

View file

@ -33,7 +33,7 @@ declare global {
formatSmall: (x: DecimalSource, precision?: number) => string;
formatLimit: (list: [DecimalSource, string][], unit: string) => string;
invertOOM: (x: DecimalSource) => Decimal;
formatGain: (x: DecimalSource) => string
formatGain: (x: DecimalSource) => string;
}
}
window.Decimal = Decimal;
@ -47,6 +47,6 @@ window.toPlaces = toPlaces;
window.formatSmall = formatSmall;
window.formatLimit = formatLimit;
window.invertOOM = invertOOM;
window.formatGain = formatGain
window.formatGain = formatGain;
export default Decimal;

View file

@ -196,7 +196,11 @@ export function invertOOM(x: DecimalSource): Decimal {
return x;
}
export function formatLimit(list: [DecimalSource, string][], unit: string, gainMultiplier: DecimalSource = Decimal.dOne): string {
export function formatLimit(
list: [DecimalSource, string][],
unit: string,
gainMultiplier: DecimalSource = Decimal.dOne
): string {
let num = list[0][0];
let str = list[0][1];
for (let i = 1; i < list.length; i++) {

View file

@ -39,7 +39,7 @@ export function createLazyProxy<T extends object, S extends T>(
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const val = (calculateObj() as any)[key];
if (val && typeof val === "object" && NonPersistent in val) {
if (val != null && typeof val === "object" && NonPersistent in val) {
return val[NonPersistent];
}
return val;

View file

@ -86,7 +86,7 @@ export function getUniqueID(): string {
i = 0;
do {
id = `${projInfo.id}-${i++}`;
} while (localStorage.getItem(id));
} while (localStorage.getItem(id) != null);
return id;
}
@ -107,7 +107,12 @@ export async function loadSave(playerObj: Partial<PlayerData>): Promise<void> {
getInitialLayers(playerObj).forEach(layer => addLayer(layer, playerObj));
playerObj = setupInitialStore(playerObj);
if (playerObj.offlineProd && playerObj.time && playerObj.devSpeed !== 0) {
if (
playerObj.offlineProd &&
playerObj.time != null &&
playerObj.time &&
playerObj.devSpeed !== 0
) {
if (playerObj.offlineTime == undefined) playerObj.offlineTime = 0;
playerObj.offlineTime += Math.min(
playerObj.offlineTime + (Date.now() - playerObj.time) / 1000,

View file

@ -229,7 +229,10 @@ export function computeOptionalComponent(
const comp = shallowRef<Component | "" | null>(null);
watchEffect(() => {
const currComponent = unwrapRef(component);
comp.value = !currComponent ? null : coerceComponent(currComponent, defaultWrapper);
comp.value =
currComponent == "" || currComponent == null
? null
: coerceComponent(currComponent, defaultWrapper);
});
return comp;
}