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

SpaceNinjaServer

A simple server for a small space ninja game

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

XFEstudio/SpaceNinjaServer

fix: restrict sortie mission types based on what the tileset supports (#2003)

Closes #2000 Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/2003 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>

e545ecf7
Sainan <63328889+Sainan@users.noreply.github.com>
提交于

代码差异

2 个文件 +77 -66
Modified src/services/worldStateService.ts +32 -66
@@ -1,11 +1,12 @@
1 1 import staticWorldState from "@/static/fixed_responses/worldState/worldState.json";
2 2 import sortieTilesets from "@/static/fixed_responses/worldState/sortieTilesets.json";
3 import sortieTilesetMissions from "@/static/fixed_responses/worldState/sortieTilesetMissions.json";
3 4 import syndicateMissions from "@/static/fixed_responses/worldState/syndicateMissions.json";
4 5 import { buildConfig } from "@/src/services/buildConfigService";
5 6 import { unixTimesInMs } from "@/src/constants/timeConstants";
6 7 import { config } from "@/src/services/configService";
7 8 import { CRng } from "@/src/services/rngService";
8 import { eMissionType, ExportNightwave, ExportRegions, IRegion } from "warframe-public-export-plus";
9 import { ExportNightwave, ExportRegions, IRegion } from "warframe-public-export-plus";
9 10 import {
10 11 ICalendarDay,
11 12 ICalendarEvent,
@@ -72,12 +73,6 @@ const sortieFactionToFactionIndexes: Record<string, number[]> = {
72 73 FC_OROKIN: [3]
73 74 };
74 75
75 const sortieFactionToSpecialMissionTileset: Record<string, string> = {
76 FC_GRINEER: "GrineerGalleonTileset",
77 FC_CORPUS: "CorpusShipTileset",
78 FC_INFESTATION: "CorpusShipTileset"
79 };
80
81 76 const sortieBossNode: Record<Exclude<TSortieBoss, "SORTIE_BOSS_CORRUPTED_VOR">, string> = {
82 77 SORTIE_BOSS_ALAD: "SolNode53",
83 78 SORTIE_BOSS_AMBULAS: "SolNode51",
@@ -217,6 +212,27 @@ const pushSyndicateMissions = (
217 212 });
218 213 };
219 214
215 type TSortieTileset = keyof typeof sortieTilesetMissions;
216
217 const pushTilesetModifiers = (modifiers: string[], tileset: TSortieTileset): void => {
218 switch (tileset) {
219 case "GrineerForestTileset":
220 modifiers.push("SORTIE_MODIFIER_HAZARD_FOG");
221 break;
222 case "CorpusShipTileset":
223 case "GrineerGalleonTileset":
224 case "InfestedCorpusShipTileset":
225 modifiers.push("SORTIE_MODIFIER_HAZARD_MAGNETIC");
226 modifiers.push("SORTIE_MODIFIER_HAZARD_FIRE");
227 modifiers.push("SORTIE_MODIFIER_HAZARD_ICE");
228 break;
229 case "CorpusIcePlanetTileset":
230 case "CorpusIcePlanetTilesetCaves":
231 modifiers.push("SORTIE_MODIFIER_HAZARD_COLD");
232 break;
233 }
234 };
235
220 236 export const getSortie = (day: number): ISortie => {
221 237 const seed = new CRng(day).randomInt(0, 0xffff);
222 238 const rng = new CRng(seed);
@@ -224,54 +240,22 @@ export const getSortie = (day: number): ISortie => {
224 240 const boss = rng.randomElement(sortieBosses)!;
225 241
226 242 const nodes: string[] = [];
227 const availableMissionIndexes: number[] = [];
228 243 for (const [key, value] of Object.entries(ExportRegions)) {
229 244 if (
230 245 sortieFactionToSystemIndexes[sortieBossToFaction[boss]].includes(value.systemIndex) &&
231 246 sortieFactionToFactionIndexes[sortieBossToFaction[boss]].includes(value.factionIndex!) &&
232 247 key in sortieTilesets
233 248 ) {
234 if (
235 value.missionIndex != 0 && // Assassination will be decided independently
236 value.missionIndex != 5 && // Sorties do not have capture missions
237 !availableMissionIndexes.includes(value.missionIndex)
238 ) {
239 availableMissionIndexes.push(value.missionIndex);
240 }
241 249 nodes.push(key);
242 250 }
243 251 }
244 252
245 const specialMissionTypes = [1, 3, 5, 9];
246 if (!(sortieBossToFaction[boss] in sortieFactionToSpecialMissionTileset)) {
247 for (const missionType of specialMissionTypes) {
248 const i = availableMissionIndexes.indexOf(missionType);
249 if (i != -1) {
250 availableMissionIndexes.splice(i, 1);
251 }
252 }
253 }
254
255 253 const selectedNodes: ISortieMission[] = [];
256 254 const missionTypes = new Set();
257 255
258 256 for (let i = 0; i < 3; i++) {
259 let randomIndex;
260 let node;
261 let missionIndex;
262 do {
263 randomIndex = rng.randomInt(0, nodes.length - 1);
264 node = nodes[randomIndex];
265
266 missionIndex = ExportRegions[node].missionIndex;
267 if (missionIndex != 28) {
268 missionIndex = rng.randomElement(availableMissionIndexes)!;
269 }
270 } while (
271 specialMissionTypes.indexOf(missionIndex) != -1 &&
272 sortieTilesets[node as keyof typeof sortieTilesets] !=
273 sortieFactionToSpecialMissionTileset[sortieBossToFaction[boss]]
274 );
257 const randomIndex = rng.randomInt(0, nodes.length - 1);
258 const node = nodes[randomIndex];
275 259
276 260 const modifiers = [
277 261 "SORTIE_MODIFIER_LOW_ENERGY",
@@ -294,28 +278,10 @@ export const getSortie = (day: number): ISortie => {
294 278 "SORTIE_MODIFIER_RIFLE_ONLY",
295 279 "SORTIE_MODIFIER_BOW_ONLY"
296 280 ];
297 const pushTilesetModifiers = (tileset: string): void => {
298 switch (tileset) {
299 case "GrineerForestTileset":
300 modifiers.push("SORTIE_MODIFIER_HAZARD_FOG");
301 break;
302 case "CorpusShipTileset":
303 case "GrineerGalleonTileset":
304 case "InfestedCorpusShipTileset":
305 modifiers.push("SORTIE_MODIFIER_HAZARD_MAGNETIC");
306 modifiers.push("SORTIE_MODIFIER_HAZARD_FIRE");
307 modifiers.push("SORTIE_MODIFIER_HAZARD_ICE");
308 break;
309 case "CorpusIcePlanetTileset":
310 case "CorpusIcePlanetTilesetCaves":
311 modifiers.push("SORTIE_MODIFIER_HAZARD_COLD");
312 break;
313 }
314 };
315 281
316 282 if (i == 2 && boss != "SORTIE_BOSS_CORRUPTED_VOR" && rng.randomInt(0, 2) == 2) {
317 const tileset = sortieTilesets[sortieBossNode[boss] as keyof typeof sortieTilesets];
318 pushTilesetModifiers(tileset);
283 const tileset = sortieTilesets[sortieBossNode[boss] as keyof typeof sortieTilesets] as TSortieTileset;
284 pushTilesetModifiers(modifiers, tileset);
319 285
320 286 const modifierType = rng.randomElement(modifiers)!;
321 287
@@ -328,9 +294,12 @@ export const getSortie = (day: number): ISortie => {
328 294 continue;
329 295 }
330 296
331 const missionType = eMissionType[missionIndex].tag;
297 const tileset = sortieTilesets[node as keyof typeof sortieTilesets] as TSortieTileset;
298 pushTilesetModifiers(modifiers, tileset);
332 299
333 if (missionTypes.has(missionType)) {
300 const missionType = rng.randomElement(sortieTilesetMissions[tileset])!;
301
302 if (missionTypes.has(missionType) || missionType == "MT_ASSASSINATION") {
334 303 i--;
335 304 continue;
336 305 }
@@ -349,9 +318,6 @@ export const getSortie = (day: number): ISortie => {
349 318 modifiers.push("SORTIE_MODIFIER_SHIELDS");
350 319 }
351 320
352 const tileset = sortieTilesets[node as keyof typeof sortieTilesets];
353 pushTilesetModifiers(tileset);
354
355 321 const modifierType = rng.randomElement(modifiers)!;
356 322
357 323 selectedNodes.push({
Added static/fixed_responses/worldState/sortieTilesetMissions.json +45 -0
@@ -0,0 +1,45 @@
1 {
2 "CorpusGasCityTileset": ["MT_ARTIFACT", "MT_ASSASSINATION", "MT_DEFENSE", "MT_EXTERMINATION", "MT_INTEL", "MT_MOBILE_DEFENSE", "MT_RESCUE", "MT_SABOTAGE", "MT_SURVIVAL", "MT_TERRITORY"],
3 "CorpusIcePlanetTileset": ["MT_ASSASSINATION", "MT_DEFENSE", "MT_EXCAVATE", "MT_INTEL", "MT_MOBILE_DEFENSE", "MT_RESCUE", "MT_RETRIEVAL", "MT_TERRITORY"],
4 "CorpusIcePlanetTilesetCaves": ["MT_EXTERMINATION", "MT_INTEL"],
5 "CorpusOutpostTileset": [
6 "MT_ARTIFACT",
7 "MT_ASSASSINATION",
8 "MT_DEFENSE",
9 "MT_EXCAVATE",
10 "MT_EXTERMINATION",
11 "MT_INTEL",
12 "MT_MOBILE_DEFENSE",
13 "MT_RESCUE",
14 "MT_SABOTAGE",
15 "MT_SURVIVAL",
16 "MT_TERRITORY"
17 ],
18 "CorpusShipTileset": ["MT_ARTIFACT", "MT_ASSASSINATION", "MT_DEFENSE", "MT_EXTERMINATION", "MT_INTEL", "MT_MOBILE_DEFENSE", "MT_RESCUE", "MT_SABOTAGE", "MT_SURVIVAL", "MT_TERRITORY"],
19 "EidolonTileset": ["MT_LANDSCAPE"],
20 "GrineerAsteroidTileset": ["MT_ASSASSINATION", "MT_DEFENSE", "MT_EVACUATION", "MT_EXTERMINATION", "MT_INTEL", "MT_MOBILE_DEFENSE", "MT_RESCUE", "MT_SURVIVAL", "MT_TERRITORY"],
21 "GrineerForestTileset": ["MT_ASSASSINATION", "MT_EXTERMINATION", "MT_INTEL", "MT_MOBILE_DEFENSE", "MT_TERRITORY"],
22 "GrineerFortressTileset": ["MT_ARTIFACT", "MT_ASSAULT", "MT_INTEL", "MT_MOBILE_DEFENSE", "MT_RESCUE", "MT_SURVIVAL"],
23 "GrineerGalleonTileset": [
24 "MT_ARTIFACT",
25 "MT_ASSASSINATION",
26 "MT_DEFENSE",
27 "MT_EVACUATION",
28 "MT_EXTERMINATION",
29 "MT_INTEL",
30 "MT_MOBILE_DEFENSE",
31 "MT_RESCUE",
32 "MT_SABOTAGE",
33 "MT_SURVIVAL",
34 "MT_TERRITORY"
35 ],
36 "GrineerOceanTileset": ["MT_DEFENSE", "MT_EXTERMINATION", "MT_INTEL", "MT_MOBILE_DEFENSE", "MT_RESCUE", "MT_SABOTAGE", "MT_SURVIVAL", "MT_TERRITORY"],
37 "GrineerOceanTilesetAnywhere": ["MT_ASSASSINATION"],
38 "GrineerSettlementTileset": ["MT_ASSASSINATION", "MT_DEFENSE", "MT_EXTERMINATION", "MT_INTEL", "MT_MOBILE_DEFENSE", "MT_RESCUE", "MT_SABOTAGE", "MT_TERRITORY"],
39 "GrineerShipyardsTileset": ["MT_DEFENSE", "MT_EXTERMINATION", "MT_INTEL", "MT_MOBILE_DEFENSE", "MT_RESCUE", "MT_RETRIEVAL", "MT_TERRITORY"],
40 "InfestedCorpusShipTileset": ["MT_ASSASSINATION", "MT_HIVE", "MT_MOBILE_DEFENSE", "MT_RESCUE"],
41 "OrokinDerelictTileset": ["MT_ARTIFACT", "MT_ASSASSINATION", "MT_DEFENSE", "MT_EXTERMINATION", "MT_MOBILE_DEFENSE", "MT_SABOTAGE", "MT_SURVIVAL"],
42 "OrokinMoonTilesetCorpus": ["MT_ARTIFACT", "MT_DEFENSE", "MT_EXTERMINATION", "MT_MOBILE_DEFENSE", "MT_RESCUE", "MT_SURVIVAL"],
43 "OrokinMoonTilesetGrineer": ["MT_DEFENSE", "MT_EXTERMINATION", "MT_MOBILE_DEFENSE", "MT_RESCUE", "MT_SURVIVAL"],
44 "OrokinVoidTileset": ["MT_DEFENSE", "MT_EXTERMINATION", "MT_MOBILE_DEFENSE", "MT_SABOTAGE", "MT_SURVIVAL", "MT_TERRITORY"]
45 }