aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/at/hannibal2/skyhanni/features/skillprogress/SkillUtil.kt
blob: b4af74d13989fae11518a4a66e0bceea5b35a1de (plain)
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package at.hannibal2.skyhanni.features.skillprogress

import at.hannibal2.skyhanni.api.SkillAPI
import at.hannibal2.skyhanni.api.SkillAPI.activeSkill
import at.hannibal2.skyhanni.api.SkillAPI.exactLevelingMap
import at.hannibal2.skyhanni.api.SkillAPI.excludedSkills
import at.hannibal2.skyhanni.api.SkillAPI.levelingMap
import at.hannibal2.skyhanni.utils.Quad
import com.google.common.base.Splitter

object SkillUtil {

    val SPACE_SPLITTER = Splitter.on("  ").omitEmptyStrings().trimResults()
    const val XP_NEEDED_FOR_60 = 111_672_425L

    fun getSkillInfo(skill: SkillType): SkillAPI.SkillInfo? {
        return SkillAPI.storage?.get(skill)
    }

    fun getSkillInfo(currentLevel: Int, currentXp: Long, neededXp: Long, totalXp: Long): Quad<Int, Long, Long, Long> {
        return if (currentLevel == 50 && neededXp == 0L)
            calculateOverFlow50(currentXp)
        else if (currentLevel >= 60)
            calculateOverFlow(currentXp)
        else
            Quad(currentLevel, currentXp, neededXp, totalXp)
    }

    /**
     * @author Soopyboo32
     */
    fun calculateOverFlow(currentXp: Long): Quad<Int, Long, Long, Long> {
        var xpCurrent = currentXp
        var slope = 600000L
        var xpForCurr = 7000000 + slope
        var level = 60
        var total = 0L
        while (xpCurrent > xpForCurr) {
            level++
            xpCurrent -= xpForCurr
            total += xpForCurr
            xpForCurr += slope
            if (level % 10 == 0) slope *= 2
        }
        total += xpCurrent
        return Quad(level, xpCurrent, xpForCurr, total)
    }

    /**
     * Calculate overflow starting at level 50
     */
    private fun calculateOverFlow50(currentXp: Long): Quad<Int, Long, Long, Long> {
        var xpCurrent = currentXp
        var level = 50
        var total = 0L
        var slope = 300000L
        var xpForCurr = 4000000 + slope

        while (level < 60 && xpCurrent > xpForCurr) {
            level++
            xpCurrent -= xpForCurr
            total += xpForCurr
            xpForCurr += slope
            if (level % 10 == 0) slope *= 2
        }

        if (level >= 60) {
            slope = 600000L
            xpForCurr = 7000000 + slope
        }

        while (xpCurrent > xpForCurr) {
            level++
            xpCurrent -= xpForCurr
            total += xpForCurr
            xpForCurr += slope
            if (level % 10 == 0) slope *= 2
        }
        total += xpCurrent

        return Quad(level, xpCurrent, xpForCurr, total)
    }

    fun xpRequiredForLevel(levelWithProgress: Double): Long {
        val level = levelWithProgress.toInt()
        var slope = 600000L
        var xpForCurr = 7000000 + slope
        var totalXpRequired = 0L

        for (i in 61..level) {
            totalXpRequired += xpForCurr
            xpForCurr += slope
            if (i % 10 == 0) slope *= 2
        }

        val fractionalProgress = levelWithProgress - level
        totalXpRequired += (xpForCurr * fractionalProgress).toLong()

        val xp = if (level <= 60) {
            levelingMap.filter { it.key < level }.values.sum().toLong()
        } else {
            totalXpRequired + levelingMap.values.sum()
        }

        return xp
    }

    fun getLevelExact(neededXp: Long): Int {
        val defaultLevel = if (activeSkill in excludedSkills) 50 else 60
        return exactLevelingMap.getOrDefault(neededXp.toInt(), defaultLevel)
    }

    fun getLevel(currentXp: Long): Int {
        var level = 0
        var remainingXp = currentXp
        for ((i, v) in levelingMap) {
            if (remainingXp >= v) {
                remainingXp -= v
                level++
            }
        }
        return level
    }

    fun calculateLevelXp(level: Int): Double {
        return SkillAPI.levelArray.asSequence().take(level + 1).sumOf { it.toDouble() }
    }

}