From bfce46cf836699a52cc6bf02955c9531763112e9 Mon Sep 17 00:00:00 2001 From: Sainan <63328889+Sainan@users.noreply.github.com> Date: Tue, 14 Oct 2025 19:04:40 +0200 Subject: [PATCH 01/10] chore: initial support for focus 2.0 handling some common operations but not implementing pools yet --- src/controllers/api/focusController.ts | 112 +++++++++++++++---- src/models/inventoryModels/inventoryModel.ts | 3 +- src/types/inventoryTypes/inventoryTypes.ts | 1 + 3 files changed, 95 insertions(+), 21 deletions(-) diff --git a/src/controllers/api/focusController.ts b/src/controllers/api/focusController.ts index f838a9f4..6ff6b6f6 100644 --- a/src/controllers/api/focusController.ts +++ b/src/controllers/api/focusController.ts @@ -1,23 +1,79 @@ import type { RequestHandler } from "express"; -import { getAccountIdForRequest } from "../../services/loginService.ts"; +import { getAccountForRequest } from "../../services/loginService.ts"; import { getInventory, addMiscItems, addEquipment, occupySlot } from "../../services/inventoryService.ts"; import type { IMiscItem, TFocusPolarity, TEquipmentKey } from "../../types/inventoryTypes/inventoryTypes.ts"; import { InventorySlot } from "../../types/inventoryTypes/inventoryTypes.ts"; import { logger } from "../../utils/logger.ts"; import { ExportFocusUpgrades } from "warframe-public-export-plus"; import { Inventory } from "../../models/inventoryModels/inventoryModel.ts"; +import { version_compare } from "../../helpers/inventoryHelpers.ts"; export const focusController: RequestHandler = async (req, res) => { - const accountId = await getAccountIdForRequest(req); - switch (req.query.op) { + const account = await getAccountForRequest(req); + + let op: string | undefined; + const focus2 = account.BuildLabel && version_compare(account.BuildLabel, "2022.04.29.12.53") < 0; + if (focus2) { + // Focus 2.0 + switch (req.query.op) { + case Focus2Operation.UnlockWay: + op = "UnlockWay"; + break; + case Focus2Operation.IncreasePool: + op = "IncreasePool"; + break; + case Focus2Operation.UnlockUpgrade: + op = "UnlockUpgrade"; + break; + case Focus2Operation.ActivateWay: + op = "ActivateWay"; + break; + case Focus2Operation.LevelUpUpgrade: + op = "LevelUpUpgrade"; + break; + case Focus2Operation.ConvertShard: + op = "ConvertShard"; + break; + } + } else { + // Focus 3.0 + switch (req.query.op) { + case Focus3Operation.InstallLens: + op = "InstallLens"; + break; + case Focus3Operation.UnlockWay: + op = "UnlockWay"; + break; + case Focus3Operation.UnlockUpgrade: + op = "UnlockUpgrade"; + break; + case Focus3Operation.LevelUpUpgrade: + op = "LevelUpUpgrade"; + break; + case Focus3Operation.ActivateWay: + op = "ActivateWay"; + break; + case Focus3Operation.SentTrainingAmplifier: + op = "SentTrainingAmplifier"; + break; + case Focus3Operation.UnbindUpgrade: + op = "UnbindUpgrade"; + break; + case Focus3Operation.ConvertShard: + op = "ConvertShard"; + break; + } + } + + switch (op) { default: logger.error("Unhandled focus op type: " + String(req.query.op)); logger.debug(String(req.body)); res.end(); break; - case FocusOperation.InstallLens: { + case "InstallLens": { const request = JSON.parse(String(req.body)) as ILensInstallRequest; - const inventory = await getInventory(accountId); + const inventory = await getInventory(account._id.toString()); const item = inventory[request.Category].id(request.WeaponId); if (item) { item.FocusLens = request.LensType; @@ -35,10 +91,10 @@ export const focusController: RequestHandler = async (req, res) => { }); break; } - case FocusOperation.UnlockWay: { + case "UnlockWay": { const focusType = (JSON.parse(String(req.body)) as IWayRequest).FocusType; const focusPolarity = focusTypeToPolarity(focusType); - const inventory = await getInventory(accountId, "FocusAbility FocusUpgrades FocusXP"); + const inventory = await getInventory(account._id.toString(), "FocusAbility FocusUpgrades FocusXP"); const cost = inventory.FocusAbility ? 50_000 : 0; inventory.FocusAbility ??= focusType; inventory.FocusUpgrades.push({ ItemType: focusType }); @@ -52,12 +108,12 @@ export const focusController: RequestHandler = async (req, res) => { }); break; } - case FocusOperation.ActivateWay: { + case "ActivateWay": { const focusType = (JSON.parse(String(req.body)) as IWayRequest).FocusType; await Inventory.updateOne( { - accountOwnerId: accountId + accountOwnerId: account._id.toString() }, { FocusAbility: focusType @@ -69,10 +125,10 @@ export const focusController: RequestHandler = async (req, res) => { }); break; } - case FocusOperation.UnlockUpgrade: { + case "UnlockUpgrade": { const request = JSON.parse(String(req.body)) as IUnlockUpgradeRequest; const focusPolarity = focusTypeToPolarity(request.FocusTypes[0]); - const inventory = await getInventory(accountId); + const inventory = await getInventory(account._id.toString()); let cost = 0; for (const focusType of request.FocusTypes) { cost += ExportFocusUpgrades[focusType].baseFocusPointCost; @@ -86,15 +142,18 @@ export const focusController: RequestHandler = async (req, res) => { }); break; } - case FocusOperation.LevelUpUpgrade: { + case "LevelUpUpgrade": { const request = JSON.parse(String(req.body)) as ILevelUpUpgradeRequest; const focusPolarity = focusTypeToPolarity(request.FocusInfos[0].ItemType); - const inventory = await getInventory(accountId); + const inventory = await getInventory(account._id.toString()); let cost = 0; for (const focusUpgrade of request.FocusInfos) { cost += focusUpgrade.FocusXpCost; const focusUpgradeDb = inventory.FocusUpgrades.find(entry => entry.ItemType == focusUpgrade.ItemType)!; focusUpgradeDb.Level = focusUpgrade.Level; + if (focus2) { + focusUpgradeDb.IsActive = focusUpgrade.IsActive; + } } inventory.FocusXP![focusPolarity]! -= cost; await inventory.save(); @@ -104,9 +163,9 @@ export const focusController: RequestHandler = async (req, res) => { }); break; } - case FocusOperation.SentTrainingAmplifier: { + case "SentTrainingAmplifier": { const request = JSON.parse(String(req.body)) as ISentTrainingAmplifierRequest; - const inventory = await getInventory(accountId); + const inventory = await getInventory(account._id.toString()); const inventoryChanges = addEquipment(inventory, "OperatorAmps", request.StartingWeaponType, { ModularParts: [ "/Lotus/Weapons/Sentients/OperatorAmplifiers/SentTrainingAmplifier/SentAmpTrainingGrip", @@ -119,10 +178,10 @@ export const focusController: RequestHandler = async (req, res) => { res.json(inventoryChanges.OperatorAmps![0]); break; } - case FocusOperation.UnbindUpgrade: { + case "UnbindUpgrade": { const request = JSON.parse(String(req.body)) as IUnbindUpgradeRequest; const focusPolarity = focusTypeToPolarity(request.FocusTypes[0]); - const inventory = await getInventory(accountId); + const inventory = await getInventory(account._id.toString()); inventory.FocusXP![focusPolarity]! -= 750_000 * request.FocusTypes.length; addMiscItems(inventory, [ { @@ -149,7 +208,7 @@ export const focusController: RequestHandler = async (req, res) => { }); break; } - case FocusOperation.ConvertShard: { + case "ConvertShard": { const request = JSON.parse(String(req.body)) as IConvertShardRequest; // Tally XP let xp = 0; @@ -167,7 +226,7 @@ export const focusController: RequestHandler = async (req, res) => { for (const shard of request.Shards) { shard.ItemCount *= -1; } - const inventory = await getInventory(accountId); + const inventory = await getInventory(account._id.toString()); const polarity = request.Polarity; inventory.FocusXP ??= {}; inventory.FocusXP[polarity] ??= 0; @@ -179,7 +238,8 @@ export const focusController: RequestHandler = async (req, res) => { } }; -enum FocusOperation { +// Focus 3.0 +enum Focus3Operation { InstallLens = "1", UnlockWay = "2", UnlockUpgrade = "3", @@ -190,6 +250,17 @@ enum FocusOperation { ConvertShard = "9" } +// Focus 2.0 +// eslint-disable-next-line @typescript-eslint/no-unused-vars +enum Focus2Operation { + UnlockWay = "2", + IncreasePool = "4", // {"FocusType":"/Lotus/Upgrades/Focus/Defense/DefenseFocusAbility","CurrentTotalCapacity":5,"NewTotalCapacity":7} + UnlockUpgrade = "5", + ActivateWay = "6", + LevelUpUpgrade = "7", // used to level up & activate ability + ConvertShard = "11" +} + // For UnlockWay & ActivateWay interface IWayRequest { FocusType: string; @@ -206,6 +277,7 @@ interface ILevelUpUpgradeRequest { IsUniversal: boolean; Level: number; IsActiveAbility: boolean; + IsActive?: number; // Focus 2.0 }[]; } diff --git a/src/models/inventoryModels/inventoryModel.ts b/src/models/inventoryModels/inventoryModel.ts index 78b0effe..139fa255 100644 --- a/src/models/inventoryModels/inventoryModel.ts +++ b/src/models/inventoryModels/inventoryModel.ts @@ -146,7 +146,8 @@ const focusUpgradeSchema = new Schema( { ItemType: String, Level: Number, - IsUniversal: Boolean + IsUniversal: Boolean, + IsActive: Number }, { _id: false } ); diff --git a/src/types/inventoryTypes/inventoryTypes.ts b/src/types/inventoryTypes/inventoryTypes.ts index ffbec905..647aaf95 100644 --- a/src/types/inventoryTypes/inventoryTypes.ts +++ b/src/types/inventoryTypes/inventoryTypes.ts @@ -638,6 +638,7 @@ export interface IFocusUpgrade { ItemType: string; Level?: number; IsUniversal?: boolean; + IsActive?: number; // Focus 2.0 } export interface IFocusXP { -- 2.47.2 From 978ecf6b1e7281cf05fc7c947932c6c62579c8fc Mon Sep 17 00:00:00 2001 From: Sainan <63328889+Sainan@users.noreply.github.com> Date: Tue, 14 Oct 2025 19:15:33 +0200 Subject: [PATCH 02/10] fix unlock all focus schools for when logged in on an old version --- src/controllers/api/focusController.ts | 2 +- static/webui/script.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/controllers/api/focusController.ts b/src/controllers/api/focusController.ts index 6ff6b6f6..cd19406e 100644 --- a/src/controllers/api/focusController.ts +++ b/src/controllers/api/focusController.ts @@ -11,7 +11,7 @@ import { version_compare } from "../../helpers/inventoryHelpers.ts"; export const focusController: RequestHandler = async (req, res) => { const account = await getAccountForRequest(req); - let op: string | undefined; + let op = req.query.op as string; const focus2 = account.BuildLabel && version_compare(account.BuildLabel, "2022.04.29.12.53") < 0; if (focus2) { // Focus 2.0 diff --git a/static/webui/script.js b/static/webui/script.js index 0ca1ff4b..ab1a894d 100644 --- a/static/webui/script.js +++ b/static/webui/script.js @@ -3276,13 +3276,13 @@ function unlockFocusSchool(upgradeType) { return new Promise(resolve => { // Deselect current FocusAbility so we will be able to unlock the way for free $.post({ - url: "/api/focus.php?" + window.authz + "&op=5", + url: "/api/focus.php?" + window.authz + "&op=ActivateWay", contentType: "text/plain", data: JSON.stringify({ FocusType: null }) }).done(function () { // Unlock the way now $.post({ - url: "/api/focus.php?" + window.authz + "&op=2", + url: "/api/focus.php?" + window.authz + "&op=UnlockWay", contentType: "text/plain", data: JSON.stringify({ FocusType: upgradeType -- 2.47.2 From 2686c229fd037d8723d34ef05303db3508d0db25 Mon Sep 17 00:00:00 2001 From: Sainan <63328889+Sainan@users.noreply.github.com> Date: Tue, 14 Oct 2025 19:24:36 +0200 Subject: [PATCH 03/10] fix confusion --- src/controllers/api/focusController.ts | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/controllers/api/focusController.ts b/src/controllers/api/focusController.ts index cd19406e..46de50de 100644 --- a/src/controllers/api/focusController.ts +++ b/src/controllers/api/focusController.ts @@ -22,14 +22,17 @@ export const focusController: RequestHandler = async (req, res) => { case Focus2Operation.IncreasePool: op = "IncreasePool"; break; + case Focus2Operation.LevelUpUpgrade: + op = "LevelUpUpgrade"; + break; case Focus2Operation.UnlockUpgrade: op = "UnlockUpgrade"; break; case Focus2Operation.ActivateWay: op = "ActivateWay"; break; - case Focus2Operation.LevelUpUpgrade: - op = "LevelUpUpgrade"; + case Focus2Operation.UpdateUpgrade: + op = "UpdateUpgrade"; break; case Focus2Operation.ConvertShard: op = "ConvertShard"; @@ -142,7 +145,8 @@ export const focusController: RequestHandler = async (req, res) => { }); break; } - case "LevelUpUpgrade": { + case "LevelUpUpgrade": + case "UpdateUpgrade": { const request = JSON.parse(String(req.body)) as ILevelUpUpgradeRequest; const focusPolarity = focusTypeToPolarity(request.FocusInfos[0].ItemType); const inventory = await getInventory(account._id.toString()); @@ -255,9 +259,10 @@ enum Focus3Operation { enum Focus2Operation { UnlockWay = "2", IncreasePool = "4", // {"FocusType":"/Lotus/Upgrades/Focus/Defense/DefenseFocusAbility","CurrentTotalCapacity":5,"NewTotalCapacity":7} - UnlockUpgrade = "5", + UnlockUpgrade = "3", + LevelUpUpgrade = "5", ActivateWay = "6", - LevelUpUpgrade = "7", // used to level up & activate ability + UpdateUpgrade = "7", // used to change the IsActive state, same format as ILevelUpUpgradeRequest ConvertShard = "11" } -- 2.47.2 From be42d9243f0ab424112cc19ef1eb8f87e266a9ba Mon Sep 17 00:00:00 2001 From: Sainan <63328889+Sainan@users.noreply.github.com> Date: Tue, 14 Oct 2025 19:30:10 +0200 Subject: [PATCH 04/10] SentTrainingAmplifier --- src/controllers/api/focusController.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/controllers/api/focusController.ts b/src/controllers/api/focusController.ts index 46de50de..73b43662 100644 --- a/src/controllers/api/focusController.ts +++ b/src/controllers/api/focusController.ts @@ -34,6 +34,9 @@ export const focusController: RequestHandler = async (req, res) => { case Focus2Operation.UpdateUpgrade: op = "UpdateUpgrade"; break; + case Focus2Operation.SentTrainingAmplifier: + op = "SentTrainingAmplifier"; + break; case Focus2Operation.ConvertShard: op = "ConvertShard"; break; @@ -263,6 +266,7 @@ enum Focus2Operation { LevelUpUpgrade = "5", ActivateWay = "6", UpdateUpgrade = "7", // used to change the IsActive state, same format as ILevelUpUpgradeRequest + SentTrainingAmplifier = "9", ConvertShard = "11" } -- 2.47.2 From db36577f6100a7c99037286f34fccba4ec135de4 Mon Sep 17 00:00:00 2001 From: Sainan <63328889+Sainan@users.noreply.github.com> Date: Tue, 14 Oct 2025 20:03:56 +0200 Subject: [PATCH 05/10] IncreasePool --- src/controllers/api/focusController.ts | 42 +++++++++++++++++++- src/models/inventoryModels/inventoryModel.ts | 2 + src/types/inventoryTypes/inventoryTypes.ts | 1 + 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/src/controllers/api/focusController.ts b/src/controllers/api/focusController.ts index 73b43662..2f6bbfa8 100644 --- a/src/controllers/api/focusController.ts +++ b/src/controllers/api/focusController.ts @@ -114,6 +114,23 @@ export const focusController: RequestHandler = async (req, res) => { }); break; } + case "IncreasePool": { + const request = JSON.parse(String(req.body)) as IIncreasePoolRequest; + const focusPolarity = focusTypeToPolarity(request.FocusType); + const inventory = await getInventory(account._id.toString(), "FocusXP FocusCapacity"); + let cost = 0; + for (let capacity = request.CurrentTotalCapacity; capacity != request.NewTotalCapacity; ++capacity) { + cost += increasePoolCost[capacity - 5]; + } + inventory.FocusXP![focusPolarity]! -= cost; + inventory.FocusCapacity = request.NewTotalCapacity; + await inventory.save(); + res.json({ + TotalCapacity: request.NewTotalCapacity, + FocusPointCosts: { [focusPolarity]: cost } + }); + break; + } case "ActivateWay": { const focusType = (JSON.parse(String(req.body)) as IWayRequest).FocusType; @@ -261,7 +278,7 @@ enum Focus3Operation { // eslint-disable-next-line @typescript-eslint/no-unused-vars enum Focus2Operation { UnlockWay = "2", - IncreasePool = "4", // {"FocusType":"/Lotus/Upgrades/Focus/Defense/DefenseFocusAbility","CurrentTotalCapacity":5,"NewTotalCapacity":7} + IncreasePool = "4", UnlockUpgrade = "3", LevelUpUpgrade = "5", ActivateWay = "6", @@ -279,6 +296,13 @@ interface IUnlockUpgradeRequest { FocusTypes: string[]; } +// Focus 2.0 +interface IIncreasePoolRequest { + FocusType: string; + CurrentTotalCapacity: number; + NewTotalCapacity: number; +} + interface ILevelUpUpgradeRequest { FocusInfos: { ItemType: string; @@ -321,3 +345,19 @@ const shardValues = { "/Lotus/Types/Gameplay/Eidolon/Resources/SentientShards/SentientShardBrilliantItem": 25_000, "/Lotus/Types/Gameplay/Eidolon/Resources/SentientShards/SentientShardBrilliantTierTwoItem": 40_000 }; + +// Starting at a capacity of 5 (Source: https://wiki.warframe.com/w/Focus_2.0) +const increasePoolCost = [ + 2576, 3099, 3638, 4190, 4755, 5331, 5918, 6514, 7120, 7734, 8357, 8988, 9626, 10271, 10923, 11582, 12247, 12918, + 13595, 14277, 14965, 15659, 16357, 17061, 17769, 18482, 19200, 19922, 20649, 21380, 22115, 22854, 23597, 24344, + 25095, 25850, 26609, 27371, 28136, 28905, 29678, 30454, 31233, 32015, 32801, 33590, 34382, 35176, 35974, 36775, + 37579, 38386, 39195, 40008, 40823, 41641, 42461, 43284, 44110, 44938, 45769, 46603, 47439, 48277, 49118, 49961, + 50807, 51655, 52505, 53357, 54212, 55069, 55929, 56790, 57654, 58520, 59388, 60258, 61130, 62005, 62881, 63759, + 64640, 65522, 66407, 67293, 68182, 69072, 69964, 70858, 71754, 72652, 73552, 74453, 75357, 76262, 77169, 78078, + 78988, 79900, 80814, 81730, 82648, 83567, 84488, 85410, 86334, 87260, 88188, 89117, 90047, 90980, 91914, 92849, + 93786, 94725, 95665, 96607, 97550, 98495, 99441, 100389, 101338, 102289, 103241, 104195, 105150, 106107, 107065, + 108024, 108985, 109948, 110911, 111877, 112843, 113811, 114780, 115751, 116723, 117696, 118671, 119647, 120624, + 121603, 122583, 123564, 124547, 125531, 126516, 127503, 128490, 129479, 130470, 131461, 132454, 133448, 134443, + 135440, 136438, 137437, 138437, 139438, 140441, 141444, 142449, 143455, 144463, 145471, 146481, 147492, 148503, + 149517 +]; diff --git a/src/models/inventoryModels/inventoryModel.ts b/src/models/inventoryModels/inventoryModel.ts index 139fa255..ac95f362 100644 --- a/src/models/inventoryModels/inventoryModel.ts +++ b/src/models/inventoryModels/inventoryModel.ts @@ -1543,6 +1543,8 @@ const inventorySchema = new Schema( FocusAbility: String, //The treeways of the Focus school.(Active and passive Ability) FocusUpgrades: [focusUpgradeSchema], + //Focus 2.0 Pool + FocusCapacity: Number, //Achievement ChallengeProgress: [challengeProgressSchema], diff --git a/src/types/inventoryTypes/inventoryTypes.ts b/src/types/inventoryTypes/inventoryTypes.ts index 647aaf95..bb181b61 100644 --- a/src/types/inventoryTypes/inventoryTypes.ts +++ b/src/types/inventoryTypes/inventoryTypes.ts @@ -340,6 +340,7 @@ export interface IInventoryClient extends IDailyAffiliations, InventoryClientEqu EmailItems: ITypeCount[]; CompletedSyndicates: string[]; FocusXP?: IFocusXP; + FocusCapacity?: number; Wishlist: string[]; Alignment?: IAlignment; CompletedSorties: string[]; -- 2.47.2 From 3044d87bb30398784e802a4347bf959c39fa606d Mon Sep 17 00:00:00 2001 From: Sainan <63328889+Sainan@users.noreply.github.com> Date: Tue, 14 Oct 2025 20:05:52 +0200 Subject: [PATCH 06/10] InstallLens --- src/controllers/api/focusController.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/controllers/api/focusController.ts b/src/controllers/api/focusController.ts index 2f6bbfa8..c7954999 100644 --- a/src/controllers/api/focusController.ts +++ b/src/controllers/api/focusController.ts @@ -16,18 +16,21 @@ export const focusController: RequestHandler = async (req, res) => { if (focus2) { // Focus 2.0 switch (req.query.op) { + case Focus2Operation.InstallLens: + op = "InstallLens"; + break; case Focus2Operation.UnlockWay: op = "UnlockWay"; break; + case Focus2Operation.UnlockUpgrade: + op = "UnlockUpgrade"; + break; case Focus2Operation.IncreasePool: op = "IncreasePool"; break; case Focus2Operation.LevelUpUpgrade: op = "LevelUpUpgrade"; break; - case Focus2Operation.UnlockUpgrade: - op = "UnlockUpgrade"; - break; case Focus2Operation.ActivateWay: op = "ActivateWay"; break; @@ -277,9 +280,10 @@ enum Focus3Operation { // Focus 2.0 // eslint-disable-next-line @typescript-eslint/no-unused-vars enum Focus2Operation { + InstallLens = "1", UnlockWay = "2", - IncreasePool = "4", UnlockUpgrade = "3", + IncreasePool = "4", LevelUpUpgrade = "5", ActivateWay = "6", UpdateUpgrade = "7", // used to change the IsActive state, same format as ILevelUpUpgradeRequest -- 2.47.2 From 5997b12451733bdd92bd210dc61cfe6f7541ebb4 Mon Sep 17 00:00:00 2001 From: Sainan <63328889+Sainan@users.noreply.github.com> Date: Tue, 14 Oct 2025 20:13:38 +0200 Subject: [PATCH 07/10] UnbindUpgrade --- src/controllers/api/focusController.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/controllers/api/focusController.ts b/src/controllers/api/focusController.ts index c7954999..21a5152a 100644 --- a/src/controllers/api/focusController.ts +++ b/src/controllers/api/focusController.ts @@ -40,6 +40,9 @@ export const focusController: RequestHandler = async (req, res) => { case Focus2Operation.SentTrainingAmplifier: op = "SentTrainingAmplifier"; break; + case Focus2Operation.UnbindUpgrade: + op = "UnbindUpgrade"; + break; case Focus2Operation.ConvertShard: op = "ConvertShard"; break; @@ -288,6 +291,7 @@ enum Focus2Operation { ActivateWay = "6", UpdateUpgrade = "7", // used to change the IsActive state, same format as ILevelUpUpgradeRequest SentTrainingAmplifier = "9", + UnbindUpgrade = "10", ConvertShard = "11" } -- 2.47.2 From 05e3ad4744fe51cf296013460eb6f917511b5631 Mon Sep 17 00:00:00 2001 From: Sainan <63328889+Sainan@users.noreply.github.com> Date: Tue, 14 Oct 2025 20:14:36 +0200 Subject: [PATCH 08/10] fix activating/deactivating a focus upgrade resetting its level --- src/controllers/api/focusController.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/controllers/api/focusController.ts b/src/controllers/api/focusController.ts index 21a5152a..22873205 100644 --- a/src/controllers/api/focusController.ts +++ b/src/controllers/api/focusController.ts @@ -180,9 +180,10 @@ export const focusController: RequestHandler = async (req, res) => { for (const focusUpgrade of request.FocusInfos) { cost += focusUpgrade.FocusXpCost; const focusUpgradeDb = inventory.FocusUpgrades.find(entry => entry.ItemType == focusUpgrade.ItemType)!; - focusUpgradeDb.Level = focusUpgrade.Level; - if (focus2) { + if (op == "UpdateUpgrade") { focusUpgradeDb.IsActive = focusUpgrade.IsActive; + } else { + focusUpgradeDb.Level = focusUpgrade.Level; } } inventory.FocusXP![focusPolarity]! -= cost; -- 2.47.2 From a93c42f89898039d283fae17de7c8d520270ecdd Mon Sep 17 00:00:00 2001 From: Sainan <63328889+Sainan@users.noreply.github.com> Date: Tue, 14 Oct 2025 20:16:39 +0200 Subject: [PATCH 09/10] not unused --- src/controllers/api/focusController.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/controllers/api/focusController.ts b/src/controllers/api/focusController.ts index 22873205..17c135b4 100644 --- a/src/controllers/api/focusController.ts +++ b/src/controllers/api/focusController.ts @@ -282,7 +282,6 @@ enum Focus3Operation { } // Focus 2.0 -// eslint-disable-next-line @typescript-eslint/no-unused-vars enum Focus2Operation { InstallLens = "1", UnlockWay = "2", -- 2.47.2 From e219b3bcdadc8aad06c2ee21762836f2a8b00e88 Mon Sep 17 00:00:00 2001 From: Sainan <63328889+Sainan@users.noreply.github.com> Date: Wed, 15 Oct 2025 10:05:19 +0200 Subject: [PATCH 10/10] handle UnlockUpgrade for Zenurik's Inner Might --- src/controllers/api/focusController.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/controllers/api/focusController.ts b/src/controllers/api/focusController.ts index 17c135b4..89fccdb3 100644 --- a/src/controllers/api/focusController.ts +++ b/src/controllers/api/focusController.ts @@ -160,7 +160,14 @@ export const focusController: RequestHandler = async (req, res) => { const inventory = await getInventory(account._id.toString()); let cost = 0; for (const focusType of request.FocusTypes) { - cost += ExportFocusUpgrades[focusType].baseFocusPointCost; + if (focusType in ExportFocusUpgrades) { + cost += ExportFocusUpgrades[focusType].baseFocusPointCost; + } else if (focusType == "/Lotus/Upgrades/Focus/Power/Residual/ChannelEfficiencyFocusUpgrade") { + // Zenurik's Inner Might (Focus 2.0) + cost += 50_000; + } else { + logger.warn(`unknown focus upgrade ${focusType}, will unlock it for free`); + } inventory.FocusUpgrades.push({ ItemType: focusType, Level: 0 }); } inventory.FocusXP![focusPolarity]! -= cost; -- 2.47.2