forked from OpenWF/SpaceNinjaServer
chore: improve LiteSortie handling at week rollover (#1735)
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. Reviewed-on: OpenWF/SpaceNinjaServer#1735 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
7040d422a2
commit
c2a633b549
@ -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[] => {
|
||||||
@ -990,11 +990,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