Compare commits

..

12 Commits

Author SHA1 Message Date
cf68201ce5 make rewardInfo an optional argument
All checks were successful
Build / build (pull_request) Successful in 44s
Build / build (push) Successful in 1m26s
2025-04-15 19:49:18 +02:00
5d81e03e1a fix: respect VaultsCracked when rolling droptable for level key rewards 2025-04-15 19:49:18 +02:00
3165d9f459 fix: respect rewardTier for rescue missions (#1650)
All checks were successful
Build Docker image / docker (push) Successful in 46s
Build / build (push) Successful in 1m42s
Reviewed-on: #1650
Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com>
Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
2025-04-15 10:47:38 -07:00
28d7ca8ca0 chore: address eslint warnings
All checks were successful
Build Docker image / docker (push) Successful in 35s
Build / build (push) Successful in 1m33s
2025-04-15 18:48:17 +02:00
3f0a2bec48 fix: generate rewards based on RewardSeed to match what's show in client (#1628)
All checks were successful
Build Docker image / docker (push) Successful in 44s
Build / build (push) Successful in 1m29s
Reviewed-on: #1628
Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com>
Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
2025-04-15 09:46:08 -07:00
d28437b658 feat: give 5 steel essence when completing an SP incursion (#1637)
All checks were successful
Build Docker image / docker (push) Successful in 54s
Build / build (push) Successful in 54s
Closes #1631

Reviewed-on: #1637
Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com>
Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
2025-04-15 06:16:40 -07:00
a6d2c8b18a fix: don't give credits for junctions, the index, and free flight (#1635)
Some checks failed
Build / build (push) Has been cancelled
Build Docker image / docker (push) Has been cancelled
Closes #1625

Reviewed-on: #1635
Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com>
Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
2025-04-15 06:16:31 -07:00
0c884576bd feat: picking up prex cards (#1634)
Some checks failed
Build / build (push) Has been cancelled
Build Docker image / docker (push) Has been cancelled
Closes #1621

Reviewed-on: #1634
Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com>
Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
2025-04-15 06:16:19 -07:00
380f0662a4 fix: don't try to subtract MiscItems for polarity swap (#1633)
Some checks failed
Build / build (push) Has been cancelled
Build Docker image / docker (push) Has been cancelled
Closes #1620

Reviewed-on: #1633
Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com>
Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
2025-04-15 06:16:07 -07:00
bd83738168 fix: provide a response to setPlacedDecoInfo (#1632)
Some checks failed
Build / build (push) Has been cancelled
Build Docker image / docker (push) Has been cancelled
This seems to be needed for the client when refreshing the ship after loading into a mission as it does not resync the ship otherwise.

Closes #1629

Reviewed-on: #1632
Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com>
Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
2025-04-15 06:15:49 -07:00
fa68a1357d chore(webui): update to German translation (#1642)
Some checks failed
Build / build (push) Has been cancelled
Build Docker image / docker (push) Has been cancelled
Reviewed-on: #1642
Co-authored-by: Animan8000 <animan8000@noreply.localhost>
Co-committed-by: Animan8000 <animan8000@noreply.localhost>
2025-04-15 06:15:33 -07:00
43f3917b09 fix: additional checks in bounty rewards (#1626)
All checks were successful
Build Docker image / docker (push) Successful in 58s
Build / build (push) Successful in 1m28s
Reviewed-on: #1626
Co-authored-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com>
Co-committed-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com>
2025-04-15 06:10:25 -07:00
12 changed files with 133 additions and 44 deletions

View File

@ -1,14 +1,12 @@
import { Inventory } from "@/src/models/inventoryModels/inventoryModel"; import { Inventory } from "@/src/models/inventoryModels/inventoryModel";
import { generateRewardSeed } from "@/src/services/inventoryService"; import { generateRewardSeed } from "@/src/services/inventoryService";
import { getAccountIdForRequest } from "@/src/services/loginService"; import { getAccountIdForRequest } from "@/src/services/loginService";
import { logger } from "@/src/utils/logger";
import { RequestHandler } from "express"; import { RequestHandler } from "express";
export const getNewRewardSeedController: RequestHandler = async (req, res) => { export const getNewRewardSeedController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req); const accountId = await getAccountIdForRequest(req);
const rewardSeed = generateRewardSeed(); const rewardSeed = generateRewardSeed();
logger.debug(`generated new reward seed: ${rewardSeed}`);
await Inventory.updateOne( await Inventory.updateOne(
{ {
accountOwnerId: accountId accountOwnerId: accountId

View File

@ -0,0 +1,20 @@
import { getJSONfromString } from "@/src/helpers/stringHelpers";
import { addLoreFragmentScans, addShipDecorations, getInventory } from "@/src/services/inventoryService";
import { getAccountIdForRequest } from "@/src/services/loginService";
import { ILoreFragmentScan, ITypeCount } from "@/src/types/inventoryTypes/inventoryTypes";
import { RequestHandler } from "express";
export const giveShipDecoAndLoreFragmentController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req);
const inventory = await getInventory(accountId, "LoreFragmentScans ShipDecorations");
const data = getJSONfromString<IGiveShipDecoAndLoreFragmentRequest>(String(req.body));
addLoreFragmentScans(inventory, data.LoreFragmentScans);
addShipDecorations(inventory, data.ShipDecorations);
await inventory.save();
res.end();
};
interface IGiveShipDecoAndLoreFragmentRequest {
LoreFragmentScans: ILoreFragmentScan[];
ShipDecorations: ITypeCount[];
}

View File

@ -1,5 +1,5 @@
import { getAccountIdForRequest } from "@/src/services/loginService"; import { getAccountIdForRequest } from "@/src/services/loginService";
import { ISetPlacedDecoInfoRequest } from "@/src/types/shipTypes"; import { IPictureFrameInfo, ISetPlacedDecoInfoRequest } from "@/src/types/shipTypes";
import { RequestHandler } from "express"; import { RequestHandler } from "express";
import { handleSetPlacedDecoInfo } from "@/src/services/shipCustomizationsService"; import { handleSetPlacedDecoInfo } from "@/src/services/shipCustomizationsService";
@ -7,5 +7,17 @@ export const setPlacedDecoInfoController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req); const accountId = await getAccountIdForRequest(req);
const payload = JSON.parse(req.body as string) as ISetPlacedDecoInfoRequest; const payload = JSON.parse(req.body as string) as ISetPlacedDecoInfoRequest;
await handleSetPlacedDecoInfo(accountId, payload); await handleSetPlacedDecoInfo(accountId, payload);
res.end(); res.json({
DecoId: payload.DecoId,
IsPicture: true,
PictureFrameInfo: payload.PictureFrameInfo,
BootLocation: payload.BootLocation
} satisfies ISetPlacedDecoInfoResponse);
}; };
interface ISetPlacedDecoInfoResponse {
DecoId: string;
IsPicture: boolean;
PictureFrameInfo?: IPictureFrameInfo;
BootLocation?: string;
}

View File

@ -25,7 +25,13 @@ export const upgradesController: RequestHandler = async (req, res) => {
operation.UpgradeRequirement == "/Lotus/Types/Items/MiscItems/CustomizationSlotUnlocker" operation.UpgradeRequirement == "/Lotus/Types/Items/MiscItems/CustomizationSlotUnlocker"
) { ) {
updateCurrency(inventory, 10, true); updateCurrency(inventory, 10, true);
} else if (operation.OperationType != "UOT_ABILITY_OVERRIDE") { } else if (
operation.OperationType != "UOT_SWAP_POLARITY" &&
operation.OperationType != "UOT_ABILITY_OVERRIDE"
) {
if (!operation.UpgradeRequirement) {
throw new Error(`${operation.OperationType} operation should be free?`);
}
addMiscItems(inventory, [ addMiscItems(inventory, [
{ {
ItemType: operation.UpgradeRequirement, ItemType: operation.UpgradeRequirement,

View File

@ -1213,7 +1213,7 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
accountOwnerId: Schema.Types.ObjectId, accountOwnerId: Schema.Types.ObjectId,
SubscribedToEmails: { type: Number, default: 0 }, SubscribedToEmails: { type: Number, default: 0 },
SubscribedToEmailsPersonalized: { type: Number, default: 0 }, SubscribedToEmailsPersonalized: { type: Number, default: 0 },
RewardSeed: Number, RewardSeed: BigInt,
//Credit //Credit
RegularCredits: { type: Number, default: 0 }, RegularCredits: { type: Number, default: 0 },

View File

@ -62,6 +62,7 @@ import { gildWeaponController } from "@/src/controllers/api/gildWeaponController
import { giveKeyChainTriggeredItemsController } from "@/src/controllers/api/giveKeyChainTriggeredItemsController"; import { giveKeyChainTriggeredItemsController } from "@/src/controllers/api/giveKeyChainTriggeredItemsController";
import { giveKeyChainTriggeredMessageController } from "@/src/controllers/api/giveKeyChainTriggeredMessageController"; import { giveKeyChainTriggeredMessageController } from "@/src/controllers/api/giveKeyChainTriggeredMessageController";
import { giveQuestKeyRewardController } from "@/src/controllers/api/giveQuestKey"; import { giveQuestKeyRewardController } from "@/src/controllers/api/giveQuestKey";
import { giveShipDecoAndLoreFragmentController } from "@/src/controllers/api/giveShipDecoAndLoreFragmentController";
import { giveStartingGearController } from "@/src/controllers/api/giveStartingGearController"; import { giveStartingGearController } from "@/src/controllers/api/giveStartingGearController";
import { guildTechController } from "@/src/controllers/api/guildTechController"; import { guildTechController } from "@/src/controllers/api/guildTechController";
import { hostSessionController } from "@/src/controllers/api/hostSessionController"; import { hostSessionController } from "@/src/controllers/api/hostSessionController";
@ -239,6 +240,7 @@ apiRouter.post("/gildWeapon.php", gildWeaponController);
apiRouter.post("/giveKeyChainTriggeredItems.php", giveKeyChainTriggeredItemsController); apiRouter.post("/giveKeyChainTriggeredItems.php", giveKeyChainTriggeredItemsController);
apiRouter.post("/giveKeyChainTriggeredMessage.php", giveKeyChainTriggeredMessageController); apiRouter.post("/giveKeyChainTriggeredMessage.php", giveKeyChainTriggeredMessageController);
apiRouter.post("/giveQuestKeyReward.php", giveQuestKeyRewardController); apiRouter.post("/giveQuestKeyReward.php", giveQuestKeyRewardController);
apiRouter.post("/giveShipDecoAndLoreFragment.php", giveShipDecoAndLoreFragmentController);
apiRouter.post("/giveStartingGear.php", giveStartingGearController); apiRouter.post("/giveStartingGear.php", giveStartingGearController);
apiRouter.post("/guildTech.php", guildTechController); apiRouter.post("/guildTech.php", guildTechController);
apiRouter.post("/hostSession.php", hostSessionController); apiRouter.post("/hostSession.php", hostSessionController);

View File

@ -21,7 +21,8 @@ import {
ICalendarProgress, ICalendarProgress,
IDroneClient, IDroneClient,
IUpgradeClient, IUpgradeClient,
TPartialStartingGear TPartialStartingGear,
ILoreFragmentScan
} from "@/src/types/inventoryTypes/inventoryTypes"; } from "@/src/types/inventoryTypes/inventoryTypes";
import { IGenericUpdate, IUpdateNodeIntrosResponse } from "../types/genericUpdate"; import { IGenericUpdate, IUpdateNodeIntrosResponse } from "../types/genericUpdate";
import { IKeyChainRequest, IMissionInventoryUpdateRequest } from "../types/requestTypes"; import { IKeyChainRequest, IMissionInventoryUpdateRequest } from "../types/requestTypes";
@ -1350,6 +1351,17 @@ export const addFocusXpIncreases = (inventory: TInventoryDatabaseDocument, focus
inventory.DailyFocus -= focusXpPlus.reduce((a, b) => a + b, 0); inventory.DailyFocus -= focusXpPlus.reduce((a, b) => a + b, 0);
}; };
export const addLoreFragmentScans = (inventory: TInventoryDatabaseDocument, arr: ILoreFragmentScan[]): void => {
arr.forEach(clientFragment => {
const fragment = inventory.LoreFragmentScans.find(x => x.ItemType == clientFragment.ItemType);
if (fragment) {
fragment.Progress += clientFragment.Progress;
} else {
inventory.LoreFragmentScans.push(clientFragment);
}
});
};
export const addChallenges = ( export const addChallenges = (
inventory: TInventoryDatabaseDocument, inventory: TInventoryDatabaseDocument,
ChallengeProgress: IChallengeProgress[], ChallengeProgress: IChallengeProgress[],

View File

@ -9,7 +9,7 @@ import {
} from "warframe-public-export-plus"; } from "warframe-public-export-plus";
import { IMissionInventoryUpdateRequest, IRewardInfo } from "../types/requestTypes"; import { IMissionInventoryUpdateRequest, IRewardInfo } from "../types/requestTypes";
import { logger } from "@/src/utils/logger"; import { logger } from "@/src/utils/logger";
import { IRngResult, getRandomElement, getRandomReward } from "@/src/services/rngService"; import { IRngResult, SRng, getRandomElement, getRandomReward } from "@/src/services/rngService";
import { equipmentKeys, TEquipmentKey } from "@/src/types/inventoryTypes/inventoryTypes"; import { equipmentKeys, TEquipmentKey } from "@/src/types/inventoryTypes/inventoryTypes";
import { import {
addBooster, addBooster,
@ -23,6 +23,7 @@ import {
addGearExpByCategory, addGearExpByCategory,
addItem, addItem,
addLevelKeys, addLevelKeys,
addLoreFragmentScans,
addMiscItems, addMiscItems,
addMissionComplete, addMissionComplete,
addMods, addMods,
@ -30,6 +31,7 @@ import {
addShipDecorations, addShipDecorations,
addStanding, addStanding,
combineInventoryChanges, combineInventoryChanges,
generateRewardSeed,
updateCurrency, updateCurrency,
updateSyndicate updateSyndicate
} from "@/src/services/inventoryService"; } from "@/src/services/inventoryService";
@ -53,7 +55,22 @@ import { Loadout } from "../models/inventoryModels/loadoutModel";
import { ILoadoutConfigDatabase } from "../types/saveLoadoutTypes"; import { ILoadoutConfigDatabase } from "../types/saveLoadoutTypes";
import { getWorldState } from "./worldStateService"; import { getWorldState } from "./worldStateService";
const getRotations = (rotationCount: number, tierOverride: number | undefined): number[] => { const getRotations = (rewardInfo: IRewardInfo, tierOverride: number | undefined): number[] => {
// For Spy missions, e.g. 3 vaults cracked = A, B, C
if (rewardInfo.VaultsCracked) {
const rotations: number[] = [];
for (let i = 0; i != rewardInfo.VaultsCracked; ++i) {
rotations.push(i);
}
return rotations;
}
// For Rescue missions
if (rewardInfo.rewardTier) {
return [rewardInfo.rewardTier];
}
const rotationCount = rewardInfo.rewardQualifications?.length || 0;
if (rotationCount === 0) return [0]; if (rotationCount === 0) return [0];
const rotationPattern = const rotationPattern =
@ -69,7 +86,12 @@ const getRotations = (rotationCount: number, tierOverride: number | undefined):
return rotatedValues; return rotatedValues;
}; };
const getRandomRewardByChance = (pool: IReward[]): IRngResult | undefined => { const getRandomRewardByChance = (pool: IReward[], rng?: SRng): IRngResult | undefined => {
if (rng) {
const res = rng.randomReward(pool as IRngResult[]);
rng.randomFloat(); // something related to rewards multiplier
return res;
}
return getRandomReward(pool as IRngResult[]); return getRandomReward(pool as IRngResult[]);
}; };
@ -291,14 +313,7 @@ export const addMissionInventoryUpdates = async (
break; break;
} }
case "LoreFragmentScans": case "LoreFragmentScans":
value.forEach(clientFragment => { addLoreFragmentScans(inventory, value);
const fragment = inventory.LoreFragmentScans.find(x => x.ItemType == clientFragment.ItemType);
if (fragment) {
fragment.Progress += clientFragment.Progress;
} else {
inventory.LoreFragmentScans.push(clientFragment);
}
});
break; break;
case "LibraryScans": case "LibraryScans":
value.forEach(scan => { value.forEach(scan => {
@ -554,6 +569,11 @@ export const addMissionRewards = async (
return { MissionRewards: [] }; return { MissionRewards: [] };
} }
if (rewardInfo.rewardSeed) {
// We're using a reward seed, so give the client a new one in the response. On live, missionInventoryUpdate seems to always provide a fresh one in the response.
inventory.RewardSeed = generateRewardSeed();
}
//TODO: check double reward merging //TODO: check double reward merging
const MissionRewards: IMissionReward[] = getRandomMissionDrops(rewardInfo, wagerTier); const MissionRewards: IMissionReward[] = getRandomMissionDrops(rewardInfo, wagerTier);
logger.debug("random mission drops:", MissionRewards); logger.debug("random mission drops:", MissionRewards);
@ -592,7 +612,14 @@ export const addMissionRewards = async (
const node = ExportRegions[missions.Tag]; const node = ExportRegions[missions.Tag];
//node based credit rewards for mission completion //node based credit rewards for mission completion
if (node.missionIndex !== 28) { if (
node.missionIndex != 23 && // junction
node.missionIndex != 28 && // open world
missions.Tag != "SolNode761" && // the index
missions.Tag != "SolNode762" && // the index
missions.Tag != "SolNode763" && // the index
missions.Tag != "CrewBattleNode556" // free flight
) {
const levelCreditReward = getLevelCreditRewards(node); const levelCreditReward = getLevelCreditRewards(node);
missionCompletionCredits += levelCreditReward; missionCompletionCredits += levelCreditReward;
inventory.RegularCredits += levelCreditReward; inventory.RegularCredits += levelCreditReward;
@ -910,6 +937,12 @@ function getLevelCreditRewards(node: IRegion): number {
function getRandomMissionDrops(RewardInfo: IRewardInfo, tierOverride: number | undefined): IMissionReward[] { function getRandomMissionDrops(RewardInfo: IRewardInfo, tierOverride: number | undefined): IMissionReward[] {
const drops: IMissionReward[] = []; const drops: IMissionReward[] = [];
if (RewardInfo.periodicMissionTag?.startsWith("HardDaily")) {
drops.push({
StoreItem: "/Lotus/StoreItems/Types/Items/MiscItems/SteelEssence",
ItemCount: 5
});
}
if (RewardInfo.node in ExportRegions) { if (RewardInfo.node in ExportRegions) {
const region = ExportRegions[RewardInfo.node]; const region = ExportRegions[RewardInfo.node];
let rewardManifests: string[] = let rewardManifests: string[] =
@ -934,7 +967,7 @@ function getRandomMissionDrops(RewardInfo: IRewardInfo, tierOverride: number | u
if (syndicateEntry.Tag === "EntratiSyndicate") { if (syndicateEntry.Tag === "EntratiSyndicate") {
const vault = syndicateEntry.Jobs.find(j => j.locationTag === locationTag); const vault = syndicateEntry.Jobs.find(j => j.locationTag === locationTag);
if (vault) job = vault; if (vault && locationTag) job = vault;
// if ( // if (
// [ // [
// "DeimosRuinsExterminateBounty", // "DeimosRuinsExterminateBounty",
@ -1009,8 +1042,11 @@ function getRandomMissionDrops(RewardInfo: IRewardInfo, tierOverride: number | u
(RewardInfo.JobStage === job.xpAmounts.length - 1 || job.isVault) && (RewardInfo.JobStage === job.xpAmounts.length - 1 || job.isVault) &&
!isEndlessJob !isEndlessJob
) { ) {
rewardManifests.push(job.rewards); // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
rotations.push(ExportRewards[job.rewards].length - 1); if (ExportRewards[job.rewards]) {
rewardManifests.push(job.rewards);
rotations.push(ExportRewards[job.rewards].length - 1);
}
} }
} }
} }
@ -1053,29 +1089,28 @@ function getRandomMissionDrops(RewardInfo: IRewardInfo, tierOverride: number | u
} else { } else {
logger.error(`Unknown syndicate or tier: ${RewardInfo.challengeMissionId}`); logger.error(`Unknown syndicate or tier: ${RewardInfo.challengeMissionId}`);
} }
} else if (RewardInfo.VaultsCracked) {
// For Spy missions, e.g. 3 vaults cracked = A, B, C
for (let i = 0; i != RewardInfo.VaultsCracked; ++i) {
rotations.push(i);
}
} else { } else {
const rotationCount = RewardInfo.rewardQualifications?.length || 0; rotations = getRotations(RewardInfo, tierOverride);
rotations = getRotations(rotationCount, tierOverride);
} }
if (rewardManifests.length != 0) { if (rewardManifests.length != 0) {
logger.debug(`generating random mission rewards`, { rewardManifests, rotations }); logger.debug(`generating random mission rewards`, { rewardManifests, rotations });
} }
rewardManifests const rng = new SRng(BigInt(RewardInfo.rewardSeed ?? generateRewardSeed()) ^ 0xffffffffffffffffn);
.map(name => ExportRewards[name]) rewardManifests.forEach(name => {
.forEach(table => { const table = ExportRewards[name];
for (const rotation of rotations) { // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
const rotationRewards = table[rotation]; if (!table) {
const drop = getRandomRewardByChance(rotationRewards); logger.error(`unknown droptable: ${name}`);
if (drop) { return;
drops.push({ StoreItem: drop.type, ItemCount: drop.itemCount }); }
} for (const rotation of rotations) {
const rotationRewards = table[rotation];
const drop = getRandomRewardByChance(rotationRewards, rng);
if (drop) {
drops.push({ StoreItem: drop.type, ItemCount: drop.itemCount });
} }
}); }
});
if (region.cacheRewardManifest && RewardInfo.EnemyCachesFound) { if (region.cacheRewardManifest && RewardInfo.EnemyCachesFound) {
const deck = ExportRewards[region.cacheRewardManifest]; const deck = ExportRewards[region.cacheRewardManifest];

View File

@ -31,7 +31,7 @@ const getRewardAtPercentage = <T extends { probability: number }>(pool: T[], per
return item; return item;
} }
} }
throw new Error("What the fuck?"); return pool[pool.length - 1];
}; };
export const getRandomReward = <T extends { probability: number }>(pool: T[]): T | undefined => { export const getRandomReward = <T extends { probability: number }>(pool: T[]): T | undefined => {
@ -142,4 +142,8 @@ export class SRng {
this.state = (0x5851f42d4c957f2dn * this.state + 0x14057b7ef767814fn) & 0xffffffffffffffffn; this.state = (0x5851f42d4c957f2dn * this.state + 0x14057b7ef767814fn) & 0xffffffffffffffffn;
return (Number(this.state >> 38n) & 0xffffff) * 0.000000059604645; return (Number(this.state >> 38n) & 0xffffff) * 0.000000059604645;
} }
randomReward<T extends { probability: number }>(pool: T[]): T | undefined {
return getRewardAtPercentage(pool, this.randomFloat());
}
} }

View File

@ -194,7 +194,7 @@ export interface IInventoryClient extends IDailyAffiliations, InventoryClientEqu
Mailbox?: IMailboxClient; Mailbox?: IMailboxClient;
SubscribedToEmails: number; SubscribedToEmails: number;
Created: IMongoDate; Created: IMongoDate;
RewardSeed: number; RewardSeed: number | bigint;
RegularCredits: number; RegularCredits: number;
PremiumCredits: number; PremiumCredits: number;
PremiumCreditsFree: number; PremiumCreditsFree: number;

View File

@ -130,7 +130,7 @@ export type IMissionInventoryUpdateRequest = {
export interface IRewardInfo { export interface IRewardInfo {
node: string; node: string;
VaultsCracked?: number; // for Spy missions VaultsCracked?: number; // for Spy missions
rewardTier?: number; rewardTier?: number; // for Rescue missions
nightmareMode?: boolean; nightmareMode?: boolean;
useVaultManifest?: boolean; useVaultManifest?: boolean;
EnemyCachesFound?: number; EnemyCachesFound?: number;
@ -141,7 +141,7 @@ export interface IRewardInfo {
EOM_AFK?: number; EOM_AFK?: number;
rewardQualifications?: string; // did a Survival for 5 minutes and this was "1" rewardQualifications?: string; // did a Survival for 5 minutes and this was "1"
PurgatoryRewardQualifications?: string; PurgatoryRewardQualifications?: string;
rewardSeed?: number; rewardSeed?: number | bigint;
periodicMissionTag?: string; periodicMissionTag?: string;
// for bounties, only EOM_AFK and node are given from above, plus: // for bounties, only EOM_AFK and node are given from above, plus:

View File

@ -139,7 +139,7 @@ dict = {
cheats_noVendorPurchaseLimits: `Keine Kaufbeschränkungen bei Händlern`, cheats_noVendorPurchaseLimits: `Keine Kaufbeschränkungen bei Händlern`,
cheats_noKimCooldowns: `Keine Wartezeit bei KIM`, cheats_noKimCooldowns: `Keine Wartezeit bei KIM`,
cheats_instantResourceExtractorDrones: `Sofortige Ressourcen-Extraktor-Drohnen`, cheats_instantResourceExtractorDrones: `Sofortige Ressourcen-Extraktor-Drohnen`,
cheats_noResourceExtractorDronesDamage: `[UNTRANSLATED] No Resource Extractor Drones Damage`, cheats_noResourceExtractorDronesDamage: `Kein Schaden für Ressourcen-Extraktor-Drohnen`,
cheats_noDojoRoomBuildStage: `Kein Dojo-Raum-Bauvorgang`, cheats_noDojoRoomBuildStage: `Kein Dojo-Raum-Bauvorgang`,
cheats_noDojoDecoBuildStage: `Kein Dojo-Deko-Bauvorgang`, cheats_noDojoDecoBuildStage: `Kein Dojo-Deko-Bauvorgang`,
cheats_fastDojoRoomDestruction: `Schnelle Dojo-Raum-Zerstörung`, cheats_fastDojoRoomDestruction: `Schnelle Dojo-Raum-Zerstörung`,