diff --git a/config-vanilla.json b/config-vanilla.json index b8810686..fef4a021 100644 --- a/config-vanilla.json +++ b/config-vanilla.json @@ -41,6 +41,10 @@ "naberusNightsOverride": null, "proxyRebellion": false, "proxyRebellionRewardsOverride": 0, + "voidCorruption2025Week1": false, + "voidCorruption2025Week2": false, + "voidCorruption2025Week3": false, + "voidCorruption2025Week4": false, "galleonOfGhouls": 0, "ghoulEmergenceOverride": null, "plagueStarOverride": null, diff --git a/src/services/configService.ts b/src/services/configService.ts index 0c34e967..0eface6b 100644 --- a/src/services/configService.ts +++ b/src/services/configService.ts @@ -51,6 +51,10 @@ export interface IConfig { naberusNightsOverride?: boolean; proxyRebellion?: boolean; proxyRebellionRewardsOverride?: number; + voidCorruption2025Week1?: boolean; + voidCorruption2025Week2?: boolean; + voidCorruption2025Week3?: boolean; + voidCorruption2025Week4?: boolean; galleonOfGhouls?: number; ghoulEmergenceOverride?: boolean; plagueStarOverride?: boolean; diff --git a/src/services/missionInventoryUpdateService.ts b/src/services/missionInventoryUpdateService.ts index eb586eee..0c2a4f4c 100644 --- a/src/services/missionInventoryUpdateService.ts +++ b/src/services/missionInventoryUpdateService.ts @@ -1151,6 +1151,27 @@ export const addMissionRewards = async ( let ConquestCompletedMissionsCount; let missionCompletionCredits = 0; + + if (rewardInfo.alertId) { + const alert = getWorldState().Alerts.find(x => x._id.$oid == rewardInfo.alertId); + if (!alert) { + logger.warn(`mission completed unknown alert`, { alertId: rewardInfo.alertId }); + } else { + if (inventory.CompletedAlerts.includes(alert._id.$oid)) { + logger.debug(`alert ${alert._id.$oid} already completed, skipping alert reward`); + } else { + inventory.CompletedAlerts.push(alert._id.$oid); + if (alert.MissionInfo.missionReward) { + missionCompletionCredits += addFixedLevelRewards( + alert.MissionInfo.missionReward, + MissionRewards, + rewardInfo + ); + } + } + } + } + //inventory change is what the client has not rewarded itself, also the client needs to know the credit changes for display if (rewardInfo.goalId) { diff --git a/src/services/worldStateService.ts b/src/services/worldStateService.ts index 144698e9..fb8fb029 100644 --- a/src/services/worldStateService.ts +++ b/src/services/worldStateService.ts @@ -19,6 +19,7 @@ import type { ICalendarDay, ICalendarEvent, ICalendarSeason, + IAlert, IGoal, IInvasion, ILiteSortie, @@ -112,6 +113,89 @@ const sortieBossNode: Record, SORTIE_BOSS_VOR: "SolNode108" }; +const configAlerts: Record = { + voidCorruption2025Week1: { + _id: { $oid: "677d452e2f324ee7b90f8ccf" }, + Activation: { $date: { $numberLong: "1736524800000" } }, + Expiry: { $date: { $numberLong: "2000000000000" } }, + MissionInfo: { + location: "SolNode61", + missionType: "MT_SABOTAGE", + faction: "FC_CORPUS", + difficulty: 1, + missionReward: { + credits: 30000, + items: ["/Lotus/StoreItems/Upgrades/Mods/Pistol/DualStat/CorruptedFireRateDamagePistol"] + }, + levelOverride: "/Lotus/Levels/Proc/Corpus/CorpusShipCoreSabotage", + enemySpec: "/Lotus/Types/Game/EnemySpecs/CorpusShipEnemySpecs/CorpusShipSquadA", + extraEnemySpec: "/Lotus/Types/Game/EnemySpecs/GamemodeExtraEnemySpecs/CorpusSabotageTiersA", + minEnemyLevel: 10, + maxEnemyLevel: 15 + } + }, + voidCorruption2025Week2: { + _id: { $oid: "677d45811daeae9de40e8c0f" }, + Activation: { $date: { $numberLong: "1737129600000" } }, + Expiry: { $date: { $numberLong: "2000000000000" } }, + MissionInfo: { + location: "SettlementNode11", + missionType: "MT_DEFENSE", + faction: "FC_CORPUS", + difficulty: 1, + missionReward: { + credits: 30000, + items: ["/Lotus/StoreItems/Upgrades/Mods/Pistol/DualStat/CorruptedCritChanceFireRatePistol"] + }, + levelOverride: "/Lotus/Levels/Proc/Corpus/CorpusShipDefense", + enemySpec: "/Lotus/Types/Game/EnemySpecs/CorpusShipEnemySpecs/CorpusShipSquadDefenseB", + minEnemyLevel: 20, + maxEnemyLevel: 25, + maxWaveNum: 6 + } + }, + voidCorruption2025Week3: { + _id: { $oid: "677d45a494ad716c90006b9a" }, + Activation: { $date: { $numberLong: "1737734400000" } }, + Expiry: { $date: { $numberLong: "2000000000000" } }, + MissionInfo: { + location: "SolNode118", + missionType: "MT_ARTIFACT", + faction: "FC_CORPUS", + difficulty: 1, + missionReward: { + credits: 30000, + items: ["/Lotus/StoreItems/Upgrades/Mods/Pistol/DualStat/CorruptedCritDamagePistol"] + }, + levelOverride: "/Lotus/Levels/Proc/Corpus/CorpusShipDisruption", + enemySpec: "/Lotus/Types/Game/EnemySpecs/CorpusShipEnemySpecs/CorpusShipSurvivalA", + extraEnemySpec: "/Lotus/Types/Game/EnemySpecs/SpecialMissionSpecs/DisruptionCorpusShip", + customAdvancedSpawners: ["/Lotus/Types/Enemies/AdvancedSpawners/ErrantSpecterInvasion"], + minEnemyLevel: 30, + maxEnemyLevel: 35 + } + }, + voidCorruption2025Week4: { + _id: { $oid: "677d4700682d173abb0e19fe" }, + Activation: { $date: { $numberLong: "1738339200000" } }, + Expiry: { $date: { $numberLong: "2000000000000" } }, + MissionInfo: { + location: "SolNode4", + missionType: "MT_EXTERMINATION", + faction: "FC_CORPUS", + difficulty: 1, + missionReward: { + credits: 30000, + items: ["/Lotus/StoreItems/Upgrades/Mods/Pistol/DualStat/CorruptedDamageRecoilPistol"] + }, + levelOverride: "/Lotus/Levels/Proc/Corpus/CorpusShipExterminate", + enemySpec: "/Lotus/Types/Game/EnemySpecs/CorpusShipEnemySpecs/CorpusShipExterminateMixed", + minEnemyLevel: 40, + maxEnemyLevel: 45 + } + } +}; + const eidolonJobs: readonly string[] = [ "/Lotus/Types/Gameplay/Eidolon/Jobs/AssassinateBountyAss", "/Lotus/Types/Gameplay/Eidolon/Jobs/AssassinateBountyCap", @@ -1481,6 +1565,15 @@ export const getWorldState = (buildLabel?: string): IWorldState => { worldState.VoidTraders.push(vt); fullyStockBaro(vt); } + + if (config.worldState) { + for (const [key, alert] of Object.entries(configAlerts)) { + if (config.worldState[key as keyof typeof config.worldState]) { + worldState.Alerts.push(alert); + } + } + } + const isFebruary = date.getUTCMonth() == 1; if (config.worldState?.starDaysOverride ?? isFebruary) { worldState.Goals.push({ diff --git a/src/types/requestTypes.ts b/src/types/requestTypes.ts index 0dac8d75..d762edd8 100644 --- a/src/types/requestTypes.ts +++ b/src/types/requestTypes.ts @@ -178,6 +178,7 @@ export interface IRewardInfo { goalManifest?: string; invasionId?: string; invasionAllyFaction?: "FC_GRINEER" | "FC_CORPUS"; + alertId?: string; sortieId?: string; sortieTag?: "Mission1" | "Mission2" | "Final"; sortiePrereqs?: string[]; diff --git a/src/types/worldStateTypes.ts b/src/types/worldStateTypes.ts index f39c4bf7..723e8875 100644 --- a/src/types/worldStateTypes.ts +++ b/src/types/worldStateTypes.ts @@ -1,4 +1,4 @@ -import type { IMissionReward } from "warframe-public-export-plus"; +import type { IMissionReward, TFaction } from "warframe-public-export-plus"; import type { IMongoDate, IOid } from "./commonTypes.ts"; export interface IWorldState { @@ -7,7 +7,7 @@ export interface IWorldState { Time: number; InGameMarket: IInGameMarket; Goals: IGoal[]; - Alerts: []; + Alerts: IAlert[]; Sorties: ISortie[]; LiteSorties: ILiteSortie[]; SyndicateMissions: ISyndicateMissionInfo[]; @@ -35,6 +35,28 @@ export interface IWorldState { Tmp?: string; } +export interface IAlert { + _id: IOid; + Activation: IMongoDate; + Expiry: IMongoDate; + MissionInfo: IAlertMissionInfo; +} + +export interface IAlertMissionInfo { + location: string; + missionType: string; + faction: TFaction; + difficulty: number; + missionReward?: IMissionReward; + levelOverride?: string; + enemySpec?: string; + extraEnemySpec?: string; + customAdvancedSpawners?: string[]; + minEnemyLevel?: number; + maxEnemyLevel?: number; + maxWaveNum?: number; +} + export interface IGoal { _id: IOid; Activation: IMongoDate; diff --git a/static/webui/index.html b/static/webui/index.html index ba8e4b78..70703102 100644 --- a/static/webui/index.html +++ b/static/webui/index.html @@ -1232,6 +1232,27 @@ +
+ +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
diff --git a/static/webui/translations/de.js b/static/webui/translations/de.js index b642b800..540de36f 100644 --- a/static/webui/translations/de.js +++ b/static/webui/translations/de.js @@ -279,6 +279,7 @@ dict = { worldState_dogDays: `Hitzefrei`, worldState_dogDaysRewards: `[UNTRANSLATED] Dog Days Rewards`, worldState_wolfHunt: `Wolfsjagd (2025)`, + worldState_voidCorruption: `[UNTRANSLATED] Void Corruption (|VAL|)`, worldState_orphixVenom: `Orphix Gift`, worldState_longShadow: `Lange Schatten`, worldState_hallowedFlame: `Geweihte Flamme`, diff --git a/static/webui/translations/en.js b/static/webui/translations/en.js index 57a32595..33ae5fa7 100644 --- a/static/webui/translations/en.js +++ b/static/webui/translations/en.js @@ -278,6 +278,7 @@ dict = { worldState_dogDays: `Dog Days`, worldState_dogDaysRewards: `Dog Days Rewards`, worldState_wolfHunt: `Wolf Hunt (2025)`, + worldState_voidCorruption: `Void Corruption (|VAL|)`, worldState_orphixVenom: `Orphix Venom`, worldState_longShadow: `Long Shadow`, worldState_hallowedFlame: `Hallowed Flame`, diff --git a/static/webui/translations/es.js b/static/webui/translations/es.js index 888f16da..267e66c3 100644 --- a/static/webui/translations/es.js +++ b/static/webui/translations/es.js @@ -279,6 +279,7 @@ dict = { worldState_dogDays: `Canícula`, worldState_dogDaysRewards: `Recompensas de Canícula`, worldState_wolfHunt: `Cacería del Lobo (2025)`, + worldState_voidCorruption: `Corrupción del Vacío (|VAL|)`, worldState_orphixVenom: `Veneno de Orphix`, worldState_longShadow: `Sombra Prolongada`, worldState_hallowedFlame: `Llama Sagrada`, diff --git a/static/webui/translations/fr.js b/static/webui/translations/fr.js index 66fbad3c..3e7e2434 100644 --- a/static/webui/translations/fr.js +++ b/static/webui/translations/fr.js @@ -279,6 +279,7 @@ dict = { worldState_dogDays: `Bataille d'Eau`, worldState_dogDaysRewards: `Récompenses de la Bataille d'Eau`, worldState_wolfHunt: `Chasse au Loup (2025)`, + worldState_voidCorruption: `[UNTRANSLATED] Void Corruption (|VAL|)`, worldState_orphixVenom: `Venin Orphix`, worldState_longShadow: `La Propagation des Ombres`, worldState_hallowedFlame: `Flamme Hantée`, diff --git a/static/webui/translations/ru.js b/static/webui/translations/ru.js index 4de12099..c4ab0386 100644 --- a/static/webui/translations/ru.js +++ b/static/webui/translations/ru.js @@ -279,6 +279,7 @@ dict = { worldState_dogDays: `Знойные дни`, worldState_dogDaysRewards: `Награды Знойных дней`, worldState_wolfHunt: `Волчья Охота (2025)`, + worldState_voidCorruption: `[UNTRANSLATED] Void Corruption (|VAL|)`, worldState_orphixVenom: `Яд Орфикса`, worldState_longShadow: `Длинная Тень`, worldState_hallowedFlame: `Священное пламя`, diff --git a/static/webui/translations/uk.js b/static/webui/translations/uk.js index dcfdc95c..ffb3d11a 100644 --- a/static/webui/translations/uk.js +++ b/static/webui/translations/uk.js @@ -279,6 +279,7 @@ dict = { worldState_dogDays: `Спекотні дні`, worldState_dogDaysRewards: `Нагороди Спекотних днів`, worldState_wolfHunt: `Полювання на Вовка (2025)`, + worldState_voidCorruption: `[UNTRANSLATED] Void Corruption (|VAL|)`, worldState_orphixVenom: `Орфіксова отрута`, worldState_longShadow: `Довга тінь`, worldState_hallowedFlame: `Священне полум'я`, diff --git a/static/webui/translations/zh.js b/static/webui/translations/zh.js index 97a24244..0230716e 100644 --- a/static/webui/translations/zh.js +++ b/static/webui/translations/zh.js @@ -279,6 +279,7 @@ dict = { worldState_dogDays: `三伏天`, worldState_dogDaysRewards: `三伏天奖励设置`, worldState_wolfHunt: `恶狼狩猎 (2025)`, + worldState_voidCorruption: `[UNTRANSLATED] Void Corruption (|VAL|)`, worldState_orphixVenom: `奥影之毒`, worldState_longShadow: `暗夜长影`, worldState_hallowedFlame: `万圣之焰`,