Viewing old revision of Module:Game
You are viewing an old revision of this page from 2/26/2026, 3:25:06 PM.
View latest versionconst VENDOR_SELL_MODIFIER = 0.38;
function getSellPrice(buyPrice) {
return buyPrice ? Math.floor(Math.max(buyPrice * VENDOR_SELL_MODIFIER, 1)) : "N/A";
}
function calculateDropChance(entry) {
if (!entry) return 0;
if (typeof entry.dropChance === "number") return entry.dropChance;
if (entry.tag) {
const match = entry.tag.match(/\(([\d.]+)%\)/);
if (match) return parseFloat(match[1]) / 100;
}
return 0;
}
function resolveCategory(entries, limit) {
if (!entries?.length) return [];
const parsed = entries.map(e => ({
...e,
_p: calculateDropChance(e)
}));
const expected = parsed.reduce((sum, e) => sum + e._p, 0);
if (expected <= limit) {
return parsed.map(e => ({
...e,
effectiveChance: +(e._p * 100).toFixed(2)
}));
}
const scale = limit / expected;
return parsed.map(e => ({
...e,
effectiveChance: +(e._p * scale * 100).toFixed(2)
}));
}
function calculateCreepDrops(lootTable, limits) {
const categories = ["gear", "consumable", "trade"];
const resolved = {};
const perCategory = {};
let totalExpected = 0;
for (const cat of categories) {
const entries = resolveCategory(
lootTable?.[cat] || [],
limits?.[cat] || 0
);
resolved[cat] = entries;
const expected = entries.reduce(
(sum, e) => sum + (e.effectiveChance || 0) / 100,
0
);
perCategory[cat] = {
expectedDrops: +expected.toFixed(4),
totalChancePercent: +(expected * 100).toFixed(2)
};
totalExpected += expected;
}
return {
items: resolved,
totals: {
totalExpectedDrops: +totalExpected.toFixed(4),
totalEffectiveChancePercent: +(totalExpected * 100).toFixed(2),
perCategory
}
};
}
exports = {
getSellPrice,
calculateCreepDrops
}