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

fix: get bounty info by id to handle rollover (#1998)

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

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

代码差异

2 个文件 +265 -254
Modified src/services/missionInventoryUpdateService.ts +11 -11
@@ -58,9 +58,10 @@ import conservationAnimals from "@/static/fixed_responses/conservationAnimals.js
58 58 import { getInfNodes, getWeaponsForManifest, sendCodaFinishedMessage } from "@/src/helpers/nemesisHelpers";
59 59 import { Loadout } from "../models/inventoryModels/loadoutModel";
60 60 import { ILoadoutConfigDatabase } from "../types/saveLoadoutTypes";
61 import { getLiteSortie, getSortie, getWorldState, idToDay, idToWeek } from "./worldStateService";
61 import { getLiteSortie, getSortie, idToBountyCycle, idToDay, idToWeek, pushClassicBounties } from "./worldStateService";
62 62 import { config } from "./configService";
63 63 import libraryDailyTasks from "@/static/fixed_responses/libraryDailyTasks.json";
64 import { ISyndicateMissionInfo } from "../types/worldStateTypes";
64 65
65 66 const getRotations = (rewardInfo: IRewardInfo, tierOverride?: number): number[] => {
66 67 // For Spy missions, e.g. 3 vaults cracked = A, B, C
@@ -1086,10 +1087,10 @@ export const addMissionRewards = async (
1086 1087
1087 1088 if (rewardInfo.JobStage != undefined && rewardInfo.jobId) {
1088 1089 // eslint-disable-next-line @typescript-eslint/no-unused-vars
1089 const [jobType, unkIndex, hubNode, syndicateId, locationTag] = rewardInfo.jobId.split("_");
1090 const worldState = getWorldState();
1091 let syndicateEntry = worldState.SyndicateMissions.find(m => m._id.$oid === syndicateId);
1092 if (!syndicateEntry) syndicateEntry = worldState.SyndicateMissions.find(m => m.Tag === syndicateId); // Sometimes syndicateId can be tag
1090 const [jobType, unkIndex, hubNode, syndicateMissionId, locationTag] = rewardInfo.jobId.split("_");
1091 const syndicateMissions: ISyndicateMissionInfo[] = [];
1092 pushClassicBounties(syndicateMissions, idToBountyCycle(syndicateMissionId));
1093 const syndicateEntry = syndicateMissions.find(m => m._id.$oid === syndicateMissionId);
1093 1094 if (syndicateEntry && syndicateEntry.Jobs) {
1094 1095 let currentJob = syndicateEntry.Jobs[rewardInfo.JobTier!];
1095 1096 if (syndicateEntry.Tag === "EntratiSyndicate") {
@@ -1383,13 +1384,12 @@ function getRandomMissionDrops(
1383 1384 if (RewardInfo.jobId) {
1384 1385 if (RewardInfo.JobStage! >= 0) {
1385 1386 // eslint-disable-next-line @typescript-eslint/no-unused-vars
1386 const [jobType, unkIndex, hubNode, syndicateId, locationTag] = RewardInfo.jobId.split("_");
1387 const [jobType, unkIndex, hubNode, syndicateMissionId, locationTag] = RewardInfo.jobId.split("_");
1387 1388 let isEndlessJob = false;
1388 if (syndicateId) {
1389 const worldState = getWorldState();
1390 let syndicateEntry = worldState.SyndicateMissions.find(m => m._id.$oid === syndicateId);
1391 if (!syndicateEntry) syndicateEntry = worldState.SyndicateMissions.find(m => m.Tag === syndicateId);
1392
1389 if (syndicateMissionId) {
1390 const syndicateMissions: ISyndicateMissionInfo[] = [];
1391 pushClassicBounties(syndicateMissions, idToBountyCycle(syndicateMissionId));
1392 const syndicateEntry = syndicateMissions.find(m => m._id.$oid === syndicateMissionId);
1393 1393 if (syndicateEntry && syndicateEntry.Jobs) {
1394 1394 let job = syndicateEntry.Jobs[RewardInfo.JobTier!];
1395 1395
Modified src/services/worldStateService.ts +254 -243
@@ -14,6 +14,7 @@ import {
14 14 ISeasonChallenge,
15 15 ISortie,
16 16 ISortieMission,
17 ISyndicateMissionInfo,
17 18 IWorldState
18 19 } from "../types/worldStateTypes";
19 20
@@ -457,6 +458,254 @@ const pushWeeklyActs = (worldState: IWorldState, week: number): void => {
457 458 });
458 459 };
459 460
461 export const pushClassicBounties = (syndicateMissions: ISyndicateMissionInfo[], bountyCycle: number): void => {
462 const table = String.fromCharCode(65 + (bountyCycle % 3));
463 const vaultTable = String.fromCharCode(65 + ((bountyCycle + 1) % 3));
464 const deimosDTable = String.fromCharCode(65 + (bountyCycle % 2));
465
466 // TODO: xpAmounts need to be calculated based on the jobType somehow?
467
468 const seed = new CRng(bountyCycle).randomInt(0, 0xffff);
469 const bountyCycleStart = bountyCycle * 9000000;
470 const bountyCycleEnd = bountyCycleStart + 9000000;
471
472 {
473 const rng = new CRng(seed);
474 syndicateMissions.push({
475 _id: {
476 $oid: ((bountyCycleStart / 1000) & 0xffffffff).toString(16).padStart(8, "0") + "0000000000000008"
477 },
478 Activation: { $date: { $numberLong: bountyCycleStart.toString(10) } },
479 Expiry: { $date: { $numberLong: bountyCycleEnd.toString(10) } },
480 Tag: "CetusSyndicate",
481 Seed: seed,
482 Nodes: [],
483 Jobs: [
484 {
485 jobType: rng.randomElement(eidolonJobs),
486 rewards: `/Lotus/Types/Game/MissionDecks/EidolonJobMissionRewards/TierATable${table}Rewards`,
487 masteryReq: 0,
488 minEnemyLevel: 5,
489 maxEnemyLevel: 15,
490 xpAmounts: [430, 430, 430]
491 },
492 {
493 jobType: rng.randomElement(eidolonJobs),
494 rewards: `/Lotus/Types/Game/MissionDecks/EidolonJobMissionRewards/TierBTable${table}Rewards`,
495 masteryReq: 1,
496 minEnemyLevel: 10,
497 maxEnemyLevel: 30,
498 xpAmounts: [620, 620, 620]
499 },
500 {
501 jobType: rng.randomElement(eidolonJobs),
502 rewards: `/Lotus/Types/Game/MissionDecks/EidolonJobMissionRewards/TierCTable${table}Rewards`,
503 masteryReq: 2,
504 minEnemyLevel: 20,
505 maxEnemyLevel: 40,
506 xpAmounts: [670, 670, 670, 990]
507 },
508 {
509 jobType: rng.randomElement(eidolonJobs),
510 rewards: `/Lotus/Types/Game/MissionDecks/EidolonJobMissionRewards/TierDTable${table}Rewards`,
511 masteryReq: 3,
512 minEnemyLevel: 30,
513 maxEnemyLevel: 50,
514 xpAmounts: [570, 570, 570, 570, 1110]
515 },
516 {
517 jobType: rng.randomElement(eidolonJobs),
518 rewards: `/Lotus/Types/Game/MissionDecks/EidolonJobMissionRewards/TierETable${table}Rewards`,
519 masteryReq: 5,
520 minEnemyLevel: 40,
521 maxEnemyLevel: 60,
522 xpAmounts: [740, 740, 740, 740, 1450]
523 },
524 {
525 jobType: rng.randomElement(eidolonJobs),
526 rewards: `/Lotus/Types/Game/MissionDecks/EidolonJobMissionRewards/TierETable${table}Rewards`,
527 masteryReq: 10,
528 minEnemyLevel: 100,
529 maxEnemyLevel: 100,
530 xpAmounts: [840, 840, 840, 840, 1660]
531 },
532 {
533 jobType: rng.randomElement(eidolonNarmerJobs),
534 rewards: `/Lotus/Types/Game/MissionDecks/EidolonJobMissionRewards/NarmerTable${table}Rewards`,
535 masteryReq: 0,
536 minEnemyLevel: 50,
537 maxEnemyLevel: 70,
538 xpAmounts: [840, 840, 840, 840, 1650]
539 }
540 ]
541 });
542 }
543
544 {
545 const rng = new CRng(seed);
546 syndicateMissions.push({
547 _id: {
548 $oid: ((bountyCycleStart / 1000) & 0xffffffff).toString(16).padStart(8, "0") + "0000000000000025"
549 },
550 Activation: { $date: { $numberLong: bountyCycleStart.toString(10) } },
551 Expiry: { $date: { $numberLong: bountyCycleEnd.toString(10) } },
552 Tag: "SolarisSyndicate",
553 Seed: seed,
554 Nodes: [],
555 Jobs: [
556 {
557 jobType: rng.randomElement(venusJobs),
558 rewards: `/Lotus/Types/Game/MissionDecks/VenusJobMissionRewards/VenusTierATable${table}Rewards`,
559 masteryReq: 0,
560 minEnemyLevel: 5,
561 maxEnemyLevel: 15,
562 xpAmounts: [340, 340, 340]
563 },
564 {
565 jobType: rng.randomElement(venusJobs),
566 rewards: `/Lotus/Types/Game/MissionDecks/VenusJobMissionRewards/VenusTierBTable${table}Rewards`,
567 masteryReq: 1,
568 minEnemyLevel: 10,
569 maxEnemyLevel: 30,
570 xpAmounts: [660, 660, 660]
571 },
572 {
573 jobType: rng.randomElement(venusJobs),
574 rewards: `/Lotus/Types/Game/MissionDecks/VenusJobMissionRewards/VenusTierCTable${table}Rewards`,
575 masteryReq: 2,
576 minEnemyLevel: 20,
577 maxEnemyLevel: 40,
578 xpAmounts: [610, 610, 610, 900]
579 },
580 {
581 jobType: rng.randomElement(venusJobs),
582 rewards: `/Lotus/Types/Game/MissionDecks/VenusJobMissionRewards/VenusTierDTable${table}Rewards`,
583 masteryReq: 3,
584 minEnemyLevel: 30,
585 maxEnemyLevel: 50,
586 xpAmounts: [600, 600, 600, 600, 1170]
587 },
588 {
589 jobType: rng.randomElement(venusJobs),
590 rewards: `/Lotus/Types/Game/MissionDecks/VenusJobMissionRewards/VenusTierETable${table}Rewards`,
591 masteryReq: 5,
592 minEnemyLevel: 40,
593 maxEnemyLevel: 60,
594 xpAmounts: [690, 690, 690, 690, 1350]
595 },
596 {
597 jobType: rng.randomElement(venusJobs),
598 rewards: `/Lotus/Types/Game/MissionDecks/VenusJobMissionRewards/VenusTierETable${table}Rewards`,
599 masteryReq: 10,
600 minEnemyLevel: 100,
601 maxEnemyLevel: 100,
602 xpAmounts: [840, 840, 840, 840, 1660]
603 },
604 {
605 jobType: rng.randomElement(venusNarmerJobs),
606 rewards: "/Lotus/Types/Game/MissionDecks/EidolonJobMissionRewards/NarmerTableBRewards",
607 masteryReq: 0,
608 minEnemyLevel: 50,
609 maxEnemyLevel: 70,
610 xpAmounts: [780, 780, 780, 780, 1540]
611 }
612 ]
613 });
614 }
615
616 {
617 const rng = new CRng(seed);
618 syndicateMissions.push({
619 _id: {
620 $oid: ((bountyCycleStart / 1000) & 0xffffffff).toString(16).padStart(8, "0") + "0000000000000002"
621 },
622 Activation: { $date: { $numberLong: bountyCycleStart.toString(10) } },
623 Expiry: { $date: { $numberLong: bountyCycleEnd.toString(10) } },
624 Tag: "EntratiSyndicate",
625 Seed: seed,
626 Nodes: [],
627 Jobs: [
628 {
629 jobType: rng.randomElement(microplanetJobs),
630 rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/TierATable${table}Rewards`,
631 masteryReq: 0,
632 minEnemyLevel: 5,
633 maxEnemyLevel: 15,
634 xpAmounts: [5, 5, 5]
635 },
636 {
637 jobType: rng.randomElement(microplanetJobs),
638 rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/TierCTable${table}Rewards`,
639 masteryReq: 1,
640 minEnemyLevel: 15,
641 maxEnemyLevel: 25,
642 xpAmounts: [12, 12, 12]
643 },
644 {
645 jobType: rng.randomElement(microplanetEndlessJobs),
646 rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/TierBTable${table}Rewards`,
647 masteryReq: 5,
648 minEnemyLevel: 25,
649 maxEnemyLevel: 30,
650 endless: true,
651 xpAmounts: [14, 14, 14]
652 },
653 {
654 jobType: rng.randomElement(microplanetJobs),
655 rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/TierDTable${deimosDTable}Rewards`,
656 masteryReq: 2,
657 minEnemyLevel: 30,
658 maxEnemyLevel: 40,
659 xpAmounts: [17, 17, 17, 25]
660 },
661 {
662 jobType: rng.randomElement(microplanetJobs),
663 rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/TierETableARewards`,
664 masteryReq: 3,
665 minEnemyLevel: 40,
666 maxEnemyLevel: 60,
667 xpAmounts: [22, 22, 22, 22, 43]
668 },
669 {
670 jobType: rng.randomElement(microplanetJobs),
671 rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/TierETableARewards`,
672 masteryReq: 10,
673 minEnemyLevel: 100,
674 maxEnemyLevel: 100,
675 xpAmounts: [25, 25, 25, 25, 50]
676 },
677 {
678 rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/VaultBountyTierATable${vaultTable}Rewards`,
679 masteryReq: 5,
680 minEnemyLevel: 30,
681 maxEnemyLevel: 40,
682 xpAmounts: [2, 2, 2, 4],
683 locationTag: "ChamberB",
684 isVault: true
685 },
686 {
687 rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/VaultBountyTierBTable${vaultTable}Rewards`,
688 masteryReq: 5,
689 minEnemyLevel: 40,
690 maxEnemyLevel: 50,
691 xpAmounts: [4, 4, 4, 5],
692 locationTag: "ChamberA",
693 isVault: true
694 },
695 {
696 rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/VaultBountyTierCTable${vaultTable}Rewards`,
697 masteryReq: 5,
698 minEnemyLevel: 50,
699 maxEnemyLevel: 60,
700 xpAmounts: [5, 5, 5, 7],
701 locationTag: "ChamberC",
702 isVault: true
703 }
704 ]
705 });
706 }
707 };
708
460 709 const birthdays: number[] = [
461 710 1, // Kaya
462 711 45, // Lettie
@@ -799,249 +1048,7 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
799 1048 Nodes: []
800 1049 });
801 1050
802 const table = String.fromCharCode(65 + (bountyCycle % 3));
803 const vaultTable = String.fromCharCode(65 + ((bountyCycle + 1) % 3));
804 const deimosDTable = String.fromCharCode(65 + (bountyCycle % 2));
805
806 // TODO: xpAmounts need to be calculated based on the jobType somehow?
807
808 const seed = new CRng(bountyCycle).randomInt(0, 0xffff);
809
810 {
811 const rng = new CRng(seed);
812 worldState.SyndicateMissions.push({
813 _id: {
814 $oid: ((bountyCycleStart / 1000) & 0xffffffff).toString(16).padStart(8, "0") + "0000000000000008"
815 },
816 Activation: { $date: { $numberLong: bountyCycleStart.toString(10) } },
817 Expiry: { $date: { $numberLong: bountyCycleEnd.toString(10) } },
818 Tag: "CetusSyndicate",
819 Seed: seed,
820 Nodes: [],
821 Jobs: [
822 {
823 jobType: rng.randomElement(eidolonJobs),
824 rewards: `/Lotus/Types/Game/MissionDecks/EidolonJobMissionRewards/TierATable${table}Rewards`,
825 masteryReq: 0,
826 minEnemyLevel: 5,
827 maxEnemyLevel: 15,
828 xpAmounts: [430, 430, 430]
829 },
830 {
831 jobType: rng.randomElement(eidolonJobs),
832 rewards: `/Lotus/Types/Game/MissionDecks/EidolonJobMissionRewards/TierBTable${table}Rewards`,
833 masteryReq: 1,
834 minEnemyLevel: 10,
835 maxEnemyLevel: 30,
836 xpAmounts: [620, 620, 620]
837 },
838 {
839 jobType: rng.randomElement(eidolonJobs),
840 rewards: `/Lotus/Types/Game/MissionDecks/EidolonJobMissionRewards/TierCTable${table}Rewards`,
841 masteryReq: 2,
842 minEnemyLevel: 20,
843 maxEnemyLevel: 40,
844 xpAmounts: [670, 670, 670, 990]
845 },
846 {
847 jobType: rng.randomElement(eidolonJobs),
848 rewards: `/Lotus/Types/Game/MissionDecks/EidolonJobMissionRewards/TierDTable${table}Rewards`,
849 masteryReq: 3,
850 minEnemyLevel: 30,
851 maxEnemyLevel: 50,
852 xpAmounts: [570, 570, 570, 570, 1110]
853 },
854 {
855 jobType: rng.randomElement(eidolonJobs),
856 rewards: `/Lotus/Types/Game/MissionDecks/EidolonJobMissionRewards/TierETable${table}Rewards`,
857 masteryReq: 5,
858 minEnemyLevel: 40,
859 maxEnemyLevel: 60,
860 xpAmounts: [740, 740, 740, 740, 1450]
861 },
862 {
863 jobType: rng.randomElement(eidolonJobs),
864 rewards: `/Lotus/Types/Game/MissionDecks/EidolonJobMissionRewards/TierETable${table}Rewards`,
865 masteryReq: 10,
866 minEnemyLevel: 100,
867 maxEnemyLevel: 100,
868 xpAmounts: [840, 840, 840, 840, 1660]
869 },
870 {
871 jobType: rng.randomElement(eidolonNarmerJobs),
872 rewards: `/Lotus/Types/Game/MissionDecks/EidolonJobMissionRewards/NarmerTable${table}Rewards`,
873 masteryReq: 0,
874 minEnemyLevel: 50,
875 maxEnemyLevel: 70,
876 xpAmounts: [840, 840, 840, 840, 1650]
877 }
878 ]
879 });
880 }
881
882 {
883 const rng = new CRng(seed);
884 worldState.SyndicateMissions.push({
885 _id: {
886 $oid: ((bountyCycleStart / 1000) & 0xffffffff).toString(16).padStart(8, "0") + "0000000000000025"
887 },
888 Activation: { $date: { $numberLong: bountyCycleStart.toString(10) } },
889 Expiry: { $date: { $numberLong: bountyCycleEnd.toString(10) } },
890 Tag: "SolarisSyndicate",
891 Seed: seed,
892 Nodes: [],
893 Jobs: [
894 {
895 jobType: rng.randomElement(venusJobs),
896 rewards: `/Lotus/Types/Game/MissionDecks/VenusJobMissionRewards/VenusTierATable${table}Rewards`,
897 masteryReq: 0,
898 minEnemyLevel: 5,
899 maxEnemyLevel: 15,
900 xpAmounts: [340, 340, 340]
901 },
902 {
903 jobType: rng.randomElement(venusJobs),
904 rewards: `/Lotus/Types/Game/MissionDecks/VenusJobMissionRewards/VenusTierBTable${table}Rewards`,
905 masteryReq: 1,
906 minEnemyLevel: 10,
907 maxEnemyLevel: 30,
908 xpAmounts: [660, 660, 660]
909 },
910 {
911 jobType: rng.randomElement(venusJobs),
912 rewards: `/Lotus/Types/Game/MissionDecks/VenusJobMissionRewards/VenusTierCTable${table}Rewards`,
913 masteryReq: 2,
914 minEnemyLevel: 20,
915 maxEnemyLevel: 40,
916 xpAmounts: [610, 610, 610, 900]
917 },
918 {
919 jobType: rng.randomElement(venusJobs),
920 rewards: `/Lotus/Types/Game/MissionDecks/VenusJobMissionRewards/VenusTierDTable${table}Rewards`,
921 masteryReq: 3,
922 minEnemyLevel: 30,
923 maxEnemyLevel: 50,
924 xpAmounts: [600, 600, 600, 600, 1170]
925 },
926 {
927 jobType: rng.randomElement(venusJobs),
928 rewards: `/Lotus/Types/Game/MissionDecks/VenusJobMissionRewards/VenusTierETable${table}Rewards`,
929 masteryReq: 5,
930 minEnemyLevel: 40,
931 maxEnemyLevel: 60,
932 xpAmounts: [690, 690, 690, 690, 1350]
933 },
934 {
935 jobType: rng.randomElement(venusJobs),
936 rewards: `/Lotus/Types/Game/MissionDecks/VenusJobMissionRewards/VenusTierETable${table}Rewards`,
937 masteryReq: 10,
938 minEnemyLevel: 100,
939 maxEnemyLevel: 100,
940 xpAmounts: [840, 840, 840, 840, 1660]
941 },
942 {
943 jobType: rng.randomElement(venusNarmerJobs),
944 rewards: "/Lotus/Types/Game/MissionDecks/EidolonJobMissionRewards/NarmerTableBRewards",
945 masteryReq: 0,
946 minEnemyLevel: 50,
947 maxEnemyLevel: 70,
948 xpAmounts: [780, 780, 780, 780, 1540]
949 }
950 ]
951 });
952 }
953
954 {
955 const rng = new CRng(seed);
956 worldState.SyndicateMissions.push({
957 _id: {
958 $oid: ((bountyCycleStart / 1000) & 0xffffffff).toString(16).padStart(8, "0") + "0000000000000002"
959 },
960 Activation: { $date: { $numberLong: bountyCycleStart.toString(10) } },
961 Expiry: { $date: { $numberLong: bountyCycleEnd.toString(10) } },
962 Tag: "EntratiSyndicate",
963 Seed: seed,
964 Nodes: [],
965 Jobs: [
966 {
967 jobType: rng.randomElement(microplanetJobs),
968 rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/TierATable${table}Rewards`,
969 masteryReq: 0,
970 minEnemyLevel: 5,
971 maxEnemyLevel: 15,
972 xpAmounts: [5, 5, 5]
973 },
974 {
975 jobType: rng.randomElement(microplanetJobs),
976 rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/TierCTable${table}Rewards`,
977 masteryReq: 1,
978 minEnemyLevel: 15,
979 maxEnemyLevel: 25,
980 xpAmounts: [12, 12, 12]
981 },
982 {
983 jobType: rng.randomElement(microplanetEndlessJobs),
984 rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/TierBTable${table}Rewards`,
985 masteryReq: 5,
986 minEnemyLevel: 25,
987 maxEnemyLevel: 30,
988 endless: true,
989 xpAmounts: [14, 14, 14]
990 },
991 {
992 jobType: rng.randomElement(microplanetJobs),
993 rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/TierDTable${deimosDTable}Rewards`,
994 masteryReq: 2,
995 minEnemyLevel: 30,
996 maxEnemyLevel: 40,
997 xpAmounts: [17, 17, 17, 25]
998 },
999 {
1000 jobType: rng.randomElement(microplanetJobs),
1001 rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/TierETableARewards`,
1002 masteryReq: 3,
1003 minEnemyLevel: 40,
1004 maxEnemyLevel: 60,
1005 xpAmounts: [22, 22, 22, 22, 43]
1006 },
1007 {
1008 jobType: rng.randomElement(microplanetJobs),
1009 rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/TierETableARewards`,
1010 masteryReq: 10,
1011 minEnemyLevel: 100,
1012 maxEnemyLevel: 100,
1013 xpAmounts: [25, 25, 25, 25, 50]
1014 },
1015 {
1016 rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/VaultBountyTierATable${vaultTable}Rewards`,
1017 masteryReq: 5,
1018 minEnemyLevel: 30,
1019 maxEnemyLevel: 40,
1020 xpAmounts: [2, 2, 2, 4],
1021 locationTag: "ChamberB",
1022 isVault: true
1023 },
1024 {
1025 rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/VaultBountyTierBTable${vaultTable}Rewards`,
1026 masteryReq: 5,
1027 minEnemyLevel: 40,
1028 maxEnemyLevel: 50,
1029 xpAmounts: [4, 4, 4, 5],
1030 locationTag: "ChamberA",
1031 isVault: true
1032 },
1033 {
1034 rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/VaultBountyTierCTable${vaultTable}Rewards`,
1035 masteryReq: 5,
1036 minEnemyLevel: 50,
1037 maxEnemyLevel: 60,
1038 xpAmounts: [5, 5, 5, 7],
1039 locationTag: "ChamberC",
1040 isVault: true
1041 }
1042 ]
1043 });
1044 }
1051 pushClassicBounties(worldState.SyndicateMissions, bountyCycle);
1045 1052 } while (isBeforeNextExpectedWorldStateRefresh(bountyCycleEnd) && ++bountyCycle);
1046 1053
1047 1054 if (config.worldState?.creditBoost) {
@@ -1178,6 +1185,10 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
1178 1185 return worldState;
1179 1186 };
1180 1187
1188 export const idToBountyCycle = (id: string): number => {
1189 return Math.trunc((parseInt(id.substring(0, 8), 16) * 1000) / 9000_000);
1190 };
1191
1181 1192 export const idToDay = (id: string): number => {
1182 1193 return Math.trunc((parseInt(id.substring(0, 8), 16) * 1000 - EPOCH) / 86400_000);
1183 1194 };