Compare commits
7 Commits
630d7471f2
...
24d778371f
Author | SHA1 | Date | |
---|---|---|---|
24d778371f | |||
aa2c71a206 | |||
6fe0a42b13 | |||
6104eeb524 | |||
3bc08e0c19 | |||
8d30cedf82 | |||
c19780fc1d |
17
AGENTS.md
17
AGENTS.md
@ -1,17 +0,0 @@
|
|||||||
## In General
|
|
||||||
|
|
||||||
### Prerequisites
|
|
||||||
|
|
||||||
Use `npm i` or `npm ci` to install all dependencies.
|
|
||||||
|
|
||||||
### Testing
|
|
||||||
|
|
||||||
Use `npm run verify` to verify that your changes pass TypeScript's checks.
|
|
||||||
|
|
||||||
### Formatting
|
|
||||||
|
|
||||||
Use `npm run prettier` to ensure your formatting matches the expected format. Failing to do so will cause CI failure.
|
|
||||||
|
|
||||||
## WebUI Specific
|
|
||||||
|
|
||||||
The translation system is designed around additions being made to `static/webui/translations/en.js`. They are copied over for translation via `npm run update-translations`. DO NOT produce non-English strings; we want them to be translated by humans who can understand the full context.
|
|
@ -59,10 +59,6 @@
|
|||||||
"unlockAllSimarisResearchEntries": false,
|
"unlockAllSimarisResearchEntries": false,
|
||||||
"spoofMasteryRank": -1,
|
"spoofMasteryRank": -1,
|
||||||
"nightwaveStandingMultiplier": 1,
|
"nightwaveStandingMultiplier": 1,
|
||||||
"unfaithfulBugFixes": {
|
|
||||||
"ignore1999LastRegionPlayed": false,
|
|
||||||
"fixXtraCheeseTimer": false
|
|
||||||
},
|
|
||||||
"worldState": {
|
"worldState": {
|
||||||
"creditBoost": false,
|
"creditBoost": false,
|
||||||
"affinityBoost": false,
|
"affinityBoost": false,
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { checkCalendarChallengeCompletion, getCalendarProgress, getInventory } from "@/src/services/inventoryService";
|
import { getCalendarProgress, getInventory } from "@/src/services/inventoryService";
|
||||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||||
import { handleStoreItemAcquisition } from "@/src/services/purchaseService";
|
import { handleStoreItemAcquisition } from "@/src/services/purchaseService";
|
||||||
import { getWorldState } from "@/src/services/worldStateService";
|
import { getWorldState } from "@/src/services/worldStateService";
|
||||||
@ -12,23 +12,27 @@ export const completeCalendarEventController: RequestHandler = async (req, res)
|
|||||||
const calendarProgress = getCalendarProgress(inventory);
|
const calendarProgress = getCalendarProgress(inventory);
|
||||||
const currentSeason = getWorldState().KnownCalendarSeasons[0];
|
const currentSeason = getWorldState().KnownCalendarSeasons[0];
|
||||||
let inventoryChanges: IInventoryChanges = {};
|
let inventoryChanges: IInventoryChanges = {};
|
||||||
const dayIndex = calendarProgress.SeasonProgress.LastCompletedDayIdx + 1;
|
let dayIndex = 0;
|
||||||
const day = currentSeason.Days[dayIndex];
|
for (const day of currentSeason.Days) {
|
||||||
|
if (day.events.length == 0 || day.events[0].type != "CET_CHALLENGE") {
|
||||||
|
if (dayIndex == calendarProgress.SeasonProgress.LastCompletedDayIdx) {
|
||||||
if (day.events.length != 0) {
|
if (day.events.length != 0) {
|
||||||
if (day.events[0].type == "CET_CHALLENGE") {
|
|
||||||
throw new Error(`completeCalendarEvent should not be used for challenges`);
|
|
||||||
}
|
|
||||||
const selection = day.events[parseInt(req.query.CompletedEventIdx as string)];
|
const selection = day.events[parseInt(req.query.CompletedEventIdx as string)];
|
||||||
if (selection.type == "CET_REWARD") {
|
if (selection.type == "CET_REWARD") {
|
||||||
inventoryChanges = (await handleStoreItemAcquisition(selection.reward!, inventory)).InventoryChanges;
|
inventoryChanges = (await handleStoreItemAcquisition(selection.reward!, inventory))
|
||||||
|
.InventoryChanges;
|
||||||
} else if (selection.type == "CET_UPGRADE") {
|
} else if (selection.type == "CET_UPGRADE") {
|
||||||
calendarProgress.YearProgress.Upgrades.push(selection.upgrade!);
|
calendarProgress.YearProgress.Upgrades.push(selection.upgrade!);
|
||||||
} else if (selection.type != "CET_PLOT") {
|
} else if (selection.type != "CET_PLOT") {
|
||||||
throw new Error(`unexpected selection type: ${selection.type}`);
|
throw new Error(`unexpected selection type: ${selection.type}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
calendarProgress.SeasonProgress.LastCompletedDayIdx = dayIndex;
|
break;
|
||||||
checkCalendarChallengeCompletion(calendarProgress, currentSeason);
|
}
|
||||||
|
++dayIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
calendarProgress.SeasonProgress.LastCompletedDayIdx++;
|
||||||
await inventory.save();
|
await inventory.save();
|
||||||
res.json({
|
res.json({
|
||||||
InventoryChanges: inventoryChanges,
|
InventoryChanges: inventoryChanges,
|
||||||
|
@ -8,15 +8,16 @@ import {
|
|||||||
getKnifeUpgrade,
|
getKnifeUpgrade,
|
||||||
getNemesisManifest,
|
getNemesisManifest,
|
||||||
getNemesisPasscode,
|
getNemesisPasscode,
|
||||||
|
getNemesisPasscodeModTypes,
|
||||||
GUESS_CORRECT,
|
GUESS_CORRECT,
|
||||||
GUESS_INCORRECT,
|
GUESS_INCORRECT,
|
||||||
GUESS_NEUTRAL,
|
GUESS_NEUTRAL,
|
||||||
GUESS_NONE,
|
GUESS_NONE,
|
||||||
GUESS_WILDCARD,
|
GUESS_WILDCARD,
|
||||||
IKnifeResponse,
|
IKnifeResponse
|
||||||
parseUpgrade
|
|
||||||
} from "@/src/helpers/nemesisHelpers";
|
} from "@/src/helpers/nemesisHelpers";
|
||||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
||||||
|
import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
|
||||||
import { Loadout } from "@/src/models/inventoryModels/loadoutModel";
|
import { Loadout } from "@/src/models/inventoryModels/loadoutModel";
|
||||||
import { freeUpSlot, getInventory } from "@/src/services/inventoryService";
|
import { freeUpSlot, getInventory } from "@/src/services/inventoryService";
|
||||||
import { getAccountForRequest } from "@/src/services/loginService";
|
import { getAccountForRequest } from "@/src/services/loginService";
|
||||||
@ -214,19 +215,7 @@ export const nemesisController: RequestHandler = async (req, res) => {
|
|||||||
}
|
}
|
||||||
];
|
];
|
||||||
inventory.Nemesis!.Weakened = true;
|
inventory.Nemesis!.Weakened = true;
|
||||||
|
await consumePasscodeModCharges(inventory, response);
|
||||||
// Subtract a charge from all requiem mods installed on parazon
|
|
||||||
const loadout = (await Loadout.findById(inventory.LoadOutPresets, "DATAKNIFE"))!;
|
|
||||||
const dataknifeLoadout = loadout.DATAKNIFE.id(
|
|
||||||
inventory.CurrentLoadOutIds[LoadoutIndex.DATAKNIFE].$oid
|
|
||||||
);
|
|
||||||
const dataknifeConfigIndex = dataknifeLoadout?.s?.mod ?? 0;
|
|
||||||
const dataknifeUpgrades = inventory.DataKnives[0].Configs[dataknifeConfigIndex].Upgrades!;
|
|
||||||
for (let i = 3; i != 6; ++i) {
|
|
||||||
//logger.debug(`subtracting a charge from ${dataknifeUpgrades[i]}`);
|
|
||||||
const upgrade = parseUpgrade(inventory, dataknifeUpgrades[i]);
|
|
||||||
consumeModCharge(response, inventory, upgrade, dataknifeUpgrades);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Guess was incorrect, increase rank
|
// Guess was incorrect, increase rank
|
||||||
@ -391,3 +380,18 @@ interface IKnife {
|
|||||||
AttachedUpgrades: IUpgradeClient[];
|
AttachedUpgrades: IUpgradeClient[];
|
||||||
HiddenWhenHolstered: boolean;
|
HiddenWhenHolstered: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const consumePasscodeModCharges = async (
|
||||||
|
inventory: TInventoryDatabaseDocument,
|
||||||
|
response: IKnifeResponse
|
||||||
|
): Promise<void> => {
|
||||||
|
const loadout = (await Loadout.findById(inventory.LoadOutPresets, "DATAKNIFE"))!;
|
||||||
|
const dataknifeLoadout = loadout.DATAKNIFE.id(inventory.CurrentLoadOutIds[LoadoutIndex.DATAKNIFE].$oid);
|
||||||
|
const dataknifeConfigIndex = dataknifeLoadout?.s?.mod ?? 0;
|
||||||
|
const dataknifeUpgrades = inventory.DataKnives[0].Configs[dataknifeConfigIndex].Upgrades!;
|
||||||
|
const modTypes = getNemesisPasscodeModTypes(inventory.Nemesis!);
|
||||||
|
for (const modType of modTypes) {
|
||||||
|
const upgrade = getKnifeUpgrade(inventory, dataknifeUpgrades, modType);
|
||||||
|
consumeModCharge(response, inventory, upgrade, dataknifeUpgrades);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
@ -13,7 +13,7 @@ export const updateChallengeProgressController: RequestHandler = async (req, res
|
|||||||
|
|
||||||
const inventory = await getInventory(
|
const inventory = await getInventory(
|
||||||
account._id.toString(),
|
account._id.toString(),
|
||||||
"ChallengesFixVersion ChallengeProgress SeasonChallengeHistory Affiliations CalendarProgress"
|
"ChallengesFixVersion ChallengeProgress SeasonChallengeHistory Affiliations"
|
||||||
);
|
);
|
||||||
let affiliationMods: IAffiliationMods[] = [];
|
let affiliationMods: IAffiliationMods[] = [];
|
||||||
if (challenges.ChallengeProgress) {
|
if (challenges.ChallengeProgress) {
|
||||||
|
@ -237,7 +237,7 @@ export const getNemesisPasscode = (nemesis: { fp: bigint; Faction: TNemesisFacti
|
|||||||
return passcode;
|
return passcode;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*const requiemMods: readonly string[] = [
|
const requiemMods: readonly string[] = [
|
||||||
"/Lotus/Upgrades/Mods/Immortal/ImmortalOneMod",
|
"/Lotus/Upgrades/Mods/Immortal/ImmortalOneMod",
|
||||||
"/Lotus/Upgrades/Mods/Immortal/ImmortalTwoMod",
|
"/Lotus/Upgrades/Mods/Immortal/ImmortalTwoMod",
|
||||||
"/Lotus/Upgrades/Mods/Immortal/ImmortalThreeMod",
|
"/Lotus/Upgrades/Mods/Immortal/ImmortalThreeMod",
|
||||||
@ -246,7 +246,7 @@ export const getNemesisPasscode = (nemesis: { fp: bigint; Faction: TNemesisFacti
|
|||||||
"/Lotus/Upgrades/Mods/Immortal/ImmortalSixMod",
|
"/Lotus/Upgrades/Mods/Immortal/ImmortalSixMod",
|
||||||
"/Lotus/Upgrades/Mods/Immortal/ImmortalSevenMod",
|
"/Lotus/Upgrades/Mods/Immortal/ImmortalSevenMod",
|
||||||
"/Lotus/Upgrades/Mods/Immortal/ImmortalEightMod"
|
"/Lotus/Upgrades/Mods/Immortal/ImmortalEightMod"
|
||||||
];*/
|
];
|
||||||
|
|
||||||
export const antivirusMods: readonly string[] = [
|
export const antivirusMods: readonly string[] = [
|
||||||
"/Lotus/Upgrades/Mods/Immortal/AntivirusOneMod",
|
"/Lotus/Upgrades/Mods/Immortal/AntivirusOneMod",
|
||||||
@ -259,12 +259,12 @@ export const antivirusMods: readonly string[] = [
|
|||||||
"/Lotus/Upgrades/Mods/Immortal/AntivirusEightMod"
|
"/Lotus/Upgrades/Mods/Immortal/AntivirusEightMod"
|
||||||
];
|
];
|
||||||
|
|
||||||
/*export const getNemesisPasscodeModTypes = (nemesis: { fp: bigint; Faction: TNemesisFaction }): string[] => {
|
export const getNemesisPasscodeModTypes = (nemesis: { fp: bigint; Faction: TNemesisFaction }): string[] => {
|
||||||
const passcode = getNemesisPasscode(nemesis);
|
const passcode = getNemesisPasscode(nemesis);
|
||||||
return nemesis.Faction == "FC_INFESTATION"
|
return nemesis.Faction == "FC_INFESTATION"
|
||||||
? passcode.map(i => antivirusMods[i])
|
? passcode.map(i => antivirusMods[i])
|
||||||
: passcode.map(i => requiemMods[i]);
|
: passcode.map(i => requiemMods[i]);
|
||||||
};*/
|
};
|
||||||
|
|
||||||
// Symbols; 0-7 are the normal requiem mods.
|
// Symbols; 0-7 are the normal requiem mods.
|
||||||
export const GUESS_NONE = 8;
|
export const GUESS_NONE = 8;
|
||||||
@ -343,27 +343,6 @@ export const getKnifeUpgrade = (
|
|||||||
throw new Error(`${type} does not seem to be installed on parazon?!`);
|
throw new Error(`${type} does not seem to be installed on parazon?!`);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const parseUpgrade = (
|
|
||||||
inventory: TInventoryDatabaseDocument,
|
|
||||||
str: string
|
|
||||||
): { ItemId: IOid; ItemType: string } => {
|
|
||||||
if (str.length == 24) {
|
|
||||||
const upgrade = inventory.Upgrades.id(str);
|
|
||||||
if (upgrade) {
|
|
||||||
return {
|
|
||||||
ItemId: { $oid: str },
|
|
||||||
ItemType: upgrade.ItemType
|
|
||||||
};
|
|
||||||
}
|
|
||||||
throw new Error(`Could not resolve oid ${str}`);
|
|
||||||
} else {
|
|
||||||
return {
|
|
||||||
ItemId: { $oid: "000000000000000000000000" },
|
|
||||||
ItemType: str
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const consumeModCharge = (
|
export const consumeModCharge = (
|
||||||
response: IKnifeResponse,
|
response: IKnifeResponse,
|
||||||
inventory: TInventoryDatabaseDocument,
|
inventory: TInventoryDatabaseDocument,
|
||||||
|
@ -66,10 +66,6 @@ export interface IConfig {
|
|||||||
unlockAllSimarisResearchEntries?: boolean;
|
unlockAllSimarisResearchEntries?: boolean;
|
||||||
spoofMasteryRank?: number;
|
spoofMasteryRank?: number;
|
||||||
nightwaveStandingMultiplier?: number;
|
nightwaveStandingMultiplier?: number;
|
||||||
unfaithfulBugFixes?: {
|
|
||||||
ignore1999LastRegionPlayed?: boolean;
|
|
||||||
fixXtraCheeseTimer?: boolean;
|
|
||||||
};
|
|
||||||
worldState?: {
|
worldState?: {
|
||||||
creditBoost?: boolean;
|
creditBoost?: boolean;
|
||||||
affinityBoost?: boolean;
|
affinityBoost?: boolean;
|
||||||
|
@ -84,11 +84,9 @@ import { getRandomElement, getRandomInt, getRandomWeightedReward, SRng } from ".
|
|||||||
import { createMessage } from "./inboxService";
|
import { createMessage } from "./inboxService";
|
||||||
import { getMaxStanding, getMinStanding } from "@/src/helpers/syndicateStandingHelper";
|
import { getMaxStanding, getMinStanding } from "@/src/helpers/syndicateStandingHelper";
|
||||||
import { getNightwaveSyndicateTag, getWorldState } from "./worldStateService";
|
import { getNightwaveSyndicateTag, getWorldState } from "./worldStateService";
|
||||||
import { ICalendarSeason } from "@/src/types/worldStateTypes";
|
|
||||||
import { generateNemesisProfile, INemesisProfile } from "../helpers/nemesisHelpers";
|
import { generateNemesisProfile, INemesisProfile } from "../helpers/nemesisHelpers";
|
||||||
import { TAccountDocument } from "./loginService";
|
import { TAccountDocument } from "./loginService";
|
||||||
import { unixTimesInMs } from "../constants/timeConstants";
|
import { unixTimesInMs } from "../constants/timeConstants";
|
||||||
import { addString } from "../helpers/stringHelpers";
|
|
||||||
|
|
||||||
export const createInventory = async (
|
export const createInventory = async (
|
||||||
accountOwnerId: Types.ObjectId,
|
accountOwnerId: Types.ObjectId,
|
||||||
@ -1785,10 +1783,6 @@ export const addChallenges = (
|
|||||||
} else {
|
} else {
|
||||||
inventory.ChallengeProgress.push({ Name, Progress });
|
inventory.ChallengeProgress.push({ Name, Progress });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Name.startsWith("Calendar")) {
|
|
||||||
addString(getCalendarProgress(inventory).SeasonProgress.ActivatedChallenges, Name);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const affiliationMods: IAffiliationMods[] = [];
|
const affiliationMods: IAffiliationMods[] = [];
|
||||||
@ -2035,20 +2029,6 @@ export const getCalendarProgress = (inventory: TInventoryDatabaseDocument): ICal
|
|||||||
return inventory.CalendarProgress;
|
return inventory.CalendarProgress;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const checkCalendarChallengeCompletion = (
|
|
||||||
calendarProgress: ICalendarProgress,
|
|
||||||
currentSeason: ICalendarSeason
|
|
||||||
): void => {
|
|
||||||
const dayIndex = calendarProgress.SeasonProgress.LastCompletedDayIdx + 1;
|
|
||||||
if (calendarProgress.SeasonProgress.LastCompletedChallengeDayIdx >= dayIndex) {
|
|
||||||
const day = currentSeason.Days[dayIndex];
|
|
||||||
if (day.events.length != 0 && day.events[0].type == "CET_CHALLENGE") {
|
|
||||||
//logger.debug(`already completed the challenge, skipping ahead`);
|
|
||||||
calendarProgress.SeasonProgress.LastCompletedDayIdx++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const giveNemesisWeaponRecipe = (
|
export const giveNemesisWeaponRecipe = (
|
||||||
inventory: TInventoryDatabaseDocument,
|
inventory: TInventoryDatabaseDocument,
|
||||||
weaponType: string,
|
weaponType: string,
|
||||||
|
@ -33,7 +33,6 @@ import {
|
|||||||
addSkin,
|
addSkin,
|
||||||
addStanding,
|
addStanding,
|
||||||
applyClientEquipmentUpdates,
|
applyClientEquipmentUpdates,
|
||||||
checkCalendarChallengeCompletion,
|
|
||||||
combineInventoryChanges,
|
combineInventoryChanges,
|
||||||
generateRewardSeed,
|
generateRewardSeed,
|
||||||
getCalendarProgress,
|
getCalendarProgress,
|
||||||
@ -68,15 +67,7 @@ import {
|
|||||||
} from "@/src/helpers/nemesisHelpers";
|
} 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 {
|
import { getLiteSortie, getSortie, idToBountyCycle, idToDay, idToWeek, pushClassicBounties } from "./worldStateService";
|
||||||
getLiteSortie,
|
|
||||||
getSortie,
|
|
||||||
getWorldState,
|
|
||||||
idToBountyCycle,
|
|
||||||
idToDay,
|
|
||||||
idToWeek,
|
|
||||||
pushClassicBounties
|
|
||||||
} 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";
|
||||||
import { ISyndicateMissionInfo } from "../types/worldStateTypes";
|
import { ISyndicateMissionInfo } from "../types/worldStateTypes";
|
||||||
@ -268,9 +259,7 @@ export const addMissionInventoryUpdates = async (
|
|||||||
addMissionComplete(inventory, value);
|
addMissionComplete(inventory, value);
|
||||||
break;
|
break;
|
||||||
case "LastRegionPlayed":
|
case "LastRegionPlayed":
|
||||||
if (!(config.unfaithfulBugFixes?.ignore1999LastRegionPlayed && value === "1999MapName")) {
|
|
||||||
inventory.LastRegionPlayed = value;
|
inventory.LastRegionPlayed = value;
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case "RawUpgrades":
|
case "RawUpgrades":
|
||||||
addMods(inventory, value);
|
addMods(inventory, value);
|
||||||
@ -631,11 +620,12 @@ export const addMissionInventoryUpdates = async (
|
|||||||
}
|
}
|
||||||
case "CalendarProgress": {
|
case "CalendarProgress": {
|
||||||
const calendarProgress = getCalendarProgress(inventory);
|
const calendarProgress = getCalendarProgress(inventory);
|
||||||
const currentSeason = getWorldState().KnownCalendarSeasons[0];
|
for (const progress of value) {
|
||||||
calendarProgress.SeasonProgress.LastCompletedChallengeDayIdx = currentSeason.Days.findIndex(
|
const challengeName = progress.challenge.substring(progress.challenge.lastIndexOf("/") + 1);
|
||||||
x => x.events[0].challenge == value[value.length - 1].challenge
|
calendarProgress.SeasonProgress.LastCompletedDayIdx++;
|
||||||
);
|
calendarProgress.SeasonProgress.LastCompletedChallengeDayIdx++;
|
||||||
checkCalendarChallengeCompletion(calendarProgress, currentSeason);
|
calendarProgress.SeasonProgress.ActivatedChallenges.push(challengeName);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "duviriCaveOffers": {
|
case "duviriCaveOffers": {
|
||||||
@ -1639,19 +1629,7 @@ function getRandomMissionDrops(
|
|||||||
}
|
}
|
||||||
rewardManifests = [job.rewards];
|
rewardManifests = [job.rewards];
|
||||||
if (job.xpAmounts.length > 1) {
|
if (job.xpAmounts.length > 1) {
|
||||||
const curentStage = RewardInfo.JobStage! + 1;
|
rotations = [RewardInfo.JobStage! % (job.xpAmounts.length - 1)];
|
||||||
const totalStage = job.xpAmounts.length;
|
|
||||||
let tableIndex = 1; // Stage 2, Stage 3 of 4, and Stage 3 of 5
|
|
||||||
|
|
||||||
if (curentStage == 1) {
|
|
||||||
tableIndex = 0;
|
|
||||||
} else if (curentStage == totalStage) {
|
|
||||||
tableIndex = 3;
|
|
||||||
} else if (totalStage == 5 && curentStage == 4) {
|
|
||||||
tableIndex = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
rotations = [tableIndex];
|
|
||||||
} else {
|
} else {
|
||||||
rotations = [0];
|
rotations = [0];
|
||||||
}
|
}
|
||||||
@ -1660,7 +1638,11 @@ function getRandomMissionDrops(
|
|||||||
(RewardInfo.JobStage === job.xpAmounts.length - 1 || job.isVault) &&
|
(RewardInfo.JobStage === job.xpAmounts.length - 1 || job.isVault) &&
|
||||||
!isEndlessJob
|
!isEndlessJob
|
||||||
) {
|
) {
|
||||||
rotations.push(3);
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||||
|
if (ExportRewards[job.rewards]) {
|
||||||
|
rewardManifests.push(job.rewards);
|
||||||
|
rotations.push(ExportRewards[job.rewards].length - 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ import { Account } from "../models/loginModel";
|
|||||||
import { createAccount, createNonce, getUsernameFromEmail, isCorrectPassword } from "./loginService";
|
import { createAccount, createNonce, getUsernameFromEmail, isCorrectPassword } from "./loginService";
|
||||||
import { IDatabaseAccountJson } from "../types/loginTypes";
|
import { IDatabaseAccountJson } from "../types/loginTypes";
|
||||||
import { HydratedDocument } from "mongoose";
|
import { HydratedDocument } from "mongoose";
|
||||||
import { Agent, WebSocket as UnidiciWebSocket } from "undici";
|
import { Agent, WebSocket } from "undici";
|
||||||
|
|
||||||
let httpServer: http.Server | undefined;
|
let httpServer: http.Server | undefined;
|
||||||
let httpsServer: https.Server | undefined;
|
let httpsServer: https.Server | undefined;
|
||||||
@ -46,9 +46,13 @@ export const startWebServer = (): void => {
|
|||||||
"Access the WebUI in your browser at http://localhost" + (httpPort == 80 ? "" : ":" + httpPort)
|
"Access the WebUI in your browser at http://localhost" + (httpPort == 80 ? "" : ":" + httpPort)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// https://github.com/oven-sh/bun/issues/20547
|
||||||
|
if (!process.versions.bun) {
|
||||||
void runWsSelfTest("wss", httpsPort).then(ok => {
|
void runWsSelfTest("wss", httpsPort).then(ok => {
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
logger.warn(`WSS self-test failed. The server may not actually be reachable at port ${httpsPort}.`);
|
logger.warn(
|
||||||
|
`WSS self-test failed. The server may not actually be reachable at port ${httpsPort}.`
|
||||||
|
);
|
||||||
if (process.platform == "win32") {
|
if (process.platform == "win32") {
|
||||||
logger.warn(
|
logger.warn(
|
||||||
`You can check who actually has that port via powershell: Get-Process -Id (Get-NetTCPConnection -LocalPort ${httpsPort}).OwningProcess`
|
`You can check who actually has that port via powershell: Get-Process -Id (Get-NetTCPConnection -LocalPort ${httpsPort}).OwningProcess`
|
||||||
@ -56,35 +60,21 @@ export const startWebServer = (): void => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const runWsSelfTest = (protocol: "ws" | "wss", port: number): Promise<boolean> => {
|
const runWsSelfTest = (protocol: "ws" | "wss", port: number): Promise<boolean> => {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
// https://github.com/oven-sh/bun/issues/20547
|
|
||||||
if (process.versions.bun) {
|
|
||||||
const client = new WebSocket(`${protocol}://localhost:${port}/custom/selftest`, {
|
|
||||||
tls: { rejectUnauthorized: false }
|
|
||||||
} as unknown as string);
|
|
||||||
client.onmessage = (e): void => {
|
|
||||||
resolve(e.data == "SpaceNinjaServer");
|
|
||||||
};
|
|
||||||
client.onerror = client.onclose = (): void => {
|
|
||||||
resolve(false);
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
const agent = new Agent({ connect: { rejectUnauthorized: false } });
|
const agent = new Agent({ connect: { rejectUnauthorized: false } });
|
||||||
const client = new UnidiciWebSocket(`${protocol}://localhost:${port}/custom/selftest`, {
|
const client = new WebSocket(`${protocol}://localhost:${port}/custom/selftest`, { dispatcher: agent });
|
||||||
dispatcher: agent
|
|
||||||
});
|
|
||||||
client.onmessage = (e): void => {
|
client.onmessage = (e): void => {
|
||||||
resolve(e.data == "SpaceNinjaServer");
|
resolve(e.data == "SpaceNinjaServer");
|
||||||
};
|
};
|
||||||
client.onerror = client.onclose = (): void => {
|
client.onerror = client.onclose = (): void => {
|
||||||
resolve(false);
|
resolve(false);
|
||||||
};
|
};
|
||||||
}
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1327,17 +1327,6 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
|
|||||||
const cheeseInterval = hourInSeconds * 8;
|
const cheeseInterval = hourInSeconds * 8;
|
||||||
const cheeseDuration = hourInSeconds * 2;
|
const cheeseDuration = hourInSeconds * 2;
|
||||||
const cheeseIndex = Math.trunc(timeSecs / cheeseInterval);
|
const cheeseIndex = Math.trunc(timeSecs / cheeseInterval);
|
||||||
let cheeseStart = cheeseIndex * cheeseInterval;
|
|
||||||
let cheeseEnd = cheeseStart + cheeseDuration;
|
|
||||||
let cheeseNext = (cheeseIndex + 1) * cheeseInterval;
|
|
||||||
// Live servers only update the start time once it happens, which makes the
|
|
||||||
// client show a negative countdown during off-hours. Optionally adjust the
|
|
||||||
// times so the next activation is always in the future.
|
|
||||||
if (config.unfaithfulBugFixes?.fixXtraCheeseTimer && timeSecs >= cheeseEnd) {
|
|
||||||
cheeseStart = cheeseNext;
|
|
||||||
cheeseEnd = cheeseStart + cheeseDuration;
|
|
||||||
cheeseNext += cheeseInterval;
|
|
||||||
}
|
|
||||||
const tmp: ITmp = {
|
const tmp: ITmp = {
|
||||||
cavabegin: "1690761600",
|
cavabegin: "1690761600",
|
||||||
PurchasePlatformLockEnabled: true,
|
PurchasePlatformLockEnabled: true,
|
||||||
@ -1362,9 +1351,9 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
|
|||||||
ennnd: true,
|
ennnd: true,
|
||||||
mbrt: true,
|
mbrt: true,
|
||||||
fbst: {
|
fbst: {
|
||||||
a: cheeseStart,
|
a: cheeseIndex * cheeseInterval, // This has a bug where the client shows a negative time for "Xtra cheese starts in ..." until it refreshes the world state. This is because we're only providing the new activation as soon as that time/date is reached. However, this is 100% faithful to live.
|
||||||
e: cheeseEnd,
|
e: cheeseIndex * cheeseInterval + cheeseDuration,
|
||||||
n: cheeseNext
|
n: (cheeseIndex + 1) * cheeseInterval
|
||||||
},
|
},
|
||||||
sfn: [550, 553, 554, 555][halfHour % 4]
|
sfn: [550, 553, 554, 555][halfHour % 4]
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user