1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
|
import typedHypixelApi from 'typed-hypixel-api'
import { fetchItemList } from '../../hypixel.js'
import { levelFromXpTable } from '../../util.js'
import { ItemListItem } from './itemList.js'
import * as constants from '../../constants.js'
// https://hypixel-skyblock.fandom.com/wiki/Module:Pet/LevelingData?action=edit
const PET_LEVELS = [
100, 110, 120, 130, 145, 160, 175, 190, 210, 230, 250, 275, 300, 330, 360, 400, 440, 490, 540, 600, 660, 730, 800, 880, 960, 1050, 1150, 1260, 1380, 1510, 1650, 1800, 1960, 2130, 2310, 2500, 2700, 2920, 3160, 3420, 3700, 4000, 4350, 4750, 5200, 5700, 6300, 7000, 7800, 8700, 9700, 10800, 12000, 13300, 14700, 16200, 17800, 19500, 21300, 23200, 25200, 27400, 29800, 32400, 35200, 38200, 41400, 44800, 48400, 52200, 56200, 60400, 64800, 69400, 74200, 79200, 84700, 90700, 97200, 104200, 111700, 119700, 128200, 137200, 146700, 156700, 167700, 179700, 192700, 206700, 221700, 237700, 254700, 272700, 291700, 311700, 333700, 357700, 383700, 411700, 441700, 476700, 516700, 561700, 611700, 666700, 726700, 791700, 861700, 936700, 1016700, 1101700, 1191700, 1286700, 1386700, 1496700, 1616700, 1746700, 1886700
]
const PET_RARITY_OFFSET: Partial<Record<typedHypixelApi.Pet['tier'], number>> = {
COMMON: 0,
UNCOMMON: 6,
RARE: 11,
EPIC: 16,
LEGENDARY: 20
}
function calculateXpTable(rarity: keyof typeof PET_RARITY_OFFSET) {
const data = [0]
let current = 0
for (let i = 0; i < 100; i++) {
current += PET_LEVELS[i + ((rarity in PET_RARITY_OFFSET) ? PET_RARITY_OFFSET[rarity] : PET_RARITY_OFFSET['LEGENDARY'])!]
data.push(current)
}
return data
}
const RARITY_XP_TABLES = {
COMMON: calculateXpTable('COMMON'),
UNCOMMON: calculateXpTable('UNCOMMON'),
RARE: calculateXpTable('RARE'),
EPIC: calculateXpTable('EPIC'),
LEGENDARY: calculateXpTable('LEGENDARY'),
MYTHIC: calculateXpTable('MYTHIC')
}
export interface Pet {
id: string
xp: number
level: number
tier: typedHypixelApi.Pet['tier']
skin: string | null
item: ItemListItem | null
}
export interface PetsData {
active: Pet | null
list: Pet[]
missingIds: string[]
}
export async function cleanPets(data: typedHypixelApi.SkyBlockProfileMember): Promise<PetsData> {
const obtainedPets: Pet[] = []
let activePet: Pet | null = null
const allPetIds = await constants.fetchPets()
const obtainedPetIds: string[] = []
const itemList = await fetchItemList()
let petIds: string[] = []
for (const petData of data.pets ?? []) {
petIds.push(petData.type)
const xpTable = RARITY_XP_TABLES[petData.tier] ?? RARITY_XP_TABLES.LEGENDARY
const level = levelFromXpTable(petData.exp, xpTable)
const pet: Pet = {
id: petData.type,
// we round down xp because there's no point in showing decimals
xp: Math.floor(petData.exp),
level,
tier: petData.tier,
skin: petData.skin ?? null,
item: petData.heldItem ? (itemList.list.find(i => i.id === petData.heldItem) ?? null) : null
}
obtainedPetIds.push(pet.id)
obtainedPets.push(pet)
if (petData.active)
activePet = pet
}
constants.addPets(petIds)
const missingPetIds = allPetIds.filter(id => !obtainedPetIds.includes(id))
return {
active: activePet,
list: obtainedPets,
missingIds: missingPetIds
}
}
|