diff --git a/src/data/layers/prestige.tsx b/src/data/layers/prestige.tsx new file mode 100644 index 0000000..6e3cb69 --- /dev/null +++ b/src/data/layers/prestige.tsx @@ -0,0 +1,73 @@ +/** + * @module + * @hidden + */ +import { main } from "data/projEntry"; +import { createCumulativeConversion } from "features/conversion"; +import { jsx } from "features/feature"; +import { createHotkey } from "features/hotkey"; +import { createReset } from "features/reset"; +import MainDisplay from "features/resources/MainDisplay.vue"; +import { createResource } from "features/resources/resource"; +import { addTooltip } from "features/tooltips/tooltip"; +import { createResourceTooltip } from "features/trees/tree"; +import { BaseLayer, createLayer } from "game/layers"; +import type { DecimalSource } from "util/bignum"; +import { render } from "util/vue"; +import { createLayerTreeNode, createResetButton } from "../common"; + +const id = "p"; +const layer = createLayer(id, function (this: BaseLayer) { + const name = "Prestige"; + const color = "#4BDC13"; + const points = createResource(0, "prestige points"); + + const conversion = createCumulativeConversion(() => ({ + formula: x => x.div(10).sqrt(), + baseResource: main.points, + gainResource: points + })); + + const reset = createReset(() => ({ + thingsToReset: (): Record[] => [layer] + })); + + const treeNode = createLayerTreeNode(() => ({ + layerID: id, + color, + reset + })); + const tooltip = addTooltip(treeNode, { + display: createResourceTooltip(points), + pinnable: true + }); + + const resetButton = createResetButton(() => ({ + conversion, + tree: main.tree, + treeNode + })); + + const hotkey = createHotkey(() => ({ + description: "Reset for prestige points", + key: "p", + onPress: resetButton.onClick + })); + + return { + name, + color, + points, + tooltip, + display: jsx(() => ( + <> + + {render(resetButton)} + + )), + treeNode, + hotkey + }; +}); + +export default layer; diff --git a/src/data/projEntry.tsx b/src/data/projEntry.tsx index a52dcc3..f69ac8b 100644 --- a/src/data/projEntry.tsx +++ b/src/data/projEntry.tsx @@ -1,428 +1,92 @@ -import Board from "game/boards/Board.vue"; -import CircleProgress from "game/boards/CircleProgress.vue"; -import SVGNode from "game/boards/SVGNode.vue"; -import SquareProgress from "game/boards/SquareProgress.vue"; -import { - NodePosition, - makeDraggable, - placeInAvailableSpace, - setupActions, - setupDraggableNode, - setupUniqueIds -} from "game/boards/board"; +import Node from "components/Node.vue"; +import Spacer from "components/layout/Spacer.vue"; import { jsx } from "features/feature"; -import { createResource } from "features/resources/resource"; -import { createUpgrade } from "features/upgrades/upgrade"; +import { createResource, trackBest, trackOOMPS, trackTotal } from "features/resources/resource"; +import type { GenericTree } from "features/trees/tree"; +import { branchedResetPropagation, createTree } from "features/trees/tree"; +import { globalBus } from "game/events"; import type { BaseLayer, GenericLayer } from "game/layers"; import { createLayer } from "game/layers"; -import { Persistent, persistent } from "game/persistence"; import type { Player } from "game/player"; -import { createCostRequirement } from "game/requirements"; +import player from "game/player"; +import type { DecimalSource } from "util/bignum"; +import Decimal, { format, formatTime } from "util/bignum"; import { render } from "util/vue"; -import { ComponentPublicInstance, computed, ref, watch } from "vue"; -import { setupSelectable } from "./common"; -import "./common.css"; +import { computed, toRaw } from "vue"; +import prestige from "./layers/prestige"; /** * @hidden */ export const main = createLayer("main", function (this: BaseLayer) { - type ANode = NodePosition & { id: number; links: number[]; type: "anode"; z: number }; - type BNode = NodePosition & { id: number; links: number[]; type: "bnode"; z: number }; - type CNode = typeof cNode & { position: Persistent }; - type NodeTypes = ANode | BNode; + const points = createResource(10); + const best = trackBest(points); + const total = trackTotal(points); - const board = ref>(); - - const { select, deselect, selected } = setupSelectable(); - const { - select: selectAction, - deselect: deselectAction, - selected: selectedAction - } = setupSelectable(); - - watch(selected, selected => { - if (selected == null) { - deselectAction(); - } + const pointGain = computed(() => { + // eslint-disable-next-line prefer-const + let gain = new Decimal(1); + return gain; }); + globalBus.on("update", diff => { + points.value = Decimal.add(points.value, Decimal.times(pointGain.value, diff)); + }); + const oomps = trackOOMPS(points, pointGain); - const { - startDrag, - endDrag, - drag, - nodeBeingDragged, - hasDragged, - receivingNodes, - receivingNode, - dragDelta - } = setupDraggableNode({ - board, - getPosition(id) { - return nodesById.value[id] ?? (cNode as CNode).position.value; + const tree = createTree(() => ({ + nodes: [[prestige.treeNode]], + branches: [], + onReset() { + points.value = toRaw(this.resettingNode.value) === toRaw(prestige.treeNode) ? 0 : 10; + best.value = points.value; + total.value = points.value; }, - setPosition(id, position) { - const node = nodesById.value[id] ?? (cNode as CNode).position.value; - node.x = position.x; - node.y = position.y; - } - }); - - // a nodes can be slotted into b nodes to draw a branch between them, with limited connections - // a nodes can be selected and have an action to spawn a b node, and vice versa - // Newly spawned nodes should find a safe spot to spawn, and display a link to their creator - // a nodes use all the stuff circles used to have, and b diamonds - // c node also exists but is a single Upgrade element that cannot be selected, but can be dragged - // d nodes are a performance test - 1000 simple nodes that have no interactions - // Make all nodes animate in (decorator? `fadeIn(feature)?) - const nodes = persistent<(ANode | BNode)[]>([ - { id: 0, x: 0, y: 0, z: 0, links: [], type: "anode" } - ]); - const nodesById = computed>(() => - nodes.value.reduce((acc, curr) => ({ ...acc, [curr.id]: curr }), {}) - ); - function mouseDownNode(e: MouseEvent | TouchEvent, node: NodeTypes) { - const oldZ = node.z; - nodes.value.forEach(node => { - if (node.z > oldZ) { - node.z--; - } - }); - node.z = nextId.value; - if (nodeBeingDragged.value == null) { - startDrag(e, node.id); - } - deselect(); - } - function mouseUpNode(e: MouseEvent | TouchEvent, node: NodeTypes) { - if (!hasDragged.value) { - endDrag(); - if (typeof node.id === "number") { - select(node.id); - } - e.stopPropagation(); - } - } - function translate(node: NodePosition, isDragging: boolean) { - let x = node.x; - let y = node.y; - if (isDragging) { - x += dragDelta.value.x; - y += dragDelta.value.y; - } - return ` translate(${x}px,${y}px)`; - } - function rotate(rotation: number) { - return ` rotate(${rotation}deg) `; - } - function scale(nodeOrBool: NodeTypes | boolean) { - const isSelected = - typeof nodeOrBool === "boolean" ? nodeOrBool : selected.value === nodeOrBool.id; - return isSelected ? " scale(1.2)" : ""; - } - function opacity(node: NodeTypes) { - const isDragging = selected.value !== node.id && nodeBeingDragged.value === node.id; - if (isDragging) { - return "; opacity: 0.5;"; - } - return ""; - } - function zIndex(node: NodeTypes) { - if (selected.value === node.id || nodeBeingDragged.value === node.id) { - return "; z-index: 100000000"; - } - return "; z-index: " + node.z; - } - - const renderANode = function (node: ANode) { - return ( - mouseDownNode(e, node)} - onMouseUp={e => mouseUpNode(e, node)} - > - - {receivingNodes.value.includes(node.id) && ( - - )} - - - - {selected.value === node.id && selectedAction.value === 0 && ( - - Spawn B Node - - )} - - A - - - ); - }; - const aActions = setupActions({ - node: () => nodesById.value[selected.value ?? ""], - shouldShowActions: node => node.type === "anode", - actions(node) { - return [ - p => ( - { - if (selectedAction.value === 0) { - spawnBNode(node as ANode); - } else { - selectAction(0); - } - }} - > - - - add - - - ) - ]; - }, - distance: 100 - }); - const sqrtTwo = Math.sqrt(2); - const renderBNode = function (node: BNode) { - return ( - mouseDownNode(e, node)} - onMouseUp={e => mouseUpNode(e, node)} - > - - {receivingNodes.value.includes(node.id) && ( - - )} - - - - {selected.value === node.id && selectedAction.value === 0 && ( - - Spawn A Node - - )} - - B - - - ); - }; - const bActions = setupActions({ - node: () => nodesById.value[selected.value ?? ""], - shouldShowActions: node => node.type === "bnode", - actions(node) { - return [ - p => ( - { - if (selectedAction.value === 0) { - spawnANode(node as BNode); - } else { - selectAction(0); - } - }} - > - - - add - - - ) - ]; - }, - distance: 100 - }); - function spawnANode(parent: ANode | BNode) { - const node: ANode = { - x: parent.x, - y: parent.y, - z: nextId.value, - type: "anode", - links: [parent.id], - id: nextId.value - }; - placeInAvailableSpace(node, nodes.value); - nodes.value.push(node); - } - function spawnBNode(parent: ANode | BNode) { - const node: BNode = { - x: parent.x, - y: parent.y, - z: nextId.value, - type: "bnode", - links: [parent.id], - id: nextId.value - }; - placeInAvailableSpace(node, nodes.value); - nodes.value.push(node); - } - - const points = createResource(10); - const cNode = createUpgrade(() => ({ - display: "

C

", - // Purposefully not using noPersist - requirements: createCostRequirement(() => ({ cost: 10, resource: points })), - style: { - x: "100px", - y: "100px", - pointerEvents: "none" - } - })); - makeDraggable(cNode, { - id: "cnode", - endDrag, - startDrag, - hasDragged, - nodeBeingDragged, - dragDelta, - onMouseUp() { - if (!hasDragged.value) { - cNode.purchase(); - } - } - }); - - const dNodesPerAxis = 50; - const dNodes = jsx(() => ( - <> - {new Array(dNodesPerAxis * dNodesPerAxis).fill(0).map((_, i) => { - const x = (Math.floor(i / dNodesPerAxis) - dNodesPerAxis / 2) * 100; - const y = ((i % dNodesPerAxis) - dNodesPerAxis / 2) * 100; - return ( - - ); - })} - - )); - - const links = jsx(() => ( - <> - {nodes.value - .reduce( - (acc, curr) => [ - ...acc, - ...curr.links.map(l => ({ from: curr, to: nodesById.value[l] })) - ], - [] as { from: NodeTypes; to: NodeTypes }[] - ) - .map(link => ( - - ))} - - )); - - const nextId = setupUniqueIds(() => nodes.value); - - function renderNode(node: NodeTypes | typeof cNode) { - if (node.type === "anode") { - return renderANode(node); - } else if (node.type === "bnode") { - return renderBNode(node); - } else { - return render(node); - } - } + resetPropagation: branchedResetPropagation + })) as GenericTree; return { name: "Tree", - color: "var(--accent1)", + links: tree.links, display: jsx(() => ( <> - - - {dNodes()} - {links()} - - {nodes.value.map(renderNode)} - {render(cNode)} - - {aActions()} - {bActions()} - - + {player.devSpeed === 0 ? ( +
+ Game Paused + +
+ ) : null} + {player.devSpeed != null && player.devSpeed !== 0 && player.devSpeed !== 1 ? ( +
+ Dev Speed: {format(player.devSpeed)}x + +
+ ) : null} + {player.offlineTime != null && player.offlineTime !== 0 ? ( +
+ Offline Time: {formatTime(player.offlineTime)} + +
+ ) : null} +
+ {Decimal.lt(points.value, "1e1000") ? You have : null} +

{format(points.value)}

+ {Decimal.lt(points.value, "1e1e6") ? points : null} +
+ {Decimal.gt(pointGain.value, 0) ? ( +
+ ({oomps.value}) + +
+ ) : null} + + {render(tree)} )), - boardNodes: nodes, - cNode, - selected: persistent(selected) + points, + best, + total, + oomps, + tree }; }); @@ -433,7 +97,7 @@ export const main = createLayer("main", function (this: BaseLayer) { export const getInitialLayers = ( /* eslint-disable-next-line @typescript-eslint/no-unused-vars */ player: Partial -): Array => [main]; +): Array => [main, prestige]; /** * A computed ref whose value is true whenever the game is over.