mirror of
https://github.com/thepaperpilot/Planar-Pioneers.git
synced 2024-11-25 01:41:44 +00:00
Implement most treasures
Implemented resource caches, resource generation, resource multis, and energy multis. Remaining: influences and relics.
This commit is contained in:
parent
da393b7f5a
commit
fd7df64e0e
2 changed files with 183 additions and 26 deletions
|
@ -20,7 +20,7 @@ import { Direction, WithRequired, camelToTitle } from "util/common";
|
|||
import { VueFeature, render, renderRow, trackHover } from "util/vue";
|
||||
import { ComputedRef, Ref, computed, ref } from "vue";
|
||||
import { createCollapsibleModifierSections, createFormulaPreview, estimateTime } from "./common";
|
||||
import { main, Resources, resourceNames } from "./projEntry";
|
||||
import { main, Resources, resourceNames, mineLootTable, ResourceState } from "./projEntry";
|
||||
import { getColor, getName, sfc32 } from "./utils";
|
||||
import ModalVue from "components/Modal.vue";
|
||||
import { addTooltip } from "features/tooltips/tooltip";
|
||||
|
@ -185,7 +185,10 @@ export function createPlane(id: string, tier: Resources, seed: number) {
|
|||
break;
|
||||
}
|
||||
const treasureWeights = {
|
||||
dirtGeneration: 16
|
||||
cache: 100,
|
||||
generation: 10,
|
||||
resourceMulti: 5,
|
||||
energyMulti: 5
|
||||
};
|
||||
const sumTreasureWeights = Object.values(treasureWeights).reduce((a, b) => a + b);
|
||||
const treasureWeightsKeys = Object.keys(
|
||||
|
@ -209,11 +212,43 @@ export function createPlane(id: string, tier: Resources, seed: number) {
|
|||
let update: (diff: number) => void;
|
||||
let onComplete: VoidFunction;
|
||||
let link: ComputedRef<BoardNode>;
|
||||
let randomResource: Resources;
|
||||
let effectedResource: Resources | "energy";
|
||||
let resourceMulti: DecimalSource;
|
||||
switch (treasureType) {
|
||||
case "dirtGeneration":
|
||||
description = `Gain ${format(difficulty)} dirt/s while plane is active`;
|
||||
update = diff => main.grantResource("dirt", Decimal.times(diff, difficulty));
|
||||
link = computed(() => main.resourceNodes.value["dirt"]);
|
||||
case "cache":
|
||||
randomResource = getRandomResource(random);
|
||||
description = `Gain ${format(difficulty)}x your current ${randomResource}.`;
|
||||
onComplete = () =>
|
||||
main.grantResource(
|
||||
randomResource,
|
||||
Decimal.times(
|
||||
(
|
||||
main.resourceNodes.value[randomResource]
|
||||
?.state as unknown as ResourceState | null
|
||||
)?.amount ?? 0,
|
||||
difficulty
|
||||
)
|
||||
);
|
||||
break;
|
||||
case "generation":
|
||||
randomResource = getRandomResource(random);
|
||||
const gain = Decimal.div(difficulty, 120).times(mineLootTable[randomResource]);
|
||||
description = `Gain ${format(gain)} ${randomResource}/s while plane is active.`;
|
||||
update = diff => main.grantResource(randomResource, Decimal.times(diff, gain));
|
||||
link = computed(() => main.resourceNodes.value[randomResource]);
|
||||
break;
|
||||
case "resourceMulti":
|
||||
effectedResource = randomResource = getRandomResource(random);
|
||||
resourceMulti = Decimal.div(difficulty, 17).pow_base(2);
|
||||
description = `Gain ${format(
|
||||
resourceMulti
|
||||
)}x ${randomResource} while plane is active.`;
|
||||
break;
|
||||
case "energyMulti":
|
||||
effectedResource = "energy";
|
||||
resourceMulti = Decimal.div(difficulty, 17);
|
||||
description = `Gain ${format(resourceMulti)}x energy while plane is active.`;
|
||||
break;
|
||||
}
|
||||
const cost = Decimal.times(difficulty, random() + 0.5)
|
||||
|
@ -237,7 +272,9 @@ export function createPlane(id: string, tier: Resources, seed: number) {
|
|||
},
|
||||
update,
|
||||
onComplete,
|
||||
link
|
||||
link,
|
||||
effectedResource,
|
||||
resourceMulti
|
||||
})) as GenericAchievement;
|
||||
features.push([milestone]);
|
||||
visibility = milestone.earned;
|
||||
|
@ -317,6 +354,32 @@ export function createPlane(id: string, tier: Resources, seed: number) {
|
|||
return links;
|
||||
});
|
||||
|
||||
const resourceMultis = computed(() => {
|
||||
const multis: Partial<Record<Resources | "energy", DecimalSource>> = {};
|
||||
for (let i = 1; i < features.length; i += 2) {
|
||||
const treasure = features[i][0] as GenericAchievement & {
|
||||
effectedResource?: Resources | "energy";
|
||||
resourceMulti: DecimalSource;
|
||||
};
|
||||
if (
|
||||
treasure.earned.value &&
|
||||
treasure.effectedResource != null &&
|
||||
treasure.resourceMulti != null
|
||||
) {
|
||||
if (multis[treasure.effectedResource] != null) {
|
||||
multis[treasure.effectedResource] = Decimal.times(
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
multis[treasure.effectedResource]!,
|
||||
treasure.resourceMulti
|
||||
);
|
||||
} else {
|
||||
multis[treasure.effectedResource] = treasure.resourceMulti;
|
||||
}
|
||||
}
|
||||
}
|
||||
return multis;
|
||||
});
|
||||
|
||||
return {
|
||||
tier: persistent(tier),
|
||||
seed: persistent(seed),
|
||||
|
@ -331,6 +394,7 @@ export function createPlane(id: string, tier: Resources, seed: number) {
|
|||
features,
|
||||
resourceTabCollapsed,
|
||||
links,
|
||||
resourceMultis,
|
||||
display: jsx(() => (
|
||||
<>
|
||||
<StickyVue class="nav-container">
|
||||
|
@ -375,4 +439,23 @@ export function createPlane(id: string, tier: Resources, seed: number) {
|
|||
});
|
||||
}
|
||||
|
||||
// Using separate method from what's used in mining, because planes are influenced by influences and not things like dowsing
|
||||
function getRandomResource(random: () => number) {
|
||||
const sumResourceWeights = (Object.values(mineLootTable) as number[]).reduce((a, b) => a + b);
|
||||
const resourceWeightsKeys = Object.keys(mineLootTable) as Resources[];
|
||||
const r = Math.floor(random() * sumResourceWeights);
|
||||
let weight = 0;
|
||||
let resource: Resources;
|
||||
for (let i = 0; i < resourceWeightsKeys.length; i++) {
|
||||
const type = resourceWeightsKeys[i];
|
||||
weight += mineLootTable[type];
|
||||
if (r < weight) {
|
||||
resource = type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
return resource!;
|
||||
}
|
||||
|
||||
export type GenericPlane = ReturnType<typeof createPlane>;
|
||||
|
|
|
@ -74,7 +74,7 @@ export interface PortalState {
|
|||
powered: boolean;
|
||||
}
|
||||
|
||||
const mineLootTable = {
|
||||
export const mineLootTable = {
|
||||
dirt: 120,
|
||||
sand: 60,
|
||||
gravel: 40,
|
||||
|
@ -202,7 +202,7 @@ const passives = {
|
|||
},
|
||||
gravel: {
|
||||
description: (empowered: boolean) =>
|
||||
empowered ? "Quadruples material drops" : "Doubles material drops"
|
||||
empowered ? "Quadruples mine ore drops" : "Doubles mine ore drops"
|
||||
},
|
||||
stone: {
|
||||
description: (empowered: boolean) =>
|
||||
|
@ -715,10 +715,14 @@ export const main = createLayer("main", function (this: BaseLayer) {
|
|||
progressColor: "var(--accent3)",
|
||||
classes: node => ({
|
||||
"affected-node":
|
||||
dowsing.value != null &&
|
||||
(dowsing.value != null &&
|
||||
isPowered(dowsing.value) &&
|
||||
(dowsing.value.state as unknown as DowsingState).resources.includes(
|
||||
(node.state as unknown as ResourceState).type
|
||||
)) ||
|
||||
Decimal.neq(
|
||||
planarMultis.value[(node.state as unknown as ResourceState).type] ?? 1,
|
||||
1
|
||||
)
|
||||
}),
|
||||
draggable: true
|
||||
|
@ -1107,20 +1111,34 @@ export const main = createLayer("main", function (this: BaseLayer) {
|
|||
});
|
||||
// TODO link to influences
|
||||
}
|
||||
links.push(
|
||||
...activePortals.value
|
||||
.map(node =>
|
||||
(
|
||||
layers[(node.state as unknown as PortalState).id] as GenericPlane
|
||||
).links.value.map(n => ({
|
||||
(board as GenericBoard).types.portal.nodes.value.forEach(node => {
|
||||
const plane = layers[(node.state as unknown as PortalState).id] as GenericPlane;
|
||||
plane.links.value.forEach(n => {
|
||||
if (n.value != null) {
|
||||
links.push({
|
||||
startNode: node,
|
||||
endNode: n.value,
|
||||
stroke: "var(--accent3)",
|
||||
stroke: isPowered(node) ? "var(--accent3)" : "var(--foreground)",
|
||||
strokeWidth: 4
|
||||
}))
|
||||
)
|
||||
.reduce((a, b) => [...a, ...b], [])
|
||||
});
|
||||
}
|
||||
});
|
||||
(Object.keys(plane.resourceMultis.value) as (Resources | "energy")[]).forEach(
|
||||
type => {
|
||||
if (type !== "energy" && type in resourceNodes.value) {
|
||||
links.push({
|
||||
startNode: node,
|
||||
endNode: resourceNodes.value[type],
|
||||
stroke: isPowered(node)
|
||||
? "var(--accent1)"
|
||||
: "var(--foreground)",
|
||||
strokeWidth: 4
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
return links;
|
||||
});
|
||||
}
|
||||
return links;
|
||||
}
|
||||
|
@ -1143,6 +1161,7 @@ export const main = createLayer("main", function (this: BaseLayer) {
|
|||
|
||||
function grantResource(type: Resources, amount: DecimalSource) {
|
||||
let node = resourceNodes.value[type];
|
||||
amount = Decimal.times(amount, resourceGain[type].computedModifier.value);
|
||||
if (node == null) {
|
||||
node = {
|
||||
id: getUniqueNodeID(board),
|
||||
|
@ -1169,6 +1188,26 @@ export const main = createLayer("main", function (this: BaseLayer) {
|
|||
)
|
||||
);
|
||||
|
||||
const planarMultis = computed(() => {
|
||||
const multis: Partial<Record<Resources | "energy", DecimalSource>> = {};
|
||||
board.types.portal.nodes.value.forEach(n => {
|
||||
if (!isPowered(n)) {
|
||||
return;
|
||||
}
|
||||
const plane = layers[(n.state as unknown as PortalState).id] as GenericPlane;
|
||||
const planeMultis = plane.resourceMultis.value;
|
||||
(Object.keys(planeMultis) as (Resources | "energy")[]).forEach(type => {
|
||||
if (multis[type] != null) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
multis[type] = Decimal.times(multis[type]!, planeMultis[type]!);
|
||||
} else {
|
||||
multis[type] = planeMultis[type];
|
||||
}
|
||||
});
|
||||
});
|
||||
return multis;
|
||||
});
|
||||
|
||||
const energyModifier = createSequentialModifier(() => [
|
||||
...resourceNames.map(resource =>
|
||||
createMultiplicativeModifier(() => ({
|
||||
|
@ -1205,6 +1244,11 @@ export const main = createLayer("main", function (this: BaseLayer) {
|
|||
: "") + tools.stone.name,
|
||||
enabled: () => toolNodes.value["stone"] != null
|
||||
})),
|
||||
createMultiplicativeModifier(() => ({
|
||||
multiplier: () => planarMultis.value.energy ?? 1,
|
||||
description: "Planar Treasures",
|
||||
enabled: () => Decimal.neq(planarMultis.value.energy ?? 1, 1)
|
||||
})),
|
||||
createAdditiveModifier(() => ({
|
||||
addend: () => Decimal.pow(100, poweredMachines.value).div(10).neg(),
|
||||
description: "Powered Machines (100^n/10 energy/s)",
|
||||
|
@ -1293,6 +1337,23 @@ export const main = createLayer("main", function (this: BaseLayer) {
|
|||
return acc;
|
||||
}, {} as Record<Resources, { modifier: WithRequired<Modifier, "invert" | "description">; computedModifier: ComputedRef<DecimalSource>; section: Section }>);
|
||||
|
||||
const resourceGain = (Object.keys(mineLootTable) as Resources[]).reduce((acc, resource) => {
|
||||
const modifier = createSequentialModifier(() => [
|
||||
createMultiplicativeModifier(() => ({
|
||||
multiplier: () => planarMultis.value[resource] ?? 1,
|
||||
description: "Planar Treasures",
|
||||
enabled: () => Decimal.neq(planarMultis.value[resource] ?? 1, 1)
|
||||
}))
|
||||
]);
|
||||
const computedModifier = computed(() => modifier.apply(1));
|
||||
const section = {
|
||||
title: `${camelToTitle(resource)} Gain`,
|
||||
modifier
|
||||
};
|
||||
acc[resource] = { modifier, computedModifier, section };
|
||||
return acc;
|
||||
}, {} as Record<Resources, { modifier: WithRequired<Modifier, "invert" | "description">; computedModifier: ComputedRef<DecimalSource>; section: Section }>);
|
||||
|
||||
const [energyTab, energyTabCollapsed] = createCollapsibleModifierSections(() => [
|
||||
{
|
||||
title: "Energy Gain",
|
||||
|
@ -1325,6 +1386,9 @@ export const main = createLayer("main", function (this: BaseLayer) {
|
|||
const [resourcesTab, resourcesCollapsed] = createCollapsibleModifierSections(() =>
|
||||
Object.values(dropRates).map(d => d.section)
|
||||
);
|
||||
const [resourceGainTab, resourceGainCollapsed] = createCollapsibleModifierSections(() =>
|
||||
Object.values(resourceGain).map(d => d.section)
|
||||
);
|
||||
const modifierTabs = createTabFamily({
|
||||
general: () => ({
|
||||
display: "Energy",
|
||||
|
@ -1335,7 +1399,7 @@ export const main = createLayer("main", function (this: BaseLayer) {
|
|||
energyTabCollapsed
|
||||
}),
|
||||
mining: () => ({
|
||||
display: "Mining",
|
||||
display: "Mine",
|
||||
glowColor(): string {
|
||||
return modifierTabs.activeTab.value === this.tab ? "white" : "";
|
||||
},
|
||||
|
@ -1344,13 +1408,23 @@ export const main = createLayer("main", function (this: BaseLayer) {
|
|||
miningTabCollapsed
|
||||
}),
|
||||
resources: () => ({
|
||||
display: "Resources",
|
||||
display: "Mine Rates",
|
||||
glowColor(): string {
|
||||
return modifierTabs.activeTab.value === this.tab ? "white" : "";
|
||||
},
|
||||
visibility: () => dowsing.value != null,
|
||||
tab: resourcesTab,
|
||||
resourcesCollapsed
|
||||
}),
|
||||
resourcesGain: () => ({
|
||||
display: "Resource Gain",
|
||||
glowColor(): string {
|
||||
return modifierTabs.activeTab.value === this.tab ? "white" : "";
|
||||
},
|
||||
visibility: () =>
|
||||
Object.values(resourceGain).some(r => Decimal.neq(r.computedModifier.value, 1)),
|
||||
tab: resourceGainTab,
|
||||
resourceGainCollapsed
|
||||
})
|
||||
});
|
||||
const showModifiersModal = ref(false);
|
||||
|
|
Loading…
Reference in a new issue