返回提交历史
Modified
src/services/missionInventoryUpdateService.ts
+2
-6
Modified
src/services/worldStateService.ts
+78
-60
Modified
src/types/worldStateTypes.ts
+1
-1
XFEstudio/XFESpaceNinjaServer
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: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/1735 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
c2a633b5
代码差异
3 个文件
+81
-67
@@ -53,7 +53,7 @@ import conservationAnimals from "@/static/fixed_responses/conservationAnimals.js
53
53
import { getInfNodes } from "@/src/helpers/nemesisHelpers";
54
54
import { Loadout } from "../models/inventoryModels/loadoutModel";
55
55
import { ILoadoutConfigDatabase } from "../types/saveLoadoutTypes";
56
import { getWorldState } from "./worldStateService";
56
import { getLiteSortie, getWorldState, idToWeek } from "./worldStateService";
57
57
import { config } from "./configService";
58
58
59
59
const getRotations = (rewardInfo: IRewardInfo, tierOverride?: number): number[] => {
@@ -990,11 +990,7 @@ function getRandomMissionDrops(
990
990
if (sortieId == "Lite") {
991
991
sortieId = arr[2];
992
992
993
// TODO: Some way to get from sortieId to reward to make this faster + more reliable at week rollover.
994
const boss = getWorldState().LiteSorties[0].Boss as
995
| "SORTIE_BOSS_AMAR"
996
| "SORTIE_BOSS_NIRA"
997
| "SORTIE_BOSS_BOREAL";
993
const boss = getLiteSortie(idToWeek(sortieId)).Boss;
998
994
let crystalType = {
999
995
SORTIE_BOSS_AMAR: "/Lotus/StoreItems/Types/Gameplay/NarmerSorties/ArchonCrystalAmar",
1000
996
SORTIE_BOSS_NIRA: "/Lotus/StoreItems/Types/Gameplay/NarmerSorties/ArchonCrystalNira",
@@ -4,7 +4,14 @@ import { unixTimesInMs } from "@/src/constants/timeConstants";
4
4
import { config } from "@/src/services/configService";
5
5
import { CRng } from "@/src/services/rngService";
6
6
import { eMissionType, ExportNightwave, ExportRegions } from "warframe-public-export-plus";
7
import { ICalendarDay, ICalendarSeason, ISeasonChallenge, ISortie, IWorldState } from "../types/worldStateTypes";
7
import {
8
ICalendarDay,
9
ICalendarSeason,
10
ILiteSortie,
11
ISeasonChallenge,
12
ISortie,
13
IWorldState
14
} from "../types/worldStateTypes";
8
15
9
16
const sortieBosses = [
10
17
"SORTIE_BOSS_HYENA",
@@ -941,65 +948,9 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
941
948
pushSortieIfRelevant(worldState.Sorties, day);
942
949
943
950
// Archon Hunt cycling every week
944
// TODO: Handle imminent rollover
945
{
946
const boss = ["SORTIE_BOSS_AMAR", "SORTIE_BOSS_NIRA", "SORTIE_BOSS_BOREAL"][week % 3];
947
const showdownNode = ["SolNode99", "SolNode53", "SolNode24"][week % 3];
948
const systemIndex = [3, 4, 2][week % 3]; // Mars, Jupiter, Earth
949
950
const nodes: string[] = [];
951
for (const [key, value] of Object.entries(ExportRegions)) {
952
if (
953
value.systemIndex === systemIndex &&
954
value.factionIndex !== undefined &&
955
value.factionIndex < 2 &&
956
value.name.indexOf("Archwing") == -1 &&
957
value.missionIndex != 0 // Exclude MT_ASSASSINATION
958
) {
959
nodes.push(key);
960
}
961
}
962
963
const rng = new CRng(week);
964
const firstNodeIndex = rng.randomInt(0, nodes.length - 1);
965
const firstNode = nodes[firstNodeIndex];
966
nodes.splice(firstNodeIndex, 1);
967
worldState.LiteSorties.push({
968
_id: {
969
$oid: Math.trunc(weekStart / 1000).toString(16) + "5e23a244740a190c"
970
},
971
Activation: { $date: { $numberLong: weekStart.toString() } },
972
Expiry: { $date: { $numberLong: weekEnd.toString() } },
973
Reward: "/Lotus/Types/Game/MissionDecks/ArchonSortieRewards",
974
Seed: week,
975
Boss: boss,
976
Missions: [
977
{
978
missionType: rng.randomElement([
979
"MT_INTEL",
980
"MT_MOBILE_DEFENSE",
981
"MT_EXTERMINATION",
982
"MT_SABOTAGE",
983
"MT_RESCUE"
984
]),
985
node: firstNode
986
},
987
{
988
missionType: rng.randomElement([
989
"MT_DEFENSE",
990
"MT_TERRITORY",
991
"MT_ARTIFACT",
992
"MT_EXCAVATE",
993
"MT_SURVIVAL"
994
]),
995
node: rng.randomElement(nodes)
996
},
997
{
998
missionType: "MT_ASSASSINATION",
999
node: showdownNode
1000
}
1001
]
1002
});
951
worldState.LiteSorties.push(getLiteSortie(week));
952
if (isBeforeNextExpectedWorldStateRefresh(weekEnd)) {
953
worldState.LiteSorties.push(getLiteSortie(week + 1));
1003
954
}
1004
955
1005
956
// Circuit choices cycling every week
@@ -1071,3 +1022,70 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
1071
1022
1072
1023
return worldState;
1073
1024
};
1025
1026
export const idToWeek = (id: string): number => {
1027
return (parseInt(id.substring(0, 8), 16) * 1000 - EPOCH) / 604800000;
1028
};
1029
1030
export const getLiteSortie = (week: number): ILiteSortie => {
1031
const boss = (["SORTIE_BOSS_AMAR", "SORTIE_BOSS_NIRA", "SORTIE_BOSS_BOREAL"] as const)[week % 3];
1032
const showdownNode = ["SolNode99", "SolNode53", "SolNode24"][week % 3];
1033
const systemIndex = [3, 4, 2][week % 3]; // Mars, Jupiter, Earth
1034
1035
const nodes: string[] = [];
1036
for (const [key, value] of Object.entries(ExportRegions)) {
1037
if (
1038
value.systemIndex === systemIndex &&
1039
value.factionIndex !== undefined &&
1040
value.factionIndex < 2 &&
1041
value.name.indexOf("Archwing") == -1 &&
1042
value.missionIndex != 0 // Exclude MT_ASSASSINATION
1043
) {
1044
nodes.push(key);
1045
}
1046
}
1047
1048
const rng = new CRng(week);
1049
const firstNodeIndex = rng.randomInt(0, nodes.length - 1);
1050
const firstNode = nodes[firstNodeIndex];
1051
nodes.splice(firstNodeIndex, 1);
1052
1053
const weekStart = EPOCH + week * 604800000;
1054
const weekEnd = weekStart + 604800000;
1055
return {
1056
_id: {
1057
$oid: Math.trunc(weekStart / 1000).toString(16) + "5e23a244740a190c"
1058
},
1059
Activation: { $date: { $numberLong: weekStart.toString() } },
1060
Expiry: { $date: { $numberLong: weekEnd.toString() } },
1061
Reward: "/Lotus/Types/Game/MissionDecks/ArchonSortieRewards",
1062
Seed: week,
1063
Boss: boss,
1064
Missions: [
1065
{
1066
missionType: rng.randomElement([
1067
"MT_INTEL",
1068
"MT_MOBILE_DEFENSE",
1069
"MT_EXTERMINATION",
1070
"MT_SABOTAGE",
1071
"MT_RESCUE"
1072
]),
1073
node: firstNode
1074
},
1075
{
1076
missionType: rng.randomElement([
1077
"MT_DEFENSE",
1078
"MT_TERRITORY",
1079
"MT_ARTIFACT",
1080
"MT_EXCAVATE",
1081
"MT_SURVIVAL"
1082
]),
1083
node: rng.randomElement(nodes)
1084
},
1085
{
1086
missionType: "MT_ASSASSINATION",
1087
node: showdownNode
1088
}
1089
]
1090
};
1091
};
@@ -103,7 +103,7 @@ export interface ILiteSortie {
103
103
Expiry: IMongoDate;
104
104
Reward: "/Lotus/Types/Game/MissionDecks/ArchonSortieRewards";
105
105
Seed: number;
106
Boss: string; // "SORTIE_BOSS_AMAR" | "SORTIE_BOSS_NIRA" | "SORTIE_BOSS_BOREAL"
106
Boss: "SORTIE_BOSS_AMAR" | "SORTIE_BOSS_NIRA" | "SORTIE_BOSS_BOREAL";
107
107
Missions: {
108
108
missionType: string;
109
109
node: string;