mirror of
https://github.com/thepaperpilot/Advent-Incremental.git
synced 2024-12-03 13:21:31 +00:00
Settings update
This commit is contained in:
parent
f193d0f4b3
commit
3bdf33a4b6
13 changed files with 155 additions and 37 deletions
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
|
@ -6,7 +6,7 @@
|
||||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||||
"git.ignoreLimitWarning": true,
|
"git.ignoreLimitWarning": true,
|
||||||
"[typescriptreact]": {
|
"[typescriptreact]": {
|
||||||
"editor.defaultFormatter": "vscode.typescript-language-features"
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
},
|
},
|
||||||
"typescript.tsdk": "node_modules/typescript/lib"
|
"typescript.tsdk": "node_modules/typescript/lib"
|
||||||
}
|
}
|
|
@ -1,17 +1,26 @@
|
||||||
<template>
|
<template>
|
||||||
<Modal v-model="isOpen">
|
<Modal v-model="isOpen">
|
||||||
<template v-slot:header>
|
<template v-slot:header>
|
||||||
<h2>Options</h2>
|
<h2>Settings</h2>
|
||||||
|
<div class="option-tabs">
|
||||||
|
<button :class="{selected: isTab('behaviour')}" @click="setTab('behaviour')">Behaviour</button>
|
||||||
|
<button :class="{selected: isTab('appearance')}" @click="setTab('appearance')">Appearance</button>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template v-slot:body>
|
<template v-slot:body>
|
||||||
<Select title="Theme" :options="themes" v-model="theme" />
|
<div v-if="isTab('behaviour')">
|
||||||
<component :is="settingFieldsComponent" />
|
<Toggle :title="autosaveTitle" v-model="autosave" />
|
||||||
<Toggle title="Show TPS" v-model="showTPS" />
|
<FeedbackButton v-if="!autosave" class="button save-button" @click="save()">Manually save</FeedbackButton>
|
||||||
<hr />
|
<Toggle v-if="projInfo.enablePausing" :title="isPausedTitle" v-model="isPaused" />
|
||||||
<Toggle :title="autosaveTitle" v-model="autosave" />
|
<Toggle :title="autoPauseTitle" v-model="autoPause" />
|
||||||
<Toggle v-if="projInfo.enablePausing" :title="isPausedTitle" v-model="isPaused" />
|
</div>
|
||||||
<Toggle :title="progressMethodTitle" v-model="usingLog" />
|
<div v-if="isTab('appearance')">
|
||||||
<Toggle :title="alignModifierUnitsTitle" v-model="alignUnits" />
|
<Select :title="themeTitle" :options="themes" v-model="theme" />
|
||||||
|
<component :is="settingFieldsComponent" />
|
||||||
|
<Toggle :title="showTPSTitle" v-model="showTPS" />
|
||||||
|
<Toggle :title="progressMethodTitle" v-model="usingLog" />
|
||||||
|
<Toggle :title="alignModifierUnitsTitle" v-model="alignUnits" />
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</Modal>
|
</Modal>
|
||||||
</template>
|
</template>
|
||||||
|
@ -25,19 +34,36 @@ import Tooltip from "features/tooltips/Tooltip.vue";
|
||||||
import player from "game/player";
|
import player from "game/player";
|
||||||
import settings, { settingFields } from "game/settings";
|
import settings, { settingFields } from "game/settings";
|
||||||
import { camelToTitle } from "util/common";
|
import { camelToTitle } from "util/common";
|
||||||
|
import { save } from "util/save";
|
||||||
import { coerceComponent, render } from "util/vue";
|
import { coerceComponent, render } from "util/vue";
|
||||||
import { computed, ref, toRefs } from "vue";
|
import { computed, ref, toRefs } from "vue";
|
||||||
import Select from "./fields/Select.vue";
|
import Select from "./fields/Select.vue";
|
||||||
import Toggle from "./fields/Toggle.vue";
|
import Toggle from "./fields/Toggle.vue";
|
||||||
|
import FeedbackButton from "./fields/FeedbackButton.vue";
|
||||||
|
|
||||||
const isOpen = ref(false);
|
const isOpen = ref(false);
|
||||||
|
|
||||||
|
const currentTab = ref("behaviour");
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
|
isTab,
|
||||||
|
setTab,
|
||||||
|
save() {
|
||||||
|
save();
|
||||||
|
},
|
||||||
open() {
|
open() {
|
||||||
isOpen.value = true;
|
isOpen.value = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function isTab (tab: string): boolean {
|
||||||
|
return tab == currentTab.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setTab (tab: string) {
|
||||||
|
currentTab.value = tab;
|
||||||
|
}
|
||||||
|
|
||||||
const themes = Object.keys(rawThemes).map(theme => ({
|
const themes = Object.keys(rawThemes).map(theme => ({
|
||||||
label: camelToTitle(theme),
|
label: camelToTitle(theme),
|
||||||
value: theme
|
value: theme
|
||||||
|
@ -47,8 +73,10 @@ const settingFieldsComponent = computed(() => {
|
||||||
return coerceComponent(jsx(() => <>{settingFields.map(render)}</>));
|
return coerceComponent(jsx(() => <>{settingFields.map(render)}</>));
|
||||||
});
|
});
|
||||||
|
|
||||||
const { showTPS, theme } = toRefs(settings);
|
const { showTPS, theme, usingLog, alignUnits } = toRefs(settings);
|
||||||
const { autosave, usingLog, alignUnits } = toRefs(player);
|
|
||||||
|
const { autosave, autoPause } = toRefs(player);
|
||||||
|
|
||||||
const isPaused = computed({
|
const isPaused = computed({
|
||||||
get() {
|
get() {
|
||||||
return player.devSpeed === 0;
|
return player.devSpeed === 0;
|
||||||
|
@ -58,32 +86,85 @@ const isPaused = computed({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
const autosaveTitle = jsx(() => (
|
const autosaveTitle = jsx(() => (
|
||||||
<span>
|
<span class="option-title">
|
||||||
Autosave<Tooltip display="Save-specific">*</Tooltip>
|
Autosave<Tooltip display="Save-specific">*</Tooltip>
|
||||||
|
<desc>Automatically save the game every second or when the game is closed.</desc>
|
||||||
</span>
|
</span>
|
||||||
));
|
));
|
||||||
const isPausedTitle = jsx(() => (
|
const isPausedTitle = jsx(() => (
|
||||||
<span>
|
<span class="option-title">
|
||||||
Pause game<Tooltip display="Save-specific">*</Tooltip>
|
Pause game<Tooltip display="Save-specific">*</Tooltip>
|
||||||
|
<desc>Stop everything from moving.</desc>
|
||||||
|
</span>
|
||||||
|
));
|
||||||
|
const autoPauseTitle = jsx(() => (
|
||||||
|
<span class="option-title">
|
||||||
|
Auto-pause<Tooltip display="Save-specific">*</Tooltip>
|
||||||
|
<desc>Automatically pause the game when a day is completed. It is best to keep this on to avoid over-grinding.</desc>
|
||||||
|
</span>
|
||||||
|
));
|
||||||
|
|
||||||
|
const themeTitle = jsx(() => (
|
||||||
|
<span class="option-title">
|
||||||
|
Theme
|
||||||
|
<desc>How the game looks.</desc>
|
||||||
|
</span>
|
||||||
|
));
|
||||||
|
const showTPSTitle = jsx(() => (
|
||||||
|
<span class="option-title">
|
||||||
|
Show TPS
|
||||||
|
<desc>Show TPS meter at the bottom-left corner of the page.</desc>
|
||||||
</span>
|
</span>
|
||||||
));
|
));
|
||||||
const progressMethodTitle = jsx(() => (
|
const progressMethodTitle = jsx(() => (
|
||||||
<span>
|
<span class="option-title">
|
||||||
Logarithmic progress bars<Tooltip display="Save-specific">*</Tooltip>
|
Logarithmic progress bars
|
||||||
|
<desc>Whether progress bars should be normalized for exponential growth.</desc>
|
||||||
</span>
|
</span>
|
||||||
));
|
));
|
||||||
const alignModifierUnitsTitle = jsx(() => (
|
const alignModifierUnitsTitle = jsx(() => (
|
||||||
<span>
|
<span class="option-title">
|
||||||
Align modifier units<Tooltip display="Save-specific">*</Tooltip>
|
Align modifier units
|
||||||
|
<desc>Align numbers to the beginning of the unit in modifier view.</desc>
|
||||||
</span>
|
</span>
|
||||||
));
|
));
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style>
|
||||||
|
.option-tabs {
|
||||||
|
border-bottom: 2px solid var(--outline);
|
||||||
|
}
|
||||||
|
|
||||||
*:deep() .tooltip-container {
|
.option-tabs button {
|
||||||
|
background-color: transparent;
|
||||||
|
color: var(--foreground);
|
||||||
|
margin-bottom: -2px;
|
||||||
|
font-size: 14px;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 5px 20px;
|
||||||
|
border: none;
|
||||||
|
border-bottom: 2px solid var(--foreground);
|
||||||
|
}
|
||||||
|
|
||||||
|
.option-tabs button:not(.selected) {
|
||||||
|
border-bottom-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.option-title .tooltip-container {
|
||||||
display: inline;
|
display: inline;
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
}
|
}
|
||||||
|
.option-title desc {
|
||||||
|
display: block;
|
||||||
|
opacity: 0.6;
|
||||||
|
font-size: small;
|
||||||
|
width: 300px;
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.save-button {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -8,10 +8,13 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.modifier-amount {
|
.modifier-amount {
|
||||||
flex-basis: 100px;
|
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
:not(:first-of-type, :last-of-type) > .modifier-amount::after {
|
||||||
|
content: var(--unit);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.modifier-description {
|
.modifier-description {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
|
|
|
@ -87,6 +87,10 @@ function onUpdate(value: SelectOption) {
|
||||||
background-color: var(--bought);
|
background-color: var(--bought);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.vue-input input {
|
||||||
|
font-size: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
.vue-input input::placeholder {
|
.vue-input input::placeholder {
|
||||||
color: var(--link);
|
color: var(--link);
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,14 +44,16 @@ input {
|
||||||
|
|
||||||
span {
|
span {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
padding-right: 41px;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* track */
|
/* track */
|
||||||
input + span::before {
|
input + span::before {
|
||||||
content: "";
|
content: "";
|
||||||
float: right;
|
position: absolute;
|
||||||
margin: 5px 0 5px 10px;
|
top: calc(50% - 7px);
|
||||||
|
right: 0px;
|
||||||
border-radius: 7px;
|
border-radius: 7px;
|
||||||
width: 36px;
|
width: 36px;
|
||||||
height: 14px;
|
height: 14px;
|
||||||
|
@ -66,7 +68,7 @@ input + span::before {
|
||||||
input + span::after {
|
input + span::after {
|
||||||
content: "";
|
content: "";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 2px;
|
top: calc(50% - 10px);
|
||||||
right: 16px;
|
right: 16px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
width: 20px;
|
width: 20px;
|
||||||
|
|
|
@ -20,6 +20,7 @@ import type { Modifier } from "game/modifiers";
|
||||||
import type { Persistent } from "game/persistence";
|
import type { Persistent } from "game/persistence";
|
||||||
import { DefaultValue, persistent } from "game/persistence";
|
import { DefaultValue, persistent } from "game/persistence";
|
||||||
import player from "game/player";
|
import player from "game/player";
|
||||||
|
import settings from "game/settings";
|
||||||
import type { DecimalSource } from "util/bignum";
|
import type { DecimalSource } from "util/bignum";
|
||||||
import Decimal, { format } from "util/bignum";
|
import Decimal, { format } from "util/bignum";
|
||||||
import { formatWhole } from "util/break_eternity";
|
import { formatWhole } from "util/break_eternity";
|
||||||
|
@ -333,7 +334,7 @@ export function createCollapsibleModifierSections(
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{hasPreviousSection ? <br /> : null}
|
{hasPreviousSection ? <br /> : null}
|
||||||
<div>
|
<div style={{"--unit": settings.alignUnits && s.unit ? "'" + s.unit + "'" : ""}}>
|
||||||
{header}
|
{header}
|
||||||
<br />
|
<br />
|
||||||
{modifiers}
|
{modifiers}
|
||||||
|
@ -424,7 +425,7 @@ export function setUpDailyProgressTracker(options: {
|
||||||
if (main.day.value !== options.day) return 1;
|
if (main.day.value !== options.day) return 1;
|
||||||
let progress = Decimal.add(total.value, 1);
|
let progress = Decimal.add(total.value, 1);
|
||||||
let requirement = options.goal;
|
let requirement = options.goal;
|
||||||
if (options.usingLog?.value ?? player.usingLog) {
|
if (options.usingLog?.value ?? settings.usingLog) {
|
||||||
progress = progress.log10();
|
progress = progress.log10();
|
||||||
requirement = Decimal.log10(requirement);
|
requirement = Decimal.log10(requirement);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1164,7 +1164,7 @@ const layer = createLayer(id, () => {
|
||||||
<h3>Build a Classroom</h3>
|
<h3>Build a Classroom</h3>
|
||||||
<div>
|
<div>
|
||||||
Hopefully it makes the school a bit less boring. Multiplies elves' XP gain by{" "}
|
Hopefully it makes the school a bit less boring. Multiplies elves' XP gain by{" "}
|
||||||
<Sqrt>Classrooms + 1</Sqrt>.
|
(Classrooms + 1)<sup>0.9</sup>.
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
You have {formatWhole(classrooms.amount.value)} classrooms, which are currently
|
You have {formatWhole(classrooms.amount.value)} classrooms, which are currently
|
||||||
|
|
|
@ -146,7 +146,7 @@ export const main = createLayer("main", function (this: BaseLayer) {
|
||||||
loreScene.value = -1;
|
loreScene.value = -1;
|
||||||
loreTitle.value = unref(layers[layer ?? "trees"]?.name ?? "");
|
loreTitle.value = unref(layers[layer ?? "trees"]?.name ?? "");
|
||||||
loreBody.value = story;
|
loreBody.value = story;
|
||||||
player.devSpeed = null;
|
if (player.autoPause) player.devSpeed = null;
|
||||||
showLoreModal.value = true;
|
showLoreModal.value = true;
|
||||||
}, 1000);
|
}, 1000);
|
||||||
}
|
}
|
||||||
|
@ -370,7 +370,7 @@ export const main = createLayer("main", function (this: BaseLayer) {
|
||||||
showLoreModal.value = true;
|
showLoreModal.value = true;
|
||||||
day.value++;
|
day.value++;
|
||||||
main.minimized.value = false;
|
main.minimized.value = false;
|
||||||
player.devSpeed = 0;
|
if (player.autoPause) player.devSpeed = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -299,7 +299,12 @@ globalBus.on("loadSettings", settings => {
|
||||||
registerSettingField(
|
registerSettingField(
|
||||||
jsx(() => (
|
jsx(() => (
|
||||||
<Toggle
|
<Toggle
|
||||||
title="Hide Maxed Challenges"
|
title={jsx(() => (
|
||||||
|
<span class="option-title">
|
||||||
|
Hide maxed challenges
|
||||||
|
<desc>Hide challenges that have been fully completed.</desc>
|
||||||
|
</span>
|
||||||
|
))}
|
||||||
onUpdate:modelValue={value => (settings.hideChallenges = value)}
|
onUpdate:modelValue={value => (settings.hideChallenges = value)}
|
||||||
modelValue={settings.hideChallenges}
|
modelValue={settings.hideChallenges}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -204,7 +204,12 @@ const msDisplayOptions = Object.values(MilestoneDisplay).map(option => ({
|
||||||
registerSettingField(
|
registerSettingField(
|
||||||
jsx(() => (
|
jsx(() => (
|
||||||
<Select
|
<Select
|
||||||
title="Show Milestones"
|
title={jsx(() => (
|
||||||
|
<span class="option-title">
|
||||||
|
Show milestones
|
||||||
|
<desc>Select which milestones to display based on criterias.</desc>
|
||||||
|
</span>
|
||||||
|
))}
|
||||||
options={msDisplayOptions}
|
options={msDisplayOptions}
|
||||||
onUpdate:modelValue={value => (settings.msDisplay = value as MilestoneDisplay)}
|
onUpdate:modelValue={value => (settings.msDisplay = value as MilestoneDisplay)}
|
||||||
modelValue={settings.msDisplay}
|
modelValue={settings.msDisplay}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import "components/common/modifiers.css";
|
import "components/common/modifiers.css";
|
||||||
import type { CoercableComponent } from "features/feature";
|
import type { CoercableComponent } from "features/feature";
|
||||||
import { jsx } from "features/feature";
|
import { jsx } from "features/feature";
|
||||||
|
import settings from "game/settings";
|
||||||
import type { DecimalSource } from "util/bignum";
|
import type { DecimalSource } from "util/bignum";
|
||||||
import Decimal, { format } from "util/bignum";
|
import Decimal, { format } from "util/bignum";
|
||||||
import type { WithRequired } from "util/common";
|
import type { WithRequired } from "util/common";
|
||||||
|
@ -9,6 +10,7 @@ import { convertComputable } from "util/computed";
|
||||||
import { createLazyProxy } from "util/proxies";
|
import { createLazyProxy } from "util/proxies";
|
||||||
import { renderJSX } from "util/vue";
|
import { renderJSX } from "util/vue";
|
||||||
import { computed, unref } from "vue";
|
import { computed, unref } from "vue";
|
||||||
|
import player from "./player";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An object that can be used to apply or unapply some modification to a number.
|
* An object that can be used to apply or unapply some modification to a number.
|
||||||
|
@ -272,7 +274,7 @@ export function createModifierSection(
|
||||||
baseText: CoercableComponent = "Base"
|
baseText: CoercableComponent = "Base"
|
||||||
) {
|
) {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div style={{"--unit": settings.alignUnits ? "'" + unit + "'" : ""}}>
|
||||||
<h3>
|
<h3>
|
||||||
{title}
|
{title}
|
||||||
{subtitle ? <span class="subtitle"> ({subtitle})</span> : null}
|
{subtitle ? <span class="subtitle"> ({subtitle})</span> : null}
|
||||||
|
|
|
@ -34,8 +34,9 @@ export interface PlayerData {
|
||||||
modVersion: string;
|
modVersion: string;
|
||||||
/** A dictionary of layer save data. */
|
/** A dictionary of layer save data. */
|
||||||
layers: Record<string, LayerData<unknown>>;
|
layers: Record<string, LayerData<unknown>>;
|
||||||
/** Whether to use log for progress toward finishing the day, or use linear. */
|
|
||||||
usingLog: boolean;
|
/** Should the game be paused when the player complete a day? */
|
||||||
|
autoPause: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The proxied player that is used to track NaN values. */
|
/** The proxied player that is used to track NaN values. */
|
||||||
|
@ -68,7 +69,8 @@ const state = reactive<PlayerData>({
|
||||||
modID: "",
|
modID: "",
|
||||||
modVersion: "",
|
modVersion: "",
|
||||||
layers: {},
|
layers: {},
|
||||||
usingLog: false
|
|
||||||
|
autoPause: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
/** Convert a player save data object into a JSON string. Unwraps refs. */
|
/** Convert a player save data object into a JSON string. Unwraps refs. */
|
||||||
|
|
|
@ -18,6 +18,13 @@ export interface Settings {
|
||||||
theme: Themes;
|
theme: Themes;
|
||||||
/** Whether or not to cap the project at 20 ticks per second. */
|
/** Whether or not to cap the project at 20 ticks per second. */
|
||||||
unthrottled: boolean;
|
unthrottled: boolean;
|
||||||
|
|
||||||
|
/** Game-specific settings */
|
||||||
|
|
||||||
|
/** Whether to use log for progress toward finishing the day, or use linear. */
|
||||||
|
usingLog: boolean;
|
||||||
|
/** Whether to align modifiers to the unit. */
|
||||||
|
alignUnits: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const state = reactive<Partial<Settings>>({
|
const state = reactive<Partial<Settings>>({
|
||||||
|
@ -25,7 +32,10 @@ const state = reactive<Partial<Settings>>({
|
||||||
saves: [],
|
saves: [],
|
||||||
showTPS: true,
|
showTPS: true,
|
||||||
theme: Themes.Nordic,
|
theme: Themes.Nordic,
|
||||||
unthrottled: false
|
unthrottled: false,
|
||||||
|
|
||||||
|
usingLog: false,
|
||||||
|
alignUnits: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
|
@ -57,7 +67,10 @@ export const hardResetSettings = (window.hardResetSettings = () => {
|
||||||
active: "",
|
active: "",
|
||||||
saves: [],
|
saves: [],
|
||||||
showTPS: true,
|
showTPS: true,
|
||||||
theme: Themes.Nordic
|
theme: Themes.Nordic,
|
||||||
|
|
||||||
|
usingLog: false,
|
||||||
|
alignUnits: false,
|
||||||
};
|
};
|
||||||
globalBus.emit("loadSettings", settings);
|
globalBus.emit("loadSettings", settings);
|
||||||
Object.assign(state, settings);
|
Object.assign(state, settings);
|
||||||
|
|
Loading…
Reference in a new issue