farming-weight
Version:
Tools for calculating farming weight and fortune in Hypixel Skyblock
234 lines • 9.06 kB
JavaScript
import { FARMING_ENCHANTS } from '../constants/enchants.js';
import { ReforgeTarget } from '../constants/reforges.js';
import { Stat } from '../constants/stats.js';
import { FARMING_EQUIPMENT_INFO } from '../items/equipment.js';
import { statsToEffects } from '../items/sources/effects-util.js';
import { enchantEffects } from '../items/sources/enchants.js';
import { gemEffects } from '../items/sources/gems.js';
import { reforgeEffects } from '../items/sources/reforges.js';
import { ZorroMode } from '../player/playeroptions.js';
import { getSourceProgress } from '../upgrades/getsourceprogress.js';
import { GEAR_FORTUNE_SOURCES } from '../upgrades/sources/gearsources.js';
import { getFortuneFromEnchant, getStatFromEnchant } from '../util/enchants.js';
import { getGemStat } from '../util/gems.js';
import { extractNumberFromLine } from '../util/lore.js';
import { getLotusToBlossomPieceBonus, setLotusPieceBonusLore } from './lotuspiecebonus.js';
import { UpgradeableBase } from './upgradeablebase.js';
export class FarmingEquipment extends UpgradeableBase {
get type() {
return ReforgeTarget.Equipment;
}
get slot() {
return this.info.slot;
}
constructor(item, options) {
super({ item, options, items: FARMING_EQUIPMENT_INFO });
this.getFortune();
}
getProgress(stats, zeroed = false) {
return getSourceProgress(this, GEAR_FORTUNE_SOURCES, zeroed, stats);
}
setOptions(options) {
this.options = options;
this.getFortune();
}
getStat(stat, crop) {
if (stat === Stat.FarmingFortune) {
return this.getFortune();
}
let sum = 0;
// Base fortune
sum += this.info.baseStats?.[stat] ?? 0;
// Reforge
sum += this.reforgeStats?.stats?.[stat] ?? 0;
// Gems
sum += getGemStat(this.item, stat, this.rarity);
// Enchantments
for (const [key, level] of Object.entries(this.item.enchantments ?? {})) {
const enchant = FARMING_ENCHANTS[key];
if (!enchant || !level || enchant.cropSpecific)
continue;
sum += getStatFromEnchant(level, enchant, stat, this.options, crop);
}
return sum;
}
/**
* Returns the declarative `Effect[]` representation of every contribution
* this equipment piece makes: base stats, reforge, gems, enchants. Set
* bonuses are emitted at the {@link ArmorSet} level.
*/
getEffects(env) {
const sourceName = this.item.name ?? this.info.name;
const effects = [];
effects.push(...statsToEffects(this.info.baseStats, sourceName));
if (this.reforge && this.item.attributes?.modifier) {
effects.push(...reforgeEffects(this.item.attributes.modifier, this.rarity, `${sourceName} (${this.reforge.name})`));
}
effects.push(...gemEffects(this.item, this.rarity, `${sourceName} (Gems)`));
for (const [enchantId, level] of Object.entries(this.item.enchantments ?? {})) {
if (!level)
continue;
effects.push(...enchantEffects(enchantId, level, env, this.options ?? {}));
}
if (this.info.family === 'LOTUS') {
const pieceBonus = this.getPieceBonus();
if (pieceBonus > 0) {
effects.push({
source: `${sourceName} (Salesperson)`,
op: 'add-stat',
stat: Stat.FarmingFortune,
value: pieceBonus,
});
}
}
return effects;
}
getFortune() {
this.fortuneBreakdown = {};
let sum = 0;
// Base fortune
const base = this.info.baseStats?.[Stat.FarmingFortune] ?? 0;
if (base > 0) {
this.fortuneBreakdown['Base Stats'] = base;
sum += base;
}
// Reforge
const reforge = this.reforgeStats?.stats?.[Stat.FarmingFortune] ?? 0;
if (reforge > 0) {
this.fortuneBreakdown['Reforge'] = reforge;
sum += reforge;
}
// Enchantments
for (const [key, level] of Object.entries(this.item.enchantments ?? {})) {
const enchant = FARMING_ENCHANTS[key];
if (!enchant || !level || enchant.cropSpecific)
continue;
const fortune = getFortuneFromEnchant(level, enchant, this.options);
if (fortune > 0) {
this.fortuneBreakdown[enchant.name] = fortune;
sum += fortune;
}
}
// Lotus Piece Specific
if (this.info.family === 'LOTUS') {
// Green thumb from lore as a fallback
if (!this.options?.uniqueVisitors) {
const visitors = this.getFortuneFromVisitors(base, reforge);
if (visitors > 0) {
this.fortuneBreakdown['Green Thumb'] = visitors;
sum += visitors;
}
}
// Salesperson lotus piece bonus
const pieceBonus = this.getPieceBonus();
if (pieceBonus > 0) {
this.fortuneBreakdown['Salesperson'] = pieceBonus;
sum += pieceBonus;
}
}
if (this.item.skyblockId === 'ZORROS_CAPE') {
// If Zorro is disabled, set fortune to 0
if (this.options?.zorro?.enabled === false) {
this.fortune = 0;
return 0;
}
// Zorro's Cape
const zorro = this.options?.zorro ?? {
enabled: true,
mode: ZorroMode.Normal,
};
switch (zorro.mode) {
case ZorroMode.Averaged:
sum *= 1.3333;
for (const key in this.fortuneBreakdown) {
if (this.fortuneBreakdown[key] === undefined)
continue;
this.fortuneBreakdown[key] *= 1.3333;
}
break;
case ZorroMode.Contest:
sum *= 2;
for (const key in this.fortuneBreakdown) {
if (this.fortuneBreakdown[key] === undefined)
continue;
this.fortuneBreakdown[key] *= 2;
}
break;
case ZorroMode.Normal:
default:
break;
}
}
this.fortune = sum;
return sum;
}
getFortuneFromVisitors(base, reforge) {
if (!this.item.enchantments?.green_thumb)
return 0;
const regex = /§7Farming Fortune: §a\+(\d+.?\d+)/g;
let found = 0;
for (const line of this.item.lore ?? []) {
const number = extractNumberFromLine(line, regex) ?? 0;
if (!number)
continue;
found = +number;
break;
}
if (found === 0)
return 0;
return Math.max(0, found - base - reforge);
}
/**
* Get the bonus from the Salesperson lotus piece
* @returns {number} Fortune from the Salesperson lotus piece
*/
getPieceBonus() {
if (!this.item.lore)
return 0;
const regex = /Piece Bonus: §6\+(\d+.?\d*)☘/g;
let found = 0;
for (let i = (this.item.lore ?? []).length - 1; i >= 0; i--) {
const line = this.item.lore?.[i];
if (!line)
continue;
const number = extractNumberFromLine(line, regex) ?? 0;
if (!number)
continue;
found = number;
break;
}
return found;
}
applyTierUpgradeStateTo(newItem) {
const upgradedPieceBonus = getLotusToBlossomPieceBonus(this.item.skyblockId, newItem.item.skyblockId, this.getPieceBonus());
if (upgradedPieceBonus === undefined)
return;
setLotusPieceBonusLore(newItem.item, upgradedPieceBonus);
}
static isValid(item) {
return FARMING_EQUIPMENT_INFO[item.skyblockId] !== undefined;
}
static fromArray(items, options) {
return items
.filter((item) => FarmingEquipment.isValid(item))
.map((item) => new FarmingEquipment(item, options))
.sort((a, b) => b.fortune - a.fortune);
}
static fakeItem(info, options) {
const fake = {
name: info.name,
skyblockId: info.skyblockId,
uuid: crypto.randomUUID(),
lore: ['This is a fake item used for upgrade calculations!'],
attributes: {},
enchantments: {},
};
if (!FarmingEquipment.isValid(fake))
return undefined;
return new FarmingEquipment(fake, options);
}
}
// For backwards compatibility
// eslint-disable-next-line @typescript-eslint/naming-convention
export const LotusGear = FarmingEquipment;
//# sourceMappingURL=farmingequipment.js.map