diff options
author | CalMWolfs <94038482+CalMWolfs@users.noreply.github.com> | 2024-04-30 21:53:47 +1000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-04-30 13:53:47 +0200 |
commit | d595c90008c81adbbb7e072f31543416b263906b (patch) | |
tree | 5aa83e5d2c95e0ebcfe533d98e680766df877b5d | |
parent | ce7fdde67857fd2e0690907e2df756830229b048 (diff) | |
download | skyhanni-d595c90008c81adbbb7e072f31543416b263906b.tar.gz skyhanni-d595c90008c81adbbb7e072f31543416b263906b.tar.bz2 skyhanni-d595c90008c81adbbb7e072f31543416b263906b.zip |
Feature: More info on chocolate upgrades (#1594)
Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com>
11 files changed, 172 insertions, 39 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt index cae61fe89..74ebfb1de 100644 --- a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt +++ b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt @@ -131,6 +131,7 @@ import at.hannibal2.skyhanni.features.event.chocolatefactory.ChocolateFactoryInv import at.hannibal2.skyhanni.features.event.chocolatefactory.ChocolateFactoryShortcut import at.hannibal2.skyhanni.features.event.chocolatefactory.ChocolateFactoryStats import at.hannibal2.skyhanni.features.event.chocolatefactory.ChocolateFactoryTimeTowerManager +import at.hannibal2.skyhanni.features.event.chocolatefactory.ChocolateFactoryTooltip import at.hannibal2.skyhanni.features.event.chocolatefactory.HoppityCollectionStats import at.hannibal2.skyhanni.features.event.chocolatefactory.HoppityEggLocator import at.hannibal2.skyhanni.features.event.chocolatefactory.HoppityEggsManager @@ -633,6 +634,7 @@ class SkyHanniMod { loadModule(ChocolateFactoryStats) loadModule(FactoryItemTooltipFeatures) loadModule(ChocolateFactoryTimeTowerManager) + loadModule(ChocolateFactoryTooltip) loadModule(HoppityNpc) loadModule(HoppityEggsManager) loadModule(HoppityEggLocator) diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/event/ChocolateFactoryConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/event/ChocolateFactoryConfig.java index 6316ca34d..affb69381 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/event/ChocolateFactoryConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/event/ChocolateFactoryConfig.java @@ -87,6 +87,12 @@ public class ChocolateFactoryConfig { public int barnCapacityThreshold = 6; @Expose + @ConfigOption(name = "Extra Tooltip Stats", desc = "Shows extra information about upgrades in the tooltip.") + @ConfigEditorBoolean + @FeatureToggle + public boolean extraTooltipStats = true; + + @Expose @ConfigOption(name = "Hoppity Collection Stats", desc = "Shows info about your hoppity rabbit collection.") @ConfigEditorBoolean @FeatureToggle diff --git a/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java b/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java index a353bd88a..472f1e8af 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java +++ b/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java @@ -87,6 +87,9 @@ public class ProfileSpecificStorage { public int currentTimeTowerUses = -1; @Expose + public int timeTowerCooldown = 8; + + @Expose public int maxTimeTowerUses = 3; @Expose diff --git a/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/HoppityEggLocationsJson.kt b/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/HoppityEggLocationsJson.kt index b5b4c699e..7e12607d2 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/HoppityEggLocationsJson.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/HoppityEggLocationsJson.kt @@ -15,6 +15,9 @@ data class HoppityEggLocationsJson( @Expose val prestigeIndex: Int, @Expose val milestoneIndex: Int, @Expose val leaderboardIndex: Int, + @Expose val handCookieIndex: Int, @Expose val timeTowerIndex: Int, + @Expose val shrineIndex: Int, + @Expose val coachRabbitIndex: Int, @Expose val maxRabbits: Int, ) diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateAmount.kt b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateAmount.kt index 230799df0..bbaf0dc25 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateAmount.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateAmount.kt @@ -3,6 +3,7 @@ package at.hannibal2.skyhanni.features.event.chocolatefactory import at.hannibal2.skyhanni.features.event.chocolatefactory.ChocolateFactoryAPI.profileStorage import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators import at.hannibal2.skyhanni.utils.SimpleTimeMark +import at.hannibal2.skyhanni.utils.TimeUtils.format import kotlin.time.Duration import kotlin.time.Duration.Companion.seconds @@ -12,21 +13,30 @@ enum class ChocolateAmount(val chocolate: () -> Long) { ALL_TIME({ profileStorage?.chocolateAllTime ?: 0 }), ; - val formatted get(): String = chocolate().addSeparators() + val formatted get(): String = (chocolate() + chocolateSinceUpdate()).addSeparators() - fun timeUntilGoal(goal: Long): Duration { + fun formattedTimeUntilGoal(goal: Long): String { + val time = timeUntilGoal(goal) + return when { + time.isInfinite() -> "§cNever" + time.isNegative() -> "§aNow" + else -> "§6${time.format()}" + } + } + + private fun timeUntilGoal(goal: Long): Duration { val profileStorage = ChocolateFactoryAPI.profileStorage ?: return Duration.ZERO val updatedAgo = SimpleTimeMark(profileStorage.lastDataSave).passedSince().inWholeSeconds val baseMultiplier = profileStorage.rawChocolateMultiplier - val baseChocolatePerSecond = profileStorage.rawChocPerSecond + val rawChocolatePerSecond = profileStorage.rawChocPerSecond val timeTowerMultiplier = baseMultiplier + profileStorage.timeTowerLevel * 0.1 var needed = goal - chocolate() val secondsUntilTowerExpires = ChocolateFactoryTimeTowerManager.timeTowerActiveDuration().inWholeSeconds - val timeTowerChocPerSecond = baseChocolatePerSecond * timeTowerMultiplier + val timeTowerChocPerSecond = rawChocolatePerSecond * timeTowerMultiplier val secondsAtRate = needed / timeTowerChocPerSecond if (secondsAtRate < secondsUntilTowerExpires) { @@ -34,7 +44,18 @@ enum class ChocolateAmount(val chocolate: () -> Long) { } needed -= (secondsUntilTowerExpires * timeTowerChocPerSecond).toLong() - val chocPerSecond = baseChocolatePerSecond * baseMultiplier - return (needed / chocPerSecond + secondsUntilTowerExpires).seconds - updatedAgo.seconds + val basePerSecond = rawChocolatePerSecond * baseMultiplier + return (needed / basePerSecond + secondsUntilTowerExpires).seconds - updatedAgo.seconds + } + + companion object { + fun chocolateSinceUpdate(): Long { + val lastUpdate = SimpleTimeMark(profileStorage?.lastDataSave ?: return 0) + val currentTime = SimpleTimeMark.now() + val secondsSinceUpdate = (currentTime - lastUpdate).inWholeSeconds + + val perSecond = ChocolateFactoryAPI.chocolatePerSecond + return (perSecond * secondsSinceUpdate).toLong() + } } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryAPI.kt b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryAPI.kt index e00f2073c..3ecbaf47e 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryAPI.kt @@ -4,7 +4,6 @@ import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.config.features.event.ChocolateFactoryConfig import at.hannibal2.skyhanni.config.storage.ProfileSpecificStorage.ChocolateFactoryStorage import at.hannibal2.skyhanni.data.ProfileStorageData -import at.hannibal2.skyhanni.data.jsonobjects.repo.DisabledFeaturesJson import at.hannibal2.skyhanni.data.jsonobjects.repo.HoppityEggLocationsJson import at.hannibal2.skyhanni.events.InventoryCloseEvent import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent @@ -107,10 +106,13 @@ object ChocolateFactoryAPI { var barnIndex = 34 private var infoIndex = 13 private var productionInfoIndex = 45 - private var prestigeIndex = 28 + var prestigeIndex = 28 var milestoneIndex = 53 private var leaderboardIndex = 51 + var handCookieIndex = 38 var timeTowerIndex = 39 + var shrineIndex = 41 + var coachRabbitIndex = 42 var maxRabbits = 395 var inChocolateFactory = false @@ -174,7 +176,7 @@ object ChocolateFactoryAPI { } val lore = item.getLore() - val upgradeCost = lore.getUpgradeCost() ?: continue + val upgradeCost = getChocolateUpgradeCost(lore) ?: continue val canAfford = upgradeCost <= ChocolateAmount.CURRENT.chocolate() if (canAfford) upgradeableSlots.add(slotIndex) @@ -316,14 +318,17 @@ object ChocolateFactoryAPI { prestigeIndex = data.prestigeIndex milestoneIndex = data.milestoneIndex leaderboardIndex = data.leaderboardIndex + handCookieIndex = data.handCookieIndex timeTowerIndex = data.timeTowerIndex + shrineIndex = data.shrineIndex + coachRabbitIndex = data.coachRabbitIndex maxRabbits = data.maxRabbits - val disabledFeatures = event.getConstant<DisabledFeaturesJson>("DisabledFeatures") + ChocolateFactoryTooltip.updateIgnoredSlots() } - private fun List<String>.getUpgradeCost(): Long? { - val nextLine = this.nextAfter({ UtilsPatterns.costLinePattern.matches(it) }) ?: return null + fun getChocolateUpgradeCost(lore: List<String>): Long? { + val nextLine = lore.nextAfter({ UtilsPatterns.costLinePattern.matches(it) }) ?: return null return chocolateAmountPattern.matchMatcher(nextLine.removeColor()) { group("amount").formatLong() } diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryStats.kt b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryStats.kt index d9300ace4..a621059b0 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryStats.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryStats.kt @@ -2,16 +2,15 @@ package at.hannibal2.skyhanni.features.event.chocolatefactory import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator import at.hannibal2.skyhanni.events.GuiRenderEvent +import at.hannibal2.skyhanni.events.SecondPassedEvent import at.hannibal2.skyhanni.utils.ClipboardUtils import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators import at.hannibal2.skyhanni.utils.RenderUtils.renderRenderables import at.hannibal2.skyhanni.utils.StringUtils.removeColor -import at.hannibal2.skyhanni.utils.TimeUtils.format import at.hannibal2.skyhanni.utils.renderables.Renderable import com.google.gson.JsonPrimitive import net.minecraftforge.fml.common.eventhandler.SubscribeEvent -import kotlin.time.Duration object ChocolateFactoryStats { @@ -21,6 +20,13 @@ object ChocolateFactoryStats { private var display = listOf<Renderable>() @SubscribeEvent + fun onSecondPassed(event: SecondPassedEvent) { + if (!LorenzUtils.inSkyBlock) return + if (!ChocolateFactoryAPI.chocolateFactoryPaused) return + updateDisplay() + } + + @SubscribeEvent fun onBackgroundDraw(event: GuiRenderEvent.ChestGuiOverlayRenderEvent) { if (!ChocolateFactoryAPI.inChocolateFactory && !ChocolateFactoryAPI.chocolateFactoryPaused) return if (!config.statsDisplay) return @@ -43,14 +49,7 @@ object ChocolateFactoryStats { "§6${ChocolateFactoryTimeTowerManager.timeTowerCharges()}" } - val timeUntilPrestige = ChocolateAmount.PRESTIGE.timeUntilGoal(ChocolateFactoryAPI.chocolateForPrestige) - - // todo once TimeUtils.formatDuration() is no longer used add custom formatting for infinite - val prestigeEstimate = if (timeUntilPrestige == Duration.INFINITE) { - "§cNever" - } else { - "§6${timeUntilPrestige.format()}" - } + val prestigeEstimate = ChocolateAmount.PRESTIGE.formattedTimeUntilGoal(ChocolateFactoryAPI.chocolateForPrestige) val text = formatList(buildList { add("§6§lChocolate Factory Stats") @@ -78,18 +77,6 @@ object ChocolateFactoryStats { add("§eRaw Per Second: §6${profileStorage.rawChocPerSecond.addSeparators()}") }) - // TODO keep counting, we dont want pauses -// val firstElement = displayText.firstOrNull { it.isNotEmpty() } ?: return -// -// if (ChocolateFactoryAPI.chocolateFactoryPaused) { -// val leftMargin = (firstElement.width() - "§f(§cPaused§f)".width()) / 2 -// val spaceWidth = " ".width() -// displayText.add(0, "${" ".repeat(leftMargin / spaceWidth)}§f(§cPaused§f)") -// } else { -// displayText.add(0, "") -// } -// displayList = displayText.map(Renderable::string).toMutableList() - display = listOf(Renderable.clickAndHover( Renderable.verticalContainer(text.map(Renderable::string)), tips = listOf("§bCopy to Clipboard!"), diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryTimeTowerManager.kt b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryTimeTowerManager.kt index 55390605d..2fe1af812 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryTimeTowerManager.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryTimeTowerManager.kt @@ -11,6 +11,7 @@ import at.hannibal2.skyhanni.utils.SoundUtils import net.minecraftforge.fml.common.eventhandler.SubscribeEvent import kotlin.time.Duration import kotlin.time.Duration.Companion.hours +import kotlin.time.Duration.Companion.milliseconds import kotlin.time.Duration.Companion.minutes import kotlin.time.Duration.Companion.seconds @@ -37,8 +38,7 @@ object ChocolateFactoryTimeTowerManager { if (nextCharge.isInPast() && !nextCharge.isFarPast() && currentCharges() < maxCharges()) { profileStorage.currentTimeTowerUses++ - // todo in future once have Einstein rabbit account for that - val nextTimeTower = SimpleTimeMark(profileStorage.nextTimeTower) + 8.hours + val nextTimeTower = SimpleTimeMark(profileStorage.nextTimeTower) + (profileStorage.timeTowerCooldown).hours profileStorage.nextTimeTower = nextTimeTower.toMillis() if (!config.timeTowerWarning) return @@ -90,11 +90,20 @@ object ChocolateFactoryTimeTowerManager { fun timeTowerFull() = currentCharges() >= maxCharges() - fun timeTowerActive() = profileStorage?.currentTimeTowerEnds != 0L + fun timeTowerActive(): Boolean { + val currentTime = profileStorage?.lastDataSave ?: 0 + val endTime = profileStorage?.currentTimeTowerEnds ?: 0 + + return endTime > currentTime + } fun timeTowerActiveDuration(): Duration { if (!timeTowerActive()) return Duration.ZERO - return SimpleTimeMark(profileStorage?.currentTimeTowerEnds ?: 0).timeUntil() + val currentTime = profileStorage?.lastDataSave ?: 0 + val endTime = profileStorage?.currentTimeTowerEnds ?: 0 + + val duration = endTime - currentTime + return duration.milliseconds } @SubscribeEvent diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryTooltip.kt b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryTooltip.kt new file mode 100644 index 000000000..3861fe76d --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryTooltip.kt @@ -0,0 +1,92 @@ +package at.hannibal2.skyhanni.features.event.chocolatefactory + +import at.hannibal2.skyhanni.events.LorenzToolTipEvent +import at.hannibal2.skyhanni.features.event.chocolatefactory.ChocolateFactoryAPI.profileStorage +import at.hannibal2.skyhanni.utils.LorenzUtils.round +import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators +import net.minecraftforge.fml.common.eventhandler.EventPriority +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent + +object ChocolateFactoryTooltip { + + private val config get() = ChocolateFactoryAPI.config + + private var ignoredSlotIndexes = listOf<Int>() + + fun updateIgnoredSlots() { + ignoredSlotIndexes = listOf( + ChocolateFactoryAPI.prestigeIndex, + ChocolateFactoryAPI.handCookieIndex, + ChocolateFactoryAPI.shrineIndex, + ChocolateFactoryAPI.barnIndex, + ) + } + + @SubscribeEvent(priority = EventPriority.HIGH) + fun onTooltip(event: LorenzToolTipEvent) { + if (!ChocolateFactoryAPI.inChocolateFactory) return + if (!config.extraTooltipStats) return + + val slotIndex = event.slot.slotNumber + if (slotIndex == ChocolateFactoryAPI.prestigeIndex) return + if (slotIndex !in ChocolateFactoryAPI.otherUpgradeSlots && slotIndex !in ChocolateFactoryAPI.rabbitSlots) return + + val upgradeCost = ChocolateFactoryAPI.getChocolateUpgradeCost(event.toolTip) ?: return + + event.toolTip.add("§8§m-----------------") + val timeToUpgrade = ChocolateAmount.CURRENT.formattedTimeUntilGoal(upgradeCost) + + event.toolTip.add("§7Time until upgrade: §e$timeToUpgrade") + + if (slotIndex in ignoredSlotIndexes) return + + val averageChocolate = averageChocPerSecond().round(2) + + val newAverageChocolate = when (slotIndex) { + in ChocolateFactoryAPI.rabbitSlots -> { + val chocolateIncrease = ChocolateFactoryAPI.rabbitSlots[slotIndex] ?: 0 + averageChocPerSecond(rawPerSecondIncrease = chocolateIncrease) + } + + ChocolateFactoryAPI.timeTowerIndex -> averageChocPerSecond(timeTowerLevelIncrease = 1) + ChocolateFactoryAPI.coachRabbitIndex -> averageChocPerSecond(baseMultiplierIncrease = 0.01) + else -> averageChocolate + }.round(2) + + val extra = (newAverageChocolate - averageChocolate).round(2) + val ratioForUpgrade = (upgradeCost / extra).round(2) + + event.toolTip.add("§7Extra: §6$extra §7choc/s") + event.toolTip.add("§7Effective Cost: §6${ratioForUpgrade.addSeparators()}") + + if (slotIndex == ChocolateFactoryAPI.timeTowerIndex) { + event.toolTip.add("§7One charge will give: §6${chocPerTimeTower().addSeparators()}") + } + } + + private fun averageChocPerSecond( + baseMultiplierIncrease: Double = 0.0, + rawPerSecondIncrease: Int = 0, + timeTowerLevelIncrease: Int = 0, + ): Double { + val profileStorage = profileStorage ?: return 0.0 + + val baseMultiplier = profileStorage.chocolateMultiplier + baseMultiplierIncrease + val rawPerSecond = profileStorage.rawChocPerSecond + rawPerSecondIncrease + val timeTowerLevel = profileStorage.timeTowerLevel + timeTowerLevelIncrease + + val timeTowerCooldown = profileStorage.timeTowerCooldown + + val basePerSecond = rawPerSecond * baseMultiplier + val towerCalc = (rawPerSecond * timeTowerLevel * .1) / timeTowerCooldown + + return basePerSecond + towerCalc + } + + private fun chocPerTimeTower(): Int { + val profileStorage = profileStorage ?: return 0 + val amountPerSecond = profileStorage.rawChocPerSecond * profileStorage.timeTowerLevel * .1 + val amountPerHour = amountPerSecond * 60 * 60 + return amountPerHour.toInt() + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/HoppityCollectionStats.kt b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/HoppityCollectionStats.kt index 05361500e..ee3b3d2eb 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/HoppityCollectionStats.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/HoppityCollectionStats.kt @@ -80,6 +80,11 @@ class HoppityCollectionStats { } val rarity = rabbitRarity ?: continue + + if (itemName == "§dEinstein" && found) { + ChocolateFactoryAPI.profileStorage?.timeTowerCooldown = 7 + } + val duplicates = duplicatesFound.coerceAtLeast(0) loggedRabbits[itemName] = RabbitCollectionInfo(rarity, found, duplicates) } diff --git a/src/main/java/at/hannibal2/skyhanni/utils/UtilsPatterns.kt b/src/main/java/at/hannibal2/skyhanni/utils/UtilsPatterns.kt index 797207d0b..f68c8edc1 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/UtilsPatterns.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/UtilsPatterns.kt @@ -57,7 +57,7 @@ object UtilsPatterns { ) val costLinePattern by patternGroup.pattern( "item.cost.line", - "§7Cost" + "(?:§5§o)?§7Cost" ) val timeAmountPattern by patternGroup.pattern( |