aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/at/hannibal2/skyhanni/features
diff options
context:
space:
mode:
authorMTOnline69 <97001154+MTOnline69@users.noreply.github.com>2024-09-12 09:21:53 +0100
committerGitHub <noreply@github.com>2024-09-12 10:21:53 +0200
commit4e23db746f35965b84f8dd5be19b9883c67d8add (patch)
tree3df56c12f7e3766c33c64eb309136367e3009a42 /src/main/java/at/hannibal2/skyhanni/features
parent996b70464766ca017de65b85b0574b0ed6eccab4 (diff)
downloadskyhanni-4e23db746f35965b84f8dd5be19b9883c67d8add.tar.gz
skyhanni-4e23db746f35965b84f8dd5be19b9883c67d8add.tar.bz2
skyhanni-4e23db746f35965b84f8dd5be19b9883c67d8add.zip
Feature: Broodmother alerts/messages and damage indicator support (#2325)
Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com>
Diffstat (limited to 'src/main/java/at/hannibal2/skyhanni/features')
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/combat/BroodmotherFeatures.kt183
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/combat/SpidersDenAPI.kt12
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/combat/damageindicator/BossType.kt3
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/combat/damageindicator/MobFinder.kt5
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardEvent.kt5
5 files changed, 203 insertions, 5 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/features/combat/BroodmotherFeatures.kt b/src/main/java/at/hannibal2/skyhanni/features/combat/BroodmotherFeatures.kt
new file mode 100644
index 000000000..e087fdd19
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/combat/BroodmotherFeatures.kt
@@ -0,0 +1,183 @@
+package at.hannibal2.skyhanni.features.combat
+
+import at.hannibal2.skyhanni.SkyHanniMod
+import at.hannibal2.skyhanni.data.IslandType
+import at.hannibal2.skyhanni.data.model.TabWidget
+import at.hannibal2.skyhanni.events.GuiRenderEvent
+import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent
+import at.hannibal2.skyhanni.events.SecondPassedEvent
+import at.hannibal2.skyhanni.events.WidgetUpdateEvent
+import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule
+import at.hannibal2.skyhanni.utils.ChatUtils
+import at.hannibal2.skyhanni.utils.HypixelCommands
+import at.hannibal2.skyhanni.utils.LorenzUtils
+import at.hannibal2.skyhanni.utils.LorenzUtils.isInIsland
+import at.hannibal2.skyhanni.utils.RenderUtils.renderString
+import at.hannibal2.skyhanni.utils.SimpleTimeMark
+import at.hannibal2.skyhanni.utils.SoundUtils
+import at.hannibal2.skyhanni.utils.SoundUtils.playSound
+import at.hannibal2.skyhanni.utils.StringUtils
+import at.hannibal2.skyhanni.utils.TimeUtils.format
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import kotlin.reflect.KMutableProperty0
+import kotlin.time.Duration.Companion.minutes
+import kotlin.time.Duration.Companion.seconds
+import kotlin.time.DurationUnit
+
+@SkyHanniModule
+object BroodmotherFeatures {
+
+ enum class StageEntry(private val str: String, val minutes: Int) {
+ SLAIN("§eSlain", 10),
+ DORMANT("§eDormant", 9),
+ SOON("§6Soon", 6),
+ AWAKENING("§6Awakening", 3),
+ IMMINENT("§4Imminent", 1),
+ ALIVE("§4Alive!", 0);
+
+ override fun toString() = str
+ }
+
+ private val config get() = SkyHanniMod.feature.combat.broodmother
+ private val spawnAlertConfig get() = config.spawnAlert
+
+ private var lastStage: StageEntry? = null
+ private var currentStage: StageEntry? = null
+ private var broodmotherSpawnTime = SimpleTimeMark.farPast()
+ private var display = ""
+
+ @SubscribeEvent
+ fun onTabListUpdate(event: WidgetUpdateEvent) {
+ if (!event.isWidget(TabWidget.BROODMOTHER)) return
+ val newStage = event.widget.matchMatcherFirstLine { group("stage") } ?: ""
+ if (newStage.isNotEmpty()) {
+ lastStage = currentStage
+ currentStage = StageEntry.valueOf(newStage.replace("!", "").uppercase())
+ onStageUpdate()
+ }
+ }
+
+ private fun onStageUpdate() {
+ ChatUtils.debug("New Broodmother stage: $currentStage")
+
+ if (lastStage == null) {
+ if (onServerJoin()) return
+ }
+
+ // ignore Hypixel bug where the stage may temporarily revert to Imminent after the Broodmother's death
+ if (currentStage == StageEntry.IMMINENT && lastStage == StageEntry.ALIVE) return
+
+ if (currentStage == StageEntry.ALIVE) {
+ onBroodmotherSpawn()
+ return
+ }
+
+ val timeUntilSpawn = currentStage?.minutes?.minutes
+ broodmotherSpawnTime = SimpleTimeMark.now() + timeUntilSpawn!!
+
+ if (currentStage == StageEntry.IMMINENT && config.imminentWarning) {
+ playImminentWarning()
+ return
+ }
+
+ if (config.stages.contains(currentStage) && lastStage != null) {
+ if (currentStage == StageEntry.SLAIN) {
+ onBroodmotherSlain()
+ } else {
+ val pluralize = StringUtils.pluralize(timeUntilSpawn.toInt(DurationUnit.MINUTES), "minute")
+ ChatUtils.chat(
+ "Broodmother: $lastStage §e-> $currentStage§e. §b${timeUntilSpawn.inWholeMinutes} $pluralize §euntil it spawns!"
+ )
+ }
+ }
+ }
+
+ private fun onServerJoin(): Boolean {
+ // don't send if user has config enabled for either of the alive messages
+ // this is so that two messages aren't immediately sent upon joining a server
+ if (config.stageOnJoin && !(currentStage == StageEntry.ALIVE && isAliveMessageEnabled())) {
+ val pluralize = StringUtils.pluralize(currentStage?.minutes ?: 0, "minute")
+ var message = "The Broodmother's current stage in this server is ${currentStage.toString().replace("!", "")}§e."
+ if (currentStage?.minutes != 0) {
+ message += " It will spawn within §b${currentStage?.minutes} $pluralize§e."
+ }
+ ChatUtils.chat(message)
+ return true
+ } else {
+ return false
+ }
+ }
+
+ private fun onBroodmotherSpawn() {
+ broodmotherSpawnTime = SimpleTimeMark.farPast()
+ if (!isAliveMessageEnabled()) return
+ val feature: KMutableProperty0<*>
+ if (config.alertOnSpawn) {
+ feature = config::alertOnSpawn
+ val alertSound = SoundUtils.createSound(spawnAlertConfig.alertSound, spawnAlertConfig.pitch)
+ SoundUtils.repeatSound(100, spawnAlertConfig.repeatSound, alertSound)
+ LorenzUtils.sendTitle(spawnAlertConfig.text.replace("&", "§"), 3.seconds)
+ } else {
+ feature = config::stages
+ }
+ ChatUtils.clickToActionOrDisable(
+ "The Broodmother has spawned!",
+ feature,
+ actionName = "warp to the Top of the Nest",
+ action = { HypixelCommands.warp("nest") },
+ )
+ }
+
+ private fun playImminentWarning() {
+ SoundUtils.repeatSound(100, 2, SoundUtils.createSound("note.pling", 0.5f))
+ ChatUtils.chat("The Broodmother is §4Imminent§e! It will spawn in §b60 seconds§e!")
+ }
+
+ private fun onBroodmotherSlain() {
+ broodmotherSpawnTime = SimpleTimeMark.now() + 10.minutes
+ if (!(config.hideSlainWhenNearby && SpidersDenAPI.isAtTopOfNest())) {
+ ChatUtils.chat("The Broodmother was killed!")
+ }
+ }
+
+ @SubscribeEvent
+ fun onWorldChange(event: LorenzWorldChangeEvent) {
+ broodmotherSpawnTime = SimpleTimeMark.farPast()
+ lastStage = null
+ currentStage = null
+ display = ""
+ }
+
+ @SubscribeEvent
+ fun onRenderOverlay(event: GuiRenderEvent.GuiOverlayRenderEvent) {
+ if (!isCountdownEnabled()) return
+ if (display.isEmpty()) return
+
+ config.countdownPosition.renderString(display, posLabel = "Broodmother Countdown")
+ }
+
+ @SubscribeEvent
+ fun onSecondPassed(event: SecondPassedEvent) {
+ if (!isCountdownEnabled()) return
+
+ if (broodmotherSpawnTime.isFarPast()) {
+ if (lastStage != null) {
+ display = "§4Broodmother spawned!"
+ }
+ } else {
+ val countdown = broodmotherSpawnTime.timeUntil().format()
+ display = "§4Broodmother spawning in §b$countdown"
+ }
+ }
+
+ @JvmStatic
+ fun playTestSound() {
+ with(spawnAlertConfig) {
+ SoundUtils.createSound(alertSound, pitch).playSound()
+ }
+ }
+
+ private fun inSpidersDen() = IslandType.SPIDER_DEN.isInIsland()
+ private fun isCountdownEnabled() = inSpidersDen() && config.countdown
+ private fun isAliveMessageEnabled() = config.alertOnSpawn || config.stages.contains(StageEntry.ALIVE)
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/combat/SpidersDenAPI.kt b/src/main/java/at/hannibal2/skyhanni/features/combat/SpidersDenAPI.kt
new file mode 100644
index 000000000..7986c55e9
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/combat/SpidersDenAPI.kt
@@ -0,0 +1,12 @@
+package at.hannibal2.skyhanni.features.combat
+
+import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboard
+import at.hannibal2.skyhanni.features.gui.customscoreboard.ScoreboardPattern
+import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule
+import at.hannibal2.skyhanni.utils.RegexUtils.matches
+
+@SkyHanniModule
+object SpidersDenAPI {
+ private fun getSbLines(): List<String> = CustomScoreboard.activeLines
+ fun isAtTopOfNest(): Boolean = getSbLines().any { ScoreboardPattern.broodmotherPattern.matches(it) }
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/combat/damageindicator/BossType.kt b/src/main/java/at/hannibal2/skyhanni/features/combat/damageindicator/BossType.kt
index 3bc12fa4c..3d46d3edc 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/combat/damageindicator/BossType.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/combat/damageindicator/BossType.kt
@@ -101,6 +101,7 @@ enum class BossType(
DUMMY("Dummy", Type.DUMMY),
ARACHNE_SMALL("§cSmall Arachne", Type.ARACHNE),
ARACHNE_BIG("§4Big Arachne", Type.ARACHNE),
+ BROODMOTHER("§cBroodmother", Type.BROODMOTHER),
// The Rift
LEECH_SUPREME("§cLeech Supreme", Type.THE_RIFT_BOSSES),
@@ -119,8 +120,6 @@ enum class BossType(
GARDEN_PEST_SLUG("§cSlug", Type.GARDEN_PESTS),
GARDEN_PEST_EARTHWORM("§cEarthworm", Type.GARDEN_PESTS),
- // TODO arachne
-
// TODO Corleone
// TODO bal
diff --git a/src/main/java/at/hannibal2/skyhanni/features/combat/damageindicator/MobFinder.kt b/src/main/java/at/hannibal2/skyhanni/features/combat/damageindicator/MobFinder.kt
index e9b2f879b..975e3b4f8 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/combat/damageindicator/MobFinder.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/combat/damageindicator/MobFinder.kt
@@ -429,6 +429,11 @@ class MobFinder {
entity.hasMaxHealth(2_400_000, true) -> return EntityResult(bossType = BossType.SLAYER_SPIDER_4)
}
}
+ if (entity.hasNameTagWith(1, "[§7Lv12§8] §4Broodmother")) {
+ if (entity.hasMaxHealth(6000)) {
+ return EntityResult(bossType = BossType.BROODMOTHER)
+ }
+ }
checkArachne(entity as EntitySpider)?.let { return it }
return null
}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardEvent.kt b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardEvent.kt
index efe7c953d..9f3c009e5 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardEvent.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardEvent.kt
@@ -2,6 +2,7 @@ package at.hannibal2.skyhanni.features.gui.customscoreboard
import at.hannibal2.skyhanni.data.HypixelData
import at.hannibal2.skyhanni.data.IslandType
+import at.hannibal2.skyhanni.features.combat.SpidersDenAPI.isAtTopOfNest
import at.hannibal2.skyhanni.features.dungeon.DungeonAPI
import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboard.eventsConfig
import at.hannibal2.skyhanni.features.gui.customscoreboard.ScoreboardEvent.VOTING
@@ -121,7 +122,7 @@ enum class ScoreboardEvent(
),
BROODMOTHER(
::getBroodmotherLines,
- ::getBroodmotherShowWhen,
+ ::isAtTopOfNest,
"§4Broodmother§7: §eDormant",
),
MINING_EVENTS(
@@ -441,8 +442,6 @@ private fun getSoonEventShowWhen(): Boolean =
private fun getBroodmotherLines(): List<String> =
listOf(getSbLines().first { SbPattern.broodmotherPattern.matches(it) })
-private fun getBroodmotherShowWhen(): Boolean = getSbLines().any { SbPattern.broodmotherPattern.matches(it) }
-
private fun getMiningEventsLines() = buildList {
// Wind
if (getSbLines().any { SbPattern.windCompassPattern.matches(it) }