fix: ensure every bounty tier has a unique job type
All checks were successful
Build / build (pull_request) Successful in 1m24s

I saw "trash their traps" show up twice on Eudico in different tiers, I don't think that's correct.
This commit is contained in:
Sainan 2025-06-24 20:07:51 +02:00
parent ca3cfb5299
commit 18dfffb3cf
2 changed files with 36 additions and 23 deletions

View File

@ -107,6 +107,16 @@ export class SRng {
return arr[this.randomInt(0, arr.length - 1)];
}
randomElementPop<T>(arr: T[]): T | undefined {
if (arr.length != 0) {
const index = this.randomInt(0, arr.length - 1);
const elm = arr[index];
arr.splice(index, 1);
return elm;
}
return undefined;
}
randomFloat(): number {
this.state = (0x5851f42d4c957f2dn * this.state + 0x14057b7ef767814fn) & 0xffffffffffffffffn;
return (Number(this.state >> 38n) & 0xffffff) * 0.000000059604645;

View File

@ -98,7 +98,7 @@ const sortieBossNode: Record<Exclude<TSortieBoss, "SORTIE_BOSS_CORRUPTED_VOR">,
SORTIE_BOSS_VOR: "SolNode108"
};
const eidolonJobs = [
const eidolonJobs: readonly string[] = [
"/Lotus/Types/Gameplay/Eidolon/Jobs/AssassinateBountyAss",
"/Lotus/Types/Gameplay/Eidolon/Jobs/AssassinateBountyCap",
"/Lotus/Types/Gameplay/Eidolon/Jobs/AttritionBountySab",
@ -114,14 +114,14 @@ const eidolonJobs = [
"/Lotus/Types/Gameplay/Eidolon/Jobs/RescueBountyResc"
];
const eidolonNarmerJobs = [
const eidolonNarmerJobs: readonly string[] = [
"/Lotus/Types/Gameplay/Eidolon/Jobs/Narmer/AssassinateBountyAss",
"/Lotus/Types/Gameplay/Eidolon/Jobs/Narmer/AttritionBountyExt",
"/Lotus/Types/Gameplay/Eidolon/Jobs/Narmer/ReclamationBountyTheft",
"/Lotus/Types/Gameplay/Eidolon/Jobs/Narmer/AttritionBountyLib"
];
const venusJobs = [
const venusJobs: readonly string[] = [
"/Lotus/Types/Gameplay/Venus/Jobs/VenusArtifactJobAmbush",
"/Lotus/Types/Gameplay/Venus/Jobs/VenusArtifactJobExcavation",
"/Lotus/Types/Gameplay/Venus/Jobs/VenusArtifactJobRecovery",
@ -147,14 +147,14 @@ const venusJobs = [
"/Lotus/Types/Gameplay/Venus/Jobs/VenusWetworkJobSpy"
];
const venusNarmerJobs = [
const venusNarmerJobs: readonly string[] = [
"/Lotus/Types/Gameplay/Venus/Jobs/Narmer/NarmerVenusCullJobAssassinate",
"/Lotus/Types/Gameplay/Venus/Jobs/Narmer/NarmerVenusCullJobExterminate",
"/Lotus/Types/Gameplay/Venus/Jobs/Narmer/NarmerVenusPreservationJobDefense",
"/Lotus/Types/Gameplay/Venus/Jobs/Narmer/NarmerVenusTheftJobExcavation"
];
const microplanetJobs = [
const microplanetJobs: readonly string[] = [
"/Lotus/Types/Gameplay/InfestedMicroplanet/Jobs/DeimosAreaDefenseBounty",
"/Lotus/Types/Gameplay/InfestedMicroplanet/Jobs/DeimosAssassinateBounty",
"/Lotus/Types/Gameplay/InfestedMicroplanet/Jobs/DeimosCrpSurvivorBounty",
@ -164,7 +164,7 @@ const microplanetJobs = [
"/Lotus/Types/Gameplay/InfestedMicroplanet/Jobs/DeimosPurifyBounty"
];
const microplanetEndlessJobs = [
const microplanetEndlessJobs: readonly string[] = [
"/Lotus/Types/Gameplay/InfestedMicroplanet/Jobs/DeimosEndlessAreaDefenseBounty",
"/Lotus/Types/Gameplay/InfestedMicroplanet/Jobs/DeimosEndlessExcavateBounty",
"/Lotus/Types/Gameplay/InfestedMicroplanet/Jobs/DeimosEndlessPurifyBounty"
@ -495,6 +495,7 @@ export const pushClassicBounties = (syndicateMissions: ISyndicateMissionInfo[],
{
const rng = new SRng(seed);
const pool = [...eidolonJobs];
syndicateMissions.push({
_id: {
$oid: ((bountyCycleStart / 1000) & 0xffffffff).toString(16).padStart(8, "0") + "0000000000000008"
@ -506,7 +507,7 @@ export const pushClassicBounties = (syndicateMissions: ISyndicateMissionInfo[],
Nodes: [],
Jobs: [
{
jobType: rng.randomElement(eidolonJobs),
jobType: rng.randomElementPop(pool),
rewards: `/Lotus/Types/Game/MissionDecks/EidolonJobMissionRewards/TierATable${table}Rewards`,
masteryReq: 0,
minEnemyLevel: 5,
@ -514,7 +515,7 @@ export const pushClassicBounties = (syndicateMissions: ISyndicateMissionInfo[],
xpAmounts: generateXpAmounts(rng, 3, 1000, 1500)
},
{
jobType: rng.randomElement(eidolonJobs),
jobType: rng.randomElementPop(pool),
rewards: `/Lotus/Types/Game/MissionDecks/EidolonJobMissionRewards/TierBTable${table}Rewards`,
masteryReq: 1,
minEnemyLevel: 10,
@ -522,7 +523,7 @@ export const pushClassicBounties = (syndicateMissions: ISyndicateMissionInfo[],
xpAmounts: generateXpAmounts(rng, 3, 1750, 2250)
},
{
jobType: rng.randomElement(eidolonJobs),
jobType: rng.randomElementPop(pool),
rewards: `/Lotus/Types/Game/MissionDecks/EidolonJobMissionRewards/TierCTable${table}Rewards`,
masteryReq: 2,
minEnemyLevel: 20,
@ -530,7 +531,7 @@ export const pushClassicBounties = (syndicateMissions: ISyndicateMissionInfo[],
xpAmounts: generateXpAmounts(rng, 4, 2500, 3000)
},
{
jobType: rng.randomElement(eidolonJobs),
jobType: rng.randomElementPop(pool),
rewards: `/Lotus/Types/Game/MissionDecks/EidolonJobMissionRewards/TierDTable${table}Rewards`,
masteryReq: 3,
minEnemyLevel: 30,
@ -538,7 +539,7 @@ export const pushClassicBounties = (syndicateMissions: ISyndicateMissionInfo[],
xpAmounts: generateXpAmounts(rng, 5, 3250, 3750)
},
{
jobType: rng.randomElement(eidolonJobs),
jobType: rng.randomElementPop(pool),
rewards: `/Lotus/Types/Game/MissionDecks/EidolonJobMissionRewards/TierETable${table}Rewards`,
masteryReq: 5,
minEnemyLevel: 40,
@ -546,7 +547,7 @@ export const pushClassicBounties = (syndicateMissions: ISyndicateMissionInfo[],
xpAmounts: generateXpAmounts(rng, 5, 4000, 4500)
},
{
jobType: rng.randomElement(eidolonJobs),
jobType: rng.randomElementPop(pool),
rewards: `/Lotus/Types/Game/MissionDecks/EidolonJobMissionRewards/TierETable${table}Rewards`,
masteryReq: 10,
minEnemyLevel: 100,
@ -567,6 +568,7 @@ export const pushClassicBounties = (syndicateMissions: ISyndicateMissionInfo[],
{
const rng = new SRng(seed);
const pool = [...venusJobs];
syndicateMissions.push({
_id: {
$oid: ((bountyCycleStart / 1000) & 0xffffffff).toString(16).padStart(8, "0") + "0000000000000025"
@ -578,7 +580,7 @@ export const pushClassicBounties = (syndicateMissions: ISyndicateMissionInfo[],
Nodes: [],
Jobs: [
{
jobType: rng.randomElement(venusJobs),
jobType: rng.randomElementPop(pool),
rewards: `/Lotus/Types/Game/MissionDecks/VenusJobMissionRewards/VenusTierATable${table}Rewards`,
masteryReq: 0,
minEnemyLevel: 5,
@ -586,7 +588,7 @@ export const pushClassicBounties = (syndicateMissions: ISyndicateMissionInfo[],
xpAmounts: generateXpAmounts(rng, 3, 1000, 1500)
},
{
jobType: rng.randomElement(venusJobs),
jobType: rng.randomElementPop(pool),
rewards: `/Lotus/Types/Game/MissionDecks/VenusJobMissionRewards/VenusTierBTable${table}Rewards`,
masteryReq: 1,
minEnemyLevel: 10,
@ -594,7 +596,7 @@ export const pushClassicBounties = (syndicateMissions: ISyndicateMissionInfo[],
xpAmounts: generateXpAmounts(rng, 3, 1750, 2250)
},
{
jobType: rng.randomElement(venusJobs),
jobType: rng.randomElementPop(pool),
rewards: `/Lotus/Types/Game/MissionDecks/VenusJobMissionRewards/VenusTierCTable${table}Rewards`,
masteryReq: 2,
minEnemyLevel: 20,
@ -602,7 +604,7 @@ export const pushClassicBounties = (syndicateMissions: ISyndicateMissionInfo[],
xpAmounts: generateXpAmounts(rng, 4, 2500, 3000)
},
{
jobType: rng.randomElement(venusJobs),
jobType: rng.randomElementPop(pool),
rewards: `/Lotus/Types/Game/MissionDecks/VenusJobMissionRewards/VenusTierDTable${table}Rewards`,
masteryReq: 3,
minEnemyLevel: 30,
@ -610,7 +612,7 @@ export const pushClassicBounties = (syndicateMissions: ISyndicateMissionInfo[],
xpAmounts: generateXpAmounts(rng, 5, 3250, 3750)
},
{
jobType: rng.randomElement(venusJobs),
jobType: rng.randomElementPop(pool),
rewards: `/Lotus/Types/Game/MissionDecks/VenusJobMissionRewards/VenusTierETable${table}Rewards`,
masteryReq: 5,
minEnemyLevel: 40,
@ -618,7 +620,7 @@ export const pushClassicBounties = (syndicateMissions: ISyndicateMissionInfo[],
xpAmounts: generateXpAmounts(rng, 5, 4000, 4500)
},
{
jobType: rng.randomElement(venusJobs),
jobType: rng.randomElementPop(pool),
rewards: `/Lotus/Types/Game/MissionDecks/VenusJobMissionRewards/VenusTierETable${table}Rewards`,
masteryReq: 10,
minEnemyLevel: 100,
@ -639,6 +641,7 @@ export const pushClassicBounties = (syndicateMissions: ISyndicateMissionInfo[],
{
const rng = new SRng(seed);
const pool = [...microplanetJobs];
syndicateMissions.push({
_id: {
$oid: ((bountyCycleStart / 1000) & 0xffffffff).toString(16).padStart(8, "0") + "0000000000000002"
@ -650,7 +653,7 @@ export const pushClassicBounties = (syndicateMissions: ISyndicateMissionInfo[],
Nodes: [],
Jobs: [
{
jobType: rng.randomElement(microplanetJobs),
jobType: rng.randomElementPop(pool),
rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/TierATable${table}Rewards`,
masteryReq: 0,
minEnemyLevel: 5,
@ -658,7 +661,7 @@ export const pushClassicBounties = (syndicateMissions: ISyndicateMissionInfo[],
xpAmounts: generateXpAmounts(rng, 3, 12, 18)
},
{
jobType: rng.randomElement(microplanetJobs),
jobType: rng.randomElementPop(pool),
rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/TierCTable${table}Rewards`,
masteryReq: 1,
minEnemyLevel: 15,
@ -675,7 +678,7 @@ export const pushClassicBounties = (syndicateMissions: ISyndicateMissionInfo[],
xpAmounts: [14, 14, 14]
},
{
jobType: rng.randomElement(microplanetJobs),
jobType: rng.randomElementPop(pool),
rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/TierDTable${deimosDTable}Rewards`,
masteryReq: 2,
minEnemyLevel: 30,
@ -683,7 +686,7 @@ export const pushClassicBounties = (syndicateMissions: ISyndicateMissionInfo[],
xpAmounts: generateXpAmounts(rng, 4, 72, 88)
},
{
jobType: rng.randomElement(microplanetJobs),
jobType: rng.randomElementPop(pool),
rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/TierETableARewards`,
masteryReq: 3,
minEnemyLevel: 40,
@ -691,7 +694,7 @@ export const pushClassicBounties = (syndicateMissions: ISyndicateMissionInfo[],
xpAmounts: generateXpAmounts(rng, 5, 115, 135)
},
{
jobType: rng.randomElement(microplanetJobs),
jobType: rng.randomElementPop(pool),
rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/TierETableARewards`,
masteryReq: 10,
minEnemyLevel: 100,