aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/io/github/moulberry/notenoughupdates/util/PetLeveling.kt
blob: 9f809798b652fe7e62aeaf2f0472dfac0ab9bf97 (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
/*
 * Copyright (C) 2022 Linnea Gräf
 *
 * This file is part of NotEnoughUpdates.
 *
 * NotEnoughUpdates is free software: you can redistribute it
 * and/or modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation, either
 * version 3 of the License, or (at your option) any later version.
 *
 * NotEnoughUpdates is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
 */

package io.github.moulberry.notenoughupdates.util

import com.google.gson.JsonObject
import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe
import io.github.moulberry.notenoughupdates.events.RepositoryReloadEvent
import io.github.moulberry.notenoughupdates.miscfeatures.PetInfoOverlay.Rarity
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent

@NEUAutoSubscribe
object PetLeveling {

    data class ExpLadder(
        val individualLevelCost: List<Long>,
    ) {
        val cumulativeLevelCost = individualLevelCost.runningFold(0F) { a, b -> a + b }.map { it.toLong() }
        fun getPetLevel(currentExp: Double): PetLevel {
            val currentOneIndexedLevel = cumulativeLevelCost.indexOfLast { it <= currentExp } + 1
            val expForNextLevel = if (currentOneIndexedLevel > individualLevelCost.size) { // Max leveled pet
                individualLevelCost.last()
            } else {
                individualLevelCost[currentOneIndexedLevel - 1]
            }
            val expInCurrentLevel =
                if (currentOneIndexedLevel >= cumulativeLevelCost.size)
                    currentExp.toFloat() - cumulativeLevelCost.last()
                else
                    (expForNextLevel - (cumulativeLevelCost[currentOneIndexedLevel] - currentExp.toFloat())).coerceAtLeast(0F)
            return PetLevel(
                currentLevel = currentOneIndexedLevel,
                maxLevel = cumulativeLevelCost.size,
                expRequiredForNextLevel = expForNextLevel,
                expRequiredForMaxLevel = cumulativeLevelCost.last(),
                expInCurrentLevel = expInCurrentLevel,
                expTotal = currentExp.toFloat()
            )
        }

        fun getPetExpForLevel(level: Int): Long {
            if (level < 2) return 0L
            if (level >= cumulativeLevelCost.size) return cumulativeLevelCost.last()
            return cumulativeLevelCost[level - 1]
        }
    }

    data class PetLevel(
        val currentLevel: Int,
        val maxLevel: Int,
        val expRequiredForNextLevel: Long,
        val expRequiredForMaxLevel: Long,
        val expInCurrentLevel: Float,
        var expTotal: Float,
    ) {
        val percentageToNextLevel: Float = expInCurrentLevel / expRequiredForNextLevel
    }

    private data class Key(val petIdWithoutRarity: String, val rarity: Rarity)

    private val cache = mutableMapOf<Key, ExpLadder>()

    @SubscribeEvent
    fun onRepoReload(event: RepositoryReloadEvent) {
        cache.clear()
    }

    var petConstants: JsonObject? = null

    @JvmStatic
    fun getPetLevelingForPet(petIdWithoutRarity: String, rarity: Rarity): ExpLadder {
        return cache.computeIfAbsent(Key(petIdWithoutRarity, rarity)) {
            getPetLevelingForPet0(
                petIdWithoutRarity,
                rarity
            )
        }
    }

    val stubExpLadder by lazy {
        Utils.showOutdatedRepoNotification("pets.json")
        ExpLadder(listOf(1, 1))
    }

    internal fun getPetLevelingForPet0(petIdWithoutRarity: String, rarity: Rarity): ExpLadder {
        val petConstants = this.petConstants ?: Constants.PETS ?: return stubExpLadder
        var levels = petConstants["pet_levels"]?.asJsonArray?.map { it.asLong }?.toMutableList() ?: return stubExpLadder
        val customLeveling = petConstants["custom_pet_leveling"]?.asJsonObject?.get(petIdWithoutRarity)
        var rarityOffsets = petConstants["pet_rarity_offset"]?.asJsonObject
        var maxLevel = 100
        if (customLeveling is JsonObject) {
            val customLevels by lazy { customLeveling["pet_levels"]?.asJsonArray?.map { it.asLong } }
            when (customLeveling["type"]?.asInt ?: 0) {
                1 -> levels.addAll(customLevels ?: return stubExpLadder)
                2 -> levels = customLevels?.toMutableList() ?: return stubExpLadder
            }
            maxLevel = customLeveling["max_level"]?.asInt ?: maxLevel
            rarityOffsets = customLeveling["rarity_offset"]?.asJsonObject ?: rarityOffsets
        }
        val offset = rarityOffsets?.get(rarity.name)?.asInt ?: return stubExpLadder

        return ExpLadder(levels.drop(offset).take(maxLevel - 1))
    }

}