diff --git a/src/controllers/api/creditsController.ts b/src/controllers/api/creditsController.ts index 5fb60575..d7b91d24 100644 --- a/src/controllers/api/creditsController.ts +++ b/src/controllers/api/creditsController.ts @@ -4,9 +4,15 @@ import { getAccountIdForRequest } from "@/src/services/loginService"; import { getInventory } from "@/src/services/inventoryService"; export const creditsController: RequestHandler = async (req, res) => { - const accountId = await getAccountIdForRequest(req); - - const inventory = await getInventory(accountId, "RegularCredits TradesRemaining PremiumCreditsFree PremiumCredits"); + const inventory = ( + await Promise.all([ + getAccountIdForRequest(req), + getInventory( + req.query.accountId as string, + "RegularCredits TradesRemaining PremiumCreditsFree PremiumCredits" + ) + ]) + )[1]; const response = { RegularCredits: inventory.RegularCredits, diff --git a/src/controllers/api/inventoryController.ts b/src/controllers/api/inventoryController.ts index 730756a1..cb855f16 100644 --- a/src/controllers/api/inventoryController.ts +++ b/src/controllers/api/inventoryController.ts @@ -13,7 +13,8 @@ import { allDailyAffiliationKeys, cleanupInventory, createLibraryDailyTask, - generateRewardSeed + generateRewardSeed, + getCalendarProgress } from "@/src/services/inventoryService"; import { logger } from "@/src/utils/logger"; import { addString, catBreadHash } from "@/src/helpers/stringHelpers"; @@ -108,6 +109,10 @@ export const inventoryController: RequestHandler = async (request, response) => } } + if (inventory.CalendarProgress) { + getCalendarProgress(inventory); // handle year rollover; the client expects to receive an inventory with an up-to-date CalendarProgress + } + cleanupInventory(inventory); inventory.NextRefill = new Date((today + 1) * 86400000); // tomorrow at 0 UTC diff --git a/src/controllers/api/loginRewardsController.ts b/src/controllers/api/loginRewardsController.ts index 8959c5c7..19940d08 100644 --- a/src/controllers/api/loginRewardsController.ts +++ b/src/controllers/api/loginRewardsController.ts @@ -9,6 +9,7 @@ import { } from "@/src/services/loginRewardService"; import { getInventory } from "@/src/services/inventoryService"; import { config } from "@/src/services/configService"; +import { sendWsBroadcastTo } from "@/src/services/webService"; export const loginRewardsController: RequestHandler = async (req, res) => { const account = await getAccountForRequest(req); @@ -51,6 +52,8 @@ export const loginRewardsController: RequestHandler = async (req, res) => { setAccountGotLoginRewardToday(account); await account.save(); + + sendWsBroadcastTo(account._id.toString(), { update_inventory: true }); } res.json(response); }; diff --git a/src/controllers/api/loginRewardsSelectionController.ts b/src/controllers/api/loginRewardsSelectionController.ts index 290a13f8..e3a699ec 100644 --- a/src/controllers/api/loginRewardsSelectionController.ts +++ b/src/controllers/api/loginRewardsSelectionController.ts @@ -6,6 +6,7 @@ import { } from "@/src/services/loginRewardService"; import { getAccountForRequest } from "@/src/services/loginService"; import { handleStoreItemAcquisition } from "@/src/services/purchaseService"; +import { sendWsBroadcastTo } from "@/src/services/webService"; import { IInventoryChanges } from "@/src/types/purchaseTypes"; import { logger } from "@/src/utils/logger"; import { RequestHandler } from "express"; @@ -39,6 +40,7 @@ export const loginRewardsSelectionController: RequestHandler = async (req, res) setAccountGotLoginRewardToday(account); await account.save(); + sendWsBroadcastTo(account._id.toString(), { update_inventory: true }); res.json({ DailyTributeInfo: { NewInventory: inventoryChanges, diff --git a/src/controllers/api/sellController.ts b/src/controllers/api/sellController.ts index ff5c8f42..ccc96385 100644 --- a/src/controllers/api/sellController.ts +++ b/src/controllers/api/sellController.ts @@ -58,6 +58,9 @@ export const sellController: RequestHandler = async (req, res) => { if (payload.Items.Hoverboards) { requiredFields.add(InventorySlot.SPACESUITS); } + if (payload.Items.CrewMembers) { + requiredFields.add(InventorySlot.CREWMEMBERS); + } if (payload.Items.CrewShipWeapons || payload.Items.CrewShipWeaponSkins) { requiredFields.add(InventorySlot.RJ_COMPONENT_AND_ARMAMENTS); requiredFields.add("CrewShipRawSalvage"); @@ -181,6 +184,12 @@ export const sellController: RequestHandler = async (req, res) => { inventory.Drones.pull({ _id: sellItem.String }); }); } + if (payload.Items.CrewMembers) { + payload.Items.CrewMembers.forEach(sellItem => { + inventory.CrewMembers.pull({ _id: sellItem.String }); + freeUpSlot(inventory, InventorySlot.CREWMEMBERS); + }); + } if (payload.Items.CrewShipWeapons) { payload.Items.CrewShipWeapons.forEach(sellItem => { if (sellItem.String[0] == "/") { @@ -303,6 +312,7 @@ interface ISellRequest { OperatorAmps?: ISellItem[]; Hoverboards?: ISellItem[]; Drones?: ISellItem[]; + CrewMembers?: ISellItem[]; CrewShipWeapons?: ISellItem[]; CrewShipWeaponSkins?: ISellItem[]; }; diff --git a/src/services/itemDataService.ts b/src/services/itemDataService.ts index 0e862283..c44691f5 100644 --- a/src/services/itemDataService.ts +++ b/src/services/itemDataService.ts @@ -45,6 +45,39 @@ export type WeaponTypeInternal = | "SpecialItems"; export const getRecipe = (uniqueName: string): IRecipe | undefined => { + // Handle crafting of archwing summon for versions prior to 39.0.0 as this blueprint was removed then. + if (uniqueName == "/Lotus/Types/Recipes/EidolonRecipes/OpenArchwingSummonBlueprint") { + return { + resultType: "/Lotus/Types/Restoratives/OpenArchwingSummon", + buildPrice: 7500, + buildTime: 1800, + skipBuildTimePrice: 10, + consumeOnUse: false, + num: 1, + codexSecret: false, + alwaysAvailable: true, + ingredients: [ + { + ItemType: "/Lotus/Types/Gameplay/Eidolon/Resources/IraditeItem", + ItemCount: 50 + }, + { + ItemType: "/Lotus/Types/Gameplay/Eidolon/Resources/GrokdrulItem", + ItemCount: 50 + }, + { + ItemType: "/Lotus/Types/Items/Fish/Eidolon/FishParts/EidolonFishOilItem", + ItemCount: 30 + }, + { + ItemType: "/Lotus/Types/Items/MiscItems/Circuits", + ItemCount: 600 + } + ], + excludeFromMarket: true + }; + } + return ExportRecipes[uniqueName]; }; diff --git a/static/webui/index.html b/static/webui/index.html index 6c62867e..c228a9ef 100644 --- a/static/webui/index.html +++ b/static/webui/index.html @@ -75,7 +75,7 @@ -
+

diff --git a/static/webui/script.js b/static/webui/script.js index 9948247c..f648809c 100644 --- a/static/webui/script.js +++ b/static/webui/script.js @@ -2738,3 +2738,9 @@ function handleValenceBonusChange(event) { }); }); } + +document.querySelectorAll("#sidebar .nav-link").forEach(function (elm) { + elm.addEventListener("click", function () { + window.scrollTo(0, 0); + }); +}); diff --git a/static/webui/style.css b/static/webui/style.css index 05677dd7..becce85d 100644 --- a/static/webui/style.css +++ b/static/webui/style.css @@ -4,9 +4,19 @@ } body.logged-in #sidebar { - position: sticky; - top: 5rem; - margin-right: 3rem; + position: fixed; + } + + body.logged-in #main-content { + margin-left: 7rem; + } + + body.logged-in:has([data-lang="de"].active) #main-content { + margin-left: 8rem; + } + + body.logged-in:has([data-lang="zh"].active) #main-content { + margin-left: 6rem; } body:not(.logged-in) #sidebar { diff --git a/static/webui/translations/es.js b/static/webui/translations/es.js index fc56db1c..86d8c6be 100644 --- a/static/webui/translations/es.js +++ b/static/webui/translations/es.js @@ -2,8 +2,8 @@ dict = { general_inventoryUpdateNote: `Para ver los cambios en el juego, necesitas volver a sincronizar tu inventario, por ejemplo, usando el comando /sync del bootstrapper, visitando un dojo o repetidor, o volviendo a iniciar sesión.`, general_addButton: `Agregar`, - general_setButton: `[UNTRANSLATED] Set`, - general_removeButton: `[UNTRANSLATED] Remove`, + general_setButton: `Establecer`, + general_removeButton: `Quitar`, general_bulkActions: `Acciones masivas`, code_loginFail: `Error al iniciar sesión. Verifica el correo electrónico y la contraseña.`, @@ -120,7 +120,7 @@ dict = { detailedView_archonShardsDescription: `Puedes usar estas ranuras ilimitadas para aplicar una amplia variedad de mejoras`, detailedView_archonShardsDescription2: `Ten en cuenta que cada fragmento de archón tarda un poco en aplicarse al cargar`, detailedView_valenceBonusLabel: `Bônus de Valência`, - detailedView_valenceBonusDescription: `[UNTRANSLATED] You can set or remove the Valence Bonus from your weapon.`, + detailedView_valenceBonusDescription: `Puedes establecer o quitar el bono de valencia de tu arma.`, mods_addRiven: `Agregar Agrietado`, mods_fingerprint: `Huella digital`, @@ -136,7 +136,7 @@ dict = { cheats_skipAllDialogue: `Omitir todos los diálogos`, cheats_unlockAllScans: `Desbloquear todos los escaneos`, cheats_unlockAllMissions: `Desbloquear todas las misiones`, - cheats_unlockAllMissions_ok: `[UNTRANSLATED] Success. Please note that you'll need to enter a dojo/relay or relog for the client to refresh the star chart.`, + cheats_unlockAllMissions_ok: `Éxito. Ten en cuenta que deberás entrar a un dojo, repetidor o volver a iniciar sesión para que el cliente actualice el mapa estelar.`, cheats_infiniteCredits: `Créditos infinitos`, cheats_infinitePlatinum: `Platino infinito`, cheats_infiniteEndo: `Endo infinito`, @@ -306,8 +306,8 @@ dict = { damageType_Poison: `Tóxico`, damageType_Radiation: `Radioativo`, - theme_dark: `[UNTRANSLATED] Dark Theme`, - theme_light: `[UNTRANSLATED] Light Theme`, + theme_dark: `Tema Oscuro`, + theme_light: `Tema Claro`, prettier_sucks_ass: `` };