Skip to content

Commit 28aae84

Browse files
authored
fix: relic refinement drop rates (#796)
1 parent b6e8dd2 commit 28aae84

File tree

2 files changed

+70
-3
lines changed

2 files changed

+70
-3
lines changed

build/parser.mjs

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ class Parser {
199199
this.addIsPrime(result);
200200
this.addVaultData(result, data.vaultData, category, data.wikia);
201201
this.addResistanceData(result, category);
202-
this.addRelics(result, data.relics);
202+
this.addRelics(result, data.relics, data.drops);
203203
this.applyMasterable(result);
204204
this.applyOverrides(result);
205205
return result;
@@ -1069,8 +1069,9 @@ class Parser {
10691069
* - market data on relics (urlName, id)
10701070
* @param {Item} item to have relics applied to
10711071
* @param {Array<module:@wfcd/relics.TitaniaRelic>} relics relic array to search
1072+
* @param {Array<DropRate>} drops drop rate data for refinement-specific chances
10721073
*/
1073-
addRelics(item, relics) {
1074+
addRelics(item, relics, drops) {
10741075
const hasRelicDrop = item.components?.some((c) => c.drops?.some((d) => d.location?.includes('Relic')));
10751076
if (item.type !== 'Relic' && !hasRelicDrop) return;
10761077

@@ -1085,7 +1086,36 @@ class Parser {
10851086
[relicItem.uniqueName] = Array.from(new Set(related.map((relic) => relic.uniqueName).flat()));
10861087
} else {
10871088
relicItem.locations = Array.from(new Set(related.map((relic) => relic.locations).flat()));
1088-
relicItem.rewards = Array.from(new Set(related.map((relic) => relic.rewards).flat()));
1089+
1090+
// Get base rewards structure from relics package (has item metadata)
1091+
const baseRewards = Array.from(new Set(related.map((relic) => relic.rewards).flat()));
1092+
1093+
// Build the correct "place" name for drops API lookup
1094+
const dropPlaceName = name.endsWith('Intact')
1095+
? name.replace(/\sIntact$/, ' Relic')
1096+
: name.replace(/\s(\w+)$/, ' Relic ($1)');
1097+
1098+
// Find drops that match this relic refinement level
1099+
const dropsForRelic = drops?.filter((d) => d.place === dropPlaceName) ?? [];
1100+
1101+
// Update reward chances from drops data (keep other metadata from relics)
1102+
// Track used drops by index to handle duplicate item names correctly
1103+
const usedDropIndices = new Set();
1104+
relicItem.rewards = baseRewards.map((reward) => {
1105+
if (!reward.item?.name) return reward;
1106+
1107+
// Find first unused drop matching this item name
1108+
const dropIndex = dropsForRelic.findIndex(
1109+
(d, idx) => d.item === reward.item.name && !usedDropIndices.has(idx)
1110+
);
1111+
1112+
if (dropIndex !== -1) {
1113+
usedDropIndices.add(dropIndex);
1114+
return { ...reward, chance: dropsForRelic[dropIndex].chance };
1115+
}
1116+
return reward;
1117+
});
1118+
10891119
[relicItem.marketInfo] = Array.from(new Set(related.map((relic) => relic.warframeMarket)));
10901120

10911121
const [vaultInfo] = Array.from(new Set(related.map((relic) => relic.vaultInfo)));

test/index.spec.mjs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,43 @@ const test = (base) => {
365365
});
366366
});
367367
});
368+
describe('relics', async () => {
369+
it('should have correct drop rates for each refinement level', async () => {
370+
const relics = await wrapConstr({ category: ['Relics'] });
371+
372+
// Expected patterns for each refinement level
373+
const expectedPatterns = {
374+
Intact: { 25.33: 3, 11: 2, 2: 1 },
375+
Exceptional: { 23.33: 3, 13: 2, 4: 1 },
376+
Flawless: { 20: 3, 17: 2, 6: 1 },
377+
Radiant: { 16.67: 3, 20: 2, 10: 1 },
378+
};
379+
380+
Object.entries(expectedPatterns).forEach(([level, expected]) => {
381+
const relicsAtLevel = relics.filter((r) => r.name.endsWith(level));
382+
relicsAtLevel.forEach((relic) => {
383+
// BUG: Skip Axi S19 - has no rewards (doesn't exist in game)
384+
if (!relic.rewards || relic.rewards.length === 0) {
385+
return;
386+
}
387+
// Group rewards by percentage
388+
const chanceGroups = {};
389+
relic.rewards.forEach((reward) => {
390+
if (!chanceGroups[reward.chance]) {
391+
chanceGroups[reward.chance] = 0;
392+
}
393+
chanceGroups[reward.chance] += 1;
394+
});
395+
396+
assert.deepStrictEqual(
397+
chanceGroups,
398+
expected,
399+
`${relic.name} should have exact distribution: ${JSON.stringify(expected)}`
400+
);
401+
});
402+
});
403+
});
404+
});
368405
});
369406
};
370407

0 commit comments

Comments
 (0)