mirror of
https://github.com/thepaperpilot/Planar-Pioneers.git
synced 2024-11-25 01:41:44 +00:00
Add automator, some cleanup
This commit is contained in:
parent
bcaff20313
commit
9dbfdef509
6 changed files with 149 additions and 38 deletions
|
@ -347,7 +347,7 @@ export function checkConnections<T extends string>(
|
||||||
};
|
};
|
||||||
const currentConnections = state[connectionsName];
|
const currentConnections = state[connectionsName];
|
||||||
const maxConnections = state.maxConnections;
|
const maxConnections = state.maxConnections;
|
||||||
if (Decimal.lt(currentConnections.length, Decimal.add(maxConnections, bonusConnections))) {
|
if (Decimal.gt(currentConnections.length, Decimal.add(maxConnections, bonusConnections))) {
|
||||||
node.value.state = {
|
node.value.state = {
|
||||||
...(node.value.state as object),
|
...(node.value.state as object),
|
||||||
[connectionsName]: currentConnections.slice(
|
[connectionsName]: currentConnections.slice(
|
||||||
|
|
|
@ -56,6 +56,12 @@ export interface UpgraderState {
|
||||||
powered: boolean;
|
powered: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface AutomatorState {
|
||||||
|
portals: string[];
|
||||||
|
maxConnections: number;
|
||||||
|
powered: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export const mineLootTable = {
|
export const mineLootTable = {
|
||||||
dirt: 120,
|
dirt: 120,
|
||||||
sand: 60,
|
sand: 60,
|
||||||
|
@ -224,8 +230,8 @@ export const passives = {
|
||||||
silver: {
|
silver: {
|
||||||
description: (empowered: boolean) =>
|
description: (empowered: boolean) =>
|
||||||
empowered
|
empowered
|
||||||
? "Doubles each plane's resource gain"
|
? "Quadruples each plane's resource gain"
|
||||||
: "Quadruples each plane's resource gain"
|
: "Doubles each plane's resource gain"
|
||||||
},
|
},
|
||||||
diamond: {
|
diamond: {
|
||||||
description: (empowered: boolean) =>
|
description: (empowered: boolean) =>
|
||||||
|
|
|
@ -29,6 +29,7 @@ import {
|
||||||
togglePoweredAction
|
togglePoweredAction
|
||||||
} from "./boardUtils";
|
} from "./boardUtils";
|
||||||
import {
|
import {
|
||||||
|
AutomatorState,
|
||||||
BoosterState,
|
BoosterState,
|
||||||
DowsingState,
|
DowsingState,
|
||||||
EmpowererState,
|
EmpowererState,
|
||||||
|
@ -239,7 +240,13 @@ export const resource = {
|
||||||
export const passive = {
|
export const passive = {
|
||||||
shape: Shape.Circle,
|
shape: Shape.Circle,
|
||||||
size: 50,
|
size: 50,
|
||||||
title: node => tools[node.state as Resources].name,
|
title: node => {
|
||||||
|
const passive = node.state as Passives;
|
||||||
|
if (passive.includes("Relic")) {
|
||||||
|
return relics[passive.slice(0, -5) as Resources];
|
||||||
|
}
|
||||||
|
return tools[passive as Resources].name;
|
||||||
|
},
|
||||||
label: node =>
|
label: node =>
|
||||||
node === main.board.selectedNode.value
|
node === main.board.selectedNode.value
|
||||||
? {
|
? {
|
||||||
|
@ -708,7 +715,7 @@ export const upgrader = {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return labelForAcceptingPortal(node, portal => {
|
return labelForAcceptingPortal(node, portal => {
|
||||||
return `Auto-buy ${(layers[portal] as GenericPlane).name}'s upgrades`;
|
return `Auto-buy ${(layers[portal] as GenericPlane).name}'s upgrades and prestiges`;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
actionDistance: Math.PI / 4,
|
actionDistance: Math.PI / 4,
|
||||||
|
@ -737,3 +744,52 @@ export const upgrader = {
|
||||||
}),
|
}),
|
||||||
draggable: true
|
draggable: true
|
||||||
} as NodeTypeOptions;
|
} as NodeTypeOptions;
|
||||||
|
|
||||||
|
export const automator = {
|
||||||
|
shape: Shape.Diamond,
|
||||||
|
size: 50,
|
||||||
|
title: "🦾",
|
||||||
|
label: node => {
|
||||||
|
if (node === main.board.selectedNode.value) {
|
||||||
|
return {
|
||||||
|
text:
|
||||||
|
(node.state as unknown as AutomatorState).portals.length === 0
|
||||||
|
? "Automator - Drag a portal to me!"
|
||||||
|
: `Automatating (${
|
||||||
|
(node.state as unknown as AutomatorState).portals.length
|
||||||
|
}/${Decimal.add(
|
||||||
|
(node.state as unknown as AutomatorState).maxConnections,
|
||||||
|
main.computedBonusConnectionsModifier.value
|
||||||
|
)})`
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return labelForAcceptingPortal(node, portal => {
|
||||||
|
return `Auto-buy ${(layers[portal] as GenericPlane).name}'s repeatables and dimensions`;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
actionDistance: Math.PI / 4,
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
id: "deselect",
|
||||||
|
icon: "close",
|
||||||
|
tooltip: {
|
||||||
|
text: "Disconnect portals"
|
||||||
|
},
|
||||||
|
onClick(node: BoardNode) {
|
||||||
|
node.state = { ...(node.state as object), portals: [] };
|
||||||
|
main.board.selectedAction.value = null;
|
||||||
|
main.board.selectedNode.value = null;
|
||||||
|
},
|
||||||
|
visibility: (node: BoardNode) =>
|
||||||
|
(node.state as unknown as AutomatorState)?.portals.length ?? 0 > 0
|
||||||
|
},
|
||||||
|
getIncreaseConnectionsAction(x => x.add(4).pow_base(1e6)),
|
||||||
|
togglePoweredAction
|
||||||
|
],
|
||||||
|
canAccept: canAcceptPortal,
|
||||||
|
onDrop: onDropPortal,
|
||||||
|
classes: node => ({
|
||||||
|
running: isPowered(node)
|
||||||
|
}),
|
||||||
|
draggable: true
|
||||||
|
} as NodeTypeOptions;
|
||||||
|
|
|
@ -4,7 +4,7 @@ import StickyVue from "components/layout/Sticky.vue";
|
||||||
import { GenericAchievement, createAchievement } from "features/achievements/achievement";
|
import { GenericAchievement, createAchievement } from "features/achievements/achievement";
|
||||||
import { createBar } from "features/bars/bar";
|
import { createBar } from "features/bars/bar";
|
||||||
import { BoardNode, getUniqueNodeID } from "features/boards/board";
|
import { BoardNode, getUniqueNodeID } from "features/boards/board";
|
||||||
import { createClickable } from "features/clickables/clickable";
|
import { GenericClickable, createClickable, setupAutoClick } from "features/clickables/clickable";
|
||||||
import { createCumulativeConversion } from "features/conversion";
|
import { createCumulativeConversion } from "features/conversion";
|
||||||
import { CoercableComponent, findFeatures, isVisible, jsx } from "features/feature";
|
import { CoercableComponent, findFeatures, isVisible, jsx } from "features/feature";
|
||||||
import { GenericRepeatable, RepeatableType, createRepeatable } from "features/repeatable";
|
import { GenericRepeatable, RepeatableType, createRepeatable } from "features/repeatable";
|
||||||
|
@ -43,12 +43,14 @@ import { useToast } from "vue-toastification";
|
||||||
import { isPowered } from "./boardUtils";
|
import { isPowered } from "./boardUtils";
|
||||||
import { createCollapsibleModifierSections, createFormulaPreview, estimateTime } from "./common";
|
import { createCollapsibleModifierSections, createFormulaPreview, estimateTime } from "./common";
|
||||||
import {
|
import {
|
||||||
|
AutomatorState,
|
||||||
BoosterState,
|
BoosterState,
|
||||||
InfluenceState,
|
InfluenceState,
|
||||||
Influences,
|
Influences,
|
||||||
PortalState,
|
PortalState,
|
||||||
ResourceState,
|
ResourceState,
|
||||||
Resources,
|
Resources,
|
||||||
|
UpgraderState,
|
||||||
influences as influenceTypes,
|
influences as influenceTypes,
|
||||||
mineLootTable,
|
mineLootTable,
|
||||||
relics,
|
relics,
|
||||||
|
@ -130,7 +132,9 @@ export function createPlane(
|
||||||
})),
|
})),
|
||||||
createMultiplicativeModifier(() => ({
|
createMultiplicativeModifier(() => ({
|
||||||
multiplier: () =>
|
multiplier: () =>
|
||||||
Decimal.div(timeActive.value, 6000).times(main.isEmpowered("emerald") ? 2 : 1),
|
Decimal.div(timeActive.value, 6000)
|
||||||
|
.times(main.isEmpowered("emerald") ? 2 : 1)
|
||||||
|
.add(1),
|
||||||
description: () =>
|
description: () =>
|
||||||
(main.isEmpowered("emerald") ? "Empowered " : "") + tools.emerald.name,
|
(main.isEmpowered("emerald") ? "Empowered " : "") + tools.emerald.name,
|
||||||
enabled: () => main.toolNodes.value.emerald != null
|
enabled: () => main.toolNodes.value.emerald != null
|
||||||
|
@ -1072,10 +1076,24 @@ export function createPlane(
|
||||||
|
|
||||||
setupAutoPurchase(
|
setupAutoPurchase(
|
||||||
this as GenericLayer,
|
this as GenericLayer,
|
||||||
() => main.upgrader.value != null && isPowered(main.upgrader.value),
|
() =>
|
||||||
|
earnedTreasures.value.length < length &&
|
||||||
|
main.upgrader.value != null &&
|
||||||
|
isPowered(main.upgrader.value) &&
|
||||||
|
(main.upgrader.value.state as unknown as UpgraderState).portals.includes(id),
|
||||||
upgrades
|
upgrades
|
||||||
);
|
);
|
||||||
|
|
||||||
|
setupAutoClick(
|
||||||
|
this as GenericLayer,
|
||||||
|
() =>
|
||||||
|
earnedTreasures.value.length < length &&
|
||||||
|
main.automator.value != null &&
|
||||||
|
isPowered(main.automator.value) &&
|
||||||
|
(main.automator.value.state as unknown as AutomatorState).portals.includes(id),
|
||||||
|
repeatables as unknown as GenericClickable[]
|
||||||
|
);
|
||||||
|
|
||||||
const resourceChange = computed(() => {
|
const resourceChange = computed(() => {
|
||||||
const preview = previews.find(p => p.shouldShowPreview.value);
|
const preview = previews.find(p => p.shouldShowPreview.value);
|
||||||
if (preview) {
|
if (preview) {
|
||||||
|
@ -1174,6 +1192,21 @@ export function createPlane(
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const renderableFeatures = computed(() => {
|
||||||
|
const lastIndex = features.findIndex(
|
||||||
|
(row, i) => i > 0 && i % 2 === 0 && !(features[i - 1][0] as Treasure).earned.value
|
||||||
|
);
|
||||||
|
let featuresToRender;
|
||||||
|
if (lastIndex === -1) {
|
||||||
|
featuresToRender = features;
|
||||||
|
} else {
|
||||||
|
featuresToRender = features.slice(0, lastIndex);
|
||||||
|
}
|
||||||
|
return featuresToRender.map((row, i) =>
|
||||||
|
i in displays ? render(displays[i]) : renderRow(...row)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
tier: persistent(tier),
|
tier: persistent(tier),
|
||||||
seed: persistent(seed),
|
seed: persistent(seed),
|
||||||
|
@ -1254,17 +1287,7 @@ export function createPlane(
|
||||||
) : null}
|
) : null}
|
||||||
</StickyVue>
|
</StickyVue>
|
||||||
<SpacerVue height="60px" />
|
<SpacerVue height="60px" />
|
||||||
{features
|
{renderableFeatures.value}
|
||||||
.slice(
|
|
||||||
0,
|
|
||||||
features.findIndex(
|
|
||||||
(row, i) =>
|
|
||||||
i > 0 &&
|
|
||||||
i % 2 === 0 &&
|
|
||||||
!(features[i - 1][0] as Treasure).earned.value
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.map((row, i) => (i in displays ? render(displays[i]) : renderRow(...row)))}
|
|
||||||
{render(modifiersModal)}
|
{render(modifiersModal)}
|
||||||
</>
|
</>
|
||||||
)),
|
)),
|
||||||
|
|
|
@ -37,6 +37,7 @@ import {
|
||||||
} from "./boardUtils";
|
} from "./boardUtils";
|
||||||
import { Section, createCollapsibleModifierSections, createFormulaPreview } from "./common";
|
import { Section, createCollapsibleModifierSections, createFormulaPreview } from "./common";
|
||||||
import {
|
import {
|
||||||
|
AutomatorState,
|
||||||
BoosterState,
|
BoosterState,
|
||||||
DowsingState,
|
DowsingState,
|
||||||
EmpowererState,
|
EmpowererState,
|
||||||
|
@ -68,7 +69,8 @@ import {
|
||||||
portalGenerator,
|
portalGenerator,
|
||||||
quarry,
|
quarry,
|
||||||
resource,
|
resource,
|
||||||
upgrader
|
upgrader,
|
||||||
|
automator
|
||||||
} from "./nodeTypes";
|
} from "./nodeTypes";
|
||||||
import { GenericPlane, createPlane } from "./planes";
|
import { GenericPlane, createPlane } from "./planes";
|
||||||
|
|
||||||
|
@ -87,7 +89,8 @@ const types = {
|
||||||
portal,
|
portal,
|
||||||
influence,
|
influence,
|
||||||
booster,
|
booster,
|
||||||
upgrader
|
upgrader,
|
||||||
|
automator
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -113,7 +116,8 @@ export const main = createLayer("main", function (this: BaseLayer) {
|
||||||
coal: board.types.empowerer.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],
|
gold: board.types.booster.nodes.value[0],
|
||||||
platinum: board.types.upgrader.nodes.value[0]
|
platinum: board.types.upgrader.nodes.value[0],
|
||||||
|
berylium: board.types.automator.nodes.value[0]
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const influenceNodes: ComputedRef<Record<Influences, BoardNode>> = computed(() => ({
|
const influenceNodes: ComputedRef<Record<Influences, BoardNode>> = computed(() => ({
|
||||||
|
@ -123,6 +127,13 @@ export const main = createLayer("main", function (this: BaseLayer) {
|
||||||
}, {} as Record<Influences, BoardNode>)
|
}, {} as Record<Influences, BoardNode>)
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
const portalNodes: ComputedRef<Record<string, BoardNode>> = computed(() => ({
|
||||||
|
...board.types.portal.nodes.value.reduce((acc, curr) => {
|
||||||
|
acc[(curr.state as unknown as PortalState).id] = curr;
|
||||||
|
return acc;
|
||||||
|
}, {} as Record<string, BoardNode>)
|
||||||
|
}));
|
||||||
|
|
||||||
const resourceLevels = computed(() =>
|
const resourceLevels = computed(() =>
|
||||||
resourceNames.reduce((acc, curr) => {
|
resourceNames.reduce((acc, curr) => {
|
||||||
const amount =
|
const amount =
|
||||||
|
@ -337,10 +348,7 @@ export const main = createLayer("main", function (this: BaseLayer) {
|
||||||
links.push({
|
links.push({
|
||||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
startNode: booster.value!,
|
startNode: booster.value!,
|
||||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
endNode: portalNodes.value[portal],
|
||||||
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
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
stroke: isPowered(booster.value!) ? "var(--accent1)" : "var(--foreground)",
|
stroke: isPowered(booster.value!) ? "var(--accent1)" : "var(--foreground)",
|
||||||
strokeWidth: 4
|
strokeWidth: 4
|
||||||
|
@ -353,9 +361,19 @@ export const main = createLayer("main", function (this: BaseLayer) {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
startNode: upgrader.value!,
|
startNode: upgrader.value!,
|
||||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
endNode: (board as GenericBoard).types.portal.nodes.value.find(
|
endNode: portalNodes.value[portal],
|
||||||
node => (node.state as unknown as PortalState).id === portal
|
stroke: "var(--foreground)",
|
||||||
)!,
|
strokeWidth: 4
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (automator.value != null) {
|
||||||
|
(automator.value.state as unknown as AutomatorState).portals.forEach(portal => {
|
||||||
|
links.push({
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
|
startNode: automator.value!,
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
|
endNode: portalNodes.value[portal],
|
||||||
stroke: "var(--foreground)",
|
stroke: "var(--foreground)",
|
||||||
strokeWidth: 4
|
strokeWidth: 4
|
||||||
});
|
});
|
||||||
|
@ -390,7 +408,8 @@ export const main = createLayer("main", function (this: BaseLayer) {
|
||||||
);
|
);
|
||||||
const booster: ComputedRef<BoardNode | undefined> = computed(() => toolNodes.value.gold);
|
const booster: ComputedRef<BoardNode | undefined> = computed(() => toolNodes.value.gold);
|
||||||
const upgrader: ComputedRef<BoardNode | undefined> = computed(() => toolNodes.value.platinum);
|
const upgrader: ComputedRef<BoardNode | undefined> = computed(() => toolNodes.value.platinum);
|
||||||
const poweredMachines = [mine, dowsing, quarry, empowerer, booster, upgrader];
|
const automator: ComputedRef<BoardNode | undefined> = computed(() => toolNodes.value.berylium);
|
||||||
|
const poweredMachines = [mine, dowsing, quarry, empowerer, booster, upgrader, automator];
|
||||||
|
|
||||||
function grantResource(type: Resources, amount: DecimalSource) {
|
function grantResource(type: Resources, amount: DecimalSource) {
|
||||||
let node = resourceNodes.value[type];
|
let node = resourceNodes.value[type];
|
||||||
|
@ -800,6 +819,7 @@ export const main = createLayer("main", function (this: BaseLayer) {
|
||||||
checkConnections(curr, empowerer, "tools");
|
checkConnections(curr, empowerer, "tools");
|
||||||
checkConnections(curr, booster, "portals");
|
checkConnections(curr, booster, "portals");
|
||||||
checkConnections(curr, upgrader, "portals");
|
checkConnections(curr, upgrader, "portals");
|
||||||
|
checkConnections(curr, automator, "portals");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -822,6 +842,7 @@ export const main = createLayer("main", function (this: BaseLayer) {
|
||||||
empowerer,
|
empowerer,
|
||||||
booster,
|
booster,
|
||||||
upgrader,
|
upgrader,
|
||||||
|
automator,
|
||||||
resourceLevels,
|
resourceLevels,
|
||||||
planarMultis,
|
planarMultis,
|
||||||
display: jsx(() => (
|
display: jsx(() => (
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
import ClickableComponent from "features/clickables/Clickable.vue";
|
import ClickableComponent from "features/clickables/Clickable.vue";
|
||||||
import { GenericDecorator } from "features/decorators/common";
|
import { GenericDecorator } from "features/decorators/common";
|
||||||
import type {
|
import {
|
||||||
CoercableComponent,
|
CoercableComponent,
|
||||||
GenericComponent,
|
GenericComponent,
|
||||||
OptionsFunc,
|
OptionsFunc,
|
||||||
Replace,
|
Replace,
|
||||||
StyleValue
|
StyleValue,
|
||||||
|
findFeatures
|
||||||
} from "features/feature";
|
} from "features/feature";
|
||||||
import { Component, GatherProps, Visibility, getUniqueID, setDefault } from "features/feature";
|
import { Component, GatherProps, Visibility, getUniqueID, setDefault } from "features/feature";
|
||||||
import type { BaseLayer } from "game/layers";
|
import type { BaseLayer, GenericLayer } from "game/layers";
|
||||||
import type { Unsubscribe } from "nanoevents";
|
import type { Unsubscribe } from "nanoevents";
|
||||||
import type {
|
import type {
|
||||||
Computable,
|
Computable,
|
||||||
|
@ -190,15 +191,19 @@ export function createClickable<T extends ClickableOptions>(
|
||||||
* @param autoActive Whether or not the clickable should currently be auto-clicking
|
* @param autoActive Whether or not the clickable should currently be auto-clicking
|
||||||
*/
|
*/
|
||||||
export function setupAutoClick(
|
export function setupAutoClick(
|
||||||
layer: BaseLayer,
|
layer: GenericLayer,
|
||||||
clickable: GenericClickable,
|
autoActive: Computable<boolean>,
|
||||||
autoActive: Computable<boolean> = true
|
clickables: GenericClickable[] = []
|
||||||
): Unsubscribe {
|
): Unsubscribe {
|
||||||
|
clickables =
|
||||||
|
clickables.length === 0
|
||||||
|
? (findFeatures(layer, ClickableType) as GenericClickable[])
|
||||||
|
: clickables;
|
||||||
const isActive: ProcessedComputable<boolean> =
|
const isActive: ProcessedComputable<boolean> =
|
||||||
typeof autoActive === "function" ? computed(autoActive) : autoActive;
|
typeof autoActive === "function" ? computed(autoActive) : autoActive;
|
||||||
return layer.on("update", () => {
|
return layer.on("update", () => {
|
||||||
if (unref(isActive) && unref(clickable.canClick)) {
|
if (unref(isActive)) {
|
||||||
clickable.onClick?.();
|
clickables.filter(c => unref(c.canClick)).forEach(c => c.onClick?.());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue