From e545ecf7675e10c379dadbe2ab7a022f9879a699 Mon Sep 17 00:00:00 2001 From: Sainan <63328889+Sainan@users.noreply.github.com> Date: Wed, 7 May 2025 20:14:05 -0700 Subject: [PATCH] fix: restrict sortie mission types based on what the tileset supports (#2003) Closes #2000 Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/2003 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com> --- src/services/worldStateService.ts | 98 ++++++------------- .../worldState/sortieTilesetMissions.json | 45 +++++++++ 2 files changed, 77 insertions(+), 66 deletions(-) create mode 100644 static/fixed_responses/worldState/sortieTilesetMissions.json diff --git a/src/services/worldStateService.ts b/src/services/worldStateService.ts index a9535c9f8..09b1c4837 100644 --- a/src/services/worldStateService.ts +++ b/src/services/worldStateService.ts @@ -1,11 +1,12 @@ import staticWorldState from "@/static/fixed_responses/worldState/worldState.json"; import sortieTilesets from "@/static/fixed_responses/worldState/sortieTilesets.json"; +import sortieTilesetMissions from "@/static/fixed_responses/worldState/sortieTilesetMissions.json"; import syndicateMissions from "@/static/fixed_responses/worldState/syndicateMissions.json"; import { buildConfig } from "@/src/services/buildConfigService"; import { unixTimesInMs } from "@/src/constants/timeConstants"; import { config } from "@/src/services/configService"; import { CRng } from "@/src/services/rngService"; -import { eMissionType, ExportNightwave, ExportRegions, IRegion } from "warframe-public-export-plus"; +import { ExportNightwave, ExportRegions, IRegion } from "warframe-public-export-plus"; import { ICalendarDay, ICalendarEvent, @@ -72,12 +73,6 @@ const sortieFactionToFactionIndexes: Record = { FC_OROKIN: [3] }; -const sortieFactionToSpecialMissionTileset: Record = { - FC_GRINEER: "GrineerGalleonTileset", - FC_CORPUS: "CorpusShipTileset", - FC_INFESTATION: "CorpusShipTileset" -}; - const sortieBossNode: Record, string> = { SORTIE_BOSS_ALAD: "SolNode53", SORTIE_BOSS_AMBULAS: "SolNode51", @@ -217,6 +212,27 @@ const pushSyndicateMissions = ( }); }; +type TSortieTileset = keyof typeof sortieTilesetMissions; + +const pushTilesetModifiers = (modifiers: string[], tileset: TSortieTileset): void => { + switch (tileset) { + case "GrineerForestTileset": + modifiers.push("SORTIE_MODIFIER_HAZARD_FOG"); + break; + case "CorpusShipTileset": + case "GrineerGalleonTileset": + case "InfestedCorpusShipTileset": + modifiers.push("SORTIE_MODIFIER_HAZARD_MAGNETIC"); + modifiers.push("SORTIE_MODIFIER_HAZARD_FIRE"); + modifiers.push("SORTIE_MODIFIER_HAZARD_ICE"); + break; + case "CorpusIcePlanetTileset": + case "CorpusIcePlanetTilesetCaves": + modifiers.push("SORTIE_MODIFIER_HAZARD_COLD"); + break; + } +}; + export const getSortie = (day: number): ISortie => { const seed = new CRng(day).randomInt(0, 0xffff); const rng = new CRng(seed); @@ -224,54 +240,22 @@ export const getSortie = (day: number): ISortie => { const boss = rng.randomElement(sortieBosses)!; const nodes: string[] = []; - const availableMissionIndexes: number[] = []; for (const [key, value] of Object.entries(ExportRegions)) { if ( sortieFactionToSystemIndexes[sortieBossToFaction[boss]].includes(value.systemIndex) && sortieFactionToFactionIndexes[sortieBossToFaction[boss]].includes(value.factionIndex!) && key in sortieTilesets ) { - if ( - value.missionIndex != 0 && // Assassination will be decided independently - value.missionIndex != 5 && // Sorties do not have capture missions - !availableMissionIndexes.includes(value.missionIndex) - ) { - availableMissionIndexes.push(value.missionIndex); - } nodes.push(key); } } - const specialMissionTypes = [1, 3, 5, 9]; - if (!(sortieBossToFaction[boss] in sortieFactionToSpecialMissionTileset)) { - for (const missionType of specialMissionTypes) { - const i = availableMissionIndexes.indexOf(missionType); - if (i != -1) { - availableMissionIndexes.splice(i, 1); - } - } - } - const selectedNodes: ISortieMission[] = []; const missionTypes = new Set(); for (let i = 0; i < 3; i++) { - let randomIndex; - let node; - let missionIndex; - do { - randomIndex = rng.randomInt(0, nodes.length - 1); - node = nodes[randomIndex]; - - missionIndex = ExportRegions[node].missionIndex; - if (missionIndex != 28) { - missionIndex = rng.randomElement(availableMissionIndexes)!; - } - } while ( - specialMissionTypes.indexOf(missionIndex) != -1 && - sortieTilesets[node as keyof typeof sortieTilesets] != - sortieFactionToSpecialMissionTileset[sortieBossToFaction[boss]] - ); + const randomIndex = rng.randomInt(0, nodes.length - 1); + const node = nodes[randomIndex]; const modifiers = [ "SORTIE_MODIFIER_LOW_ENERGY", @@ -294,28 +278,10 @@ export const getSortie = (day: number): ISortie => { "SORTIE_MODIFIER_RIFLE_ONLY", "SORTIE_MODIFIER_BOW_ONLY" ]; - const pushTilesetModifiers = (tileset: string): void => { - switch (tileset) { - case "GrineerForestTileset": - modifiers.push("SORTIE_MODIFIER_HAZARD_FOG"); - break; - case "CorpusShipTileset": - case "GrineerGalleonTileset": - case "InfestedCorpusShipTileset": - modifiers.push("SORTIE_MODIFIER_HAZARD_MAGNETIC"); - modifiers.push("SORTIE_MODIFIER_HAZARD_FIRE"); - modifiers.push("SORTIE_MODIFIER_HAZARD_ICE"); - break; - case "CorpusIcePlanetTileset": - case "CorpusIcePlanetTilesetCaves": - modifiers.push("SORTIE_MODIFIER_HAZARD_COLD"); - break; - } - }; if (i == 2 && boss != "SORTIE_BOSS_CORRUPTED_VOR" && rng.randomInt(0, 2) == 2) { - const tileset = sortieTilesets[sortieBossNode[boss] as keyof typeof sortieTilesets]; - pushTilesetModifiers(tileset); + const tileset = sortieTilesets[sortieBossNode[boss] as keyof typeof sortieTilesets] as TSortieTileset; + pushTilesetModifiers(modifiers, tileset); const modifierType = rng.randomElement(modifiers)!; @@ -328,9 +294,12 @@ export const getSortie = (day: number): ISortie => { continue; } - const missionType = eMissionType[missionIndex].tag; + const tileset = sortieTilesets[node as keyof typeof sortieTilesets] as TSortieTileset; + pushTilesetModifiers(modifiers, tileset); - if (missionTypes.has(missionType)) { + const missionType = rng.randomElement(sortieTilesetMissions[tileset])!; + + if (missionTypes.has(missionType) || missionType == "MT_ASSASSINATION") { i--; continue; } @@ -349,9 +318,6 @@ export const getSortie = (day: number): ISortie => { modifiers.push("SORTIE_MODIFIER_SHIELDS"); } - const tileset = sortieTilesets[node as keyof typeof sortieTilesets]; - pushTilesetModifiers(tileset); - const modifierType = rng.randomElement(modifiers)!; selectedNodes.push({ diff --git a/static/fixed_responses/worldState/sortieTilesetMissions.json b/static/fixed_responses/worldState/sortieTilesetMissions.json new file mode 100644 index 000000000..36d5e194e --- /dev/null +++ b/static/fixed_responses/worldState/sortieTilesetMissions.json @@ -0,0 +1,45 @@ +{ + "CorpusGasCityTileset": ["MT_ARTIFACT", "MT_ASSASSINATION", "MT_DEFENSE", "MT_EXTERMINATION", "MT_INTEL", "MT_MOBILE_DEFENSE", "MT_RESCUE", "MT_SABOTAGE", "MT_SURVIVAL", "MT_TERRITORY"], + "CorpusIcePlanetTileset": ["MT_ASSASSINATION", "MT_DEFENSE", "MT_EXCAVATE", "MT_INTEL", "MT_MOBILE_DEFENSE", "MT_RESCUE", "MT_RETRIEVAL", "MT_TERRITORY"], + "CorpusIcePlanetTilesetCaves": ["MT_EXTERMINATION", "MT_INTEL"], + "CorpusOutpostTileset": [ + "MT_ARTIFACT", + "MT_ASSASSINATION", + "MT_DEFENSE", + "MT_EXCAVATE", + "MT_EXTERMINATION", + "MT_INTEL", + "MT_MOBILE_DEFENSE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_SURVIVAL", + "MT_TERRITORY" + ], + "CorpusShipTileset": ["MT_ARTIFACT", "MT_ASSASSINATION", "MT_DEFENSE", "MT_EXTERMINATION", "MT_INTEL", "MT_MOBILE_DEFENSE", "MT_RESCUE", "MT_SABOTAGE", "MT_SURVIVAL", "MT_TERRITORY"], + "EidolonTileset": ["MT_LANDSCAPE"], + "GrineerAsteroidTileset": ["MT_ASSASSINATION", "MT_DEFENSE", "MT_EVACUATION", "MT_EXTERMINATION", "MT_INTEL", "MT_MOBILE_DEFENSE", "MT_RESCUE", "MT_SURVIVAL", "MT_TERRITORY"], + "GrineerForestTileset": ["MT_ASSASSINATION", "MT_EXTERMINATION", "MT_INTEL", "MT_MOBILE_DEFENSE", "MT_TERRITORY"], + "GrineerFortressTileset": ["MT_ARTIFACT", "MT_ASSAULT", "MT_INTEL", "MT_MOBILE_DEFENSE", "MT_RESCUE", "MT_SURVIVAL"], + "GrineerGalleonTileset": [ + "MT_ARTIFACT", + "MT_ASSASSINATION", + "MT_DEFENSE", + "MT_EVACUATION", + "MT_EXTERMINATION", + "MT_INTEL", + "MT_MOBILE_DEFENSE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_SURVIVAL", + "MT_TERRITORY" + ], + "GrineerOceanTileset": ["MT_DEFENSE", "MT_EXTERMINATION", "MT_INTEL", "MT_MOBILE_DEFENSE", "MT_RESCUE", "MT_SABOTAGE", "MT_SURVIVAL", "MT_TERRITORY"], + "GrineerOceanTilesetAnywhere": ["MT_ASSASSINATION"], + "GrineerSettlementTileset": ["MT_ASSASSINATION", "MT_DEFENSE", "MT_EXTERMINATION", "MT_INTEL", "MT_MOBILE_DEFENSE", "MT_RESCUE", "MT_SABOTAGE", "MT_TERRITORY"], + "GrineerShipyardsTileset": ["MT_DEFENSE", "MT_EXTERMINATION", "MT_INTEL", "MT_MOBILE_DEFENSE", "MT_RESCUE", "MT_RETRIEVAL", "MT_TERRITORY"], + "InfestedCorpusShipTileset": ["MT_ASSASSINATION", "MT_HIVE", "MT_MOBILE_DEFENSE", "MT_RESCUE"], + "OrokinDerelictTileset": ["MT_ARTIFACT", "MT_ASSASSINATION", "MT_DEFENSE", "MT_EXTERMINATION", "MT_MOBILE_DEFENSE", "MT_SABOTAGE", "MT_SURVIVAL"], + "OrokinMoonTilesetCorpus": ["MT_ARTIFACT", "MT_DEFENSE", "MT_EXTERMINATION", "MT_MOBILE_DEFENSE", "MT_RESCUE", "MT_SURVIVAL"], + "OrokinMoonTilesetGrineer": ["MT_DEFENSE", "MT_EXTERMINATION", "MT_MOBILE_DEFENSE", "MT_RESCUE", "MT_SURVIVAL"], + "OrokinVoidTileset": ["MT_DEFENSE", "MT_EXTERMINATION", "MT_MOBILE_DEFENSE", "MT_SABOTAGE", "MT_SURVIVAL", "MT_TERRITORY"] +}