56 lines
1.6 KiB
JavaScript
56 lines
1.6 KiB
JavaScript
import { RNG } from '../utils/RNG.js';
|
|
|
|
export class PackManager {
|
|
constructor(packsData, cardManager) {
|
|
this.packs = new Map(packsData.map(p => [p.id, p]));
|
|
this.cardManager = cardManager;
|
|
}
|
|
|
|
getPack(id) {
|
|
return this.packs.get(id);
|
|
}
|
|
|
|
getAllPacks() {
|
|
return [...this.packs.values()];
|
|
}
|
|
|
|
isPackUnlocked(pack, save, campaigns) {
|
|
if (!pack.unlockCondition) return true;
|
|
const campaign = campaigns.find(c => c.id === pack.unlockCondition);
|
|
if (!campaign) return false;
|
|
if (campaign.missions.length === 0) return false;
|
|
const completed = save.campaignProgress?.completedMissions || [];
|
|
return campaign.missions.every(m => completed.includes(m));
|
|
}
|
|
|
|
openPack(packId, save) {
|
|
const pack = this.getPack(packId);
|
|
if (!pack) return null;
|
|
const rng = new RNG(Date.now() ^ (Math.random() * 0xffffffff));
|
|
const results = [];
|
|
for (const slot of pack.slots) {
|
|
const rarity = this._rollRarity(slot.dropRates, rng);
|
|
const pool = this.cardManager.getAllCards().filter(c =>
|
|
c.rarity === rarity &&
|
|
c.type !== 'commander' &&
|
|
c.type !== 'token' &&
|
|
slot.cardPool.includes(c.faction)
|
|
);
|
|
if (pool.length === 0) continue;
|
|
const card = pool[rng.nextInt(0, pool.length - 1)];
|
|
results.push({ ...card, _slotSpecial: !!slot.special });
|
|
}
|
|
return results;
|
|
}
|
|
|
|
_rollRarity(dropRates, rng) {
|
|
const r = rng.next();
|
|
let cumulative = 0;
|
|
for (const [rarity, rate] of Object.entries(dropRates)) {
|
|
cumulative += rate;
|
|
if (r < cumulative) return rarity;
|
|
}
|
|
return 'common';
|
|
}
|
|
}
|