Implement remaining forgable passives

This commit is contained in:
thepaperpilot 2023-05-03 21:47:33 -05:00
parent 6f2edb8f0c
commit 8c59fba254
2 changed files with 191 additions and 100 deletions

View file

@ -3,11 +3,11 @@ import SpacerVue from "components/layout/Spacer.vue";
import StickyVue from "components/layout/Sticky.vue"; import StickyVue from "components/layout/Sticky.vue";
import { GenericAchievement, createAchievement } from "features/achievements/achievement"; import { GenericAchievement, createAchievement } from "features/achievements/achievement";
import { BoardNode, getUniqueNodeID } from "features/boards/board"; import { BoardNode, getUniqueNodeID } from "features/boards/board";
import { jsx } from "features/feature"; import { findFeatures, jsx } from "features/feature";
import { createRepeatable } from "features/repeatable"; import { GenericRepeatable, RepeatableType, createRepeatable } from "features/repeatable";
import { createResource } from "features/resources/resource"; import { createResource } from "features/resources/resource";
import { addTooltip } from "features/tooltips/tooltip"; import { addTooltip } from "features/tooltips/tooltip";
import { createUpgrade } from "features/upgrades/upgrade"; import { GenericUpgrade, UpgradeType, createUpgrade } from "features/upgrades/upgrade";
import Formula, { unrefFormulaSource } from "game/formulas/formulas"; import Formula, { unrefFormulaSource } from "game/formulas/formulas";
import { FormulaSource, GenericFormula } from "game/formulas/types"; import { FormulaSource, GenericFormula } from "game/formulas/types";
import { BaseLayer, createLayer } from "game/layers"; import { BaseLayer, createLayer } from "game/layers";
@ -65,6 +65,7 @@ export function createPlane(
const color = getColor([0.64, 0.75, 0.55], random); const color = getColor([0.64, 0.75, 0.55], random);
const background = getColor([0.18, 0.2, 0.25], random); const background = getColor([0.18, 0.2, 0.25], random);
const resource = createResource<DecimalSource>(0, getName(random)); const resource = createResource<DecimalSource>(0, getName(random));
const timeActive = persistent<DecimalSource>(0);
const tierIndex = resourceNames.indexOf(tier); const tierIndex = resourceNames.indexOf(tier);
let difficultyRand = random(); let difficultyRand = random();
const influenceState = influences.reduce((acc, curr) => { const influenceState = influences.reduce((acc, curr) => {
@ -89,7 +90,31 @@ export function createPlane(
} }
const resourceModifiers: WithRequired<Modifier, "description" | "invert">[] = []; const resourceModifiers: WithRequired<Modifier, "description" | "invert">[] = [];
const resourceGainModifier = createSequentialModifier(() => resourceModifiers); const resourceGainModifier = createSequentialModifier(() => [
...resourceModifiers,
createMultiplicativeModifier(() => ({
multiplier: () => (main.isEmpowered("silver") ? 4 : 2),
description: () =>
(main.isEmpowered("silver") ? "Empowered " : "") + main.tools.silver.name,
enabled: () => main.toolNodes.value.silver != null
})),
createMultiplicativeModifier(() => ({
multiplier: () =>
((main.isEmpowered("diamond") ? 2 : 1) *
upgrades.filter(u => u.bought.value).length) /
10,
description: () =>
(main.isEmpowered("diamond") ? "Empowered " : "") + main.tools.diamond.name,
enabled: () => main.toolNodes.value.diamond != null
})),
createMultiplicativeModifier(() => ({
multiplier: () =>
Decimal.div(timeActive.value, 6000).times(main.isEmpowered("emerald") ? 2 : 1),
description: () =>
(main.isEmpowered("emerald") ? "Empowered " : "") + main.tools.emerald.name,
enabled: () => main.toolNodes.value.emerald != null
}))
]);
const computedResourceGain = computed(() => resourceGainModifier.apply(0)); const computedResourceGain = computed(() => resourceGainModifier.apply(0));
const previews: { const previews: {
@ -492,6 +517,15 @@ export function createPlane(
visibility = milestone.earned; visibility = milestone.earned;
} }
const upgrades = findFeatures(
features as unknown as Record<string, unknown>,
UpgradeType
) as GenericUpgrade[];
const repeatables = findFeatures(
features as unknown as Record<string, unknown>,
RepeatableType
) as GenericRepeatable[];
const [resourceTab, resourceTabCollapsed] = createCollapsibleModifierSections(() => [ const [resourceTab, resourceTabCollapsed] = createCollapsibleModifierSections(() => [
{ {
title: `${camelToTitle(resource.displayName)} Gain`, title: `${camelToTitle(resource.displayName)} Gain`,
@ -519,6 +553,7 @@ export function createPlane(
return; return;
} }
timeActive.value = Decimal.add(timeActive.value, diff);
resource.value = Decimal.times(computedResourceGain.value, diff).add(resource.value); resource.value = Decimal.times(computedResourceGain.value, diff).add(resource.value);
earnedTreasures.value.forEach(treasure => { earnedTreasures.value.forEach(treasure => {
@ -645,6 +680,7 @@ export function createPlane(
resourceMultis, resourceMultis,
earnedTreasures, earnedTreasures,
showNotif, showNotif,
timeActive,
display: jsx(() => ( display: jsx(() => (
<> <>
<StickyVue class="nav-container" style="z-index: 5"> <StickyVue class="nav-container" style="z-index: 5">

View file

@ -252,8 +252,8 @@ const passives = {
diamond: { diamond: {
description: (empowered: boolean) => description: (empowered: boolean) =>
empowered empowered
? "+2% plane's resource gain per repeatable purchase" ? "+20% plane's resource gain per upgrade bought"
: "+1% plane's resource gain per repeatable purchase" : "+10% plane's resource gain per upgrade bought"
}, },
emerald: { emerald: {
description: (empowered: boolean) => description: (empowered: boolean) =>
@ -476,6 +476,14 @@ export const main = createLayer("main", function (this: BaseLayer) {
}, {} as Record<Influences, BoardNode>) }, {} as Record<Influences, BoardNode>)
})); }));
function isEmpowered(passive: Passives) {
return (
empowerer.value != null &&
isPowered(empowerer.value) &&
(empowerer.value.state as unknown as EmpowererState).tools.includes(passive)
);
}
const resourceLevels = computed(() => const resourceLevels = computed(() =>
resourceNames.reduce((acc, curr) => { resourceNames.reduce((acc, curr) => {
const amount = const amount =
@ -544,20 +552,19 @@ export const main = createLayer("main", function (this: BaseLayer) {
}); });
}); });
const poweredMachines: ComputedRef<number> = computed(() => { const numPoweredMachines: ComputedRef<number> = computed(() => {
return ( return (
[mine, dowsing, quarry, empowerer].filter( poweredMachines.filter(node => (node.value?.state as { powered: boolean })?.powered)
node => (node.value?.state as { powered: boolean })?.powered .length +
).length +
board.types.portal.nodes.value.filter( board.types.portal.nodes.value.filter(
node => (node.state as { powered: boolean }).powered node => (node.state as { powered: boolean }).powered
).length ).length
); );
}); });
const nextPowerCost = computed(() => const nextPowerCost = computed(() =>
Decimal.eq(poweredMachines.value, 0) Decimal.eq(numPoweredMachines.value, 0)
? 10 ? 10
: Decimal.add(poweredMachines.value, 1).pow_base(100).div(10).times(0.99) : Decimal.add(numPoweredMachines.value, 1).pow_base(100).div(10).times(0.99)
); );
const quarryProgressRequired = computed(() => { const quarryProgressRequired = computed(() => {
@ -653,12 +660,18 @@ export const main = createLayer("main", function (this: BaseLayer) {
} }
node.state = { node.state = {
...(node.state as object), ...(node.state as object),
maxConnections: (node.state as { maxConnections: number }).maxConnections + 1 maxConnections: Decimal.add(
(node.state as { maxConnections: number }).maxConnections,
1
)
}; };
board.selectedAction.value = null; board.selectedAction.value = null;
}, },
visibility: (node: BoardNode) => visibility: (node: BoardNode) =>
(node.state as { maxConnections: number }).maxConnections < maxConnections Decimal.add(
(node.state as { maxConnections: number }).maxConnections,
computedBonusConnectionsModifier.value
).lt(maxConnections)
}; };
} }
@ -674,7 +687,11 @@ export const main = createLayer("main", function (this: BaseLayer) {
if (resources.includes(resource)) { if (resources.includes(resource)) {
return { text: "Disconnect", color: "var(--accent2)" }; return { text: "Disconnect", color: "var(--accent2)" };
} }
if (resources.length === maxConnections) { if (
Decimal.add(maxConnections, computedBonusConnectionsModifier.value).lte(
resources.length
)
) {
return { text: "Max connections", color: "var(--danger)" }; return { text: "Max connections", color: "var(--danger)" };
} }
return { return {
@ -695,7 +712,11 @@ export const main = createLayer("main", function (this: BaseLayer) {
if (tools.includes(passive)) { if (tools.includes(passive)) {
return { text: "Disconnect", color: "var(--accent2)" }; return { text: "Disconnect", color: "var(--accent2)" };
} }
if (tools.length === maxConnections) { if (
Decimal.add(maxConnections, computedBonusConnectionsModifier.value).lte(
tools.length
)
) {
return { text: "Max connections", color: "var(--danger)" }; return { text: "Max connections", color: "var(--danger)" };
} }
return { return {
@ -715,7 +736,11 @@ export const main = createLayer("main", function (this: BaseLayer) {
if (resources.includes(resource)) { if (resources.includes(resource)) {
return true; return true;
} }
if (resources.length === maxConnections) { if (
Decimal.add(maxConnections, computedBonusConnectionsModifier.value).lte(
resources.length
)
) {
return false; return false;
} }
return true; return true;
@ -750,7 +775,7 @@ export const main = createLayer("main", function (this: BaseLayer) {
if (tools.includes(passive)) { if (tools.includes(passive)) {
return true; return true;
} }
if (tools.length === maxConnections) { if (Decimal.add(maxConnections, computedBonusConnectionsModifier.value).lte(tools.length)) {
return false; return false;
} }
return true; return true;
@ -978,22 +1003,13 @@ export const main = createLayer("main", function (this: BaseLayer) {
node === board.selectedNode.value node === board.selectedNode.value
? { ? {
text: passives[node.state as Passives].description( text: passives[node.state as Passives].description(
empowerer.value != null && isEmpowered(node.state as Passives)
isPowered(empowerer.value) &&
(
empowerer.value.state as unknown as EmpowererState
).tools.includes(node.state as Passives)
) )
} }
: null, : null,
outlineColor: "var(--bought)", outlineColor: "var(--bought)",
classes: node => ({ classes: node => ({
"affected-node": "affected-node": isEmpowered(node.state as Passives)
empowerer.value != null &&
isPowered(empowerer.value) &&
(empowerer.value.state as unknown as EmpowererState).tools.includes(
node.state as Passives
)
}), }),
draggable: true draggable: true
}, },
@ -1010,9 +1026,10 @@ export const main = createLayer("main", function (this: BaseLayer) {
: `Dowsing (${ : `Dowsing (${
(node.state as { resources: Resources[] }).resources (node.state as { resources: Resources[] }).resources
.length .length
}/${ }/${Decimal.add(
(node.state as { maxConnections: number }).maxConnections (node.state as { maxConnections: number }).maxConnections,
})` computedBonusConnectionsModifier.value
)})`
}; };
} }
return labelForAcceptingResource(node, resource => `Double ${resource} odds`); return labelForAcceptingResource(node, resource => `Double ${resource} odds`);
@ -1043,9 +1060,10 @@ export const main = createLayer("main", function (this: BaseLayer) {
: `Quarrying (${ : `Quarrying (${
(node.state as { resources: Resources[] }).resources (node.state as { resources: Resources[] }).resources
.length .length
}/${ }/${Decimal.add(
(node.state as { maxConnections: number }).maxConnections (node.state as { maxConnections: number }).maxConnections,
})` computedBonusConnectionsModifier.value
)})`
}; };
} }
return labelForAcceptingResource( return labelForAcceptingResource(
@ -1091,9 +1109,10 @@ export const main = createLayer("main", function (this: BaseLayer) {
? "Empowerer - Drag a tool to me!" ? "Empowerer - Drag a tool to me!"
: `Empowering (${ : `Empowering (${
(node.state as { tools: Passives[] }).tools.length (node.state as { tools: Passives[] }).tools.length
}/${ }/${Decimal.add(
(node.state as { maxConnections: number }).maxConnections (node.state as { maxConnections: number }).maxConnections,
})` computedBonusConnectionsModifier.value
)})`
}; };
} }
return labelForAcceptingTool(node, passive => { return labelForAcceptingTool(node, passive => {
@ -1503,6 +1522,7 @@ export const main = createLayer("main", function (this: BaseLayer) {
const portalGenerator: ComputedRef<BoardNode | undefined> = computed( const portalGenerator: ComputedRef<BoardNode | undefined> = computed(
() => toolNodes.value.iron () => toolNodes.value.iron
); );
const poweredMachines = [mine, dowsing, quarry, empowerer];
function grantResource(type: Resources, amount: DecimalSource) { function grantResource(type: Resources, amount: DecimalSource) {
let node = resourceNodes.value[type]; let node = resourceNodes.value[type];
@ -1575,19 +1595,9 @@ export const main = createLayer("main", function (this: BaseLayer) {
})) }))
), ),
createMultiplicativeModifier(() => ({ createMultiplicativeModifier(() => ({
multiplier: () => multiplier: () => (isEmpowered("stone") ? 4 : 2),
empowerer.value != null && description: () => (isEmpowered("stone") ? "Empowered " : "") + tools.stone.name,
isPowered(empowerer.value) && enabled: () => toolNodes.value.stone != null
(empowerer.value.state as unknown as EmpowererState).tools.includes("stone")
? 4
: 2,
description: () =>
(empowerer.value != null &&
isPowered(empowerer.value) &&
(empowerer.value.state as unknown as EmpowererState).tools.includes("stone")
? "Empowered "
: "") + tools.stone.name,
enabled: () => toolNodes.value["stone"] != null
})), })),
createMultiplicativeModifier(() => ({ createMultiplicativeModifier(() => ({
multiplier: () => planarMultis.value.energy ?? 1, multiplier: () => planarMultis.value.energy ?? 1,
@ -1595,66 +1605,46 @@ export const main = createLayer("main", function (this: BaseLayer) {
enabled: () => Decimal.neq(planarMultis.value.energy ?? 1, 1) enabled: () => Decimal.neq(planarMultis.value.energy ?? 1, 1)
})), })),
createAdditiveModifier(() => ({ createAdditiveModifier(() => ({
addend: () => Decimal.pow(100, poweredMachines.value).div(10).neg(), addend: () => Decimal.pow(100, numPoweredMachines.value).div(10).neg(),
description: "Powered Machines (100^n/10 energy/s)", description: "Powered Machines (100^n/10 energy/s)",
enabled: () => Decimal.gt(poweredMachines.value, 0) enabled: () => Decimal.gt(numPoweredMachines.value, 0)
})) }))
]); ]);
const computedEnergyModifier = computed(() => energyModifier.apply(1)); const computedEnergyModifier = computed(() => energyModifier.apply(1));
const bonusConnectionsModifier = createSequentialModifier(() => [
createAdditiveModifier(() => ({
addend: () => (isEmpowered("unobtainium") ? 2 : 1),
description: () =>
(isEmpowered("unobtainium") ? "Empowered " : "") + tools.unobtainium.name,
enabled: () => toolNodes.value.unobtainium != null
}))
]);
const computedBonusConnectionsModifier = computed(() => bonusConnectionsModifier.apply(0));
const miningSpeedModifier = createSequentialModifier(() => [ const miningSpeedModifier = createSequentialModifier(() => [
createMultiplicativeModifier(() => ({ createMultiplicativeModifier(() => ({
multiplier: () => multiplier: () => (isEmpowered("dirt") ? 4 : 2),
empowerer.value != null && description: () => (isEmpowered("dirt") ? "Empowered " : "") + tools.dirt.name,
isPowered(empowerer.value) && enabled: () => toolNodes.value.dirt != null
(empowerer.value.state as unknown as EmpowererState).tools.includes("dirt")
? 4
: 2,
description: () =>
(empowerer.value != null &&
isPowered(empowerer.value) &&
(empowerer.value.state as unknown as EmpowererState).tools.includes("dirt")
? "Empowered "
: "") + tools.dirt.name,
enabled: () => toolNodes.value["dirt"] != null
})) }))
]); ]);
const computedMiningSpeedModifier = computed(() => miningSpeedModifier.apply(1)); const computedMiningSpeedModifier = computed(() => miningSpeedModifier.apply(1));
const materialGainModifier = createSequentialModifier(() => [ const materialGainModifier = createSequentialModifier(() => [
createMultiplicativeModifier(() => ({ createMultiplicativeModifier(() => ({
multiplier: () => multiplier: () => (isEmpowered("gravel") ? 4 : 2),
empowerer.value != null && description: () => (isEmpowered("gravel") ? "Empowered " : "") + tools.gravel.name,
isPowered(empowerer.value) && enabled: () => toolNodes.value.gravel != null
(empowerer.value.state as unknown as EmpowererState).tools.includes("gravel")
? 4
: 2,
description: () =>
(empowerer.value != null &&
isPowered(empowerer.value) &&
(empowerer.value.state as unknown as EmpowererState).tools.includes("gravel")
? "Empowered "
: "") + tools.gravel.name,
enabled: () => toolNodes.value["gravel"] != null
})) }))
]); ]);
const computedMaterialGainModifier = computed(() => materialGainModifier.apply(1)); const computedMaterialGainModifier = computed(() => materialGainModifier.apply(1));
const materialLevelEffectModifier = createSequentialModifier(() => [ const materialLevelEffectModifier = createSequentialModifier(() => [
createAdditiveModifier(() => ({ createAdditiveModifier(() => ({
addend: () => addend: () => (isEmpowered("copper") ? 0.002 : 0.001),
empowerer.value != null && description: () => (isEmpowered("copper") ? "Empowered " : "") + tools.copper.name,
isPowered(empowerer.value) && enabled: () => toolNodes.value.copper != null
(empowerer.value.state as unknown as EmpowererState).tools.includes("copper")
? 0.002
: 0.001,
description: () =>
(empowerer.value != null &&
isPowered(empowerer.value) &&
(empowerer.value.state as unknown as EmpowererState).tools.includes("copper")
? "Empowered "
: "") + tools.copper.name,
enabled: () => toolNodes.value["copper"] != null
})) }))
]); ]);
const computedmaterialLevelEffectModifier = computed(() => const computedmaterialLevelEffectModifier = computed(() =>
@ -1705,6 +1695,11 @@ export const main = createLayer("main", function (this: BaseLayer) {
modifier: energyModifier, modifier: energyModifier,
base: 1, base: 1,
unit: "/s" unit: "/s"
},
{
title: "Bonus Connections",
modifier: bonusConnectionsModifier,
base: 0
} }
]); ]);
const [miningTab, miningTabCollapsed] = createCollapsibleModifierSections(() => [ const [miningTab, miningTabCollapsed] = createCollapsibleModifierSections(() => [
@ -1713,19 +1708,19 @@ export const main = createLayer("main", function (this: BaseLayer) {
modifier: miningSpeedModifier, modifier: miningSpeedModifier,
base: 1, base: 1,
unit: "/s", unit: "/s",
visible: () => toolNodes.value["dirt"] != null visible: () => toolNodes.value.dirt != null
}, },
{ {
title: "Ore Dropped", title: "Ore Dropped",
modifier: materialGainModifier, modifier: materialGainModifier,
base: 1, base: 1,
visible: () => toolNodes.value["gravel"] != null visible: () => toolNodes.value.gravel != null
}, },
{ {
title: "Material Level Effect", title: "Material Level Effect",
modifier: materialLevelEffectModifier, modifier: materialLevelEffectModifier,
base: 1.01, base: 1.01,
visible: () => toolNodes.value["copper"] != null visible: () => toolNodes.value.copper != null
} }
]); ]);
const [resourcesTab, resourcesCollapsed] = createCollapsibleModifierSections(() => const [resourcesTab, resourcesCollapsed] = createCollapsibleModifierSections(() =>
@ -1736,7 +1731,7 @@ export const main = createLayer("main", function (this: BaseLayer) {
); );
const modifierTabs = createTabFamily({ const modifierTabs = createTabFamily({
general: () => ({ general: () => ({
display: "Energy", display: "General",
glowColor(): string { glowColor(): string {
return modifierTabs.activeTab.value === this.tab ? "white" : ""; return modifierTabs.activeTab.value === this.tab ? "white" : "";
}, },
@ -1906,9 +1901,9 @@ export const main = createLayer("main", function (this: BaseLayer) {
const energyProductionChange = computed(() => { const energyProductionChange = computed(() => {
if (board.selectedAction.value === togglePoweredAction) { if (board.selectedAction.value === togglePoweredAction) {
return (board.selectedNode.value?.state as { powered: boolean }).powered return (board.selectedNode.value?.state as { powered: boolean }).powered
? Decimal.eq(poweredMachines.value, 1) ? Decimal.eq(numPoweredMachines.value, 1)
? 10 ? 10
: Decimal.pow(100, poweredMachines.value).div(10).times(0.99) : Decimal.pow(100, numPoweredMachines.value).div(10).times(0.99)
: Decimal.neg(nextPowerCost.value); : Decimal.neg(nextPowerCost.value);
} }
return 0; return 0;
@ -1930,6 +1925,65 @@ export const main = createLayer("main", function (this: BaseLayer) {
}); });
}); });
watch(computedBonusConnectionsModifier, (curr, prev) => {
if (Decimal.lt(curr, prev)) {
if (dowsing.value) {
const maxConnections = (dowsing.value.state as unknown as DowsingState)
.maxConnections;
if (
Decimal.lt(
(dowsing.value.state as unknown as DowsingState).resources.length,
Decimal.add(maxConnections, curr)
)
) {
dowsing.value.state = {
...(dowsing.value.state as object),
resources: (dowsing.value.state as unknown as DowsingState).resources.slice(
0,
Decimal.add(maxConnections, curr).toNumber()
)
};
}
}
if (quarry.value) {
const maxConnections = (quarry.value.state as unknown as QuarryState)
.maxConnections;
if (
Decimal.lt(
(quarry.value.state as unknown as QuarryState).resources.length,
Decimal.add(maxConnections, curr)
)
) {
quarry.value.state = {
...(quarry.value.state as object),
resources: (quarry.value.state as unknown as QuarryState).resources.slice(
0,
Decimal.add(maxConnections, curr).toNumber()
)
};
}
}
if (empowerer.value) {
const maxConnections = (empowerer.value.state as unknown as EmpowererState)
.maxConnections;
if (
Decimal.lt(
(empowerer.value.state as unknown as EmpowererState).tools.length,
Decimal.add(maxConnections, curr)
)
) {
empowerer.value.state = {
...(empowerer.value.state as object),
resources: (empowerer.value.state as unknown as EmpowererState).tools.slice(
0,
Decimal.add(maxConnections, curr).toNumber()
)
};
}
}
}
});
return { return {
name: "World", name: "World",
board, board,
@ -1943,6 +1997,7 @@ export const main = createLayer("main", function (this: BaseLayer) {
influenceNodes, influenceNodes,
grantResource, grantResource,
activePortals, activePortals,
isEmpowered,
display: jsx(() => ( display: jsx(() => (
<> <>
<StickyVue class="nav-container"> <StickyVue class="nav-container">
@ -1960,10 +2015,10 @@ export const main = createLayer("main", function (this: BaseLayer) {
</h3> </h3>
/s) /s)
</span> </span>
{Decimal.gt(poweredMachines.value, 0) ? ( {Decimal.gt(numPoweredMachines.value, 0) ? (
<span class="nav-segment"> <span class="nav-segment">
<h3 style="color: var(--accent1); text-shadow: 0px 0px 10px var(--accent1);"> <h3 style="color: var(--accent1); text-shadow: 0px 0px 10px var(--accent1);">
{formatWhole(poweredMachines.value)} {formatWhole(numPoweredMachines.value)}
</h3>{" "} </h3>{" "}
machines powered machines powered
</span> </span>