diff --git a/src/app.ts b/src/app.ts index 514d4336..26a9ac87 100644 --- a/src/app.ts +++ b/src/app.ts @@ -15,9 +15,11 @@ import { statsRouter } from "@/src/routes/stats"; import { webuiRouter } from "@/src/routes/webui"; import { connectDatabase } from "@/src/services/mongoService"; import { registerLogFileCreationListener } from "@/src/utils/logger"; +import { worldStateRunner } from "@/src/services/worldStateService"; void registerLogFileCreationListener(); void connectDatabase(); +void worldStateRunner(); const app = express(); diff --git a/src/constants/worldStateConstants.ts b/src/constants/worldStateConstants.ts new file mode 100644 index 00000000..0fe0adcf --- /dev/null +++ b/src/constants/worldStateConstants.ts @@ -0,0 +1,3659 @@ +export const SortiesMissionTypes = [ + "MT_ARTIFACT", + "MT_ASSAULT", + "MT_ASSASSINATION", + "MT_DEFENSE", + "MT_DISRUPTION", + "MT_EVACUATION", + "MT_EXCAVATE", + "MT_EXTERMINATION", + "MT_HIVE", + "MT_INTEL", + "MT_LANDSCAPE", + "MT_MOBILE_DEFENSE", + "MT_RESCUE", + "MT_RETRIEVAL", + "MT_SABOTAGE", + "MT_SECTOR", + "MT_SURVIVAL", + "MT_TERRITORY" +]; + +export const voidTiers = ["VoidT1", "VoidT2", "VoidT3", "VoidT4", "VoidT5", "VoidT6"]; + +export const modifierTypes = [ + "SORTIE_MODIFIER_LOW_ENERGY", + "SORTIE_MODIFIER_IMPACT", + "SORTIE_MODIFIER_SLASH", + "SORTIE_MODIFIER_PUNCTURE", + "SORTIE_MODIFIER_EXIMUS", + "SORTIE_MODIFIER_MAGNETIC", + "SORTIE_MODIFIER_CORROSIVE", + "SORTIE_MODIFIER_VIRAL", + "SORTIE_MODIFIER_ELECTRICITY", + "SORTIE_MODIFIER_RADIATION", + "SORTIE_MODIFIER_GAS", + "SORTIE_MODIFIER_FIRE", + "SORTIE_MODIFIER_EXPLOSION", + "SORTIE_MODIFIER_FREEZE", + "SORTIE_MODIFIER_TOXIN", + "SORTIE_MODIFIER_POISON", + "SORTIE_MODIFIER_HAZARD_RADIATION", + "SORTIE_MODIFIER_HAZARD_MAGNETIC", + "SORTIE_MODIFIER_HAZARD_FOG", + "SORTIE_MODIFIER_HAZARD_FIRE", + "SORTIE_MODIFIER_HAZARD_ICE", + "SORTIE_MODIFIER_HAZARD_COLD", + "SORTIE_MODIFIER_ARMOR", + "SORTIE_MODIFIER_SHIELDS", + "SORTIE_MODIFIER_SECONDARY_ONLY", + "SORTIE_MODIFIER_SHOTGUN_ONLY", + "SORTIE_MODIFIER_SNIPER_ONLY", + "SORTIE_MODIFIER_RIFLE_ONLY", + "SORTIE_MODIFIER_MELEE_ONLY", + "SORTIE_MODIFIER_BOW_ONLY" +]; + +export const liteSortiesBoss = ["SORTIE_BOSS_AMAR", "SORTIE_BOSS_NIRA", "SORTIE_BOSS_PAAZUL"]; + +/* data from wfcd worldstate-data sucks, + missing bosses: + SORTIE_BOSS_CORRUPTED_VOR + also missing tilesets and void missions + */ +export const endStates = [ + { + bossName: "SORTIE_BOSS_VOR", + regions: [ + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_DEFENSE", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_EXTERMINATION", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_TERRITORY", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_EXCAVATE", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_RETRIEVAL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_RETRIEVAL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_EXTERMINATION", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_EXTERMINATION", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_EXTERMINATION", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_ASSASSINATION" + ] + } + ] + }, + { + bossName: "SORTIE_BOSS_HEK", + regions: [ + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_DEFENSE", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_EXTERMINATION", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_TERRITORY", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_EXCAVATE", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_RETRIEVAL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_RETRIEVAL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_EXTERMINATION", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_EXTERMINATION", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_ASSASSINATION" + ] + } + ] + }, + { + bossName: "SORTIE_BOSS_RUK", + regions: [ + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_DEFENSE", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_EXTERMINATION", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_TERRITORY", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_EXCAVATE", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_DEFENSE", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_RETRIEVAL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_EXTERMINATION", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_EXTERMINATION", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_ASSASSINATION" + ] + } + ] + }, + { + bossName: "SORTIE_BOSS_KELA", + regions: [ + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_SURVIVAL", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_DEFENSE", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_EXTERMINATION", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_TERRITORY", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_EXCAVATE", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_RETRIEVAL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_RETRIEVAL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_EXTERMINATION", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_EXTERMINATION", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_ASSASSINATION" + ] + } + ] + }, + { + bossName: "SORTIE_BOSS_KRIL", + regions: [ + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_DEFENSE", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_EXTERMINATION", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_TERRITORY", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_EXCAVATE", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_RETRIEVAL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_RETRIEVAL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_EXTERMINATION", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_EXTERMINATION", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_ASSASSINATION" + ] + } + ] + }, + { + bossName: "SORTIE_BOSS_TYL", + regions: [ + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_DEFENSE", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_EXTERMINATION", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_TERRITORY", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_EXCAVATE", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_RETRIEVAL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_RETRIEVAL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_EXTERMINATION", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_EXTERMINATION", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_EXTERMINATION", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_ASSASSINATION" + ] + } + ] + }, + { + bossName: "SORTIE_BOSS_JACKAL", + regions: [ + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_DEFENSE", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_EXTERMINATION", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_TERRITORY", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_EXCAVATE", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_RETRIEVAL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_RETRIEVAL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_EXTERMINATION", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_EXTERMINATION", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_ASSASSINATION" + ] + } + ] + }, + { + bossName: "SORTIE_BOSS_ALAD", + regions: [ + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_DEFENSE", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_EXTERMINATION", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_TERRITORY", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_EXCAVATE", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_RETRIEVAL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_RETRIEVAL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_EXTERMINATION", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_EXTERMINATION", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_EXTERMINATION", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_ASSASSINATION" + ] + } + ] + }, + { + bossName: "SORTIE_BOSS_AMBULAS", + regions: [ + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_DEFENSE", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_EXTERMINATION", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXTERMINATION", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_TERRITORY", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_EXCAVATE", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_RETRIEVAL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_RETRIEVAL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_EXTERMINATION", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_EXTERMINATION", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_EXTERMINATION", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_ASSASSINATION" + ] + } + ] + }, + { + bossName: "SORTIE_BOSS_HYENA", + regions: [ + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_RESCUE", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_EXTERMINATION", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_SABOTAGE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_INTEL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_RETRIEVAL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_RETRIEVAL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_EXTERMINATION", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_EXTERMINATION", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_EXTERMINATION", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_ASSASSINATION" + ] + } + ] + }, + { + bossName: "SORTIE_BOSS_NEF", + regions: [ + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_EXTERMINATION", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_TERRITORY", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_EXCAVATE", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_RETRIEVAL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_RETRIEVAL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_EXTERMINATION", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_EXTERMINATION", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_EXTERMINATION", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_ASSASSINATION" + ] + } + ] + }, + { + bossName: "SORTIE_BOSS_RAPTOR", + regions: [ + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_DEFENSE", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_EXTERMINATION", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_TERRITORY", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_RETRIEVAL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_RETRIEVAL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_EXTERMINATION", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_EXTERMINATION", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_EXTERMINATION", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_ASSASSINATION" + ] + } + ] + }, + { + bossName: "SORTIE_BOSS_PHORID", + regions: [ + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_DEFENSE", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_EXTERMINATION", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_TERRITORY", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_EXCAVATE", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_RETRIEVAL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "Hive", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_RETRIEVAL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_EXTERMINATION", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_EXTERMINATION", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_EXTERMINATION", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_ASSASSINATION" + ] + } + ] + }, + { + bossName: "SORTIE_BOSS_LEPHANTIS", + regions: [ + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_DEFENSE", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_EXTERMINATION", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_INTEL", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_RETRIEVAL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_INTEL", + "MT_MOBILE_DEFENSE", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "Hive", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_RETRIEVAL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_EXTERMINATION", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_EXTERMINATION", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_EXTERMINATION", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_ASSASSINATION" + ] + } + ] + }, + { + bossName: "SORTIE_BOSS_INFALAD", + regions: [ + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_DEFENSE", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_EXTERMINATION", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_TERRITORY", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_EXCAVATE", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_RETRIEVAL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_SURVIVAL", + "Hive", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_SURVIVAL", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_INTEL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_RETRIEVAL", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_EXTERMINATION", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_EXTERMINATION", + "MT_EXCAVATE", + "MT_RESCUE", + "MT_SABOTAGE", + "MT_INTEL", + "MT_DEFENSE", + "MT_MOBILE_DEFENSE", + "MT_TERRITORY", + "MT_EXTERMINATION", + "MT_ASSASSINATION" + ] + }, + { + missions: [ + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_EXTERMINATION", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_DEFENSE", + "MT_ASSASSINATION" + ] + } + ] + } +]; + +export const validFisureMissionIndex = [ + 1, // Exterminate + 2, // Survival + 3, // Rescue + 4, // Sabotage + 5, // Capture + 7, // Spy + 8, // Defense + 9, // Mobile Defense + 13, // Interception + 15, // Hive + 17, // Excavation + 26, // Assault + 33, // Disruption + 34, // Void Flood + 35, // Void Cascade + 38 // Alchemy +]; + +export const omniaNodes = ["SolNode309", "SolNode310", "SolNode230", "SolNode718", "SolNode232", "SolNode717"]; + +export const voidFisuresMissionTypes: { [key: number]: string } = { + 1: "MT_EXTERMINATION", + 2: "MT_SURVIVAL", + 3: "MT_RESCUE", + 4: "MT_SABOTAGE", + 5: "MT_CAPTURE", + 7: "MT_INTEL", + 8: "MT_DEFENSE", + 9: "MT_MOBILE_DEFENSE", + 13: "MT_TERRITORY", + 15: "MT_HIVE", + 17: "MT_EXCAVATE", + 26: "MT_ASSAULT", + 33: "MT_ARTIFACT", + 34: "MT_VOID_FLOOD", // Maybe + 35: "MT_VOID_CASCADE", + 38: "MT_ALCHEMY" // Maybe +}; + +export const ZarimanNormalJobs = [ + "/Lotus/Types/Gameplay/InfestedMicroplanet/Jobs/DeimosAreaDefenseBounty", + "/Lotus/Types/Gameplay/InfestedMicroplanet/Jobs/DeimosAssassinateBounty", + "/Lotus/Types/Gameplay/InfestedMicroplanet/Jobs/DeimosCrpSurvivorBounty", + "/Lotus/Types/Gameplay/InfestedMicroplanet/Jobs/DeimosEndessExcavateBounty", + "/Lotus/Types/Gameplay/InfestedMicroplanet/Jobs/DeimosEndesspurifyBounty", + "/Lotus/Types/Gameplay/InfestedMicroplanet/Jobs/DeimosExcavateBounty", + "/Lotus/Types/Gameplay/InfestedMicroplanet/Jobs/DeimosGrnSurvivorBounty", + "/Lotus/Types/Gameplay/InfestedMicroplanet/Jobs/DeimosKeypiecesBounty", + "/Lotus/Types/Gameplay/InfestedMicroplanet/Jobs/DeimosPurifyBounty" +]; + +export const CertusNarmerJobs = [ + "/Lotus/Types/Gameplay/Eidolon/Jobs/Narmer/AssassinateBountyAss", + "/Lotus/Types/Gameplay/Eidolon/Jobs/Narmer/AttritionBountyExt", + "/Lotus/Types/Gameplay/Eidolon/Jobs/Narmer/AttritionBountyLib" +]; +/* +export const CertusGhoulalertJobs = [ + "/Lotus/Types/Gameplay/Eidolon/Jobs/Events/GhoulAlertBountyAss", + "/Lotus/Types/Gameplay/Eidolon/Jobs/Events/GhoulAlertBountyExt", + "/Lotus/Types/Gameplay/Eidolon/Jobs/Events/GhoulAlertBountyBunt", + "/Lotus/Types/Gameplay/Eidolon/Jobs/Events/GhoulAlertBountyRes" +] +export const CertusPlagueStarJob = "/Lotus/Types/Gameplay/Eidolon/Jobs/Events/InfestedPlainsBounty" +*/ +export const CertusNormalJobs = [ + "/Lotus/Types/Gameplay/Eidolon/Jobs/AssassinateBountyAss", + "/Lotus/Types/Gameplay/Eidolon/Jobs/AssassinateBountyCap", + "/Lotus/Types/Gameplay/Eidolon/Jobs/AttritionBountyCap", + "/Lotus/Types/Gameplay/Eidolon/Jobs/AttritionBountyExt", + "/Lotus/Types/Gameplay/Eidolon/Jobs/AttritionBountyLib", + "/Lotus/Types/Gameplay/Eidolon/Jobs/AttritionBountySab", + "/Lotus/Types/Gameplay/Eidolon/Jobs/CaptureBountyCapOne", + "/Lotus/Types/Gameplay/Eidolon/Jobs/CaptureBountyCapTwo", + "/Lotus/Types/Gameplay/Eidolon/Jobs/ReclamationBountyCache", + "/Lotus/Types/Gameplay/Eidolon/Jobs/ReclamationBountyCap", + "/Lotus/Types/Gameplay/Eidolon/Jobs/ReclamationBountyTheft", + "/Lotus/Types/Gameplay/Eidolon/Jobs/RescueBountyResc", + "/Lotus/Types/Gameplay/Eidolon/Jobs/SabotageBountySab" +]; + +export const factionSyndicates = [ + "ArbitersSyndicate", + "CephalonSudaSyndicate", + "NewLokaSyndicate", + "PerrinSyndicate", + "RedVeilSyndicate", + "SteelMeridianSyndicate" +]; +export const neutralJobsSyndicates = ["EntratiSyndicate", "CetusSyndicate", "SolarisSyndicate"]; +export const neutralSyndicates = ["ZarimanSyndicate", "EntratiLabSyndicate"]; +export const restSyndicates = [ + "NecraloidSyndicate", + "KahlSyndicate", + "EventSyndicate", + "QuillsSyndicate", + "VoxSyndicate", + "VentKidsSyndicate", + "RadioLegionSyndicate", + "RadioLegion2Syndicate", + "RadioLegion3Syndicate", + "RadioLegionIntermissionSyndicate", + "RadioLegionIntermission2Syndicate", + "RadioLegionIntermission3Syndicate", + "RadioLegionIntermission4Syndicate", + "RadioLegionIntermission5Syndicate", + "RadioLegionIntermission6Syndicate", + "RadioLegionIntermission8Syndicate", + "RadioLegionIntermission7Syndicate", + "RadioLegionIntermission9Syndicate", + "RadioLegionIntermission10Syndicate" +]; + +export const FortunaNarmerJobs = [ + "/Lotus/Types/Gameplay/Venus/Jobs/Narmer/NarmerVenusCullJobAssassinate", + "/Lotus/Types/Gameplay/Venus/Jobs/Narmer/NarmerVenusCullJobExterminate", + "/Lotus/Types/Gameplay/Venus/Jobs/Narmer/NarmerVenusTheftJobExcavation" +]; +export const FortunaNormalJobs = [ + "/Lotus/Types/Gameplay/Venus/Jobs/VenusArtifactJobAmbush", + "/Lotus/Types/Gameplay/Venus/Jobs/VenusArtifactJobExcavation", + "/Lotus/Types/Gameplay/Venus/Jobs/VenusArtifactJobRecovery", + "/Lotus/Types/Gameplay/Venus/Jobs/VenusChaosJobAssassinate", + "/Lotus/Types/Gameplay/Venus/Jobs/VenusChaosJobExcavation", + "/Lotus/Types/Gameplay/Venus/Jobs/VenusCullJobAssassinate", + "/Lotus/Types/Gameplay/Venus/Jobs/VenusCullJobExterminate", + "/Lotus/Types/Gameplay/Venus/Jobs/VenusCullJobResource", + "/Lotus/Types/Gameplay/Venus/Jobs/VenusHelpingJobcaches", + "/Lotus/Types/Gameplay/Venus/Jobs/VenusHelpingJobResource", + "/Lotus/Types/Gameplay/Venus/Jobs/VenusHelpingJobSpy", + "/Lotus/Types/Gameplay/Venus/Jobs/VenusIntelJobRecovery", + "/Lotus/Types/Gameplay/Venus/Jobs/VenusIntelJobResource", + "/Lotus/Types/Gameplay/Venus/Jobs/VenusIntelJobSpy", + "/Lotus/Types/Gameplay/Venus/Jobs/VenusPreservationJobDefense", + "/Lotus/Types/Gameplay/Venus/Jobs/VenusPreservationJobRecovery", + "/Lotus/Types/Gameplay/Venus/Jobs/VenusPreservationJobResource", + "/Lotus/Types/Gameplay/Venus/Jobs/VenusSpyJobSpy", + "/Lotus/Types/Gameplay/Venus/Jobs/VenusTheftJobAmbush", + "/Lotus/Types/Gameplay/Venus/Jobs/VenusTheftJobExcavation", + "/Lotus/Types/Gameplay/Venus/Jobs/VenusTheftJobResource", + "/Lotus/Types/Gameplay/Venus/Jobs/VenusWetworkJobAssassinate", + "/Lotus/Types/Gameplay/Venus/Jobs/VenusWetworkJobSpy" +]; diff --git a/src/controllers/dynamic/worldStateController.ts b/src/controllers/dynamic/worldStateController.ts index 428c9834..25463140 100644 --- a/src/controllers/dynamic/worldStateController.ts +++ b/src/controllers/dynamic/worldStateController.ts @@ -1,18 +1,17 @@ import { RequestHandler } from "express"; import worldState from "@/static/fixed_responses/worldState.json"; import buildConfig from "@/static/data/buildConfig.json"; -import { IWorldState } from "@/src/types/worldStateTypes"; import { config } from "@/src/services/configService"; import { getWorldState } from "@/src/services/worldStateService"; const worldStateController: RequestHandler = async (_req, res) => { - let ws: IWorldState = {}; + let ws: { [k: string]: any } = {}; if (config.useStaticWorldState) { ws = worldState; ws.BuildLabel = buildConfig.buildLabel; ws.Time = Math.round(Date.now() / 1000); } else { - ws = (await getWorldState()).toJSON(); + ws = await getWorldState(); ws.BuildLabel = buildConfig.buildLabel; ws.Time = Math.round(Date.now() / 1000); } diff --git a/src/helpers/general.ts b/src/helpers/general.ts index 23fb9df6..bb5cd914 100644 --- a/src/helpers/general.ts +++ b/src/helpers/general.ts @@ -74,4 +74,13 @@ export const isObject = (objectCandidate: unknown): objectCandidate is Record { + return Math.floor(Math.random() * (max - min + 1) + min); +}; + +export const getRandomKey = (keys: string[]) => { + const randomIndex = Math.floor(Math.random() * keys.length); + return keys[randomIndex]; +}; + export { isString, isNumber, parseString, parseNumber, parseDateNumber, parseBoolean, parseEmail }; diff --git a/src/helpers/worldstateHelpers.ts b/src/helpers/worldstateHelpers.ts new file mode 100644 index 00000000..7504d54b --- /dev/null +++ b/src/helpers/worldstateHelpers.ts @@ -0,0 +1,30 @@ +import { ExportRegions } from "warframe-public-export-plus"; +import { unixTimesInMs } from "@/src/constants/timeConstants"; +import { logger } from "../utils/logger"; + +export const getRandomNodes = (n: number) => { + const nodes = Object.entries(ExportRegions).map(([key]) => { + return { + nodeKey: key + }; + }); // may be filter that? + const output: string[] = []; + for (let i = 0; i < n; i++) { + logger.debug(i); + const randomIndex = Math.floor(Math.random() * nodes.length); + output[i] = nodes[randomIndex].nodeKey; + } + return output; +}; + +export const getCurrentRotation = () => { + const intervalMilliseconds = 2.5 * unixTimesInMs.hour; + const rotations = ["A", "B", "C"]; + + const now = new Date(); + const currentTimeMs = now.getTime(); + + const intervalIndex = Math.floor(currentTimeMs / intervalMilliseconds) % 3; + + return rotations[intervalIndex]; +}; diff --git a/src/models/worldStateModel.ts b/src/models/worldStateModel.ts index 68e1d018..45b128c1 100644 --- a/src/models/worldStateModel.ts +++ b/src/models/worldStateModel.ts @@ -57,10 +57,10 @@ const EventSchema = new Schema({ Messages: [messageSchema], Prop: String, Links: [linkSchema], - Date: Date, + Date: Number, Icon: String, - EventStartDate: Date, - EventEndDate: Date, + EventStartDate: Number, + EventEndDate: Number, ImageUrl: String, Priority: Boolean, MobileOnly: Boolean, @@ -71,6 +71,9 @@ const EventSchema = new Schema({ EventSchema.set("toJSON", { transform(_document, returnedObject) { returnedObject._id = { $oid: returnedObject._id.toString() }; + returnedObject.Date = { $date: { $numberLong: returnedObject.Date.toString() } }; + returnedObject.EventStartDate = { $date: { $numberLong: returnedObject.EventStartDate.toString() } }; + returnedObject.EventEndDate = { $date: { $numberLong: returnedObject.EventEndDate.toString() } }; } }); @@ -121,8 +124,8 @@ const MissionSchema = new Schema( ); const AlertSchema = new Schema({ - Activation: Date, - Expiry: Date, + Activation: Number, + Expiry: Number, MissionInfo: MissionSchema, ForceUnlock: Boolean, Tag: String @@ -131,27 +134,26 @@ const AlertSchema = new Schema({ AlertSchema.set("toJSON", { transform(_document, returnedObject) { returnedObject._id = { $oid: returnedObject._id.toString() }; + returnedObject.Activation = { $date: { $numberLong: returnedObject.Activation.toString() } }; + returnedObject.Expiry = { $date: { $numberLong: returnedObject.Expiry.toString() } }; } }); -const SortieMissionSchema = new Schema({ - missionType: String, - modifierType: String, - node: String, - tileset: String -}); - -SortieMissionSchema.set("toJSON", { - transform(_document, returnedObject) { - returnedObject._id = { $oid: returnedObject._id.toString() }; - } -}); +const SortieMissionSchema = new Schema( + { + missionType: String, + modifierType: String, + node: String, + tileset: String + }, + { _id: false } +); const LiteSortieSchema = new Schema({ - Activation: Date, - Expiry: Date, + Activation: Number, + Expiry: Number, Reward: String, - Seed: String, + Seed: Number, Boss: String, Missions: [SortieMissionSchema] }); @@ -159,15 +161,18 @@ const LiteSortieSchema = new Schema({ LiteSortieSchema.set("toJSON", { transform(_document, returnedObject) { returnedObject._id = { $oid: returnedObject._id.toString() }; + returnedObject.Activation = { $date: { $numberLong: returnedObject.Activation.toString() } }; + returnedObject.Expiry = { $date: { $numberLong: returnedObject.Expiry.toString() } }; } }); const SortieSchema = new Schema({ - Activation: Date, - Expiry: Date, + Activation: Number, + Expiry: Number, Reward: String, - Seed: String, + Seed: Number, Boss: String, + ExtraDrops: [String], Variants: [SortieMissionSchema], Twitter: Boolean }); @@ -175,6 +180,8 @@ const SortieSchema = new Schema({ SortieSchema.set("toJSON", { transform(_document, returnedObject) { returnedObject._id = { $oid: returnedObject._id.toString() }; + returnedObject.Activation = { $date: { $numberLong: returnedObject.Activation.toString() } }; + returnedObject.Expiry = { $date: { $numberLong: returnedObject.Expiry.toString() } }; } }); @@ -195,10 +202,10 @@ const JobSchema = new Schema( ); const SyndicateMissionSchema = new Schema({ - Activation: Date, - Expiry: Date, + Activation: Number, + Expiry: Number, Tag: String, - Seed: String, + Seed: Number, Nodes: [String], Jobs: [JobSchema] }); @@ -206,14 +213,16 @@ const SyndicateMissionSchema = new Schema({ SyndicateMissionSchema.set("toJSON", { transform(_document, returnedObject) { returnedObject._id = { $oid: returnedObject._id.toString() }; + returnedObject.Activation = { $date: { $numberLong: returnedObject.Activation.toString() } }; + returnedObject.Expiry = { $date: { $numberLong: returnedObject.Expiry.toString() } }; } }); const ActiveMissionSchema = new Schema({ - Activation: Date, - Expiry: Date, - Region: String, - Seed: String, + Activation: Number, + Expiry: Number, + Region: Number, + Seed: Number, Node: String, MissionType: String, Modifier: String, @@ -223,12 +232,14 @@ const ActiveMissionSchema = new Schema({ ActiveMissionSchema.set("toJSON", { transform(_document, returnedObject) { returnedObject._id = { $oid: returnedObject._id.toString() }; + returnedObject.Activation = { $date: { $numberLong: returnedObject.Activation.toString() } }; + returnedObject.Expiry = { $date: { $numberLong: returnedObject.Expiry.toString() } }; } }); const GlobalUpgradeSchema = new Schema({ - Activation: Date, - Expiry: Date, + Activation: Number, + Expiry: Number, UpgradeType: String, OperationType: String, Value: String @@ -237,14 +248,16 @@ const GlobalUpgradeSchema = new Schema({ GlobalUpgradeSchema.set("toJSON", { transform(_document, returnedObject) { returnedObject._id = { $oid: returnedObject._id.toString() }; + returnedObject.Activation = { $date: { $numberLong: returnedObject.Activation.toString() } }; + returnedObject.Expiry = { $date: { $numberLong: returnedObject.Expiry.toString() } }; } }); const FlashSaleSchema = new Schema( { TypeName: String, - StartDate: Date, - EndDate: Date, + StartDate: Number, + EndDate: Number, ShowInMarket: Boolean, HideFromMarket: Boolean, SupporterPack: Boolean, @@ -257,6 +270,13 @@ const FlashSaleSchema = new Schema( { _id: false } ); +FlashSaleSchema.set("toJSON", { + transform(_document, returnedObject) { + returnedObject.StartDate = { $date: { $numberLong: returnedObject.StartDate.toString() } }; + returnedObject.EndDate = { $date: { $numberLong: returnedObject.EndDate.toString() } }; + } +}); + const ShopCategorySchema = new Schema( { CategoryName: String, @@ -291,7 +311,7 @@ const InvasionMissionInfoSchema = new Schema( ); const InvasionSchema = new Schema({ - Activation: Date, + Activation: Number, Faction: String, DefenderFaction: String, Node: String, @@ -309,12 +329,13 @@ const InvasionSchema = new Schema({ InvasionSchema.set("toJSON", { transform(_document, returnedObject) { returnedObject._id = { $oid: returnedObject._id.toString() }; + returnedObject.Activation = { $date: { $numberLong: returnedObject.Activation.toString() } }; } }); const NodeOverrideSchema = new Schema({ - Activation: Date, - Expiry: Date, + Activation: Number, + Expiry: Number, Node: String, Faction: String, CustomNpcEncounters: [String], @@ -324,6 +345,8 @@ const NodeOverrideSchema = new Schema({ NodeOverrideSchema.set("toJSON", { transform(_document, returnedObject) { returnedObject._id = { $oid: returnedObject._id.toString() }; + returnedObject.Activation = { $date: { $numberLong: returnedObject.Activation.toString() } }; + returnedObject.Expiry = { $date: { $numberLong: returnedObject.Expiry.toString() } }; } }); @@ -338,16 +361,23 @@ const VoidTraderItemSchema = new Schema( const VoidTraderScheduleInfoSchema = new Schema( { - Expiry: Date, - PreviewHiddenUntil: Date, + Expiry: Number, + PreviewHiddenUntil: Number, FeaturedItem: String }, { _id: false } ); +VoidTraderScheduleInfoSchema.set("toJSON", { + transform(_document, returnedObject) { + returnedObject.Expiry = { $date: { $numberLong: returnedObject.Expiry.toString() } }; + returnedObject.PreviewHiddenUntil = { $date: { $numberLong: returnedObject.PreviewHiddenUntil.toString() } }; + } +}); + const VoidTraderSchema = new Schema({ - Activation: Date, - Expiry: Date, + Activation: Number, + Expiry: Number, Character: String, Node: String, Completed: Boolean, @@ -359,12 +389,14 @@ const VoidTraderSchema = new Schema({ VoidTraderSchema.set("toJSON", { transform(_document, returnedObject) { returnedObject._id = { $oid: returnedObject._id.toString() }; + returnedObject.Activation = { $date: { $numberLong: returnedObject.Activation.toString() } }; + returnedObject.Expiry = { $date: { $numberLong: returnedObject.Expiry.toString() } }; } }); const VoidStormSchema = new Schema({ - Activation: Date, - Expiry: Date, + Activation: Number, + Expiry: Number, Node: String, ActiveMissionTier: String }); @@ -372,6 +404,8 @@ const VoidStormSchema = new Schema({ VoidStormSchema.set("toJSON", { transform(_document, returnedObject) { returnedObject._id = { $oid: returnedObject._id.toString() }; + returnedObject.Activation = { $date: { $numberLong: returnedObject.Activation.toString() } }; + returnedObject.Expiry = { $date: { $numberLong: returnedObject.Expiry.toString() } }; } }); @@ -384,8 +418,8 @@ const PrimeAccessAvailabilitySchema = new Schema( const DailyDealSchema = new Schema( { - Activation: Date, - Expiry: Date, + Activation: Number, + Expiry: Number, StoreItem: String, Discount: Number, OriginalPrice: Number, @@ -396,6 +430,13 @@ const DailyDealSchema = new Schema( { _id: false } ); +DailyDealSchema.set("toJSON", { + transform(_document, returnedObject) { + returnedObject.Activation = { $date: { $numberLong: returnedObject.Activation.toString() } }; + returnedObject.Expiry = { $date: { $numberLong: returnedObject.Expiry.toString() } }; + } +}); + const LibraryInfoSchema = new Schema( { LastCompletedTargetType: String @@ -413,8 +454,8 @@ const PVPChallengeInstanceParam = new Schema( const PVPChallengeInstanceSchema = new Schema({ challengeTypeRefID: String, - startDate: Date, - endDate: Date, + startDate: Number, + endDate: Number, params: [PVPChallengeInstanceParam], isGenerated: Boolean, PVPMode: String, @@ -425,6 +466,8 @@ const PVPChallengeInstanceSchema = new Schema({ PVPChallengeInstanceSchema.set("toJSON", { transform(_document, returnedObject) { returnedObject._id = { $oid: returnedObject._id.toString() }; + returnedObject.startDate = { $date: { $numberLong: returnedObject.startDate.toString() } }; + returnedObject.endDate = { $date: { $numberLong: returnedObject.endDate.toString() } }; } }); @@ -451,8 +494,8 @@ FeaturedGuildShema.set("toJSON", { }); const ActiveChallengeSchema = new Schema({ - Activation: Date, - Expiry: Date, + Activation: Number, + Expiry: Number, Daily: Boolean, Challenge: String }); @@ -460,6 +503,8 @@ const ActiveChallengeSchema = new Schema({ FeaturedGuildShema.set("toJSON", { transform(_document, returnedObject) { returnedObject._id = { $oid: returnedObject._id.toString() }; + returnedObject.Activation = { $date: { $numberLong: returnedObject.Activation.toString() } }; + returnedObject.Expiry = { $date: { $numberLong: returnedObject.Expiry.toString() } }; } }); diff --git a/src/services/worldStateService.ts b/src/services/worldStateService.ts index c236be3b..7e7c6430 100644 --- a/src/services/worldStateService.ts +++ b/src/services/worldStateService.ts @@ -1,8 +1,43 @@ import { WorldState } from "@/src/models/worldStateModel"; +import { unixTimesInMs } from "@/src/constants/timeConstants"; +import { + IActiveMission, + ILiteSortie, + ISortie, + ISyndicateMission, + IVoidStorm, + IWorldState +} from "@/src/types/worldStateTypes"; +import { getRandomNumber, getRandomKey } from "@/src/helpers/general"; +import { getRandomNodes, getCurrentRotation } from "@/src/helpers/worldstateHelpers"; +import { ExportRailjack, ExportRegions } from "warframe-public-export-plus"; +import { logger } from "@/src/utils/logger"; +import { + factionSyndicates, + neutralJobsSyndicates, + neutralSyndicates, + restSyndicates, + CertusNormalJobs, + CertusNarmerJobs, + ZarimanNormalJobs, + voidFisuresMissionTypes, + validFisureMissionIndex, + omniaNodes, + liteSortiesBoss, + endStates, + modifierTypes, + SortiesMissionTypes, + voidTiers, + FortunaNarmerJobs, + FortunaNormalJobs +} from "@/src/constants/worldStateConstants"; export const createWorldState = async () => { const worldState = new WorldState(); await worldState.save(); + await updateSyndicateMissions(); + await updateVoidFisures(); + await updateSorties(); return worldState; }; @@ -11,6 +46,574 @@ export const getWorldState = async () => { if (!ws) { ws = await createWorldState(); } - - return ws; + return ws.toJSON(); +}; + +export const worldStateRunner = async () => { + await getWorldState(); + setInterval(async () => { + logger.info("Update worldState"); + await updateSyndicateMissions(); + await updateVoidFisures(); + await updateSorties(); + }, unixTimesInMs.minute); +}; + +const updateSyndicateMissions = async (): Promise => { + const currentDate = Date.now(); + const oneDayIntervalStart = + Math.floor(currentDate / unixTimesInMs.day) * unixTimesInMs.day + 16 * unixTimesInMs.hour; + const oneDayIntervalEnd = oneDayIntervalStart + unixTimesInMs.day; + + const neutralJobsIntervalStart = Math.floor(currentDate / (2.5 * unixTimesInMs.hour)) * (2.5 * unixTimesInMs.hour); + const neutralJobsIntervalEnd = neutralJobsIntervalStart + 2.5 * unixTimesInMs.hour; + + const neutralSeed = getRandomNumber(1, 99999); + + try { + const ws = await WorldState.findOne(); + if (!ws) throw new Error("Missing worldState"); + + const syndicateArray = ws.SyndicateMissions || []; + + const existingTags = syndicateArray.map(syndicate => syndicate.Tag); + + const createNewSyndicateEntry = (tag: string): ISyndicateMission => { + switch (true) { + case factionSyndicates.includes(tag): + return { + Tag: tag, + Seed: getRandomNumber(1, 99999), + Nodes: getRandomNodes(7), + Activation: oneDayIntervalStart, + Expiry: oneDayIntervalEnd + }; + case neutralJobsSyndicates.includes(tag): + return { + Tag: tag, + Seed: neutralSeed, + Nodes: [], + Activation: neutralJobsIntervalStart, + Expiry: neutralJobsIntervalEnd, + Jobs: getJobs(tag) + }; + case neutralSyndicates.includes(tag): + return { + Tag: tag, + Seed: neutralSeed, + Nodes: [], + Activation: neutralJobsIntervalStart, + Expiry: neutralJobsIntervalEnd + }; + case restSyndicates.includes(tag): + return { + Tag: tag, + Seed: getRandomNumber(1, 99999), + Nodes: [], + Activation: oneDayIntervalStart, + Expiry: oneDayIntervalEnd + }; + default: + throw new Error(`Unhandled syndicate tag: ${tag}`); + } + }; + + [...factionSyndicates, ...neutralJobsSyndicates, ...neutralSyndicates, ...restSyndicates].forEach(tag => { + if (!existingTags.includes(tag)) { + syndicateArray.push(createNewSyndicateEntry(tag)); + } else { + const syndicateIndex = existingTags.indexOf(tag); + const shouldUpdate = currentDate >= syndicateArray[syndicateIndex].Expiry; + + if (shouldUpdate) { + syndicateArray[syndicateIndex] = { + ...syndicateArray[syndicateIndex], + Tag: tag, + Seed: + neutralJobsSyndicates.includes(tag) || neutralSyndicates.includes(tag) + ? neutralSeed + : getRandomNumber(1, 99999), + Nodes: + neutralJobsSyndicates.includes(tag) || neutralSyndicates.includes(tag) + ? [] + : getRandomNodes(7), + Activation: + neutralJobsSyndicates.includes(tag) || neutralSyndicates.includes(tag) + ? neutralJobsIntervalStart + : oneDayIntervalStart, + Expiry: + neutralJobsSyndicates.includes(tag) || neutralSyndicates.includes(tag) + ? neutralJobsIntervalEnd + : oneDayIntervalEnd, + Jobs: neutralJobsSyndicates.includes(tag) ? getJobs(tag) : undefined + }; + } + } + }); + + ws.SyndicateMissions = syndicateArray; + + await ws.save(); + return ws; + } catch (error) { + throw new Error(`Error while updating Syndicates ${error}`); + } +}; + +const getJobs = (tag: string) => { + const rotration = getCurrentRotation(); + switch (tag) { + case "CetusSyndicate": + const Certusjobs = [ + { + jobType: CertusNormalJobs[Math.floor(Math.random() * CertusNormalJobs.length)], + rewards: `/Lotus/Types/Game/MissionDecks/EidolonJobMissionRewards/TierATable${rotration}Rewards`, + masteryReq: 0, + minEnemyLevel: 5, + maxEnemyLevel: 15, + xpAmounts: [410, 410, 410] + }, + { + jobType: CertusNormalJobs[Math.floor(Math.random() * CertusNormalJobs.length)], + rewards: `/Lotus/Types/Game/MissionDecks/EidolonJobMissionRewards/TierBTable${rotration}Rewards`, + masteryReq: 1, + minEnemyLevel: 10, + maxEnemyLevel: 30, + xpAmounts: [750, 750, 750] + }, + { + jobType: CertusNormalJobs[Math.floor(Math.random() * CertusNormalJobs.length)], + rewards: `/Lotus/Types/Game/MissionDecks/EidolonJobMissionRewards/TierCTable${rotration}Rewards`, + masteryReq: 2, + minEnemyLevel: 20, + maxEnemyLevel: 40, + xpAmounts: [580, 580, 580, 850] + }, + { + jobType: CertusNormalJobs[Math.floor(Math.random() * CertusNormalJobs.length)], + rewards: `/Lotus/Types/Game/MissionDecks/EidolonJobMissionRewards/TierDTable${rotration}Rewards`, + masteryReq: 3, + minEnemyLevel: 30, + maxEnemyLevel: 50, + xpAmounts: [580, 580, 580, 580, 1130] + }, + { + jobType: CertusNormalJobs[Math.floor(Math.random() * CertusNormalJobs.length)], + rewards: `/Lotus/Types/Game/MissionDecks/EidolonJobMissionRewards/TierETable${rotration}Rewards`, + masteryReq: 5, + minEnemyLevel: 40, + maxEnemyLevel: 60, + xpAmounts: [710, 710, 710, 710, 1390] + }, + { + jobType: CertusNormalJobs[Math.floor(Math.random() * CertusNormalJobs.length)], + rewards: `/Lotus/Types/Game/MissionDecks/EidolonJobMissionRewards/TierETable${rotration}Rewards`, + masteryReq: 10, + minEnemyLevel: 100, + maxEnemyLevel: 100, + xpAmounts: [840, 840, 840, 840, 1660] + }, + { + jobType: CertusNarmerJobs[Math.floor(Math.random() * CertusNarmerJobs.length)], + rewards: `/Lotus/Types/Game/MissionDecks/EidolonJobMissionRewards/NarmerTable${rotration}Rewards`, + masteryReq: 0, + minEnemyLevel: 50, + maxEnemyLevel: 70, + xpAmounts: [820, 820, 820, 820, 1610] + } + ]; + return Certusjobs; + + case "SolarisSyndicate": + const FortunaJobs = [ + { + jobType: FortunaNormalJobs[Math.floor(Math.random() * FortunaNormalJobs.length)], + rewards: `/Lotus/Types/Game/MissionDecks/VenusJobMissionRewards/VenusTierATable${rotration}Rewards`, + masteryReq: 0, + minEnemyLevel: 5, + maxEnemyLevel: 15, + xpAmounts: [410, 410, 410] + }, + { + jobType: FortunaNormalJobs[Math.floor(Math.random() * FortunaNormalJobs.length)], + rewards: `/Lotus/Types/Game/MissionDecks/VenusJobMissionRewards/VenusTierBTable${rotration}Rewards`, + masteryReq: 1, + minEnemyLevel: 10, + maxEnemyLevel: 30, + xpAmounts: [750, 750, 750] + }, + { + jobType: FortunaNormalJobs[Math.floor(Math.random() * FortunaNormalJobs.length)], + rewards: `/Lotus/Types/Game/MissionDecks/VenusJobMissionRewards/VenusTierCTable${rotration}Rewards`, + masteryReq: 2, + minEnemyLevel: 20, + maxEnemyLevel: 40, + xpAmounts: [580, 580, 580, 850] + }, + { + jobType: FortunaNormalJobs[Math.floor(Math.random() * FortunaNormalJobs.length)], + rewards: `/Lotus/Types/Game/MissionDecks/VenusJobMissionRewards/VenusTierDTable${rotration}Rewards`, + masteryReq: 3, + minEnemyLevel: 30, + maxEnemyLevel: 50, + xpAmounts: [580, 580, 580, 580, 1130] + }, + { + jobType: FortunaNormalJobs[Math.floor(Math.random() * FortunaNormalJobs.length)], + rewards: `/Lotus/Types/Game/MissionDecks/VenusJobMissionRewards/VenusTierETable${rotration}Rewards`, + masteryReq: 5, + minEnemyLevel: 40, + maxEnemyLevel: 60, + xpAmounts: [710, 710, 710, 710, 1390] + }, + { + jobType: FortunaNormalJobs[Math.floor(Math.random() * FortunaNormalJobs.length)], + rewards: `/Lotus/Types/Game/MissionDecks/VenusJobMissionRewards/VenusTierETable${rotration}Rewards`, + masteryReq: 10, + minEnemyLevel: 100, + maxEnemyLevel: 100, + xpAmounts: [840, 840, 840, 840, 1660] + }, + { + jobType: FortunaNarmerJobs[Math.floor(Math.random() * FortunaNarmerJobs.length)], + rewards: `/Lotus/Types/Game/MissionDecks/VenusJobMissionRewards/VenusNarmerTable${rotration}Rewards`, + masteryReq: 0, + minEnemyLevel: 50, + maxEnemyLevel: 70, + xpAmounts: [820, 820, 820, 820, 1610] + } + ]; + return FortunaJobs; + + case "EntratiSyndicate": + const ZarimanJobs = [ + { + jobType: ZarimanNormalJobs[Math.floor(Math.random() * ZarimanNormalJobs.length)], + rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/TierATable${getRandomKey(["A", "B", "C"])}Rewards`, + masteryReq: 0, + minEnemyLevel: 5, + maxEnemyLevel: 15, + xpAmounts: [5, 5, 5] + }, + { + jobType: ZarimanNormalJobs[Math.floor(Math.random() * ZarimanNormalJobs.length)], + rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/TierCTable${getRandomKey(["A", "B", "C"])}Rewards`, + masteryReq: 1, + minEnemyLevel: 15, + maxEnemyLevel: 25, + xpAmounts: [9, 9, 9] + }, + { + jobType: ZarimanNormalJobs[Math.floor(Math.random() * ZarimanNormalJobs.length)], + rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/TierBTable${getRandomKey(["A", "B", "C"])}Rewards`, + masteryReq: 5, + minEnemyLevel: 25, + maxEnemyLevel: 30, + endless: true, + xpAmounts: [14, 14, 14] + }, + { + jobType: ZarimanNormalJobs[Math.floor(Math.random() * ZarimanNormalJobs.length)], + rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/TierDTable${getRandomKey(["A", "B", "C"])}Rewards`, + masteryReq: 2, + minEnemyLevel: 30, + maxEnemyLevel: 40, + xpAmounts: [19, 19, 19, 29] + }, + { + jobType: ZarimanNormalJobs[Math.floor(Math.random() * ZarimanNormalJobs.length)], + rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/TierETable${getRandomKey(["A", "B", "C"])}Rewards`, + masteryReq: 3, + minEnemyLevel: 40, + maxEnemyLevel: 60, + xpAmounts: [21, 21, 21, 21, 41] + }, + { + jobType: ZarimanNormalJobs[Math.floor(Math.random() * ZarimanNormalJobs.length)], + rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/TierETable${getRandomKey(["A", "B", "C"])}Rewards`, + masteryReq: 10, + minEnemyLevel: 100, + maxEnemyLevel: 100, + xpAmounts: [25, 25, 25, 25, 50] + }, + { + rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/VaultBountyTierATable${getCurrentRotation()}Rewards`, + masteryReq: 5, + minEnemyLevel: 30, + maxEnemyLevel: 40, + xpAmounts: [2, 2, 2, 4], + locationTag: "ChamberB", + isVault: true + }, + { + rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/VaultBountyTierBTable${getCurrentRotation()}Rewards`, + masteryReq: 5, + minEnemyLevel: 40, + maxEnemyLevel: 50, + xpAmounts: [4, 4, 4, 5], + locationTag: "ChamberA", + isVault: true + }, + { + rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/VaultBountyTierCTable${getCurrentRotation()}Rewards`, + masteryReq: 5, + minEnemyLevel: 50, + maxEnemyLevel: 60, + xpAmounts: [5, 5, 5, 7], + locationTag: "ChamberC", + isVault: true + } + ]; + return ZarimanJobs; + + default: + throw new Error(`Error while updating Syndicates: Unknown Jobs syndicate ${tag}`); + } +}; + +const updateVoidFisures = async () => { + const curDate = Date.now(); + try { + const ws = await WorldState.findOne(); + if (!ws) throw new Error("Missing worldState"); + const voidFisures = ws.ActiveMissions; + const voidStorms = ws.VoidStorms; + const voidFisuresByTier: { [key: string]: IActiveMission[] } = { + VoidT1: [], + VoidT2: [], + VoidT3: [], + VoidT4: [], + VoidT5: [], + VoidT6: [] + }; + const voidStormsByTier: { [key: string]: IVoidStorm[] } = { + VoidT1: [], + VoidT2: [], + VoidT3: [], + VoidT4: [], + VoidT5: [], + VoidT6: [] + }; + + if (voidFisures) { + voidFisures.forEach(mission => { + const tier = mission.Modifier; + if (tier) { + if (!voidFisuresByTier[tier]) { + voidFisuresByTier[tier] = []; + } + voidFisuresByTier[tier].push(mission); + } + }); + } + + if (voidStorms) { + voidStorms.forEach(mission => { + const tier = mission.ActiveMissionTier; + if (tier) { + if (!voidStormsByTier[tier]) { + voidStormsByTier[tier] = []; + } + voidStormsByTier[tier].push(mission); + } + }); + } + + voidTiers.forEach(voidTier => { + if (voidFisuresByTier[voidTier].length < 3) { + const nodeData = getRandomFisureNode(false, voidTier == "VoidT6"); + logger.debug(voidTier); + if (!nodeData.missionIndex) nodeData.missionIndex = 1; + const node = { + Region: nodeData.systemIndex, + Seed: getRandomNumber(1, 99999), + Activation: curDate, + Expiry: curDate + Math.floor(Math.random() * unixTimesInMs.hour), + Node: nodeData.nodeKey, + MissionType: voidFisuresMissionTypes[nodeData.missionIndex], + Modifier: voidTier, + Hard: Math.random() < 0.1 + } as IActiveMission; + voidFisures?.push(node); + } + + if (voidStormsByTier[voidTier].length < 2) { + const nodeData = getRandomFisureNode(true, voidTier == "VoidT6"); + logger.debug(voidTier); + const node = { + Activation: curDate, + Expiry: curDate + Math.floor(Math.random() * unixTimesInMs.hour), + Node: nodeData.nodeKey, + ActiveMissionTier: voidTier + } as IVoidStorm; + voidStorms?.push(node); + } + }); + await ws.save(); + return ws; + } catch (error) { + throw new Error(`Error while updating VoidFisures: ${error}`); + } +}; + +const getRandomFisureNode = (isRailJack: boolean, isOmnia: boolean) => { + const validNodes = Object.entries(ExportRegions) + .map(([key, node]) => { + return { + ...node, + nodeKey: key + }; + }) + .filter(node => { + return validFisureMissionIndex.includes(node.missionIndex) && !node.missionName.includes("Archwing"); + }); + + if (isRailJack) { + const railJackNodes = Object.keys(ExportRailjack.nodes); + const randomKey = railJackNodes[Math.floor(Math.random() * railJackNodes.length)]; + return { + nodeKey: randomKey + }; + } else if (isOmnia) { + const validOmniaNodes = validNodes.filter(node => { + return omniaNodes.includes(node.nodeKey); + }); + const randomNode = validOmniaNodes[Math.floor(Math.random() * validOmniaNodes.length)]; + return { + nodeKey: randomNode.nodeKey, + systemIndex: randomNode.systemIndex, + missionIndex: randomNode.missionIndex + }; + } else { + const randomNode = validNodes[Math.floor(Math.random() * validNodes.length)]; + return { + nodeKey: randomNode.nodeKey, + systemIndex: randomNode.systemIndex, + missionIndex: randomNode.missionIndex + }; + } +}; + +const updateSorties = async () => { + const currentDate = Date.now(); + const oneDayIntervalStart = + Math.floor(currentDate / unixTimesInMs.day) * unixTimesInMs.day + 16 * unixTimesInMs.hour; + const oneDayIntervalEnd = oneDayIntervalStart + unixTimesInMs.day; + const oneWeekIntervalStart = + Math.floor(currentDate / (unixTimesInMs.day * 7)) * unixTimesInMs.day * 7 + 16 * unixTimesInMs.hour; + const oneWeekIntervalEnd = oneDayIntervalStart + unixTimesInMs.day * 7; + const nodes = Object.entries(ExportRegions).map(([key, node]) => { + return { + nodeSystemIndex: node.systemIndex, + nodeKey: key + }; + }); + + try { + const ws = await WorldState.findOne(); + if (!ws) throw new Error("Missing worldState"); + const liteSorties: ILiteSortie[] = ws?.LiteSorties; + const sorties: ISortie[] = ws?.Sorties; + + [...liteSorties, ...sorties].forEach((sortie, index, array) => { + if (currentDate >= sortie.Expiry) array.splice(index, 1); + }); + + if (liteSorties.length < 1) { + const sortie: ILiteSortie = { + Activation: oneWeekIntervalStart, + Expiry: oneWeekIntervalEnd, + Reward: "/Lotus/Types/Game/MissionDecks/ArchonSortieRewards", + Seed: getRandomNumber(1, 99999), + Boss: liteSortiesBoss[Math.floor(Math.random() * liteSortiesBoss.length)], + Missions: [ + { + missionType: SortiesMissionTypes[Math.floor(Math.random() * SortiesMissionTypes.length)], + node: nodes[Math.floor(Math.random() * nodes.length)].nodeKey + }, + { + missionType: SortiesMissionTypes[Math.floor(Math.random() * SortiesMissionTypes.length)], + node: nodes[Math.floor(Math.random() * nodes.length)].nodeKey + }, + { + missionType: SortiesMissionTypes[Math.floor(Math.random() * SortiesMissionTypes.length)], + node: nodes[Math.floor(Math.random() * nodes.length)].nodeKey + } + ] + }; + liteSorties.push(sortie); + } + + if (sorties.length < 1) { + const randomBoss = endStates[Math.floor(Math.random() * endStates.length)]; + const randomRegionIndex = [ + Math.floor(Math.random() * randomBoss.regions.length), + Math.floor(Math.random() * randomBoss.regions.length), + Math.floor(Math.random() * randomBoss.regions.length) + ]; + const randomRegionIndexFake = randomRegionIndex; + randomRegionIndexFake.forEach((element, index, array) => { + if (element == 13) { + array[index] = element + 2; + } else if (element == 14) { + array[index] = element + 1; + } + }); + const filteredNodes = [ + nodes.filter(node => { + return randomRegionIndexFake[0] === node.nodeSystemIndex; + }), + nodes.filter(node => { + return randomRegionIndexFake[1] === node.nodeSystemIndex; + }), + nodes.filter(node => { + return randomRegionIndexFake[2] === node.nodeSystemIndex; + }) + ]; + const sortie: ISortie = { + Activation: oneDayIntervalStart, + Expiry: oneDayIntervalEnd, + ExtraDrops: [], + Reward: "/Lotus/Types/Game/MissionDecks/SortieRewards", + Seed: getRandomNumber(1, 99999), + Boss: randomBoss.bossName, + Variants: [ + { + missionType: + randomBoss.regions[randomRegionIndex[0]].missions[ + Math.floor(Math.random() * randomBoss.regions[randomRegionIndex[0]].missions.length) + ], + modifierType: modifierTypes[Math.floor(Math.random() * modifierTypes.length)], + node: filteredNodes[0][Math.floor(Math.random() * filteredNodes[0].length)].nodeKey, + tileset: "CorpusShipTileset" + }, + { + missionType: + randomBoss.regions[randomRegionIndex[1]].missions[ + Math.floor(Math.random() * randomBoss.regions[randomRegionIndex[1]].missions.length) + ], + modifierType: modifierTypes[Math.floor(Math.random() * modifierTypes.length)], + node: filteredNodes[1][Math.floor(Math.random() * filteredNodes[1].length)].nodeKey, + tileset: "OrokinMoonTilesetCorpus" + }, + { + missionType: + randomBoss.regions[randomRegionIndex[2]].missions[ + Math.floor(Math.random() * randomBoss.regions[randomRegionIndex[2]].missions.length) + ], + modifierType: modifierTypes[Math.floor(Math.random() * modifierTypes.length)], + node: filteredNodes[2][Math.floor(Math.random() * filteredNodes[2].length)].nodeKey, + tileset: "CorpusShipTileset" + } + ], + Twitter: true + }; + sorties.push(sortie); + } + + await ws.save(); + return ws; + } catch (error) { + throw new Error(`Error while updating Sorties ${error}`); + } }; diff --git a/src/types/worldStateTypes.ts b/src/types/worldStateTypes.ts index c8d6b8ac..a9e02a88 100644 --- a/src/types/worldStateTypes.ts +++ b/src/types/worldStateTypes.ts @@ -1,4 +1,4 @@ -import { IMongoDate, IOid } from "@/src/types/commonTypes"; +import { IOid } from "@/src/types/commonTypes"; export interface IMessage { LanguageCode?: string; @@ -11,8 +11,8 @@ export interface ILink { } export interface IBaseWorldStateObject { - Activation: IMongoDate; - Expiry: IMongoDate; + Activation: number; + Expiry: number; _id?: IOid; } @@ -61,12 +61,11 @@ export interface IEvent { Icon?: string; Community?: boolean; Priority?: boolean; - EventStartDate?: IMongoDate; - EventEndDate?: IMongoDate; + EventStartDate?: number; + EventEndDate?: number; MobileOnly?: boolean; HideEndDateModifier?: boolean; - Date?: IMongoDate; - _id?: IOid; + Date?: number; } export interface IGoal extends IBaseWorldStateObject { @@ -103,7 +102,7 @@ export interface ISortieMission { } export interface ISortie extends Omit { - // ExtraDrops: []; Unknown + ExtraDrops: string[]; //Unknown Variants: ISortieMission[]; Twitter: boolean; } @@ -150,8 +149,8 @@ export interface IGlobalUpgrade extends IBaseWorldStateObject { } export interface IFlashSale { - StartDate: IMongoDate; - EndDate: IMongoDate; + StartDate: number; + EndDate: number; TypeName: string; ShowInMarket: boolean; HideFromMarket: boolean; @@ -200,8 +199,8 @@ export interface IInvasionMissionInfo { } export interface INodeOverride { - Activation?: IMongoDate; - Expiry?: IMongoDate; + Activation?: number; + Expiry?: number; Node: string; Faction?: string; CustomNpcEncounters?: string[]; @@ -224,7 +223,7 @@ export interface IVoidTraderItem { } export interface IVoidTraderScheduleInfo extends Omit { - PreviewHiddenUntil?: IMongoDate; + PreviewHiddenUntil?: number; FeaturedItem?: string; } @@ -252,8 +251,8 @@ export interface ILibraryInfo { export interface IPVPChallengeInstance { challengeTypeRefID: string; - startDate: IMongoDate; - endDate: IMongoDate; + startDate: number; + endDate: number; params: IPVPChallengeInstanceParam[]; isGenerated: boolean; PVPMode: string; @@ -302,8 +301,8 @@ export interface IWorldState { Events?: IEvent[]; Goals?: IGoal[]; Alerts?: IAlert[]; - Sorties?: ISortie[]; - LiteSorties?: ILiteSortie[]; + Sorties: ISortie[]; + LiteSorties: ILiteSortie[]; SyndicateMissions?: ISyndicateMission[]; ActiveMissions?: IActiveMission[]; GlobalUpgrades?: IGlobalUpgrade[]; diff --git a/static/webui/index.html b/static/webui/index.html index 533b2f20..b9042c79 100644 --- a/static/webui/index.html +++ b/static/webui/index.html @@ -273,7 +273,62 @@ - +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +