forked from profectus/Profectus
Make layers lazy instantiate
This commit is contained in:
parent
90e49e196f
commit
067ba6ce90
8 changed files with 929 additions and 909 deletions
|
@ -118,6 +118,7 @@ export type LayerTreeNode<T extends LayerTreeNodeOptions> = Replace<
|
|||
append: ProcessedComputable<boolean>;
|
||||
}
|
||||
>;
|
||||
export type GenericLayerTreeNode = LayerTreeNode<LayerTreeNodeOptions>;
|
||||
|
||||
export function createLayerTreeNode<T extends LayerTreeNodeOptions>(options: T): LayerTreeNode<T> {
|
||||
processComputable(options as T, "append");
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import Tooltip from "@/components/system/Tooltip.vue";
|
||||
import { points as mainPoints } from "@/data/mod";
|
||||
import { main } from "@/data/mod";
|
||||
import { createAchievement } from "@/features/achievement";
|
||||
import { createGrid } from "@/features/grid";
|
||||
import { createResource } from "@/features/resource";
|
||||
|
@ -8,108 +8,110 @@ import { createLayer } from "@/game/layers";
|
|||
import { DecimalSource } from "@/lib/break_eternity";
|
||||
import Decimal from "@/util/bignum";
|
||||
import { render, renderRow } from "@/util/vue";
|
||||
import { points as fPoints } from "./f";
|
||||
import f from "./f";
|
||||
|
||||
const id = "a";
|
||||
const color = "yellow";
|
||||
const name = "Achievements";
|
||||
const points = createResource<DecimalSource>(0, "achievement power");
|
||||
const layer = createLayer(() => {
|
||||
const id = "a";
|
||||
const color = "yellow";
|
||||
const name = "Achievements";
|
||||
const points = createResource<DecimalSource>(0, "achievement power");
|
||||
|
||||
export const treeNode = createTreeNode({
|
||||
tooltip: "Achievements",
|
||||
onClick() {
|
||||
// TODO open this layer as a modal
|
||||
}
|
||||
});
|
||||
|
||||
const ach1 = createAchievement({
|
||||
image: "https://unsoftcapped2.github.io/The-Modding-Tree-2/discord.png",
|
||||
display: "Get me!",
|
||||
tooltip() {
|
||||
if (this.earned.value) {
|
||||
return "You did it!";
|
||||
const treeNode = createTreeNode({
|
||||
tooltip: "Achievements",
|
||||
onClick() {
|
||||
// TODO open this layer as a modal
|
||||
}
|
||||
return "How did this happen?";
|
||||
},
|
||||
shouldEarn: true
|
||||
});
|
||||
const ach2 = createAchievement({
|
||||
display: "Impossible!",
|
||||
tooltip() {
|
||||
if (this.earned.value) {
|
||||
return "HOW????";
|
||||
});
|
||||
|
||||
const ach1 = createAchievement({
|
||||
image: "https://unsoftcapped2.github.io/The-Modding-Tree-2/discord.png",
|
||||
display: "Get me!",
|
||||
tooltip() {
|
||||
if (this.earned.value) {
|
||||
return "You did it!";
|
||||
}
|
||||
return "How did this happen?";
|
||||
},
|
||||
shouldEarn: true
|
||||
});
|
||||
const ach2 = createAchievement({
|
||||
display: "Impossible!",
|
||||
tooltip() {
|
||||
if (this.earned.value) {
|
||||
return "HOW????";
|
||||
}
|
||||
return "Mwahahaha!";
|
||||
},
|
||||
style: { color: "#04e050" }
|
||||
});
|
||||
const ach3 = createAchievement({
|
||||
display: "EIEIO",
|
||||
tooltip:
|
||||
"Get a farm point.\n\nReward: The dinosaur is now your friend (you can max Farm Points).",
|
||||
shouldEarn: function () {
|
||||
return Decimal.gte(f.value.points.value, 1);
|
||||
},
|
||||
onComplete() {
|
||||
console.log("Bork bork bork!");
|
||||
}
|
||||
return "Mwahahaha!";
|
||||
},
|
||||
style: { color: "#04e050" }
|
||||
});
|
||||
const ach3 = createAchievement({
|
||||
display: "EIEIO",
|
||||
tooltip:
|
||||
"Get a farm point.\n\nReward: The dinosaur is now your friend (you can max Farm Points).",
|
||||
shouldEarn: function () {
|
||||
return Decimal.gte(fPoints.value, 1);
|
||||
},
|
||||
onComplete() {
|
||||
console.log("Bork bork bork!");
|
||||
}
|
||||
});
|
||||
const achievements = [ach1, ach2, ach3];
|
||||
});
|
||||
const achievements = [ach1, ach2, ach3];
|
||||
|
||||
const grid = createGrid({
|
||||
rows: 2,
|
||||
cols: 2,
|
||||
getStartState(id) {
|
||||
return id;
|
||||
},
|
||||
getStyle(id) {
|
||||
return { backgroundColor: `#${(Number(id) * 1234) % 999999}` };
|
||||
},
|
||||
// TODO display should return an object
|
||||
getTitle(id) {
|
||||
let direction;
|
||||
if (id === "101") {
|
||||
direction = "top";
|
||||
} else if (id === "102") {
|
||||
direction = "bottom";
|
||||
} else if (id === "201") {
|
||||
direction = "left";
|
||||
} else if (id === "202") {
|
||||
direction = "right";
|
||||
const grid = createGrid({
|
||||
rows: 2,
|
||||
cols: 2,
|
||||
getStartState(id) {
|
||||
return id;
|
||||
},
|
||||
getStyle(id) {
|
||||
return { backgroundColor: `#${(Number(id) * 1234) % 999999}` };
|
||||
},
|
||||
// TODO display should return an object
|
||||
getTitle(id) {
|
||||
let direction;
|
||||
if (id === "101") {
|
||||
direction = "top";
|
||||
} else if (id === "102") {
|
||||
direction = "bottom";
|
||||
} else if (id === "201") {
|
||||
direction = "left";
|
||||
} else if (id === "202") {
|
||||
direction = "right";
|
||||
}
|
||||
return (
|
||||
<Tooltip display={JSON.stringify(this.cells[id].style)} {...{ direction }}>
|
||||
<h3>Gridable #{id}</h3>
|
||||
</Tooltip>
|
||||
);
|
||||
},
|
||||
getDisplay(id) {
|
||||
return String(id);
|
||||
},
|
||||
getCanClick(): boolean {
|
||||
return Decimal.eq(main.value.points.value, 10);
|
||||
},
|
||||
onClick(id, state) {
|
||||
this.cells[id].state = Number(state) + 1;
|
||||
}
|
||||
return (
|
||||
<Tooltip display={JSON.stringify(this.cells[id].style)} {...{ direction }}>
|
||||
<h3>Gridable #{id}</h3>
|
||||
</Tooltip>
|
||||
);
|
||||
},
|
||||
getDisplay(id) {
|
||||
return String(id);
|
||||
},
|
||||
getCanClick() {
|
||||
return Decimal.eq(mainPoints.value, 10);
|
||||
},
|
||||
onClick(id, state) {
|
||||
this.cells[id].state = Number(state) + 1;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const display = (
|
||||
<template>
|
||||
{renderRow(achievements)}
|
||||
{render(grid)}
|
||||
</template>
|
||||
);
|
||||
const display = (
|
||||
<template>
|
||||
{renderRow(achievements)}
|
||||
{render(grid)}
|
||||
</template>
|
||||
);
|
||||
|
||||
const layer = createLayer({
|
||||
id,
|
||||
color,
|
||||
name,
|
||||
points,
|
||||
achievements,
|
||||
grid,
|
||||
treeNode,
|
||||
display
|
||||
return {
|
||||
id,
|
||||
color,
|
||||
name,
|
||||
points,
|
||||
achievements,
|
||||
grid,
|
||||
treeNode,
|
||||
display
|
||||
};
|
||||
});
|
||||
|
||||
export default layer;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
|||
import MainDisplay from "@/components/features/MainDisplay.vue";
|
||||
import { createLayerTreeNode, createResetButton } from "@/data/common";
|
||||
import { points as mainPoints, tree as mainTree } from "@/data/mod";
|
||||
import { main } from "@/data/mod";
|
||||
import { createClickable } from "@/features/clickable";
|
||||
import { createExponentialScaling, createIndependentConversion } from "@/features/conversion";
|
||||
import { persistent } from "@/features/feature";
|
||||
|
@ -10,169 +10,169 @@ import { createResource, displayResource } from "@/features/resource";
|
|||
import { createLayer, getLayer } from "@/game/layers";
|
||||
import Decimal, { DecimalSource, formatWhole } from "@/util/bignum";
|
||||
import { render } from "@/util/vue";
|
||||
import { otherThingy } from "./c";
|
||||
import c from "./c";
|
||||
|
||||
const f = getLayer("f");
|
||||
const layer = createLayer(() => {
|
||||
const id = "f";
|
||||
const color = "#FE0102";
|
||||
const name = "Farms";
|
||||
const points = createResource<DecimalSource>(0, "farm points");
|
||||
const boop = persistent<boolean>(false);
|
||||
|
||||
const id = "f";
|
||||
const color = "#FE0102";
|
||||
const name = "Farms";
|
||||
export const points = createResource<DecimalSource>(0, "farm points");
|
||||
export const boop = persistent<boolean>(false);
|
||||
const coolInfo = createInfobox({
|
||||
title: "Lore",
|
||||
titleStyle: { color: "#FE0000" },
|
||||
display: "DEEP LORE!",
|
||||
bodyStyle: { backgroundColor: "#0000EE" }
|
||||
});
|
||||
|
||||
const coolInfo = createInfobox({
|
||||
title: "Lore",
|
||||
titleStyle: { color: "#FE0000" },
|
||||
display: "DEEP LORE!",
|
||||
bodyStyle: { backgroundColor: "#0000EE" }
|
||||
});
|
||||
|
||||
const clickableState = persistent<string>("Start");
|
||||
const clickable = createClickable({
|
||||
display: {
|
||||
title: "Clicky clicky!",
|
||||
description() {
|
||||
return "Current state:<br>" + clickableState.value;
|
||||
const clickableState = persistent<string>("Start");
|
||||
const clickable = createClickable({
|
||||
display: {
|
||||
title: "Clicky clicky!",
|
||||
description() {
|
||||
return "Current state:<br>" + clickableState.value;
|
||||
}
|
||||
},
|
||||
initialState: "Start",
|
||||
canClick() {
|
||||
return clickableState.value !== "Borkened...";
|
||||
},
|
||||
onClick() {
|
||||
switch (clickableState.value) {
|
||||
case "Start":
|
||||
clickableState.value = "A new state!";
|
||||
break;
|
||||
case "A new state!":
|
||||
clickableState.value = "Keep going!";
|
||||
break;
|
||||
case "Keep going!":
|
||||
clickableState.value = "Maybe that's a bit too far...";
|
||||
break;
|
||||
case "Maybe that's a bit too far...":
|
||||
//makeParticles(coolParticle, 4)
|
||||
clickableState.value = "Borkened...";
|
||||
break;
|
||||
default:
|
||||
clickableState.value = "Start";
|
||||
break;
|
||||
}
|
||||
},
|
||||
onHold() {
|
||||
console.log("Clickkkkk...");
|
||||
},
|
||||
style() {
|
||||
switch (clickableState.value) {
|
||||
case "Start":
|
||||
return { "background-color": "green" };
|
||||
case "A new state!":
|
||||
return { "background-color": "yellow" };
|
||||
case "Keep going!":
|
||||
return { "background-color": "orange" };
|
||||
case "Maybe that's a bit too far...":
|
||||
return { "background-color": "red" };
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
}
|
||||
},
|
||||
initialState: "Start",
|
||||
canClick() {
|
||||
return clickableState.value !== "Borkened...";
|
||||
},
|
||||
onClick() {
|
||||
switch (clickableState.value) {
|
||||
case "Start":
|
||||
clickableState.value = "A new state!";
|
||||
break;
|
||||
case "A new state!":
|
||||
clickableState.value = "Keep going!";
|
||||
break;
|
||||
case "Keep going!":
|
||||
clickableState.value = "Maybe that's a bit too far...";
|
||||
break;
|
||||
case "Maybe that's a bit too far...":
|
||||
//makeParticles(coolParticle, 4)
|
||||
clickableState.value = "Borkened...";
|
||||
break;
|
||||
default:
|
||||
});
|
||||
|
||||
const resetClickable = createClickable({
|
||||
onClick() {
|
||||
if (clickableState.value == "Borkened...") {
|
||||
clickableState.value = "Start";
|
||||
break;
|
||||
}
|
||||
},
|
||||
display() {
|
||||
return clickableState.value == "Borkened..." ? "Fix the clickable!" : "Does nothing";
|
||||
}
|
||||
},
|
||||
onHold() {
|
||||
console.log("Clickkkkk...");
|
||||
},
|
||||
style() {
|
||||
switch (clickableState.value) {
|
||||
case "Start":
|
||||
return { "background-color": "green" };
|
||||
case "A new state!":
|
||||
return { "background-color": "yellow" };
|
||||
case "Keep going!":
|
||||
return { "background-color": "orange" };
|
||||
case "Maybe that's a bit too far...":
|
||||
return { "background-color": "red" };
|
||||
default:
|
||||
return {};
|
||||
});
|
||||
|
||||
const reset = createReset({
|
||||
thingsToReset: () => [getLayer("f")]
|
||||
});
|
||||
|
||||
const conversion = createIndependentConversion({
|
||||
scaling: createExponentialScaling(10, 3, 0.5),
|
||||
baseResource: main.value.points,
|
||||
gainResource: points,
|
||||
modifyGainAmount: gain => Decimal.times(gain, c.value.otherThingy.value)
|
||||
});
|
||||
|
||||
const treeNode = createLayerTreeNode({
|
||||
layerID: id,
|
||||
color,
|
||||
reset,
|
||||
tooltip() {
|
||||
if (treeNode.canClick.value) {
|
||||
return `${displayResource(points)} ${points.displayName}`;
|
||||
}
|
||||
return `This weird farmer dinosaur will only see you if you have at least 10 points. You only have ${displayResource(
|
||||
main.value.points
|
||||
)}`;
|
||||
},
|
||||
canClick() {
|
||||
return Decimal.gte(main.value.points.value, 10);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const resetClickable = createClickable({
|
||||
onClick() {
|
||||
if (clickableState.value == "Borkened...") {
|
||||
clickableState.value = "Start";
|
||||
const resetButton = createResetButton({
|
||||
conversion,
|
||||
tree: main.value.tree,
|
||||
treeNode,
|
||||
display() {
|
||||
if (this.conversion.buyMax) {
|
||||
return (
|
||||
<span>
|
||||
Hi! I'm a <u>weird dinosaur</u> and I'll give you{" "}
|
||||
<b>{formatWhole(this.conversion.currentGain.value)}</b> Farm Points in
|
||||
exchange for all of your points and lollipops! (You'll get another one at{" "}
|
||||
{formatWhole(this.conversion.nextAt.value)} points)
|
||||
</span>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<span>
|
||||
Hi! I'm a <u>weird dinosaur</u> and I'll give you a Farm Point in exchange
|
||||
for all of your points and lollipops! (At least{" "}
|
||||
{formatWhole(this.conversion.nextAt.value)} points)
|
||||
</span>
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
display() {
|
||||
return clickableState.value == "Borkened..." ? "Fix the clickable!" : "Does nothing";
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const reset = createReset({
|
||||
thingsToReset: () => [f()]
|
||||
});
|
||||
const tab = (): JSX.Element => (
|
||||
<template>
|
||||
{render(coolInfo)}
|
||||
<MainDisplay resource={points} color={color} />
|
||||
{render(resetButton)}
|
||||
<div>You have {formatWhole(conversion.baseResource.value)} points</div>
|
||||
<div>
|
||||
<br />
|
||||
<img src="https://images.beano.com/store/24ab3094eb95e5373bca1ccd6f330d4406db8d1f517fc4170b32e146f80d?auto=compress%2Cformat&dpr=1&w=390" />
|
||||
<div>Bork Bork!</div>
|
||||
</div>
|
||||
{render(clickable)}
|
||||
</template>
|
||||
);
|
||||
|
||||
const conversion = createIndependentConversion({
|
||||
scaling: createExponentialScaling(10, 3, 0.5),
|
||||
baseResource: mainPoints,
|
||||
gainResource: points,
|
||||
modifyGainAmount: gain => Decimal.times(gain, otherThingy.value)
|
||||
});
|
||||
|
||||
export const treeNode = createLayerTreeNode({
|
||||
layerID: id,
|
||||
color,
|
||||
reset,
|
||||
tooltip() {
|
||||
if (treeNode.canClick.value) {
|
||||
return `${displayResource(points)} ${points.displayName}`;
|
||||
}
|
||||
return `This weird farmer dinosaur will only see you if you have at least 10 points. You only have ${displayResource(
|
||||
mainPoints
|
||||
)}`;
|
||||
},
|
||||
canClick() {
|
||||
return Decimal.gte(mainPoints.value, 10);
|
||||
}
|
||||
});
|
||||
|
||||
const resetButton = createResetButton({
|
||||
conversion,
|
||||
tree: mainTree,
|
||||
treeNode,
|
||||
display() {
|
||||
if (this.conversion.buyMax) {
|
||||
return (
|
||||
<span>
|
||||
Hi! I'm a <u>weird dinosaur</u> and I'll give you{" "}
|
||||
<b>{formatWhole(this.conversion.currentGain.value)}</b> Farm Points in exchange
|
||||
for all of your points and lollipops! (You'll get another one at{" "}
|
||||
{formatWhole(this.conversion.nextAt.value)} points)
|
||||
</span>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<span>
|
||||
Hi! I'm a <u>weird dinosaur</u> and I'll give you a Farm Point in exchange for
|
||||
all of your points and lollipops! (At least{" "}
|
||||
{formatWhole(this.conversion.nextAt.value)} points)
|
||||
</span>
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export const tab = (): JSX.Element => (
|
||||
<template>
|
||||
{render(coolInfo)}
|
||||
<MainDisplay resource={points} color={color} />
|
||||
{render(resetButton)}
|
||||
<div>You have {formatWhole(conversion.baseResource.value)} points</div>
|
||||
<div>
|
||||
<br />
|
||||
<img src="https://images.beano.com/store/24ab3094eb95e5373bca1ccd6f330d4406db8d1f517fc4170b32e146f80d?auto=compress%2Cformat&dpr=1&w=390" />
|
||||
<div>Bork Bork!</div>
|
||||
</div>
|
||||
{render(clickable)}
|
||||
</template>
|
||||
);
|
||||
|
||||
const layer = createLayer({
|
||||
id,
|
||||
color,
|
||||
name,
|
||||
points,
|
||||
boop,
|
||||
coolInfo,
|
||||
clickable,
|
||||
clickableState,
|
||||
resetClickable,
|
||||
reset,
|
||||
conversion,
|
||||
treeNode,
|
||||
resetButton,
|
||||
display: tab
|
||||
return {
|
||||
id,
|
||||
color,
|
||||
name,
|
||||
points,
|
||||
boop,
|
||||
coolInfo,
|
||||
clickable,
|
||||
clickableState,
|
||||
resetClickable,
|
||||
reset,
|
||||
conversion,
|
||||
treeNode,
|
||||
resetButton,
|
||||
display: tab
|
||||
};
|
||||
});
|
||||
|
||||
export default layer;
|
||||
|
|
160
src/data/mod.tsx
160
src/data/mod.tsx
|
@ -10,97 +10,97 @@ import Decimal, { format, formatSmall, formatTime } from "@/util/bignum";
|
|||
import { render } from "@/util/vue";
|
||||
import { computed, ref } from "vue";
|
||||
import a from "./layers/aca/a";
|
||||
import c, {
|
||||
generatorUpgrade,
|
||||
lollipopMultiplierEffect,
|
||||
lollipopMultiplierUpgrade
|
||||
} from "./layers/aca/c";
|
||||
import c from "./layers/aca/c";
|
||||
import f from "./layers/aca/f";
|
||||
|
||||
export const points = createResource<DecimalSource>(0);
|
||||
const best = trackBest(points);
|
||||
const total = trackTotal(points);
|
||||
const oomps = trackOOMPS(points);
|
||||
const showModal = ref(false);
|
||||
export const main = createLayer(() => {
|
||||
const points = createResource<DecimalSource>(0);
|
||||
const best = trackBest(points);
|
||||
const total = trackTotal(points);
|
||||
const oomps = trackOOMPS(points);
|
||||
const showModal = ref(false);
|
||||
|
||||
const pointGain = computed(() => {
|
||||
if (!generatorUpgrade.bought) return new Decimal(0);
|
||||
let gain = new Decimal(3.19);
|
||||
if (lollipopMultiplierUpgrade.bought) gain = gain.times(lollipopMultiplierEffect.value);
|
||||
return gain;
|
||||
});
|
||||
globalBus.on("update", diff => {
|
||||
points.value = Decimal.add(points.value, Decimal.times(pointGain.value, diff));
|
||||
});
|
||||
const pointGain = computed(() => {
|
||||
if (!c.value.generatorUpgrade.bought) return new Decimal(0);
|
||||
let gain = new Decimal(3.19);
|
||||
if (c.value.lollipopMultiplierUpgrade.bought)
|
||||
gain = gain.times(c.value.lollipopMultiplierEffect.value);
|
||||
return gain;
|
||||
});
|
||||
globalBus.on("update", diff => {
|
||||
points.value = Decimal.add(points.value, Decimal.times(pointGain.value, diff));
|
||||
});
|
||||
|
||||
// Note: Casting as generic tree to avoid recursive type definitions
|
||||
export const tree = createTree({
|
||||
nodes: () => [[c.treeNode], [f.treeNode, c.spook]],
|
||||
leftSideNodes: [a.treeNode, c.h],
|
||||
branches: [
|
||||
{
|
||||
startNode: f.treeNode,
|
||||
endNode: c.treeNode,
|
||||
stroke: "blue",
|
||||
"stroke-width": "25px",
|
||||
style: {
|
||||
filter: "blur(5px)"
|
||||
}
|
||||
},
|
||||
{ startNode: c.treeNode, endNode: c.g }
|
||||
]
|
||||
}) as GenericTree;
|
||||
// Note: Casting as generic tree to avoid recursive type definitions
|
||||
const tree = createTree({
|
||||
nodes: [[c.value.treeNode], [f.value.treeNode, c.value.spook]],
|
||||
leftSideNodes: [a.value.treeNode, c.value.h],
|
||||
branches: [
|
||||
{
|
||||
startNode: f.value.treeNode,
|
||||
endNode: c.value.treeNode,
|
||||
stroke: "blue",
|
||||
"stroke-width": "25px",
|
||||
style: {
|
||||
filter: "blur(5px)"
|
||||
}
|
||||
},
|
||||
{ startNode: c.value.treeNode, endNode: c.value.g }
|
||||
]
|
||||
}) as GenericTree;
|
||||
|
||||
// Note: layers don't _need_ a reference to everything, but I'd recommend it over trying to remember
|
||||
// what does and doesn't need to be included. Officially all you need are anything with persistency
|
||||
export const main = createLayer({
|
||||
id: "main",
|
||||
name: "Tree",
|
||||
links: tree.links,
|
||||
display: (
|
||||
<template>
|
||||
<div v-show={player.devSpeed === 0}>Game Paused</div>
|
||||
<div v-show={player.devSpeed && player.devSpeed !== 1}>
|
||||
Dev Speed: {format(player.devSpeed || 0)}x
|
||||
</div>
|
||||
<div v-show={player.offlineTime != undefined}>
|
||||
Offline Time: {formatTime(player.offlineTime || 0)}
|
||||
</div>
|
||||
<div>
|
||||
<span v-show={Decimal.lt(points.value, "1e1000")}>You have </span>
|
||||
<h2>{format(points.value)}</h2>
|
||||
<span v-show={Decimal.lt(points.value, "1e1e6")}> points</span>
|
||||
</div>
|
||||
<div v-show={Decimal.gt(pointGain.value, 0)}>
|
||||
({oomps.value === "" ? formatSmall(pointGain.value) : oomps.value}/sec)
|
||||
</div>
|
||||
<Spacer />
|
||||
<Modal
|
||||
modelValue={showModal.value}
|
||||
onUpdate:modelValue={value => (showModal.value = value)}
|
||||
>
|
||||
<svg style="height: 80vmin; width: 80vmin;">
|
||||
<path d="M 32 222 Q 128 222, 128 0 Q 128 222, 224 222 L 224 224 L 32 224" />
|
||||
// Note: layers don't _need_ a reference to everything,
|
||||
// but I'd recommend it over trying to remember what does and doesn't need to be included.
|
||||
// Officially all you need are anything with persistency or that you want to access elsewhere
|
||||
return {
|
||||
id: "main",
|
||||
name: "Tree",
|
||||
links: tree.links,
|
||||
display: (
|
||||
<template>
|
||||
<div v-show={player.devSpeed === 0}>Game Paused</div>
|
||||
<div v-show={player.devSpeed && player.devSpeed !== 1}>
|
||||
Dev Speed: {format(player.devSpeed || 0)}x
|
||||
</div>
|
||||
<div v-show={player.offlineTime != undefined}>
|
||||
Offline Time: {formatTime(player.offlineTime || 0)}
|
||||
</div>
|
||||
<div>
|
||||
<span v-show={Decimal.lt(points.value, "1e1000")}>You have </span>
|
||||
<h2>{format(points.value)}</h2>
|
||||
<span v-show={Decimal.lt(points.value, "1e1e6")}> points</span>
|
||||
</div>
|
||||
<div v-show={Decimal.gt(pointGain.value, 0)}>
|
||||
({oomps.value === "" ? formatSmall(pointGain.value) : oomps.value}/sec)
|
||||
</div>
|
||||
<Spacer />
|
||||
<Modal
|
||||
modelValue={showModal.value}
|
||||
onUpdate:modelValue={value => (showModal.value = value)}
|
||||
>
|
||||
<svg style="height: 80vmin; width: 80vmin;">
|
||||
<path d="M 32 222 Q 128 222, 128 0 Q 128 222, 224 222 L 224 224 L 32 224" />
|
||||
|
||||
<circle cx="64" cy="128" r="64" fill="#8da8b0" />
|
||||
<circle cx="128" cy="64" r="64" fill="#71368a" />
|
||||
<circle cx="192" cy="128" r="64" fill="#fa8508" />
|
||||
</svg>
|
||||
</Modal>
|
||||
{render(tree)}
|
||||
</template>
|
||||
),
|
||||
points,
|
||||
best,
|
||||
total,
|
||||
oomps,
|
||||
tree
|
||||
<circle cx="64" cy="128" r="64" fill="#8da8b0" />
|
||||
<circle cx="128" cy="64" r="64" fill="#71368a" />
|
||||
<circle cx="192" cy="128" r="64" fill="#fa8508" />
|
||||
</svg>
|
||||
</Modal>
|
||||
{render(tree)}
|
||||
</template>
|
||||
),
|
||||
points,
|
||||
best,
|
||||
total,
|
||||
oomps,
|
||||
tree
|
||||
};
|
||||
});
|
||||
|
||||
export const getInitialLayers = (
|
||||
/* eslint-disable-next-line @typescript-eslint/no-unused-vars */
|
||||
player: Partial<PlayerData>
|
||||
): Array<GenericLayer> => [main, f, c, a];
|
||||
): Array<GenericLayer> => [main.value, f.value, c.value, a.value];
|
||||
|
||||
export const hasWon = computed(() => {
|
||||
return false;
|
||||
|
|
|
@ -37,7 +37,7 @@ type BuyableDisplay =
|
|||
export interface BuyableOptions {
|
||||
visibility?: Computable<Visibility>;
|
||||
cost?: Computable<DecimalSource>;
|
||||
resource?: Computable<Resource>;
|
||||
resource?: Resource;
|
||||
canPurchase?: Computable<boolean>;
|
||||
purchaseLimit?: Computable<DecimalSource>;
|
||||
classes?: Computable<Record<string, boolean>>;
|
||||
|
|
|
@ -34,7 +34,7 @@ export interface ChallengeOptions {
|
|||
canComplete?: Computable<boolean | DecimalSource>;
|
||||
completionLimit?: Computable<DecimalSource>;
|
||||
mark?: Computable<boolean | string>;
|
||||
resource?: Computable<Resource>;
|
||||
resource?: Resource;
|
||||
goal?: Computable<DecimalSource>;
|
||||
classes?: Computable<Record<string, boolean>>;
|
||||
style?: Computable<StyleValue>;
|
||||
|
@ -72,7 +72,6 @@ export type Challenge<T extends ChallengeOptions> = Replace<
|
|||
canComplete: GetComputableTypeWithDefault<T["canComplete"], Ref<boolean>>;
|
||||
completionLimit: GetComputableTypeWithDefault<T["completionLimit"], 1>;
|
||||
mark: GetComputableTypeWithDefault<T["mark"], Ref<boolean>>;
|
||||
resource: GetComputableType<T["resource"]>;
|
||||
goal: GetComputableType<T["goal"]>;
|
||||
classes: GetComputableType<T["classes"]>;
|
||||
style: GetComputableType<T["style"]>;
|
||||
|
@ -160,7 +159,7 @@ export function createChallenge<T extends ChallengeOptions>(
|
|||
if (!proxy.active.value || proxy.resource == null || proxy.goal == null) {
|
||||
return false;
|
||||
}
|
||||
return Decimal.gte(unref<Resource>(proxy.resource).value, unref(proxy.goal));
|
||||
return Decimal.gte(proxy.resource.value, unref(proxy.goal));
|
||||
});
|
||||
}
|
||||
if (challenge.mark == null) {
|
||||
|
@ -174,7 +173,6 @@ export function createChallenge<T extends ChallengeOptions>(
|
|||
processComputable(challenge as T, "completionLimit");
|
||||
setDefault(challenge, "completionLimit", 1);
|
||||
processComputable(challenge as T, "mark");
|
||||
processComputable(challenge as T, "resource");
|
||||
processComputable(challenge as T, "goal");
|
||||
processComputable(challenge as T, "classes");
|
||||
processComputable(challenge as T, "style");
|
||||
|
|
|
@ -17,6 +17,7 @@ import {
|
|||
} from "@/util/computed";
|
||||
import { createProxy } from "@/util/proxies";
|
||||
import { createNanoEvents, Emitter } from "nanoevents";
|
||||
import { customRef, Ref } from "vue";
|
||||
import { globalBus } from "./events";
|
||||
import player from "./player";
|
||||
|
||||
|
@ -81,27 +82,40 @@ export type GenericLayer = Replace<
|
|||
}
|
||||
>;
|
||||
|
||||
export function createLayer<T extends LayerOptions>(options: T): Layer<T> {
|
||||
const layer: T & Partial<BaseLayer> = options;
|
||||
export function createLayer<T extends LayerOptions>(optionsFunc: () => T): Ref<Layer<T>> {
|
||||
let layer: Layer<T> | null = null;
|
||||
|
||||
const emitter = (layer.emitter = createNanoEvents<LayerEvents>());
|
||||
layer.on = emitter.on.bind(emitter);
|
||||
layer.emit = emitter.emit.bind(emitter);
|
||||
return customRef(track => {
|
||||
return {
|
||||
get() {
|
||||
if (layer == undefined) {
|
||||
const partialLayer = optionsFunc() as T & Partial<BaseLayer>;
|
||||
const emitter = (partialLayer.emitter = createNanoEvents<LayerEvents>());
|
||||
partialLayer.on = emitter.on.bind(emitter);
|
||||
partialLayer.emit = emitter.emit.bind(emitter);
|
||||
|
||||
layer.minimized = persistent(false);
|
||||
partialLayer.minimized = persistent(false);
|
||||
|
||||
processComputable(layer as T, "color");
|
||||
processComputable(layer as T, "display");
|
||||
processComputable(layer as T, "name");
|
||||
setDefault(layer, "name", options.id);
|
||||
processComputable(layer as T, "minWidth");
|
||||
setDefault(layer, "minWidth", 600);
|
||||
processComputable(layer as T, "minimizable");
|
||||
setDefault(layer, "minimizable", true);
|
||||
processComputable(layer as T, "links");
|
||||
processComputable(partialLayer as T, "color");
|
||||
processComputable(partialLayer as T, "display");
|
||||
processComputable(partialLayer as T, "name");
|
||||
setDefault(partialLayer, "name", partialLayer.id);
|
||||
processComputable(partialLayer as T, "minWidth");
|
||||
setDefault(partialLayer, "minWidth", 600);
|
||||
processComputable(partialLayer as T, "minimizable");
|
||||
setDefault(partialLayer, "minimizable", true);
|
||||
processComputable(partialLayer as T, "links");
|
||||
|
||||
const proxy = createProxy(layer as unknown as Layer<T>);
|
||||
return proxy;
|
||||
layer = createProxy(partialLayer as unknown as Layer<T>);
|
||||
}
|
||||
track();
|
||||
return layer;
|
||||
},
|
||||
set() {
|
||||
console.error("Layers are read-only!");
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
export function addLayer(
|
||||
|
@ -127,8 +141,8 @@ export function addLayer(
|
|||
globalBus.emit("addLayer", layer, player.layers[layer.id]);
|
||||
}
|
||||
|
||||
export function getLayer<T extends GenericLayer>(layerID: string): () => T {
|
||||
return () => layers[layerID] as T;
|
||||
export function getLayer<T extends GenericLayer>(layerID: string): T {
|
||||
return layers[layerID] as T;
|
||||
}
|
||||
|
||||
export function removeLayer(layer: GenericLayer): void {
|
||||
|
|
Loading…
Reference in a new issue