diff --git a/src/helpers/nemesisHelpers.ts b/src/helpers/nemesisHelpers.ts index 14cb6ba8..5ff27a3d 100644 --- a/src/helpers/nemesisHelpers.ts +++ b/src/helpers/nemesisHelpers.ts @@ -212,12 +212,12 @@ export const getInfNodes = (manifest: INemesisManifest, rank: number): IInfNode[ value.systemIndex === systemIndex && value.nodeType != 3 && // not hub value.nodeType != 7 && // not junction - value.missionIndex && // must have a mission type and not assassination - value.missionIndex != 28 && // not open world - value.missionIndex != 32 && // not railjack - value.missionIndex != 41 && // not saya's visions - value.missionIndex != 42 && // not face off - value.name.indexOf("1999NodeI") == -1 && // not stage defence + value.missionType != "MT_ASSASSINATION" && + value.missionType != "MT_LANDSCAPE" && + value.missionType != "MT_RAILJACK" && + value.missionType != "MT_OFFERING" && + value.missionType != "MT_PVPVE" && + value.name.indexOf("1999NodeI") == -1 && // not stage defense value.name.indexOf("1999NodeJ") == -1 && // not lich bounty !isArchwingMission(value) ) { diff --git a/src/services/inventoryService.ts b/src/services/inventoryService.ts index b3c2d2c6..b0603244 100644 --- a/src/services/inventoryService.ts +++ b/src/services/inventoryService.ts @@ -2160,7 +2160,7 @@ export const addMissionComplete = (inventory: TInventoryDatabaseDocument, { Tag, } }; -export const addBooster = (ItemType: string, time: number, inventory: TInventoryDatabaseDocument): void => { +export const addBooster = (ItemType: string, timeSecs: number, inventory: TInventoryDatabaseDocument): void => { const currentTime = Math.floor(Date.now() / 1000); const { Boosters } = inventory; @@ -2169,9 +2169,9 @@ export const addBooster = (ItemType: string, time: number, inventory: TInventory if (itemIndex !== -1) { const existingBooster = Boosters[itemIndex]; - existingBooster.ExpiryDate = Math.max(existingBooster.ExpiryDate, currentTime) + time; + existingBooster.ExpiryDate = Math.max(existingBooster.ExpiryDate, currentTime) + timeSecs; } else { - Boosters.push({ ItemType, ExpiryDate: currentTime + time }); + Boosters.push({ ItemType, ExpiryDate: currentTime + timeSecs }); } }; diff --git a/src/services/missionInventoryUpdateService.ts b/src/services/missionInventoryUpdateService.ts index a6f17c73..c9fa0241 100644 --- a/src/services/missionInventoryUpdateService.ts +++ b/src/services/missionInventoryUpdateService.ts @@ -1,4 +1,9 @@ -import type { IMissionReward as IMissionRewardExternal, IRegion, IReward } from "warframe-public-export-plus"; +import type { + IMissionReward as IMissionRewardExternal, + IRegion, + IReward, + TMissionType +} from "warframe-public-export-plus"; import { ExportEnemies, ExportFusionBundles, @@ -102,10 +107,9 @@ const getRotations = (rewardInfo: IRewardInfo, tierOverride?: number): number[] } const region = ExportRegions[rewardInfo.node] as IRegion | undefined; - const missionIndex: number | undefined = region?.missionIndex; + const missionType: TMissionType | undefined = region?.missionType; - // For Rescue missions - if (missionIndex == 3 && rewardInfo.rewardTier) { + if (missionType == "MT_RESCUE" && rewardInfo.rewardTier) { return [rewardInfo.rewardTier]; } @@ -123,7 +127,7 @@ const getRotations = (rewardInfo: IRewardInfo, tierOverride?: number): number[] // Empty or absent rewardQualifications should not give rewards when: // - Completing only 1 zone of (E)SO (https://onlyg.it/OpenWF/SpaceNinjaServer/issues/1823) // - Aborting a railjack mission (https://onlyg.it/OpenWF/SpaceNinjaServer/issues/1741) - if (rotationCount == 0 && missionIndex != 30 && missionIndex != 32) { + if (rotationCount == 0 && missionType != "MT_ENDLESS_EXTERMINATION" && missionType != "MT_RAILJACK") { return [0]; } @@ -1095,8 +1099,8 @@ const isEligibleForCreditReward = (rewardInfo: IRewardInfo, missions: IMission, } // The rest here might not be needed anymore, but just to be sure we don't give undue credits... return ( - node.missionIndex != 23 && // junction - node.missionIndex != 28 && // open world + node.missionType != "MT_JUNCTION" && + node.missionType != "MT_LANDSCAPE" && missions.Tag != "SolNode761" && // the index missions.Tag != "SolNode762" && // the index missions.Tag != "SolNode763" && // the index @@ -1792,14 +1796,14 @@ function getRandomMissionDrops( let rewardManifests: string[]; if (RewardInfo.periodicMissionTag == "EliteAlert" || RewardInfo.periodicMissionTag == "EliteAlertB") { rewardManifests = ["/Lotus/Types/Game/MissionDecks/EliteAlertMissionRewards/EliteAlertMissionRewards"]; - } else if (RewardInfo.invasionId && region.missionIndex == 0) { + } else if (RewardInfo.invasionId && region.missionType == "MT_ASSASSINATION") { // Invasion assassination has Phorid has the boss who should drop Nyx parts // TODO: Check that the invasion faction is indeed FC_INFESTATION once the Invasions in worldState are more dynamic rewardManifests = ["/Lotus/Types/Game/MissionDecks/BossMissionRewards/NyxRewards"]; } else if (RewardInfo.sortieId) { // Sortie mission types differ from the underlying node and hence also don't give rewards from the underlying nodes. // Assassinations in non-lite sorties are an exception to this. - if (region.missionIndex == 0) { + if (region.missionType == "MT_ASSASSINATION") { const arr = RewardInfo.sortieId.split("_"); let giveNodeReward = false; if (arr[1] != "Lite") { @@ -2165,7 +2169,7 @@ function getRandomMissionDrops( const deck = ExportRewards["/Lotus/Types/Game/MissionDecks/NightmareModeRewards"]; let rotation = 0; - if (region.missionIndex === 3 && RewardInfo.rewardTier) { + if (region.missionType == "MT_RESCUE" && RewardInfo.rewardTier) { rotation = RewardInfo.rewardTier; } else if ([6, 7, 8, 10, 11].includes(region.systemIndex)) { rotation = 2; diff --git a/src/services/purchaseService.ts b/src/services/purchaseService.ts index 60caea76..a1aa6ee2 100644 --- a/src/services/purchaseService.ts +++ b/src/services/purchaseService.ts @@ -20,7 +20,6 @@ import type { import { PurchaseSource } from "../types/purchaseTypes.ts"; import { logger } from "../utils/logger.ts"; import { getWorldState } from "./worldStateService.ts"; -import type { TRarity } from "warframe-public-export-plus"; import { ExportBoosterPacks, ExportBoosters, @@ -419,7 +418,7 @@ export const handleBundleAcqusition = async ( component.typeName, inventory, component.purchaseQuantity * quantity, - component.durability, + component.durabilityDays, true ) ).InventoryChanges @@ -432,7 +431,7 @@ export const handleStoreItemAcquisition = async ( storeItemName: string, inventory: TInventoryDatabaseDocument, quantity: number = 1, - durability: TRarity = "COMMON", + durabilityDays: number = 3, ignorePurchaseQuantity: boolean = false, premiumPurchase: boolean = true, seed?: bigint @@ -482,7 +481,7 @@ export const handleStoreItemAcquisition = async ( ); break; case "Boosters": - purchaseResponse = handleBoostersPurchase(storeItemName, inventory, durability); + purchaseResponse = handleBoostersPurchase(storeItemName, inventory, durabilityDays); break; } } @@ -672,7 +671,7 @@ const handleTypesPurchase = async ( const handleBoostersPurchase = ( boosterStoreName: string, inventory: TInventoryDatabaseDocument, - durability: TRarity + durabilityDays: number ): { InventoryChanges: IInventoryChanges } => { if (!(boosterStoreName in ExportBoosters)) { logger.error(`unknown booster type: ${boosterStoreName}`); @@ -680,7 +679,7 @@ const handleBoostersPurchase = ( } const ItemType = ExportBoosters[boosterStoreName].typeName; - const ExpiryDate = ExportMisc.boosterDurations[durability]; + const ExpiryDate = durabilityDays * 86400; addBooster(ItemType, ExpiryDate, inventory); diff --git a/src/services/worldStateService.ts b/src/services/worldStateService.ts index b028cc55..e970496d 100644 --- a/src/services/worldStateService.ts +++ b/src/services/worldStateService.ts @@ -13,8 +13,8 @@ import { buildConfig } from "./buildConfigService.ts"; import { unixTimesInMs } from "../constants/timeConstants.ts"; import { config } from "./configService.ts"; import { getRandomElement, getRandomInt, sequentiallyUniqueRandomElement, SRng } from "./rngService.ts"; -import type { IMissionReward, IRegion } from "warframe-public-export-plus"; -import { eMissionType, ExportRegions, ExportSyndicates } from "warframe-public-export-plus"; +import type { IMissionReward, IRegion, TFaction } from "warframe-public-export-plus"; +import { ExportRegions, ExportSyndicates } from "warframe-public-export-plus"; import type { ICalendarDay, ICalendarEvent, @@ -87,11 +87,11 @@ const sortieFactionToSystemIndexes: Record = { FC_OROKIN: [14] }; -const sortieFactionToFactionIndexes: Record = { - FC_GRINEER: [0], - FC_CORPUS: [1], - FC_INFESTATION: [0, 1, 2], - FC_OROKIN: [3] +const sortieFactionToFactions: Record = { + FC_GRINEER: ["FC_GRINEER"], + FC_CORPUS: ["FC_CORPUS"], + FC_INFESTATION: ["FC_GRINEER", "FC_CORPUS", "FC_INFESTATION"], + FC_OROKIN: ["FC_OROKIN"] }; const sortieBossNode: Record, string> = { @@ -271,7 +271,7 @@ export const getSortie = (day: number): ISortie => { for (const [key, value] of Object.entries(ExportRegions)) { if ( sortieFactionToSystemIndexes[sortieBossToFaction[boss]].includes(value.systemIndex) && - sortieFactionToFactionIndexes[sortieBossToFaction[boss]].includes(value.factionIndex!) && + sortieFactionToFactions[sortieBossToFaction[boss]].includes(value.faction!) && key in sortieTilesets && (key != "SolNode228" || sortieBossToFaction[boss] == "FC_GRINEER") // PoE does not work for non-infested enemies ) { @@ -339,10 +339,10 @@ export const getSortie = (day: number): ISortie => { modifiers.push("SORTIE_MODIFIER_HAZARD_RADIATION"); } - if (ExportRegions[node].factionIndex == 0) { + if (ExportRegions[node].faction == "FC_GRINEER") { // Grineer modifiers.push("SORTIE_MODIFIER_ARMOR"); - } else if (ExportRegions[node].factionIndex == 1) { + } else if (ExportRegions[node].faction == "FC_CORPUS") { // Corpus modifiers.push("SORTIE_MODIFIER_SHIELDS"); } @@ -1306,7 +1306,7 @@ const createInvasion = (day: number, idx: number): IInvasion => { ), Goal: 30000, // Value seems to range from 30000 to 98000 in intervals of 1000. Higher values are increasingly rare. I don't think this is relevant for the frontend besides dividing count by it. LocTag: isInfestationOutbreak - ? ExportRegions[node].missionIndex == 0 + ? ExportRegions[node].missionType == "MT_ASSASSINATION" ? "/Lotus/Language/Menu/InfestedInvasionBoss" : "/Lotus/Language/Menu/InfestedInvasionGeneric" : attacker == "FC_CORPUS" @@ -3179,7 +3179,7 @@ export const populateFissures = async (worldState: IWorldState): Promise = Activation: { $date: { $numberLong: "1000000000000" } }, Expiry: { $date: { $numberLong: "2000000000000" } }, Node: node, - MissionType: eMissionType[meta.missionIndex].tag, + MissionType: meta.missionType, Modifier: tier, Hard: config.worldState.allTheFissures == "hard" }); @@ -3199,7 +3199,7 @@ export const populateFissures = async (worldState: IWorldState): Promise = : toMongoDate(fissure.Activation), Expiry: toMongoDate(fissure.Expiry), Node: fissure.Node, - MissionType: eMissionType[meta.missionIndex].tag, + MissionType: meta.missionType, Modifier: fissure.Modifier, Hard: fissure.Hard }); @@ -3246,13 +3246,12 @@ export const getLiteSortie = (week: number): ILiteSortie => { for (const [key, value] of Object.entries(ExportRegions)) { if ( value.systemIndex === systemIndex && - value.factionIndex !== undefined && - value.factionIndex < 2 && + (value.faction == "FC_GRINEER" || value.faction == "FC_CORPUS") && !isArchwingMission(value) && - value.missionIndex != 0 && // Exclude MT_ASSASSINATION - value.missionIndex != 23 && // Exclude junctions - value.missionIndex != 28 && // Exclude open worlds - value.missionIndex != 32 // Exclude railjack + value.missionType != "MT_ASSASSINATION" && + value.missionType != "MT_JUNCTION" && + value.missionType != "MT_LANDSCAPE" && + value.missionType != "MT_RAILJACK" ) { nodes.push(key); } @@ -3309,7 +3308,7 @@ export const isArchwingMission = (node: IRegion): boolean => { return true; } // SettlementNode10 - if (node.missionIndex == 25) { + if (node.missionType == "MT_RACE") { return true; } return false;