farming-weight
Version:
Tools for calculating farming weight and fortune in Hypixel Skyblock
210 lines (209 loc) • 6.69 kB
JavaScript
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
exports.FarmingArmor = exports.ArmorSet = void 0;
const ARMOR_1 = require('../constants/armor');
const ENCHANTS_1 = require('../constants/enchants');
const REFORGES_1 = require('../constants/reforges');
const SKILLS_1 = require('../constants/skills');
const SPECIALCROPS_1 = require('../constants/specialcrops');
const SPECIAL_1 = require('../crops/special');
const GEMS_1 = require('../util/gems');
const ITEMSTATS_1 = require('../util/itemstats');
class ArmorSet {
get armor() {
return [this.helmet ?? null, this.chestplate ?? null, this.leggings ?? null, this.boots ?? null];
}
constructor(armor) {
armor.sort((a, b) => b.potential - a.potential);
this.pieces = armor;
this.helmet = armor.find((a) => a.slot === ARMOR_1.GearSlot.Helmet);
this.chestplate = armor.find((a) => a.slot === ARMOR_1.GearSlot.Chestplate);
this.leggings = armor.find((a) => a.slot === ARMOR_1.GearSlot.Leggings);
this.boots = armor.find((a) => a.slot === ARMOR_1.GearSlot.Boots);
this.recalculateFamilies();
}
getPiece(slot) {
switch (slot) {
case ARMOR_1.GearSlot.Helmet:
return this.helmet;
case ARMOR_1.GearSlot.Chestplate:
return this.chestplate;
case ARMOR_1.GearSlot.Leggings:
return this.leggings;
case ARMOR_1.GearSlot.Boots:
return this.boots;
default:
return undefined;
}
}
setPiece(armor) {
switch (armor.slot) {
case ARMOR_1.GearSlot.Helmet:
this.helmet = armor;
break;
case ARMOR_1.GearSlot.Chestplate:
this.chestplate = armor;
break;
case ARMOR_1.GearSlot.Leggings:
this.leggings = armor;
break;
case ARMOR_1.GearSlot.Boots:
this.boots = armor;
break;
default:
return;
}
this.recalculateFamilies();
}
recalculateFamilies() {
const FAMILIES = new Map();
const ARMOR = this.armor.filter((a) => a);
this.setBonuses = [];
for (const PIECE of ARMOR) {
if (!PIECE.armor.family) continue;
FAMILIES.set(PIECE.armor.family, (FAMILIES.get(PIECE.armor.family) ?? 0) + 1);
}
for (const [FAMILY, COUNT] of FAMILIES.entries()) {
if (COUNT < 2) continue;
const BONUS = ARMOR_1.ARMOR_SET_BONUS[FAMILY];
if (!BONUS) continue;
this.setBonuses.push({
count: COUNT,
from: ARMOR.filter((a) => a.armor.family === FAMILY).map((a) => a.slot),
bonus: BONUS,
special: BONUS.special,
});
}
this.getFortuneBreakdown();
}
getFortuneBreakdown(reloadFamilies = false) {
if (reloadFamilies) {
this.recalculateFamilies();
}
let SUM = 0;
const BREAKDOWN = {};
for (const PIECE of this.armor) {
if (!PIECE) continue;
const FORTUNE = PIECE.fortune;
if (FORTUNE > 0) {
BREAKDOWN[PIECE.item.name ?? ''] = FORTUNE;
SUM += FORTUNE;
}
}
for (const { bonus, count } of this.setBonuses) {
if (count < 2 || count > 4) continue;
const FORTUNE = bonus.stats?.[count]?.[REFORGES_1.Stat.FarmingFortune] ?? 0;
if (FORTUNE > 0) {
BREAKDOWN[bonus.name] = FORTUNE;
SUM += FORTUNE;
}
}
this.fortune = SUM;
return BREAKDOWN;
}
specialDropsCalc(blocksBroken, crop) {
const SPECIAL = SPECIALCROPS_1.MATCHING_SPECIAL_CROP[crop];
const APPLICABLE_BONUSES = this.setBonuses.filter((b) => b.special?.includes(SPECIAL));
if (APPLICABLE_BONUSES.length === 0) return null;
// Armor set counts need to be combined for special crops
// There will only be 2 applicable bonuses at most when Fermento armor plus
// a lower tier armor is used. Hypixel appeats to count these as the same
// set bonus instead of rolling them separately.
let COUNT = 0;
for (const BONUS of APPLICABLE_BONUSES) {
COUNT += BONUS.count;
}
return (0, SPECIAL_1.calculateAverageSpecialCrops)(blocksBroken, crop, COUNT);
}
}
exports.ArmorSet = ArmorSet;
class FarmingArmor {
get slot() {
return this.armor.slot;
}
get potential() {
if (!this.armor.family) {
return this.fortune;
}
// Add the set bonus potential to the fortune
return (
this.fortune +
(ARMOR_1.ARMOR_SET_BONUS[this.armor.family]?.piecePotential?.[REFORGES_1.Stat.FarmingFortune] ?? 0)
);
}
constructor(item, options) {
this.options = options;
this.item = item;
const ARMOR = ARMOR_1.ARMOR_INFO[item.skyblockId];
if (!ARMOR) {
throw new Error(`Unknown farming armor: ${item.name} (${item.skyblockId})`);
}
this.armor = ARMOR;
if (item.lore) {
this.rarity = (0, ITEMSTATS_1.getRarityFromLore)(item.lore);
}
this.reforge = REFORGES_1.REFORGES[item.attributes?.modifier ?? ''] ?? undefined;
this.reforgeStats = this.reforge?.tiers?.[this.rarity];
this.recombobulated = this.item.attributes?.rarity_upgrades === '1';
this.sumFortune();
}
setOptions(options) {
this.options = options;
this.fortune = this.sumFortune();
}
sumFortune() {
this.fortuneBreakdown = {};
let SUM = 0;
// Base fortune
const BASE = this.armor.stats?.[REFORGES_1.Stat.FarmingFortune] ?? 0;
if (BASE > 0) {
this.fortuneBreakdown['Base Stats'] = BASE;
SUM += BASE;
}
// Per farming level stats like Rancher's Boots
if (this.armor.perLevelStats?.skill === SKILLS_1.Skill.Farming && this.options?.farmingLevel) {
const PER_LEVEL = this.armor.perLevelStats?.stats[REFORGES_1.Stat.FarmingFortune] ?? 0;
if (PER_LEVEL > 0) {
this.fortuneBreakdown['Farming Level'] = PER_LEVEL * this.options.farmingLevel;
SUM += PER_LEVEL * this.options.farmingLevel;
}
}
// Reforge stats
const REFORGE = this.reforgeStats?.stats?.[REFORGES_1.Stat.FarmingFortune] ?? 0;
if (REFORGE > 0) {
this.fortuneBreakdown[this.reforge?.name ?? 'Reforge'] = REFORGE;
SUM += REFORGE;
}
// Gems
const PERIDOT = (0, GEMS_1.getPeridotFortune)(this.rarity, this.item);
if (PERIDOT > 0) {
this.fortuneBreakdown['Peridot Gems'] = PERIDOT;
SUM += PERIDOT;
}
// Enchantments
const ENCHANTMENTS = Object.entries(this.item.enchantments ?? {});
for (const [ENCHANT, LEVEL] of ENCHANTMENTS) {
if (!LEVEL) continue;
const ENCHANTMENT = ENCHANTS_1.FARMING_ARMOR_ENCHANTS[ENCHANT];
if (!ENCHANTMENT || !LEVEL) continue;
const FORTUNE = ENCHANTMENT.levels?.[LEVEL]?.[REFORGES_1.Stat.FarmingFortune] ?? 0;
if (FORTUNE > 0) {
this.fortuneBreakdown[ENCHANTMENT.name] = FORTUNE;
SUM += FORTUNE;
}
}
this.fortune = SUM;
return SUM;
}
static isValid(item) {
return ARMOR_1.ARMOR_INFO[item.skyblockId] !== undefined;
}
static fromArray(items, options) {
return items
.filter((item) => FarmingArmor.isValid(item))
.map((item) => new FarmingArmor(item, options))
.sort((a, b) => b.fortune - a.fortune);
}
}
exports.FarmingArmor = FarmingArmor;
//# sourceMappingURL=farmingarmor.js.map