feat: void storm rotation (#2171)
Re #1512 Reviewed-on: OpenWF/SpaceNinjaServer#2171 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
This commit is contained in:
		
							parent
							
								
									9731004de6
								
							
						
					
					
						commit
						3e99e069be
					
				@ -16,6 +16,7 @@ import {
 | 
			
		||||
    ISortie,
 | 
			
		||||
    ISortieMission,
 | 
			
		||||
    ISyndicateMissionInfo,
 | 
			
		||||
    IVoidStorm,
 | 
			
		||||
    IWorldState
 | 
			
		||||
} from "../types/worldStateTypes";
 | 
			
		||||
import { version_compare } from "../helpers/inventoryHelpers";
 | 
			
		||||
@ -963,6 +964,61 @@ const getCalendarSeason = (week: number): ICalendarSeason => {
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Not very faithful, but to avoid the same node coming up back-to-back (which is not valid), I've split these into 2 arrays which we're alternating between.
 | 
			
		||||
 | 
			
		||||
const voidStormMissionsA = {
 | 
			
		||||
    VoidT1: ["CrewBattleNode519", "CrewBattleNode518", "CrewBattleNode515", "CrewBattleNode503"],
 | 
			
		||||
    VoidT2: ["CrewBattleNode501", "CrewBattleNode534", "CrewBattleNode530"],
 | 
			
		||||
    VoidT3: ["CrewBattleNode521", "CrewBattleNode516"],
 | 
			
		||||
    VoidT4: [
 | 
			
		||||
        "CrewBattleNode555",
 | 
			
		||||
        "CrewBattleNode553",
 | 
			
		||||
        "CrewBattleNode554",
 | 
			
		||||
        "CrewBattleNode539",
 | 
			
		||||
        "CrewBattleNode531",
 | 
			
		||||
        "CrewBattleNode527"
 | 
			
		||||
    ]
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const voidStormMissionsB = {
 | 
			
		||||
    VoidT1: ["CrewBattleNode509", "CrewBattleNode522", "CrewBattleNode511", "CrewBattleNode512"],
 | 
			
		||||
    VoidT2: ["CrewBattleNode535", "CrewBattleNode533"],
 | 
			
		||||
    VoidT3: ["CrewBattleNode524", "CrewBattleNode525"],
 | 
			
		||||
    VoidT4: [
 | 
			
		||||
        "CrewBattleNode542",
 | 
			
		||||
        "CrewBattleNode538",
 | 
			
		||||
        "CrewBattleNode543",
 | 
			
		||||
        "CrewBattleNode536",
 | 
			
		||||
        "CrewBattleNode550",
 | 
			
		||||
        "CrewBattleNode529"
 | 
			
		||||
    ]
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const pushVoidStorms = (arr: IVoidStorm[], hour: number): void => {
 | 
			
		||||
    const activation = hour * unixTimesInMs.hour + 40 * unixTimesInMs.minute;
 | 
			
		||||
    const expiry = activation + 90 * unixTimesInMs.minute;
 | 
			
		||||
    let accum = 0;
 | 
			
		||||
    const rng = new SRng(new SRng(hour).randomInt(0, 100_000));
 | 
			
		||||
    const voidStormMissions = structuredClone(hour & 1 ? voidStormMissionsA : voidStormMissionsB);
 | 
			
		||||
    for (const tier of ["VoidT1", "VoidT1", "VoidT2", "VoidT3", "VoidT4", "VoidT4"] as const) {
 | 
			
		||||
        const idx = rng.randomInt(0, voidStormMissions[tier].length - 1);
 | 
			
		||||
        const node = voidStormMissions[tier][idx];
 | 
			
		||||
        voidStormMissions[tier].splice(idx, 1);
 | 
			
		||||
        arr.push({
 | 
			
		||||
            _id: {
 | 
			
		||||
                $oid:
 | 
			
		||||
                    ((activation / 1000) & 0xffffffff).toString(16).padStart(8, "0") +
 | 
			
		||||
                    "0321e89b" +
 | 
			
		||||
                    (accum++).toString().padStart(8, "0")
 | 
			
		||||
            },
 | 
			
		||||
            Node: node,
 | 
			
		||||
            Activation: { $date: { $numberLong: activation.toString() } },
 | 
			
		||||
            Expiry: { $date: { $numberLong: expiry.toString() } },
 | 
			
		||||
            ActiveMissionTier: tier
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const doesTimeSatsifyConstraints = (timeSecs: number): boolean => {
 | 
			
		||||
    if (config.worldState?.eidolonOverride) {
 | 
			
		||||
        const eidolonEpoch = 1391992660;
 | 
			
		||||
@ -1032,6 +1088,7 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
 | 
			
		||||
        Sorties: [],
 | 
			
		||||
        LiteSorties: [],
 | 
			
		||||
        GlobalUpgrades: [],
 | 
			
		||||
        VoidStorms: [],
 | 
			
		||||
        EndlessXpChoices: [],
 | 
			
		||||
        KnownCalendarSeasons: [],
 | 
			
		||||
        ...staticWorldState,
 | 
			
		||||
@ -1228,6 +1285,18 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
 | 
			
		||||
        worldState.KnownCalendarSeasons.push(getCalendarSeason(week + 1));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Void Storms
 | 
			
		||||
    const hour = Math.trunc(timeMs / unixTimesInMs.hour);
 | 
			
		||||
    const overLastHourStormExpiry = hour * unixTimesInMs.hour + 10 * unixTimesInMs.minute;
 | 
			
		||||
    const thisHourStormActivation = hour * unixTimesInMs.hour + 40 * unixTimesInMs.minute;
 | 
			
		||||
    if (overLastHourStormExpiry > timeMs) {
 | 
			
		||||
        pushVoidStorms(worldState.VoidStorms, hour - 2);
 | 
			
		||||
    }
 | 
			
		||||
    pushVoidStorms(worldState.VoidStorms, hour - 1);
 | 
			
		||||
    if (isBeforeNextExpectedWorldStateRefresh(timeMs, thisHourStormActivation)) {
 | 
			
		||||
        pushVoidStorms(worldState.VoidStorms, hour);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Sentient Anomaly cycling every 30 minutes
 | 
			
		||||
    const halfHour = Math.trunc(timeMs / (unixTimesInMs.hour / 2));
 | 
			
		||||
    const tmp = {
 | 
			
		||||
 | 
			
		||||
@ -12,6 +12,7 @@ export interface IWorldState {
 | 
			
		||||
    GlobalUpgrades: IGlobalUpgrade[];
 | 
			
		||||
    ActiveMissions: IFissure[];
 | 
			
		||||
    NodeOverrides: INodeOverride[];
 | 
			
		||||
    VoidStorms: IVoidStorm[];
 | 
			
		||||
    PVPChallengeInstances: IPVPChallengeInstance[];
 | 
			
		||||
    EndlessXpChoices: IEndlessXpChoice[];
 | 
			
		||||
    SeasonInfo?: {
 | 
			
		||||
@ -131,6 +132,14 @@ export interface ILiteSortie {
 | 
			
		||||
    }[];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface IVoidStorm {
 | 
			
		||||
    _id: IOid;
 | 
			
		||||
    Node: string;
 | 
			
		||||
    Activation: IMongoDate;
 | 
			
		||||
    Expiry: IMongoDate;
 | 
			
		||||
    ActiveMissionTier: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface IPVPChallengeInstance {
 | 
			
		||||
    _id: IOid;
 | 
			
		||||
    challengeTypeRefID: string;
 | 
			
		||||
 | 
			
		||||
@ -2562,50 +2562,6 @@
 | 
			
		||||
      ]
 | 
			
		||||
    }
 | 
			
		||||
  ],
 | 
			
		||||
  "VoidStorms": [
 | 
			
		||||
    {
 | 
			
		||||
      "_id": { "$oid": "663a7581ced28e18f694b550" },
 | 
			
		||||
      "Node": "CrewBattleNode519",
 | 
			
		||||
      "Activation": { "$date": { "$numberLong": "1715109601821" } },
 | 
			
		||||
      "Expiry": { "$date": { "$numberLong": "2000000000000" } },
 | 
			
		||||
      "ActiveMissionTier": "VoidT1"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "_id": { "$oid": "663a7581ced28e18f694b551" },
 | 
			
		||||
      "Node": "CrewBattleNode515",
 | 
			
		||||
      "Activation": { "$date": { "$numberLong": "1715109601825" } },
 | 
			
		||||
      "Expiry": { "$date": { "$numberLong": "2000000000000" } },
 | 
			
		||||
      "ActiveMissionTier": "VoidT1"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "_id": { "$oid": "663a7581ced28e18f694b554" },
 | 
			
		||||
      "Node": "CrewBattleNode536",
 | 
			
		||||
      "Activation": { "$date": { "$numberLong": "1715109601832" } },
 | 
			
		||||
      "Expiry": { "$date": { "$numberLong": "2000000000000" } },
 | 
			
		||||
      "ActiveMissionTier": "VoidT4"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "_id": { "$oid": "663a7581ced28e18f694b555" },
 | 
			
		||||
      "Node": "CrewBattleNode539",
 | 
			
		||||
      "Activation": { "$date": { "$numberLong": "1715109601834" } },
 | 
			
		||||
      "Expiry": { "$date": { "$numberLong": "2000000000000" } },
 | 
			
		||||
      "ActiveMissionTier": "VoidT4"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "_id": { "$oid": "663a7581ced28e18f694b553" },
 | 
			
		||||
      "Node": "CrewBattleNode521",
 | 
			
		||||
      "Activation": { "$date": { "$numberLong": "1715109601829" } },
 | 
			
		||||
      "Expiry": { "$date": { "$numberLong": "2000000000000" } },
 | 
			
		||||
      "ActiveMissionTier": "VoidT3"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "_id": { "$oid": "663a7581ced28e18f694b552" },
 | 
			
		||||
      "Node": "CrewBattleNode535",
 | 
			
		||||
      "Activation": { "$date": { "$numberLong": "1715109601827" } },
 | 
			
		||||
      "Expiry": { "$date": { "$numberLong": "2000000000000" } },
 | 
			
		||||
      "ActiveMissionTier": "VoidT2"
 | 
			
		||||
    }
 | 
			
		||||
  ],
 | 
			
		||||
  "PrimeAccessAvailability": { "State": "PRIME1" },
 | 
			
		||||
  "PrimeVaultAvailabilities": [false, false, false, false, false],
 | 
			
		||||
  "PrimeTokenAvailability": true,
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user