farming-weight
Version:
Tools for calculating farming weight and fortune in Hypixel Skyblock
295 lines • 10.4 kB
JavaScript
import { Crop } from './crops.js';
import { Rarity } from './reforges.js';
import { getStatValue, Stat } from './stats.js';
export const FARMING_ATTRIBUTE_SHARDS = {
wart_eater: {
name: 'Warty Bug Shard',
skyblockId: 'SHARD_WARTYBUG',
rarity: Rarity.Legendary,
effect: 'rates',
wiki: 'https://w.elitesb.gg/Wartybug_Shard',
},
garden_wisdom: {
name: 'Dragonfly Shard',
skyblockId: 'SHARD_DRAGONFLY',
rarity: Rarity.Epic,
effect: 'wisdom',
wiki: 'https://w.elitesb.gg/Dragonfly_Shard',
perLevelStats: {
[Stat.FarmingWisdom]: {
value: 0.5,
},
},
},
solar_power: {
name: 'Firefly Shard',
skyblockId: 'SHARD_FIREFLY',
rarity: Rarity.Epic,
effect: 'fortune',
wiki: 'https://w.elitesb.gg/Firefly_Shard',
active: (options) => {
const firefly = getAttributeAmount(options.attributes, 'solar_power');
const lunarMoth = getAttributeAmount(options.attributes, 'lunar_power');
const forceFirefly = 'options' in options && options.options.selectedCrop === Crop.Sunflower;
const forceLunarMoth = 'options' in options && options.options.selectedCrop === Crop.Moonflower;
if (forceFirefly) {
return {
active: true,
reason: 'Firefly Shard is active because you have selected Sunflower!',
};
}
if (forceLunarMoth) {
return {
active: false,
reason: 'Firefly Shard is disabled because you have selected Moonflower!',
fortune: 5 * getShardLevel(Rarity.Epic, lunarMoth),
};
}
if (lunarMoth >= firefly) {
return {
active: false,
reason: 'Lunar Moth shard is at a higher or equal level, using it instead.',
fortune: 5 * getShardLevel(Rarity.Epic, lunarMoth),
};
}
return {
active: true,
reason: 'This shard is only active during the day! Set your garden to day time to use it.',
};
},
perLevelStats: {
[Stat.FarmingFortune]: {
value: 5,
},
},
},
lunar_power: {
name: 'Lunar Moth Shard',
skyblockId: 'SHARD_LUNAR_MOTH',
rarity: Rarity.Epic,
effect: 'fortune',
wiki: 'https://w.elitesb.gg/Lunar_Moth_Shard',
active: (options) => {
const firefly = getAttributeAmount(options.attributes, 'solar_power');
const lunarMoth = getAttributeAmount(options.attributes, 'lunar_power');
const forceFirefly = 'options' in options && options.options.selectedCrop === Crop.Sunflower;
const forceLunarMoth = 'options' in options && options.options.selectedCrop === Crop.Moonflower;
if (forceLunarMoth) {
return {
active: true,
reason: 'Lunar Moth Shard is active because you have selected Moonflower!',
};
}
if (forceFirefly) {
return {
active: false,
reason: 'Lunar Moth Shard is disabled because you have selected Sunflower!',
fortune: 5 * getShardLevel(Rarity.Epic, firefly),
};
}
if (firefly > lunarMoth) {
return {
active: false,
reason: 'Firefly shard is at a higher level, using it instead.',
fortune: 5 * getShardLevel(Rarity.Epic, firefly),
};
}
return {
active: true,
reason: 'This shard is only active during the night! Set your garden to night time to use it.',
};
},
perLevelStats: {
[Stat.FarmingFortune]: {
value: 5,
},
},
},
pretty_clothes: {
// 1% more copper from visitors per level
name: 'Ladybug Shard',
skyblockId: 'SHARD_LADYBUG',
rarity: Rarity.Rare,
effect: 'none',
wiki: 'https://w.elitesb.gg/Ladybug_Shard',
},
crop_bug: {
name: 'Cropeetle Shard',
skyblockId: 'SHARD_CROPEETLE',
rarity: Rarity.Rare,
effect: 'rates',
wiki: 'https://w.elitesb.gg/Cropeetle_Shard',
perLevelStats: {
[Stat.Overbloom]: {
value: 1,
},
},
},
fancy_visit: {
// 1% chance for rare or higher visitor per level
name: 'Invisibug Shard',
skyblockId: 'SHARD_INVISIBUG',
rarity: Rarity.Rare,
effect: 'none',
wiki: 'https://w.elitesb.gg/Invisibug_Shard',
},
infiltration: {
name: 'Termite Shard',
skyblockId: 'SHARD_TERMITE',
rarity: Rarity.Uncommon,
effect: 'fortune',
wiki: 'https://w.elitesb.gg/Termite_Shard',
active: (options) => {
const opt = 'options' in options ? options.options : options;
if (!opt.infestedPlotProbability || opt.infestedPlotProbability <= 0) {
return {
active: false,
reason: 'Termite shard is only active on infested plots.',
fortune: 3 * getShardLevel(Rarity.Uncommon, getAttributeAmount(options.attributes, 'infiltration')),
};
}
return {
active: true,
reason: 'This shard is only active on infested plots!',
};
},
perLevelStats: {
[Stat.FarmingFortune]: {
value: 3,
},
},
},
insect_power: {
// 5% vacuum damage per level
name: 'Praying Mantis Shard',
skyblockId: 'SHARD_PRAYING_MANTIS',
rarity: Rarity.Uncommon,
effect: 'none',
wiki: 'https://w.elitesb.gg/Praying_Mantis_Shard',
},
pest_luck: {
name: 'Pest Shard',
skyblockId: 'SHARD_PEST',
rarity: Rarity.Uncommon,
effect: 'rates',
wiki: 'https://w.elitesb.gg/Pest',
},
visitor_bait: {
// Garden visitors 1% faster per level
name: 'Mudworm Shard',
skyblockId: 'SHARD_MUDWORM',
rarity: Rarity.Common,
effect: 'none',
wiki: 'https://w.elitesb.gg/Mudworm_Shard',
},
ultimate_dna: {
// 1 farming fortune per level
name: 'Galaxy Fish Shard',
skyblockId: 'SHARD_GALAXY_FISH',
rarity: Rarity.Legendary,
effect: 'fortune',
wiki: 'https://w.elitesb.gg/Galaxy_Fish_Shard',
perLevelStats: {
[Stat.FarmingFortune]: {
value: 1,
},
[Stat.MiningFortune]: {
value: 1,
},
[Stat.ForagingFortune]: {
value: 1,
},
},
},
};
const ATTRIBUTE_SHARD_ID_BY_SKYBLOCK_ID = Object.fromEntries(Object.entries(FARMING_ATTRIBUTE_SHARDS).map(([id, shard]) => [shard.skyblockId.toUpperCase(), id]));
export function normalizeAttributeId(id) {
const normalized = id.trim().toLowerCase();
if (normalized in FARMING_ATTRIBUTE_SHARDS) {
return normalized;
}
return ATTRIBUTE_SHARD_ID_BY_SKYBLOCK_ID[id.trim().toUpperCase()];
}
export function getAttributeAmount(attributes, id) {
if (!attributes)
return 0;
const direct = attributes[id];
if (direct !== undefined && direct !== null)
return direct;
const legacyId = FARMING_ATTRIBUTE_SHARDS[id]?.skyblockId;
if (!legacyId)
return 0;
const legacy = attributes[legacyId];
return legacy ?? 0;
}
export function normalizeAttributes(attributes) {
if (!attributes)
return undefined;
const normalized = {};
for (const [id, amount] of Object.entries(attributes)) {
const shardId = normalizeAttributeId(id) ?? id;
normalized[shardId] = amount;
}
return normalized;
}
export const ATTRIBUTE_SHARD_LEVELING = {
[Rarity.Common]: [1, 3, 5, 6, 7, 8, 10, 14, 18, 24],
[Rarity.Uncommon]: [1, 2, 3, 4, 5, 6, 7, 8, 12, 16],
[Rarity.Rare]: [1, 2, 3, 3, 4, 4, 5, 6, 8, 12],
[Rarity.Epic]: [1, 1, 2, 2, 3, 3, 4, 4, 5, 7],
[Rarity.Legendary]: [1, 1, 1, 2, 2, 2, 3, 3, 4, 5],
};
export function getShardLevel(rarity, amount) {
if (!amount || amount <= 0)
return 0;
const levels = ATTRIBUTE_SHARD_LEVELING[rarity];
if (!levels)
return 0;
for (let i = 0; i < levels.length; i++) {
const threshold = levels[i];
if (amount < threshold) {
return i;
}
amount -= threshold;
}
return levels.length;
}
export function getShardsForLevel(rarity, level) {
const levels = ATTRIBUTE_SHARD_LEVELING[rarity];
if (!levels || level <= 0)
return 0;
return levels.slice(0, level).reduce((sum, current) => sum + current, 0);
}
export function getShardsForNextLevel(rarity, amount) {
const levels = ATTRIBUTE_SHARD_LEVELING[rarity];
if (!levels || amount < 0)
return 0;
for (let i = 0; i < levels.length; i++) {
const threshold = levels[i];
if (amount < threshold) {
return threshold - amount;
}
amount -= threshold;
}
return 0;
}
export function getShardFortune(shard, player, level) {
return getShardStat(shard, player, Stat.FarmingFortune, level);
}
export function getShardStat(shard, player, stat, level) {
const shardId = normalizeAttributeId(shard.skyblockId);
const amount = shardId !== undefined
? getAttributeAmount(player.attributes, shardId)
: (player.attributes?.[shard.skyblockId] ?? 0);
level ??= getShardLevel(shard.rarity, amount);
if (level <= 0)
return 0;
const active = shard.active?.(player);
if (active && !active.active) {
return 0;
}
const stats = getStatValue(shard.stats?.[stat], player);
const perLevel = getStatValue(shard.perLevelStats?.[stat], player);
return stats + level * perLevel;
}
//# sourceMappingURL=attributes.js.map