From e3a34399e50aaf3b484e778ed822ba5746c9f6d5 Mon Sep 17 00:00:00 2001 From: hxedcl Date: Mon, 21 Apr 2025 11:55:58 -0700 Subject: [PATCH 01/16] chore(webui): update to Spanish translation (#1772) Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/1772 Co-authored-by: hxedcl Co-committed-by: hxedcl --- static/webui/translations/es.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/static/webui/translations/es.js b/static/webui/translations/es.js index 00a80ecc..96916759 100644 --- a/static/webui/translations/es.js +++ b/static/webui/translations/es.js @@ -54,8 +54,8 @@ dict = { code_completed: `Completada`, code_active: `Activa`, code_pigment: `Pigmento`, - code_mature: `[UNTRANSLATED] Mature for combat`, - code_unmature: `[UNTRANSLATED] Regress genetic aging`, + code_mature: `Listo para el combate`, + code_unmature: `Regresar el envejecimiento genético`, login_description: `Inicia sesión con las credenciales de tu cuenta OpenWF (las mismas que usas en el juego al conectarte a este servidor).`, login_emailLabel: `Dirección de correo electrónico`, login_passwordLabel: `Contraseña`, @@ -82,7 +82,7 @@ dict = { inventory_operatorAmps: `Amps`, inventory_hoverboards: `K-Drives`, inventory_moaPets: `Moa`, - inventory_kubrowPets: `[UNTRANSLATED] Beasts`, + inventory_kubrowPets: `Bestias`, inventory_bulkAddSuits: `Agregar Warframes faltantes`, inventory_bulkAddWeapons: `Agregar armas faltantes`, inventory_bulkAddSpaceSuits: `Agregar Archwings faltantes`, From a49edefbd1db19b7b4f2728bc7a21cce90f43fe5 Mon Sep 17 00:00:00 2001 From: Sainan <63328889+Sainan@users.noreply.github.com> Date: Mon, 21 Apr 2025 15:21:40 -0700 Subject: [PATCH 02/16] fix(webui): don't halve required R30 XP for MoaPets & KubrowPets (#1771) Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/1771 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com> --- static/webui/script.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/static/webui/script.js b/static/webui/script.js index 2e4477bb..a2b8619c 100644 --- a/static/webui/script.js +++ b/static/webui/script.js @@ -436,7 +436,9 @@ function updateInventory() { category != "SpaceSuits" && category != "Sentinels" && category != "Hoverboards" && - category != "MechSuits" + category != "MechSuits" && + category != "MoaPets" && + category != "KubrowPets" ) { maxXP /= 2; } From 731be0d5e339f90b134a86d81e1e764d9961f319 Mon Sep 17 00:00:00 2001 From: Sainan <63328889+Sainan@users.noreply.github.com> Date: Mon, 21 Apr 2025 22:06:39 -0700 Subject: [PATCH 03/16] fix: exclude MT_ARENA from sortie node options (#1769) Fixes #1764 Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/1769 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com> --- src/services/worldStateService.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/services/worldStateService.ts b/src/services/worldStateService.ts index d8cd0c3c..2ca13620 100644 --- a/src/services/worldStateService.ts +++ b/src/services/worldStateService.ts @@ -232,6 +232,7 @@ const pushSortieIfRelevant = (out: ISortie[], day: number): void => { value.missionIndex != 0 && // Exclude MT_ASSASSINATION value.missionIndex != 5 && // Exclude MT_CAPTURE value.missionIndex != 21 && // Exclude MT_PURIFY + value.missionIndex != 22 && // Exclude MT_ARENA value.missionIndex != 23 && // Exclude MT_JUNCTION value.missionIndex <= 28 ) { From c94bc3ef90a88dae9fc6301ae603c5722a3233f4 Mon Sep 17 00:00:00 2001 From: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com> Date: Tue, 22 Apr 2025 00:00:52 -0700 Subject: [PATCH 04/16] chore(webui): update Russian translation (#1783) Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/1783 Co-authored-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com> Co-committed-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com> --- static/webui/translations/ru.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/static/webui/translations/ru.js b/static/webui/translations/ru.js index b299c14c..97956a1b 100644 --- a/static/webui/translations/ru.js +++ b/static/webui/translations/ru.js @@ -108,7 +108,7 @@ dict = { currency_owned: `У тебя |COUNT|.`, powersuit_archonShardsLabel: `Ячейки осколков архонта`, powersuit_archonShardsDescription: `Вы можете использовать эти неограниченные ячейки для установки множества улучшений.`, - powersuit_archonShardsDescription2: `[UNTRANSLATED] Note that each archon shard takes some time to be applied when loading in.`, + powersuit_archonShardsDescription2: `Обратите внимание: каждый фрагмент архонта применяется с задержкой при загрузке.`, mods_addRiven: `Добавить Мод Разлома`, mods_fingerprint: `Отпечаток`, mods_fingerprintHelp: `Нужна помощь с отпечатком?`, @@ -136,15 +136,15 @@ dict = { cheats_unlockDoubleCapacityPotatoesEverywhere: `Катализаторы везде`, cheats_unlockExilusEverywhere: `Адаптеры Эксилус везде`, cheats_unlockArcanesEverywhere: `Адаптеры для мистификаторов везде`, - cheats_noDailyStandingLimits: `Без ежедневных ограничений репутации`, - cheats_noDailyFocusLimit: `[UNTRANSLATED] No Daily Focus Limits`, + cheats_noDailyStandingLimits: `Без ежедневных лимитов репутации`, + cheats_noDailyFocusLimit: `Без ежедневных лимитов фокуса`, cheats_noArgonCrystalDecay: `Без распада аргоновых кристаллов`, cheats_noMasteryRankUpCooldown: `Повышение ранга мастерства без кулдауна`, cheats_noVendorPurchaseLimits: `Отсутствие лимитов на покупки у вендоров`, - cheats_noDeathMarks: `[UNTRANSLATED] No Death Marks`, - cheats_noKimCooldowns: `[UNTRANSLATED] No KIM Cooldowns`, + cheats_noDeathMarks: `Без меток сметри`, + cheats_noKimCooldowns: `Чаты KIM без кулдауна`, cheats_instantResourceExtractorDrones: `Мгновенные Экстракторы Ресурсов`, - cheats_noResourceExtractorDronesDamage: `[UNTRANSLATED] No Resource Extractor Drones Damage`, + cheats_noResourceExtractorDronesDamage: `Без урона по дронам-сборщикам`, cheats_noDojoRoomBuildStage: `Мгновенное Строительтво Комнат Додзё`, cheats_noDojoDecoBuildStage: `Мгновенное Строительтво Декораций Додзё`, cheats_fastDojoRoomDestruction: `Мгновенные Уничтожение Комнат Додзё`, From e3fca682d6f2c7cf139e47c32feddedc7f713acb Mon Sep 17 00:00:00 2001 From: Vitruvio Date: Tue, 22 Apr 2025 09:44:07 -0700 Subject: [PATCH 05/16] Update static/webui/translations/fr.js (#1784) Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/1784 Co-authored-by: Vitruvio Co-committed-by: Vitruvio --- static/webui/translations/fr.js | 64 ++++++++++++++++----------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/static/webui/translations/fr.js b/static/webui/translations/fr.js index bf76ac9e..11b310d1 100644 --- a/static/webui/translations/fr.js +++ b/static/webui/translations/fr.js @@ -25,10 +25,10 @@ dict = { code_renamePrompt: `Nouveau nom :`, code_remove: `Retirer`, code_addItemsConfirm: `Ajouter |COUNT| items à l'inventaire ?`, - code_succRankUp: `[UNTRANSLATED] Successfully ranked up.`, - code_noEquipmentToRankUp: `No equipment to rank up.`, + code_succRankUp: `Montée de niveau effectuée.`, + code_noEquipmentToRankUp: `Aucun équipement à monter de niveau.`, code_succAdded: `Ajouté.`, - code_succRemoved: `[UNTRANSLATED] Successfully removed.`, + code_succRemoved: `Retiré.`, code_buffsNumber: `Nombre de buffs`, code_cursesNumber: `Nombre de débuffs`, code_rerollsNumber: `Nombre de rerolls`, @@ -45,17 +45,17 @@ dict = { code_zanukaA: `Molosse Dorma`, code_zanukaB: `Molosse Bhaira`, code_zanukaC: `Molosse Hec`, - code_stage: `[UNTRANSLATED] Stage`, - code_complete: `[UNTRANSLATED] Complete`, - code_nextStage: `[UNTRANSLATED] Next stage`, - code_prevStage: `[UNTRANSLATED] Previous stage`, - code_reset: `[UNTRANSLATED] Reset`, - code_setInactive: `[UNTRANSLATED] Make the quest inactive`, - code_completed: `[UNTRANSLATED] Completed`, - code_active: `[UNTRANSLATED] Active`, + code_stage: `Étape`, + code_complete: `Compléter`, + code_nextStage: `Étape suivante`, + code_prevStage: `Étape précédente`, + code_reset: `Réinitialiser`, + code_setInactive: `Rendre la quête inactive`, + code_completed: `Complétée`, + code_active: `Active`, code_pigment: `Pigment`, - code_mature: `[UNTRANSLATED] Mature for combat`, - code_unmature: `[UNTRANSLATED] Regress genetic aging`, + code_mature: `Maturer pour le combat`, + code_unmature: `Régrésser l'âge génétique`, login_description: `Connexion avec les informations de connexion OpenWF.`, login_emailLabel: `Email`, login_passwordLabel: `Mot de passe`, @@ -82,7 +82,7 @@ dict = { inventory_operatorAmps: `Amplificateurs`, inventory_hoverboards: `K-Drives`, inventory_moaPets: `Moa`, - inventory_kubrowPets: `[UNTRANSLATED] Beasts`, + inventory_kubrowPets: `Bêtes`, inventory_bulkAddSuits: `Ajouter les Warframes manquantes`, inventory_bulkAddWeapons: `Ajouter les armes manquantes`, inventory_bulkAddSpaceSuits: `Ajouter les Archwings manquants`, @@ -107,8 +107,8 @@ dict = { currency_PrimeTokens: `Aya Raffiné`, currency_owned: `|COUNT| possédés.`, powersuit_archonShardsLabel: `Emplacements de fragments d'Archonte`, - powersuit_archonShardsDescription: `Slots illimités pour appliquer plusieurs améliorations.`, - powersuit_archonShardsDescription2: `[UNTRANSLATED] Note that each archon shard takes some time to be applied when loading in.`, + powersuit_archonShardsDescription: `Slots illimités pour appliquer plusieurs améliorations`, + powersuit_archonShardsDescription2: `Un délai sera présent entre l'application des éclats et le chargement en jeu.`, mods_addRiven: `Ajouter un riven`, mods_fingerprint: `Empreinte`, mods_fingerprintHelp: `Besoin d'aide pour l'empreinte ?`, @@ -131,32 +131,32 @@ dict = { cheats_unlockAllFlavourItems: `Débloquer tous les Flavor Items`, cheats_unlockAllSkins: `Débloquer tous les skins`, cheats_unlockAllCapturaScenes: `Débloquer toutes les scènes captura`, - cheats_unlockAllDecoRecipes: `[UNTRANSLATED] Unlock All Dojo Deco Recipes`, + cheats_unlockAllDecoRecipes: `Débloquer toutes les recherches dojo`, cheats_universalPolarityEverywhere: `Polarités universelles partout`, cheats_unlockDoubleCapacityPotatoesEverywhere: `Réacteurs et Catalyseurs partout`, cheats_unlockExilusEverywhere: `Adaptateurs Exilus partout`, cheats_unlockArcanesEverywhere: `Adaptateur d'Arcanes partout`, - cheats_noDailyStandingLimits: `Pas de limite de réputation journalière`, - cheats_noDailyFocusLimit: `[UNTRANSLATED] No Daily Focus Limits`, - cheats_noArgonCrystalDecay: `[UNTRANSLATED] No Argon Crystal Decay`, - cheats_noMasteryRankUpCooldown: `[UNTRANSLATED] No Mastery Rank Up Cooldown`, - cheats_noVendorPurchaseLimits: `[UNTRANSLATED] No Vendor Purchase Limits`, - cheats_noDeathMarks: `[UNTRANSLATED] No Death Marks`, - cheats_noKimCooldowns: `[UNTRANSLATED] No KIM Cooldowns`, - cheats_instantResourceExtractorDrones: `Ressources de drone d'extraction instantannées`, - cheats_noResourceExtractorDronesDamage: `[UNTRANSLATED] No Resource Extractor Drones Damage`, - cheats_noDojoRoomBuildStage: `No Dojo Room Build Stage`, - cheats_noDojoDecoBuildStage: `[UNTRANSLATED] No Dojo Deco Build Stage`, - cheats_fastDojoRoomDestruction: `[UNTRANSLATED] Fast Dojo Room Destruction`, + cheats_noDailyStandingLimits: `Aucune limite de réputation journalière`, + cheats_noDailyFocusLimit: `Aucune limite journalière de focus`, + cheats_noArgonCrystalDecay: `Aucune désintégration des Cristaux d'Argon`, + cheats_noMasteryRankUpCooldown: `Aucune attente pour la montée de rang de maîtrise`, + cheats_noVendorPurchaseLimits: `Aucune limite d'achat chez les PNJ`, + cheats_noDeathMarks: `Aucune marque d'assassin`, + cheats_noKimCooldowns: `Aucun cooldown sur le KIM`, + cheats_instantResourceExtractorDrones: `Ressources de drones d'extraction instantannées`, + cheats_noResourceExtractorDronesDamage: `Aucun dégâts aux drones d'extraction de resources`, + cheats_noDojoRoomBuildStage: `Aucune attente (construction des salles)`, + cheats_noDojoDecoBuildStage: `Aucune attente (construction des décorations)`, + cheats_fastDojoRoomDestruction: `Destruction de salle instantanée (Dojo)`, cheats_noDojoResearchCosts: `Aucun coût de recherche (Dojo)`, cheats_noDojoResearchTime: `Aucun temps de recherche (Dojo)`, - cheats_fastClanAscension: `[UNTRANSLATED] Fast Clan Ascension`, - cheats_spoofMasteryRank: `Spoofed Mastery Rank (-1 to disable)`, + cheats_fastClanAscension: `Ascension de clan rapide`, + cheats_spoofMasteryRank: `Rang de maîtrise personnalisé (-1 pour désactiver)`, cheats_saveSettings: `Sauvegarder les paramètres`, cheats_account: `Compte`, cheats_unlockAllFocusSchools: `Débloquer toutes les écoles de focus`, cheats_helminthUnlockAll: `Helminth niveau max`, - cheats_intrinsicsUnlockAll: `[UNTRANSLATED] Max Rank All Intrinsics`, + cheats_intrinsicsUnlockAll: `Inhérences niveau max`, cheats_changeSupportedSyndicate: `Allégeance`, cheats_changeButton: `Changer`, cheats_none: `Aucun`, From 03590c73606c91ee4bb5986e7d48684141831a91 Mon Sep 17 00:00:00 2001 From: Animan8000 Date: Tue, 22 Apr 2025 09:44:47 -0700 Subject: [PATCH 06/16] chore(webui): update German translation (#1786) Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/1786 Co-authored-by: Animan8000 Co-committed-by: Animan8000 --- static/webui/translations/de.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/static/webui/translations/de.js b/static/webui/translations/de.js index 061da9c4..40bb5667 100644 --- a/static/webui/translations/de.js +++ b/static/webui/translations/de.js @@ -54,8 +54,8 @@ dict = { code_completed: `Abgeschlossen`, code_active: `Aktiv`, code_pigment: `Pigment`, - code_mature: `[UNTRANSLATED] Mature for combat`, - code_unmature: `[UNTRANSLATED] Regress genetic aging`, + code_mature: `Für den Kampf auswachsen lassen`, + code_unmature: `Genetisches Altern zurücksetzen`, login_description: `Melde dich mit deinem OpenWF-Account an (denselben Angaben wie im Spiel, wenn du dich mit diesem Server verbindest).`, login_emailLabel: `E-Mail-Adresse`, login_passwordLabel: `Passwort`, @@ -82,7 +82,7 @@ dict = { inventory_operatorAmps: `Verstärker`, inventory_hoverboards: `K-Drives`, inventory_moaPets: `Moa`, - inventory_kubrowPets: `[UNTRANSLATED] Beasts`, + inventory_kubrowPets: `Bestien`, inventory_bulkAddSuits: `Fehlende Warframes hinzufügen`, inventory_bulkAddWeapons: `Fehlende Waffen hinzufügen`, inventory_bulkAddSpaceSuits: `Fehlende Archwings hinzufügen`, From ad2f143f1507467b8d56392957c7f223ee2c2644 Mon Sep 17 00:00:00 2001 From: Sainan <63328889+Sainan@users.noreply.github.com> Date: Tue, 22 Apr 2025 09:59:30 -0700 Subject: [PATCH 07/16] feat: cleanup some problems in inventories at daily reset (#1767) Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/1767 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com> --- src/controllers/api/inventoryController.ts | 9 ++++++++- src/services/inventoryService.ts | 20 ++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/controllers/api/inventoryController.ts b/src/controllers/api/inventoryController.ts index bede097f..ab739c4c 100644 --- a/src/controllers/api/inventoryController.ts +++ b/src/controllers/api/inventoryController.ts @@ -14,7 +14,12 @@ import { ExportVirtuals } from "warframe-public-export-plus"; import { applyCheatsToInfestedFoundry, handleSubsumeCompletion } from "@/src/services/infestedFoundryService"; -import { addMiscItems, allDailyAffiliationKeys, createLibraryDailyTask } from "@/src/services/inventoryService"; +import { + addMiscItems, + allDailyAffiliationKeys, + cleanupInventory, + createLibraryDailyTask +} from "@/src/services/inventoryService"; import { logger } from "@/src/utils/logger"; import { catBreadHash } from "@/src/helpers/stringHelpers"; @@ -79,6 +84,8 @@ export const inventoryController: RequestHandler = async (request, response) => } } + cleanupInventory(inventory); + inventory.NextRefill = new Date((Math.trunc(Date.now() / 86400000) + 1) * 86400000); await inventory.save(); } diff --git a/src/services/inventoryService.ts b/src/services/inventoryService.ts index fd6a597b..c9e81c78 100644 --- a/src/services/inventoryService.ts +++ b/src/services/inventoryService.ts @@ -1769,3 +1769,23 @@ export const setupKahlSyndicate = (inventory: TInventoryDatabaseDocument): void Tag: "KahlSyndicate" }); }; + +export const cleanupInventory = (inventory: TInventoryDatabaseDocument): void => { + let index = inventory.MiscItems.findIndex(x => x.ItemType == ""); + if (index != -1) { + inventory.MiscItems.splice(index, 1); + } + + index = inventory.Affiliations.findIndex(x => x.Tag == "KahlSyndicate"); + if (index != -1 && !inventory.Affiliations[index].WeeklyMissions) { + logger.debug(`KahlSyndicate seems broken, removing it and setting up again`); + inventory.Affiliations.splice(index, 1); + setupKahlSyndicate(inventory); + } + + const LibrarySyndicate = inventory.Affiliations.find(x => x.Tag == "LibrarySyndicate"); + if (LibrarySyndicate && LibrarySyndicate.FreeFavorsEarned) { + logger.debug(`removing FreeFavorsEarned from LibrarySyndicate`); + LibrarySyndicate.FreeFavorsEarned = undefined; + } +}; From 6d93ae9f2dcb8d109d14d8804deed690ed205280 Mon Sep 17 00:00:00 2001 From: Sainan <63328889+Sainan@users.noreply.github.com> Date: Tue, 22 Apr 2025 09:59:41 -0700 Subject: [PATCH 08/16] fix: be less strict with required avatar type for personal synthesis (#1768) Fixes #1766 Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/1768 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com> --- src/services/missionInventoryUpdateService.ts | 58 ++++++++++--------- 1 file changed, 30 insertions(+), 28 deletions(-) diff --git a/src/services/missionInventoryUpdateService.ts b/src/services/missionInventoryUpdateService.ts index 4dcb0fe4..46d039c1 100644 --- a/src/services/missionInventoryUpdateService.ts +++ b/src/services/missionInventoryUpdateService.ts @@ -55,6 +55,7 @@ import { Loadout } from "../models/inventoryModels/loadoutModel"; import { ILoadoutConfigDatabase } from "../types/saveLoadoutTypes"; import { getLiteSortie, getWorldState, idToWeek } from "./worldStateService"; import { config } from "./configService"; +import libraryDailyTasks from "@/static/fixed_responses/libraryDailyTasks.json"; const getRotations = (rewardInfo: IRewardInfo, tierOverride?: number): number[] => { // For Spy missions, e.g. 3 vaults cracked = A, B, C @@ -331,35 +332,36 @@ export const addMissionInventoryUpdates = async ( case "LibraryScans": value.forEach(scan => { let synthesisIgnored = true; - if ( - inventory.LibraryPersonalTarget && - libraryPersonalTargetToAvatar[inventory.LibraryPersonalTarget] == scan.EnemyType - ) { - let progress = inventory.LibraryPersonalProgress.find( - x => x.TargetType == inventory.LibraryPersonalTarget - ); - if (!progress) { - progress = - inventory.LibraryPersonalProgress[ - inventory.LibraryPersonalProgress.push({ - TargetType: inventory.LibraryPersonalTarget, - Scans: 0, - Completed: false - }) - 1 - ]; + if (inventory.LibraryPersonalTarget) { + const taskAvatar = libraryPersonalTargetToAvatar[inventory.LibraryPersonalTarget]; + const taskAvatars = libraryDailyTasks.find(x => x.indexOf(taskAvatar) != -1)!; + if (taskAvatars.indexOf(scan.EnemyType) != -1) { + let progress = inventory.LibraryPersonalProgress.find( + x => x.TargetType == inventory.LibraryPersonalTarget + ); + if (!progress) { + progress = + inventory.LibraryPersonalProgress[ + inventory.LibraryPersonalProgress.push({ + TargetType: inventory.LibraryPersonalTarget, + Scans: 0, + Completed: false + }) - 1 + ]; + } + progress.Scans += scan.Count; + if ( + progress.Scans >= + (inventory.LibraryPersonalTarget == + "/Lotus/Types/Game/Library/Targets/DragonframeQuestTarget" + ? 3 + : 10) + ) { + progress.Completed = true; + } + logger.debug(`synthesis of ${scan.EnemyType} added to personal target progress`); + synthesisIgnored = false; } - progress.Scans += scan.Count; - if ( - progress.Scans >= - (inventory.LibraryPersonalTarget == - "/Lotus/Types/Game/Library/Targets/DragonframeQuestTarget" - ? 3 - : 10) - ) { - progress.Completed = true; - } - logger.debug(`synthesis of ${scan.EnemyType} added to personal target progress`); - synthesisIgnored = false; } if ( inventory.LibraryActiveDailyTaskInfo && From 3b20a109f65fa7f9763f1abcd463ca0ff094457f Mon Sep 17 00:00:00 2001 From: Sainan <63328889+Sainan@users.noreply.github.com> Date: Tue, 22 Apr 2025 09:59:54 -0700 Subject: [PATCH 09/16] fix: handle saveDialogue without YearIteration having been supplied (#1774) This is needed for The Hex rank up dialogues, which are independent of the year iterations. Fixes #1773 Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/1774 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com> --- src/controllers/api/saveDialogueController.ts | 11 +++-------- src/models/inventoryModels/inventoryModel.ts | 2 +- src/types/inventoryTypes/inventoryTypes.ts | 4 ++-- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/src/controllers/api/saveDialogueController.ts b/src/controllers/api/saveDialogueController.ts index 7d7d6380..49cc605c 100644 --- a/src/controllers/api/saveDialogueController.ts +++ b/src/controllers/api/saveDialogueController.ts @@ -12,22 +12,17 @@ export const saveDialogueController: RequestHandler = async (req, res) => { const request = JSON.parse(String(req.body)) as SaveDialogueRequest; if ("YearIteration" in request) { const inventory = await getInventory(accountId, "DialogueHistory"); - if (inventory.DialogueHistory) { - inventory.DialogueHistory.YearIteration = request.YearIteration; - } else { - inventory.DialogueHistory = { YearIteration: request.YearIteration }; - } + inventory.DialogueHistory ??= {}; + inventory.DialogueHistory.YearIteration = request.YearIteration; await inventory.save(); res.end(); } else { const inventory = await getInventory(accountId); - if (!inventory.DialogueHistory) { - throw new Error("bad inventory state"); - } const inventoryChanges: IInventoryChanges = {}; const tomorrowAt0Utc = config.noKimCooldowns ? Date.now() : (Math.trunc(Date.now() / 86400_000) + 1) * 86400_000; + inventory.DialogueHistory ??= {}; inventory.DialogueHistory.Dialogues ??= []; const dialogue = getDialogue(inventory, request.DialogueName); dialogue.Rank = request.Rank; diff --git a/src/models/inventoryModels/inventoryModel.ts b/src/models/inventoryModels/inventoryModel.ts index 775de04a..6b73186f 100644 --- a/src/models/inventoryModels/inventoryModel.ts +++ b/src/models/inventoryModels/inventoryModel.ts @@ -909,7 +909,7 @@ dialogueSchema.set("toJSON", { const dialogueHistorySchema = new Schema( { - YearIteration: { type: Number, required: true }, + YearIteration: Number, Resets: Number, Dialogues: { type: [dialogueSchema], required: false } }, diff --git a/src/types/inventoryTypes/inventoryTypes.ts b/src/types/inventoryTypes/inventoryTypes.ts index 219f43a5..8ddfbf42 100644 --- a/src/types/inventoryTypes/inventoryTypes.ts +++ b/src/types/inventoryTypes/inventoryTypes.ts @@ -1130,13 +1130,13 @@ export interface IEndlessXpProgress { } export interface IDialogueHistoryClient { - YearIteration: number; + YearIteration?: number; Resets?: number; // added in 38.5.0 Dialogues?: IDialogueClient[]; } export interface IDialogueHistoryDatabase { - YearIteration: number; + YearIteration?: number; Resets?: number; Dialogues?: IDialogueDatabase[]; } From c4b8a71c5affbb99de264840d8d7b9a3d9c6cd74 Mon Sep 17 00:00:00 2001 From: Sainan <63328889+Sainan@users.noreply.github.com> Date: Tue, 22 Apr 2025 10:00:04 -0700 Subject: [PATCH 10/16] chore(webui): provide "max rank" option when only exalted needs it (#1776) Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/1776 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com> --- static/webui/script.js | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/static/webui/script.js b/static/webui/script.js index a2b8619c..d570d1b9 100644 --- a/static/webui/script.js +++ b/static/webui/script.js @@ -443,12 +443,28 @@ function updateInventory() { maxXP /= 2; } - if (item.XP < maxXP) { + let anyExaltedMissingXP = false; + if (item.XP >= maxXP && "exalted" in itemMap[item.ItemType]) { + for (const exaltedType of itemMap[item.ItemType].exalted) { + const exaltedItem = data.SpecialItems.find(x => x.ItemType == exaltedType); + if (exaltedItem) { + const exaltedCap = itemMap[exaltedType]?.type == "weapons" ? 800_000 : 1_600_000; + if (exaltedItem.XP < exaltedCap) { + anyExaltedMissingXP = true; + break; + } + } + } + } + + if (item.XP < maxXP || anyExaltedMissingXP) { const a = document.createElement("a"); a.href = "#"; a.onclick = function (event) { event.preventDefault(); - addGearExp(category, item.ItemId.$oid, maxXP - item.XP); + if (item.XP < maxXP) { + addGearExp(category, item.ItemId.$oid, maxXP - item.XP); + } if ("exalted" in itemMap[item.ItemType]) { for (const exaltedType of itemMap[item.ItemType].exalted) { const exaltedItem = data.SpecialItems.find(x => x.ItemType == exaltedType); From 409f41d3bf346d1807fb32f50cf90f5da33b7173 Mon Sep 17 00:00:00 2001 From: Sainan <63328889+Sainan@users.noreply.github.com> Date: Tue, 22 Apr 2025 10:00:10 -0700 Subject: [PATCH 11/16] feat(webui): remove unranked mods (#1778) Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/1778 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com> --- src/app.ts | 2 +- .../custom/getItemListsController.ts | 4 +++ static/webui/index.html | 3 ++- static/webui/script.js | 27 ++++++++++++++++++- static/webui/translations/de.js | 1 + static/webui/translations/en.js | 1 + static/webui/translations/es.js | 1 + static/webui/translations/fr.js | 1 + static/webui/translations/ru.js | 1 + static/webui/translations/zh.js | 1 + 10 files changed, 39 insertions(+), 3 deletions(-) diff --git a/src/app.ts b/src/app.ts index c8b19583..291372f0 100644 --- a/src/app.ts +++ b/src/app.ts @@ -26,7 +26,7 @@ app.use((req, _res, next) => { app.use(bodyParser.raw()); app.use(express.json({ limit: "4mb" })); -app.use(bodyParser.text()); +app.use(bodyParser.text({ limit: "4mb" })); app.use(requestLogger); app.use("/api", apiRouter); diff --git a/src/controllers/custom/getItemListsController.ts b/src/controllers/custom/getItemListsController.ts index 214c51e7..1c7d95f4 100644 --- a/src/controllers/custom/getItemListsController.ts +++ b/src/controllers/custom/getItemListsController.ts @@ -29,6 +29,7 @@ interface ListedItem { badReason?: "starter" | "frivolous" | "notraw"; partType?: string; chainLength?: number; + parazon?: boolean; } const relicQualitySuffixes: Record = { @@ -196,6 +197,9 @@ const getItemListsController: RequestHandler = (req, response) => { } else if (upgrade.upgradeEntries) { mod.badReason = "notraw"; } + if (upgrade.type == "PARAZON") { + mod.parazon = true; + } res.mods.push(mod); } for (const [uniqueName, upgrade] of Object.entries(ExportAvionics)) { diff --git a/static/webui/index.html b/static/webui/index.html index 5df7ba59..eb131de2 100644 --- a/static/webui/index.html +++ b/static/webui/index.html @@ -490,8 +490,9 @@
-
+
+
diff --git a/static/webui/script.js b/static/webui/script.js index d570d1b9..562591fb 100644 --- a/static/webui/script.js +++ b/static/webui/script.js @@ -804,7 +804,7 @@ function updateInventory() { { const td = document.createElement("td"); td.classList = "text-end text-nowrap"; - { + if (maxRank != 0) { const a = document.createElement("a"); a.href = "#"; a.onclick = function (event) { @@ -1612,6 +1612,31 @@ function doAddAllMods() { }); } +function doRemoveUnrankedMods() { + revalidateAuthz(() => { + const req = $.get("/api/inventory.php?" + window.authz + "&xpBasedLevelCapDisabled=1"); + req.done(inventory => { + window.itemListPromise.then(itemMap => { + $.post({ + url: "/api/sell.php?" + window.authz, + contentType: "text/plain", + data: JSON.stringify({ + SellCurrency: "SC_RegularCredits", + SellPrice: 0, + Items: { + Upgrades: inventory.RawUpgrades.filter( + x => !itemMap[x.ItemType]?.parazon && x.ItemCount > 0 + ).map(x => ({ String: x.ItemType, Count: x.ItemCount })) + } + }) + }).done(function () { + updateInventory(); + }); + }); + }); + }); +} + // Powersuit Route single.getRoute("#powersuit-route").on("beforeload", function () { diff --git a/static/webui/translations/de.js b/static/webui/translations/de.js index 40bb5667..73ffcc83 100644 --- a/static/webui/translations/de.js +++ b/static/webui/translations/de.js @@ -115,6 +115,7 @@ dict = { mods_rivens: `Rivens`, mods_mods: `Mods`, mods_bulkAddMods: `Fehlende Mods hinzufügen`, + mods_removeUnranked: `[UNTRANSLATED] Remove Unranked Mods`, cheats_administratorRequirement: `Du musst Administrator sein, um diese Funktion nutzen zu können. Um Administrator zu werden, füge |DISPLAYNAME| zu administratorNames in der config.json hinzu.`, cheats_server: `Server`, cheats_skipTutorial: `Tutorial überspringen`, diff --git a/static/webui/translations/en.js b/static/webui/translations/en.js index cd27b42d..dc895457 100644 --- a/static/webui/translations/en.js +++ b/static/webui/translations/en.js @@ -114,6 +114,7 @@ dict = { mods_rivens: `Rivens`, mods_mods: `Mods`, mods_bulkAddMods: `Add Missing Mods`, + mods_removeUnranked: `Remove Unranked Mods`, cheats_administratorRequirement: `You must be an administrator to use this feature. To become an administrator, add |DISPLAYNAME| to administratorNames in the config.json.`, cheats_server: `Server`, cheats_skipTutorial: `Skip Tutorial`, diff --git a/static/webui/translations/es.js b/static/webui/translations/es.js index 96916759..24eed094 100644 --- a/static/webui/translations/es.js +++ b/static/webui/translations/es.js @@ -115,6 +115,7 @@ dict = { mods_rivens: `Agrietados`, mods_mods: `Mods`, mods_bulkAddMods: `Agregar mods faltantes`, + mods_removeUnranked: `[UNTRANSLATED] Remove Unranked Mods`, cheats_administratorRequirement: `Debes ser administrador para usar esta función. Para convertirte en administrador, agrega |DISPLAYNAME| a administratorNames en el archivo config.json.`, cheats_server: `Servidor`, cheats_skipTutorial: `Omitir tutorial`, diff --git a/static/webui/translations/fr.js b/static/webui/translations/fr.js index 11b310d1..e174ec7d 100644 --- a/static/webui/translations/fr.js +++ b/static/webui/translations/fr.js @@ -115,6 +115,7 @@ dict = { mods_rivens: `Rivens`, mods_mods: `Mods`, mods_bulkAddMods: `Ajouter les mods manquants`, + mods_removeUnranked: `[UNTRANSLATED] Remove Unranked Mods`, cheats_administratorRequirement: `Rôle d'administrateur requis pour cette fonctionnalité. Ajoutez |DISPLAYNAME| à la ligne administratorNames dans le fichier config.json.`, cheats_server: `Serveur`, cheats_skipTutorial: `Passer le tutoriel`, diff --git a/static/webui/translations/ru.js b/static/webui/translations/ru.js index 97956a1b..e3862a26 100644 --- a/static/webui/translations/ru.js +++ b/static/webui/translations/ru.js @@ -115,6 +115,7 @@ dict = { mods_rivens: `Моды Разлома`, mods_mods: `Моды`, mods_bulkAddMods: `Добавить отсутствующие моды`, + mods_removeUnranked: `[UNTRANSLATED] Remove Unranked Mods`, cheats_administratorRequirement: `Вы должны быть администратором для использования этой функции. Чтобы стать администратором, добавьте \"|DISPLAYNAME|\" в administratorNames в config.json.`, cheats_server: `Сервер`, cheats_skipTutorial: `Пропустить обучение`, diff --git a/static/webui/translations/zh.js b/static/webui/translations/zh.js index f97ec5d2..ae832c7d 100644 --- a/static/webui/translations/zh.js +++ b/static/webui/translations/zh.js @@ -115,6 +115,7 @@ dict = { mods_rivens: `裂罅MOD`, mods_mods: `Mods`, mods_bulkAddMods: `添加缺失MOD`, + mods_removeUnranked: `[UNTRANSLATED] Remove Unranked Mods`, cheats_administratorRequirement: `您必须是管理员才能使用此功能。要成为管理员,请将 |DISPLAYNAME| 添加到 config.json 的 administratorNames 中。`, cheats_server: `服务器`, cheats_skipTutorial: `跳过教程`, From 3aa853f953438f3265d6f471955395f35ccc9283 Mon Sep 17 00:00:00 2001 From: Sainan <63328889+Sainan@users.noreply.github.com> Date: Tue, 22 Apr 2025 10:00:26 -0700 Subject: [PATCH 12/16] feat(webui): register (#1779) Closes #740 Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/1779 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com> --- static/webui/index.html | 1 + static/webui/script.js | 14 ++++++++++++-- static/webui/translations/de.js | 1 + static/webui/translations/en.js | 1 + static/webui/translations/es.js | 1 + static/webui/translations/fr.js | 1 + static/webui/translations/ru.js | 1 + static/webui/translations/zh.js | 1 + 8 files changed, 19 insertions(+), 2 deletions(-) diff --git a/static/webui/index.html b/static/webui/index.html index eb131de2..65a9d832 100644 --- a/static/webui/index.html +++ b/static/webui/index.html @@ -85,6 +85,7 @@
+
diff --git a/static/webui/script.js b/static/webui/script.js index 562591fb..7868e189 100644 --- a/static/webui/script.js +++ b/static/webui/script.js @@ -1,8 +1,15 @@ +let loginOrRegisterPending = false; +window.registerSubmit = false; + function doLogin() { + if (loginOrRegisterPending) { + return; + } + loginOrRegisterPending = true; localStorage.setItem("email", $("#email").val()); localStorage.setItem("password", $("#password").val()); - $("#email, #password").val(""); loginFromLocalStorage(); + registerSubmit = false; } function loginFromLocalStorage() { @@ -37,12 +44,15 @@ function doLoginRequest(succ_cb, fail_cb) { s: "W0RFXVN0ZXZlIGxpa2VzIGJpZyBidXR0cw==", // signature of some kind lang: "en", date: 1501230947855458660, // ??? - ClientType: "webui", + ClientType: registerSubmit ? "" : "webui", PS: "W0RFXVN0ZXZlIGxpa2VzIGJpZyBidXR0cw==" // anti-cheat data }) }); req.done(succ_cb); req.fail(fail_cb); + req.always(() => { + loginOrRegisterPending = false; + }); } function revalidateAuthz(succ_cb) { diff --git a/static/webui/translations/de.js b/static/webui/translations/de.js index 73ffcc83..b8725e00 100644 --- a/static/webui/translations/de.js +++ b/static/webui/translations/de.js @@ -60,6 +60,7 @@ dict = { login_emailLabel: `E-Mail-Adresse`, login_passwordLabel: `Passwort`, login_loginButton: `Anmelden`, + login_registerButton: `[UNTRANSLATED] Register`, navbar_logout: `Abmelden`, navbar_renameAccount: `Account umbenennen`, navbar_deleteAccount: `Account löschen`, diff --git a/static/webui/translations/en.js b/static/webui/translations/en.js index dc895457..23b8133a 100644 --- a/static/webui/translations/en.js +++ b/static/webui/translations/en.js @@ -59,6 +59,7 @@ dict = { login_emailLabel: `Email address`, login_passwordLabel: `Password`, login_loginButton: `Login`, + login_registerButton: `Register`, navbar_logout: `Logout`, navbar_renameAccount: `Rename Account`, navbar_deleteAccount: `Delete Account`, diff --git a/static/webui/translations/es.js b/static/webui/translations/es.js index 24eed094..222534cd 100644 --- a/static/webui/translations/es.js +++ b/static/webui/translations/es.js @@ -60,6 +60,7 @@ dict = { login_emailLabel: `Dirección de correo electrónico`, login_passwordLabel: `Contraseña`, login_loginButton: `Iniciar sesión`, + login_registerButton: `[UNTRANSLATED] Register`, navbar_logout: `Cerrar sesión`, navbar_renameAccount: `Renombrar cuenta`, navbar_deleteAccount: `Eliminar cuenta`, diff --git a/static/webui/translations/fr.js b/static/webui/translations/fr.js index e174ec7d..682086aa 100644 --- a/static/webui/translations/fr.js +++ b/static/webui/translations/fr.js @@ -60,6 +60,7 @@ dict = { login_emailLabel: `Email`, login_passwordLabel: `Mot de passe`, login_loginButton: `Connexion`, + login_registerButton: `[UNTRANSLATED] Register`, navbar_logout: `Déconnexion`, navbar_renameAccount: `Renommer le compte`, navbar_deleteAccount: `Supprimer le compte`, diff --git a/static/webui/translations/ru.js b/static/webui/translations/ru.js index e3862a26..959678f3 100644 --- a/static/webui/translations/ru.js +++ b/static/webui/translations/ru.js @@ -60,6 +60,7 @@ dict = { login_emailLabel: `Адрес электронной почты`, login_passwordLabel: `Пароль`, login_loginButton: `Войти`, + login_registerButton: `[UNTRANSLATED] Register`, navbar_logout: `Выйти`, navbar_renameAccount: `Переименовать аккаунт`, navbar_deleteAccount: `Удалить аккаунт`, diff --git a/static/webui/translations/zh.js b/static/webui/translations/zh.js index ae832c7d..3f0e01f5 100644 --- a/static/webui/translations/zh.js +++ b/static/webui/translations/zh.js @@ -60,6 +60,7 @@ dict = { login_emailLabel: `电子邮箱`, login_passwordLabel: `密码`, login_loginButton: `登录`, + login_registerButton: `[UNTRANSLATED] Register`, navbar_logout: `退出登录`, navbar_renameAccount: `重命名账户`, navbar_deleteAccount: `删除账户`, From 23dafb53d1a1619f7dc8fe316984aa663e46ca2c Mon Sep 17 00:00:00 2001 From: Sainan <63328889+Sainan@users.noreply.github.com> Date: Tue, 22 Apr 2025 10:00:38 -0700 Subject: [PATCH 13/16] fix: skipTutorial sets ReceivedStartingGear before giving the gear (#1780) This was raising a warning when creating a new account. Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/1780 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com> --- src/services/inventoryService.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/services/inventoryService.ts b/src/services/inventoryService.ts index c9e81c78..9e89dcfe 100644 --- a/src/services/inventoryService.ts +++ b/src/services/inventoryService.ts @@ -87,9 +87,7 @@ export const createInventory = async ( const inventory = new Inventory({ accountOwnerId: accountOwnerId, LoadOutPresets: defaultItemReferences.loadOutPresetId, - Ships: [defaultItemReferences.ship], - PlayedParkourTutorial: config.skipTutorial, - ReceivedStartingGear: config.skipTutorial + Ships: [defaultItemReferences.ship] }); inventory.LibraryAvailableDailyTaskInfo = createLibraryDailyTask(); @@ -102,6 +100,7 @@ export const createInventory = async ( await addItem(inventory, "/Lotus/Types/Friendly/PlayerControllable/Weapons/DuviriDualSwords"); if (config.skipTutorial) { + inventory.PlayedParkourTutorial = true; await addStartingGear(inventory); await completeQuest(inventory, "/Lotus/Types/Keys/VorsPrize/VorsPrizeQuestKeyChain"); From 32bb6d4ccbb0bcb8890679528612b5194984b113 Mon Sep 17 00:00:00 2001 From: Sainan <63328889+Sainan@users.noreply.github.com> Date: Tue, 22 Apr 2025 10:00:49 -0700 Subject: [PATCH 14/16] feat: syndicate mission rotation (#1781) Closes #1530 Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/1781 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com> --- src/services/worldStateService.ts | 67 +++++++++++++++---- .../worldState/worldState.json | 48 ------------- 2 files changed, 54 insertions(+), 61 deletions(-) diff --git a/src/services/worldStateService.ts b/src/services/worldStateService.ts index 2ca13620..e1946f7a 100644 --- a/src/services/worldStateService.ts +++ b/src/services/worldStateService.ts @@ -4,14 +4,7 @@ import { unixTimesInMs } from "@/src/constants/timeConstants"; import { config } from "@/src/services/configService"; import { CRng } from "@/src/services/rngService"; import { eMissionType, ExportNightwave, ExportRegions } from "warframe-public-export-plus"; -import { - ICalendarDay, - ICalendarSeason, - ILiteSortie, - ISeasonChallenge, - ISortie, - IWorldState -} from "../types/worldStateTypes"; +import { ICalendarDay, ICalendarSeason, ILiteSortie, ISeasonChallenge, IWorldState } from "../types/worldStateTypes"; const sortieBosses = [ "SORTIE_BOSS_HYENA", @@ -174,7 +167,47 @@ const getSortieTime = (day: number): number => { return dayStart + (isDst ? 16 : 17) * 3600000; }; -const pushSortieIfRelevant = (out: ISortie[], day: number): void => { +const pushSyndicateMissions = ( + worldState: IWorldState, + day: number, + seed: number, + idSuffix: string, + syndicateTag: string +): void => { + const nodeOptions: string[] = []; + for (const [key, value] of Object.entries(ExportRegions)) { + if ( + value.name.indexOf("Archwing") == -1 && // no archwing + value.systemIndex != 23 && // no 1999 stuff + value.missionIndex != 10 && // Exclude MT_PVP (for relays) + value.missionIndex != 23 && // no junctions + value.missionIndex <= 28 // no railjack or some such + ) { + nodeOptions.push(key); + } + } + + const rng = new CRng(seed); + const nodes: string[] = []; + for (let i = 0; i != 6; ++i) { + const index = rng.randomInt(0, nodeOptions.length - 1); + nodes.push(nodeOptions[index]); + nodeOptions.splice(index, 1); + } + + const dayStart = getSortieTime(day); + const dayEnd = getSortieTime(day + 1); + worldState.SyndicateMissions.push({ + _id: { $oid: Math.trunc(dayStart / 1000).toString(16) + idSuffix }, + Activation: { $date: { $numberLong: dayStart.toString() } }, + Expiry: { $date: { $numberLong: dayEnd.toString() } }, + Tag: syndicateTag, + Seed: seed, + Nodes: nodes + }); +}; + +const pushSortieIfRelevant = (worldState: IWorldState, day: number): void => { const dayStart = getSortieTime(day); if (!isBeforeNextExpectedWorldStateRefresh(dayStart)) { return; @@ -231,6 +264,7 @@ const pushSortieIfRelevant = (out: ISortie[], day: number): void => { value.name.indexOf("Archwing") == -1 && value.missionIndex != 0 && // Exclude MT_ASSASSINATION value.missionIndex != 5 && // Exclude MT_CAPTURE + value.missionIndex != 10 && // Exclude MT_PVP (for relays) value.missionIndex != 21 && // Exclude MT_PURIFY value.missionIndex != 22 && // Exclude MT_ARENA value.missionIndex != 23 && // Exclude MT_JUNCTION @@ -292,7 +326,7 @@ const pushSortieIfRelevant = (out: ISortie[], day: number): void => { missionTypes.add(missionType); } - out.push({ + worldState.Sorties.push({ _id: { $oid: Math.trunc(dayStart / 1000).toString(16) + "d4d932c97c0a3acd" }, Activation: { $date: { $numberLong: dayStart.toString() } }, Expiry: { $date: { $numberLong: dayEnd.toString() } }, @@ -301,6 +335,13 @@ const pushSortieIfRelevant = (out: ISortie[], day: number): void => { Boss: boss, Variants: selectedNodes }); + + pushSyndicateMissions(worldState, day, rng.randomInt(0, 0xffff), "ba6f84724fa48049", "ArbitersSyndicate"); + pushSyndicateMissions(worldState, day, rng.randomInt(0, 0xffff), "ba6f84724fa4804a", "CephalonSudaSyndicate"); + pushSyndicateMissions(worldState, day, rng.randomInt(0, 0xffff), "ba6f84724fa4804e", "NewLokaSyndicate"); + pushSyndicateMissions(worldState, day, rng.randomInt(0, 0xffff), "ba6f84724fa48050", "PerrinSyndicate"); + pushSyndicateMissions(worldState, day, rng.randomInt(0, 0xffff), "ba6f84724fa4805e", "RedVeilSyndicate"); + pushSyndicateMissions(worldState, day, rng.randomInt(0, 0xffff), "ba6f84724fa48061", "SteelMeridianSyndicate"); }; const dailyChallenges = Object.keys(ExportNightwave.challenges).filter(x => @@ -953,9 +994,9 @@ export const getWorldState = (buildLabel?: string): IWorldState => { }); } - // Sortie cycling every day - pushSortieIfRelevant(worldState.Sorties, day - 1); - pushSortieIfRelevant(worldState.Sorties, day); + // Sortie & syndicate missions cycling every day (at 16:00 or 17:00 UTC depending on if London, OT is observing DST) + pushSortieIfRelevant(worldState, day - 1); + pushSortieIfRelevant(worldState, day); // Archon Hunt cycling every week worldState.LiteSorties.push(getLiteSortie(week)); diff --git a/static/fixed_responses/worldState/worldState.json b/static/fixed_responses/worldState/worldState.json index dd76dd56..9adb9556 100644 --- a/static/fixed_responses/worldState/worldState.json +++ b/static/fixed_responses/worldState/worldState.json @@ -63,22 +63,6 @@ } ], "SyndicateMissions": [ - { - "_id": { "$oid": "663a4fc5ba6f84724fa48049" }, - "Activation": { "$date": { "$numberLong": "1715097541439" } }, - "Expiry": { "$date": { "$numberLong": "2000000000000" } }, - "Tag": "ArbitersSyndicate", - "Seed": 24491, - "Nodes": ["SolNode223", "SolNode89", "SolNode146", "SolNode212", "SolNode167", "SolNode48", "SolNode78"] - }, - { - "_id": { "$oid": "663a4fc5ba6f84724fa4804a" }, - "Activation": { "$date": { "$numberLong": "1715097541439" } }, - "Expiry": { "$date": { "$numberLong": "2000000000000" } }, - "Tag": "CephalonSudaSyndicate", - "Seed": 12770, - "Nodes": ["SolNode36", "SolNode59", "SettlementNode12", "SolNode61", "SolNode12", "SolNode138", "SolNode72"] - }, { "_id": { "$oid": "663a4fc5ba6f84724fa4804c" }, "Activation": { "$date": { "$numberLong": "1715097541439" } }, @@ -103,14 +87,6 @@ "Seed": 50102, "Nodes": [] }, - { - "_id": { "$oid": "663a4fc5ba6f84724fa4804e" }, - "Activation": { "$date": { "$numberLong": "1715097541439" } }, - "Expiry": { "$date": { "$numberLong": "2000000000000" } }, - "Tag": "NewLokaSyndicate", - "Seed": 16064, - "Nodes": ["SolNode101", "SolNode224", "SolNode205", "SettlementNode2", "SolNode171", "SolNode188", "SolNode75"] - }, { "_id": { "$oid": "663a4fc5ba6f84724fa4804f" }, "Activation": { "$date": { "$numberLong": "1715097541439" } }, @@ -119,14 +95,6 @@ "Seed": 77721, "Nodes": [] }, - { - "_id": { "$oid": "663a4fc5ba6f84724fa48050" }, - "Activation": { "$date": { "$numberLong": "1715097541439" } }, - "Expiry": { "$date": { "$numberLong": "2000000000000" } }, - "Tag": "PerrinSyndicate", - "Seed": 9940, - "Nodes": ["SolNode39", "SolNode14", "SolNode203", "SolNode100", "SolNode130", "SolNode64", "SettlementNode15"] - }, { "_id": { "$oid": "663a4fc5ba6f84724fa48052" }, "Activation": { "$date": { "$numberLong": "1715097541439" } }, @@ -255,14 +223,6 @@ "Seed": 67257, "Nodes": [] }, - { - "_id": { "$oid": "663a4fc5ba6f84724fa4805e" }, - "Activation": { "$date": { "$numberLong": "1715097541439" } }, - "Expiry": { "$date": { "$numberLong": "2000000000000" } }, - "Tag": "RedVeilSyndicate", - "Seed": 46649, - "Nodes": ["SolNode226", "SolNode79", "SolNode216", "SettlementNode11", "SolNode56", "SolNode41", "SolNode23"] - }, { "_id": { "$oid": "663a4fc5ba6f84724fa48060" }, "Activation": { "$date": { "$numberLong": "1715097541439" } }, @@ -270,14 +230,6 @@ "Tag": "VoxSyndicate", "Seed": 77972, "Nodes": [] - }, - { - "_id": { "$oid": "663a4fc5ba6f84724fa48061" }, - "Activation": { "$date": { "$numberLong": "1715097541439" } }, - "Expiry": { "$date": { "$numberLong": "2000000000000" } }, - "Tag": "SteelMeridianSyndicate", - "Seed": 42366, - "Nodes": ["SolNode27", "SolNode107", "SolNode214", "SettlementNode1", "SolNode177", "SolNode141", "SolNode408"] } ], "ActiveMissions": [ From daacbf6f7b2deeb3aeb47b2b1eb70ce1efc9048c Mon Sep 17 00:00:00 2001 From: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com> Date: Tue, 22 Apr 2025 10:00:58 -0700 Subject: [PATCH 15/16] fix(webui): add `exalted` array for KubrowPets ItemLists (#1782) Closes #1770 Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/1782 Co-authored-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com> Co-committed-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com> --- src/controllers/custom/getItemListsController.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/controllers/custom/getItemListsController.ts b/src/controllers/custom/getItemListsController.ts index 1c7d95f4..1ff78b62 100644 --- a/src/controllers/custom/getItemListsController.ts +++ b/src/controllers/custom/getItemListsController.ts @@ -69,7 +69,8 @@ const getItemListsController: RequestHandler = (req, response) => { if (item.productCategory != "SpecialItems") { res[item.productCategory].push({ uniqueName, - name: getString(item.name, lang) + name: getString(item.name, lang), + exalted: item.exalted }); } } From e17d43dcb6eef137adb60a10d1b6b1032e5de059 Mon Sep 17 00:00:00 2001 From: Sainan <63328889+Sainan@users.noreply.github.com> Date: Tue, 22 Apr 2025 15:20:50 -0700 Subject: [PATCH 16/16] chore: fix slotNames duplication (#1798) Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/1798 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com> --- src/services/importService.ts | 16 ++-------------- src/types/purchaseTypes.ts | 1 + 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/src/services/importService.ts b/src/services/importService.ts index ea03047b..cde182cc 100644 --- a/src/services/importService.ts +++ b/src/services/importService.ts @@ -37,6 +37,7 @@ import { } from "../types/inventoryTypes/inventoryTypes"; import { TInventoryDatabaseDocument } from "../models/inventoryModels/inventoryModel"; import { ILoadoutConfigDatabase, ILoadoutDatabase } from "../types/saveLoadoutTypes"; +import { slotNames } from "../types/purchaseTypes"; const convertDate = (value: IMongoDate): Date => { return new Date(parseInt(value.$date.$numberLong)); @@ -212,20 +213,7 @@ export const importInventory = (db: TInventoryDatabaseDocument, client: Partial< replaceArray(db[key], client[key].map(convertOperatorConfig)); } } - for (const key of [ - "SuitBin", - "WeaponBin", - "SentinelBin", - "SpaceSuitBin", - "SpaceWeaponBin", - "PvpBonusLoadoutBin", - "PveBonusLoadoutBin", - "RandomModBin", - "MechBin", - "CrewMemberBin", - "OperatorAmpBin", - "CrewShipSalvageBin" - ] as const) { + for (const key of slotNames) { if (client[key] !== undefined) { replaceSlots(db[key], client[key]); } diff --git a/src/types/purchaseTypes.ts b/src/types/purchaseTypes.ts index 3600e6b7..8cb92ccc 100644 --- a/src/types/purchaseTypes.ts +++ b/src/types/purchaseTypes.ts @@ -103,6 +103,7 @@ export const slotNames = [ "WeaponBin", "MechBin", "PveBonusLoadoutBin", + "PvpBonusLoadoutBin", "SentinelBin", "SpaceSuitBin", "SpaceWeaponBin",