chore: improve LiteSortie handling at week rollover #1735
@ -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",
 | 
				
			||||||
 | 
				
			|||||||
@ -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
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
@ -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;
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user