Making many design changes

This commit is contained in:
thepaperpilot 2023-04-22 14:31:30 -05:00
parent 2f97dbc58d
commit 286341e054
3 changed files with 181 additions and 75 deletions

View file

@ -1,4 +1,15 @@
.tooltip-inline-container, .nav-container {
.tooltip-inline-container > .tooltip-container { margin-top: -50px;
display: inline; text-align: left;
border-bottom: solid 1px var(--outline);
margin-left: -10px;
margin-right: -10px;
padding: 10px;
width: 100%;
}
.nav-segment {
border-right: solid 1px var(--outline);
padding-right: 10px;
margin-right: 10px;
} }

View file

@ -1,3 +1,4 @@
import Modal from "components/Modal.vue";
import StickyVue from "components/layout/Sticky.vue"; import StickyVue from "components/layout/Sticky.vue";
import { import {
BoardNode, BoardNode,
@ -7,26 +8,26 @@ import {
getUniqueNodeID getUniqueNodeID
} from "features/boards/board"; } from "features/boards/board";
import { jsx } from "features/feature"; import { jsx } from "features/feature";
import MainDisplay from "features/resources/MainDisplay.vue";
import { createResource, displayResource } from "features/resources/resource"; import { createResource, displayResource } from "features/resources/resource";
import TooltipVue from "features/tooltips/Tooltip.vue"; import { createTabFamily } from "features/tabs/tabFamily";
import Formula, { calculateCost } from "game/formulas/formulas"; import Formula, { calculateCost } from "game/formulas/formulas";
import type { BaseLayer, GenericLayer } from "game/layers"; import type { BaseLayer, GenericLayer } from "game/layers";
import { createLayer } from "game/layers"; import { createLayer } from "game/layers";
import { import { createMultiplicativeModifier, createSequentialModifier } from "game/modifiers";
createModifierSection,
createMultiplicativeModifier,
createSequentialModifier
} from "game/modifiers";
import { State } from "game/persistence"; import { State } from "game/persistence";
import type { Player } from "game/player"; import type { Player } from "game/player";
import player from "game/player"; import player from "game/player";
import Decimal, { DecimalSource } from "lib/break_eternity"; import Decimal, { DecimalSource } from "lib/break_eternity";
import { format, formatTime, formatWhole } from "util/bignum"; import { format, formatWhole } from "util/bignum";
import { Direction } from "util/common"; import { camelToTitle } from "util/common";
import { render } from "util/vue"; import { render } from "util/vue";
import { ComputedRef, computed, reactive } from "vue"; import { ComputedRef, computed, nextTick, reactive, ref, watch } from "vue";
import { useToast } from "vue-toastification";
import { createCollapsibleModifierSections } from "./common";
import "./main.css"; import "./main.css";
import settings from "game/settings";
const toast = useToast();
export interface ResourceState { export interface ResourceState {
type: Resources; type: Resources;
@ -61,21 +62,44 @@ export const main = createLayer("main", function (this: BaseLayer) {
const energy = createResource<DecimalSource>(0, "energy"); const energy = createResource<DecimalSource>(0, "energy");
const resourceLevelFormula = Formula.variable(0).add(1); const resourceLevelFormula = Formula.variable(0).add(1);
function getResourceLevelProgress(amount: DecimalSource) {
// Sub 10 and then manually sum until we go over amount const resourceNodes: ComputedRef<Record<Resources, BoardNode>> = computed(() =>
let currentLevel = Decimal.floor(resourceLevelFormula.invertIntegral(amount)) board.nodes.value.reduce((acc, curr) => {
.sub(10) if (curr.type === "resource") {
.clampMin(0); acc[(curr.state as unknown as ResourceState).type] = curr;
let summedCost = calculateCost(resourceLevelFormula, currentLevel, true, 0);
while (true) {
const nextCost = resourceLevelFormula.evaluate(currentLevel);
if (Decimal.add(summedCost, nextCost).lte(amount)) {
currentLevel = currentLevel.add(1);
summedCost = Decimal.add(summedCost, nextCost);
} else {
break;
} }
} return acc;
}, {} as Record<Resources, BoardNode>)
);
const resourceLevels = computed(() =>
resourceNames.reduce((acc, curr) => {
const amount =
(resourceNodes.value[curr]?.state as unknown as ResourceState | undefined)
?.amount ?? 0;
// Sub 10 and then manually sum until we go over amount
let currentLevel = Decimal.floor(resourceLevelFormula.invertIntegral(amount))
.sub(10)
.clampMin(0);
let summedCost = calculateCost(resourceLevelFormula, currentLevel, true, 0);
while (true) {
const nextCost = resourceLevelFormula.evaluate(currentLevel);
if (Decimal.add(summedCost, nextCost).lte(amount)) {
currentLevel = currentLevel.add(1);
summedCost = Decimal.add(summedCost, nextCost);
} else {
break;
}
}
acc[curr] = currentLevel;
return acc;
}, {} as Record<Resources, DecimalSource>)
);
function getResourceLevelProgress(resource: Resources) {
const amount =
(resourceNodes.value[resource]?.state as unknown as ResourceState | undefined)
?.amount ?? 0;
const currentLevel = resourceLevels.value[resource];
const requiredForCurrentLevel = calculateCost(resourceLevelFormula, currentLevel, true); const requiredForCurrentLevel = calculateCost(resourceLevelFormula, currentLevel, true);
const requiredForNextLevel = calculateCost( const requiredForNextLevel = calculateCost(
resourceLevelFormula, resourceLevelFormula,
@ -90,20 +114,71 @@ export const main = createLayer("main", function (this: BaseLayer) {
const resourceMinedCooldown: Partial<Record<Resources, number>> = reactive({}); const resourceMinedCooldown: Partial<Record<Resources, number>> = reactive({});
nextTick(() => {
resourceNames.forEach(resource => {
watch(
() => resourceLevels.value[resource],
(level, prevLevel) => {
if (Decimal.gt(level, prevLevel) && settings.active === player.id) {
toast.info(
<div>
<h3>
{Decimal.eq(level, 1)
? `${camelToTitle(resource)} discovered`
: `${camelToTitle(resource)} is now Level ${formatWhole(
level
)}`}
!
</h3>
<div>Energy gain is now 1.01x higher.</div>
</div>
);
}
}
);
});
});
const board = createBoard(board => ({ const board = createBoard(board => ({
startNodes: () => [{ position: { x: 0, y: 0 }, type: "mine", state: 0 }], startNodes: () => [
{ position: { x: 0, y: 0 }, type: "mine", state: 0 },
{ position: { x: 400, y: -400 }, type: "brokenFactory" }
],
types: { types: {
mine: { mine: {
shape: Shape.Diamond, shape: Shape.Diamond,
size: 50, size: 50,
title: "Mine", title: "🪨",
label: node => (node === board.selectedNode.value ? null : { text: "Click me!" }), label: node =>
node === board.selectedNode.value
? { text: "Mining..." }
: Object.keys(resourceNodes.value).length === 0
? { text: "Click me!" }
: null,
progress: node => progress: node =>
node == board.selectedNode.value node == board.selectedNode.value
? new Decimal(node.state as DecimalSource).toNumber() ? new Decimal(node.state as DecimalSource).toNumber()
: 0, : 0,
progressDisplay: ProgressDisplay.Outline, progressDisplay: ProgressDisplay.Outline,
progressColor: "var(--accent2)" progressColor: "var(--accent2)",
draggable: true
},
brokenFactory: {
shape: Shape.Diamond,
size: 50,
title: "🛠️",
label: node => (node === board.selectedNode.value ? { text: "Repair me!" } : null),
actionDistance: 80,
actions: [
{ id: "repair", icon: "build", tooltip: "Costs 1000 energy", onClick() {} }
],
draggable: true
},
factory: {
shape: Shape.Diamond,
size: 50,
title: "🛠️",
draggable: true
}, },
resource: { resource: {
shape: Shape.Circle, shape: Shape.Circle,
@ -111,7 +186,10 @@ export const main = createLayer("main", function (this: BaseLayer) {
title: node => (node.state as unknown as ResourceState).type, title: node => (node.state as unknown as ResourceState).type,
subtitle: node => formatWhole((node.state as unknown as ResourceState).amount), subtitle: node => formatWhole((node.state as unknown as ResourceState).amount),
progress: node => progress: node =>
getResourceLevelProgress((node.state as unknown as ResourceState).amount), getResourceLevelProgress((node.state as unknown as ResourceState).type),
// Make clicking resources a no-op so they can't be selected
// eslint-disable-next-line @typescript-eslint/no-empty-function
onClick() {},
progressDisplay: ProgressDisplay.Outline, progressDisplay: ProgressDisplay.Outline,
progressColor: "var(--accent3)", progressColor: "var(--accent3)",
draggable: true draggable: true
@ -136,15 +214,6 @@ export const main = createLayer("main", function (this: BaseLayer) {
} }
})); }));
const resourceNodes: ComputedRef<Record<Resources, BoardNode>> = computed(() =>
board.nodes.value.reduce((acc, curr) => {
if (curr.type === "resource") {
acc[(curr.state as unknown as ResourceState).type] = curr;
}
return acc;
}, {} as Record<Resources, BoardNode>)
);
function grantResource(type: Resources, amount: DecimalSource) { function grantResource(type: Resources, amount: DecimalSource) {
let node = resourceNodes.value[type]; let node = resourceNodes.value[type];
if (node == null) { if (node == null) {
@ -175,15 +244,11 @@ export const main = createLayer("main", function (this: BaseLayer) {
const energyModifier = createSequentialModifier(() => const energyModifier = createSequentialModifier(() =>
resourceNames.map(resource => resourceNames.map(resource =>
createMultiplicativeModifier(() => ({ createMultiplicativeModifier(() => ({
description: resource, description: () =>
multiplier: () => `${camelToTitle(resource)} (Lv. ${formatWhole(
Decimal.pow( resourceLevels.value[resource]
1.01, )})`,
resourceLevelFormula.invertIntegral( multiplier: () => Decimal.pow(1.01, resourceLevels.value[resource]),
(resourceNodes.value[resource]?.state as ResourceState | undefined)
?.amount ?? 0
)
),
enabled: () => enabled: () =>
resource in resourceNodes.value && resource in resourceNodes.value &&
Decimal.gt( Decimal.gt(
@ -195,14 +260,36 @@ export const main = createLayer("main", function (this: BaseLayer) {
) )
); );
const computedEnergyModifier = computed(() => energyModifier.apply(1)); const computedEnergyModifier = computed(() => energyModifier.apply(1));
const energyGainTooltip = jsx(() =>
createModifierSection({ const [energyTab, energyTabCollapsed] = createCollapsibleModifierSections(() => [
{
title: "Energy Gain", title: "Energy Gain",
modifier: energyModifier, modifier: energyModifier,
base: 1, base: 1,
unit: "/s" unit: "/s"
}
]);
const modifierTabs = createTabFamily({
general: () => ({
display: "Energy",
glowColor(): string {
return modifierTabs.activeTab.value === this.tab ? "white" : "";
},
tab: energyTab,
energyTabCollapsed
}) })
); });
const showModifiersModal = ref(false);
const modifiersModal = jsx(() => (
<Modal
modelValue={showModifiersModal.value}
onUpdate:modelValue={(value: boolean) => (showModifiersModal.value = value)}
v-slots={{
header: () => <h2>Modifiers</h2>,
body: () => render(modifierTabs)
}}
/>
));
this.on("preUpdate", diff => { this.on("preUpdate", diff => {
Object.keys(resourceMinedCooldown).forEach(resource => { Object.keys(resourceMinedCooldown).forEach(resource => {
@ -255,32 +342,40 @@ export const main = createLayer("main", function (this: BaseLayer) {
name: "World", name: "World",
board, board,
energy, energy,
modifierTabs,
display: jsx(() => ( display: jsx(() => (
<> <>
{player.devSpeed === 0 ? <div>Game Paused</div> : null} <StickyVue class="nav-container">
{player.devSpeed != null && player.devSpeed !== 0 && player.devSpeed !== 1 ? ( <span class="nav-segment">
<div>Dev Speed: {format(player.devSpeed)}x</div> <h2 style="color: white; text-shadow: 0px 0px 10px white;">
) : null} {displayResource(energy)}
{player.offlineTime != null && player.offlineTime !== 0 ? ( </h2>{" "}
<div>Offline Time: {formatTime(player.offlineTime)}</div> energy
) : null} </span>
<MainDisplay resource={energy} /> <span class="nav-segment">
<StickyVue style="margin-top: -20px"> (
You are gaining{" "} <h3 style="color: white; text-shadow: 0px 0px 10px white;">
<span class="tooltip-inline-container"> +{format(computedEnergyModifier.value)}
<TooltipVue </h3>
display={energyGainTooltip} /s)
direction={Direction.Down} </span>
style="width: 200px; text-align: left" <span class="nav-segment">
<button
class="button"
style="display: inline"
onClick={() => (showModifiersModal.value = true)}
> >
<h3 style="color: white; text-shadow: 0px 0px 10px white;"> open modifiers
{displayResource(energy, computedEnergyModifier.value)} </button>
</h3> </span>
</TooltipVue> {player.devSpeed === 0 ? (
</span>{" "} <span class="nav-segment">Game Paused</span>
energy/sec{" "} ) : player.devSpeed != null && player.devSpeed !== 1 ? (
<span class="nav-segment">Dev Speed: {format(player.devSpeed)}x</span>
) : null}
</StickyVue> </StickyVue>
{render(board)} {render(board)}
{render(modifiersModal)}
</> </>
)) ))
}; };

View file

@ -20,7 +20,7 @@
"initialTabs": [ "main" ], "initialTabs": [ "main" ],
"maxTickLength": 3600, "maxTickLength": 3600,
"offlineLimit": 1, "offlineLimit": 0,
"enablePausing": true, "enablePausing": true,
"exportEncoding": "base64" "exportEncoding": "base64"
} }