XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFESpaceNinjaServer

A simple server for a small space ninja game

公开
关注 0 Fork 0 Star 0
返回提交历史

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
Sainan <63328889+Sainan@users.noreply.github.com>
提交于

代码差异

3 个文件 +81 -67
Modified src/services/missionInventoryUpdateService.ts +2 -6
@@ -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",
Modified src/services/worldStateService.ts +78 -60
@@ -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 };
Modified src/types/worldStateTypes.ts +1 -1
@@ -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;