mirror of
https://github.com/thepaperpilot/Planar-Pioneers.git
synced 2025-02-16 09:41:40 +00:00
Implement quarry machine
This commit is contained in:
parent
1e0666a36a
commit
d18f731c75
1 changed files with 222 additions and 92 deletions
|
@ -2,7 +2,9 @@ import Modal from "components/Modal.vue";
|
||||||
import StickyVue from "components/layout/Sticky.vue";
|
import StickyVue from "components/layout/Sticky.vue";
|
||||||
import {
|
import {
|
||||||
BoardNode,
|
BoardNode,
|
||||||
|
BoardNodeLink,
|
||||||
GenericBoard,
|
GenericBoard,
|
||||||
|
NodeLabel,
|
||||||
ProgressDisplay,
|
ProgressDisplay,
|
||||||
Shape,
|
Shape,
|
||||||
createBoard,
|
createBoard,
|
||||||
|
@ -52,6 +54,10 @@ export interface DowsingState {
|
||||||
powered: boolean;
|
powered: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface QuarryState extends DowsingState {
|
||||||
|
progress: DecimalSource;
|
||||||
|
}
|
||||||
|
|
||||||
const mineLootTable = {
|
const mineLootTable = {
|
||||||
dirt: 120,
|
dirt: 120,
|
||||||
sand: 60,
|
sand: 60,
|
||||||
|
@ -95,8 +101,9 @@ const tools = {
|
||||||
},
|
},
|
||||||
wood: {
|
wood: {
|
||||||
cost: 1e6,
|
cost: 1e6,
|
||||||
name: "Unknown Item", // (action node)
|
name: "Quarry",
|
||||||
type: "unknownType"
|
type: "quarry",
|
||||||
|
state: { resources: [], maxConnections: 1, powered: false, progress: 0 }
|
||||||
},
|
},
|
||||||
stone: {
|
stone: {
|
||||||
cost: 1e7,
|
cost: 1e7,
|
||||||
|
@ -208,7 +215,8 @@ export const main = createLayer("main", function (this: BaseLayer) {
|
||||||
acc[curr.state as Resources] = curr;
|
acc[curr.state as Resources] = curr;
|
||||||
return acc;
|
return acc;
|
||||||
}, {} as Record<Resources, BoardNode>),
|
}, {} as Record<Resources, BoardNode>),
|
||||||
sand: board.types.dowsing.nodes.value[0]
|
sand: board.types.dowsing.nodes.value[0],
|
||||||
|
wood: board.types.quarry.nodes.value[0]
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const resourceLevels = computed(() =>
|
const resourceLevels = computed(() =>
|
||||||
|
@ -252,6 +260,7 @@ export const main = createLayer("main", function (this: BaseLayer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const resourceMinedCooldown: Partial<Record<Resources, number>> = reactive({});
|
const resourceMinedCooldown: Partial<Record<Resources, number>> = reactive({});
|
||||||
|
const resourceQuarriedCooldown: Partial<Record<Resources, number>> = reactive({});
|
||||||
|
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
resourceNames.forEach(resource => {
|
resourceNames.forEach(resource => {
|
||||||
|
@ -279,8 +288,9 @@ export const main = createLayer("main", function (this: BaseLayer) {
|
||||||
});
|
});
|
||||||
|
|
||||||
const poweredMachines: ComputedRef<number> = computed(() => {
|
const poweredMachines: ComputedRef<number> = computed(() => {
|
||||||
return [mine, dowsing].filter(node => (node.value?.state as { powered: boolean })?.powered)
|
return [mine, dowsing, quarry].filter(
|
||||||
.length;
|
node => (node.value?.state as { powered: boolean })?.powered
|
||||||
|
).length;
|
||||||
});
|
});
|
||||||
const nextPowerCost = computed(() =>
|
const nextPowerCost = computed(() =>
|
||||||
Decimal.eq(poweredMachines.value, 0)
|
Decimal.eq(poweredMachines.value, 0)
|
||||||
|
@ -288,6 +298,30 @@ export const main = createLayer("main", function (this: BaseLayer) {
|
||||||
: Decimal.add(poweredMachines.value, 1).pow_base(100).div(10).times(0.99)
|
: Decimal.add(poweredMachines.value, 1).pow_base(100).div(10).times(0.99)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const quarryProgressRequired = computed(() => {
|
||||||
|
if (quarry.value == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
const resources = (quarry.value.state as unknown as QuarryState).resources;
|
||||||
|
return resources.reduce(
|
||||||
|
(acc, curr) => Decimal.div(100, dropRates[curr].computedModifier.value).add(acc),
|
||||||
|
Decimal.dZero
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
const deselectAllAction = {
|
||||||
|
id: "deselect",
|
||||||
|
icon: "close",
|
||||||
|
tooltip: { text: "Disconnect resources" },
|
||||||
|
onClick(node: BoardNode) {
|
||||||
|
node.state = { ...(node.state as object), resources: [] };
|
||||||
|
board.selectedAction.value = null;
|
||||||
|
board.selectedNode.value = null;
|
||||||
|
},
|
||||||
|
visibility: (node: BoardNode) =>
|
||||||
|
(node.state as { resources: Resources[] }).resources.length > 0
|
||||||
|
};
|
||||||
|
|
||||||
const togglePoweredAction = {
|
const togglePoweredAction = {
|
||||||
id: "toggle",
|
id: "toggle",
|
||||||
icon: "bolt",
|
icon: "bolt",
|
||||||
|
@ -341,6 +375,64 @@ export const main = createLayer("main", function (this: BaseLayer) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function labelForAcceptingResource(
|
||||||
|
node: BoardNode,
|
||||||
|
description: (resource: Resources) => string
|
||||||
|
): NodeLabel | null {
|
||||||
|
if ((board as GenericBoard).draggingNode.value?.type === "resource") {
|
||||||
|
const resource = (
|
||||||
|
(board as GenericBoard).draggingNode.value?.state as unknown as ResourceState
|
||||||
|
).type;
|
||||||
|
const { maxConnections, resources } = node.state as unknown as DowsingState;
|
||||||
|
if (resources.includes(resource)) {
|
||||||
|
return { text: "Disconnect", color: "var(--accent2)" };
|
||||||
|
}
|
||||||
|
if (resources.length === maxConnections) {
|
||||||
|
return { text: "Max connections", color: "var(--danger)" };
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
text: description(resource),
|
||||||
|
color: "var(--accent2)"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function canAcceptResource(node: BoardNode, otherNode: BoardNode) {
|
||||||
|
if (otherNode.type !== "resource") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const resource = (otherNode.state as unknown as ResourceState).type;
|
||||||
|
const { maxConnections, resources } = node.state as unknown as DowsingState;
|
||||||
|
if (resources.includes(resource)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (resources.length === maxConnections) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function onDropResource(node: BoardNode, otherNode: BoardNode) {
|
||||||
|
if (otherNode.type !== "resource") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const resource = (otherNode.state as unknown as ResourceState).type;
|
||||||
|
const resources = (node.state as unknown as { resources: Resources[] }).resources;
|
||||||
|
if (resources.includes(resource)) {
|
||||||
|
node.state = {
|
||||||
|
...(node.state as object),
|
||||||
|
resources: resources.filter(r => r !== resource)
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
node.state = {
|
||||||
|
...(node.state as object),
|
||||||
|
resources: [...resources, resource]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
board.selectedNode.value = node;
|
||||||
|
}
|
||||||
|
|
||||||
const board = createBoard(board => ({
|
const board = createBoard(board => ({
|
||||||
startNodes: () => [
|
startNodes: () => [
|
||||||
{ position: { x: 0, y: 0 }, type: "mine", state: { progress: 0, powered: false } },
|
{ position: { x: 0, y: 0 }, type: "mine", state: { progress: 0, powered: false } },
|
||||||
|
@ -432,6 +524,17 @@ export const main = createLayer("main", function (this: BaseLayer) {
|
||||||
},
|
},
|
||||||
actionDistance: Math.PI / 4,
|
actionDistance: Math.PI / 4,
|
||||||
actions: [
|
actions: [
|
||||||
|
{
|
||||||
|
id: "deselect",
|
||||||
|
icon: "close",
|
||||||
|
tooltip: { text: "Disconnect resource" },
|
||||||
|
onClick(node) {
|
||||||
|
node.state = undefined;
|
||||||
|
board.selectedAction.value = null;
|
||||||
|
board.selectedNode.value = null;
|
||||||
|
},
|
||||||
|
visibility: node => node.state != null
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: "craft",
|
id: "craft",
|
||||||
icon: "done",
|
icon: "done",
|
||||||
|
@ -472,17 +575,6 @@ export const main = createLayer("main", function (this: BaseLayer) {
|
||||||
? { text: "Tap again to confirm" }
|
? { text: "Tap again to confirm" }
|
||||||
: { text: "Already crafted", color: "var(--danger)" }
|
: { text: "Already crafted", color: "var(--danger)" }
|
||||||
: { text: "Cannot afford", color: "var(--danger)" }
|
: { text: "Cannot afford", color: "var(--danger)" }
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "deselect",
|
|
||||||
icon: "close",
|
|
||||||
tooltip: { text: "Disconnect resource" },
|
|
||||||
onClick(node) {
|
|
||||||
node.state = undefined;
|
|
||||||
board.selectedAction.value = null;
|
|
||||||
board.selectedNode.value = null;
|
|
||||||
},
|
|
||||||
visibility: node => node.state != null
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
canAccept(node, otherNode) {
|
canAccept(node, otherNode) {
|
||||||
|
@ -544,86 +636,76 @@ export const main = createLayer("main", function (this: BaseLayer) {
|
||||||
text:
|
text:
|
||||||
(node.state as unknown as DowsingState).resources.length === 0
|
(node.state as unknown as DowsingState).resources.length === 0
|
||||||
? "Dowsing - Drag a resource to me!"
|
? "Dowsing - Drag a resource to me!"
|
||||||
: `Dowsing - Doubling ${
|
: `Dowsing (${
|
||||||
(node.state as { resources: Resources[] }).resources
|
(node.state as { resources: Resources[] }).resources
|
||||||
.length
|
.length
|
||||||
}/${
|
}/${
|
||||||
(node.state as { maxConnections: number }).maxConnections
|
(node.state as { maxConnections: number }).maxConnections
|
||||||
} materials' odds`
|
})`
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if ((board as GenericBoard).draggingNode.value?.type === "resource") {
|
return labelForAcceptingResource(node, resource => `Double ${resource} odds`);
|
||||||
const resource = (
|
|
||||||
(board as GenericBoard).draggingNode.value
|
|
||||||
?.state as unknown as ResourceState
|
|
||||||
).type;
|
|
||||||
const { maxConnections, resources } = node.state as unknown as DowsingState;
|
|
||||||
if (resources.includes(resource)) {
|
|
||||||
return { text: "Disconnect", color: "var(--accent2)" };
|
|
||||||
}
|
|
||||||
if (resources.length === maxConnections) {
|
|
||||||
return { text: "Max connections", color: "var(--danger)" };
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
text: `Double ${resource} odds`,
|
|
||||||
color: "var(--accent2)"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
},
|
},
|
||||||
actionDistance: Math.PI / 4,
|
actionDistance: Math.PI / 4,
|
||||||
actions: [
|
actions: [
|
||||||
{
|
deselectAllAction,
|
||||||
id: "deselect",
|
|
||||||
icon: "close",
|
|
||||||
tooltip: { text: "Disconnect resources" },
|
|
||||||
onClick(node) {
|
|
||||||
node.state = { ...(node.state as object), resources: [] };
|
|
||||||
board.selectedAction.value = null;
|
|
||||||
board.selectedNode.value = null;
|
|
||||||
},
|
|
||||||
visibility: node =>
|
|
||||||
(node.state as unknown as DowsingState).resources.length > 0
|
|
||||||
},
|
|
||||||
getIncreaseConnectionsAction(x => x.add(2).pow_base(100), 16),
|
getIncreaseConnectionsAction(x => x.add(2).pow_base(100), 16),
|
||||||
togglePoweredAction
|
togglePoweredAction
|
||||||
],
|
],
|
||||||
classes: node => ({
|
classes: node => ({
|
||||||
running: isPowered(node)
|
running: isPowered(node)
|
||||||
}),
|
}),
|
||||||
canAccept(node, otherNode) {
|
canAccept: canAcceptResource,
|
||||||
if (otherNode.type !== "resource") {
|
onDrop: onDropResource,
|
||||||
return false;
|
draggable: true
|
||||||
}
|
},
|
||||||
const resource = (otherNode.state as unknown as ResourceState).type;
|
quarry: {
|
||||||
const { maxConnections, resources } = node.state as unknown as DowsingState;
|
shape: Shape.Diamond,
|
||||||
if (resources.includes(resource)) {
|
size: 50,
|
||||||
return true;
|
title: "⛏️",
|
||||||
}
|
label: node => {
|
||||||
if (resources.length === maxConnections) {
|
if (node === board.selectedNode.value) {
|
||||||
return false;
|
return {
|
||||||
}
|
text:
|
||||||
return true;
|
(node.state as unknown as DowsingState).resources.length === 0
|
||||||
},
|
? "Quarry - Drag a resource to me!"
|
||||||
onDrop(node, otherNode) {
|
: `Quarrying (${
|
||||||
if (otherNode.type !== "resource") {
|
(node.state as { resources: Resources[] }).resources
|
||||||
return;
|
.length
|
||||||
}
|
}/${
|
||||||
const resource = (otherNode.state as unknown as ResourceState).type;
|
(node.state as { maxConnections: number }).maxConnections
|
||||||
const resources = (node.state as unknown as DowsingState).resources;
|
})`
|
||||||
if (resources.includes(resource)) {
|
|
||||||
node.state = {
|
|
||||||
...(node.state as object),
|
|
||||||
resources: resources.filter(r => r !== resource)
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
node.state = {
|
|
||||||
...(node.state as object),
|
|
||||||
resources: [...resources, resource]
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
board.selectedNode.value = node;
|
return labelForAcceptingResource(
|
||||||
|
node,
|
||||||
|
resource =>
|
||||||
|
`Gather ${format(
|
||||||
|
Decimal.div(dropRates[resource].computedModifier.value, 100)
|
||||||
|
)} ${resource}/s`
|
||||||
|
);
|
||||||
},
|
},
|
||||||
|
actionDistance: Math.PI / 4,
|
||||||
|
actions: [
|
||||||
|
deselectAllAction,
|
||||||
|
getIncreaseConnectionsAction(x => x.add(2).pow_base(10000), 16),
|
||||||
|
togglePoweredAction
|
||||||
|
],
|
||||||
|
progress: node =>
|
||||||
|
isPowered(node)
|
||||||
|
? Decimal.eq(quarryProgressRequired.value, 0)
|
||||||
|
? 0
|
||||||
|
: new Decimal((node.state as unknown as QuarryState).progress)
|
||||||
|
.div(quarryProgressRequired.value)
|
||||||
|
.toNumber()
|
||||||
|
: 0,
|
||||||
|
progressDisplay: ProgressDisplay.Outline,
|
||||||
|
progressColor: "var(--accent2)",
|
||||||
|
canAccept: canAcceptResource,
|
||||||
|
onDrop: onDropResource,
|
||||||
|
classes: node => ({
|
||||||
|
running: isPowered(node)
|
||||||
|
}),
|
||||||
draggable: true
|
draggable: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -636,12 +718,15 @@ export const main = createLayer("main", function (this: BaseLayer) {
|
||||||
overflow: "hidden"
|
overflow: "hidden"
|
||||||
},
|
},
|
||||||
links() {
|
links() {
|
||||||
const links = Object.keys(resourceMinedCooldown).map(resource => ({
|
const links: BoardNodeLink[] = [];
|
||||||
startNode: mine.value,
|
links.push(
|
||||||
endNode: resourceNodes.value[resource as Resources],
|
...Object.keys(resourceMinedCooldown).map(resource => ({
|
||||||
stroke: "var(--accent3)",
|
startNode: mine.value,
|
||||||
strokeWidth: 5
|
endNode: resourceNodes.value[resource as Resources],
|
||||||
}));
|
stroke: "var(--accent3)",
|
||||||
|
strokeWidth: 5
|
||||||
|
}))
|
||||||
|
);
|
||||||
if (factory.value != null && factory.value.state != null) {
|
if (factory.value != null && factory.value.state != null) {
|
||||||
links.push({
|
links.push({
|
||||||
startNode: factory.value,
|
startNode: factory.value,
|
||||||
|
@ -662,6 +747,27 @@ export const main = createLayer("main", function (this: BaseLayer) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (quarry.value != null) {
|
||||||
|
(quarry.value.state as unknown as QuarryState).resources.forEach(resource => {
|
||||||
|
links.push({
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
|
startNode: quarry.value!,
|
||||||
|
endNode: resourceNodes.value[resource],
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
|
stroke: "var(--foreground)",
|
||||||
|
strokeWidth: 4
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
links.push(
|
||||||
|
...Object.keys(resourceQuarriedCooldown).map(resource => ({
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
|
startNode: quarry.value!,
|
||||||
|
endNode: resourceNodes.value[resource as Resources],
|
||||||
|
stroke: "var(--accent3)",
|
||||||
|
strokeWidth: 5
|
||||||
|
}))
|
||||||
|
);
|
||||||
return links;
|
return links;
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
@ -670,15 +776,12 @@ export const main = createLayer("main", function (this: BaseLayer) {
|
||||||
return node === board.selectedNode.value || (node.state as { powered: boolean }).powered;
|
return node === board.selectedNode.value || (node.state as { powered: boolean }).powered;
|
||||||
}
|
}
|
||||||
|
|
||||||
const mine: ComputedRef<BoardNode> = computed(
|
const mine: ComputedRef<BoardNode> = computed(() => board.types.mine.nodes.value[0]);
|
||||||
() => board.nodes.value.find(n => n.type === "mine") as BoardNode
|
const factory: ComputedRef<BoardNode | undefined> = computed(
|
||||||
);
|
() => board.types.factory.nodes.value[0]
|
||||||
const factory: ComputedRef<BoardNode | undefined> = computed(() =>
|
|
||||||
board.nodes.value.find(n => n.type === "factory")
|
|
||||||
);
|
|
||||||
const dowsing: ComputedRef<BoardNode | undefined> = computed(() =>
|
|
||||||
board.nodes.value.find(n => n.type === "dowsing")
|
|
||||||
);
|
);
|
||||||
|
const dowsing: ComputedRef<BoardNode | undefined> = computed(() => toolNodes.value.sand);
|
||||||
|
const quarry: ComputedRef<BoardNode | undefined> = computed(() => toolNodes.value.wood);
|
||||||
|
|
||||||
function grantResource(type: Resources, amount: DecimalSource) {
|
function grantResource(type: Resources, amount: DecimalSource) {
|
||||||
let node = resourceNodes.value[type];
|
let node = resourceNodes.value[type];
|
||||||
|
@ -873,6 +976,14 @@ export const main = createLayer("main", function (this: BaseLayer) {
|
||||||
delete resourceMinedCooldown[resource as Resources];
|
delete resourceMinedCooldown[resource as Resources];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
Object.keys(resourceQuarriedCooldown).forEach(resource => {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
|
resourceQuarriedCooldown[resource as Resources]! -= diff;
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
|
if (resourceQuarriedCooldown[resource as Resources]! <= 0) {
|
||||||
|
delete resourceQuarriedCooldown[resource as Resources];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if (isPowered(mine.value)) {
|
if (isPowered(mine.value)) {
|
||||||
const progress = Decimal.add(
|
const progress = Decimal.add(
|
||||||
|
@ -913,6 +1024,25 @@ export const main = createLayer("main", function (this: BaseLayer) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (quarry.value != null && isPowered(quarry.value)) {
|
||||||
|
const { progress, resources } = quarry.value.state as unknown as QuarryState;
|
||||||
|
if (resources.length > 0) {
|
||||||
|
let newProgress = Decimal.add(progress, diff);
|
||||||
|
const completions = Decimal.div(progress, quarryProgressRequired.value).floor();
|
||||||
|
newProgress = Decimal.sub(
|
||||||
|
newProgress,
|
||||||
|
Decimal.times(completions, quarryProgressRequired.value)
|
||||||
|
);
|
||||||
|
quarry.value.state = { ...(quarry.value.state as object), progress: newProgress };
|
||||||
|
if (Decimal.gt(completions, 0)) {
|
||||||
|
resources.forEach(resource => {
|
||||||
|
grantResource(resource, completions);
|
||||||
|
resourceQuarriedCooldown[resource] = 0.3;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
energy.value = Decimal.add(energy.value, Decimal.times(computedEnergyModifier.value, diff));
|
energy.value = Decimal.add(energy.value, Decimal.times(computedEnergyModifier.value, diff));
|
||||||
|
|
||||||
if (Decimal.lt(energy.value, 0)) {
|
if (Decimal.lt(energy.value, 0)) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue