mirror of
https://github.com/thepaperpilot/Planar-Pioneers.git
synced 2024-11-24 09:21:45 +00:00
Implement booster machine
This commit is contained in:
parent
a61e113109
commit
03b8dece48
2 changed files with 239 additions and 9 deletions
|
@ -29,6 +29,7 @@ import { VueFeature, render, renderRow, trackHover } from "util/vue";
|
|||
import { ComputedRef, Ref, computed, ref, unref } from "vue";
|
||||
import { createCollapsibleModifierSections, createFormulaPreview, estimateTime } from "./common";
|
||||
import {
|
||||
BoosterState,
|
||||
InfluenceState,
|
||||
Influences,
|
||||
influences as influenceTypes,
|
||||
|
@ -45,7 +46,7 @@ import TooltipVue from "features/tooltips/Tooltip.vue";
|
|||
const toast = useToast();
|
||||
|
||||
export type Treasure = GenericAchievement & {
|
||||
update?: (diff: number) => void;
|
||||
update?: (diff: DecimalSource) => void;
|
||||
link?: ComputedRef<BoardNode>;
|
||||
effectedResource?: Resources | "energy";
|
||||
resourceMulti: DecimalSource;
|
||||
|
@ -390,7 +391,7 @@ export function createPlane(
|
|||
treasureType = "relic";
|
||||
}
|
||||
let description = "";
|
||||
let update: (diff: number) => void;
|
||||
let update: (diff: DecimalSource) => void;
|
||||
let onComplete: VoidFunction;
|
||||
let link: ComputedRef<BoardNode>;
|
||||
let randomResource: Resources;
|
||||
|
@ -526,12 +527,40 @@ export function createPlane(
|
|||
RepeatableType
|
||||
) as GenericRepeatable[];
|
||||
|
||||
const planarSpeedModifier = createSequentialModifier(() => [
|
||||
createMultiplicativeModifier(() => ({
|
||||
multiplier: () =>
|
||||
Decimal.add(
|
||||
(
|
||||
main.board.types.booster.nodes.value[0]?.state as unknown as
|
||||
| BoosterState
|
||||
| undefined
|
||||
)?.level ?? 0,
|
||||
1
|
||||
),
|
||||
description: "Booster",
|
||||
enabled: () =>
|
||||
(
|
||||
main.board.types.booster.nodes.value[0]?.state as unknown as
|
||||
| BoosterState
|
||||
| undefined
|
||||
)?.portals.includes(id) ?? false
|
||||
}))
|
||||
]);
|
||||
const computedPlanarSpeedModifier = computed(() => planarSpeedModifier.apply(1));
|
||||
|
||||
const [resourceTab, resourceTabCollapsed] = createCollapsibleModifierSections(() => [
|
||||
{
|
||||
title: `${camelToTitle(resource.displayName)} Gain`,
|
||||
modifier: resourceGainModifier,
|
||||
base: 0,
|
||||
unit: "/s"
|
||||
},
|
||||
{
|
||||
title: `${camelToTitle(resource.displayName)} Time Speed`,
|
||||
modifier: planarSpeedModifier,
|
||||
base: 1,
|
||||
visible: () => Decimal.gt(computedPlanarSpeedModifier.value, 1)
|
||||
}
|
||||
]);
|
||||
const showModifiersModal = ref(false);
|
||||
|
@ -552,12 +581,15 @@ export function createPlane(
|
|||
) {
|
||||
return;
|
||||
}
|
||||
const totalDiff = Decimal.times(computedPlanarSpeedModifier.value, diff);
|
||||
|
||||
timeActive.value = Decimal.add(timeActive.value, diff);
|
||||
resource.value = Decimal.times(computedResourceGain.value, diff).add(resource.value);
|
||||
timeActive.value = Decimal.add(timeActive.value, totalDiff);
|
||||
resource.value = Decimal.times(computedResourceGain.value, totalDiff).add(
|
||||
resource.value
|
||||
);
|
||||
|
||||
earnedTreasures.value.forEach(treasure => {
|
||||
treasure.update?.(diff);
|
||||
treasure.update?.(totalDiff);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -79,6 +79,13 @@ export interface InfluenceState {
|
|||
data: State;
|
||||
}
|
||||
|
||||
export interface BoosterState {
|
||||
portals: string[];
|
||||
maxConnections: number;
|
||||
powered: boolean;
|
||||
level: DecimalSource;
|
||||
}
|
||||
|
||||
export const mineLootTable = {
|
||||
dirt: 120,
|
||||
sand: 60,
|
||||
|
@ -160,7 +167,7 @@ const tools = {
|
|||
cost: 1e15,
|
||||
name: "Booster",
|
||||
type: "booster",
|
||||
state: { planes: [], maxConnections: 1, powered: false }
|
||||
state: { planes: [], maxConnections: 1, powered: false, level: 1 }
|
||||
},
|
||||
emerald: {
|
||||
cost: 1e19,
|
||||
|
@ -195,7 +202,8 @@ const tools = {
|
|||
ultimatum: {
|
||||
cost: 1e54,
|
||||
name: "Investments",
|
||||
type: "investments"
|
||||
type: "investments",
|
||||
state: { planes: [], maxConnections: 1, powered: false }
|
||||
}
|
||||
} as const satisfies Record<
|
||||
Resources,
|
||||
|
@ -443,6 +451,8 @@ export const influences = {
|
|||
>;
|
||||
export type Influences = keyof typeof influences;
|
||||
|
||||
const increaseBoostFormula = Formula.variable(0).add(8).times(2).pow10();
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
|
@ -466,7 +476,8 @@ export const main = createLayer("main", function (this: BaseLayer) {
|
|||
sand: board.types.dowsing.nodes.value[0],
|
||||
wood: board.types.quarry.nodes.value[0],
|
||||
coal: board.types.empowerer.nodes.value[0],
|
||||
iron: board.types.portalGenerator.nodes.value[0]
|
||||
iron: board.types.portalGenerator.nodes.value[0],
|
||||
gold: board.types.booster.nodes.value[0]
|
||||
}));
|
||||
|
||||
const influenceNodes: ComputedRef<Record<Influences, BoardNode>> = computed(() => ({
|
||||
|
@ -727,6 +738,33 @@ export const main = createLayer("main", function (this: BaseLayer) {
|
|||
return null;
|
||||
}
|
||||
|
||||
function labelForAcceptingPortal(
|
||||
node: BoardNode,
|
||||
description: (portal: string) => string
|
||||
): NodeLabel | null {
|
||||
if ((board as GenericBoard).draggingNode.value?.type === "portal") {
|
||||
const portal = (
|
||||
(board as GenericBoard).draggingNode.value?.state as unknown as PortalState
|
||||
).id;
|
||||
const { maxConnections, portals } = node.state as unknown as BoosterState;
|
||||
if (portals.includes(portal)) {
|
||||
return { text: "Disconnect", color: "var(--accent2)" };
|
||||
}
|
||||
if (
|
||||
Decimal.add(maxConnections, computedBonusConnectionsModifier.value).lte(
|
||||
portals.length
|
||||
)
|
||||
) {
|
||||
return { text: "Max connections", color: "var(--danger)" };
|
||||
}
|
||||
return {
|
||||
text: description(portal),
|
||||
color: "var(--accent2)"
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function canAcceptResource(node: BoardNode, otherNode: BoardNode) {
|
||||
if (otherNode.type !== "resource") {
|
||||
return false;
|
||||
|
@ -801,6 +839,43 @@ export const main = createLayer("main", function (this: BaseLayer) {
|
|||
board.selectedNode.value = node;
|
||||
}
|
||||
|
||||
function canAcceptPortal(node: BoardNode, otherNode: BoardNode) {
|
||||
if (otherNode.type !== "portal") {
|
||||
return false;
|
||||
}
|
||||
const portal = (otherNode.state as unknown as PortalState).id;
|
||||
const { maxConnections, portals } = node.state as unknown as BoosterState;
|
||||
if (portals.includes(portal)) {
|
||||
return true;
|
||||
}
|
||||
if (
|
||||
Decimal.add(maxConnections, computedBonusConnectionsModifier.value).lte(portals.length)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function onDropPortal(node: BoardNode, otherNode: BoardNode) {
|
||||
if (otherNode.type !== "portal") {
|
||||
return;
|
||||
}
|
||||
const portal = (otherNode.state as unknown as PortalState).id;
|
||||
const { portals } = node.state as unknown as BoosterState;
|
||||
if (portals.includes(portal)) {
|
||||
node.state = {
|
||||
...(node.state as object),
|
||||
tools: portals.filter(r => r !== portal)
|
||||
};
|
||||
} else {
|
||||
node.state = {
|
||||
...(node.state as object),
|
||||
tools: [...portals, portal]
|
||||
};
|
||||
}
|
||||
board.selectedNode.value = node;
|
||||
}
|
||||
|
||||
const board = createBoard(board => ({
|
||||
startNodes: () => [
|
||||
{ position: { x: 0, y: 0 }, type: "mine", state: { progress: 0, powered: false } },
|
||||
|
@ -1368,6 +1443,95 @@ export const main = createLayer("main", function (this: BaseLayer) {
|
|||
},
|
||||
outlineColor: "var(--danger)",
|
||||
draggable: true
|
||||
},
|
||||
booster: {
|
||||
shape: Shape.Diamond,
|
||||
size: 50,
|
||||
title: "⌛",
|
||||
label: node => {
|
||||
if (node === board.selectedNode.value) {
|
||||
return {
|
||||
text:
|
||||
(node.state as unknown as BoosterState).portals.length === 0
|
||||
? "Booster - Drag a portal to me!"
|
||||
: `Boosting by ${formatWhole(
|
||||
Decimal.add(
|
||||
1,
|
||||
(node.state as unknown as BoosterState).level
|
||||
)
|
||||
)}x (${
|
||||
(node.state as { tools: Passives[] }).tools.length
|
||||
}/${Decimal.add(
|
||||
(node.state as { maxConnections: number }).maxConnections,
|
||||
computedBonusConnectionsModifier.value
|
||||
)})`
|
||||
};
|
||||
}
|
||||
return labelForAcceptingPortal(node, portal => {
|
||||
return `Boost ${(layers[portal] as GenericPlane).name}'s speed`;
|
||||
});
|
||||
},
|
||||
actionDistance: Math.PI / 4,
|
||||
actions: [
|
||||
{
|
||||
id: "deselect",
|
||||
icon: "close",
|
||||
tooltip: {
|
||||
text: "Disconnect portals"
|
||||
},
|
||||
onClick(node: BoardNode) {
|
||||
node.state = { ...(node.state as object), portals: [] };
|
||||
board.selectedAction.value = null;
|
||||
board.selectedNode.value = null;
|
||||
},
|
||||
visibility: (node: BoardNode) =>
|
||||
(node.state as unknown as BoosterState)?.portals.length ?? 0 > 0
|
||||
},
|
||||
getIncreaseConnectionsAction(x => x.add(6).pow_base(1000)),
|
||||
{
|
||||
id: "increaseBoost",
|
||||
icon: "arrow_upward",
|
||||
tooltip(node: BoardNode) {
|
||||
return {
|
||||
text: `Increase boost - ${formatWhole(
|
||||
increaseBoostFormula.evaluate(
|
||||
(node.state as unknown as BoosterState).level
|
||||
)
|
||||
)} energy`
|
||||
};
|
||||
},
|
||||
confirmationLabel(node: BoardNode) {
|
||||
return Decimal.gte(
|
||||
energy.value,
|
||||
increaseBoostFormula.evaluate(
|
||||
(node.state as unknown as BoosterState).level
|
||||
)
|
||||
)
|
||||
? { text: "Tap again to confirm" }
|
||||
: { text: "Cannot afford", color: "var(--danger)" };
|
||||
},
|
||||
onClick(node: BoardNode) {
|
||||
const cost = increaseBoostFormula.evaluate(
|
||||
(node.state as unknown as BoosterState).level
|
||||
);
|
||||
if (Decimal.gte(energy.value, cost)) {
|
||||
energy.value = Decimal.sub(energy.value, cost);
|
||||
}
|
||||
node.state = {
|
||||
...(node.state as object),
|
||||
level: Decimal.add((node.state as unknown as BoosterState).level, 1)
|
||||
};
|
||||
board.selectedAction.value = null;
|
||||
}
|
||||
},
|
||||
togglePoweredAction
|
||||
],
|
||||
canAccept: canAcceptPortal,
|
||||
onDrop: onDropPortal,
|
||||
classes: node => ({
|
||||
running: isPowered(node)
|
||||
}),
|
||||
draggable: true
|
||||
}
|
||||
},
|
||||
style: {
|
||||
|
@ -1491,6 +1655,21 @@ export const main = createLayer("main", function (this: BaseLayer) {
|
|||
return links;
|
||||
});
|
||||
}
|
||||
if (booster.value != null) {
|
||||
(booster.value.state as unknown as BoosterState).portals.forEach(portal => {
|
||||
links.push({
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
startNode: booster.value!,
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
endNode: (board as GenericBoard).types.portal.nodes.value.find(
|
||||
node => (node.state as unknown as PortalState).id === portal
|
||||
)!,
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
stroke: isPowered(booster.value!) ? "var(--accent1)" : "var(--foreground)",
|
||||
strokeWidth: 4
|
||||
});
|
||||
});
|
||||
}
|
||||
Object.values(influenceNodes.value).forEach(node => {
|
||||
const state = node.state as unknown as InfluenceState;
|
||||
if (state.type === "increaseResources" || state.type === "decreaseResources") {
|
||||
|
@ -1522,7 +1701,8 @@ export const main = createLayer("main", function (this: BaseLayer) {
|
|||
const portalGenerator: ComputedRef<BoardNode | undefined> = computed(
|
||||
() => toolNodes.value.iron
|
||||
);
|
||||
const poweredMachines = [mine, dowsing, quarry, empowerer];
|
||||
const booster: ComputedRef<BoardNode | undefined> = computed(() => toolNodes.value.gold);
|
||||
const poweredMachines = [mine, dowsing, quarry, empowerer, booster];
|
||||
|
||||
function grantResource(type: Resources, amount: DecimalSource) {
|
||||
let node = resourceNodes.value[type];
|
||||
|
@ -1981,6 +2161,24 @@ export const main = createLayer("main", function (this: BaseLayer) {
|
|||
};
|
||||
}
|
||||
}
|
||||
if (booster.value) {
|
||||
const maxConnections = (booster.value.state as unknown as BoosterState)
|
||||
.maxConnections;
|
||||
if (
|
||||
Decimal.lt(
|
||||
(booster.value.state as unknown as BoosterState).portals.length,
|
||||
Decimal.add(maxConnections, curr)
|
||||
)
|
||||
) {
|
||||
booster.value.state = {
|
||||
...(booster.value.state as object),
|
||||
resources: (booster.value.state as unknown as BoosterState).portals.slice(
|
||||
0,
|
||||
Decimal.add(maxConnections, curr).toNumber()
|
||||
)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in a new issue