UNPKG

tf2-rtp-calculator

Version:

An RTP simulator/calculator for Team Fortress 2 crates.

71 lines (66 loc) 2.12 kB
import type { TF2Crate } from "../tf2/interfaces/crateData"; import type { TF2Odds } from "../tf2/odds"; import { intInRange, random } from "./index"; import { MessagePort } from "node:worker_threads"; import { hash } from "../hash"; const DEFAULT_BATCH_SIZE = 256; export default function sim( crateData: TF2Crate, iterations: number, crateWeights: number[], odds: typeof TF2Odds, inputBatchSize: number = DEFAULT_BATCH_SIZE, parentPort?: null | MessagePort, ): void { if(!parentPort) { throw new Error("Parent port is required for worker communication."); } const totalWeight = crateWeights.reduce((a, b) => a + b, 0); const itemKeys = Object.keys(crateData.items); const batchSize = Math.min(iterations, inputBatchSize); let batch = new Array(batchSize); let batchCounter = 0; for(let i = 0; i < iterations; i++) { batch[batchCounter] = tick(crateData, crateWeights, odds, totalWeight, itemKeys); if(batchCounter === batchSize - 1) { parentPort.postMessage({ size: batchSize, batch: batch }); batch = new Array(batchSize); batchCounter = 0; } else { batchCounter++; } } if(batchCounter > 0) { parentPort.postMessage({ size: batchCounter, batch: batch }); } return; } function tick( crateData: TF2Crate, crateWeights: number[], odds: typeof TF2Odds, totalWeight: number, itemKeys: string[], ): number { // Simulate opening a crate let hatIndex = 0; let hatWeight = 0; let rngWeight = intInRange(0, totalWeight-1); while(hatIndex < crateWeights.length) { hatWeight += crateWeights[hatIndex]; if(hatWeight > rngWeight) { break; } hatIndex++; } const isStrange = random() <= odds.uncrateStrangeChance ? 1 : 0; const isUnusual = !crateData.unusualItems[itemKeys[hatIndex]] ? 0 : random() <= odds.uncrateUnusualChance ? 1 : 0; const unusualEffect = isUnusual ? intInRange(0, crateData.effects.length-1) : 0; return hash(hatIndex, isStrange, isUnusual, unusualEffect); }