From 4510cd0b43279a0db124b129e8ec0acf5bbe2d36 Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Thu, 27 Apr 2023 22:49:07 -0500 Subject: [PATCH] Implement basic procgen upgrades --- src/data/planes.tsx | 196 +++++++++++++++++++++++++++++++++++++++-- src/data/projEntry.tsx | 2 +- 2 files changed, 191 insertions(+), 7 deletions(-) diff --git a/src/data/planes.tsx b/src/data/planes.tsx index bb8814a..dba4e7a 100644 --- a/src/data/planes.tsx +++ b/src/data/planes.tsx @@ -1,11 +1,24 @@ +import SpacerVue from "components/layout/Spacer.vue"; +import StickyVue from "components/layout/Sticky.vue"; import { jsx } from "features/feature"; -import MainDisplayVue from "features/resources/MainDisplay.vue"; import { createResource } from "features/resources/resource"; +import { createUpgrade } from "features/upgrades/upgrade"; +import Formula from "game/formulas/formulas"; import { BaseLayer, createLayer } from "game/layers"; -import { persistent } from "game/persistence"; -import { DecimalSource } from "util/bignum"; -import { Resources } from "./projEntry"; +import { Modifier, createAdditiveModifier, createSequentialModifier } from "game/modifiers"; +import { noPersist, persistent } from "game/persistence"; +import { createCostRequirement } from "game/requirements"; +import { adjectives, colors, uniqueNamesGenerator } from "unique-names-generator"; +import Decimal, { DecimalSource } from "util/bignum"; +import { format } from "util/break_eternity"; +import { Direction, WithRequired, camelToTitle } from "util/common"; +import { VueFeature, render, renderRow } from "util/vue"; +import { computed, ref } from "vue"; +import { createCollapsibleModifierSections, createFormulaPreview, estimateTime } from "./common"; +import { Resources, resourceNames } from "./projEntry"; import { getColor, getName, sfc32 } from "./utils"; +import ModalVue from "components/Modal.vue"; +import { addTooltip } from "features/tooltips/tooltip"; export function createPlane(id: string, tier: Resources, seed: number) { return createLayer(id, function (this: BaseLayer) { @@ -16,6 +29,151 @@ export function createPlane(id: string, tier: Resources, seed: number) { const color = getColor([0.64, 0.75, 0.55], random); const background = getColor([0.18, 0.2, 0.25], random); const resource = createResource(0, getName(random)); + const tierIndex = resourceNames.indexOf(tier); + const difficulty = random() + tierIndex + 1; + const length = random() * (tierIndex + 1) + 1; + + const resourceModifiers: WithRequired[] = []; + const resourceGainModifier = createSequentialModifier(() => resourceModifiers); + const computedResourceGain = computed(() => resourceGainModifier.apply(0)); + + const features: VueFeature[][] = []; + const t = ref(0); + let costFormula = Formula.variable(t); + for (let i = 0; i < length; i++) { + const featureWeights = { + upgrades: 16 + }; + const sumFeatureWeights = Object.values(featureWeights).reduce((a, b) => a + b); + const featureWeightsKeys = Object.keys( + featureWeights + ) as (keyof typeof featureWeights)[]; + const r = Math.floor(random() * sumFeatureWeights); + let weight = 0; + let type: keyof typeof featureWeights | null = null; + for (let i = 0; i < featureWeightsKeys.length; i++) { + const feature = featureWeightsKeys[i]; + weight += featureWeights[feature]; + if (r < weight) { + type = feature; + break; + } + } + if (type == null) { + continue; // Should not happen + } + switch (type) { + case "upgrades": + const upgrades: VueFeature[] = []; + for (let j = 0; j < 4; j++) { + const upgradeTypeWeights = { + add: 1, + mult: 1 + }; + const sumUpgradeTypeWeights = Object.values(upgradeTypeWeights).reduce( + (a, b) => a + b + ); + const upgradeTypeWeightsKeys = Object.keys( + upgradeTypeWeights + ) as (keyof typeof upgradeTypeWeights)[]; + let upgradeType: keyof typeof upgradeTypeWeights | null = null; + const r = Math.floor(random() * sumUpgradeTypeWeights); + for (let i = 0; i < upgradeTypeWeightsKeys.length; i++) { + const type = upgradeTypeWeightsKeys[i]; + weight += upgradeTypeWeights[type]; + if (r < weight) { + upgradeType = type; + break; + } + } + if (type == null) { + continue; + } + const cost = Decimal.times(difficulty, random() + 0.5) + .pow_base(2) + .times(10) + .times(costFormula.evaluate()); + const title = camelToTitle( + uniqueNamesGenerator({ + dictionaries: [colors, adjectives], + seed: random() * 4294967296, + separator: " " + }) + "ity" + ); + let description = ""; + switch (upgradeType) { + case "add": { + const addend = Decimal.add(cost, 10).pow(random() / 4 + 0.875); + description = `Gain ${format(addend)} ${resource.displayName}/s`; + costFormula = costFormula.step(t.value, c => c.add(addend)); + t.value = Decimal.times(difficulty, random() + 0.5) + .pow_base(2) + .add(t.value); + resourceModifiers.push( + createAdditiveModifier(() => ({ + addend, + description: title, + enabled: upgrade.bought + })) + ); + break; + } + } + const upgrade = createUpgrade(() => ({ + requirements: createCostRequirement(() => ({ + resource: noPersist(resource), + cost + })), + display: { + title, + description + } + })); + addTooltip(upgrade, { + display: upgrade.bought.value + ? "" + : estimateTime(resource, computedResourceGain, cost), + direction: Direction.Down + }); + upgrades.push(upgrade); + } + features.push(upgrades); + break; + } + } + + const [resourceTab, resourceTabCollapsed] = createCollapsibleModifierSections(() => [ + { + title: `${camelToTitle(resource.displayName)} Gain`, + modifier: resourceGainModifier, + base: 0, + unit: "/s" + } + ]); + const showModifiersModal = ref(false); + const modifiersModal = jsx(() => ( + (showModifiersModal.value = value)} + v-slots={{ + header: () =>

Modifiers

, + body: () => render(resourceTab) + }} + /> + )); + + this.on("preUpdate", diff => { + resource.value = Decimal.times(computedResourceGain.value, diff).add(resource.value); + }); + + const resourceChange = computed(() => { + return 0; + }); + const resourcePreview = createFormulaPreview( + Formula.variable(0).add(resource), + () => Decimal.neq(resourceChange.value, 0), + resourceChange + ); return { tier: persistent(tier), @@ -28,10 +186,36 @@ export function createPlane(id: string, tier: Resources, seed: number) { background, "--background": background }, + features, + resourceTabCollapsed, display: jsx(() => ( <> -

{name}

- + + +

{name}

+
+ +

{tier}-tier

+
+ +

+ {render(resourcePreview)} +

{" "} + {resource.displayName} +
+ + + +
+ + {features.map(row => renderRow(...row))} + {render(modifiersModal)} )) }; diff --git a/src/data/projEntry.tsx b/src/data/projEntry.tsx index 357a23e..837ff17 100644 --- a/src/data/projEntry.tsx +++ b/src/data/projEntry.tsx @@ -94,7 +94,7 @@ const mineLootTable = { } as const; export type Resources = keyof typeof mineLootTable; -const resourceNames = Object.keys(mineLootTable) as Resources[]; +export const resourceNames = Object.keys(mineLootTable) as Resources[]; const tools = { dirt: {