chore: improve LiteSortie handling at week rollover
All checks were successful
Build / build (push) Successful in 1m30s
Build / build (pull_request) Successful in 1m31s

WorldState now provides the upcoming LiteSortie if relevant and the boss is derived from the sortieId so completing it at rollover should work as expected.
This commit is contained in:
Sainan 2025-04-19 09:12:17 +02:00
parent 8b0ba0b84a
commit 1a0577a4f4
3 changed files with 81 additions and 67 deletions

View File

@ -53,7 +53,7 @@ import conservationAnimals from "@/static/fixed_responses/conservationAnimals.js
import { getInfNodes } from "@/src/helpers/nemesisHelpers"; import { getInfNodes } from "@/src/helpers/nemesisHelpers";
import { Loadout } from "../models/inventoryModels/loadoutModel"; import { Loadout } from "../models/inventoryModels/loadoutModel";
import { ILoadoutConfigDatabase } from "../types/saveLoadoutTypes"; import { ILoadoutConfigDatabase } from "../types/saveLoadoutTypes";
import { getWorldState } from "./worldStateService"; import { getLiteSortie, getWorldState, idToWeek } from "./worldStateService";
import { config } from "./configService"; import { config } from "./configService";
const getRotations = (rewardInfo: IRewardInfo, tierOverride?: number): number[] => { const getRotations = (rewardInfo: IRewardInfo, tierOverride?: number): number[] => {
@ -988,11 +988,7 @@ function getRandomMissionDrops(
if (sortieId == "Lite") { if (sortieId == "Lite") {
sortieId = arr[2]; sortieId = arr[2];
// TODO: Some way to get from sortieId to reward to make this faster + more reliable at week rollover. const boss = getLiteSortie(idToWeek(sortieId)).Boss;
const boss = getWorldState().LiteSorties[0].Boss as
| "SORTIE_BOSS_AMAR"
| "SORTIE_BOSS_NIRA"
| "SORTIE_BOSS_BOREAL";
let crystalType = { let crystalType = {
SORTIE_BOSS_AMAR: "/Lotus/StoreItems/Types/Gameplay/NarmerSorties/ArchonCrystalAmar", SORTIE_BOSS_AMAR: "/Lotus/StoreItems/Types/Gameplay/NarmerSorties/ArchonCrystalAmar",
SORTIE_BOSS_NIRA: "/Lotus/StoreItems/Types/Gameplay/NarmerSorties/ArchonCrystalNira", SORTIE_BOSS_NIRA: "/Lotus/StoreItems/Types/Gameplay/NarmerSorties/ArchonCrystalNira",

View File

@ -4,7 +4,14 @@ import { unixTimesInMs } from "@/src/constants/timeConstants";
import { config } from "@/src/services/configService"; import { config } from "@/src/services/configService";
import { CRng } from "@/src/services/rngService"; import { CRng } from "@/src/services/rngService";
import { eMissionType, ExportNightwave, ExportRegions } from "warframe-public-export-plus"; import { eMissionType, ExportNightwave, ExportRegions } from "warframe-public-export-plus";
import { ICalendarDay, ICalendarSeason, ISeasonChallenge, ISortie, IWorldState } from "../types/worldStateTypes"; import {
ICalendarDay,
ICalendarSeason,
ILiteSortie,
ISeasonChallenge,
ISortie,
IWorldState
} from "../types/worldStateTypes";
const sortieBosses = [ const sortieBosses = [
"SORTIE_BOSS_HYENA", "SORTIE_BOSS_HYENA",
@ -941,65 +948,9 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
pushSortieIfRelevant(worldState.Sorties, day); pushSortieIfRelevant(worldState.Sorties, day);
// Archon Hunt cycling every week // Archon Hunt cycling every week
// TODO: Handle imminent rollover worldState.LiteSorties.push(getLiteSortie(week));
{ if (isBeforeNextExpectedWorldStateRefresh(weekEnd)) {
const boss = ["SORTIE_BOSS_AMAR", "SORTIE_BOSS_NIRA", "SORTIE_BOSS_BOREAL"][week % 3]; worldState.LiteSorties.push(getLiteSortie(week + 1));
const showdownNode = ["SolNode99", "SolNode53", "SolNode24"][week % 3];
const systemIndex = [3, 4, 2][week % 3]; // Mars, Jupiter, Earth
const nodes: string[] = [];
for (const [key, value] of Object.entries(ExportRegions)) {
if (
value.systemIndex === systemIndex &&
value.factionIndex !== undefined &&
value.factionIndex < 2 &&
value.name.indexOf("Archwing") == -1 &&
value.missionIndex != 0 // Exclude MT_ASSASSINATION
) {
nodes.push(key);
}
}
const rng = new CRng(week);
const firstNodeIndex = rng.randomInt(0, nodes.length - 1);
const firstNode = nodes[firstNodeIndex];
nodes.splice(firstNodeIndex, 1);
worldState.LiteSorties.push({
_id: {
$oid: Math.trunc(weekStart / 1000).toString(16) + "5e23a244740a190c"
},
Activation: { $date: { $numberLong: weekStart.toString() } },
Expiry: { $date: { $numberLong: weekEnd.toString() } },
Reward: "/Lotus/Types/Game/MissionDecks/ArchonSortieRewards",
Seed: week,
Boss: boss,
Missions: [
{
missionType: rng.randomElement([
"MT_INTEL",
"MT_MOBILE_DEFENSE",
"MT_EXTERMINATION",
"MT_SABOTAGE",
"MT_RESCUE"
]),
node: firstNode
},
{
missionType: rng.randomElement([
"MT_DEFENSE",
"MT_TERRITORY",
"MT_ARTIFACT",
"MT_EXCAVATE",
"MT_SURVIVAL"
]),
node: rng.randomElement(nodes)
},
{
missionType: "MT_ASSASSINATION",
node: showdownNode
}
]
});
} }
// Circuit choices cycling every week // Circuit choices cycling every week
@ -1071,3 +1022,70 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
return worldState; return worldState;
}; };
export const idToWeek = (id: string): number => {
return (parseInt(id.substring(0, 8), 16) * 1000 - EPOCH) / 604800000;
};
export const getLiteSortie = (week: number): ILiteSortie => {
const boss = (["SORTIE_BOSS_AMAR", "SORTIE_BOSS_NIRA", "SORTIE_BOSS_BOREAL"] as const)[week % 3];
const showdownNode = ["SolNode99", "SolNode53", "SolNode24"][week % 3];
const systemIndex = [3, 4, 2][week % 3]; // Mars, Jupiter, Earth
const nodes: string[] = [];
for (const [key, value] of Object.entries(ExportRegions)) {
if (
value.systemIndex === systemIndex &&
value.factionIndex !== undefined &&
value.factionIndex < 2 &&
value.name.indexOf("Archwing") == -1 &&
value.missionIndex != 0 // Exclude MT_ASSASSINATION
) {
nodes.push(key);
}
}
const rng = new CRng(week);
const firstNodeIndex = rng.randomInt(0, nodes.length - 1);
const firstNode = nodes[firstNodeIndex];
nodes.splice(firstNodeIndex, 1);
const weekStart = EPOCH + week * 604800000;
const weekEnd = weekStart + 604800000;
return {
_id: {
$oid: Math.trunc(weekStart / 1000).toString(16) + "5e23a244740a190c"
},
Activation: { $date: { $numberLong: weekStart.toString() } },
Expiry: { $date: { $numberLong: weekEnd.toString() } },
Reward: "/Lotus/Types/Game/MissionDecks/ArchonSortieRewards",
Seed: week,
Boss: boss,
Missions: [
{
missionType: rng.randomElement([
"MT_INTEL",
"MT_MOBILE_DEFENSE",
"MT_EXTERMINATION",
"MT_SABOTAGE",
"MT_RESCUE"
]),
node: firstNode
},
{
missionType: rng.randomElement([
"MT_DEFENSE",
"MT_TERRITORY",
"MT_ARTIFACT",
"MT_EXCAVATE",
"MT_SURVIVAL"
]),
node: rng.randomElement(nodes)
},
{
missionType: "MT_ASSASSINATION",
node: showdownNode
}
]
};
};

View File

@ -103,7 +103,7 @@ export interface ILiteSortie {
Expiry: IMongoDate; Expiry: IMongoDate;
Reward: "/Lotus/Types/Game/MissionDecks/ArchonSortieRewards"; Reward: "/Lotus/Types/Game/MissionDecks/ArchonSortieRewards";
Seed: number; Seed: number;
Boss: string; // "SORTIE_BOSS_AMAR" | "SORTIE_BOSS_NIRA" | "SORTIE_BOSS_BOREAL" Boss: "SORTIE_BOSS_AMAR" | "SORTIE_BOSS_NIRA" | "SORTIE_BOSS_BOREAL";
Missions: { Missions: {
missionType: string; missionType: string;
node: string; node: string;