Circuit, Nightwave, Elite santuary

This commit is contained in:
dutlist 2024-06-26 01:29:02 +02:00 committed by AMelonInsideLemon
parent abaddeb544
commit 9a43bb9a82
4 changed files with 4035 additions and 3566 deletions

File diff suppressed because it is too large Load Diff

View File

@ -339,14 +339,20 @@ const NodeOverrideSchema = new Schema<INodeOverride>({
Node: String, Node: String,
Faction: String, Faction: String,
CustomNpcEncounters: [String], CustomNpcEncounters: [String],
LevelOverride: String LevelOverride: String,
Seed: Number,
Hide: Boolean
}); });
NodeOverrideSchema.set("toJSON", { NodeOverrideSchema.set("toJSON", {
transform(_document, returnedObject) { transform(_document, returnedObject) {
returnedObject._id = { $oid: returnedObject._id.toString() }; returnedObject._id = { $oid: returnedObject._id.toString() };
returnedObject.Activation = { $date: { $numberLong: returnedObject.Activation.toString() } }; if (returnedObject.Activation !== undefined) {
returnedObject.Expiry = { $date: { $numberLong: returnedObject.Expiry.toString() } }; returnedObject.Activation = { $date: { $numberLong: returnedObject.Activation.toString() } };
}
if (returnedObject.Expiry !== undefined) {
returnedObject.Expiry = { $date: { $numberLong: returnedObject.Expiry.toString() } };
}
} }
}); });
@ -500,7 +506,7 @@ const ActiveChallengeSchema = new Schema<IActiveChallenge>({
Challenge: String Challenge: String
}); });
FeaturedGuildShema.set("toJSON", { ActiveChallengeSchema.set("toJSON", {
transform(_document, returnedObject) { transform(_document, returnedObject) {
returnedObject._id = { $oid: returnedObject._id.toString() }; returnedObject._id = { $oid: returnedObject._id.toString() };
returnedObject.Activation = { $date: { $numberLong: returnedObject.Activation.toString() } }; returnedObject.Activation = { $date: { $numberLong: returnedObject.Activation.toString() } };
@ -511,14 +517,25 @@ FeaturedGuildShema.set("toJSON", {
const SeasonInfoSchema = new Schema<ISeasonInfo>( const SeasonInfoSchema = new Schema<ISeasonInfo>(
{ {
AffiliationTag: String, AffiliationTag: String,
Activation: Number,
Expiry: Number,
Season: Number, Season: Number,
Phase: Number, Phase: Number,
Params: String, Params: String,
ActiveChallenges: [ActiveChallengeSchema] ActiveChallenges: [ActiveChallengeSchema],
UsedChallenges: [String]
}, },
{ _id: false } { _id: false }
); );
SeasonInfoSchema.set("toJSON", {
transform(_document, returnedObject) {
delete returnedObject.UsedChallenges;
returnedObject.Activation = { $date: { $numberLong: returnedObject.Activation.toString() } };
returnedObject.Expiry = { $date: { $numberLong: returnedObject.Expiry.toString() } };
}
});
const WorldStateSchema = new Schema<IWorldState>({ const WorldStateSchema = new Schema<IWorldState>({
Events: [EventSchema], Events: [EventSchema],
// Goals: [GoalSchema], // Goals: [GoalSchema],

View File

@ -1,7 +1,9 @@
import { WorldState } from "@/src/models/worldStateModel"; import { WorldState } from "@/src/models/worldStateModel";
import { unixTimesInMs } from "@/src/constants/timeConstants"; import { unixTimesInMs } from "@/src/constants/timeConstants";
import { import {
IActiveChallenge,
IActiveMission, IActiveMission,
IJob,
ILiteSortie, ILiteSortie,
ISortie, ISortie,
ISyndicateMission, ISyndicateMission,
@ -10,7 +12,7 @@ import {
} from "@/src/types/worldStateTypes"; } from "@/src/types/worldStateTypes";
import { getRandomNumber, getRandomKey } from "@/src/helpers/general"; import { getRandomNumber, getRandomKey } from "@/src/helpers/general";
import { getRandomNodes, getCurrentRotation } from "@/src/helpers/worldstateHelpers"; import { getRandomNodes, getCurrentRotation } from "@/src/helpers/worldstateHelpers";
import { ExportRailjack, ExportRegions } from "warframe-public-export-plus"; import { ExportRailjack, ExportRegions, ExportNightwave } from "warframe-public-export-plus";
import { logger } from "@/src/utils/logger"; import { logger } from "@/src/utils/logger";
import { import {
factionSyndicates, factionSyndicates,
@ -19,18 +21,22 @@ import {
restSyndicates, restSyndicates,
CertusNormalJobs, CertusNormalJobs,
CertusNarmerJobs, CertusNarmerJobs,
ZarimanNormalJobs, EntratiNormalJobs,
voidFisuresMissionTypes, missionIndexToMissionTypes,
validFisureMissionIndex, validFisureMissionIndex,
omniaNodes, omniaNodes,
liteSortiesBoss, liteSortiesBosses,
endStates, endStates,
modifierTypes, modifierTypes,
SortiesMissionTypes,
voidTiers, voidTiers,
FortunaNarmerJobs, FortunaNarmerJobs,
FortunaNormalJobs FortunaNormalJobs,
liteSortiesMissionIndex,
EntratiEndlessJobs,
normalCircutRotations,
hardCircutRotations
} from "@/src/constants/worldStateConstants"; } from "@/src/constants/worldStateConstants";
import { config } from "./configService";
export const createWorldState = async () => { export const createWorldState = async () => {
const worldState = new WorldState(); const worldState = new WorldState();
@ -38,6 +44,9 @@ export const createWorldState = async () => {
await updateSyndicateMissions(); await updateSyndicateMissions();
await updateVoidFisures(); await updateVoidFisures();
await updateSorties(); await updateSorties();
await updateCircuit();
await updateNigthWave();
await updateNodeOverrides();
return worldState; return worldState;
}; };
@ -56,6 +65,9 @@ export const worldStateRunner = async () => {
await updateSyndicateMissions(); await updateSyndicateMissions();
await updateVoidFisures(); await updateVoidFisures();
await updateSorties(); await updateSorties();
await updateCircuit();
await updateNigthWave();
await updateNodeOverrides();
}, unixTimesInMs.minute); }, unixTimesInMs.minute);
}; };
@ -164,7 +176,7 @@ const getJobs = (tag: string) => {
const rotration = getCurrentRotation(); const rotration = getCurrentRotation();
switch (tag) { switch (tag) {
case "CetusSyndicate": case "CetusSyndicate":
const Certusjobs = [ const CertusJobs: IJob[] = [
{ {
jobType: CertusNormalJobs[Math.floor(Math.random() * CertusNormalJobs.length)], jobType: CertusNormalJobs[Math.floor(Math.random() * CertusNormalJobs.length)],
rewards: `/Lotus/Types/Game/MissionDecks/EidolonJobMissionRewards/TierATable${rotration}Rewards`, rewards: `/Lotus/Types/Game/MissionDecks/EidolonJobMissionRewards/TierATable${rotration}Rewards`,
@ -222,10 +234,10 @@ const getJobs = (tag: string) => {
xpAmounts: [820, 820, 820, 820, 1610] xpAmounts: [820, 820, 820, 820, 1610]
} }
]; ];
return Certusjobs; return CertusJobs;
case "SolarisSyndicate": case "SolarisSyndicate":
const FortunaJobs = [ const FortunaJobs: IJob[] = [
{ {
jobType: FortunaNormalJobs[Math.floor(Math.random() * FortunaNormalJobs.length)], jobType: FortunaNormalJobs[Math.floor(Math.random() * FortunaNormalJobs.length)],
rewards: `/Lotus/Types/Game/MissionDecks/VenusJobMissionRewards/VenusTierATable${rotration}Rewards`, rewards: `/Lotus/Types/Game/MissionDecks/VenusJobMissionRewards/VenusTierATable${rotration}Rewards`,
@ -286,9 +298,9 @@ const getJobs = (tag: string) => {
return FortunaJobs; return FortunaJobs;
case "EntratiSyndicate": case "EntratiSyndicate":
const ZarimanJobs = [ const EntratiJobs: IJob[] = [
{ {
jobType: ZarimanNormalJobs[Math.floor(Math.random() * ZarimanNormalJobs.length)], jobType: EntratiNormalJobs[Math.floor(Math.random() * EntratiNormalJobs.length)],
rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/TierATable${getRandomKey(["A", "B", "C"])}Rewards`, rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/TierATable${getRandomKey(["A", "B", "C"])}Rewards`,
masteryReq: 0, masteryReq: 0,
minEnemyLevel: 5, minEnemyLevel: 5,
@ -296,7 +308,7 @@ const getJobs = (tag: string) => {
xpAmounts: [5, 5, 5] xpAmounts: [5, 5, 5]
}, },
{ {
jobType: ZarimanNormalJobs[Math.floor(Math.random() * ZarimanNormalJobs.length)], jobType: EntratiNormalJobs[Math.floor(Math.random() * EntratiNormalJobs.length)],
rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/TierCTable${getRandomKey(["A", "B", "C"])}Rewards`, rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/TierCTable${getRandomKey(["A", "B", "C"])}Rewards`,
masteryReq: 1, masteryReq: 1,
minEnemyLevel: 15, minEnemyLevel: 15,
@ -304,7 +316,7 @@ const getJobs = (tag: string) => {
xpAmounts: [9, 9, 9] xpAmounts: [9, 9, 9]
}, },
{ {
jobType: ZarimanNormalJobs[Math.floor(Math.random() * ZarimanNormalJobs.length)], jobType: EntratiEndlessJobs[Math.floor(Math.random() * EntratiEndlessJobs.length)],
rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/TierBTable${getRandomKey(["A", "B", "C"])}Rewards`, rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/TierBTable${getRandomKey(["A", "B", "C"])}Rewards`,
masteryReq: 5, masteryReq: 5,
minEnemyLevel: 25, minEnemyLevel: 25,
@ -313,7 +325,7 @@ const getJobs = (tag: string) => {
xpAmounts: [14, 14, 14] xpAmounts: [14, 14, 14]
}, },
{ {
jobType: ZarimanNormalJobs[Math.floor(Math.random() * ZarimanNormalJobs.length)], jobType: EntratiNormalJobs[Math.floor(Math.random() * EntratiNormalJobs.length)],
rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/TierDTable${getRandomKey(["A", "B", "C"])}Rewards`, rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/TierDTable${getRandomKey(["A", "B", "C"])}Rewards`,
masteryReq: 2, masteryReq: 2,
minEnemyLevel: 30, minEnemyLevel: 30,
@ -321,7 +333,7 @@ const getJobs = (tag: string) => {
xpAmounts: [19, 19, 19, 29] xpAmounts: [19, 19, 19, 29]
}, },
{ {
jobType: ZarimanNormalJobs[Math.floor(Math.random() * ZarimanNormalJobs.length)], jobType: EntratiNormalJobs[Math.floor(Math.random() * EntratiNormalJobs.length)],
rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/TierETable${getRandomKey(["A", "B", "C"])}Rewards`, rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/TierETable${getRandomKey(["A", "B", "C"])}Rewards`,
masteryReq: 3, masteryReq: 3,
minEnemyLevel: 40, minEnemyLevel: 40,
@ -329,7 +341,7 @@ const getJobs = (tag: string) => {
xpAmounts: [21, 21, 21, 21, 41] xpAmounts: [21, 21, 21, 21, 41]
}, },
{ {
jobType: ZarimanNormalJobs[Math.floor(Math.random() * ZarimanNormalJobs.length)], jobType: EntratiNormalJobs[Math.floor(Math.random() * EntratiNormalJobs.length)],
rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/TierETable${getRandomKey(["A", "B", "C"])}Rewards`, rewards: `/Lotus/Types/Game/MissionDecks/DeimosMissionRewards/TierETable${getRandomKey(["A", "B", "C"])}Rewards`,
masteryReq: 10, masteryReq: 10,
minEnemyLevel: 100, minEnemyLevel: 100,
@ -364,7 +376,7 @@ const getJobs = (tag: string) => {
isVault: true isVault: true
} }
]; ];
return ZarimanJobs; return EntratiJobs;
default: default:
throw new Error(`Error while updating Syndicates: Unknown Jobs syndicate ${tag}`); throw new Error(`Error while updating Syndicates: Unknown Jobs syndicate ${tag}`);
@ -430,7 +442,7 @@ const updateVoidFisures = async () => {
Activation: curDate, Activation: curDate,
Expiry: curDate + Math.floor(Math.random() * unixTimesInMs.hour), Expiry: curDate + Math.floor(Math.random() * unixTimesInMs.hour),
Node: nodeData.nodeKey, Node: nodeData.nodeKey,
MissionType: voidFisuresMissionTypes[nodeData.missionIndex], MissionType: missionIndexToMissionTypes[nodeData.missionIndex],
Modifier: voidTier, Modifier: voidTier,
Hard: Math.random() < 0.1 Hard: Math.random() < 0.1
} as IActiveMission; } as IActiveMission;
@ -458,40 +470,34 @@ const updateVoidFisures = async () => {
const getRandomFisureNode = (isRailJack: boolean, isOmnia: boolean) => { const getRandomFisureNode = (isRailJack: boolean, isOmnia: boolean) => {
const validNodes = Object.entries(ExportRegions) const validNodes = Object.entries(ExportRegions)
.map(([key, node]) => { .map(([key, node]) => ({ ...node, nodeKey: key }))
return { .filter(node =>
...node, validFisureMissionIndex.includes(node.missionIndex) &&
nodeKey: key !node.missionName.includes("Archwing")
}; );
})
.filter(node => {
return validFisureMissionIndex.includes(node.missionIndex) && !node.missionName.includes("Archwing");
});
if (isRailJack) { if (isRailJack) {
const railJackNodes = Object.keys(ExportRailjack.nodes); const railJackNodes = Object.keys(ExportRailjack.nodes);
const randomKey = railJackNodes[Math.floor(Math.random() * railJackNodes.length)]; const randomKey = railJackNodes[Math.floor(Math.random() * railJackNodes.length)];
return { return { nodeKey: randomKey };
nodeKey: randomKey }
};
} else if (isOmnia) { if (isOmnia) {
const validOmniaNodes = validNodes.filter(node => { const validOmniaNodes = validNodes.filter(node => omniaNodes.includes(node.nodeKey));
return omniaNodes.includes(node.nodeKey);
});
const randomNode = validOmniaNodes[Math.floor(Math.random() * validOmniaNodes.length)]; const randomNode = validOmniaNodes[Math.floor(Math.random() * validOmniaNodes.length)];
return { return {
nodeKey: randomNode.nodeKey, nodeKey: randomNode.nodeKey,
systemIndex: randomNode.systemIndex, systemIndex: randomNode.systemIndex,
missionIndex: randomNode.missionIndex missionIndex: randomNode.missionIndex
}; };
} else {
const randomNode = validNodes[Math.floor(Math.random() * validNodes.length)];
return {
nodeKey: randomNode.nodeKey,
systemIndex: randomNode.systemIndex,
missionIndex: randomNode.missionIndex
};
} }
const randomNode = validNodes[Math.floor(Math.random() * validNodes.length)];
return {
nodeKey: randomNode.nodeKey,
systemIndex: randomNode.systemIndex,
missionIndex: randomNode.missionIndex
};
}; };
const updateSorties = async () => { const updateSorties = async () => {
@ -501,10 +507,11 @@ const updateSorties = async () => {
const oneDayIntervalEnd = oneDayIntervalStart + unixTimesInMs.day; const oneDayIntervalEnd = oneDayIntervalStart + unixTimesInMs.day;
const oneWeekIntervalStart = const oneWeekIntervalStart =
Math.floor(currentDate / (unixTimesInMs.day * 7)) * unixTimesInMs.day * 7 + 16 * unixTimesInMs.hour; Math.floor(currentDate / (unixTimesInMs.day * 7)) * unixTimesInMs.day * 7 + 16 * unixTimesInMs.hour;
const oneWeekIntervalEnd = oneDayIntervalStart + unixTimesInMs.day * 7; const oneWeekIntervalEnd = oneWeekIntervalStart + unixTimesInMs.day * 7;
const nodes = Object.entries(ExportRegions).map(([key, node]) => { const nodes = Object.entries(ExportRegions).map(([key, node]) => {
return { return {
nodeSystemIndex: node.systemIndex, systemIndex: node.systemIndex,
missionIndex: node.missionIndex,
nodeKey: key nodeKey: key
}; };
}); });
@ -520,95 +527,73 @@ const updateSorties = async () => {
}); });
if (liteSorties.length < 1) { if (liteSorties.length < 1) {
const sortie: ILiteSortie = { const liteSortiesBoss = liteSortiesBosses[Math.floor(Math.random() * liteSortiesBosses.length)];
const liteSortiesSystemIndex = nodes.filter(node => {
switch (liteSortiesBoss) {
case "SORTIE_BOSS_AMAR":
return node.systemIndex === 3;
case "SORTIE_BOSS_NIRA":
return node.systemIndex === 4;
case "SORTIE_BOSS_PAAZUL":
return node.systemIndex === 0;
default:
throw new Error(`Unknown liteSortiesBoss: ${liteSortiesBoss}`);
}
});
const filteredLiteSortiesNodes = liteSortiesMissionIndex.map(missionIndexArray =>
liteSortiesSystemIndex.filter(node =>
missionIndexArray.includes(node.missionIndex)
)
);
const selectedLiteSortiesNodes = filteredLiteSortiesNodes.map(filteredNodes =>
filteredNodes[Math.floor(Math.random() * filteredNodes.length)]
);
const sortie = {
Activation: oneWeekIntervalStart, Activation: oneWeekIntervalStart,
Expiry: oneWeekIntervalEnd, Expiry: oneWeekIntervalEnd,
Reward: "/Lotus/Types/Game/MissionDecks/ArchonSortieRewards", Reward: "/Lotus/Types/Game/MissionDecks/ArchonSortieRewards",
Seed: getRandomNumber(1, 99999), Seed: getRandomNumber(1, 99999),
Boss: liteSortiesBoss[Math.floor(Math.random() * liteSortiesBoss.length)], Boss: liteSortiesBoss,
Missions: [ Missions: selectedLiteSortiesNodes.map(node => ({
{ missionType: missionIndexToMissionTypes[node.missionIndex],
missionType: SortiesMissionTypes[Math.floor(Math.random() * SortiesMissionTypes.length)], node: node.nodeKey
node: nodes[Math.floor(Math.random() * nodes.length)].nodeKey }))
},
{
missionType: SortiesMissionTypes[Math.floor(Math.random() * SortiesMissionTypes.length)],
node: nodes[Math.floor(Math.random() * nodes.length)].nodeKey
},
{
missionType: SortiesMissionTypes[Math.floor(Math.random() * SortiesMissionTypes.length)],
node: nodes[Math.floor(Math.random() * nodes.length)].nodeKey
}
]
}; };
liteSorties.push(sortie); liteSorties.push(sortie);
} }
if (sorties.length < 1) { if (sorties.length < 1) {
const randomBoss = endStates[Math.floor(Math.random() * endStates.length)]; const randomState = endStates[Math.floor(Math.random() * endStates.length)];
const randomRegionIndex = [ const selectedSortieNodes = Array.from({ length: 3 }, () => {
Math.floor(Math.random() * randomBoss.regions.length), const randomIndex = Math.floor(Math.random() * randomState.regions.length);
Math.floor(Math.random() * randomBoss.regions.length), const filteredNodes = nodes.filter(node =>
Math.floor(Math.random() * randomBoss.regions.length) randomState.regions[randomIndex].systemIndex === node.systemIndex &&
]; randomState.regions[randomIndex].missionIndex.includes(node.missionIndex)
const randomRegionIndexFake = randomRegionIndex; );
randomRegionIndexFake.forEach((element, index, array) => { return filteredNodes[Math.floor(Math.random() * filteredNodes.length)];
if (element == 13) {
array[index] = element + 2;
} else if (element == 14) {
array[index] = element + 1;
}
}); });
const filteredNodes = [
nodes.filter(node => {
return randomRegionIndexFake[0] === node.nodeSystemIndex;
}),
nodes.filter(node => {
return randomRegionIndexFake[1] === node.nodeSystemIndex;
}),
nodes.filter(node => {
return randomRegionIndexFake[2] === node.nodeSystemIndex;
})
];
const sortie: ISortie = { const sortie: ISortie = {
Activation: oneDayIntervalStart, Activation: oneDayIntervalStart,
Expiry: oneDayIntervalEnd, Expiry: oneDayIntervalEnd,
ExtraDrops: [], ExtraDrops: [],
Reward: "/Lotus/Types/Game/MissionDecks/SortieRewards", Reward: "/Lotus/Types/Game/MissionDecks/SortieRewards",
Seed: getRandomNumber(1, 99999), Seed: getRandomNumber(1, 99999),
Boss: randomBoss.bossName, Boss: randomState.bossName,
Variants: [ Variants: selectedSortieNodes.map(node => ({
{ missionType: missionIndexToMissionTypes[node.missionIndex],
missionType: modifierType: modifierTypes[Math.floor(Math.random() * modifierTypes.length)],
randomBoss.regions[randomRegionIndex[0]].missions[ node: node.nodeKey,
Math.floor(Math.random() * randomBoss.regions[randomRegionIndex[0]].missions.length) tileset: "CorpusShipTileset" // needs more info about tilesets used in nodes
], })),
modifierType: modifierTypes[Math.floor(Math.random() * modifierTypes.length)],
node: filteredNodes[0][Math.floor(Math.random() * filteredNodes[0].length)].nodeKey,
tileset: "CorpusShipTileset"
},
{
missionType:
randomBoss.regions[randomRegionIndex[1]].missions[
Math.floor(Math.random() * randomBoss.regions[randomRegionIndex[1]].missions.length)
],
modifierType: modifierTypes[Math.floor(Math.random() * modifierTypes.length)],
node: filteredNodes[1][Math.floor(Math.random() * filteredNodes[1].length)].nodeKey,
tileset: "OrokinMoonTilesetCorpus"
},
{
missionType:
randomBoss.regions[randomRegionIndex[2]].missions[
Math.floor(Math.random() * randomBoss.regions[randomRegionIndex[2]].missions.length)
],
modifierType: modifierTypes[Math.floor(Math.random() * modifierTypes.length)],
node: filteredNodes[2][Math.floor(Math.random() * filteredNodes[2].length)].nodeKey,
tileset: "CorpusShipTileset"
}
],
Twitter: true Twitter: true
}; };
sorties.push(sortie); sorties.push(sortie);
} }
await ws.save(); await ws.save();
@ -617,3 +602,143 @@ const updateSorties = async () => {
throw new Error(`Error while updating Sorties ${error}`); throw new Error(`Error while updating Sorties ${error}`);
} }
}; };
const updateCircuit = async () => {
try {
const ws = await WorldState.findOne();
if (!ws) throw new Error("Missing worldState");
const curWeek = Math.floor(Date.now()/(7*unixTimesInMs.day));
const normalIndex = curWeek % 11;
const hardIndex = curWeek % 7;
ws.EndlessXpChoices = [
{ "Category": "EXC_NORMAL", "Choices": normalCircutRotations[normalIndex] },
{ "Category": "EXC_HARD", "Choices": hardCircutRotations[hardIndex] }
];
await ws.save();
return ws;
} catch (error) {
throw new Error(`Error while updating Circuit ${error}`);
}
};
const updateNigthWave = async () => {
const currentDate = Date.now();
const oneDayIntervalStart =
Math.floor(currentDate / unixTimesInMs.day) * unixTimesInMs.day + 16 * unixTimesInMs.hour;
const oneDayIntervalEnd = oneDayIntervalStart + unixTimesInMs.day;
const oneWeekIntervalStart =
Math.floor(currentDate / (unixTimesInMs.day * 7)) * unixTimesInMs.day * 7 + 16 * unixTimesInMs.hour;
const oneWeekIntervalEnd = oneWeekIntervalStart + unixTimesInMs.day * 7;
try {
const ws = await WorldState.findOne();
if (!ws) throw new Error("Missing worldState");
let season = ws.SeasonInfo
if(!season) season = {
Activation: 1715796000000,
Expiry: 9999999999999,
AffiliationTag: "RadioLegionIntermission10Syndicate",
Season: 12,
Phase: 0,
Params: "",
ActiveChallenges: [],
UsedChallenges: []
}
const activeChallenges = season.ActiveChallenges.filter(challenge => currentDate < challenge.Expiry)
const usedChallenges = season.UsedChallenges
const exportChallenges = Object.keys(ExportNightwave.challenges);
const filterChallenges = (prefix: string) => exportChallenges.filter(challenge => challenge.startsWith(prefix));
const dailyChallenges = filterChallenges("/Lotus/Types/Challenges/Seasons/Daily/");
const weeklyChallenges = filterChallenges("/Lotus/Types/Challenges/Seasons/Weekly/");
const weeklyHardChallenges = filterChallenges("/Lotus/Types/Challenges/Seasons/WeeklyHard/");
let dailyCount = 0, weeklyCount = 0, weeklyHardCount = 0;
activeChallenges.forEach(challenge => {
if (challenge.Challenge.startsWith("/Lotus/Types/Challenges/Seasons/Daily/")) dailyCount++;
else if (challenge.Challenge.startsWith("/Lotus/Types/Challenges/Seasons/Weekly/")) weeklyCount++;
else if (challenge.Challenge.startsWith("/Lotus/Types/Challenges/Seasons/WeeklyHard/")) weeklyHardCount++;
});
const addChallenges = async (count: number, limit: number, intervalStart: number, intervalEnd: number, challengesArray: string[], isDaily = false) => {
while (count < limit) {
challengesArray = challengesArray.filter(challenge => !usedChallenges.includes(challenge))
const uniqueName = challengesArray[Math.floor(Math.random() * challengesArray.length)]
const challenge: IActiveChallenge = {
Activation: intervalStart,
Expiry: intervalEnd,
Challenge: uniqueName
};
if (isDaily){
challenge.Daily = true;
} else {
usedChallenges.push(uniqueName)
}
activeChallenges.push(challenge);
count++;
}
};
await addChallenges(dailyCount, 3, oneDayIntervalStart, oneDayIntervalEnd, dailyChallenges, true);
await addChallenges(weeklyCount, 5, oneWeekIntervalStart, oneWeekIntervalEnd, weeklyChallenges);
await addChallenges(weeklyHardCount, 2, oneWeekIntervalStart, oneWeekIntervalEnd, weeklyHardChallenges);
season = {
Activation: season.Activation || 1715796000000,
Expiry: season.Expiry || 9999999999999,
AffiliationTag: season.AffiliationTag || "RadioLegionIntermission10Syndicate",
Season: season.Season || 12,
Phase: season.Phase || 0,
Params: season.Params || "",
ActiveChallenges: activeChallenges,
UsedChallenges: usedChallenges
}
ws.SeasonInfo = season
await ws.save();
return ws
} catch (error) {
throw new Error(`Error while updating NigthWave ${error}`);
}
};
const updateNodeOverrides = async () => {
try {
const ws = await WorldState.findOne();
if (!ws) throw new Error("Missing worldState");
const curWeek = Math.floor(Date.now()/(7*unixTimesInMs.day));
let overrides = ws.NodeOverrides
if(overrides == undefined || overrides.length<1 ){
overrides = [
{ "Node": "EuropaHUB", "Hide": true },
{ "Node": "ErisHUB", "Hide": true },
{ "Node": "VenusHUB", "Hide": true },
{ "Node": "SolNode802", "Seed": curWeek }, // Elite santuary onnslaught
{
"Node": "EarthHUB",
"Hide": false,
"LevelOverride": "/Lotus/Levels/Proc/Hub/RelayStationHubTwoB",
},
{
"Node": "MercuryHUB",
"Hide": true,
"LevelOverride": "/Lotus/Levels/Proc/Hub/RelayStationHubHydroid",
}
];
} else {
const solNodeIndex = overrides.findIndex(node => node.Node === "SolNode802");
if (solNodeIndex !== -1) {
if (overrides[solNodeIndex].Seed !== curWeek) overrides[solNodeIndex].Seed = curWeek;
} else {
overrides.push({ "Node": "SolNode802", "Seed": curWeek });
}
}
ws.NodeOverrides = overrides
await ws.save();
return ws;
} catch (error) {
throw new Error(`Error while updating NodeOverrides ${error}`);
}
}

View File

@ -205,6 +205,8 @@ export interface INodeOverride {
Faction?: string; Faction?: string;
CustomNpcEncounters?: string[]; CustomNpcEncounters?: string[];
LevelOverride?: string; LevelOverride?: string;
Seed?: number;
Hide?: boolean;
} }
export interface IVoidTrader extends IBaseWorldStateObject { export interface IVoidTrader extends IBaseWorldStateObject {
@ -285,6 +287,7 @@ export interface ISeasonInfo extends Omit<IBaseWorldStateObject, "_id"> {
Phase: number; Phase: number;
Params: string; Params: string;
ActiveChallenges: IActiveChallenge[]; ActiveChallenges: IActiveChallenge[];
UsedChallenges: string[];
} }
export interface IActiveChallenge extends IBaseWorldStateObject { export interface IActiveChallenge extends IBaseWorldStateObject {
@ -321,7 +324,7 @@ export interface IWorldState {
EndlessXpChoices?: IEndlessXpChoice[]; EndlessXpChoices?: IEndlessXpChoice[];
ForceLogoutVersion?: number; ForceLogoutVersion?: number;
FeaturedGuilds?: IFeaturedGuild[]; FeaturedGuilds?: IFeaturedGuild[];
SeasonInfo?: ISeasonInfo; SeasonInfo: ISeasonInfo;
Tmp?: string; Tmp?: string;
// Unkown // Unkown