aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/at/hannibal2/skyhanni/features
diff options
context:
space:
mode:
authorILike2WatchMemes <ilike2watchmemes@gmail.com>2024-09-12 02:31:14 +0200
committerGitHub <noreply@github.com>2024-09-12 02:31:14 +0200
commitb2d1c22d4baebc6eaf9eef823b11fa9d1801ced1 (patch)
treec50c9326f59faf1ad13a0fe5719508dd66213b8f /src/main/java/at/hannibal2/skyhanni/features
parent5459fc8aa33915e8d4be0c538dbb19a5e80d29db (diff)
downloadskyhanni-b2d1c22d4baebc6eaf9eef823b11fa9d1801ced1.tar.gz
skyhanni-b2d1c22d4baebc6eaf9eef823b11fa9d1801ced1.tar.bz2
skyhanni-b2d1c22d4baebc6eaf9eef823b11fa9d1801ced1.zip
Feature: Zombie Shootout QOL (#2497)
Diffstat (limited to 'src/main/java/at/hannibal2/skyhanni/features')
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/event/carnival/CarnivalZombieShootout.kt164
1 files changed, 164 insertions, 0 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/carnival/CarnivalZombieShootout.kt b/src/main/java/at/hannibal2/skyhanni/features/event/carnival/CarnivalZombieShootout.kt
new file mode 100644
index 000000000..cae5cbda1
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/event/carnival/CarnivalZombieShootout.kt
@@ -0,0 +1,164 @@
+package at.hannibal2.skyhanni.features.event.carnival
+
+import at.hannibal2.skyhanni.SkyHanniMod
+import at.hannibal2.skyhanni.events.GuiRenderEvent
+import at.hannibal2.skyhanni.events.LorenzChatEvent
+import at.hannibal2.skyhanni.events.LorenzRenderWorldEvent
+import at.hannibal2.skyhanni.events.ServerBlockChangeEvent
+import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule
+import at.hannibal2.skyhanni.utils.EntityUtils
+import at.hannibal2.skyhanni.utils.LorenzUtils
+import at.hannibal2.skyhanni.utils.LorenzVec
+import at.hannibal2.skyhanni.utils.RegexUtils.matches
+import at.hannibal2.skyhanni.utils.RenderUtils
+import at.hannibal2.skyhanni.utils.RenderUtils.draw3DLine
+import at.hannibal2.skyhanni.utils.RenderUtils.drawHitbox
+import at.hannibal2.skyhanni.utils.RenderUtils.drawWaypointFilled
+import at.hannibal2.skyhanni.utils.RenderUtils.exactPlayerEyeLocation
+import at.hannibal2.skyhanni.utils.RenderUtils.renderRenderable
+import at.hannibal2.skyhanni.utils.SimpleTimeMark
+import at.hannibal2.skyhanni.utils.StringUtils.removeColor
+import at.hannibal2.skyhanni.utils.renderables.Renderable
+import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern
+import net.minecraft.entity.monster.EntityZombie
+import net.minecraft.init.Blocks
+import net.minecraft.item.ItemStack
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import java.awt.Color
+import kotlin.time.Duration.Companion.seconds
+
+@SkyHanniModule
+object CarnivalZombieShootout {
+
+ private val config get() = SkyHanniMod.feature.event.carnival.zombieShootout
+
+ private data class Lamp(var pos: LorenzVec, var time: SimpleTimeMark)
+ private data class Updates(var zombie: SimpleTimeMark, var content: SimpleTimeMark)
+
+ private var lastUpdate = Updates(SimpleTimeMark.farPast(), SimpleTimeMark.farPast())
+
+ private var content = Renderable.horizontalContainer(listOf())
+ private var drawZombies = mapOf<EntityZombie, ZombieType>()
+ private var lamp: Lamp? = null
+ private var started = false
+
+ private val patternGroup = RepoPattern.group("event.carnival")
+
+ /**
+ * REGEX-TEST: [NPC] Carnival Cowboy: Good luck, pal!
+ */
+ private val startPattern by patternGroup.pattern(
+ "shootout.start",
+ "\\[NPC] Carnival Cowboy: Good luck, pal!",
+ )
+
+ /**
+ * REGEX-TEST: Zombie Shootout
+ */
+ private val endPattern by patternGroup.pattern(
+ "shootout.end",
+ " {29}Zombie Shootout",
+ )
+
+ enum class ZombieType(val points: Int, val helmet: String, val color: Color) {
+ LEATHER(30, "Leather Cap", Color(165, 42, 42)), //Brown
+ IRON(50, "Iron Helmet", Color(192, 192, 192)), //Silver
+ GOLD(80, "Golden Helmet", Color(255, 215, 0)), //Gold
+ DIAMOND(120, "Diamond Helmet", Color(185, 242, 255)) //Diamond
+ }
+
+ @SubscribeEvent
+ fun onRenderWorld(event: LorenzRenderWorldEvent) {
+ if (!isEnabled() || !started || (!config.coloredHitboxes && !config.coloredLines)) return
+
+ lamp?.let {
+ if (config.coloredLines) event.draw3DLine(event.exactPlayerEyeLocation(), it.pos.add(0.0, 0.5, 0.0), Color.RED, 3, false)
+ if (config.coloredHitboxes) event.drawWaypointFilled(it.pos, Color.RED, minimumAlpha = 1.0f)
+ }
+
+ if (!config.coloredHitboxes) return
+
+ if (lastUpdate.zombie.passedSince() >= 0.25.seconds) {
+ val nearbyZombies = EntityUtils.getEntitiesNextToPlayer<EntityZombie>(50.0).mapNotNull { zombie ->
+ if (zombie.health <= 0) return@mapNotNull null
+ val armor = zombie.getCurrentArmor(3) ?: return@mapNotNull null
+ val type = toType(armor) ?: return@mapNotNull null
+ zombie to type
+ }.toMap()
+
+ drawZombies = nearbyZombies.filterValues { it == nearbyZombies.values.maxByOrNull { it.points } }
+ lastUpdate.zombie = SimpleTimeMark.now()
+ }
+
+ for ((zombie, type) in drawZombies) {
+ val entity = EntityUtils.getEntityByID(zombie.entityId) ?: continue
+
+ event.drawHitbox(
+ entity.entityBoundingBox.expand(0.1, 0.05, 0.0).offset(0.0, 0.05, 0.0),
+ lineWidth = 3,
+ type.color,
+ depth = false,
+ )
+ }
+ }
+
+ @SubscribeEvent
+ fun onRenderOverlay(event: GuiRenderEvent.GuiOverlayRenderEvent) {
+ if (!isEnabled() || !started || !config.lampTimer) return
+
+ val time = lamp?.time ?: return
+
+ val lamp = ItemStack(Blocks.redstone_lamp)
+ val timer = 6.seconds - (SimpleTimeMark.now() - time)
+ val prefix = when (timer) {
+ in 4.seconds..6.seconds -> "§a"
+ in 2.seconds..4.seconds -> "§e"
+ else -> "§c"
+ }
+
+ if (lastUpdate.content.passedSince() >= 0.1.seconds) {
+ content = Renderable.horizontalContainer(
+ listOf(
+ Renderable.itemStack(lamp),
+ Renderable.string("§6Disappears in $prefix${timer}"),
+ ),
+ spacing = 1,
+ verticalAlign = RenderUtils.VerticalAlignment.CENTER,
+ )
+ lastUpdate.content = SimpleTimeMark.now()
+ }
+
+ config.lampPosition.renderRenderable(content, posLabel = "Lantern Timer")
+ }
+
+ @SubscribeEvent
+ fun onBlockChange(event: ServerBlockChangeEvent) {
+ if (!isEnabled() || !started) return
+
+ val old = event.old
+ val new = event.new
+
+ lamp = when {
+ old == "redstone_lamp" && new == "lit_redstone_lamp" -> Lamp(event.location, SimpleTimeMark.now())
+ old == "lit_redstone_lamp" && new == "redstone_lamp" -> null
+ else -> lamp
+ }
+ }
+
+ @SubscribeEvent
+ fun onChat(event: LorenzChatEvent) {
+ if (!isEnabled()) return
+
+ val message = event.message.removeColor()
+
+ if (startPattern.matches(message)) {
+ started = true
+ } else if (endPattern.matches(message)) {
+ started = false
+ }
+ }
+
+ private fun toType(item: ItemStack) = ZombieType.entries.find { it.helmet == item.displayName }
+
+ private fun isEnabled() = config.enabled && LorenzUtils.skyBlockArea == "Carnival"
+}