fix: generate rewards based on RewardSeed to match what's show in client (#1628)
Reviewed-on: #1628 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:
parent
d28437b658
commit
3f0a2bec48
@ -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
|
||||||
|
@ -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 },
|
||||||
|
@ -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,
|
||||||
@ -31,6 +31,7 @@ import {
|
|||||||
addShipDecorations,
|
addShipDecorations,
|
||||||
addStanding,
|
addStanding,
|
||||||
combineInventoryChanges,
|
combineInventoryChanges,
|
||||||
|
generateRewardSeed,
|
||||||
updateCurrency,
|
updateCurrency,
|
||||||
updateSyndicate
|
updateSyndicate
|
||||||
} from "@/src/services/inventoryService";
|
} from "@/src/services/inventoryService";
|
||||||
@ -70,7 +71,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[]);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -548,6 +554,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);
|
||||||
@ -1062,6 +1073,7 @@ function getRandomMissionDrops(RewardInfo: IRewardInfo, tierOverride: number | u
|
|||||||
if (rewardManifests.length != 0) {
|
if (rewardManifests.length != 0) {
|
||||||
logger.debug(`generating random mission rewards`, { rewardManifests, rotations });
|
logger.debug(`generating random mission rewards`, { rewardManifests, rotations });
|
||||||
}
|
}
|
||||||
|
const rng = new SRng(BigInt(RewardInfo.rewardSeed ?? generateRewardSeed()) ^ 0xffffffffffffffffn);
|
||||||
rewardManifests.forEach(name => {
|
rewardManifests.forEach(name => {
|
||||||
const table = ExportRewards[name];
|
const table = ExportRewards[name];
|
||||||
if (!table) {
|
if (!table) {
|
||||||
@ -1070,7 +1082,7 @@ function getRandomMissionDrops(RewardInfo: IRewardInfo, tierOverride: number | u
|
|||||||
}
|
}
|
||||||
for (const rotation of rotations) {
|
for (const rotation of rotations) {
|
||||||
const rotationRewards = table[rotation];
|
const rotationRewards = table[rotation];
|
||||||
const drop = getRandomRewardByChance(rotationRewards);
|
const drop = getRandomRewardByChance(rotationRewards, rng);
|
||||||
if (drop) {
|
if (drop) {
|
||||||
drops.push({ StoreItem: drop.type, ItemCount: drop.itemCount });
|
drops.push({ StoreItem: drop.type, ItemCount: drop.itemCount });
|
||||||
}
|
}
|
||||||
|
@ -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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user