aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/combat/CombatConfig.java6
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/combat/broodmother/BroodmotherConfig.java68
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/combat/broodmother/BroodmotherSpawnAlertConfig.java41
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/combat/damageindicator/DamageIndicatorConfig.java3
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/model/TabWidget.kt2
-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
10 files changed, 322 insertions, 6 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/combat/CombatConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/combat/CombatConfig.java
index 4beede62b..7042b2fdb 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/combat/CombatConfig.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/combat/CombatConfig.java
@@ -1,6 +1,7 @@
package at.hannibal2.skyhanni.config.features.combat;
import at.hannibal2.skyhanni.config.FeatureToggle;
+import at.hannibal2.skyhanni.config.features.combat.broodmother.BroodmotherConfig;
import at.hannibal2.skyhanni.config.features.combat.damageindicator.DamageIndicatorConfig;
import at.hannibal2.skyhanni.config.features.combat.ghostcounter.GhostCounterConfig;
import com.google.gson.annotations.Expose;
@@ -61,6 +62,11 @@ public class CombatConfig {
public FlareConfig flare = new FlareConfig();
@Expose
+ @ConfigOption(name = "Broodmother", desc = "")
+ @Accordion
+ public BroodmotherConfig broodmother = new BroodmotherConfig();
+
+ @Expose
@ConfigOption(name = "Hide Damage Splash", desc = "Hide all damage splashes anywhere in SkyBlock.")
@ConfigEditorBoolean
@FeatureToggle
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/combat/broodmother/BroodmotherConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/combat/broodmother/BroodmotherConfig.java
new file mode 100644
index 000000000..8acd69c1f
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/combat/broodmother/BroodmotherConfig.java
@@ -0,0 +1,68 @@
+package at.hannibal2.skyhanni.config.features.combat.broodmother;
+
+import at.hannibal2.skyhanni.config.FeatureToggle;
+import at.hannibal2.skyhanni.config.core.config.Position;
+import at.hannibal2.skyhanni.features.combat.BroodmotherFeatures.StageEntry;
+import com.google.gson.annotations.Expose;
+import io.github.notenoughupdates.moulconfig.annotations.Accordion;
+import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorBoolean;
+import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorDraggableList;
+import io.github.notenoughupdates.moulconfig.annotations.ConfigLink;
+import io.github.notenoughupdates.moulconfig.annotations.ConfigOption;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class BroodmotherConfig {
+
+ @Expose
+ @ConfigOption(name = "Countdown", desc = "Display a countdown until the Broodmother will spawn.\n" +
+ "§cCountdown will not show unless the time until spawn has been established, and may be off by a few seconds.")
+ @ConfigEditorBoolean
+ @FeatureToggle
+ public boolean countdown = true;
+
+ @Expose
+ @ConfigOption(name = "Spawn Alert", desc = "Send a chat message, title and sound when the Broodmother spawns.")
+ @ConfigEditorBoolean
+ @FeatureToggle
+ public boolean alertOnSpawn = false;
+
+ @Expose
+ @ConfigOption(name = "Alert Settings", desc = "")
+ @Accordion
+ public BroodmotherSpawnAlertConfig spawnAlert = new BroodmotherSpawnAlertConfig();
+
+ @Expose
+ @ConfigOption(name = "Imminent Warning", desc = "Warns you when the Broodmother is 1 minute away from spawning.")
+ @ConfigEditorBoolean
+ @FeatureToggle
+ public boolean imminentWarning = false;
+
+ @Expose
+ @ConfigOption(name = "Chat Messages", desc = "Send a chat message when the Broodmother enters these stages.\n" +
+ "§cThe 'Alive!' and 'Imminent' stages are overridden by the \"Spawn Alert\" and \"Imminent Warning\" features.")
+ @ConfigEditorDraggableList
+ public List<StageEntry> stages = new ArrayList<>(Arrays.asList(
+ StageEntry.SLAIN,
+ StageEntry.ALIVE
+ ));
+
+ @Expose
+ @ConfigOption(name = "Stage on Server Join", desc = "Send a chat message with the Broodmother's current stage upon joining the Spider's Den.")
+ @ConfigEditorBoolean
+ @FeatureToggle
+ public boolean stageOnJoin = false;
+
+ @Expose
+ @ConfigOption(name = "Hide own kills", desc = "Disable the chat message for the §eSlain §rstage if at the Spider Mound.")
+ @ConfigEditorBoolean
+ @FeatureToggle
+ public boolean hideSlainWhenNearby = false;
+
+ @Expose
+ @ConfigLink(owner = BroodmotherConfig.class, field = "countdown")
+ public Position countdownPosition = new Position(10, 10, false, true);
+
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/combat/broodmother/BroodmotherSpawnAlertConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/combat/broodmother/BroodmotherSpawnAlertConfig.java
new file mode 100644
index 000000000..d0c2ccfe9
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/combat/broodmother/BroodmotherSpawnAlertConfig.java
@@ -0,0 +1,41 @@
+package at.hannibal2.skyhanni.config.features.combat.broodmother;
+
+import at.hannibal2.skyhanni.features.combat.BroodmotherFeatures;
+import at.hannibal2.skyhanni.utils.OSUtils;
+import com.google.gson.annotations.Expose;
+import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorButton;
+import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorSlider;
+import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorText;
+import io.github.notenoughupdates.moulconfig.annotations.ConfigOption;
+
+public class BroodmotherSpawnAlertConfig {
+
+ @Expose
+ @ConfigOption(name = "Alert Sound", desc = "The sound that plays for the alert.")
+ @ConfigEditorText
+ public String alertSound = "note.pling";
+
+ @Expose
+ @ConfigOption(name = "Pitch", desc = "The pitch of the alert sound.")
+ @ConfigEditorSlider(minValue = 0.5f, maxValue = 2.0f, minStep = 0.1f)
+ public float pitch = 1.0f;
+
+ @ConfigOption(name = "Test Sound", desc = "Test current sound settings.")
+ @ConfigEditorButton(buttonText = "Test")
+ public Runnable testSound = BroodmotherFeatures::playTestSound;
+
+ @Expose
+ @ConfigOption(name = "Repeat Sound", desc = "How many times the sound should be repeated.")
+ @ConfigEditorSlider(minValue = 1, maxValue = 20, minStep = 1)
+ public int repeatSound = 20;
+
+ @ConfigOption(name = "Sounds", desc = "Click to open the list of available sounds.")
+ @ConfigEditorButton(buttonText = "OPEN")
+ public Runnable sounds = () -> OSUtils.openBrowser("https://www.minecraftforum.net/forums/mapping-and-modding-java-edition/mapping-and-modding-tutorials/2213619-1-8-all-playsound-sound-arguments");
+
+ @Expose
+ @ConfigOption(name = "Text", desc = "The text with color to be displayed as the title notification.")
+ @ConfigEditorText
+ public String text = "&4Broodmother has spawned!";
+
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/combat/damageindicator/DamageIndicatorConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/combat/damageindicator/DamageIndicatorConfig.java
index 7010c7d35..ed37c396c 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/combat/damageindicator/DamageIndicatorConfig.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/combat/damageindicator/DamageIndicatorConfig.java
@@ -14,6 +14,7 @@ import java.util.Arrays;
import java.util.List;
import static at.hannibal2.skyhanni.config.features.combat.damageindicator.DamageIndicatorConfig.BossCategory.ARACHNE;
+import static at.hannibal2.skyhanni.config.features.combat.damageindicator.DamageIndicatorConfig.BossCategory.BROODMOTHER;
import static at.hannibal2.skyhanni.config.features.combat.damageindicator.DamageIndicatorConfig.BossCategory.DIANA_MOBS;
import static at.hannibal2.skyhanni.config.features.combat.damageindicator.DamageIndicatorConfig.BossCategory.GARDEN_PESTS;
import static at.hannibal2.skyhanni.config.features.combat.damageindicator.DamageIndicatorConfig.BossCategory.INFERNO_DEMONLORD;
@@ -96,6 +97,7 @@ public class DamageIndicatorConfig {
DIANA_MOBS,
SEA_CREATURES,
ARACHNE,
+ BROODMOTHER,
THE_RIFT_BOSSES,
RIFTSTALKER_BLOODFIEND,
REINDRAKE,
@@ -129,6 +131,7 @@ public class DamageIndicatorConfig {
RIFTSTALKER_BLOODFIEND("§bRiftstalker Bloodfiend", 23),
REINDRAKE("§6Reindrake", 24),
GARDEN_PESTS("§aGarden Pests", 25),
+ BROODMOTHER("§bBroodmother")
;
private final String str;
diff --git a/src/main/java/at/hannibal2/skyhanni/data/model/TabWidget.kt b/src/main/java/at/hannibal2/skyhanni/data/model/TabWidget.kt
index 523121b37..85c50528f 100644
--- a/src/main/java/at/hannibal2/skyhanni/data/model/TabWidget.kt
+++ b/src/main/java/at/hannibal2/skyhanni/data/model/TabWidget.kt
@@ -195,7 +195,7 @@ enum class TabWidget(
),
BROODMOTHER(
// language=RegExp
- "Broodmother: (?:§.)*(?<time>.*)",
+ "Broodmother: (?:§.)*(?<stage>.*)",
),
EYES_PLACED(
// language=RegExp
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) }