mirror of
https://github.com/thepaperpilot/Planar-Pioneers.git
synced 2025-02-16 09:41:40 +00:00
Implement basic procgen upgrades
This commit is contained in:
parent
600fa67baf
commit
4510cd0b43
2 changed files with 191 additions and 7 deletions
|
@ -1,11 +1,24 @@
|
||||||
|
import SpacerVue from "components/layout/Spacer.vue";
|
||||||
|
import StickyVue from "components/layout/Sticky.vue";
|
||||||
import { jsx } from "features/feature";
|
import { jsx } from "features/feature";
|
||||||
import MainDisplayVue from "features/resources/MainDisplay.vue";
|
|
||||||
import { createResource } from "features/resources/resource";
|
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 { BaseLayer, createLayer } from "game/layers";
|
||||||
import { persistent } from "game/persistence";
|
import { Modifier, createAdditiveModifier, createSequentialModifier } from "game/modifiers";
|
||||||
import { DecimalSource } from "util/bignum";
|
import { noPersist, persistent } from "game/persistence";
|
||||||
import { Resources } from "./projEntry";
|
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 { 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) {
|
export function createPlane(id: string, tier: Resources, seed: number) {
|
||||||
return createLayer(id, function (this: BaseLayer) {
|
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 color = getColor([0.64, 0.75, 0.55], random);
|
||||||
const background = getColor([0.18, 0.2, 0.25], random);
|
const background = getColor([0.18, 0.2, 0.25], random);
|
||||||
const resource = createResource<DecimalSource>(0, getName(random));
|
const resource = createResource<DecimalSource>(0, getName(random));
|
||||||
|
const tierIndex = resourceNames.indexOf(tier);
|
||||||
|
const difficulty = random() + tierIndex + 1;
|
||||||
|
const length = random() * (tierIndex + 1) + 1;
|
||||||
|
|
||||||
|
const resourceModifiers: WithRequired<Modifier, "description" | "invert">[] = [];
|
||||||
|
const resourceGainModifier = createSequentialModifier(() => resourceModifiers);
|
||||||
|
const computedResourceGain = computed(() => resourceGainModifier.apply(0));
|
||||||
|
|
||||||
|
const features: VueFeature[][] = [];
|
||||||
|
const t = ref<DecimalSource>(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(() => (
|
||||||
|
<ModalVue
|
||||||
|
modelValue={showModifiersModal.value}
|
||||||
|
onUpdate:modelValue={(value: boolean) => (showModifiersModal.value = value)}
|
||||||
|
v-slots={{
|
||||||
|
header: () => <h2>Modifiers</h2>,
|
||||||
|
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 {
|
return {
|
||||||
tier: persistent(tier),
|
tier: persistent(tier),
|
||||||
|
@ -28,10 +186,36 @@ export function createPlane(id: string, tier: Resources, seed: number) {
|
||||||
background,
|
background,
|
||||||
"--background": background
|
"--background": background
|
||||||
},
|
},
|
||||||
|
features,
|
||||||
|
resourceTabCollapsed,
|
||||||
display: jsx(() => (
|
display: jsx(() => (
|
||||||
<>
|
<>
|
||||||
<h1>{name}</h1>
|
<StickyVue class="nav-container">
|
||||||
<MainDisplayVue resource={resource} color={color} />
|
<span class="nav-segment">
|
||||||
|
<h2>{name}</h2>
|
||||||
|
</span>
|
||||||
|
<span class="nav-segment">
|
||||||
|
<h3>{tier}-tier</h3>
|
||||||
|
</span>
|
||||||
|
<span class="nav-segment">
|
||||||
|
<h3 style={`color: ${color}; text-shadow: 0px 0px 10px ${color};`}>
|
||||||
|
{render(resourcePreview)}
|
||||||
|
</h3>{" "}
|
||||||
|
{resource.displayName}
|
||||||
|
</span>
|
||||||
|
<span class="nav-segment">
|
||||||
|
<button
|
||||||
|
class="button"
|
||||||
|
style="display: inline"
|
||||||
|
onClick={() => (showModifiersModal.value = true)}
|
||||||
|
>
|
||||||
|
open modifiers
|
||||||
|
</button>
|
||||||
|
</span>
|
||||||
|
</StickyVue>
|
||||||
|
<SpacerVue />
|
||||||
|
{features.map(row => renderRow(...row))}
|
||||||
|
{render(modifiersModal)}
|
||||||
</>
|
</>
|
||||||
))
|
))
|
||||||
};
|
};
|
||||||
|
|
|
@ -94,7 +94,7 @@ const mineLootTable = {
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export type Resources = keyof typeof mineLootTable;
|
export type Resources = keyof typeof mineLootTable;
|
||||||
const resourceNames = Object.keys(mineLootTable) as Resources[];
|
export const resourceNames = Object.keys(mineLootTable) as Resources[];
|
||||||
|
|
||||||
const tools = {
|
const tools = {
|
||||||
dirt: {
|
dirt: {
|
||||||
|
|
Loading…
Add table
Reference in a new issue