Skip to content

Commit 67062c0

Browse files
committed
small fixes or smth
1 parent dc9cbf7 commit 67062c0

File tree

12 files changed

+1126
-142
lines changed

12 files changed

+1126
-142
lines changed

API/constants/leveling.js

Lines changed: 823 additions & 0 deletions
Large diffs are not rendered by default.

API/constants/skills.js

Lines changed: 161 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,183 @@
1-
//CREDIT: https://github.com/SkyCrypt/SkyCryptWebsite (Modified)
2-
const xp_tables = require("./xp_tables.js");
3-
4-
module.exports = function calcSkill(skill, experience, type) {
5-
let table = "normal";
6-
if (skill === "runecrafting") table = "runecrafting";
7-
if (skill === "social") table = "social";
8-
if (skill === "dungeoneering") table = "catacombs";
9-
if (skill === "hotm") table = "hotm";
10-
11-
if (experience <= 0) {
12-
return {
13-
totalXp: 0,
14-
xp: 0,
15-
level: 0,
16-
xpCurrent: 0,
17-
xpForNext: xp_tables[table][0],
18-
progress: 0
19-
};
1+
const { cropTables, skillTables } = require("./leveling.js");
2+
3+
/**
4+
* Gets the xp table for the given type.
5+
* @param {string} [type='default'] The skill table type. Defaults to the "default" table for skills.
6+
* @returns {number[]} xp table
7+
*/
8+
function getXpTable(type = "default") {
9+
return cropTables[type] ?? skillTables[type] ?? skillTables.default;
10+
}
11+
12+
/**
13+
* Gets the level and some other information from an xp amount.
14+
* @param {number} xp The experience points to calculate level information from.
15+
* @param {Object} [extra={}] Additional options for level calculation.
16+
* @param {string} [extra.type] The ID of the skill (used to determine xp table and default cap).
17+
* @param {number} [extra.cap] Override for the highest level the player can reach.
18+
*/
19+
function getLevelByXp(xp, extra = {}) {
20+
const xpTable = getXpTable(extra.type);
21+
22+
if (typeof xp !== "number" || isNaN(xp)) {
23+
xp = 0;
2024
}
21-
let xp = 0;
22-
let level = 0;
23-
let xpForNext = 0;
24-
let progress = 0;
25-
let maxLevel = 0;
2625

27-
if (xp_tables.max_levels[skill]) maxLevel = xp_tables.max_levels[skill];
26+
/** the level that this player is caped at */
27+
const levelCap =
28+
extra.cap ?? skillTables.defaultSkillCaps[extra.type] ?? Math.max(...Object.keys(xpTable).map(Number));
29+
30+
/** the level ignoring the cap and using only the table */
31+
let uncappedLevel = 0;
2832

29-
for (let i = 1; i <= maxLevel; i++) {
30-
xp += xp_tables[table][i - 1];
33+
/** the amount of xp over the amount required for the level (used for calculation progress to next level) */
34+
let xpCurrent = xp;
3135

32-
if (xp > experience) {
33-
xp -= xp_tables[table][i - 1];
34-
} else {
35-
if (i <= maxLevel) level = i;
36+
/** like xpCurrent but ignores cap */
37+
let xpRemaining = xp;
38+
39+
while (xpTable[uncappedLevel + 1] <= xpRemaining) {
40+
uncappedLevel++;
41+
xpRemaining -= xpTable[uncappedLevel];
42+
if (uncappedLevel <= levelCap) {
43+
xpCurrent = xpRemaining;
3644
}
3745
}
3846

39-
if (skill === "dungeoneering") {
40-
level += Math.floor((experience - xp) / 200_000_000);
41-
xp += Math.floor((experience - xp) / 200_000_000) * 200_000_000;
47+
/** Whether the skill has infinite leveling (dungeoneering and skyblock level) */
48+
const isInfiniteLevelable = skillTables.infiniteLeveling.includes(extra.type);
49+
50+
/** adds support for infinite leveling (dungeoneering and skyblock level) */
51+
if (isInfiniteLevelable) {
52+
const maxExperience = Object.values(xpTable).at(-1);
4253

43-
xpForNext = 200000000;
54+
uncappedLevel += Math.floor(xpRemaining / maxExperience);
55+
xpRemaining %= maxExperience;
56+
xpCurrent = xpRemaining;
4457
}
4558

46-
const xpCurrent = Math.floor(experience - xp);
59+
/** the maximum level that any player can achieve (used for gold progress bars) */
60+
const maxLevel = isInfiniteLevelable
61+
? Math.max(uncappedLevel, levelCap)
62+
: skillTables.maxedSkillCaps[extra.type] ?? levelCap;
4763

48-
const totalXp = experience;
64+
/** the level as displayed by in game UI */
65+
const level = isInfiniteLevelable ? uncappedLevel : Math.min(levelCap, uncappedLevel);
4966

50-
if (level < maxLevel) {
51-
xpForNext = Math.ceil(xp_tables[table][level] || 200000000);
52-
}
67+
/** the amount amount of xp needed to reach the next level (used for calculation progress to next level) */
68+
const xpForNext =
69+
level < maxLevel
70+
? Math.ceil(xpTable[level + 1] ?? Object.values(xpTable).at(-1))
71+
: isInfiniteLevelable
72+
? Object.values(xpTable).at(-1)
73+
: Infinity;
5374

54-
progress = level >= maxLevel && skill !== "dungeoneering" ? 0 : Math.max(0, Math.min(xpCurrent / xpForNext, 1));
75+
/** the fraction of the way toward the next level */
76+
const progress = level >= maxLevel && !isInfiniteLevelable ? 0 : Math.max(0, Math.min(xpCurrent / xpForNext, 1));
77+
78+
/** a floating point value representing the current level for example if you are half way to level 5 it would be 4.5 */
79+
const levelWithProgress = isInfiniteLevelable
80+
? uncappedLevel + progress
81+
: Math.min(uncappedLevel + progress, levelCap);
82+
83+
/** a floating point value representing the current level ignoring the in-game unlockable caps for example if you are half way to level 5 it would be 4.5 */
84+
const unlockableLevelWithProgress = extra.cap ? Math.min(uncappedLevel + progress, maxLevel) : levelWithProgress;
85+
86+
/** the amount of xp needed to max out the skill */
87+
const maxExperience = getSkillExperience(extra.type, levelCap);
5588

5689
return {
57-
totalXp,
5890
xp,
5991
level,
92+
maxLevel,
6093
xpCurrent,
6194
xpForNext,
6295
progress,
63-
levelWithProgress: level + progress || 0
96+
levelCap,
97+
uncappedLevel,
98+
levelWithProgress,
99+
unlockableLevelWithProgress,
100+
maxExperience
64101
};
102+
}
103+
104+
/**
105+
* Calculates the average skill level for a player's profile data.
106+
*
107+
* @param {Object} profileData The player's profile data.
108+
* @param {Object} hypixelPlayer The player's Hypixel data.
109+
* @param {Object} [options] Additional options for calculating the average.
110+
* @param {number} [options.decimals=2] The number of decimal places to round the average to. Default is 1.
111+
* @param {boolean} [options.progress=false] Whether to include progress towards the next level in the calculation. Default is false.
112+
* @param {boolean} [options.cosmetic=false] Whether to include cosmetic skills in the calculation. Default is false.
113+
* @returns {string} The average skill level rounded to the specified number of decimal places.
114+
*/
115+
function getSkillAverage(profileData, hypixelPlayer, options = { decimals: 2, progress: false, cosmetic: false }) {
116+
const skillLevelCaps = getSkillLevelCaps(profileData, hypixelPlayer);
117+
118+
let totalLevel = 0;
119+
for (const skillId of skillTables.skills) {
120+
if (!options.cosmetic && skillTables.cosmeticSkills.includes(skillId)) {
121+
continue;
122+
}
123+
124+
const skill = getLevelByXp(profileData.player_data?.experience?.[`SKILL_${skillId.toUpperCase()}`], {
125+
type: skillId,
126+
cap: skillLevelCaps[skillId]
127+
});
128+
129+
totalLevel += options.progress ? skill.levelWithProgress : skill.level;
130+
}
131+
132+
const average =
133+
totalLevel /
134+
skillTables.skills.filter((skill) => !(!options.cosmetic && skillTables.cosmeticSkills.includes(skill))).length;
135+
136+
return average.toFixed(options.decimals);
137+
}
138+
139+
/**
140+
* Calculates the skill level caps for different skills based on the profile data and Hypixel player data.
141+
* @param {Object} profileData The profile data containing information about the player's skills.
142+
* @param {Object} hypixelPlayer The Hypixel player data containing information about the player's achievements.
143+
* @returns {Object} An object containing the skill level caps for farming, taming, and runecrafting.
144+
*/
145+
function getSkillLevelCaps(profileData, hypixelPlayer) {
146+
return {
147+
farming: 50 + (profileData.jacobs_contest?.perks?.farming_level_cap || 0),
148+
taming: 50 + (profileData.pets_data?.pet_care?.pet_types_sacrificed?.length || 0),
149+
runecrafting: 25 // hypixelPlayer?.newPackageRank ? 25 : 3
150+
};
151+
}
152+
153+
/**
154+
* Calculates the total experience required to reach a certain level in a skill.
155+
* @param {string} skill The ID of the skill used to determine the xp table.
156+
* @param {number} level The target level.
157+
* @returns {number} The total experience required.
158+
*/
159+
function getSkillExperience(skill, level) {
160+
const skillTable = getXpTable(skill);
161+
162+
return Object.entries(skillTable).reduce((acc, [key, value]) => (key <= level ? acc + value : acc), 0);
163+
}
164+
165+
/**
166+
* Calculates the total social skill experience for a given profile.
167+
* @param {Object} profile The profile object containing skill data.
168+
* @returns {number} The total social skill experience.
169+
*/
170+
function getSocialSkillExperience(profile) {
171+
return Object.keys(profile.members).reduce((acc, member) => {
172+
return acc + (profile.members[member]?.player_data?.experience?.SKILL_SOCIAL || 0);
173+
}, 0);
174+
}
175+
176+
module.exports = {
177+
getSkillAverage,
178+
getLevelByXp,
179+
getXpTable,
180+
getSkillLevelCaps,
181+
getSkillExperience,
182+
getSocialSkillExperience
65183
};

API/stats/hotm.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ module.exports = (profile) => {
3232
forgeItem.timeStarted = item.startTime;
3333
forgeItem.timeFinished = timeFinished;
3434
forgeItem.timeFinishedText =
35-
timeFinished < Date.now() ? "Finished" : `ending ${moment(timeFinished).fromNow()}`;
35+
timeFinished < Date.now() ? "(FINISHED)" : ` (${moment(timeFinished).fromNow()})`;
3636
} else {
3737
console.error(item);
3838
forgeItem.name = "Unknown Item";
@@ -62,7 +62,7 @@ module.exports = (profile) => {
6262
}
6363
},
6464
level: calcSkill("hotm", profile?.mining_core?.experience || 0),
65-
ability: titleCase(profile?.mining_core?.selected_pickaxe_ability || "none", true),
65+
ability: miningConst.hotm.perks[profile?.mining_core?.selected_pickaxe_ability]?.name || "None",
6666
forge: forgeItems
6767
};
6868
} catch (error) {

API/stats/skills.js

Lines changed: 17 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,20 @@
1-
const calcSkill = require("../constants/skills.js");
1+
const { getSkillLevelCaps, getSocialSkillExperience, getLevelByXp } = require("../constants/skills.js");
22

3-
module.exports = function getSkills(profile) {
4-
const skill_experience = {
5-
farming: profile?.player_data?.experience?.SKILL_FARMING || 0,
6-
mining: profile?.player_data?.experience?.SKILL_MINING || 0,
7-
combat: profile?.player_data?.experience?.SKILL_COMBAT || 0,
8-
foraging: profile?.player_data?.experience?.SKILL_FORAGING || 0,
9-
fishing: profile?.player_data?.experience?.SKILL_FISHING || 0,
10-
enchanting: profile?.player_data?.experience?.SKILL_ENCHANTING || 0,
11-
alchemy: profile?.player_data?.experience?.SKILL_ALCHEMY || 0,
12-
carpentry: profile?.player_data?.experience?.SKILL_CARPENTRY || 0,
13-
runecrafting: profile?.player_data?.experience?.SKILL_RUNECRAFTING || 0,
14-
social: profile?.player_data?.experience?.SKILL_SOCIAL || 0,
15-
taming: profile?.player_data?.experience?.SKILL_TAMING || 0
16-
};
3+
module.exports = function getSkills(profile, profileData) {
4+
const skillLevelCaps = getSkillLevelCaps(profile);
5+
const totalSocialXp = getSocialSkillExperience(profileData);
176

18-
return {
19-
farming: calcSkill("farming", skill_experience["farming"]),
20-
mining: calcSkill("mining", skill_experience["mining"]),
21-
combat: calcSkill("combat", skill_experience["combat"]),
22-
foraging: calcSkill("foraging", skill_experience["foraging"]),
23-
fishing: calcSkill("fishing", skill_experience["fishing"]),
24-
enchanting: calcSkill("enchanting", skill_experience["enchanting"]),
25-
alchemy: calcSkill("alchemy", skill_experience["alchemy"]),
26-
carpentry: calcSkill("carpentry", skill_experience["carpentry"]),
27-
runecrafting: calcSkill("runecrafting", skill_experience["runecrafting"]),
28-
social: calcSkill("social", skill_experience["social"]),
29-
taming: calcSkill("taming", skill_experience["taming"])
30-
};
7+
const skills = {};
8+
for (const skill in profile.player_data?.experience || {}) {
9+
if (skill === "SKILL_DUNGEONEERING") {
10+
continue;
11+
}
12+
13+
const xp = skill === "SKILL_SOCIAL" ? totalSocialXp : profile.player_data?.experience[skill];
14+
const type = skill.split("_").at(1).toLowerCase();
15+
16+
skills[type] = getLevelByXp(xp, { type: type, cap: skillLevelCaps[type] });
17+
}
18+
19+
return skills;
3120
};

API/stats/weight.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ const getSlayer = require("../stats/slayer.js");
66

77
module.exports = (profile) => {
88
const { skills_levels, skills_experience } = formatLilySkills(getSkills(profile));
9-
const { catacombs_experience, catacombs, master_mode } = formatLilyDungeons(getDungeons(profile));
9+
const { catacombs_experience, catacombs, master_mode } = formatLilyDungeons(getDungeons(profile) ?? {});
1010
const { slayer_experience } = formatLilySlayer(getSlayer(profile));
1111

1212
const lily = getWeightRaw(

config.example.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@
107107
"unverifiedRole": "UNVERIFIED_ROLE_ID",
108108
"removeVerificationRole": true,
109109
"guildMemberRole": "GUILD_MEMBER_ROLE_ID",
110-
"autoUpdater": true,
110+
"autoUpdater": false,
111111
"autoUpdaterInterval": 24,
112112
"name": "{username}",
113113
"levelRoles": [

src/contracts/helperFunctions.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,15 @@ function getTimestamp(unixTimestamp = Date.now()) {
279279
});
280280
}
281281

282+
function splitMessage(message, amount) {
283+
const messages = [];
284+
for (let i = 0; i < message.length; i += amount) {
285+
messages.push(message.slice(i, i + amount));
286+
}
287+
288+
return messages;
289+
}
290+
282291
module.exports = {
283292
replaceAllRanks,
284293
addNotation,
@@ -295,5 +304,6 @@ module.exports = {
295304
formatUsername,
296305
formatNumber,
297306
replaceVariables,
298-
getTimestamp
307+
getTimestamp,
308+
splitMessage
299309
};

0 commit comments

Comments
 (0)