forked from OpenWF/SpaceNinjaServer
		
	fix: generate rewards based on RewardSeed to match what's show in client (#1628)
Reviewed-on: OpenWF/SpaceNinjaServer#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 { generateRewardSeed } from "@/src/services/inventoryService";
 | 
			
		||||
import { getAccountIdForRequest } from "@/src/services/loginService";
 | 
			
		||||
import { logger } from "@/src/utils/logger";
 | 
			
		||||
import { RequestHandler } from "express";
 | 
			
		||||
 | 
			
		||||
export const getNewRewardSeedController: RequestHandler = async (req, res) => {
 | 
			
		||||
    const accountId = await getAccountIdForRequest(req);
 | 
			
		||||
 | 
			
		||||
    const rewardSeed = generateRewardSeed();
 | 
			
		||||
    logger.debug(`generated new reward seed: ${rewardSeed}`);
 | 
			
		||||
    await Inventory.updateOne(
 | 
			
		||||
        {
 | 
			
		||||
            accountOwnerId: accountId
 | 
			
		||||
 | 
			
		||||
@ -1213,7 +1213,7 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
 | 
			
		||||
        accountOwnerId: Schema.Types.ObjectId,
 | 
			
		||||
        SubscribedToEmails: { type: Number, default: 0 },
 | 
			
		||||
        SubscribedToEmailsPersonalized: { type: Number, default: 0 },
 | 
			
		||||
        RewardSeed: Number,
 | 
			
		||||
        RewardSeed: BigInt,
 | 
			
		||||
 | 
			
		||||
        //Credit
 | 
			
		||||
        RegularCredits: { type: Number, default: 0 },
 | 
			
		||||
 | 
			
		||||
@ -9,7 +9,7 @@ import {
 | 
			
		||||
} from "warframe-public-export-plus";
 | 
			
		||||
import { IMissionInventoryUpdateRequest, IRewardInfo } from "../types/requestTypes";
 | 
			
		||||
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 {
 | 
			
		||||
    addBooster,
 | 
			
		||||
@ -31,6 +31,7 @@ import {
 | 
			
		||||
    addShipDecorations,
 | 
			
		||||
    addStanding,
 | 
			
		||||
    combineInventoryChanges,
 | 
			
		||||
    generateRewardSeed,
 | 
			
		||||
    updateCurrency,
 | 
			
		||||
    updateSyndicate
 | 
			
		||||
} from "@/src/services/inventoryService";
 | 
			
		||||
@ -70,7 +71,12 @@ const getRotations = (rotationCount: number, tierOverride: number | undefined):
 | 
			
		||||
    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[]);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -548,6 +554,11 @@ export const addMissionRewards = async (
 | 
			
		||||
        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
 | 
			
		||||
    const MissionRewards: IMissionReward[] = getRandomMissionDrops(rewardInfo, wagerTier);
 | 
			
		||||
    logger.debug("random mission drops:", MissionRewards);
 | 
			
		||||
@ -1062,6 +1073,7 @@ function getRandomMissionDrops(RewardInfo: IRewardInfo, tierOverride: number | u
 | 
			
		||||
        if (rewardManifests.length != 0) {
 | 
			
		||||
            logger.debug(`generating random mission rewards`, { rewardManifests, rotations });
 | 
			
		||||
        }
 | 
			
		||||
        const rng = new SRng(BigInt(RewardInfo.rewardSeed ?? generateRewardSeed()) ^ 0xffffffffffffffffn);
 | 
			
		||||
        rewardManifests.forEach(name => {
 | 
			
		||||
            const table = ExportRewards[name];
 | 
			
		||||
            if (!table) {
 | 
			
		||||
@ -1070,7 +1082,7 @@ function getRandomMissionDrops(RewardInfo: IRewardInfo, tierOverride: number | u
 | 
			
		||||
            }
 | 
			
		||||
            for (const rotation of rotations) {
 | 
			
		||||
                const rotationRewards = table[rotation];
 | 
			
		||||
                const drop = getRandomRewardByChance(rotationRewards);
 | 
			
		||||
                const drop = getRandomRewardByChance(rotationRewards, rng);
 | 
			
		||||
                if (drop) {
 | 
			
		||||
                    drops.push({ StoreItem: drop.type, ItemCount: drop.itemCount });
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
@ -31,7 +31,7 @@ const getRewardAtPercentage = <T extends { probability: number }>(pool: T[], per
 | 
			
		||||
            return item;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    throw new Error("What the fuck?");
 | 
			
		||||
    return pool[pool.length - 1];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
        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;
 | 
			
		||||
    SubscribedToEmails: number;
 | 
			
		||||
    Created: IMongoDate;
 | 
			
		||||
    RewardSeed: number;
 | 
			
		||||
    RewardSeed: number | bigint;
 | 
			
		||||
    RegularCredits: number;
 | 
			
		||||
    PremiumCredits: number;
 | 
			
		||||
    PremiumCreditsFree: number;
 | 
			
		||||
 | 
			
		||||
@ -141,7 +141,7 @@ export interface IRewardInfo {
 | 
			
		||||
    EOM_AFK?: number;
 | 
			
		||||
    rewardQualifications?: string; // did a Survival for 5 minutes and this was "1"
 | 
			
		||||
    PurgatoryRewardQualifications?: string;
 | 
			
		||||
    rewardSeed?: number;
 | 
			
		||||
    rewardSeed?: number | bigint;
 | 
			
		||||
    periodicMissionTag?: string;
 | 
			
		||||
 | 
			
		||||
    // for bounties, only EOM_AFK and node are given from above, plus:
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user