From 067ba6ce9062773cf85b7e9567b5c22cee67a2e0 Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Thu, 27 Jan 2022 22:47:26 -0600 Subject: [PATCH] Make layers lazy instantiate --- src/data/common.tsx | 1 + src/data/layers/aca/a.tsx | 192 +++---- src/data/layers/aca/c.tsx | 1119 +++++++++++++++++++------------------ src/data/layers/aca/f.tsx | 306 +++++----- src/data/mod.tsx | 160 +++--- src/features/buyable.tsx | 2 +- src/features/challenge.ts | 6 +- src/game/layers.ts | 52 +- 8 files changed, 929 insertions(+), 909 deletions(-) diff --git a/src/data/common.tsx b/src/data/common.tsx index 05fe18a..54d4d2d 100644 --- a/src/data/common.tsx +++ b/src/data/common.tsx @@ -118,6 +118,7 @@ export type LayerTreeNode = Replace< append: ProcessedComputable; } >; +export type GenericLayerTreeNode = LayerTreeNode; export function createLayerTreeNode(options: T): LayerTreeNode { processComputable(options as T, "append"); diff --git a/src/data/layers/aca/a.tsx b/src/data/layers/aca/a.tsx index e33082b..494f996 100644 --- a/src/data/layers/aca/a.tsx +++ b/src/data/layers/aca/a.tsx @@ -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(0, "achievement power"); +const layer = createLayer(() => { + const id = "a"; + const color = "yellow"; + const name = "Achievements"; + const points = createResource(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 ( + +

Gridable #{id}

+
+ ); + }, + 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 ( - -

Gridable #{id}

-
- ); - }, - getDisplay(id) { - return String(id); - }, - getCanClick() { - return Decimal.eq(mainPoints.value, 10); - }, - onClick(id, state) { - this.cells[id].state = Number(state) + 1; - } -}); + }); -const display = ( - -); + const display = ( + + ); -const layer = createLayer({ - id, - color, - name, - points, - achievements, - grid, - treeNode, - display + return { + id, + color, + name, + points, + achievements, + grid, + treeNode, + display + }; }); export default layer; diff --git a/src/data/layers/aca/c.tsx b/src/data/layers/aca/c.tsx index 7b62ce8..0ba3cf9 100644 --- a/src/data/layers/aca/c.tsx +++ b/src/data/layers/aca/c.tsx @@ -9,13 +9,13 @@ import Spacer from "@/components/system/Spacer.vue"; import Sticky from "@/components/system/Sticky.vue"; import VerticalRule from "@/components/system/VerticalRule.vue"; import { createLayerTreeNode, createResetButton } from "@/data/common"; -import { points as mainPoints, tree as mainTree } from "@/data/mod"; +import { main } from "@/data/mod"; import { createBar, Direction } from "@/features/bar"; import { createBuyable } from "@/features/buyable"; import { createChallenge } from "@/features/challenge"; import { createClickable } from "@/features/clickable"; import { createCumulativeConversion, createExponentialScaling } from "@/features/conversion"; -import { persistent, showIf } from "@/features/feature"; +import { CoercableComponent, persistent, showIf } from "@/features/feature"; import { createHotkey } from "@/features/hotkey"; import { createInfobox } from "@/features/infobox"; import { createMilestone } from "@/features/milestone"; @@ -23,583 +23,588 @@ import { createReset } from "@/features/reset"; import { addSoftcap, createResource, displayResource, trackBest } from "@/features/resource"; import { createTab } from "@/features/tab"; import { createTabButton, createTabFamily } from "@/features/tabFamily"; -import { createTree, createTreeNode } from "@/features/tree"; +import { createTree, createTreeNode, GenericTreeNode, TreeBranch } from "@/features/tree"; import { createUpgrade } from "@/features/upgrade"; import { createLayer, getLayer } from "@/game/layers"; import { DecimalSource } from "@/lib/break_eternity"; import Decimal, { format, formatWhole } from "@/util/bignum"; import { render, renderCol, renderRow } from "@/util/vue"; -import { computed } from "vue"; -import { boop, tab as fTab, treeNode as fNode } from "./f"; +import { computed, Ref } from "vue"; +import f from "./f"; -const c = getLayer("c"); +const layer = createLayer(() => { + const id = "c"; + const color = "#4BDC13"; + const name = "Candies"; + const points = addSoftcap(createResource(0, "lollipops"), 1e100, 0.5); + const best = trackBest(points); + const beep = persistent(false); + const thingy = persistent("pointy"); + const otherThingy = persistent(10); + const spentOnBuyables = persistent(new Decimal(10)); -const id = "c"; -const color = "#4BDC13"; -const name = "Candies"; -const points = addSoftcap(createResource(0, "lollipops"), 1e100, 0.5); -const best = trackBest(points); -const beep = persistent(false); -const thingy = persistent("pointy"); -export const otherThingy = persistent(10); -const spentOnBuyables = persistent(new Decimal(10)); + const waffleBoost = computed(() => Decimal.pow(points.value, 0.2)); + const icecreamCap = computed(() => Decimal.times(points.value, 10)); -const waffleBoost = computed(() => Decimal.pow(points.value, 0.2)); -const icecreamCap = computed(() => Decimal.times(points.value, 10)); + 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 lollipopMilestone3 = createMilestone({ - shouldEarn() { - return Decimal.gte(best.value, 3); - }, - display: { - requirement: "3 Lollipops", - effectDisplay: "Unlock the next milestone" - } -}); -const lollipopMilestone4 = createMilestone({ - visibility() { - return showIf(lollipopMilestone3.earned.value); - }, - shouldEarn() { - return Decimal.gte(best.value, 4); - }, - display: { - requirement: "4 Lollipops", - effectDisplay: "You can toggle beep and boop (which do nothing)", - optionsDisplay() { - return ( -
- - -
- ); - } - }, - style() { - if (this.earned) { - return { backgroundColor: "#1111DD" }; - } - return {}; - } -}); -const lollipopMilestones = [lollipopMilestone3, lollipopMilestone4]; - -const funChallenge = createChallenge({ - title: "Fun", - completionLimit: 3, - display: { - description() { - return `Makes the game 0% harder
${this.completions}/${this.completionLimit} completions`; + const lollipopMilestone3 = createMilestone({ + shouldEarn() { + return Decimal.gte(best.value, 3); }, - goal: "Have 20 points I guess", - reward: "Says hi", - effectDisplay() { - return format(funEffect.value) + "x"; + display: { + requirement: "3 Lollipops", + effectDisplay: "Unlock the next milestone" } - }, - visibility() { - return showIf(Decimal.gt(best.value, 0)); - }, - goal: 20, - resource: () => mainPoints, - onComplete() { - console.log("hiii"); - }, - onEnter() { - console.log("So challenging"); - }, - onExit() { - console.log("Sweet freedom!"); - }, - style: { - height: "200px" - } -}); -const funEffect = computed(() => Decimal.add(points.value, 1).tetrate(0.02)); - -export const generatorUpgrade = createUpgrade({ - title: "Generator of Genericness", - display: "Gain 1 point every second", - cost: 1, - resource: points -}); -export const lollipopMultiplierUpgrade = createUpgrade({ - display: () => - `Point generation is faster based on your unspent Lollipops
Currently: ${format( - lollipopMultiplierEffect.value - )}x`, - cost: 1, - resource: points, - visibility: () => showIf(generatorUpgrade.bought.value) -}); -export const lollipopMultiplierEffect = computed(() => { - let ret = Decimal.add(points.value, 1).pow(0.5); - if (ret.gte("1e20000000")) ret = ret.sqrt().times("1e10000000"); - return ret; -}); -export const unlockIlluminatiUpgrade = createUpgrade({ - visibility() { - return showIf(lollipopMultiplierUpgrade.bought.value); - }, - canPurchase() { - return Decimal.lt(mainPoints.value, 7); - }, - onPurchase() { - mainPoints.value = Decimal.add(mainPoints.value, 7); - }, - display: "Only buyable with less than 7 points, and gives you 7 more. Unlocks a secret subtab.", - style() { - if (this.bought) { - return { backgroundColor: "#1111dd" }; - } - if (!this.canAfford) { - return { backgroundColor: "#dd1111" }; - } - return {}; - } -}); -const upgrades = [generatorUpgrade, lollipopMultiplierUpgrade, unlockIlluminatiUpgrade]; - -const exhancers = createBuyable({ - resource: points, - cost() { - let x = new Decimal(this.amount.value); - if (x.gte(25)) { - x = x.pow(2).div(25); - } - const cost = Decimal.pow(2, x.pow(1.5)); - return cost.floor(); - }, - display: { - title: "Exhancers", - description() { - return `Adds ${format( - exhancersFirstEffect.value - )} things and multiplies stuff by ${format(exhancersSecondEffect.value)}.`; - } - }, - onPurchase(cost) { - spentOnBuyables.value = Decimal.add(spentOnBuyables.value, cost); - }, - style: { height: "222px" }, - purchaseLimit: 4 -}); -const exhancersFirstEffect = computed(() => { - if (Decimal.gte(exhancers.amount.value, 0)) { - return Decimal.pow(25, Decimal.pow(exhancers.amount.value, 1.1)); - } - return Decimal.pow(1 / 25, Decimal.times(exhancers.amount.value, -1).pow(1.1)); -}); -const exhancersSecondEffect = computed(() => { - if (Decimal.gte(exhancers.amount.value, 0)) { - return Decimal.pow(25, Decimal.pow(exhancers.amount.value, 1.1)); - } - return Decimal.pow(1 / 25, Decimal.times(exhancers.amount.value, -1).pow(1.1)); -}); -const confirmRespec = persistent(false); -const respecBuyables = createClickable({ - small: true, - display: "Respec Thingies", - onClick() { - if ( - confirmRespec.value && - !confirm("Are you sure? Respeccing these doesn't accomplish much.") - ) { - return; - } - - points.value = Decimal.add(points.value, spentOnBuyables.value); - mainTree.reset(treeNode); - } -}); -const sellExhancer = createClickable({ - small: true, - display: "Sell One", - onClick() { - if (Decimal.lte(exhancers.amount.value, 0)) { - return; - } - exhancers.amount.value = Decimal.sub(exhancers.amount.value, 1); - points.value = Decimal.add(points.value, exhancers.cost.value); - } -}); -const buyablesDisplay = ( - - - - {render(respecBuyables)} - - {render(exhancers)} - {render(sellExhancer)} - -); - -const longBoi = createBar({ - fillStyle: { backgroundColor: "#FFFFFF" }, - baseStyle: { backgroundColor: "#696969" }, - textStyle: { color: "#04e050" }, - direction: Direction.Right, - width: 300, - height: 30, - progress() { - return Decimal.add(mainPoints.value, 1).log(10).div(10).toNumber(); - }, - display() { - return format(mainPoints.value) + " / 1e10 points"; - } -}); -const tallBoi = createBar({ - fillStyle: { backgroundColor: "#4BEC13" }, - baseStyle: { backgroundColor: "#000000" }, - textStyle: { textShadow: "0px 0px 2px #000000" }, - borderStyle: { borderWidth: "7px" }, - direction: Direction.Up, - width: 50, - height: 200, - progress() { - return Decimal.div(mainPoints.value, 100); - }, - display() { - return formatWhole(Decimal.div(mainPoints.value, 1).min(100)) + "%"; - } -}); -const flatBoi = createBar({ - fillStyle: { backgroundColor: "#FE0102" }, - baseStyle: { backgroundColor: "#222222" }, - textStyle: { textShadow: "0px 0px 2px #000000" }, - direction: Direction.Up, - width: 100, - height: 30, - progress() { - return Decimal.div(points.value, 50); - } -}); - -const conversion = createCumulativeConversion({ - scaling: createExponentialScaling(10, 5, 0.5), - baseResource: mainPoints, - gainResource: points, - roundUpCost: true -}); - -const reset = createReset({ - thingsToReset: () => [c()] -}); - -const hotkeys = [ - createHotkey({ - key: "c", - description: "reset for lollipops or whatever", - onPress() { - if (resetButton.canClick) { - reset.reset(); - } - } - }), - createHotkey({ - key: "ctrl+c", - description: "respec things", - onPress() { - respecBuyables.onClick(); - } - }) -]; - -export const treeNode = createLayerTreeNode({ - layerID: id, - color, - reset, - mark: "https://unsoftcapped2.github.io/The-Modding-Tree-2/discord.png", - tooltip() { - let tooltip = displayResource(points); - if (Decimal.gt(exhancers.amount.value, 0)) { - tooltip += `



${formatWhole(exhancers.amount.value)} Exhancers
`; - } - return tooltip; - }, - style: { - color: "#3325CC", - textDecoration: "underline" - } -}); - -const resetButton = createResetButton({ - conversion, - tree: mainTree, - treeNode, - style: { - color: "#AA66AA" - }, - resetDescription: "Melt your points into " -}); - -export const g = createTreeNode({ - display: "TH", - color: "#6d3678", - canClick() { - return Decimal.gte(points.value, 10); - }, - tooltip: "Thanos your points", - onClick() { - points.value = Decimal.div(points.value, 2); - console.log("Thanos'd"); - }, - glowColor() { - if (Decimal.eq(exhancers.amount.value, 1)) { - return "orange"; - } - return ""; - } -}); -export const h = createTreeNode({ - id: "h", - tooltip() { - return `Restore your points to ${format(otherThingy.value)}`; - }, - canClick() { - return Decimal.lt(mainPoints.value, otherThingy.value); - }, - onClick() { - mainPoints.value = otherThingy.value; - } -}); -export const spook = createTreeNode({}); -const tree = createTree({ - nodes() { - return [ - [fNode, treeNode], - [g, spook, h] - ]; - }, - branches: () => [ - { - startNode: fNode, - endNode: treeNode, - style: { - strokeWidth: "25px", - stroke: "blue", - filter: "blur(5px)" + }); + const lollipopMilestone4 = createMilestone({ + visibility() { + return showIf(lollipopMilestone3.earned.value); + }, + shouldEarn() { + return Decimal.gte(best.value, 4); + }, + display: { + requirement: "4 Lollipops", + effectDisplay: "You can toggle beep and boop (which do nothing)", + optionsDisplay() { + return ( +
+ + } /> +
+ ); } }, - { startNode: treeNode, endNode: g }, - { startNode: g, endNode: h } - ] -}); + style() { + if (this.earned) { + return { backgroundColor: "#1111DD" }; + } + return {}; + } + }); + const lollipopMilestones = [lollipopMilestone3, lollipopMilestone4]; -const illuminatiTabs = createTabFamily({ - tabs: { - first: createTabButton({ - tab: ( - - ), - display: "first" - }), - second: createTabButton({ - tab: () => fTab, - display: "second" - }) - }, - style: { - width: "660px", - height: "370px", - backgroundColor: "brown", - "--background": "brown", - border: "solid white", - margin: "auto" - } -}); - -const tabs = createTabFamily({ - tabs: { - mainTab: createTabButton({ - tab: createTab({ - display() { - return ( - - ); - }, - style: { - backgroundColor: "#3325CC" - } - }), - display: "main tab", - glowColor() { - if ( - generatorUpgrade.canPurchase.value || - lollipopMultiplierUpgrade.canPurchase.value || - unlockIlluminatiUpgrade.canPurchase.value || - funChallenge.canComplete.value - ) { - return "blue"; - } - return ""; + const funChallenge = createChallenge({ + title: "Fun", + completionLimit: 3, + display: { + description() { + return `Makes the game 0% harder
${this.completions}/${this.completionLimit} completions`; }, - style: { color: "orange" } - }), - thingies: createTabButton({ - tab: createTab({ - glowColor: "white", - style() { - return { backgroundColor: "#222222", "--background": "#222222" }; - }, - display() { - return ( - - ); + goal: "Have 20 points I guess", + reward: "Says hi", + effectDisplay() { + return format(funEffect.value) + "x"; + } + }, + visibility() { + return showIf(Decimal.gt(best.value, 0)); + }, + goal: 20, + resource: main.value.points, + onComplete() { + console.log("hiii"); + }, + onEnter() { + console.log("So challenging"); + }, + onExit() { + console.log("Sweet freedom!"); + }, + style: { + height: "200px" + } + }); + const funEffect = computed(() => Decimal.add(points.value, 1).tetrate(0.02)); + + const generatorUpgrade = createUpgrade({ + title: "Generator of Genericness", + display: "Gain 1 point every second", + cost: 1, + resource: points + }); + const lollipopMultiplierUpgrade = createUpgrade({ + display: () => + `Point generation is faster based on your unspent Lollipops
Currently: ${format( + lollipopMultiplierEffect.value + )}x`, + cost: 1, + resource: points, + visibility: () => showIf(generatorUpgrade.bought.value) + }); + const lollipopMultiplierEffect = computed(() => { + let ret = Decimal.add(points.value, 1).pow(0.5); + if (ret.gte("1e20000000")) ret = ret.sqrt().times("1e10000000"); + return ret; + }); + const unlockIlluminatiUpgrade = createUpgrade({ + visibility() { + return showIf(lollipopMultiplierUpgrade.bought.value); + }, + canPurchase() { + return Decimal.lt(main.value.points.value, 7); + }, + onPurchase() { + main.value.points.value = Decimal.add(main.value.points.value, 7); + }, + display: + "Only buyable with less than 7 points, and gives you 7 more. Unlocks a secret subtab.", + style() { + if (this.bought) { + return { backgroundColor: "#1111dd" }; + } + if (!this.canAfford) { + return { backgroundColor: "#dd1111" }; + } + return {}; + } + }); + const upgrades = [generatorUpgrade, lollipopMultiplierUpgrade, unlockIlluminatiUpgrade]; + + const exhancers = createBuyable({ + resource: points, + cost() { + let x = new Decimal(this.amount.value); + if (x.gte(25)) { + x = x.pow(2).div(25); + } + const cost = Decimal.pow(2, x.pow(1.5)); + return cost.floor(); + }, + display: { + title: "Exhancers", + description() { + return `Adds ${format( + exhancersFirstEffect.value + )} things and multiplies stuff by ${format(exhancersSecondEffect.value)}.`; + } + }, + onPurchase(cost) { + spentOnBuyables.value = Decimal.add(spentOnBuyables.value, cost); + }, + style: { height: "222px" }, + purchaseLimit: 4 + }); + const exhancersFirstEffect = computed(() => { + if (Decimal.gte(exhancers.amount.value, 0)) { + return Decimal.pow(25, Decimal.pow(exhancers.amount.value, 1.1)); + } + return Decimal.pow(1 / 25, Decimal.times(exhancers.amount.value, -1).pow(1.1)); + }); + const exhancersSecondEffect = computed(() => { + if (Decimal.gte(exhancers.amount.value, 0)) { + return Decimal.pow(25, Decimal.pow(exhancers.amount.value, 1.1)); + } + return Decimal.pow(1 / 25, Decimal.times(exhancers.amount.value, -1).pow(1.1)); + }); + const confirmRespec = persistent(false); + const respecBuyables = createClickable({ + small: true, + display: "Respec Thingies", + onClick() { + if ( + confirmRespec.value && + !confirm("Are you sure? Respeccing these doesn't accomplish much.") + ) { + return; + } + + points.value = Decimal.add(points.value, spentOnBuyables.value); + main.value.tree.reset(treeNode); + } + }); + const sellExhancer = createClickable({ + small: true, + display: "Sell One", + onClick() { + if (Decimal.lte(exhancers.amount.value, 0)) { + return; + } + exhancers.amount.value = Decimal.sub(exhancers.amount.value, 1); + points.value = Decimal.add(points.value, exhancers.cost.value); + } + }); + const buyablesDisplay = ( + + + + {render(respecBuyables)} + + {render(exhancers)} + {render(sellExhancer)} + + ); + + const longBoi = createBar({ + fillStyle: { backgroundColor: "#FFFFFF" }, + baseStyle: { backgroundColor: "#696969" }, + textStyle: { color: "#04e050" }, + direction: Direction.Right, + width: 300, + height: 30, + progress() { + return Decimal.add(main.value.points.value, 1).log(10).div(10).toNumber(); + }, + display() { + return format(main.value.points.value) + " / 1e10 points"; + } + }); + const tallBoi = createBar({ + fillStyle: { backgroundColor: "#4BEC13" }, + baseStyle: { backgroundColor: "#000000" }, + textStyle: { textShadow: "0px 0px 2px #000000" }, + borderStyle: { borderWidth: "7px" }, + direction: Direction.Up, + width: 50, + height: 200, + progress() { + return Decimal.div(main.value.points.value, 100); + }, + display() { + return formatWhole(Decimal.div(main.value.points.value, 1).min(100)) + "%"; + } + }); + const flatBoi = createBar({ + fillStyle: { backgroundColor: "#FE0102" }, + baseStyle: { backgroundColor: "#222222" }, + textStyle: { textShadow: "0px 0px 2px #000000" }, + direction: Direction.Up, + width: 100, + height: 30, + progress() { + return Decimal.div(points.value, 50); + } + }); + + const conversion = createCumulativeConversion({ + scaling: createExponentialScaling(10, 5, 0.5), + baseResource: main.value.points, + gainResource: points, + roundUpCost: true + }); + + const reset = createReset({ + thingsToReset: () => [getLayer("c")] + }); + + const hotkeys = [ + createHotkey({ + key: "c", + description: "reset for lollipops or whatever", + onPress() { + if (resetButton.canClick) { + reset.reset(); } - }), - display: "thingies", - style: { borderColor: "orange" } + } }), - jail: createTabButton({ - tab: createTab({ - display() { - return ( - + ); + } + }), + display: "thingies", + style: { borderColor: "orange" } }), - display: "jail" - }), - illuminati: createTabButton({ - tab: createTab({ - display() { - return ( - - ); - }, - style: { - backgroundColor: "#3325CC" - } + jail: createTabButton({ + tab: createTab({ + display() { + return ( + + ); + }, + style: { + backgroundColor: "#3325CC" + } + }), + display: "jail" }), - visibility() { - return showIf(unlockIlluminatiUpgrade.bought.value); - }, - display: "illuminati" - }) - } -}); + illuminati: createTabButton({ + tab: createTab({ + display() { + return ( + + ); + }, + style: { + backgroundColor: "#3325CC" + } + }), + visibility() { + return showIf(unlockIlluminatiUpgrade.bought.value); + }, + display: "illuminati" + }) + } + }); -const layer = createLayer({ - id, - color, - name, - links() { - const links = tree.links.value.slice(); - links.push({ - startNode: h, - endNode: flatBoi, - offsetEnd: { x: -50 + 100 * flatBoi.progress.value.toNumber(), y: 0 } - }); - return links; - }, - points, - beep, - thingy, - otherThingy, - spentOnBuyables, - waffleBoost, - icecreamCap, - coolInfo, - lollipopMilestones, - funChallenge, - funEffect, - generatorUpgrade, - lollipopMultiplierUpgrade, - lollipopMultiplierEffect, - unlockIlluminatiUpgrade, - exhancers, - exhancersFirstEffect, - exhancersSecondEffect, - respecBuyables, - sellExhancer, - bars: { tallBoi, longBoi, flatBoi }, - tree, - g, - h, - spook, - conversion, - reset, - hotkeys, - treeNode, - resetButton, - minWidth: 800, - display: render(tabs) + return { + id, + color, + name, + links() { + const links = tree.links.value.slice(); + links.push({ + startNode: h, + endNode: flatBoi, + offsetEnd: { x: -50 + 100 * flatBoi.progress.value.toNumber(), y: 0 } + }); + return links; + }, + points, + beep, + thingy, + otherThingy, + spentOnBuyables, + waffleBoost, + icecreamCap, + coolInfo, + lollipopMilestones, + funChallenge, + funEffect, + generatorUpgrade, + lollipopMultiplierUpgrade, + lollipopMultiplierEffect, + unlockIlluminatiUpgrade, + exhancers, + exhancersFirstEffect, + exhancersSecondEffect, + respecBuyables, + sellExhancer, + bars: { tallBoi, longBoi, flatBoi }, + tree, + g, + h, + spook, + conversion, + reset, + hotkeys, + treeNode, + resetButton, + minWidth: 800, + display: render(tabs) + }; }); export default layer; diff --git a/src/data/layers/aca/f.tsx b/src/data/layers/aca/f.tsx index bc47647..6078156 100644 --- a/src/data/layers/aca/f.tsx +++ b/src/data/layers/aca/f.tsx @@ -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(0, "farm points"); + const boop = persistent(false); -const id = "f"; -const color = "#FE0102"; -const name = "Farms"; -export const points = createResource(0, "farm points"); -export const boop = persistent(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("Start"); -const clickable = createClickable({ - display: { - title: "Clicky clicky!", - description() { - return "Current state:
" + clickableState.value; + const clickableState = persistent("Start"); + const clickable = createClickable({ + display: { + title: "Clicky clicky!", + description() { + return "Current state:
" + 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 ( + + Hi! I'm a weird dinosaur and I'll give you{" "} + {formatWhole(this.conversion.currentGain.value)} Farm Points in + exchange for all of your points and lollipops! (You'll get another one at{" "} + {formatWhole(this.conversion.nextAt.value)} points) + + ); + } else { + return ( + + Hi! I'm a weird dinosaur 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) + + ); + } } - }, - display() { - return clickableState.value == "Borkened..." ? "Fix the clickable!" : "Does nothing"; - } -}); + }); -const reset = createReset({ - thingsToReset: () => [f()] -}); + const tab = (): JSX.Element => ( + + ); -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 ( - - Hi! I'm a weird dinosaur and I'll give you{" "} - {formatWhole(this.conversion.currentGain.value)} Farm Points in exchange - for all of your points and lollipops! (You'll get another one at{" "} - {formatWhole(this.conversion.nextAt.value)} points) - - ); - } else { - return ( - - Hi! I'm a weird dinosaur 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) - - ); - } - } -}); - -export const tab = (): JSX.Element => ( - -); - -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; diff --git a/src/data/mod.tsx b/src/data/mod.tsx index 3682d6f..e2ac896 100644 --- a/src/data/mod.tsx +++ b/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(0); -const best = trackBest(points); -const total = trackTotal(points); -const oomps = trackOOMPS(points); -const showModal = ref(false); +export const main = createLayer(() => { + const points = createResource(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: ( - - ), - points, - best, - total, - oomps, - tree + + + + + + {render(tree)} + + ), + points, + best, + total, + oomps, + tree + }; }); export const getInitialLayers = ( /* eslint-disable-next-line @typescript-eslint/no-unused-vars */ player: Partial -): Array => [main, f, c, a]; +): Array => [main.value, f.value, c.value, a.value]; export const hasWon = computed(() => { return false; diff --git a/src/features/buyable.tsx b/src/features/buyable.tsx index 698cb9a..79ec0b1 100644 --- a/src/features/buyable.tsx +++ b/src/features/buyable.tsx @@ -37,7 +37,7 @@ type BuyableDisplay = export interface BuyableOptions { visibility?: Computable; cost?: Computable; - resource?: Computable; + resource?: Resource; canPurchase?: Computable; purchaseLimit?: Computable; classes?: Computable>; diff --git a/src/features/challenge.ts b/src/features/challenge.ts index 6d6a536..8d7b652 100644 --- a/src/features/challenge.ts +++ b/src/features/challenge.ts @@ -34,7 +34,7 @@ export interface ChallengeOptions { canComplete?: Computable; completionLimit?: Computable; mark?: Computable; - resource?: Computable; + resource?: Resource; goal?: Computable; classes?: Computable>; style?: Computable; @@ -72,7 +72,6 @@ export type Challenge = Replace< canComplete: GetComputableTypeWithDefault>; completionLimit: GetComputableTypeWithDefault; mark: GetComputableTypeWithDefault>; - resource: GetComputableType; goal: GetComputableType; classes: GetComputableType; style: GetComputableType; @@ -160,7 +159,7 @@ export function createChallenge( if (!proxy.active.value || proxy.resource == null || proxy.goal == null) { return false; } - return Decimal.gte(unref(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( 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"); diff --git a/src/game/layers.ts b/src/game/layers.ts index 21517f3..6291918 100644 --- a/src/game/layers.ts +++ b/src/game/layers.ts @@ -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(options: T): Layer { - const layer: T & Partial = options; +export function createLayer(optionsFunc: () => T): Ref> { + let layer: Layer | null = null; - const emitter = (layer.emitter = createNanoEvents()); - 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; + const emitter = (partialLayer.emitter = createNanoEvents()); + 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); - return proxy; + layer = createProxy(partialLayer as unknown as Layer); + } + 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(layerID: string): () => T { - return () => layers[layerID] as T; +export function getLayer(layerID: string): T { + return layers[layerID] as T; } export function removeLayer(layer: GenericLayer): void {