diff --git a/src/controllers/custom/getItemListsController.ts b/src/controllers/custom/getItemListsController.ts index b463078c..2aa3f120 100644 --- a/src/controllers/custom/getItemListsController.ts +++ b/src/controllers/custom/getItemListsController.ts @@ -37,10 +37,10 @@ interface ListedItem { chainLength?: number; parazon?: boolean; alwaysAvailable?: boolean; + maxLevelCap?: number; } interface ItemLists { - uniqueLevelCaps: Record; Suits: ListedItem[]; LongGuns: ListedItem[]; Melee: ListedItem[]; @@ -83,7 +83,6 @@ const toTitleCase = (str: string): string => { const getItemListsController: RequestHandler = (req, response) => { const lang = getDict(typeof req.query.lang == "string" ? req.query.lang : "en"); const res: ItemLists = { - uniqueLevelCaps: {}, Suits: [], LongGuns: [], Melee: [], @@ -144,7 +143,8 @@ const getItemListsController: RequestHandler = (req, response) => { res[item.productCategory].push({ uniqueName, name: getString(item.name, lang), - exalted: item.exalted + exalted: item.exalted, + maxLevelCap: item.maxLevelCap }); item.abilities.forEach(ability => { res.Abilities.push({ @@ -152,9 +152,6 @@ const getItemListsController: RequestHandler = (req, response) => { name: getString(ability.name || uniqueName, lang) }); }); - if (item.maxLevelCap) { - res.uniqueLevelCaps[uniqueName] = item.maxLevelCap; - } } for (const [uniqueName, item] of Object.entries(ExportSentinels)) { if (item.productCategory == "Sentinels" || item.productCategory == "KubrowPets") { @@ -195,7 +192,8 @@ const getItemListsController: RequestHandler = (req, response) => { ) { res[item.productCategory].push({ uniqueName, - name: getString(item.name, lang) + name: getString(item.name, lang), + maxLevelCap: item.maxLevelCap }); } } else if (!item.excludeFromCodex) { @@ -204,9 +202,6 @@ const getItemListsController: RequestHandler = (req, response) => { name: getString(item.name, lang) }); } - if (item.maxLevelCap) { - res.uniqueLevelCaps[uniqueName] = item.maxLevelCap; - } } for (const [uniqueName, item] of Object.entries(ExportResources)) { let name = getString(item.name, lang); diff --git a/src/controllers/custom/unlockLevelCupController.ts b/src/controllers/custom/unlockLevelCupController.ts new file mode 100644 index 00000000..367e2555 --- /dev/null +++ b/src/controllers/custom/unlockLevelCupController.ts @@ -0,0 +1,25 @@ +import type { RequestHandler } from "express"; +import { getAccountIdForRequest } from "../../services/loginService.ts"; +import { broadcastInventoryUpdate } from "../../services/wsService.ts"; +import { getInventory } from "../../services/inventoryService.ts"; +import type { TEquipmentKey } from "../../types/inventoryTypes/inventoryTypes.ts"; + +export const unlockLevelCupController: RequestHandler = async (req, res) => { + const accountId = await getAccountIdForRequest(req); + const data = req.body as IUnlockLevelCupRequest; + const inventory = await getInventory(accountId, data.Category); + const equipment = inventory[data.Category].id(data.ItemId)!; + + equipment.Polarized ??= 0; + equipment.Polarized = data.Polarized; + + await inventory.save(); + res.end(); + broadcastInventoryUpdate(req); +}; + +interface IUnlockLevelCupRequest { + Category: TEquipmentKey; + ItemId: string; + Polarized: number; +} diff --git a/src/routes/custom.ts b/src/routes/custom.ts index 457f0d99..e5e164c2 100644 --- a/src/routes/custom.ts +++ b/src/routes/custom.ts @@ -41,6 +41,7 @@ import { manageQuestsController } from "../controllers/custom/manageQuestsContro import { setEvolutionProgressController } from "../controllers/custom/setEvolutionProgressController.ts"; import { setBoosterController } from "../controllers/custom/setBoosterController.ts"; import { updateFingerprintController } from "../controllers/custom/updateFingerprintController.ts"; +import { unlockLevelCupController } from "../controllers/custom/unlockLevelCupController.ts"; import { changeModularPartsController } from "../controllers/custom/changeModularPartsController.ts"; import { editSuitInvigorationUpgradeController } from "../controllers/custom/editSuitInvigorationUpgradeController.ts"; import { setAccountCheatController } from "../controllers/custom/setAccountCheatController.ts"; @@ -89,6 +90,7 @@ customRouter.post("/manageQuests", manageQuestsController); customRouter.post("/setEvolutionProgress", setEvolutionProgressController); customRouter.post("/setBooster", setBoosterController); customRouter.post("/updateFingerprint", updateFingerprintController); +customRouter.post("/unlockLevelCup", unlockLevelCupController); customRouter.post("/changeModularParts", changeModularPartsController); customRouter.post("/editSuitInvigorationUpgrade", editSuitInvigorationUpgradeController); customRouter.post("/setAccountCheat", setAccountCheatController); diff --git a/static/webui/script.js b/static/webui/script.js index 84c3676f..a43773bc 100644 --- a/static/webui/script.js +++ b/static/webui/script.js @@ -311,7 +311,6 @@ const permanentEvolutionWeapons = new Set([ "/Lotus/Weapons/Tenno/Zariman/Melee/HeavyScythe/ZarimanHeavyScythe/ZarimanHeavyScytheWeapon" ]); -let uniqueLevelCaps = {}; function fetchItemList() { window.itemListPromise = new Promise(resolve => { const req = $.get("/custom/getItemLists?lang=" + window.lang); @@ -558,8 +557,6 @@ function fetchItemList() { option.textContent = item.name; document.getElementById("worldState.varziaOverride").appendChild(option); }); - } else if (type == "uniqueLevelCaps") { - uniqueLevelCaps = items; } else if (type == "Syndicates") { items.forEach(item => { if (item.uniqueName === "ConclaveSyndicate") { @@ -791,7 +788,7 @@ function updateInventory() { const td = document.createElement("td"); td.classList = "text-end text-nowrap"; - let maxXP = Math.pow(uniqueLevelCaps[item.ItemType] ?? 30, 2) * 1000; + let maxXP = Math.pow(itemMap[item.ItemType].maxLevelCap ?? 30, 2) * 1000; if ( category != "Suits" && category != "SpaceSuits" && @@ -817,6 +814,24 @@ function updateInventory() { } } } + if ( + itemMap[item.ItemType].maxLevelCap > 30 && + (item.Polarized ?? 0) < (itemMap[item.ItemType].maxLevelCap - 30) / 2 + ) { + const a = document.createElement("a"); + a.href = "#"; + a.onclick = function (event) { + event.preventDefault(); + unlockLevelCup( + category, + item.ItemId.$oid, + (itemMap[item.ItemType].maxLevelCap - 30) / 2 + ); + }; + a.title = loc("code_unlockLevelCap"); + a.innerHTML = ``; + td.appendChild(a); + } if (item.XP < maxXP || anyExaltedMissingXP) { const a = document.createElement("a"); a.href = "#"; @@ -2759,6 +2774,22 @@ function gildEquipment(category, oid) { }); } +function unlockLevelCup(category, oid, formas) { + revalidateAuthz().then(() => { + $.post({ + url: "/custom/unlockLevelCup?" + window.authz, + contentType: "application/json", + data: JSON.stringify({ + Category: category, + ItemId: oid, + Polarized: formas + }) + }).done(function () { + updateInventory(); + }); + }); +} + function maturePet(oid, revert) { revalidateAuthz().then(() => { $.post({ diff --git a/static/webui/translations/de.js b/static/webui/translations/de.js index b47a50ec..c4618cbd 100644 --- a/static/webui/translations/de.js +++ b/static/webui/translations/de.js @@ -45,6 +45,7 @@ dict = { code_rank: `Rang`, code_rankUp: `Rang erhöhen`, code_rankDown: `Rang verringern`, + code_unlockLevelCap: `[UNTRANSLATED] Unlock level cap`, code_count: `Anzahl`, code_focusAllUnlocked: `Alle Fokus-Schulen sind bereits freigeschaltet.`, code_focusUnlocked: `|COUNT| neue Fokus-Schulen freigeschaltet! Ein Inventar-Update wird benötigt, damit die Änderungen im Spiel sichtbar werden. Die Sternenkarte zu besuchen, sollte der einfachste Weg sein, dies auszulösen.`, diff --git a/static/webui/translations/en.js b/static/webui/translations/en.js index e0777f64..c948ef9c 100644 --- a/static/webui/translations/en.js +++ b/static/webui/translations/en.js @@ -44,6 +44,7 @@ dict = { code_rank: `Rank`, code_rankUp: `Rank up`, code_rankDown: `Rank down`, + code_unlockLevelCap: `Unlock level cap`, code_count: `Count`, code_focusAllUnlocked: `All focus schools are already unlocked.`, code_focusUnlocked: `Unlocked |COUNT| new focus schools! An inventory update will be needed for the changes to be reflected in-game. Visiting the navigation should be the easiest way to trigger that.`, diff --git a/static/webui/translations/es.js b/static/webui/translations/es.js index cc8edc32..a53e1cbc 100644 --- a/static/webui/translations/es.js +++ b/static/webui/translations/es.js @@ -45,6 +45,7 @@ dict = { code_rank: `Rango`, code_rankUp: `Subir de rango`, code_rankDown: `Bajar de rango`, + code_unlockLevelCap: `[UNTRANSLATED] Unlock level cap`, code_count: `Cantidad`, code_focusAllUnlocked: `Todas las escuelas de enfoque ya están desbloqueadas.`, code_focusUnlocked: `¡Desbloqueadas |COUNT| nuevas escuelas de enfoque! Se necesita una actualización del inventario para reflejar los cambios en el juego. Visitar la navegación debería ser la forma más sencilla de activarlo.`, diff --git a/static/webui/translations/fr.js b/static/webui/translations/fr.js index b557da52..2df0c925 100644 --- a/static/webui/translations/fr.js +++ b/static/webui/translations/fr.js @@ -45,6 +45,7 @@ dict = { code_rank: `Rang`, code_rankUp: `Monter de rang`, code_rankDown: `Baisser de rang`, + code_unlockLevelCap: `[UNTRANSLATED] Unlock level cap`, code_count: `Quantité`, code_focusAllUnlocked: `Les écoles de Focus sont déjà déverrouillées.`, code_focusUnlocked: `|COUNT| écoles de Focus déverrouillées ! Synchronisation de l'inventaire nécessaire.`, diff --git a/static/webui/translations/ru.js b/static/webui/translations/ru.js index a516f3df..3e225e93 100644 --- a/static/webui/translations/ru.js +++ b/static/webui/translations/ru.js @@ -45,6 +45,7 @@ dict = { code_rank: `Ранг`, code_rankUp: `Повысить ранг`, code_rankDown: `Понизить ранг`, + code_unlockLevelCap: `[UNTRANSLATED] Unlock level cap`, code_count: `Количество`, code_focusAllUnlocked: `Все школы Фокуса уже разблокированы.`, code_focusUnlocked: `Разблокировано |COUNT| новых школ Фокуса! Для отображения изменений в игре потребуется обновление инвентаря. Посещение навигации — самый простой способ этого добиться.`, diff --git a/static/webui/translations/uk.js b/static/webui/translations/uk.js index f6e860d9..754c1f57 100644 --- a/static/webui/translations/uk.js +++ b/static/webui/translations/uk.js @@ -45,6 +45,7 @@ dict = { code_rank: `Рівень`, code_rankUp: `Підвищити рівень`, code_rankDown: `Понизити рівень`, + code_unlockLevelCap: `[UNTRANSLATED] Unlock level cap`, code_count: `Кількість`, code_focusAllUnlocked: `Всі школи Фокусу вже розблоковані.`, code_focusUnlocked: `Розблоковано |COUNT| нових шкіл Фокусу! Для відображення змін в грі знадобиться оновлення спорядження. Відвідування навігації — найпростіший спосіб цього досягти.`, diff --git a/static/webui/translations/zh.js b/static/webui/translations/zh.js index 58f62b95..6ec6bc89 100644 --- a/static/webui/translations/zh.js +++ b/static/webui/translations/zh.js @@ -45,6 +45,7 @@ dict = { code_rank: `等级`, code_rankUp: `等级提升`, code_rankDown: `等级下降`, + code_unlockLevelCap: `[UNTRANSLATED] Unlock level cap`, code_count: `数量`, code_focusAllUnlocked: `所有专精学派均已解锁`, code_focusUnlocked: `已解锁 |COUNT| 个新专精学派!需要游戏内仓库更新才能生效,您可以通过访问星图来触发仓库更新.`,