+
@@ -88,8 +122,9 @@
diff --git a/src/data/layers/main.ts b/src/data/layers/main.ts
index 9b9f41b..d15d95c 100644
--- a/src/data/layers/main.ts
+++ b/src/data/layers/main.ts
@@ -4,36 +4,34 @@ import Decimal, { DecimalSource } from "@/lib/break_eternity";
import { RawLayer } from "@/typings/layer";
import { camelToTitle } from "@/util/common";
import themes from "../themes";
+import Main from "./Main.vue";
-type ResourceNodeData = {
+export type ResourceNodeData = {
resourceType: string;
amount: DecimalSource;
maxAmount: DecimalSource;
};
-type ItemNodeData = {
+export type ItemNodeData = {
itemType: string;
amount: DecimalSource;
};
-type ActionNodeData = {
+export type ActionNodeData = {
actionType: string;
+ log: string[];
};
export default {
id: "main",
- display: `
- Game Paused
- Dev Speed: {{ format(player.devSpeed) }}x
- TODO: Board
-
-
- `,
+ display: Main,
startData() {
return {
- openNode: null
+ openNode: null,
+ showModal: false
} as {
openNode: string | null;
+ showModal: boolean;
};
},
minimizable: false,
@@ -71,7 +69,8 @@ export default {
position: { x: -150, y: 150 },
type: "action",
data: {
- actionType: "browse"
+ actionType: "web",
+ log: []
}
}
];
@@ -101,31 +100,55 @@ export default {
canAccept(node, otherNode) {
return otherNode.type === "item";
},
+ onClick(node) {
+ player.layers.main.openNode = node.id;
+ player.layers.main.showModal = true;
+ },
onDrop(node, otherNode) {
- const index = player.layers[this.layer].boards[this.id].indexOf(
+ const index = player.layers[this.layer].boards[this.id].nodes.indexOf(
otherNode
);
- player.layers[this.layer].boards[this.id].splice(index, 1);
+ player.layers[this.layer].boards[this.id].nodes.splice(index, 1);
}
},
item: {
title(node) {
return (node.data as ItemNodeData).itemType;
},
+ onClick(node) {
+ player.layers.main.openNode = node.id;
+ player.layers.main.showModal = true;
+ },
draggable: true
},
action: {
title(node) {
return camelToTitle((node.data as ActionNodeData).actionType);
},
- fillColor() {
- return themes[player.theme].variables["--background-tooltip"];
- },
+ fillColor: "#000",
draggable: true,
shape: Shape.Diamond,
- size: 100,
progressColor: "#0FF3",
- progressDisplay: ProgressDisplay.Outline
+ progressDisplay: ProgressDisplay.Outline,
+ actions: [
+ {
+ id: "info",
+ icon: "history_edu",
+ tooltip: "Log",
+ onClick(node) {
+ player.layers.main.openNode = node.id;
+ player.layers.main.showModal = true;
+ }
+ },
+ {
+ id: "reddit",
+ icon: "reddit",
+ tooltip: "Browse Reddit",
+ onClick(node) {
+ // TODO
+ }
+ }
+ ]
}
}
}
diff --git a/src/game/gameLoop.ts b/src/game/gameLoop.ts
index 3016185..d6c3f52 100644
--- a/src/game/gameLoop.ts
+++ b/src/game/gameLoop.ts
@@ -68,10 +68,10 @@ function updateLayers(diff: DecimalSource) {
);
}
layers[layer].update?.(diff);
- if (layers[layer].boards) {
- Reflect.ownKeys(player.layers[layer].boards).forEach(board => {
- player.layers[layer].boards[board.toString()].forEach(node => {
- const nodeType = layers[layer].boards!.data[board.toString()].types[node.type];
+ if (layers[layer].boards && layers[layer].boards?.data) {
+ Object.values(layers[layer].boards!.data!).forEach(board => {
+ board.nodes.forEach(node => {
+ const nodeType = board.types[node.type];
nodeType.update?.(node, diff);
});
});
diff --git a/src/game/layers.ts b/src/game/layers.ts
index 998b91b..a1b62c1 100644
--- a/src/game/layers.ts
+++ b/src/game/layers.ts
@@ -432,6 +432,29 @@ export function addLayer(layer: RawLayer, player?: Partial): void {
for (const id in layer.boards.data) {
setDefault(layer.boards.data[id], "width", "100%");
setDefault(layer.boards.data[id], "height", "400px");
+ setDefault(layer.boards.data[id], "nodes", function() {
+ return playerProxy.layers[this.layer].boards[this.id].nodes;
+ });
+ setDefault(layer.boards.data[id], "selectedNode", function() {
+ return playerProxy.layers[this.layer].boards[this.id].nodes.find(
+ node => node.id === playerProxy.layers[this.layer].boards[this.id].selectedNode
+ );
+ });
+ setDefault(layer.boards.data[id], "selectedAction", function() {
+ if (this.selectedNode == null) {
+ return null;
+ }
+ const nodeType = layers[this.layer].boards!.data[this.id].types[
+ this.selectedNode.type
+ ];
+ if (nodeType.actions === null) {
+ return null;
+ }
+ if (typeof nodeType.actions === "function") {
+ return nodeType.actions(this.selectedNode);
+ }
+ return nodeType.actions;
+ });
for (const nodeType in layer.boards.data[id].types) {
layer.boards.data[id].types[nodeType].layer = layer.id;
layer.boards.data[id].types[nodeType].id = id;
@@ -440,16 +463,20 @@ export function addLayer(layer: RawLayer, player?: Partial): void {
setDefault(layer.boards.data[id].types[nodeType], "draggable", false);
setDefault(layer.boards.data[id].types[nodeType], "shape", Shape.Circle);
setDefault(layer.boards.data[id].types[nodeType], "canAccept", false);
+ setDefault(layer.boards.data[id].types[nodeType], "actionDistance", Math.PI / 6);
setDefault(
layer.boards.data[id].types[nodeType],
"progressDisplay",
ProgressDisplay.Fill
);
setDefault(layer.boards.data[id].types[nodeType], "nodes", function() {
- return playerProxy.layers[this.layer].boards[this.id].filter(
+ return playerProxy.layers[this.layer].boards[this.id].nodes.filter(
node => node.type === this.type
);
});
+ setDefault(layer.boards.data[id].types[nodeType], "onClick", function(node) {
+ playerProxy.layers[this.layer].boards[this.id].selectedNode = node.id;
+ });
}
}
}
diff --git a/src/typings/component.d.ts b/src/typings/component.d.ts
index 5b3c011..52620a1 100644
--- a/src/typings/component.d.ts
+++ b/src/typings/component.d.ts
@@ -1,3 +1,3 @@
-import { ComponentOptions } from "vue";
+import { Component, ComponentOptions } from "vue";
-export type CoercableComponent = string | ComponentOptions;
+export type CoercableComponent = string | ComponentOptions | Component;
diff --git a/src/typings/features/board.d.ts b/src/typings/features/board.d.ts
index 13e59ca..a10d348 100644
--- a/src/typings/features/board.d.ts
+++ b/src/typings/features/board.d.ts
@@ -13,9 +13,10 @@ export interface BoardNode {
data?: State;
}
-export interface CardOption {
- text: string;
- selected: (node: BoardNode) => void;
+export interface BoardData {
+ nodes: BoardNode[];
+ selectedNode: string | null;
+ selectedAction: string | null;
}
export interface Board extends Feature {
@@ -24,6 +25,9 @@ export interface Board extends Feature {
height: string;
width: string;
types: Record;
+ nodes: BoardNode[];
+ selectedNode: BoardNode | null;
+ selectedAction: BoardNodeAction | null;
}
export type RawBoard = Omit, "types" | "startNodes"> & {
@@ -43,8 +47,17 @@ export interface NodeType extends Feature {
fillColor?: string | ((node: BoardNode) => string);
outlineColor?: string | ((node: BoardNode) => string);
titleColor?: string | ((node: BoardNode) => string);
+ actions?: BoardNodeAction[] | ((node: BoardNode) => BoardNodeAction[]);
+ actionDistance: number | ((node: BoardNode) => number);
onClick?: (node: BoardNode) => void;
onDrop?: (node: BoardNode, otherNode: BoardNode) => void;
update?: (node: BoardNode, diff: DecimalSource) => void;
nodes: BoardNode[];
}
+
+export interface BoardNodeAction {
+ id: string;
+ icon: string;
+ tooltip: string;
+ onClick: (node: BoardNode) => void;
+}
diff --git a/src/typings/player.d.ts b/src/typings/player.d.ts
index dc54d03..c901591 100644
--- a/src/typings/player.d.ts
+++ b/src/typings/player.d.ts
@@ -1,7 +1,7 @@
import { Themes } from "@/data/themes";
import { DecimalSource } from "@/lib/break_eternity";
import Decimal from "@/util/bignum";
-import { BoardNode } from "./features/board";
+import { BoardData, BoardNode } from "./features/board";
import { MilestoneDisplay } from "./features/milestone";
import { State } from "./state";
@@ -62,7 +62,7 @@ export interface LayerSaveData {
clickables: Record;
challenges: Record;
grids: Record>;
- boards: Record;
+ boards: Record;
confirmRespecBuyables: boolean;
[index: string]: unknown;
}
diff --git a/src/util/layers.ts b/src/util/layers.ts
index d9be21b..ff4d011 100644
--- a/src/util/layers.ts
+++ b/src/util/layers.ts
@@ -1,7 +1,7 @@
import { hotkeys, layers } from "@/game/layers";
import player from "@/game/player";
import { CacheableFunction } from "@/typings/cacheableFunction";
-import { Board, BoardNode, RawBoard } from "@/typings/features/board";
+import { Board, BoardData, BoardNode, RawBoard } from "@/typings/features/board";
import { Buyable } from "@/typings/features/buyable";
import { Challenge } from "@/typings/features/challenge";
import { Clickable } from "@/typings/features/clickable";
@@ -73,17 +73,21 @@ export function getStartingChallenges(
export function getStartingBoards(
boards?: Record | Record | undefined
-): Record {
+): Record {
return boards
- ? Object.keys(boards).reduce((acc: Record, curr: string): Record<
+ ? Object.keys(boards).reduce((acc: Record, curr: string): Record<
string,
- BoardNode[]
+ BoardData
> => {
const nodes = boards[curr].startNodes?.() || [];
- acc[curr] = nodes.map((node, index) => ({
- id: index.toString(),
- ...node
- })) as BoardNode[];
+ acc[curr] = {
+ nodes: nodes.map((node, index) => ({
+ id: index.toString(),
+ ...node
+ })),
+ selectedNode: null,
+ selectedAction: null
+ } as BoardData;
return acc;
}, {})
: {};
diff --git a/src/util/proxies.ts b/src/util/proxies.ts
index 83c1c58..a541eeb 100644
--- a/src/util/proxies.ts
+++ b/src/util/proxies.ts
@@ -43,7 +43,8 @@ function travel(
object[key] = computed(object[key].bind(objectProxy));
} else if (
(isPlainObject(object[key]) || Array.isArray(object[key])) &&
- !(object[key] instanceof Decimal)
+ !(object[key] instanceof Decimal) &&
+ typeof object[key].render !== "function"
) {
object[key] = callback(object[key]);
}
@@ -62,7 +63,11 @@ const layerHandler: ProxyHandler> = {
if (isRef(target[key])) {
return target[key].value;
- } else if (target[key].isProxy || target[key] instanceof Decimal) {
+ } else if (
+ target[key].isProxy ||
+ target[key] instanceof Decimal ||
+ typeof target[key].render === "function"
+ ) {
return target[key];
} else if (
(isPlainObject(target[key]) || Array.isArray(target[key])) &&
diff --git a/src/util/vue.ts b/src/util/vue.ts
index 28f12ad..b3d953a 100644
--- a/src/util/vue.ts
+++ b/src/util/vue.ts
@@ -35,7 +35,7 @@ const data = function(): Record {
return { Decimal, player, layers, hasWon, pointGain, ...numberUtils };
};
export function coerceComponent(
- component: string | ComponentOptions,
+ component: string | ComponentOptions | Component,
defaultWrapper = "span"
): Component | string {
if (typeof component === "string") {