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: provide upcoming bounties in worldState when new cycle is imminent (#1657)

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

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

代码差异

3 个文件 +343 -373
Modified src/services/worldStateService.ts +340 -129
@@ -9,7 +9,6 @@ import { config } from "@/src/services/configService";
9 9 import { CRng } from "@/src/services/rngService";
10 10 import { eMissionType, ExportNightwave, ExportRegions } from "warframe-public-export-plus";
11 11 import { ISeasonChallenge, IWorldState } from "../types/worldStateTypes";
12 import { logger } from "../utils/logger";
13 12
14 13 const sortieBosses = [
15 14 "SORTIE_BOSS_HYENA",
@@ -80,73 +79,76 @@ const sortieBossNode: Record<string, string> = {
80 79 SORTIE_BOSS_INFALAD: "SolNode705"
81 80 };
82 81
83 const jobSets: string[][] = [
84 [
85 "/Lotus/Types/Gameplay/Eidolon/Jobs/AssassinateBountyAss",
86 "/Lotus/Types/Gameplay/Eidolon/Jobs/AssassinateBountyCap",
87 "/Lotus/Types/Gameplay/Eidolon/Jobs/AttritionBountySab",
88 "/Lotus/Types/Gameplay/Eidolon/Jobs/AttritionBountyLib",
89 "/Lotus/Types/Gameplay/Eidolon/Jobs/AttritionBountyCap",
90 "/Lotus/Types/Gameplay/Eidolon/Jobs/AttritionBountyExt",
91 "/Lotus/Types/Gameplay/Eidolon/Jobs/ReclamationBountyCap",
92 "/Lotus/Types/Gameplay/Eidolon/Jobs/ReclamationBountyTheft",
93 "/Lotus/Types/Gameplay/Eidolon/Jobs/ReclamationBountyCache",
94 "/Lotus/Types/Gameplay/Eidolon/Jobs/CaptureBountyCapOne",
95 "/Lotus/Types/Gameplay/Eidolon/Jobs/CaptureBountyCapTwo",
96 "/Lotus/Types/Gameplay/Eidolon/Jobs/SabotageBountySab",
97 "/Lotus/Types/Gameplay/Eidolon/Jobs/RescueBountyResc"
98 ],
99 [
100 "/Lotus/Types/Gameplay/Eidolon/Jobs/Narmer/AssassinateBountyAss",
101 "/Lotus/Types/Gameplay/Eidolon/Jobs/Narmer/AttritionBountyExt",
102 "/Lotus/Types/Gameplay/Eidolon/Jobs/Narmer/ReclamationBountyTheft",
103 "/Lotus/Types/Gameplay/Eidolon/Jobs/Narmer/AttritionBountyLib"
104 ],
105 [
106 "/Lotus/Types/Gameplay/Venus/Jobs/VenusArtifactJobAmbush",
107 "/Lotus/Types/Gameplay/Venus/Jobs/VenusArtifactJobExcavation",
108 "/Lotus/Types/Gameplay/Venus/Jobs/VenusArtifactJobRecovery",
109 "/Lotus/Types/Gameplay/Venus/Jobs/VenusChaosJobAssassinate",
110 "/Lotus/Types/Gameplay/Venus/Jobs/VenusChaosJobExcavation",
111 "/Lotus/Types/Gameplay/Venus/Jobs/VenusCullJobAssassinate",
112 "/Lotus/Types/Gameplay/Venus/Jobs/VenusCullJobExterminate",
113 "/Lotus/Types/Gameplay/Venus/Jobs/VenusCullJobResource",
114 "/Lotus/Types/Gameplay/Venus/Jobs/VenusIntelJobRecovery",
115 "/Lotus/Types/Gameplay/Venus/Jobs/VenusIntelJobResource",
116 "/Lotus/Types/Gameplay/Venus/Jobs/VenusIntelJobSpy",
117 "/Lotus/Types/Gameplay/Venus/Jobs/VenusSpyJobSpy",
118 "/Lotus/Types/Gameplay/Venus/Jobs/VenusTheftJobAmbush",
119 "/Lotus/Types/Gameplay/Venus/Jobs/VenusTheftJobExcavation",
120 "/Lotus/Types/Gameplay/Venus/Jobs/VenusTheftJobResource",
121 "/Lotus/Types/Gameplay/Venus/Jobs/VenusHelpingJobCaches",
122 "/Lotus/Types/Gameplay/Venus/Jobs/VenusHelpingJobResource",
123 "/Lotus/Types/Gameplay/Venus/Jobs/VenusHelpingJobSpy",
124 "/Lotus/Types/Gameplay/Venus/Jobs/VenusPreservationJobDefense",
125 "/Lotus/Types/Gameplay/Venus/Jobs/VenusPreservationJobRecovery",
126 "/Lotus/Types/Gameplay/Venus/Jobs/VenusPreservationJobResource",
127 "/Lotus/Types/Gameplay/Venus/Jobs/VenusWetworkJobAssassinate",
128 "/Lotus/Types/Gameplay/Venus/Jobs/VenusWetworkJobSpy"
129 ],
130 [
131 "/Lotus/Types/Gameplay/Venus/Jobs/Narmer/NarmerVenusCullJobAssassinate",
132 "/Lotus/Types/Gameplay/Venus/Jobs/Narmer/NarmerVenusCullJobExterminate",
133 "/Lotus/Types/Gameplay/Venus/Jobs/Narmer/NarmerVenusPreservationJobDefense",
134 "/Lotus/Types/Gameplay/Venus/Jobs/Narmer/NarmerVenusTheftJobExcavation"
135 ],
136 [
137 "/Lotus/Types/Gameplay/InfestedMicroplanet/Jobs/DeimosAreaDefenseBounty",
138 "/Lotus/Types/Gameplay/InfestedMicroplanet/Jobs/DeimosAssassinateBounty",
139 "/Lotus/Types/Gameplay/InfestedMicroplanet/Jobs/DeimosCrpSurvivorBounty",
140 "/Lotus/Types/Gameplay/InfestedMicroplanet/Jobs/DeimosGrnSurvivorBounty",
141 "/Lotus/Types/Gameplay/InfestedMicroplanet/Jobs/DeimosKeyPiecesBounty",
142 "/Lotus/Types/Gameplay/InfestedMicroplanet/Jobs/DeimosExcavateBounty",
143 "/Lotus/Types/Gameplay/InfestedMicroplanet/Jobs/DeimosPurifyBounty"
144 ],
145 [
146 "/Lotus/Types/Gameplay/InfestedMicroplanet/Jobs/DeimosEndlessAreaDefenseBounty",
147 "/Lotus/Types/Gameplay/InfestedMicroplanet/Jobs/DeimosEndlessExcavateBounty",
148 "/Lotus/Types/Gameplay/InfestedMicroplanet/Jobs/DeimosEndlessPurifyBounty"
149 ]
82 const eidolonJobs = [
83 "/Lotus/Types/Gameplay/Eidolon/Jobs/AssassinateBountyAss",
84 "/Lotus/Types/Gameplay/Eidolon/Jobs/AssassinateBountyCap",
85 "/Lotus/Types/Gameplay/Eidolon/Jobs/AttritionBountySab",
86 "/Lotus/Types/Gameplay/Eidolon/Jobs/AttritionBountyLib",
87 "/Lotus/Types/Gameplay/Eidolon/Jobs/AttritionBountyCap",
88 "/Lotus/Types/Gameplay/Eidolon/Jobs/AttritionBountyExt",
89 "/Lotus/Types/Gameplay/Eidolon/Jobs/ReclamationBountyCap",
90 "/Lotus/Types/Gameplay/Eidolon/Jobs/ReclamationBountyTheft",
91 "/Lotus/Types/Gameplay/Eidolon/Jobs/ReclamationBountyCache",
92 "/Lotus/Types/Gameplay/Eidolon/Jobs/CaptureBountyCapOne",
93 "/Lotus/Types/Gameplay/Eidolon/Jobs/CaptureBountyCapTwo",
94 "/Lotus/Types/Gameplay/Eidolon/Jobs/SabotageBountySab",
95 "/Lotus/Types/Gameplay/Eidolon/Jobs/RescueBountyResc"
96 ];
97
98 const eidolonNarmerJobs = [
99 "/Lotus/Types/Gameplay/Eidolon/Jobs/Narmer/AssassinateBountyAss",
100 "/Lotus/Types/Gameplay/Eidolon/Jobs/Narmer/AttritionBountyExt",
101 "/Lotus/Types/Gameplay/Eidolon/Jobs/Narmer/ReclamationBountyTheft",
102 "/Lotus/Types/Gameplay/Eidolon/Jobs/Narmer/AttritionBountyLib"
103 ];
104
105 const venusJobs = [
106 "/Lotus/Types/Gameplay/Venus/Jobs/VenusArtifactJobAmbush",
107 "/Lotus/Types/Gameplay/Venus/Jobs/VenusArtifactJobExcavation",
108 "/Lotus/Types/Gameplay/Venus/Jobs/VenusArtifactJobRecovery",
109 "/Lotus/Types/Gameplay/Venus/Jobs/VenusChaosJobAssassinate",
110 "/Lotus/Types/Gameplay/Venus/Jobs/VenusChaosJobExcavation",
111 "/Lotus/Types/Gameplay/Venus/Jobs/VenusCullJobAssassinate",
112 "/Lotus/Types/Gameplay/Venus/Jobs/VenusCullJobExterminate",
113 "/Lotus/Types/Gameplay/Venus/Jobs/VenusCullJobResource",
114 "/Lotus/Types/Gameplay/Venus/Jobs/VenusIntelJobRecovery",
115 "/Lotus/Types/Gameplay/Venus/Jobs/VenusIntelJobResource",
116 "/Lotus/Types/Gameplay/Venus/Jobs/VenusIntelJobSpy",
117 "/Lotus/Types/Gameplay/Venus/Jobs/VenusSpyJobSpy",
118 "/Lotus/Types/Gameplay/Venus/Jobs/VenusTheftJobAmbush",
119 "/Lotus/Types/Gameplay/Venus/Jobs/VenusTheftJobExcavation",
120 "/Lotus/Types/Gameplay/Venus/Jobs/VenusTheftJobResource",
121 "/Lotus/Types/Gameplay/Venus/Jobs/VenusHelpingJobCaches",
122 "/Lotus/Types/Gameplay/Venus/Jobs/VenusHelpingJobResource",
123 "/Lotus/Types/Gameplay/Venus/Jobs/VenusHelpingJobSpy",
124 "/Lotus/Types/Gameplay/Venus/Jobs/VenusPreservationJobDefense",
125 "/Lotus/Types/Gameplay/Venus/Jobs/VenusPreservationJobRecovery",
126 "/Lotus/Types/Gameplay/Venus/Jobs/VenusPreservationJobResource",
127 "/Lotus/Types/Gameplay/Venus/Jobs/VenusWetworkJobAssassinate",
128 "/Lotus/Types/Gameplay/Venus/Jobs/VenusWetworkJobSpy"
129 ];
130
131 const venusNarmerJobs = [
132 "/Lotus/Types/Gameplay/Venus/Jobs/Narmer/NarmerVenusCullJobAssassinate",
133 "/Lotus/Types/Gameplay/Venus/Jobs/Narmer/NarmerVenusCullJobExterminate",
134 "/Lotus/Types/Gameplay/Venus/Jobs/Narmer/NarmerVenusPreservationJobDefense",
135 "/Lotus/Types/Gameplay/Venus/Jobs/Narmer/NarmerVenusTheftJobExcavation"
136 ];
137
138 const microplanetJobs = [
139 "/Lotus/Types/Gameplay/InfestedMicroplanet/Jobs/DeimosAreaDefenseBounty",
140 "/Lotus/Types/Gameplay/InfestedMicroplanet/Jobs/DeimosAssassinateBounty",
141 "/Lotus/Types/Gameplay/InfestedMicroplanet/Jobs/DeimosCrpSurvivorBounty",
142 "/Lotus/Types/Gameplay/InfestedMicroplanet/Jobs/DeimosGrnSurvivorBounty",
143 "/Lotus/Types/Gameplay/InfestedMicroplanet/Jobs/DeimosKeyPiecesBounty",
144 "/Lotus/Types/Gameplay/InfestedMicroplanet/Jobs/DeimosExcavateBounty",
145 "/Lotus/Types/Gameplay/InfestedMicroplanet/Jobs/DeimosPurifyBounty"
146 ];
147
148 const microplanetEndlessJobs = [
149 "/Lotus/Types/Gameplay/InfestedMicroplanet/Jobs/DeimosEndlessAreaDefenseBounty",
150 "/Lotus/Types/Gameplay/InfestedMicroplanet/Jobs/DeimosEndlessExcavateBounty",
151 "/Lotus/Types/Gameplay/InfestedMicroplanet/Jobs/DeimosEndlessPurifyBounty"
150 152 ];
151 153
152 154 const EPOCH = 1734307200 * 1000; // Monday, Dec 16, 2024 @ 00:00 UTC+0; should logically be winter in 1999 iteration 0
@@ -218,6 +220,10 @@ const getSeasonWeeklyHardChallenge = (week: number, id: number): ISeasonChalleng
218 220 };
219 221 };
220 222
223 const expiresBeforeNextExpectedWorldStateRefresh = (date: number): boolean => {
224 return Date.now() + 300_000 > date;
225 };
226
221 227 export const getWorldState = (buildLabel?: string): IWorldState => {
222 228 const day = Math.trunc((Date.now() - EPOCH) / 86400000);
223 229 const week = Math.trunc(day / 7);
@@ -228,9 +234,10 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
228 234 BuildLabel: typeof buildLabel == "string" ? buildLabel.split(" ").join("+") : buildConfig.buildLabel,
229 235 Time: config.worldState?.lockTime || Math.round(Date.now() / 1000),
230 236 Goals: [],
231 GlobalUpgrades: [],
237 Alerts: [],
232 238 Sorties: [],
233 239 LiteSorties: [],
240 GlobalUpgrades: [],
234 241 EndlessXpChoices: [],
235 242 SeasonInfo: {
236 243 Activation: { $date: { $numberLong: "1715796000000" } },
@@ -268,7 +275,8 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
268 275 }
269 276 ]
270 277 },
271 ...staticWorldState
278 ...staticWorldState,
279 SyndicateMissions: [...staticWorldState.SyndicateMissions]
272 280 };
273 281
274 282 if (config.worldState?.starDays) {
@@ -292,69 +300,272 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
292 300 worldState.NodeOverrides.find(x => x.Node == "SolNode802")!.Seed = week; // unfaithful
293 301
294 302 // Holdfast, Cavia, & Hex bounties cycling every 2.5 hours; unfaithful implementation
295 const bountyCycle = Math.trunc(Date.now() / 9000000);
296 const bountyCycleStart = bountyCycle * 9000000;
297 const bountyCycleEnd = bountyCycleStart + 9000000;
298 worldState.SyndicateMissions[worldState.SyndicateMissions.findIndex(x => x.Tag == "ZarimanSyndicate")] = {
299 _id: { $oid: Math.trunc(bountyCycleStart / 1000).toString(16) + "0000000000000029" },
300 Activation: { $date: { $numberLong: bountyCycleStart.toString() } },
301 Expiry: { $date: { $numberLong: bountyCycleEnd.toString() } },
302 Tag: "ZarimanSyndicate",
303 Seed: bountyCycle,
304 Nodes: []
305 };
306 worldState.SyndicateMissions[worldState.SyndicateMissions.findIndex(x => x.Tag == "EntratiLabSyndicate")] = {
307 _id: { $oid: Math.trunc(bountyCycleStart / 1000).toString(16) + "0000000000000004" },
308 Activation: { $date: { $numberLong: bountyCycleStart.toString() } },
309 Expiry: { $date: { $numberLong: bountyCycleEnd.toString() } },
310 Tag: "EntratiLabSyndicate",
311 Seed: bountyCycle,
312 Nodes: []
313 };
314 worldState.SyndicateMissions[worldState.SyndicateMissions.findIndex(x => x.Tag == "HexSyndicate")] = {
315 _id: { $oid: Math.trunc(bountyCycleStart / 1000).toString(16) + "0000000000000006" },
316 Activation: { $date: { $numberLong: bountyCycleStart.toString(10) } },
317 Expiry: { $date: { $numberLong: bountyCycleEnd.toString(10) } },
318 Tag: "HexSyndicate",
319 Seed: bountyCycle,
320 Nodes: []
321 };
322 for (const syndicateInfo of worldState.SyndicateMissions) {
323 if (syndicateInfo.Jobs && syndicateInfo.Seed != bountyCycle) {
324 syndicateInfo.Activation.$date.$numberLong = bountyCycleStart.toString(10);
325 syndicateInfo.Expiry.$date.$numberLong = bountyCycleEnd.toString(10);
326 syndicateInfo.Seed = bountyCycle;
327 logger.debug(`refreshing jobs for ${syndicateInfo.Tag}`);
303 let bountyCycle = Math.trunc(Date.now() / 9000000);
304 let bountyCycleEnd: number | undefined;
305 do {
306 const bountyCycleStart = bountyCycle * 9000000;
307 bountyCycleEnd = bountyCycleStart + 9000000;
308 worldState.SyndicateMissions.push({
309 _id: { $oid: Math.trunc(bountyCycleStart / 1000).toString(16) + "0000000000000029" },
310 Activation: { $date: { $numberLong: bountyCycleStart.toString() } },
311 Expiry: { $date: { $numberLong: bountyCycleEnd.toString() } },
312 Tag: "ZarimanSyndicate",
313 Seed: bountyCycle,
314 Nodes: []
315 });
316 worldState.SyndicateMissions.push({
317 _id: { $oid: Math.trunc(bountyCycleStart / 1000).toString(16) + "0000000000000004" },
318 Activation: { $date: { $numberLong: bountyCycleStart.toString() } },
319 Expiry: { $date: { $numberLong: bountyCycleEnd.toString() } },
320 Tag: "EntratiLabSyndicate",
321 Seed: bountyCycle,
322 Nodes: []
323 });
324 worldState.SyndicateMissions.push({
325 _id: { $oid: Math.trunc(bountyCycleStart / 1000).toString(16) + "0000000000000006" },
326 Activation: { $date: { $numberLong: bountyCycleStart.toString(10) } },
327 Expiry: { $date: { $numberLong: bountyCycleEnd.toString(10) } },
328 Tag: "HexSyndicate",
329 Seed: bountyCycle,
330 Nodes: []
331 });
332
333 const table = String.fromCharCode(65 + (bountyCycle % 3));
334 const vaultTable = String.fromCharCode(65 + ((bountyCycle + 1) % 3));
335 const deimosDTable = String.fromCharCode(65 + (bountyCycle % 2));
336
337 // TODO: xpAmounts need to be calculated based on the jobType somehow?
338
339 {
328 340 const rng = new CRng(bountyCycle);
329 const table = String.fromCharCode(65 + (bountyCycle % 3));
330 const vaultTable = String.fromCharCode(65 + ((bountyCycle + 1) % 3));
331 const deimosDTable = String.fromCharCode(65 + (bountyCycle % 2));
332 //console.log({ bountyCycleStart, bountyCycleEnd, table, vaultTable, deimosDTable });
333 for (const jobInfo of syndicateInfo.Jobs) {
334 if (jobInfo.jobType) {
335 let found = false;
336 for (const jobSet of jobSets) {
337 if (jobSet.indexOf(jobInfo.jobType) != -1) {
338 jobInfo.jobType = rng.randomElement(jobSet);
339 // TODO: xpAmounts seems like it might need to differ depending on the job?
340 found = true;
341 break;
342 }
341 worldState.SyndicateMissions.push({
342 _id: { $oid: Math.trunc(bountyCycleStart / 1000).toString(16) + "0000000000000008" },
343 Activation: { $date: { $numberLong: bountyCycleStart.toString(10) } },
344 Expiry: { $date: { $numberLong: bountyCycleEnd.toString(10) } },
345 Tag: "CetusSyndicate",
346 Seed: bountyCycle,
347 Nodes: [],
348 Jobs: [
349 {
350 jobType: rng.randomElement(eidolonJobs),
351 rewards: `/Lotus/Types/Game/MissionDecks/EidolonJobMissionRewards/TierATable${table}Rewards`,
352 masteryReq: 0,
353 minEnemyLevel: 5,
354 maxEnemyLevel: 15,
355 xpAmounts: [430, 430, 430]
356 },
357 {
358 jobType: rng.randomElement(eidolonJobs),
359 rewards: `/Lotus/Types/Game/MissionDecks/EidolonJobMissionRewards/TierBTable${table}Rewards`,
360 masteryReq: 1,
361 minEnemyLevel: 10,
362 maxEnemyLevel: 30,
363 xpAmounts: [620, 620, 620]
364 },
365 {
366 jobType: rng.randomElement(eidolonJobs),
367 rewards: `/Lotus/Types/Game/MissionDecks/EidolonJobMissionRewards/TierCTable${table}Rewards`,
368 masteryReq: 2,
369 minEnemyLevel: 20,
370 maxEnemyLevel: 40,
371 xpAmounts: [670, 670, 670, 990]
372 },
373 {
374 jobType: rng.randomElement(eidolonJobs),
375 rewards: `/Lotus/Types/Game/MissionDecks/EidolonJobMissionRewards/TierDTable${table}Rewards`,
376 masteryReq: 3,
377 minEnemyLevel: 30,
378 maxEnemyLevel: 50,
379 xpAmounts: [570, 570, 570, 570, 1110]
380 },
381 {
382 jobType: rng.randomElement(eidolonJobs),
383 rewards: `/Lotus/Types/Game/MissionDecks/EidolonJobMissionRewards/TierETable${table}Rewards`,
384 masteryReq: 5,
385 minEnemyLevel: 40,
386 maxEnemyLevel: 60,
387 xpAmounts: [740, 740, 740, 740, 1450]
388 },
389 {
390 jobType: rng.randomElement(eidolonJobs),
391 rewards: `/Lotus/Types/Game/MissionDecks/EidolonJobMissionRewards/TierETable${table}Rewards`,
392 masteryReq: 10,
393 minEnemyLevel: 100,
394 maxEnemyLevel: 100,
395 xpAmounts: [840, 840, 840, 840, 1660]
396 },
397 {
398 jobType: rng.randomElement(eidolonNarmerJobs),
399 rewards: `/Lotus/Types/Game/MissionDecks/EidolonJobMissionRewards/NarmerTable${table}Rewards`,
400 masteryReq: 0,
401 minEnemyLevel: 50,
402 maxEnemyLevel: 70,
403 xpAmounts: [840, 840, 840, 840, 1650]
343 404 }
344 if (!found) {
345 logger.warn(`no job set found for type ${jobInfo.jobType}`);
405 ]
406 });
407 }
408
409 {
410 const rng = new CRng(bountyCycle);
411 worldState.SyndicateMissions.push({
412 _id: { $oid: Math.trunc(bountyCycleStart / 1000).toString(16) + "0000000000000025" },
413 Activation: { $date: { $numberLong: bountyCycleStart.toString(10) } },
414 Expiry: { $date: { $numberLong: bountyCycleEnd.toString(10) } },
415 Tag: "SolarisSyndicate",
416 Seed: bountyCycle,
417 Nodes: [],
418 Jobs: [
419 {
420 jobType: rng.randomElement(venusJobs),
421 rewards: `Lotus/Types/Game/MissionDecks/VenusJobMissionRewards/VenusTierATable${table}Rewards`,
422 masteryReq: 0,
423 minEnemyLevel: 5,
424 maxEnemyLevel: 15,
425 xpAmounts: [340, 340, 340]
426 },
427 {
428 jobType: rng.randomElement(venusJobs),
429 rewards: `Lotus/Types/Game/MissionDecks/VenusJobMissionRewards/VenusTierBTable${table}Rewards`,
430 masteryReq: 1,
431 minEnemyLevel: 10,
432 maxEnemyLevel: 30,
433 xpAmounts: [660, 660, 660]
434 },
435 {
436 jobType: rng.randomElement(venusJobs),
437 rewards: `Lotus/Types/Game/MissionDecks/VenusJobMissionRewards/VenusTierCTable${table}Rewards`,
438 masteryReq: 2,
439 minEnemyLevel: 20,
440 maxEnemyLevel: 40,
441 xpAmounts: [610, 610, 610, 900]
442 },
443 {
444 jobType: rng.randomElement(venusJobs),
445 rewards: `Lotus/Types/Game/MissionDecks/VenusJobMissionRewards/VenusTierDTable${table}Rewards`,
446 masteryReq: 3,
447 minEnemyLevel: 30,
448 maxEnemyLevel: 50,
449 xpAmounts: [600, 600, 600, 600, 1170]
450 },
451 {
452 jobType: rng.randomElement(venusJobs),
453 rewards: `Lotus/Types/Game/MissionDecks/VenusJobMissionRewards/VenusTierETable${table}Rewards`,
454 masteryReq: 5,
455 minEnemyLevel: 40,
456 maxEnemyLevel: 60,
457 xpAmounts: [690, 690, 690, 690, 1350]
458 },
459 {
460 jobType: rng.randomElement(venusJobs),
461 rewards: `Lotus/Types/Game/MissionDecks/VenusJobMissionRewards/VenusTierETable${table}Rewards`,
462 masteryReq: 10,
463 minEnemyLevel: 100,
464 maxEnemyLevel: 100,
465 xpAmounts: [840, 840, 840, 840, 1660]
466 },
467 {
468 jobType: rng.randomElement(venusNarmerJobs),
469 rewards: "/Lotus/Types/Game/MissionDecks/EidolonJobMissionRewards/NarmerTableBRewards",
470 masteryReq: 0,
471 minEnemyLevel: 50,
472 maxEnemyLevel: 70,
473 xpAmounts: [780, 780, 780, 780, 1540]
346 474 }
347 }
348 if (jobInfo.endless || jobInfo.isVault) {
349 jobInfo.rewards = jobInfo.rewards.replace(/Table.Rewards/, `Table${vaultTable}Rewards`);
350 } else if (jobInfo.rewards.startsWith("/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/TierD")) {
351 jobInfo.rewards = jobInfo.rewards.replace(/Table.Rewards/, `Table${deimosDTable}Rewards`);
352 } else if (!jobInfo.rewards.startsWith("/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/TierE")) {
353 jobInfo.rewards = jobInfo.rewards.replace(/Table.Rewards/, `Table${table}Rewards`);
354 }
355 }
475 ]
476 });
356 477 }
357 }
478
479 {
480 const rng = new CRng(bountyCycle);
481 worldState.SyndicateMissions.push({
482 _id: { $oid: Math.trunc(bountyCycleStart / 1000).toString(16) + "0000000000000002" },
483 Activation: { $date: { $numberLong: bountyCycleStart.toString(10) } },
484 Expiry: { $date: { $numberLong: bountyCycleEnd.toString(10) } },
485 Tag: "EntratiSyndicate",
486 Seed: bountyCycle,
487 Nodes: [],
488 Jobs: [
489 {
490 jobType: rng.randomElement(microplanetJobs),
491 rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/TierATable${table}Rewards`,
492 masteryReq: 0,
493 minEnemyLevel: 5,
494 maxEnemyLevel: 15,
495 xpAmounts: [5, 5, 5]
496 },
497 {
498 jobType: rng.randomElement(microplanetJobs),
499 rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/TierCTable${table}Rewards`,
500 masteryReq: 1,
501 minEnemyLevel: 15,
502 maxEnemyLevel: 25,
503 xpAmounts: [12, 12, 12]
504 },
505 {
506 jobType: rng.randomElement(microplanetEndlessJobs),
507 rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/TierBTable${table}Rewards`,
508 masteryReq: 5,
509 minEnemyLevel: 25,
510 maxEnemyLevel: 30,
511 endless: true,
512 xpAmounts: [14, 14, 14]
513 },
514 {
515 jobType: rng.randomElement(microplanetJobs),
516 rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/TierDTable${deimosDTable}Rewards`,
517 masteryReq: 2,
518 minEnemyLevel: 30,
519 maxEnemyLevel: 40,
520 xpAmounts: [17, 17, 17, 25]
521 },
522 {
523 jobType: rng.randomElement(microplanetJobs),
524 rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/TierETableARewards`,
525 masteryReq: 3,
526 minEnemyLevel: 40,
527 maxEnemyLevel: 60,
528 xpAmounts: [22, 22, 22, 22, 43]
529 },
530 {
531 jobType: rng.randomElement(microplanetJobs),
532 rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/TierETableARewards`,
533 masteryReq: 10,
534 minEnemyLevel: 100,
535 maxEnemyLevel: 100,
536 xpAmounts: [25, 25, 25, 25, 50]
537 },
538 {
539 rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/VaultBountyTierATable${vaultTable}Rewards`,
540 masteryReq: 5,
541 minEnemyLevel: 30,
542 maxEnemyLevel: 40,
543 xpAmounts: [2, 2, 2, 4],
544 locationTag: "ChamberB",
545 isVault: true
546 },
547 {
548 rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/VaultBountyTierBTable${vaultTable}Rewards`,
549 masteryReq: 5,
550 minEnemyLevel: 40,
551 maxEnemyLevel: 50,
552 xpAmounts: [4, 4, 4, 5],
553 locationTag: "ChamberA",
554 isVault: true
555 },
556 {
557 rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/VaultBountyTierCTable${vaultTable}Rewards`,
558 masteryReq: 5,
559 minEnemyLevel: 50,
560 maxEnemyLevel: 60,
561 xpAmounts: [5, 5, 5, 7],
562 locationTag: "ChamberC",
563 isVault: true
564 }
565 ]
566 });
567 }
568 } while (expiresBeforeNextExpectedWorldStateRefresh(bountyCycleEnd) && ++bountyCycle);
358 569
359 570 if (config.worldState?.creditBoost) {
360 571 worldState.GlobalUpgrades.push({
Modified src/types/worldStateTypes.ts +3 -2
@@ -5,10 +5,11 @@ export interface IWorldState {
5 5 BuildLabel: string;
6 6 Time: number;
7 7 Goals: IGoal[];
8 SyndicateMissions: ISyndicateMissionInfo[];
9 GlobalUpgrades: IGlobalUpgrade[];
8 Alerts: [];
10 9 Sorties: ISortie[];
11 10 LiteSorties: ILiteSortie[];
11 SyndicateMissions: ISyndicateMissionInfo[];
12 GlobalUpgrades: IGlobalUpgrade[];
12 13 NodeOverrides: INodeOverride[];
13 14 EndlessXpChoices: IEndlessXpChoice[];
14 15 SeasonInfo: {
Modified static/fixed_responses/worldState/worldState.json +0 -242
@@ -278,248 +278,6 @@
278 278 "Tag": "SteelMeridianSyndicate",
279 279 "Seed": 42366,
280 280 "Nodes": ["SolNode27", "SolNode107", "SolNode214", "SettlementNode1", "SolNode177", "SolNode141", "SolNode408"]
281 },
282 {
283 "_id": { "$oid": "663a71c80000000000000002" },
284 "Activation": { "$date": { "$numberLong": "1715106248403" } },
285 "Expiry": { "$date": { "$numberLong": "2000000000000" } },
286 "Tag": "EntratiSyndicate",
287 "Seed": 99561,
288 "Nodes": [],
289 "Jobs": [
290 {
291 "jobType": "/Lotus/Types/Gameplay/InfestedMicroplanet/Jobs/DeimosGrnSurvivorBounty",
292 "rewards": "/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/TierATableBRewards",
293 "masteryReq": 0,
294 "minEnemyLevel": 5,
295 "maxEnemyLevel": 15,
296 "xpAmounts": [5, 5, 5]
297 },
298 {
299 "jobType": "/Lotus/Types/Gameplay/InfestedMicroplanet/Jobs/DeimosAreaDefenseBounty",
300 "rewards": "/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/TierCTableBRewards",
301 "masteryReq": 1,
302 "minEnemyLevel": 15,
303 "maxEnemyLevel": 25,
304 "xpAmounts": [12, 12, 12]
305 },
306 {
307 "jobType": "/Lotus/Types/Gameplay/InfestedMicroplanet/Jobs/DeimosEndlessExcavateBounty",
308 "rewards": "/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/TierBTableARewards",
309 "masteryReq": 5,
310 "minEnemyLevel": 25,
311 "maxEnemyLevel": 30,
312 "endless": true,
313 "xpAmounts": [14, 14, 14]
314 },
315 {
316 "jobType": "/Lotus/Types/Gameplay/InfestedMicroplanet/Jobs/DeimosAssassinateBounty",
317 "rewards": "/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/TierDTableBRewards",
318 "masteryReq": 2,
319 "minEnemyLevel": 30,
320 "maxEnemyLevel": 40,
321 "xpAmounts": [17, 17, 17, 25]
322 },
323 {
324 "jobType": "/Lotus/Types/Gameplay/InfestedMicroplanet/Jobs/DeimosKeyPiecesBounty",
325 "rewards": "/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/TierETableARewards",
326 "masteryReq": 3,
327 "minEnemyLevel": 40,
328 "maxEnemyLevel": 60,
329 "xpAmounts": [22, 22, 22, 22, 43]
330 },
331 {
332 "jobType": "/Lotus/Types/Gameplay/InfestedMicroplanet/Jobs/DeimosExcavateBounty",
333 "rewards": "/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/TierETableARewards",
334 "masteryReq": 10,
335 "minEnemyLevel": 100,
336 "maxEnemyLevel": 100,
337 "xpAmounts": [25, 25, 25, 25, 50]
338 },
339 {
340 "rewards": "/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/VaultBountyTierATableCRewards",
341 "masteryReq": 5,
342 "minEnemyLevel": 30,
343 "maxEnemyLevel": 40,
344 "xpAmounts": [2, 2, 2, 4],
345 "locationTag": "ChamberB",
346 "isVault": true
347 },
348 {
349 "rewards": "/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/VaultBountyTierBTableCRewards",
350 "masteryReq": 5,
351 "minEnemyLevel": 40,
352 "maxEnemyLevel": 50,
353 "xpAmounts": [4, 4, 4, 5],
354 "locationTag": "ChamberA",
355 "isVault": true
356 },
357 {
358 "rewards": "/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/VaultBountyTierCTableCRewards",
359 "masteryReq": 5,
360 "minEnemyLevel": 50,
361 "maxEnemyLevel": 60,
362 "xpAmounts": [5, 5, 5, 7],
363 "locationTag": "ChamberC",
364 "isVault": true
365 }
366 ]
367 },
368 {
369 "_id": { "$oid": "663a71c80000000000000004" },
370 "Activation": { "$date": { "$numberLong": "1715106248403" } },
371 "Expiry": { "$date": { "$numberLong": "2000000000000" } },
372 "Tag": "EntratiLabSyndicate",
373 "Seed": 99562,
374 "Nodes": []
375 },
376 {
377 "_id": { "$oid": "663a71c80000000000000008" },
378 "Activation": { "$date": { "$numberLong": "1715106248403" } },
379 "Expiry": { "$date": { "$numberLong": "2000000000000" } },
380 "Tag": "CetusSyndicate",
381 "Seed": 99561,
382 "Nodes": [],
383 "Jobs": [
384 {
385 "jobType": "/Lotus/Types/Gameplay/Eidolon/Jobs/AssassinateBountyCap",
386 "rewards": "/Lotus/Types/Game/MissionDecks/EidolonJobMissionRewards/TierATableBRewards",
387 "masteryReq": 0,
388 "minEnemyLevel": 5,
389 "maxEnemyLevel": 15,
390 "xpAmounts": [430, 430, 430]
391 },
392 {
393 "jobType": "/Lotus/Types/Gameplay/Eidolon/Jobs/AttritionBountyLib",
394 "rewards": "/Lotus/Types/Game/MissionDecks/EidolonJobMissionRewards/TierBTableBRewards",
395 "masteryReq": 1,
396 "minEnemyLevel": 10,
397 "maxEnemyLevel": 30,
398 "xpAmounts": [620, 620, 620]
399 },
400 {
401 "jobType": "/Lotus/Types/Gameplay/Eidolon/Jobs/RescueBountyResc",
402 "rewards": "/Lotus/Types/Game/MissionDecks/EidolonJobMissionRewards/TierCTableBRewards",
403 "masteryReq": 2,
404 "minEnemyLevel": 20,
405 "maxEnemyLevel": 40,
406 "xpAmounts": [670, 670, 670, 990]
407 },
408 {
409 "jobType": "/Lotus/Types/Gameplay/Eidolon/Jobs/CaptureBountyCapTwo",
410 "rewards": "/Lotus/Types/Game/MissionDecks/EidolonJobMissionRewards/TierDTableBRewards",
411 "masteryReq": 3,
412 "minEnemyLevel": 30,
413 "maxEnemyLevel": 50,
414 "xpAmounts": [570, 570, 570, 570, 1110]
415 },
416 {
417 "jobType": "/Lotus/Types/Gameplay/Eidolon/Jobs/ReclamationBountyCache",
418 "rewards": "/Lotus/Types/Game/MissionDecks/EidolonJobMissionRewards/TierETableBRewards",
419 "masteryReq": 5,
420 "minEnemyLevel": 40,
421 "maxEnemyLevel": 60,
422 "xpAmounts": [740, 740, 740, 740, 1450]
423 },
424 {
425 "jobType": "/Lotus/Types/Gameplay/Eidolon/Jobs/AttritionBountyCap",
426 "rewards": "/Lotus/Types/Game/MissionDecks/EidolonJobMissionRewards/TierETableBRewards",
427 "masteryReq": 10,
428 "minEnemyLevel": 100,
429 "maxEnemyLevel": 100,
430 "xpAmounts": [840, 840, 840, 840, 1660]
431 },
432 {
433 "jobType": "/Lotus/Types/Gameplay/Eidolon/Jobs/Narmer/AssassinateBountyAss",
434 "rewards": "/Lotus/Types/Game/MissionDecks/EidolonJobMissionRewards/NarmerTableBRewards",
435 "masteryReq": 0,
436 "minEnemyLevel": 50,
437 "maxEnemyLevel": 70,
438 "xpAmounts": [840, 840, 840, 840, 1650]
439 }
440 ]
441 },
442 {
443 "_id": { "$oid": "663a71c80000000000000025" },
444 "Activation": { "$date": { "$numberLong": "1715106248403" } },
445 "Expiry": { "$date": { "$numberLong": "2000000000000" } },
446 "Tag": "SolarisSyndicate",
447 "Seed": 99561,
448 "Nodes": [],
449 "Jobs": [
450 {
451 "jobType": "/Lotus/Types/Gameplay/Venus/Jobs/VenusIntelJobSpy",
452 "rewards": "/Lotus/Types/Game/MissionDecks/VenusJobMissionRewards/VenusTierATableBRewards",
453 "masteryReq": 0,
454 "minEnemyLevel": 5,
455 "maxEnemyLevel": 15,
456 "xpAmounts": [340, 340, 340]
457 },
458 {
459 "jobType": "/Lotus/Types/Gameplay/Venus/Jobs/VenusCullJobResource",
460 "rewards": "/Lotus/Types/Game/MissionDecks/VenusJobMissionRewards/VenusTierBTableBRewards",
461 "masteryReq": 1,
462 "minEnemyLevel": 10,
463 "maxEnemyLevel": 30,
464 "xpAmounts": [660, 660, 660]
465 },
466 {
467 "jobType": "/Lotus/Types/Gameplay/Venus/Jobs/VenusIntelJobRecovery",
468 "rewards": "/Lotus/Types/Game/MissionDecks/VenusJobMissionRewards/VenusTierCTableBRewards",
469 "masteryReq": 2,
470 "minEnemyLevel": 20,
471 "maxEnemyLevel": 40,
472 "xpAmounts": [610, 610, 610, 900]
473 },
474 {
475 "jobType": "/Lotus/Types/Gameplay/Venus/Jobs/VenusHelpingJobCaches",
476 "rewards": "/Lotus/Types/Game/MissionDecks/VenusJobMissionRewards/VenusTierDTableBRewards",
477 "masteryReq": 3,
478 "minEnemyLevel": 30,
479 "maxEnemyLevel": 50,
480 "xpAmounts": [600, 600, 600, 600, 1170]
481 },
482 {
483 "jobType": "/Lotus/Types/Gameplay/Venus/Jobs/VenusArtifactJobAmbush",
484 "rewards": "/Lotus/Types/Game/MissionDecks/VenusJobMissionRewards/VenusTierETableBRewards",
485 "masteryReq": 5,
486 "minEnemyLevel": 40,
487 "maxEnemyLevel": 60,
488 "xpAmounts": [690, 690, 690, 690, 1350]
489 },
490 {
491 "jobType": "/Lotus/Types/Gameplay/Venus/Jobs/VenusChaosJobExcavation",
492 "rewards": "/Lotus/Types/Game/MissionDecks/VenusJobMissionRewards/VenusTierETableBRewards",
493 "masteryReq": 10,
494 "minEnemyLevel": 100,
495 "maxEnemyLevel": 100,
496 "xpAmounts": [840, 840, 840, 840, 1660]
497 },
498 {
499 "jobType": "/Lotus/Types/Gameplay/Venus/Jobs/Narmer/NarmerVenusCullJobExterminate",
500 "rewards": "/Lotus/Types/Game/MissionDecks/EidolonJobMissionRewards/NarmerTableBRewards",
501 "masteryReq": 0,
502 "minEnemyLevel": 50,
503 "maxEnemyLevel": 70,
504 "xpAmounts": [780, 780, 780, 780, 1540]
505 }
506 ]
507 },
508 {
509 "_id": { "$oid": "663a71c80000000000000029" },
510 "Activation": { "$date": { "$numberLong": "1715106248403" } },
511 "Expiry": { "$date": { "$numberLong": "2000000000000" } },
512 "Tag": "ZarimanSyndicate",
513 "Seed": 99562,
514 "Nodes": []
515 },
516 {
517 "_id": { "$oid": "676b8d340000000000000006" },
518 "Activation": { "$date": { "$numberLong": "1735101748215" } },
519 "Expiry": { "$date": { "$numberLong": "2000000000000" } },
520 "Tag": "HexSyndicate",
521 "Seed": 33872,
522 "Nodes": []
523 281 }
524 282 ],
525 283 "ActiveMissions": [