diff --git a/common/constants/enchantments.js b/common/constants/enchantments.js index 6d20e30ef1..7cc3f7b02e 100644 --- a/common/constants/enchantments.js +++ b/common/constants/enchantments.js @@ -66,7 +66,9 @@ export const MAX_ENCHANTS = new Set([ "Prosecute VI", "Protection VII", "Punch II", + "Quantum V", "Rainbow I", + "Reflection V", "Rejuvenate V", "Replenish I", "Respiration III", @@ -89,6 +91,7 @@ export const MAX_ENCHANTS = new Set([ "Thunderbolt VI", "Thunderlord VII", "Titan Killer VII", + "Transylvanian V", "Triple-Strike V", "True Protection I", "Turbo-Cacti V", diff --git a/common/constants/stats.js b/common/constants/stats.js index edfc1c56c0..1c94bd4eb0 100644 --- a/common/constants/stats.js +++ b/common/constants/stats.js @@ -237,6 +237,33 @@ export const STATS_DATA = { suffix: "", color: "3", }, + mana_regen: { + name: "Mana Regen", + nameLore: "Mana Regen", + nameShort: "Mana Regen", + nameTiny: "MPR", + symbol: "🗲", + suffix: "", + color: "b", + }, + rift_time: { + name: "Rift Time", + nameLore: "Rift Time", + nameShort: "Rift Time", + nameTiny: "RT", + symbol: "ф", + suffix: "", + color: "a", + }, + undead: { + name: "Undead", + nameLore: "Undead", + nameShort: "Undead", + nameTiny: "U", + symbol: "༕", + suffix: "", + color: "2", + }, }; const symbols = { diff --git a/package.json b/package.json index 7039ccf6d6..b8b7dafe74 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,7 @@ "sharp": "^0.30.7", "sitemap": "^7.1.1", "skinview3d": "^2.2.1", - "skyhelper-networth": "^1.12.10", + "skyhelper-networth": "^1.14.1", "tippy.js": "^6.3.7", "twemoji": "^14.0.2", "upng-js": "^2.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a98ba6a873..e5eabcdd62 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -101,8 +101,8 @@ dependencies: specifier: ^2.2.1 version: 2.2.1 skyhelper-networth: - specifier: ^1.12.10 - version: 1.12.10 + specifier: ^1.14.1 + version: 1.14.1 tippy.js: specifier: ^6.3.7 version: 6.3.7 @@ -4138,8 +4138,8 @@ packages: three: 0.136.0 dev: false - /skyhelper-networth@1.12.10: - resolution: {integrity: sha512-QGPEGesL2G9uExSO26ww/WxXU31m1yBnhQOHw5OjNrXo5/JmpaelIh1BCyTaXklsornPdy2gFxpu/bWPPArdFg==} + /skyhelper-networth@1.14.1: + resolution: {integrity: sha512-UsRTBiR3Q7ZjeDaT4VlMYq1z27gb1I3SZ7qGowWGNK6TyoSFAIeEbB/JWmaLmfj8Az6gh4GRXS2aHP0JDoVxHg==} dependencies: axios: 0.27.2 prismarine-nbt: 2.2.1 diff --git a/public/resources/scss/stats.scss b/public/resources/scss/stats.scss index a9a6e8e2ab..d0c688d48e 100644 --- a/public/resources/scss/stats.scss +++ b/public/resources/scss/stats.scss @@ -2008,12 +2008,14 @@ inventory-view { .collections, .minions, .stat-farming-crops, -.sea-creatures { +.sea-creatures, +.trophy-fish { display: flex; flex-wrap: wrap; gap: 8px; - &.sea-creatures { + &.sea-creatures, + &.trophy-fish { gap: 15px; } } @@ -2065,6 +2067,63 @@ inventory-view { font-size: 14px; } +.trophy-fish-data { + font-size: 16px; + font-weight: 450; + + .trophy-fish-info { + margin-bottom: 2px; + + .trophy-fish-amount { + color: rgba(var(--text-rgb), 0.7); + font-weight: 500; + } + } + + .trophy-fish-count { + display: grid; + grid-template-columns: repeat(2, auto 1fr); + gap: 0px 4px; + height: 44px; + + text-align: left; + align-items: center; + } + + .count-value { + height: 22px; + + svg { + width: 20px; + height: 22px; + } + } + + .count-format { + height: 12px; + width: 12px; + border-radius: 50%; + } + + .bronze-count { + background-color: #a85c03; + } + + .gold-count { + background-color: #feb801; + } + + .silver-count { + background-color: #b4b4b5; + margin-left: 10px; + } + + .diamond-count { + background-color: #68ecff; + margin-left: 10px; + } +} + .narrow-info-header { position: absolute; top: 0; @@ -2381,7 +2440,8 @@ inventory-view { .collections, .minions, .stat-farming-crops, - .sea-creatures { + .sea-creatures, + .trophy-fish { flex-wrap: nowrap; overflow-x: auto; margin-left: calc(-1 * var(--padding)); @@ -2391,7 +2451,8 @@ inventory-view { contain-intrinsic-size: 200px 64px; } - &.sea-creatures { + &.sea-creatures, + &.trophy-fish { @supports (contain-intrinsic-size: 140px 230px) { contain-intrinsic-size: 140px 230px; } diff --git a/src/constants.js b/src/constants.js index 2d1803ef65..df9b3e44be 100644 --- a/src/constants.js +++ b/src/constants.js @@ -18,5 +18,6 @@ export * from "./constants/random-emoji.js"; export * from "./constants/skills.js"; export * from "./constants/skins-animations.js"; export * from "./constants/tags.js"; +export * from "./constants/trophy-fish.js"; export * from "./constants/accessories.js"; export * from "./constants/powers.js"; diff --git a/src/constants/accessories.js b/src/constants/accessories.js index 674afbe2ae..10b1fe752b 100644 --- a/src/constants/accessories.js +++ b/src/constants/accessories.js @@ -74,7 +74,6 @@ const accessoryUpgrades = [ ["KUUDRA_FOLLOWER_ARTIFACT", "KUUDRA_FOLLOWER_RELIC"], ["AGARIMOO_TALISMAN", "AGARIMOO_RING", "AGARIMOO_ARTIFACT"], ["BLOOD_DONOR_TALISMAN", "BLOOD_DONOR_RING", "BLOOD_DONOR_ARTIFACT"], - ["CRUX_TALISMAN_1", "CRUX_TALISMAN_2", "CRUX_TALISMAN_3", "CRUX_TALISMAN_4", "CRUX_TALISMAN_5", "CRUX_TALISMAN_6"], ["LUSH_TALISMAN", "LUSH_RING", "LUSH_ARTIFACT"], ]; @@ -96,6 +95,17 @@ const ignoredAccessories = [ "HOCUS_POCUS_CIPHER", "TINY_DANCER", "MINIATURIZED_TUBULATOR", + "PUNCHCARD_ARTIFACT", + "HARMONIOUS_SURGERY_TOOLKIT", + "CRUX_TALISMAN_1", + "CRUX_TALISMAN_2", + "CRUX_TALISMAN_3", + "CRUX_TALISMAN_4", + "CRUX_TALISMAN_5", + "CRUX_TALISMAN_6", + "WARDING_TRINKET", + "RING_OF_BROKEN_LOVE", + "GARLIC_FLAVORED_GUMMY_BEAR", ]; export const accessoryAliases = { diff --git a/src/constants/misc.js b/src/constants/misc.js index 53599cb84b..a8ed41412c 100644 --- a/src/constants/misc.js +++ b/src/constants/misc.js @@ -163,6 +163,7 @@ export const AREA_NAMES = { winter: "Jerry's Workshop", instanced: "Kuudra's End", garden: "The Garden", + rift: "Rift", }; export const COLOR_NAMES = { diff --git a/src/constants/pet-stats.js b/src/constants/pet-stats.js index 2da9ae6fb2..7963cbed17 100644 --- a/src/constants/pet-stats.js +++ b/src/constants/pet-stats.js @@ -9,11 +9,11 @@ const LEGENDARY = RARITIES.indexOf("legendary"); const MYTHIC = RARITIES.indexOf("mythic"); function formatStat(stat) { - const statFloored = Math.floor(stat); - if (statFloored > 0) { - return `§a+${statFloored}`; + const formattedStat = stat.toFixed(2).replace(/\.?0+$/, ""); + if (stat > 0) { + return `§a+${formattedStat}`; } else { - return `§a${statFloored}`; + return `§a${formattedStat}`; } } @@ -119,6 +119,12 @@ class Pet { case "fishing_speed": list.push(`§7Fishing Speed: ${formatStat(newStats[stat])}`); break; + case "rift_time": + list.push(`§7Rift Time: §a${formatStat(newStats[stat])}s`); + break; + case "mana_regen": + list.push(`§7Mana Regen: §a${formatStat(newStats[stat])}%`); + break; default: list.push(`§cUNKNOWN: ${stat}`); break; @@ -1008,9 +1014,9 @@ class GoldenDragon extends Pet { if (this.level >= 100) { const goldCollectionDigits = this.profile?.collections?.GOLD_INGOT?.totalAmount.toString().length ?? 0; - stats.strength = round(25 + Math.max(0, this.level - 100) * 0.25, 0) + 10 * goldCollectionDigits; - stats.bonus_attack_speed = round(25 + Math.max(0, this.level - 100) * 0.25, 0); - stats.magic_find = round(5 + Math.max(0, (this.level - 100) / 10) * 0.5, 0) + 2 * goldCollectionDigits; + stats.strength = Math.floor(25 + Math.max(0, this.level - 100) * 0.25) + 10 * goldCollectionDigits; + stats.bonus_attack_speed = Math.floor(25 + Math.max(0, this.level - 100) * 0.25); + stats.magic_find = Math.floor(5 + Math.max(0, (this.level - 100) / 10) * 0.5) + 2 * goldCollectionDigits; } return stats; } @@ -1315,11 +1321,21 @@ class Guardian extends Pet { if (this.rarity >= LEGENDARY) { list.push(this.third); } + if (this.rarity >= MYTHIC) { + list.push(this.fourth); + } return list; } get first() { - const mult = getValue(this.rarity, { common: 0.02, uncommon: 0.06, rare: 0.1, epic: 0.15, legendary: 0.2 }); + const mult = getValue(this.rarity, { + common: 0.02, + uncommon: 0.06, + rare: 0.1, + epic: 0.15, + legendary: 0.2, + mythic: 1.2, + }); return { name: "§6Lazerbeam", desc: [ @@ -1345,6 +1361,14 @@ class Guardian extends Pet { desc: [`§7Regenerate §b${round(this.level * mult, 1)}% §7extra mana, doubled when near or in water§7.`], }; } + + get fourth() { + const mult = getValue(this.rarity, { mythic: 0.07 }); + return { + name: "§6Lucky Seven", + desc: [`§7Gain §b +${round(this.level * mult, 1)}% §7chance to find §5ultra rare §7books in §dSuperpairs.`], + }; + } } class Horse extends Pet { @@ -1796,6 +1820,9 @@ class Spider extends Pet { if (this.rarity >= LEGENDARY) { list.push(this.third); } + if (this.rarity >= MYTHIC) { + list.push(this.fourth); + } return list; } @@ -1825,6 +1852,15 @@ class Spider extends Pet { desc: [`§7Spider and tarantula minions work §a${round(this.level * mult, 1)}% §7faster while on your island.`], }; } + + get fourth() { + return { + name: "§6Web Battlefield", + desc: [ + `§7Killing mobs grants §c+6 ${SYMBOLS.strength} Strength §7and §b+1 ${SYMBOLS.magic_find} Magic Find §7for §a40s §7to all players staying within §a20 §7blocks of where they died. §8Stacks up to 10 times.`, + ], + }; + } } class Spirit extends Pet { @@ -1882,6 +1918,9 @@ class Tarantula extends Pet { if (this.rarity >= LEGENDARY) { list.push(this.third); } + if (this.rarity >= MYTHIC) { + list.push(this.fourth); + } return list; } @@ -1902,10 +1941,19 @@ class Tarantula extends Pet { } get third() { - const mult = getValue(this.rarity, { legendary: 0.5 }); + const mult = getValue(this.rarity, { legendary: 0.005 }); return { name: "§6Arachnid Slayer", - desc: [`§7Grants §a${round(this.level * mult, 1)}% §3${SYMBOLS.wisdom} Combat Wisdom §7against §aSpiders§7.`], + desc: [`§7Gain §b${round(1 + this.level * mult, 1)}x §7Combat XP against §aSpiders§7.`], + }; + } + + get fourth() { + return { + name: "§6Web Battlefield", + desc: [ + `§7Killing mob grants §c+6 ${SYMBOLS.strength} Strength §7and §b+1 ${SYMBOLS.magic_find} Magic Find §7for §a40s §7to all players staying within §a20 §7blocks of where they died. §8Stacks up to 10 times.`, + ], }; } } @@ -2136,10 +2184,10 @@ class Zombie extends Pet { } get third() { - const mult = getValue(this.rarity, { legendary: 0.25 }); + const mult = getValue(this.rarity, { legendary: 0.2 }); return { name: "§6Living Dead", - desc: [`§7Increases the defense of all undead armor sets by §a${round(this.level * mult, 1)}%§7.`], + desc: [`§7Increases all stats on §7§2undead ${SYMBOLS.undead} §7armor by §a${round(this.level * mult, 1)}%§7.`], }; } } @@ -2295,6 +2343,45 @@ class Monkey extends Pet { } } +class Montezuma extends Pet { + get stats() { + const riftSouls = + "objectives" in (this.profile ?? {}) + ? Object.entries(this.profile.objectives).find( + ([key, value]) => key.startsWith("rift_") && key.endsWith("_soul") && value.status === "COMPLETE" + )?.length ?? 0 + : 0; + + return { + rift_time: riftSouls * 15, + mana_regen: riftSouls * 2, + }; + } + + get abilities() { + const list = [this.first]; + if (this.rarity >= RARE) { + list.push(this.second); + } + + return list; + } + + get first() { + return { + name: "§6Nine Lives", + desc: [`§7Gain §a+15${SYMBOLS.rift_time} Rift Time §7per Soul piece.`], + }; + } + + get second() { + return { + name: "§6Trickery", + desc: [`§7Gain §b+2 ${SYMBOLS.mana_regen} Mana Regen §7per soul piece found.`], + }; + } +} + class Ocelot extends Pet { get stats() { return { @@ -3174,7 +3261,7 @@ class Snail extends Pet { } get first() { - const mult = getValue(this.rarity, { common: 0.1, uncommon: 0.2, rare: 0.3 }); + const mult = getValue(this.rarity, { comMONTEZUMA: 0.1, uncommon: 0.2, rare: 0.3 }); return { name: "§6Red Sand Enjoyer", @@ -3334,6 +3421,28 @@ class Reindeer extends Pet { } } +class RiftFerret extends Pet { + get stats() { + return { + speed: 0.5 * this.level, + intelligence: -0.02 * this.level, + }; + } + + get abilities() { + const list = [this.first]; + + return list; + } + + get first() { + return { + name: "§6Orbs are Fun", + desc: [`§7Gain §a+10% §7experience from §bXP Orbs§7.`], + }; + } +} + class QuestionMark extends Pet { get stats() { return {}; @@ -3412,6 +3521,7 @@ export const PET_STATS = { MEGALODON: Megalodon, MITHRIL_GOLEM: MithrilGolem, MONKEY: Monkey, + MONTEZUMA: Montezuma, MOOSHROOM_COW: MooshroomCow, OCELOT: Ocelot, PARROT: Parrot, @@ -3421,6 +3531,7 @@ export const PET_STATS = { RABBIT: Rabbit, RAT: Rat, REINDEER: Reindeer, + RIFT_FERRET: RiftFerret, ROCK: Rock, SCATHA: Scatha, SHEEP: Sheep, diff --git a/src/constants/pets.js b/src/constants/pets.js index 4e8bfed84b..e85300ecce 100644 --- a/src/constants/pets.js +++ b/src/constants/pets.js @@ -239,7 +239,7 @@ export const PET_DATA = { GUARDIAN: { head: "/head/221025434045bda7025b3e514b316a4b770c6faa4ba9adb4be3809526db77f9d", type: "enchanting", - maxTier: "legendary", + maxTier: "mythic", maxLevel: 100, emoji: "🐡", }, @@ -274,7 +274,7 @@ export const PET_DATA = { SPIDER: { head: "/head/cd541541daaff50896cd258bdbdd4cf80c3ba816735726078bfe393927e57f1", type: "combat", - maxTier: "legendary", + maxTier: "mythic", maxLevel: 100, emoji: "🕷️", }, @@ -367,7 +367,7 @@ export const PET_DATA = { TARANTULA: { head: "/head/8300986ed0a04ea79904f6ae53f49ed3a0ff5b1df62bba622ecbd3777f156df8", type: "combat", - maxTier: "legendary", + maxTier: "mythic", maxLevel: 100, emoji: "🕸️", }, @@ -535,6 +535,20 @@ export const PET_DATA = { maxLevel: 100, emoji: "🦌", }, + RIFT_FERRET: { + head: "/head/b6b11399448260185da1d17e54c984515faab6d8585f00972451ec2b43d46f94", + type: "combat", + maxTier: "legendary", + maxLevel: 100, + emoji: "🦝", + }, + MONTEZUMA: { + head: "/head/df656c06e8a5cb4692564ee21748bddec9d785d1834284aaa1439601bba47d6b", + type: "combat", + maxTier: "epic", + maxLevel: 100, + emoji: "💀", + }, }; export const PET_VALUE = { @@ -863,4 +877,18 @@ export const PET_ITEMS = { description: `§7Grants §6+4 ${SYMBOLS.farming_fortune} Farming Fortune§7 for each Garden Level unlocked.`, // TODO: Add statsPerLevel once Garden data comes to the API }, + DEAD_CAT_FOOD: { + name: "Dead Cat Food", + tier: "RARE", + description: "§7Grants §a+30 ${SYMBOLS.rift_time} Rift Time §7and §b5 ${SYMBOLS.mana_regen} Mana Regen§7.", + stats: { + rift_time: 30, + mana_regen: 5, + }, + }, + FOUR_EYED_FISH: { + name: "Four-Eyed Fish", + tier: "EPIC", + description: `§7Gain §6+2,000 Coins §7when digging up any §eGriffin Burrow§7.\n§7Grants §b+10 ${SYMBOLS.magic_find} Magic Find §7and §a+55 ${SYMBOLS.defense} Defense§7.`, + }, }; diff --git a/src/constants/skins-animations.js b/src/constants/skins-animations.js index 02e075567b..d251726886 100644 --- a/src/constants/skins-animations.js +++ b/src/constants/skins-animations.js @@ -853,6 +853,20 @@ const SKINS = [ source: "firesale", release: new Date("2023-04-21 18:00:00 GMT+1").getTime(), }, + { + id: "PET_SKIN_WHALE_COSMIC", + name: "Cosmic", + texture: "/head/1a68f59a187f5b7183df2ea708a6e4704845afd433272cd32cbed52286db1fd3", + source: "firesale", + release: new Date("2023-06-02 18:00:00 GMT+1").getTime(), + }, + { + id: "PET_SKIN_MONKEY_LEMUR", + name: "Lemur", + texture: "/head/b6f45eb8a8bef3f8ee406ac0923d8626c5e5b7ff511cfbd417c994b68941f104", + source: "firesale", + release: new Date("2023-06-19 18:00:00 GMT+1").getTime(), + }, ]; /* diff --git a/src/constants/trophy-fish.js b/src/constants/trophy-fish.js new file mode 100644 index 0000000000..c9e2d13770 --- /dev/null +++ b/src/constants/trophy-fish.js @@ -0,0 +1,205 @@ +import { STATS_DATA } from "../../common/constants/stats.js"; + +export const TROPHY_FISH = { + BLOBFISH: { + display_name: "Blobfish", + description: "§7Caught everywhere.", + textures: { + bronze: "3e77a61f2a25f19bb047be985b965f069d857502881bea3f9682d00bfd5cc3e7", + silver: "40e6628e5c358e080d3180c7424b70371e67e5724020b68a64d60ab41fe70bae", + gold: "2e93d72c19e7b917f233dc291b749391f2d870ef30cafc5f17281023ae17c2b9", + diamond: "d9339dfceaa5d99a5571ec4743b004d827b229eaf00eb703ced03a86029f3ad", + }, + }, + FLYFISH: { + display_name: "Flyfish", + description: "§7Caught from §a8 §7blocks or higher above lava in the §cBlazing Volcano§7.", + textures: { + bronze: "5140c42fc3a1ba2fe77c45b975fa87e8f54a1b1833bc76e6339b4c262304011d", + diamond: "1516c233797626ce5e0132166062ae1cb435c561c00a6fa11b37e2295f8c7c5b", + gold: "6051fc3ea4b8459df839e67c157e9d1a753be0603cbf18d3c1352ebf61b58581", + silver: "adc59df19336fa7a84e4637519d7f843c38e7673ffcc3f39edeed950e28d8b57", + }, + }, + GOLDEN_FISH: { + display_name: "Golden Fish", + description: + "§7Has a chance to spawn after §a15 §7minutes of fishing, increasing linearly until reaching 100% at 20 minutes. The §6Golden Fish §7is rolled when your fishing hook is thrown out, regardless of if you catch a fish or not. You are not required to Trophy Fish to catch this one.", + textures: { + bronze: "fcfa31d81eae819936834e6664430daf8affbff30b48a1daa7ca1b4c20e3fe7d", + diamond: "f46cb8cbb60cda60092b3051648dd2db7eec49ae87f3f524c6182797b4109a12", + gold: "38175538210af6a4d1a443e08ee321abad837c6c927c7803ab361d29e3f8e509", + silver: "98ac13a462e9e9ffc3569c6beb44e4b28be5a15e7628c8957c5cddfaff26c285", + }, + }, + GUSHER: { + display_name: "Gusher", + description: "§7Caught within §a7-16 §7minutes after a §cBlazing Volcano §7eruption.", + textures: { + bronze: "afb8c51bfcd996840010bcce2a3575ae26352e00446d3ec313fcbf1f88108512", + diamond: "577322d86e61df34b2dcbb3fa7f4d03d0e3be56bddac6bdf2e7de61e21f718eb", + gold: "d550a51e76f32aaa556b98d817db6ae71aadb2af7d76c34b903dad5ee2f90439", + silver: "e5c2828e950c1fd7f73a6b7879d8b562ecff894b6cb22afb9c2660627b3b8dfe", + }, + }, + KARATE_FISH: { + display_name: "Karate Fish", + description: + "§7Caught in the lava pools near the §eDojo§7. Note - Half of the lava pools do not actually count as being in the §eDojo §7area. If you stand in the same place as your bobber and do not see '§eDojo§7' in the sidebar, you cannot catch the §5Karate Fish §7there.", + textures: { + bronze: "901ef47164aba899674cac1e04dda29895ba670807a162e888681c6428e42a83", + diamond: "fa57e62e393f80cd4bb23109c7c869b1f66621ceccae4b7601afb3269120294d", + gold: "ac28a1f0f3908274e5860e1ac1b122b7323327aeb376e8378a036c9fa8bf35c5", + silver: "e56227d0e98b7541b2922e9cd9113155d13028978d4c3f68775199ea27299fd4", + }, + }, + LAVA_HORSE: { + display_name: "Lavahorse", + description: "§7Caught everywhere.", + textures: { + bronze: "1176ea86635c4e849469ed694b3c0c3f7ec7677ed0682bee5ef6d59ea669677f", + diamond: "67e685788792dc90e7d19c2932f3dc1dbe396e6cac068260997ea0b64ffd2bf8", + gold: "a4d8850536ca5d3b735691be439c7f8619ebc14ad0aef78055fd86a37dd2adf1", + silver: "124ab405566c448c7484132f99a7bb79bdf547ae50713c0dd866a2375156b2c7", + }, + }, + MANA_RAY: { + display_name: "Mana Ray", + description: `§7Caught when you have at least §b1,200 ${STATS_DATA.intelligence.symbol} Intelligence§7.`, + textures: { + bronze: "ff357b0f4e13cc2013bf4a02a3d3351ab0d7856e73f9f0cf8b6f13e78d95b215", + diamond: "6d6dacd67f0562980e597a8ba508b3e321002f4d358c85dd9a4a39bacaea63f8", + gold: "c515e96329992b2969c427a17ae68173ad0f8b86f9e3a0e3f9460385581edfe3", + silver: "dfd706157c2a3e2c8c3674cbc37f7a1206b87b7a6453d11e7408492c01c35634", + }, + }, + MOLDFIN: { + display_name: "Moldfin", + description: "§7Caught in the §5Mystic Marsh§7.", + textures: { + bronze: "54f33dc405ba447b35926b48d90600302aeebb140ad330d885886cb1029a8af", + diamond: "9c99ddc1d711f482305d8f1ffcadd4b444fad1b0b07c5be2b73b1f08ee6cbe5e", + gold: "5113e386937a8ed25fe40fdbe6b88712ae73411f6a0ae927420ffcb9d778226b", + silver: "6a52dd3040aca257bf361c15cc4a0114f850b2a91867ee49d26cebca5203aab4", + }, + }, + OBFUSCATED_FISH_1: { + display_name: "Obfuscated 1", + description: "§7Caught with §fCorrupted Bait§7.", + textures: { + bronze: "e1f4d91e1bf8d3c4258fe0f28ec2fa40670e25ba06ac4b5cb1abf52a83731a9c", + diamond: "caa0b4b4f443257e83176df4ffd550de7ee89867e506b9c1ca53f33611327929", + gold: "8a2a44913ee1d5babc172f374351ea7ad1516ca256d16a4ef72d8a092b519cd1", + silver: "479b52391ff0cd3c83db1c1c218a02ab13a2c6a4aaa1cf126c7912bd377e8fbf", + }, + }, + OBFUSCATED_FISH_2: { + display_name: "Obfuscated 2", + description: "§7Caught whilst using Obfuscated 1 as bait.", + textures: { + bronze: "8321e19aa4b3163c8990b066b1cd0895c3c97a799057327507db0ffc80d90575", + gold: "4631953a0351988029b90e838181e4e563d782e470ea33b8c612756f730625c2", + silver: "cb12de47e0b48ab8f7d8f500fdc5d7869b7f2192f823620088582a56afcf68fb", + diamond: "cdca1057973e87f875722d7cf5c7b3de2aa4831ced2aa4259c0e4bec7b499245", + }, + }, + OBFUSCATED_FISH_3: { + display_name: "Obfuscated 3", + description: "§7Caught with §9Obfuscated 2 §7as bait.", + textures: { + bronze: "df478663687d16f79b9c32546a7c3ec2736e87ce69779991e52deaf622abd8c2", + silver: "3c800c71b925587213382eeaaa426ed63112503e278ff9f5b3d39dbdb95d31d0", + gold: "97f71c13302401772e611a2a508f23df54b778be725ce231662f3fc810d258a1", + diamond: "665a04023ce40813abee55061fe802d2f8195fcdee3570388bba072073ecef3a", + }, + }, + SKELETON_FISH: { + display_name: "Skeleton Fish", + description: "§7Caught in the §cBurning Desert§7.", + textures: { + bronze: "923e0a25048b60a2cc092f72943159ec170063bb235aa79690ef34ab181d691", + diamond: "ed01389874c7be1165d5df633daf27d936bfaf553143cfcbaa50c93c4746f9f3", + gold: "639dd2fe302e2ac4d9e8d31876489258b04e58a8e8754714669145a89a82d2e0", + silver: "a39846ad1c8fd3420febff458401bacd91d1f4fd444940f7f7cb9e2a490ca4dd", + }, + }, + SLUGFISH: { + display_name: "Slugfish", + description: "§7Caught when the bobber has been active for at least §a30 §7seconds.", + textures: { + bronze: "c1de9e49ecc8d6209c783bfd1684a89e624a4e483a86023c6df57f77d5b75890", + diamond: "a5d717aa5c9063181283811d265bfd0ffdc7eda09a0984cee59578b4a5efd4a1", + gold: "289d72f3750a5cd244cbf09af9478453b6575df591d720b6ec23d84a165c65f2", + silver: "d82efd885e6e2a964efb857de724b2ef043f1dcbbe618f10ec3742c6f2cecab", + }, + }, + SOUL_FISH: { + display_name: "Soul Fish", + description: "§7Caught in the §2Stronghold§7.", + textures: { + bronze: "7fe554d346c20c161aa85cfdc1b89779c9f64e726a5bb28ace8078e6594052d7", + diamond: "b63912df6540359774fb5cb4546a2eea1736f3fc7cf2848421697c1be8a5361", + gold: "3c9548a25e68332e6dde60816d811242fa40da58a5e24a5233e0079d9c57f779", + silver: "d086c5700ec707d703cfb45ab8afee5269a59eedda516a2c68f3e2aef7fa6a94", + }, + }, + STEAMING_HOT_FLOUNDER: { + display_name: "Steaming-Hot Flounder", + description: "§7Caught when the bobber is within §a2 §7blocks of a Geyser in the §cBlazing Volcano§7.", + textures: { + bronze: "8b88f88f3053c434660eeb4c7b2344bc21ab52596cea5a66d0f9db8c0e050209", + diamond: "c6602a15cf491f76584179221ed1da25fe6918f9100b864b39ea6493734809d1", + gold: "305cb6623837195113c04409658f9e8872a05e2321b79dfd1ce48eda6f749b90", + silver: "6887f3db9e1f28f08fed4fdc8be40dbeef7a04f026d5e30041ecd49a78558efb", + }, + }, + SULPHUR_SKITTER: { + display_name: "Sulphur Skitter", + description: "§7Caught when standing within §a8 §7blocks of a Sulphur Ore.", + textures: { + bronze: "4fbf7111609f2ec23d9b3f285e1755b62193bd7c3d770576e2b18c48afeb0e29", + diamond: "4c6eac56808a85b59d48aff59a262922a57cfa766f6c56f69c7d91fea230fa", + gold: "a79c52c2bb808d2e46e8e4e4db506f9406e9dfa20aee419ad90eacfb0216c169", + silver: "ba6e3560712f7213a428518deb66c0638269d17e90d8f31d4ade2a0acb91fd80", + }, + }, + VANILLE: { + display_name: "Vanille", + description: "§7Caught when using a §aStarter Lava Rod §7with no Enchantments.", + textures: { + bronze: "57120222cce38d53ba69fc6540e97bff9abdbe22ba6068d4ee9af52ecc56842f", + diamond: "bd6519e85f7fd69cb2d7bbd8d77018d907cab7b9ec1309eb933de78df00b63c1", + gold: "7684b553c9b045a429a775881130c5e6daa547d314f1f0255135f5bd46870e85", + silver: "7313271354dc2e5b1a720c6668f03ca7106ee439f874907f2a54083f0cb57721", + }, + }, + VOLCANIC_STONEFISH: { + display_name: "Volcanic Stonefish", + description: "§7Caught in the §cBlazing Volcano§7.", + textures: { + bronze: "38f89cbaa61ecc99a8321d53f070cef8414efc3eac47bf6fe143056fed9ee8", + diamond: "48bec97138419aff0af6fb445cd5f8d68e30698facf46ae956cbda2331fb2284", + gold: "491156fede270a2fe49acf80d5956a0a9f312e37a0be669c3da54732a4c169c2", + silver: "f868b5727d27ace0beca1ca19c783b5375a88ce3d3956a0c589b4ba167e6c18f", + }, + }, +}; + +export const TROPHY_FISH_STAGES = { + 1: { + formatted: `Bronze Hunter`, + type: "bronze", + }, + 2: { + formatted: `Silver Hunter`, + type: "silver", + }, + 3: { + formatted: `Gold Hunter`, + type: "gold", + }, + 4: { + formatted: `Diamond Hunter`, + type: "diamond", + }, +}; diff --git a/src/lib.js b/src/lib.js index ce26592e5e..402ef3fcd2 100644 --- a/src/lib.js +++ b/src/lib.js @@ -369,13 +369,13 @@ async function processItems(base64, source, customTextures = false, packs, cache Damage: hypixelItem?.damage ?? 3, id: hypixelItem?.item_id ?? 397, itemIndex: item.containsItems.length, - glowing: hypixelItem.glowing, - display_name: hypixelItem.name, - rarity: hypixelItem.tier, + glowing: hypixelItem?.glowing ?? false, + display_name: hypixelItem?.name ?? _.startCase(item.tag.ExtraAttributes[key].replace(/_/g, " ")), + rarity: hypixelItem?.tier ?? "common", categories: [], }; - if (hypixelItem.texture !== undefined) { + if (hypixelItem?.texture !== undefined) { itemData.texture_path = `/head/${hypixelItem.texture}`; } @@ -386,6 +386,10 @@ async function processItems(base64, source, customTextures = false, packs, cache itemData.texture_path = `/leather/${type}/${color}`; } + if (hypixelItem === null) { + itemData.texture_path = "/head/bc8ea1f51f253ff5142ca11ae45193a4ad8c3ab5e9c6eec8ba7a4fcb7bac40"; + } + item.containsItems.push(itemData); } } @@ -1988,6 +1992,7 @@ export async function getStats( output.minion_slots = getMinionSlots(output.minions); output.collections = await getCollections(profile.uuid, profile, options.cacheOnly); output.bestiary = getBestiary(profile.uuid, profile); + output.social = hypixelProfile.socials; output.dungeons = getDungeons(userProfile, hypixelProfile); @@ -2261,6 +2266,8 @@ export async function getStats( output.crimsonIsles = crimsonIsles; + output.trophy_fish = getTrophyFish(userProfile); + output.abiphone = { contacts: userProfile.nether_island_player_data?.abiphone?.contact_data ?? {}, active: userProfile.nether_island_player_data?.abiphone?.active_contacts?.length || 0, @@ -2336,7 +2343,7 @@ export async function getStats( output.skyblock_level = { xp: userProfile.leveling?.experience || 0, level: Math.floor(userProfile.leveling?.experience / 100 || 0), - maxLevel: 386, + maxLevel: 416, progress: (userProfile.leveling?.experience % 100) / 100 || 0, xpCurrent: userProfile.leveling?.experience % 100 || 0, xpForNext: 100, @@ -2631,6 +2638,8 @@ export async function getStats( output.reaper_peppers_eaten = userProfile.reaper_peppers_eaten ?? 0; + output.objectives = userProfile.objectives ?? 0; + if (!userProfile.pets) { userProfile.pets = []; } @@ -2684,7 +2693,7 @@ export async function getStats( return output; } -export async function getPets(profile, userProfile) { +export async function getPets(profile, calculated) { let output = []; if (!("pets" in profile)) { @@ -2692,7 +2701,7 @@ export async function getPets(profile, userProfile) { } // debug pets - // profile.pets = helper.generateDebugPets("BINGO"); + // profile.pets = helper.generateDebugPets("TARANTULA"); for (const pet of profile.pets) { if (!("tier" in pet)) { @@ -2702,7 +2711,7 @@ export async function getPets(profile, userProfile) { const petData = constants.PET_DATA[pet.type] ?? { head: "/head/bc8ea1f51f253ff5142ca11ae45193a4ad8c3ab5e9c6eec8ba7a4fcb7bac40", type: "???", - maxTier: "LEGENDARY", + maxTier: "legendary", maxLevel: 100, emoji: "❓", }; @@ -2782,9 +2791,8 @@ export async function getPets(profile, userProfile) { const rarity = constants.RARITIES.indexOf(pet.rarity); const searchName = pet.type in constants.PET_STATS ? pet.type : "???"; - const petInstance = new constants.PET_STATS[searchName](rarity, pet.level.level, pet.extra, userProfile); + const petInstance = new constants.PET_STATS[searchName](rarity, pet.level.level, pet.extra, calculated ?? profile); pet.stats = Object.assign({}, petInstance.stats); - petInstance.profile = null; pet.ref = petInstance; if (pet.heldItem) { @@ -2879,20 +2887,25 @@ export async function getPets(profile, userProfile) { const progress = Math.ceil(pet.level.progress * 20); const numerator = pet.level.xpCurrent.toLocaleString(); - const denominator = helper.formatNumber(pet.level.xpForNext, false, 10); + const denominator = helper.formatNumber(pet.level.xpForNext, false); lore.push(`§2${"-".repeat(progress)}§f${"-".repeat(20 - progress)} §e${numerator} §6/ §e${denominator}`); } else { lore.push("§bMAX LEVEL"); } + let progress = Math.floor((pet.exp / pet.level.xpMaxLevel) * 100); + if (isNaN(progress)) { + progress = 0; + } + lore.push( "", `§7Total XP: §e${helper.formatNumber(pet.exp, true, 1)} §6/ §e${helper.formatNumber( pet.level.xpMaxLevel, true, 1 - )} §6(${Math.floor((pet.exp / pet.level.xpMaxLevel) * 100)}%)` + )} §6(${progress.toLocaleString()}%)` ); if (petData.obtainsExp !== "feed") { @@ -2907,6 +2920,7 @@ export async function getPets(profile, userProfile) { pet.display_name = `${petName}${petSkin ? " ✦" : ""}`; pet.emoji = petData.emoji; + pet.ref.profile = null; output.push(pet); } @@ -2989,7 +3003,10 @@ async function getMissingPets(pets, gameMode, userProfile) { profile.pets.push(pets[0]); } - return getPets(profile, userProfile); + profile.objectives = userProfile.objectives; + profile.collections = userProfile.collections; + + return await getPets(profile); } function getPetScore(pets) { @@ -3136,6 +3153,73 @@ export async function getCollections(uuid, profile, cacheOnly = false) { return output; } +export function getTrophyFish(userProfile) { + const output = { + total_caught: 0, + stage: { + name: null, + progress: null, + }, + fish: [], + }; + + for (const key of Object.keys(constants.TROPHY_FISH)) { + const id = key.toLowerCase(); + const caught = (userProfile.trophy_fish && userProfile.trophy_fish[id]) || 0; + const caughtBronze = (userProfile.trophy_fish && userProfile.trophy_fish[`${id}_bronze`]) || 0; + const caughtSilver = (userProfile.trophy_fish && userProfile.trophy_fish[`${id}_silver`]) || 0; + const caughtGold = (userProfile.trophy_fish && userProfile.trophy_fish[`${id}_gold`]) || 0; + const caughtDiamond = (userProfile.trophy_fish && userProfile.trophy_fish[`${id}_diamond`]) || 0; + + const highestType = + caughtDiamond > 0 ? "diamond" : caughtGold > 0 ? "gold" : caughtSilver > 0 ? "silver" : "bronze"; + + output.fish.push({ + id: key, + name: constants.TROPHY_FISH[key].display_name, + texture: constants.TROPHY_FISH[key].textures[highestType], + description: constants.TROPHY_FISH[key].description, + caught: { + total: caught, + bronze: caughtBronze, + silver: caughtSilver, + gold: caughtGold, + diamond: caughtDiamond, + highestType: highestType, + }, + }); + } + + output.total_caught = userProfile.trophy_fish?.total_caught || 0; + + const { type: stageType, formatted: stageFormatted } = + constants.TROPHY_FISH_STAGES[(userProfile.trophy_fish?.rewards || []).length] || {}; + const { type: stageProgressType } = constants.TROPHY_FISH_STAGES[ + (userProfile.trophy_fish?.rewards || []).length + 1 + ] || { + type: stageType, + }; + + const stageProgress = + stageType === "diamond" + ? null + : stageType + ? `${ + Object.keys(userProfile.trophy_fish).filter( + (a) => a.endsWith(stageProgressType) && userProfile.trophy_fish[a] > 0 + ).length + } / ${Object.keys(constants.TROPHY_FISH).length}` + : null; + + output.stage = { + name: stageFormatted || "None", + type: stageType, + progress: stageProgress, + }; + + return output; +} + export function getBestiary(uuid, profile) { const output = {}; @@ -3194,7 +3278,6 @@ export function getBestiary(uuid, profile) { return result; } - export function getDungeons(userProfile, hypixelProfile) { const output = {}; diff --git a/views/stats.ejs b/views/stats.ejs index 30aec5e433..6a9d73ea0a 100644 --- a/views/stats.ejs +++ b/views/stats.ejs @@ -10,8 +10,9 @@ ..######...#######..##....##..######.....##....##.....##.##....##....##.....######. */ const rarityOrder = ["very_special", "special", "supreme", "divine", "mythic", "legendary", "epic", "rare", "uncommon", "common"]; -const slayerOrder = ["zombie", "spider", "wolf", "enderman", "blaze", "vampire"]; +const slayerOrder = ["zombie", "spider", "wolf", "enderman", "vampire", "blaze"]; const badgeOrder = ["gold", "silver", "bronze"]; +const trophyFishOrder = ["bronze", "silver", "gold", "diamond"] const skillItems = { alchemy: "icon-379_0", @@ -1848,8 +1849,63 @@ const metaDescription = getMetaDescription() } %> <% } %> - + +
+ Total Caught:
+ <%= calculated.trophy_fish.total_caught.toLocaleString() %>
+
+ <% max = calculated.trophy_fish.stage.type === "diamond" ? 'golden-text' : '' %>
+ Current Stage:
+ <%= calculated.trophy_fish.stage.name %>
+ <% if (calculated.trophy_fish.stage.progress !== null) { %>
+ (<%= calculated.trophy_fish.stage.progress %>)
+ <% } %>
+
+