Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: Skill Overflow #2808

Merged
merged 4 commits into from
Nov 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 56 additions & 58 deletions src/main/java/at/hannibal2/skyhanni/api/SkillAPI.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ import at.hannibal2.skyhanni.events.SkillOverflowLevelUpEvent
import at.hannibal2.skyhanni.features.skillprogress.SkillProgress
import at.hannibal2.skyhanni.features.skillprogress.SkillType
import at.hannibal2.skyhanni.features.skillprogress.SkillUtil.SPACE_SPLITTER
import at.hannibal2.skyhanni.features.skillprogress.SkillUtil.XP_NEEDED_FOR_50
import at.hannibal2.skyhanni.features.skillprogress.SkillUtil.XP_NEEDED_FOR_60
import at.hannibal2.skyhanni.features.skillprogress.SkillUtil.calculateLevelXp
import at.hannibal2.skyhanni.features.skillprogress.SkillUtil.calculateOverFlow
import at.hannibal2.skyhanni.features.skillprogress.SkillUtil.getLevel
import at.hannibal2.skyhanni.features.skillprogress.SkillUtil.calculateSkillLevel
import at.hannibal2.skyhanni.features.skillprogress.SkillUtil.getLevelExact
import at.hannibal2.skyhanni.features.skillprogress.SkillUtil.getSkillInfo
import at.hannibal2.skyhanni.features.skillprogress.SkillUtil.xpRequiredForLevel
Expand Down Expand Up @@ -43,29 +43,30 @@ import kotlin.time.Duration.Companion.seconds
@SkyHanniModule
object SkillAPI {
private val patternGroup = RepoPattern.group("api.skilldisplay")
// TODO add regex tests
private val skillPercentPattern by patternGroup.pattern(
"skill.percent",
"\\+(?<gained>[\\d.,]+) (?<skillName>.+) \\((?<progress>[\\d.]+)%\\)"
"\\+(?<gained>[\\d.,]+) (?<skillName>.+) \\((?<progress>[\\d.]+)%\\)",
)
private val skillPattern by patternGroup.pattern(
"skill",
"\\+(?<gained>[\\d.,]+) (?<skillName>\\w+) \\((?<current>[\\d.,]+)/(?<needed>[\\d.,]+)\\)"
"\\+(?<gained>[\\d.,]+) (?<skillName>\\w+) \\((?<current>[\\d.,]+)/(?<needed>[\\d.,]+)\\)",
)
private val skillMultiplierPattern by patternGroup.pattern(
"skill.multiplier",
"\\+(?<gained>[\\d.,]+) (?<skillName>.+) \\((?<current>[\\d.,]+)/(?<needed>[\\d,.]+[kmb])\\)"
"\\+(?<gained>[\\d.,]+) (?<skillName>.+) \\((?<current>[\\d.,]+)/(?<needed>[\\d,.]+[kmb])\\)",
)
private val skillTabPattern by patternGroup.pattern(
"skill.tab",
" (?<type>\\w+)(?: (?<level>\\d+))?: §r§a(?<progress>[0-9.]+)%"
" (?<type>\\w+)(?: (?<level>\\d+))?: §r§a(?<progress>[0-9.]+)%",
)
private val maxSkillTabPattern by patternGroup.pattern(
"skill.tab.max",
" (?<type>\\w+) (?<level>\\d+): §r§c§lMAX"
" (?<type>\\w+) (?<level>\\d+): §r§c§lMAX",
)
private val skillTabNoPercentPattern by patternGroup.pattern(
"skill.tab.nopercent",
" §r§a(?<type>\\w+)(?: (?<level>\\d+))?: §r§e(?<current>[0-9,.]+)§r§6/§r§e(?<needed>[0-9kmb]+)"
" §r§a(?<type>\\w+)(?: (?<level>\\d+))?: §r§e(?<current>[0-9,.]+)§r§6/§r§e(?<needed>[0-9kmb]+)",
)

var skillXPInfoMap = mutableMapOf<SkillType, SkillXPInfo>()
Expand All @@ -75,14 +76,8 @@ object SkillAPI {
var levelingMap = mapOf<Int, Int>()
var levelArray = listOf<Int>()
var activeSkill: SkillType? = null
var defaultSkillCap = mapOf<String, Int>()

// TODO Use a map maxSkillLevel and move it into the repo
val excludedSkills = listOf(
SkillType.FORAGING,
SkillType.FISHING,
SkillType.ALCHEMY,
SkillType.CARPENTRY
)
var showDisplay = false
var lastUpdate = SimpleTimeMark.farPast()

Expand Down Expand Up @@ -144,9 +139,12 @@ object SkillAPI {

@SubscribeEvent
fun onNEURepoReload(event: NeuRepositoryReloadEvent) {
levelArray = event.readConstant<NeuSkillLevelJson>("leveling").levelingXp
levelingMap = levelArray.withIndex().associate { (index, xp) -> index to xp }
exactLevelingMap = levelArray.withIndex().associate { (index, xp) -> xp to index }
val data = event.readConstant<NeuSkillLevelJson>("leveling")

levelArray = data.levelingXp
levelingMap = levelArray.withIndex().associate { (index, xp) -> (index + 1) to xp }
exactLevelingMap = levelArray.withIndex().associate { (index, xp) -> xp to (index + 1) }
defaultSkillCap = data.levelingCaps
}

@SubscribeEvent
Expand All @@ -170,15 +168,12 @@ object SkillAPI {
val previousLine = stack.getLore()[lineIndex - 1]
val progress = cleanLine.substring(cleanLine.lastIndexOf(' ') + 1)
if (previousLine == "§7§8Max Skill level reached!") {
var totalXp = progress.formatLong()
val minus = if (skillLevel == 50) 4_000_000 else if (skillLevel == 60) 7_000_000 else 0
totalXp -= minus
val (overflowLevel, overflowCurrent, overflowNeeded, overflowTotal) = getSkillInfo(
skillLevel,
val totalXp = progress.formatLong()
val (overflowLevel, overflowCurrent, overflowNeeded, overflowTotal) = calculateSkillLevel(
totalXp,
0L,
totalXp
defaultSkillCap[skill.lowercaseName] ?: 60,
)

skillInfo?.apply {
this.overflowLevel = overflowLevel
this.overflowCurrentXp = overflowCurrent
Expand Down Expand Up @@ -259,12 +254,16 @@ object SkillAPI {
val maxXp = matcher.group("needed").formatLong()
val level = getLevelExact(maxXp)

val (levelOverflow, currentOverflow, currentMaxOverflow, totalOverflow) = getSkillInfo(
level,
currentXp,
maxXp,
currentXp
)
val cap = defaultSkillCap[skillType.lowercaseName] ?: 60
val add = when (cap) {
50 -> XP_NEEDED_FOR_50
60 -> XP_NEEDED_FOR_60
else -> 0
}

val (levelOverflow, currentOverflow, currentMaxOverflow, totalOverflow) =
calculateSkillLevel(currentXp + add, cap)

if (skillInfo.overflowLevel > 60 && levelOverflow == skillInfo.overflowLevel + 1)
SkillOverflowLevelUpEvent(skillType, skillInfo.overflowLevel, levelOverflow).postAndCatch()

Expand Down Expand Up @@ -342,7 +341,19 @@ object SkillAPI {
}

private fun updateSkillInfo(existingLevel: SkillInfo, level: Int, currentXp: Long, maxXp: Long, totalXp: Long, gained: String) {
val (levelOverflow, currentOverflow, currentMaxOverflow, totalOverflow) = getSkillInfo(level, currentXp, maxXp, totalXp)
val cap = defaultSkillCap[activeSkill?.lowercaseName] ?: 60
val add = if (level >= 50) {
when (cap) {
50 -> XP_NEEDED_FOR_50
60 -> XP_NEEDED_FOR_60
else -> 0
}
} else {
0
}

val (levelOverflow, currentOverflow, currentMaxOverflow, totalOverflow) =
calculateSkillLevel(totalXp + add, defaultSkillCap[activeSkill?.lowercaseName] ?: 60)

existingLevel.apply {
this.totalXp = totalXp
Expand All @@ -364,12 +375,9 @@ object SkillAPI {
val maxXp = matcher.group("needed").formatLong()
val level = getLevelExact(maxXp)
val levelXp = calculateLevelXp(level - 1).toLong() + currentXp
val (currentLevel, currentOverflow, currentMaxOverflow, totalOverflow) = getSkillInfo(
level,
currentXp,
maxXp,
levelXp
)
val (currentLevel, currentOverflow, currentMaxOverflow, totalOverflow) =
calculateSkillLevel(currentXp, defaultSkillCap[skillType.lowercaseName] ?: 60)

skillInfo.apply {
this.overflowCurrentXp = currentOverflow
this.overflowCurrentXpMax = currentMaxOverflow
Expand Down Expand Up @@ -414,16 +422,11 @@ object SkillAPI {
when (first) {
"levelwithxp" -> {
val xp = second.formatLongOrUserError() ?: return
if (xp <= XP_NEEDED_FOR_60) {
val level = getLevel(xp)
ChatUtils.chat("With §b${xp.addSeparators()} §eXP you would be level §b$level")
} else {
val (overflowLevel, current, needed, _) = calculateOverFlow((xp) - XP_NEEDED_FOR_60)
ChatUtils.chat(
"With §b${xp.addSeparators()} §eXP you would be level §b$overflowLevel " +
"§ewith progress (§b${current.addSeparators()}§e/§b${needed.addSeparators()}§e) XP"
)
}
val (overflowLevel, current, needed, _) = calculateSkillLevel(xp, 60)
ChatUtils.chat(
"With §b${xp.addSeparators()} §eXP you would be level §b$overflowLevel " +
"§ewith progress (§b${current.addSeparators()}§e/§b${needed.addSeparators()}§e) XP",
)
return
}

Expand All @@ -433,13 +436,8 @@ object SkillAPI {
ChatUtils.userError("Not a valid number: '$second'")
return
}
if (level <= 60) {
val neededXp = levelingMap.filter { it.key < level }.values.sum().toLong()
ChatUtils.chat("You need §b${neededXp.addSeparators()} §eXP to be level §b${level.toDouble()}")
} else {
val neededXP = xpRequiredForLevel(level.toDouble())
ChatUtils.chat("You need §b${neededXP.addSeparators()} §eXP to be level §b${level.toDouble()}")
}
val neededXP = xpRequiredForLevel(level)
ChatUtils.chat("You need §b${neededXP.addSeparators()} §eXP to reach level §b${level.toDouble()}")
return
}

Expand Down Expand Up @@ -475,7 +473,7 @@ object SkillAPI {

if (targetLevel <= skill.overflowLevel) {
ChatUtils.userError(
"Custom goal level ($targetLevel) must be greater than your current level (${skill.overflowLevel})."
"Custom goal level ($targetLevel) must be greater than your current level (${skill.overflowLevel}).",
)
return
}
Expand All @@ -494,7 +492,7 @@ object SkillAPI {
1 -> listOf("levelwithxp", "xpforlevel", "goal")
2 -> if (strings[0].lowercase() == "goal") CommandBase.getListOfStringsMatchingLastWord(
strings,
SkillType.entries.map { it.displayName }
SkillType.entries.map { it.displayName },
)
else
listOf()
Expand All @@ -512,7 +510,7 @@ object SkillAPI {
"§6/shskills goal <skill> <level> - §bDefine your goal for <skill>",
"",
).joinToString("\n"),
prefix = false
prefix = false,
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ import com.google.gson.annotations.SerializedName

data class NeuSkillLevelJson(
@Expose @SerializedName("leveling_xp") val levelingXp: List<Int>,
@Expose @SerializedName("leveling_caps") val levelingCaps: Map<String, Int>,
)
Loading
Loading