mirror of
https://github.com/thepaperpilot/Planar-Pioneers.git
synced 2024-11-25 01:41:44 +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 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<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 {
|
||||
tier: persistent(tier),
|
||||
|
@ -28,10 +186,36 @@ export function createPlane(id: string, tier: Resources, seed: number) {
|
|||
background,
|
||||
"--background": background
|
||||
},
|
||||
features,
|
||||
resourceTabCollapsed,
|
||||
display: jsx(() => (
|
||||
<>
|
||||
<h1>{name}</h1>
|
||||
<MainDisplayVue resource={resource} color={color} />
|
||||
<StickyVue class="nav-container">
|
||||
<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;
|
||||
|
||||
export type Resources = keyof typeof mineLootTable;
|
||||
const resourceNames = Object.keys(mineLootTable) as Resources[];
|
||||
export const resourceNames = Object.keys(mineLootTable) as Resources[];
|
||||
|
||||
const tools = {
|
||||
dirt: {
|
||||
|
|
Loading…
Reference in a new issue