diff options
7 files changed, 378 insertions, 26 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/misc/EstimatedItemValueConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/misc/EstimatedItemValueConfig.java index 096370308..3f5874ac0 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/misc/EstimatedItemValueConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/misc/EstimatedItemValueConfig.java @@ -40,6 +40,15 @@ public class EstimatedItemValueConfig { public Property<Integer> enchantmentsCap = Property.of(7); @Expose + @ConfigOption(name = "Star Material Cap", desc = "Only show the top # most expensive parts of star prices.") + @ConfigEditorSlider( + minValue = 1, + maxValue = 15, + minStep = 1 + ) + public Property<Integer> starMaterialCap = Property.of(3); + + @Expose @ConfigOption(name = "Show Exact Price", desc = "Show the exact total price instead of the compact number.") @ConfigEditorBoolean public Property<Boolean> exactPrice = Property.of(false); diff --git a/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/neu/NeuEssenceCostJson.kt b/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/neu/NeuEssenceCostJson.kt new file mode 100644 index 000000000..12aa600ee --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/neu/NeuEssenceCostJson.kt @@ -0,0 +1,40 @@ +package at.hannibal2.skyhanni.data.jsonobjects.repo.neu + +import com.google.gson.annotations.Expose +import com.google.gson.annotations.SerializedName +import com.google.gson.reflect.TypeToken +import java.lang.reflect.Type + +data class NeuEssenceCostJson( + @Expose @SerializedName("type") val essenceType: String, + @Expose @SerializedName("dungeonize") val essenceForDungeonize: Int?, + @Expose @SerializedName("1") val essenceFor1: Int?, + @Expose @SerializedName("2") val essenceFor2: Int?, + @Expose @SerializedName("3") val essenceFor3: Int?, + @Expose @SerializedName("4") val essenceFor4: Int?, + @Expose @SerializedName("5") val essenceFor5: Int?, + @Expose @SerializedName("6") val essenceFor6: Int?, + @Expose @SerializedName("7") val essenceFor7: Int?, + @Expose @SerializedName("8") val essenceFor8: Int?, + @Expose @SerializedName("9") val essenceFor9: Int?, + @Expose @SerializedName("10") val essenceFor10: Int?, + @Expose @SerializedName("11") val essenceFor11: Int?, + @Expose @SerializedName("12") val essenceFor12: Int?, + @Expose @SerializedName("13") val essenceFor13: Int?, + @Expose @SerializedName("14") val essenceFor14: Int?, + @Expose @SerializedName("15") val essenceFor15: Int?, + @Expose @SerializedName("items") val extraItems: Map<String, List<String>>?, + + @Expose @SerializedName("catacombs_requirements") val catacombsRequirements: List<NeuCatacombsRequirements>, +) { + + companion object { + val TYPE: Type = object : TypeToken<Map<String?, NeuEssenceCostJson>>() {}.type + } +} + +data class NeuCatacombsRequirements( + @Expose @SerializedName("type") val type: String, + @Expose @SerializedName("dungeon_type") val dungeonType: String?, + @Expose @SerializedName("level") val level: Int, +) diff --git a/src/main/java/at/hannibal2/skyhanni/events/NeuRepositoryReloadEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/NeuRepositoryReloadEvent.kt index 6f7df5964..c2bd261ca 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/NeuRepositoryReloadEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/NeuRepositoryReloadEvent.kt @@ -1,6 +1,9 @@ + package at.hannibal2.skyhanni.events import at.hannibal2.skyhanni.config.ConfigManager +import at.hannibal2.skyhanni.data.repo.RepoError +import at.hannibal2.skyhanni.data.repo.RepoUtils import at.hannibal2.skyhanni.test.command.ErrorManager import at.hannibal2.skyhanni.utils.NEUItems.manager import at.hannibal2.skyhanni.utils.json.fromJson @@ -8,6 +11,7 @@ import com.google.gson.Gson import com.google.gson.JsonObject import com.google.gson.JsonSyntaxException import java.io.File +import java.lang.reflect.Type class NeuRepositoryReloadEvent : LorenzEvent() { fun getConstant(file: String): JsonObject? { @@ -26,4 +30,11 @@ class NeuRepositoryReloadEvent : LorenzEvent() { throw e } } + + inline fun <reified T : Any> getConstant(constant: String, type: Type? = null, gson: Gson = ConfigManager.gson): T = try { + if (!manager.repoLocation.exists()) throw RepoError("NEU-Repo folder does not exist!") + RepoUtils.getConstant(manager.repoLocation, constant, gson, T::class.java, type) + } catch (e: Exception) { + throw RepoError("Repo parsing error while trying to read constant '$constant'", e) + } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/items/EstimatedItemValue.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/items/EstimatedItemValue.kt index a587443e5..046325749 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/misc/items/EstimatedItemValue.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/items/EstimatedItemValue.kt @@ -21,6 +21,7 @@ import at.hannibal2.skyhanni.utils.ItemUtils.getLore import at.hannibal2.skyhanni.utils.ItemUtils.isRune import at.hannibal2.skyhanni.utils.ItemUtils.itemName import at.hannibal2.skyhanni.utils.ItemUtils.name +import at.hannibal2.skyhanni.utils.KeyboardManager.isKeyClicked import at.hannibal2.skyhanni.utils.KeyboardManager.isKeyHeld import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.NEUInternalName @@ -32,6 +33,7 @@ import net.minecraft.client.Minecraft import net.minecraft.init.Items import net.minecraft.item.ItemStack import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import org.lwjgl.input.Keyboard import kotlin.math.roundToLong @SkyHanniModule @@ -88,6 +90,15 @@ object EstimatedItemValue { currentlyShowing = checkCurrentlyVisible() if (!currentlyShowing) return + // TODO add "is debug enabled" check once users notice this easteregg + if (Keyboard.KEY_RIGHT.isKeyClicked()) { + EstimatedItemValueCalculator.starChange += 1 + cache.clear() + } else if (Keyboard.KEY_LEFT.isKeyClicked()) { + EstimatedItemValueCalculator.starChange -= 1 + cache.clear() + } + config.itemPriceDataPos.renderStringsAndItems(display, posLabel = "Estimated Item Value") } diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/items/EstimatedItemValueCalculator.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/items/EstimatedItemValueCalculator.kt index ffa92489c..6842ccc77 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/misc/items/EstimatedItemValueCalculator.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/items/EstimatedItemValueCalculator.kt @@ -3,9 +3,14 @@ package at.hannibal2.skyhanni.features.misc.items import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.api.ReforgeAPI import at.hannibal2.skyhanni.test.command.ErrorManager +import at.hannibal2.skyhanni.utils.CollectionUtils.addOrPut +import at.hannibal2.skyhanni.utils.CollectionUtils.sorted import at.hannibal2.skyhanni.utils.CollectionUtils.sortedDesc +import at.hannibal2.skyhanni.utils.EssenceItemUtils +import at.hannibal2.skyhanni.utils.EssenceItemUtils.getEssencePrices import at.hannibal2.skyhanni.utils.ItemUtils.getAttributeFromShard import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName +import at.hannibal2.skyhanni.utils.ItemUtils.getInternalNameOrNull import at.hannibal2.skyhanni.utils.ItemUtils.getItemRarityOrNull import at.hannibal2.skyhanni.utils.ItemUtils.getLore import at.hannibal2.skyhanni.utils.ItemUtils.isRune @@ -20,6 +25,7 @@ import at.hannibal2.skyhanni.utils.NEUItems.getItemStackOrNull import at.hannibal2.skyhanni.utils.NEUItems.getNpcPriceOrNull import at.hannibal2.skyhanni.utils.NEUItems.getPriceOrNull import at.hannibal2.skyhanni.utils.NEUItems.getRawCraftCostOrNull +import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators import at.hannibal2.skyhanni.utils.NumberUtil.shortFormat import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getAbilityScrolls @@ -41,6 +47,7 @@ import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getPowerScroll import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getReforgeName import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getRune import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getSilexCount +import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getStarCount import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getTransmissionTunerCount import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.hasArtOfPeace import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.hasArtOfWar @@ -62,6 +69,8 @@ object EstimatedItemValueCalculator { private val kuudraSets = listOf("AURORA", "CRIMSON", "TERROR", "HOLLOW", "FERVOR") + var starChange = 0 + private val additionalCostFunctions = listOf( ::addAttributeCost, ::addReforgeStone, @@ -79,6 +88,7 @@ object EstimatedItemValueCalculator { ::addDivanPowderCoating, // counted + ::addStars, // crimson, dungeon ::addMasterStars, ::addHotPotatoBooks, ::addFarmingForDummies, @@ -110,6 +120,8 @@ object EstimatedItemValueCalculator { val transmissionTuner = "TRANSMISSION_TUNER".asInternalName() val manaDisintegrator = "MANA_DISINTEGRATOR".asInternalName() + val kuudraUpgradeTiers = listOf("HOT_", "BURNING_", "FIERY_", "INFERNAL_") + fun getTotalPrice(stack: ItemStack): Double = EstimatedItemValueCalculator.calculate(stack, mutableListOf()).first fun calculate(stack: ItemStack, list: MutableList<String>): Pair<Double, Double> { @@ -118,9 +130,12 @@ object EstimatedItemValueCalculator { return Pair(totalPrice, basePrice) } - private fun isKuudraSet(internalName: String) = - (kuudraSets.any { internalName.contains(it) } && - listOf("CHESTPLATE", "LEGGINGS", "HELMET", "BOOTS").any { internalName.endsWith(it) }) + private fun isKuudraSet(internalName: String) = (kuudraSets.any { internalName.contains(it) } && listOf( + "CHESTPLATE", + "LEGGINGS", + "HELMET", + "BOOTS", + ).any { internalName.endsWith(it) }) private fun addAttributeCost(stack: ItemStack, list: MutableList<String>): Double { val attributes = stack.getAttributes() ?: return 0.0 @@ -150,8 +165,7 @@ object EstimatedItemValueCalculator { } for (attr in attributes) { val attributeName = "$genericName+ATTRIBUTE_${attr.first}" - val price = - getPriceOrCompositePriceForAttribute(attributeName, attr.second) + val price = getPriceOrCompositePriceForAttribute(attributeName, attr.second) var priceColor = "§7" val useless = isUselessAttribute(attributeName) var nameColor = if (!useless) "§9" else "§7" @@ -177,21 +191,21 @@ object EstimatedItemValueCalculator { if (!isKuudraSet(original)) return original var internalName = original - for (prefix in listOf("HOT_", "BURNING_", "FIERY_", "INFERNAL_")) { + for (prefix in kuudraUpgradeTiers) { internalName = internalName.removePrefix(prefix) } return internalName } - private fun addAttributePrice(attributePrice: Double, basePrice: Double): Double = - if (attributePrice > basePrice) { - attributePrice - basePrice - } else { - 0.0 - } + private fun addAttributePrice(attributePrice: Double, basePrice: Double): Double = if (attributePrice > basePrice) { + attributePrice - basePrice + } else { + 0.0 + } private fun isUselessAttribute(internalName: String): Boolean { if (internalName.contains("RESISTANCE")) return true + if (internalName.contains("FISHING_SPEED")) return false if (internalName.contains("SPEED")) return true if (internalName.contains("EXPERIENCE")) return true if (internalName.contains("FORTITUDE")) return true @@ -205,8 +219,7 @@ object EstimatedItemValueCalculator { private fun getPriceOrCompositePriceForAttribute(attributeName: String, level: Int): Double? { val intRange = if (config.useAttributeComposite.get()) 1..10 else level..level return intRange.mapNotNull { lowerLevel -> - "$attributeName;$lowerLevel".asInternalName().getPriceOrNull() - ?.let { it / (1 shl lowerLevel) * (1 shl level).toDouble() } + "$attributeName;$lowerLevel".asInternalName().getPriceOrNull()?.let { it / (1 shl lowerLevel) * (1 shl level).toDouble() } }.minOrNull() } @@ -414,10 +427,143 @@ object EstimatedItemValueCalculator { return price } + private fun addStars(stack: ItemStack, list: MutableList<String>): Double { + val internalName = stack.getInternalNameOrNull() ?: return 0.0 + var totalStars = stack.getDungeonStarCount() ?: stack.getStarCount() ?: 0 + + starChange.takeIf { it != 0 }?.let { + list.add("change: $it") + totalStars += it + } + + val (price, stars) = calculateStarPrice(internalName, totalStars) ?: return 0.0 + val (havingStars, maxStars) = stars + + var totalPrice = 0.0 + val map = mutableMapOf<String, Double>() + price.essencePrice.let { + val essenceName = "ESSENCE_${it.essenceType}".asInternalName() + val amount = it.essenceAmount + val essencePrice = essenceName.getPrice() * amount + map[" §8${amount.addSeparators()}x ${essenceName.itemName} §7(§6${essencePrice.shortFormat()}§7)"] = essencePrice + totalPrice += essencePrice + } + + price.coinPrice.takeIf { it != 0L }?.let { + map[" §6${it.shortFormat()} coins"] = it.toDouble() + totalPrice += it + } + + for ((materialInternalName, amount) in price.itemPrice) { + val itemPrice = materialInternalName.getPriceOrNull()?.let { it * amount } + if (itemPrice != null) { + map[" §8${amount.addSeparators()}x ${materialInternalName.itemName} §7(§6${itemPrice.shortFormat()}§7)"] = itemPrice + } else { + map[" §8${amount.addSeparators()}x ${materialInternalName.itemName}"] = 0.0 + } + totalPrice += itemPrice ?: 0.0 + } + + list.add("§7Stars: §e$havingStars§7/§e$maxStars §7(§6" + totalPrice.shortFormat() + "§7)") + val starMaterialCap: Int = config.starMaterialCap.get() + list.addAll(map.sortedDesc().keys.take(starMaterialCap)) + return totalPrice + } + + private fun calculateStarPrice( + internalName: NEUInternalName, + inputStars: Int, + ): Pair<EssenceItemUtils.EssenceUpgradePrice, Pair<Int, Int>>? { + var totalStars = inputStars + val rawInternalName = internalName.asString() + val (price, maxStars) = if (isKuudraSet(rawInternalName)) { + val tier = getKuudraTier(internalName) + totalStars += (tier + 1) * 10 + + var remainingStars = totalStars + + val removed = removeKuudraArmorPrefix(rawInternalName) + var maxStars = 0 + var finalPrice: EssenceItemUtils.EssenceUpgradePrice? = null + + val tiers = mutableMapOf<NEUInternalName, Int>() + + for ((id, prices) in EssenceItemUtils.itemPrices) { + if (!id.contains(removed)) continue + tiers[id] = getKuudraTier(id) + + } + for ((id, tier) in tiers.sorted()) { + val prices = EssenceItemUtils.itemPrices[id]!! + maxStars += prices.size + if (remainingStars <= 0) continue + + val price = getPriceFor(prices, remainingStars) ?: return null + println(" ") + println("price for $id ($remainingStars)") + println("price.itemPrice: ${price.itemPrice}") + println("essencePrice: ${price.essencePrice}") + println("itemPrice: ${price.itemPrice}") + finalPrice = finalPrice?.let { it + price } ?: price + remainingStars -= prices.size + } + if (finalPrice == null) return null + + finalPrice to maxStars + } else { + if (totalStars == 0) return null + + val prices = internalName.getEssencePrices() ?: return null + + (getPriceFor(prices, totalStars) ?: return null) to prices.size + } + val havingStars = totalStars.coerceAtMost(maxStars) + + return price to (havingStars to maxStars) + } + + private fun getKuudraTier(internalName: NEUInternalName): Int { + for (tier in kuudraUpgradeTiers) { + if (internalName.asString().contains(tier)) { + return kuudraUpgradeTiers.indexOf(tier) + } + } + return 0 + } +// private fun getKuudraTier(internalName: NEUInternalName): Int? = +// kuudraUpgradeTiers.firstOrNull { it in internalName.toString() }?.let { kuudraUpgradeTiers.indexOf(it) } + + private fun getPriceFor( + prices: Map<Int, EssenceItemUtils.EssenceUpgradePrice>, + totalStars: Int, + ): EssenceItemUtils.EssenceUpgradePrice? { + var totalEssencePrice: EssenceItemUtils.EssencePrice? = null + var totalCoinPrice = 0L + val totalItemPrice = mutableMapOf<NEUInternalName, Int>() + + for ((tier, price) in prices) { + if (tier > totalStars) break + val essencePrice = price.essencePrice + totalEssencePrice = totalEssencePrice?.let { it + essencePrice } ?: essencePrice + + price.coinPrice?.let { + totalCoinPrice += it + } + for (entry in price.itemPrice) { + totalItemPrice.addOrPut(entry.key, entry.value) + } + } + totalEssencePrice ?: return null + return EssenceItemUtils.EssenceUpgradePrice(totalEssencePrice, totalCoinPrice, totalItemPrice) + } + private fun addMasterStars(stack: ItemStack, list: MutableList<String>): Double { - val totalStars = stack.getDungeonStarCount() ?: return 0.0 + var totalStars = stack.getDungeonStarCount() ?: return 0.0 + starChange.takeIf { it != 0 }?.let { + totalStars += it + } - val masterStars = totalStars - 5 + val masterStars = (totalStars - 5).coerceAtMost(5) if (masterStars < 1) return 0.0 var price = 0.0 @@ -600,8 +746,7 @@ object EstimatedItemValueCalculator { //todo use repo val tieredEnchants = listOf("compact", "cultivating", "champion", "expertise", "hecatomb", "toxophilite") - val onlyTierOnePrices = - listOf("ultimate_chimera", "ultimate_fatal_tempo", "smoldering", "ultimate_flash", "divine_gift") + val onlyTierOnePrices = listOf("ultimate_chimera", "ultimate_fatal_tempo", "smoldering", "ultimate_flash", "divine_gift") val onlyTierFivePrices = listOf("ferocious_mana", "hardened_mana", "mana_vampire", "strong_mana") val internalName = stack.getInternalName() @@ -718,8 +863,7 @@ object EstimatedItemValueCalculator { val internalName = stack.getInternalName() // item have to contains gems.unlocked_slots NBT array for unlocked slot detection - val unlockedSlots = - stack.getExtraAttributes()?.getCompoundTag("gems")?.getTag("unlocked_slots")?.toString() ?: return 0.0 + val unlockedSlots = stack.getExtraAttributes()?.getCompoundTag("gems")?.getTag("unlocked_slots")?.toString() ?: return 0.0 // TODO detection for old items which doesn't have gems.unlocked_slots NBT array // if (unlockedSlots == "null") return 0.0 @@ -782,9 +926,8 @@ object EstimatedItemValueCalculator { return "§b$name ${second} Shard" } - fun Pair<String, Int>.getAttributePrice(): Double? = - EstimatedItemValueCalculator.getPriceOrCompositePriceForAttribute( - "ATTRIBUTE_SHARD+ATTRIBUTE_" + first, - second, - ) + fun Pair<String, Int>.getAttributePrice(): Double? = EstimatedItemValueCalculator.getPriceOrCompositePriceForAttribute( + "ATTRIBUTE_SHARD+ATTRIBUTE_" + first, + second, + ) } diff --git a/src/main/java/at/hannibal2/skyhanni/utils/EssenceItemUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/EssenceItemUtils.kt new file mode 100644 index 000000000..fbb106d08 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/utils/EssenceItemUtils.kt @@ -0,0 +1,136 @@ +package at.hannibal2.skyhanni.utils + +import at.hannibal2.skyhanni.config.ConfigManager +import at.hannibal2.skyhanni.data.jsonobjects.repo.neu.NeuEssenceCostJson +import at.hannibal2.skyhanni.events.NeuRepositoryReloadEvent +import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule +import at.hannibal2.skyhanni.test.command.ErrorManager +import at.hannibal2.skyhanni.utils.CollectionUtils.addOrPut +import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.asInternalName +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent + +@SkyHanniModule +object EssenceItemUtils { + var itemPrices = mapOf<NEUInternalName, Map<Int, EssenceUpgradePrice>>() + + @SubscribeEvent + fun onNeuRepoReload(event: NeuRepositoryReloadEvent) { + val unformattedData = event.getConstant<Map<String, NeuEssenceCostJson>>("essencecosts", NeuEssenceCostJson.TYPE) + + ConfigManager.gson.toJson(unformattedData).let { + ChatUtils.debug("saved to clipboard!") + OSUtils.copyToClipboard(it) + } + this.itemPrices = reformatData(unformattedData) + + println("result: ${itemPrices.size}") + } + + fun NEUInternalName.getEssencePrices(): Map<Int, EssenceUpgradePrice>? = itemPrices[this] + + private fun reformatData(unformattedData: Map<String, NeuEssenceCostJson>): MutableMap<NEUInternalName, Map<Int, EssenceUpgradePrice>> { + val itemPrices = mutableMapOf<NEUInternalName, Map<Int, EssenceUpgradePrice>>() + for ((name, data) in unformattedData) { + + val essencePrices = loadEssencePrices(data) + val extraItems = data.extraItems ?: emptyMap() + val (coinPrices, iemPrices) = loadCoinAndItemPrices(extraItems) + + val upgradePrices = mutableMapOf<Int, EssenceUpgradePrice>() + for ((tier, essencePrice) in essencePrices) { + val coinPrice = coinPrices[tier] + val itemPrice = iemPrices[tier] ?: emptyMap() + upgradePrices[tier] = EssenceUpgradePrice(essencePrice, coinPrice, itemPrice) + } + + val internalName = name.asInternalName() + itemPrices[internalName] = upgradePrices + } + return itemPrices + } + + private fun loadCoinAndItemPrices( + extraItems: Map<String, List<String>>, + ): Pair<MutableMap<Int, Long>, MutableMap<Int, Map<NEUInternalName, Int>>> { + + val collectCoinPrices = mutableMapOf<Int, Long>() + val collectItemPrices = mutableMapOf<Int, Map<NEUInternalName, Int>>() + + for ((tier, rawItems) in extraItems.mapKeys { it.key.toInt() }) { + val itemPrices = mutableMapOf<NEUInternalName, Int>() + + for ((itemName, amount) in rawItems.map { split(it) }) { + if (itemName == NEUInternalName.SKYBLOCK_COIN) { + collectCoinPrices[tier] = amount + } else { + itemPrices[itemName] = amount.toInt() + } + } + + collectItemPrices[tier] = itemPrices + } + return Pair(collectCoinPrices, collectItemPrices) + } + + private fun split(string: String): Pair<NEUInternalName, Long> = string.split(":").let { it[0].asInternalName() to it[1].toLong() } + + private fun loadEssencePrices(data: NeuEssenceCostJson): MutableMap<Int, EssencePrice> { + val map = mutableMapOf<Int, EssencePrice>() + val essenceType = data.essenceType + data.essenceFor1?.let { map[1] = EssencePrice(it, essenceType) } + data.essenceFor2?.let { map[2] = EssencePrice(it, essenceType) } + data.essenceFor3?.let { map[3] = EssencePrice(it, essenceType) } + data.essenceFor4?.let { map[4] = EssencePrice(it, essenceType) } + data.essenceFor5?.let { map[5] = EssencePrice(it, essenceType) } + data.essenceFor6?.let { map[6] = EssencePrice(it, essenceType) } + data.essenceFor7?.let { map[7] = EssencePrice(it, essenceType) } + data.essenceFor8?.let { map[8] = EssencePrice(it, essenceType) } + data.essenceFor9?.let { map[9] = EssencePrice(it, essenceType) } + data.essenceFor10?.let { map[10] = EssencePrice(it, essenceType) } + data.essenceFor11?.let { map[11] = EssencePrice(it, essenceType) } + data.essenceFor12?.let { map[12] = EssencePrice(it, essenceType) } + data.essenceFor13?.let { map[13] = EssencePrice(it, essenceType) } + data.essenceFor14?.let { map[14] = EssencePrice(it, essenceType) } + data.essenceFor15?.let { map[15] = EssencePrice(it, essenceType) } + return map + } + + data class EssenceUpgradePrice( + val essencePrice: EssencePrice, + val coinPrice: Long?, + val itemPrice: Map<NEUInternalName, Int>, + ) { + + operator fun plus(other: EssenceUpgradePrice): EssenceUpgradePrice { + if (other.essencePrice.essenceType != essencePrice.essenceType) ErrorManager.skyHanniError( + "Trying to add non compatible EssenceUpgradePrices!", + "essencePrice.essenceType" to essencePrice.essenceType, + "other.essencePrice.essenceType" to other.essencePrice.essenceType, + ) + + val coinPrice = coinPrice ?: 0L + val otherCoinPrice = other.coinPrice ?: 0L + + val map = itemPrice.toMutableMap() + for (entry in other.itemPrice) { + map.addOrPut(entry.key, entry.value) + } + + return EssenceUpgradePrice(essencePrice + other.essencePrice, coinPrice + otherCoinPrice, map) + } + } + + data class EssencePrice(val essenceAmount: Int, val essenceType: String) { + + operator fun plus(other: EssencePrice): EssencePrice { + if (other.essenceType != essenceType) ErrorManager.skyHanniError( + "Trying to add non compatible essence prices!", + "essenceType" to essenceType, + "other.essenceType" to other.essenceType, + ) + + return EssencePrice(essenceAmount + other.essenceAmount, essenceType) + } + } + +} diff --git a/src/main/java/at/hannibal2/skyhanni/utils/SkyBlockItemModifierUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/SkyBlockItemModifierUtils.kt index c9e193329..4d0cf4468 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/SkyBlockItemModifierUtils.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/SkyBlockItemModifierUtils.kt @@ -46,9 +46,11 @@ object SkyBlockItemModifierUtils { fun ItemStack.getManaDisintegrators() = getAttributeInt("mana_disintegrator_count") fun ItemStack.getDungeonStarCount() = if (isDungeonItem()) { - getAttributeInt("upgrade_level") ?: getAttributeInt("dungeon_item_level") + getStarCount() ?: getAttributeInt("dungeon_item_level") } else null + fun ItemStack.getStarCount() = getAttributeInt("upgrade_level") + private fun ItemStack.isDungeonItem() = getLore().any { it.contains("DUNGEON ") } fun ItemStack.getPetExp() = getPetInfo()?.get("exp")?.asDouble |