fix: don't give sortie assassination rewards if mission type differs (#1992)
Some checks failed
Build / build (push) Has been cancelled
Build Docker image / docker (push) Has been cancelled

Closes #1987

Reviewed-on: #1992
Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com>
Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
This commit is contained in:
Sainan 2025-05-06 02:29:11 -07:00 committed by Sainan
parent 460deed3ed
commit da6d75c748
2 changed files with 50 additions and 31 deletions

View File

@ -58,7 +58,7 @@ import conservationAnimals from "@/static/fixed_responses/conservationAnimals.js
import { getInfNodes, getWeaponsForManifest, sendCodaFinishedMessage } from "@/src/helpers/nemesisHelpers"; import { getInfNodes, getWeaponsForManifest, sendCodaFinishedMessage } from "@/src/helpers/nemesisHelpers";
import { Loadout } from "../models/inventoryModels/loadoutModel"; import { Loadout } from "../models/inventoryModels/loadoutModel";
import { ILoadoutConfigDatabase } from "../types/saveLoadoutTypes"; import { ILoadoutConfigDatabase } from "../types/saveLoadoutTypes";
import { getLiteSortie, getWorldState, idToWeek } from "./worldStateService"; import { getLiteSortie, getSortie, getWorldState, idToDay, idToWeek } from "./worldStateService";
import { config } from "./configService"; import { config } from "./configService";
import libraryDailyTasks from "@/static/fixed_responses/libraryDailyTasks.json"; import libraryDailyTasks from "@/static/fixed_responses/libraryDailyTasks.json";
@ -1357,9 +1357,24 @@ function getRandomMissionDrops(
// Invasion assassination has Phorid has the boss who should drop Nyx parts // Invasion assassination has Phorid has the boss who should drop Nyx parts
// TODO: Check that the invasion faction is indeed FC_INFESTATION once the Invasions in worldState are more dynamic // TODO: Check that the invasion faction is indeed FC_INFESTATION once the Invasions in worldState are more dynamic
rewardManifests = ["/Lotus/Types/Game/MissionDecks/BossMissionRewards/NyxRewards"]; rewardManifests = ["/Lotus/Types/Game/MissionDecks/BossMissionRewards/NyxRewards"];
} else if (RewardInfo.sortieId && region.missionIndex != 0) { } else if (RewardInfo.sortieId) {
// Sortie mission types differ from the underlying node and hence also don't give rewards from the underlying nodes. Assassinations are an exception to this. // Sortie mission types differ from the underlying node and hence also don't give rewards from the underlying nodes. Assassinations are an exception to this.
if (region.missionIndex == 0) {
const arr = RewardInfo.sortieId.split("_");
let sortieId = arr[1];
if (sortieId == "Lite") {
sortieId = arr[2];
}
const sortie = getSortie(idToDay(sortieId));
const mission = sortie.Variants.find(x => x.node == arr[0])!;
if (mission.missionType == "MT_ASSASSINATION") {
rewardManifests = region.rewardManifests;
} else {
rewardManifests = []; rewardManifests = [];
}
} else {
rewardManifests = [];
}
} else { } else {
rewardManifests = region.rewardManifests; rewardManifests = region.rewardManifests;
} }

View File

@ -12,6 +12,7 @@ import {
ICalendarSeason, ICalendarSeason,
ILiteSortie, ILiteSortie,
ISeasonChallenge, ISeasonChallenge,
ISortie,
ISortieMission, ISortieMission,
IWorldState IWorldState
} from "../types/worldStateTypes"; } from "../types/worldStateTypes";
@ -193,12 +194,6 @@ const pushSyndicateMissions = (
idSuffix: string, idSuffix: string,
syndicateTag: string syndicateTag: string
): void => { ): void => {
const dayStart = getSortieTime(day);
if (Date.now() >= dayStart) {
return; // The client does not seem to respect activation.
}
const dayEnd = getSortieTime(day + 1);
const nodeOptions: string[] = [...syndicateMissions]; const nodeOptions: string[] = [...syndicateMissions];
const rng = new CRng(seed); const rng = new CRng(seed);
@ -209,6 +204,8 @@ const pushSyndicateMissions = (
nodeOptions.splice(index, 1); nodeOptions.splice(index, 1);
} }
const dayStart = getSortieTime(day);
const dayEnd = getSortieTime(day + 1);
worldState.SyndicateMissions.push({ worldState.SyndicateMissions.push({
_id: { $oid: ((dayStart / 1000) & 0xffffffff).toString(16).padStart(8, "0") + idSuffix }, _id: { $oid: ((dayStart / 1000) & 0xffffffff).toString(16).padStart(8, "0") + idSuffix },
Activation: { $date: { $numberLong: dayStart.toString() } }, Activation: { $date: { $numberLong: dayStart.toString() } },
@ -219,16 +216,7 @@ const pushSyndicateMissions = (
}); });
}; };
const pushSortieIfRelevant = (worldState: IWorldState, day: number): void => { export const getSortie = (day: number): ISortie => {
const dayStart = getSortieTime(day);
if (!isBeforeNextExpectedWorldStateRefresh(dayStart)) {
return;
}
const dayEnd = getSortieTime(day + 1);
if (Date.now() >= dayEnd) {
return;
}
const seed = new CRng(day).randomInt(0, 0xffff); const seed = new CRng(day).randomInt(0, 0xffff);
const rng = new CRng(seed); const rng = new CRng(seed);
@ -375,7 +363,9 @@ const pushSortieIfRelevant = (worldState: IWorldState, day: number): void => {
missionTypes.add(missionType); missionTypes.add(missionType);
} }
worldState.Sorties.push({ const dayStart = getSortieTime(day);
const dayEnd = getSortieTime(day + 1);
return {
_id: { $oid: ((dayStart / 1000) & 0xffffffff).toString(16).padStart(8, "0") + "d4d932c97c0a3acd" }, _id: { $oid: ((dayStart / 1000) & 0xffffffff).toString(16).padStart(8, "0") + "d4d932c97c0a3acd" },
Activation: { $date: { $numberLong: dayStart.toString() } }, Activation: { $date: { $numberLong: dayStart.toString() } },
Expiry: { $date: { $numberLong: dayEnd.toString() } }, Expiry: { $date: { $numberLong: dayEnd.toString() } },
@ -383,14 +373,7 @@ const pushSortieIfRelevant = (worldState: IWorldState, day: number): void => {
Seed: seed, Seed: seed,
Boss: boss, Boss: boss,
Variants: selectedNodes Variants: selectedNodes
}); };
pushSyndicateMissions(worldState, day, rng.randomInt(0, 0xffff), "ba6f84724fa48049", "ArbitersSyndicate");
pushSyndicateMissions(worldState, day, rng.randomInt(0, 0xffff), "ba6f84724fa4804a", "CephalonSudaSyndicate");
pushSyndicateMissions(worldState, day, rng.randomInt(0, 0xffff), "ba6f84724fa4804e", "NewLokaSyndicate");
pushSyndicateMissions(worldState, day, rng.randomInt(0, 0xffff), "ba6f84724fa48050", "PerrinSyndicate");
pushSyndicateMissions(worldState, day, rng.randomInt(0, 0xffff), "ba6f84724fa4805e", "RedVeilSyndicate");
pushSyndicateMissions(worldState, day, rng.randomInt(0, 0xffff), "ba6f84724fa48061", "SteelMeridianSyndicate");
}; };
const dailyChallenges = Object.keys(ExportNightwave.challenges).filter(x => const dailyChallenges = Object.keys(ExportNightwave.challenges).filter(x =>
@ -1099,8 +1082,25 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
} }
// Sortie & syndicate missions cycling every day (at 16:00 or 17:00 UTC depending on if London, OT is observing DST) // Sortie & syndicate missions cycling every day (at 16:00 or 17:00 UTC depending on if London, OT is observing DST)
pushSortieIfRelevant(worldState, day - 1); {
pushSortieIfRelevant(worldState, day); const rollover = getSortieTime(day);
if (Date.now() < rollover) {
worldState.Sorties.push(getSortie(day - 1));
}
if (isBeforeNextExpectedWorldStateRefresh(rollover)) {
worldState.Sorties.push(getSortie(day));
}
// The client does not seem to respect activation for classic syndicate missions, so only pushing current ones.
const rng = new CRng(Date.now() >= rollover ? day : day - 1);
pushSyndicateMissions(worldState, day, rng.randomInt(0, 0xffff), "ba6f84724fa48049", "ArbitersSyndicate");
pushSyndicateMissions(worldState, day, rng.randomInt(0, 0xffff), "ba6f84724fa4804a", "CephalonSudaSyndicate");
pushSyndicateMissions(worldState, day, rng.randomInt(0, 0xffff), "ba6f84724fa4804e", "NewLokaSyndicate");
pushSyndicateMissions(worldState, day, rng.randomInt(0, 0xffff), "ba6f84724fa48050", "PerrinSyndicate");
pushSyndicateMissions(worldState, day, rng.randomInt(0, 0xffff), "ba6f84724fa4805e", "RedVeilSyndicate");
pushSyndicateMissions(worldState, day, rng.randomInt(0, 0xffff), "ba6f84724fa48061", "SteelMeridianSyndicate");
}
// Archon Hunt cycling every week // Archon Hunt cycling every week
worldState.LiteSorties.push(getLiteSortie(week)); worldState.LiteSorties.push(getLiteSortie(week));
@ -1178,8 +1178,12 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
return worldState; return worldState;
}; };
export const idToDay = (id: string): number => {
return Math.trunc((parseInt(id.substring(0, 8), 16) * 1000 - EPOCH) / 86400_000);
};
export const idToWeek = (id: string): number => { export const idToWeek = (id: string): number => {
return (parseInt(id.substring(0, 8), 16) * 1000 - EPOCH) / 604800000; return Math.trunc((parseInt(id.substring(0, 8), 16) * 1000 - EPOCH) / 604800_000);
}; };
export const getLiteSortie = (week: number): ILiteSortie => { export const getLiteSortie = (week: number): ILiteSortie => {