diff options
7 files changed, 433 insertions, 8 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 518282cfe..4b853ed4e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,8 @@ #### Rift Features + Added **Rift Timer** + Show the remaining rift time, max time, percentage, and extra time changes. -+ **Rift Highlight Guide** ++ **Rift ++ Highlight Guide** + Highlight things to do in the Rift Guide. + Added **Shy Warning** (Contributed by CalMWolfs) + Shows a warning when a shy is going to steal your time. diff --git a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt index 7e2408424..64ddf43e7 100644 --- a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt +++ b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt @@ -62,6 +62,7 @@ import at.hannibal2.skyhanni.features.nether.ashfang.* import at.hannibal2.skyhanni.features.nether.reputationhelper.CrimsonIsleReputationHelper import at.hannibal2.skyhanni.features.rift.RiftTimer import at.hannibal2.skyhanni.features.rift.ShowMotesNpcSellPrice +import at.hannibal2.skyhanni.features.rift.VampireSlayerFeatures import at.hannibal2.skyhanni.features.rift.area.RiftLarva import at.hannibal2.skyhanni.features.rift.area.colosseum.BlobbercystsHighlight import at.hannibal2.skyhanni.features.rift.area.dreadfarm.RiftAgaricusCap @@ -340,6 +341,7 @@ class SkyHanniMod { loadModule(HighlightMiningCommissionMobs()) loadModule(ShowMotesNpcSellPrice()) loadModule(LivingMetalSuitProgress()) + loadModule(VampireSlayerFeatures()) loadModule(BlobbercystsHighlight()) init() diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/RiftConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/RiftConfig.java index 175a60c02..62f551490 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/RiftConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/RiftConfig.java @@ -447,6 +447,7 @@ public class RiftConfig { public static class LivingCaveConfig { + @Expose @ConfigOption(name = "Living Metal Suit Progress", desc = "") @Accordion diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/Slayer.java b/src/main/java/at/hannibal2/skyhanni/config/features/Slayer.java index 852b54970..36a4c6e3d 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/Slayer.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/Slayer.java @@ -7,7 +7,7 @@ import io.github.moulberry.moulconfig.annotations.*; public class Slayer { @Expose - @ConfigOption(name = "Enderman", desc = "") + @ConfigOption(name = "Enderman Slayer Features", desc = "") @ConfigEditorAccordion(id = 0) public boolean enderman = false; @@ -83,6 +83,162 @@ public class Slayer { public boolean blazeClearView = false; @Expose + @ConfigOption(name = "Vampire Slayer Features", desc = "") + @Accordion + public VampireSlayerConfig vampireSlayerConfig = new VampireSlayerConfig(); + + public static class VampireSlayerConfig { + + @Expose + @ConfigOption(name = "Your Boss", desc = "") + @Accordion + public OwnBoss ownBoss = new OwnBoss(); + + public static class OwnBoss { + + @Expose + @ConfigOption(name = "Highlight your boss", desc = "Highlight your own vampire slayer boss.") + @ConfigEditorBoolean + public boolean highlight = true; + + @Expose + @ConfigOption(name = "Highlight Color", desc = "What color to highlight the boss in.") + @ConfigEditorColour + public String highlightColor = "0:249:0:255:88"; + + @Expose + @ConfigOption(name = "Steak Alert", desc = "Show a title when you can steak your boss.") + @ConfigEditorBoolean + public boolean steakAlert = true; + + @Expose + @ConfigOption(name = "Twinclaws warning", desc = "Send a title when Twinclaws is about to happen.\nWork on others highlighted people boss.") + @ConfigEditorBoolean + public boolean twinClawsTitle = true; + } + + @Expose + @ConfigOption(name = "Others Boss", desc = "") + @Accordion + public OthersBoss othersBoss = new OthersBoss(); + + public static class OthersBoss { + + @Expose + @ConfigOption(name = "Highlight Others people boss", desc = "Highlight others players boss.\nYou need to hit them first.") + @ConfigEditorBoolean + public boolean highlight = true; + + @Expose + @ConfigOption(name = "Highlight Color", desc = "What color to highlight the boss in.") + @ConfigEditorColour + public String highlightColor = "0:249:0:255:88"; + + @Expose + @ConfigOption(name = "Steak Alert", desc = "Show a title when you can steak the boss.") + @ConfigEditorBoolean + public boolean steakAlert = true; + + @Expose + @ConfigOption(name = "Twinclaws warning", desc = "Send a title when Twinclaws is about to happen.") + @ConfigEditorBoolean + public boolean twinClawsTitle = true; + } + + @Expose + @ConfigOption(name = "Co-op Boss", desc = "") + @Accordion + public CoopBossHighlight coopsBossHighlight = new CoopBossHighlight(); + + public static class CoopBossHighlight { + @Expose + @ConfigOption(name = "Highlight Co-op Boss", desc = "Highlight boss of your co-op member.") + @ConfigEditorBoolean + public boolean highlight = true; + + @Expose + @ConfigOption(name = "Highlight Color", desc = "What color to highlight the boss in.") + @ConfigEditorColour + public String highlightColor = "0:249:0:255:88"; + + @Expose + @ConfigOption(name = "Co-op Members", desc = "Add your co-op member here.\n§eFormat: §7Name1,Name2,Name3") + @ConfigEditorText + public String coopMembers = ""; + + @Expose + @ConfigOption(name = "Steak Alert", desc = "Show a title when you can steak the boss.") + @ConfigEditorBoolean + public boolean steakAlert = true; + + @Expose + @ConfigOption(name = "Twinclaws warning", desc = "Send a title when Twinclaws is about to happen.") + @ConfigEditorBoolean + public boolean twinClawsTitle = true; + } + + @Expose + @ConfigOption(name = "Transparency", desc = "Choose the transparency of the color.") + @ConfigEditorSlider(minStep = 1, minValue = 1, maxValue = 250) + public int withAlpha = 80; + + @Expose + @ConfigOption(name = "See Through Blocs", desc = "Highlight even when behind others mobs/players") + @ConfigEditorBoolean + public boolean seeThrough = false; + + @Expose + @ConfigOption(name = "Low Health", desc = "Change color when the boss is below 20% health.") + @ConfigEditorBoolean + public boolean changeColorWhenCanSteak = true; + + @Expose + @ConfigOption(name = "Can use Steak Color", desc = "Color when the boss is below 20% health.") + @ConfigEditorColour + public String steakColor = "0:255:255:0:88"; + + + @Expose + @ConfigOption(name = "Blood Ichor", desc = "") + @Accordion + public BloodIchor bloodIchor = new BloodIchor(); + + public static class BloodIchor { + @Expose + @ConfigOption(name = "Highlight blood Ichor", desc = "Highlight the blood Ichor.") + @ConfigEditorBoolean + public boolean highlight = true; + + @Expose + @ConfigOption(name = "Beacon Beam", desc = "Render a beacon beam where the Blood Ichor is.") + @ConfigEditorBoolean + public boolean renderBeam = true; + + @Expose + @ConfigOption(name = "Color", desc = "Highlight color.") + @ConfigEditorColour + public String color = "0:199:100:0:88"; + } + + @Expose + @ConfigOption(name = "Killer Spring", desc = "") + @Accordion + public KillerSpring killerSpring = new KillerSpring(); + + public static class KillerSpring { + @Expose + @ConfigOption(name = "Highlight Killer Spring", desc = "Highlight the Killer Spring tower.") + @ConfigEditorBoolean + public boolean highlight = true; + + @Expose + @ConfigOption(name = "Color", desc = "Highlight color.") + @ConfigEditorColour + public String color = "0:199:100:0:88"; + } + } + + @Expose @ConfigOption(name = "Item Profit Tracker", desc = "") @Accordion public ItemProfitTracker itemProfitTracker = new ItemProfitTracker(); diff --git a/src/main/java/at/hannibal2/skyhanni/data/TitleUtils.kt b/src/main/java/at/hannibal2/skyhanni/data/TitleUtils.kt index c43511afa..d66a321b2 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/TitleUtils.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/TitleUtils.kt @@ -13,10 +13,12 @@ class TitleUtils { companion object { private var display = "" private var endTime = 0L + private var heightModifier = 1.8 - fun sendTitle(text: String, duration: Int) { + fun sendTitle(text: String, duration: Int, height: Double = 1.8) { display = "§f$text" endTime = System.currentTimeMillis() + duration + heightModifier = height } } @@ -38,7 +40,7 @@ class TitleUtils { val renderer = Minecraft.getMinecraft().fontRendererObj GlStateManager.pushMatrix() - GlStateManager.translate((width / 2).toFloat(), (height / 1.8).toFloat(), 0.0f) + GlStateManager.translate((width / 2).toFloat(), (height / heightModifier).toFloat(), 0.0f) GlStateManager.scale(4.0f, 4.0f, 4.0f) TextRenderUtils.drawStringCenteredScaledMaxWidth(display, renderer, 0f, 0f, false, 75, 0) GlStateManager.popMatrix() diff --git a/src/main/java/at/hannibal2/skyhanni/features/rift/VampireSlayerFeatures.kt b/src/main/java/at/hannibal2/skyhanni/features/rift/VampireSlayerFeatures.kt new file mode 100644 index 000000000..7b83e1487 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/rift/VampireSlayerFeatures.kt @@ -0,0 +1,248 @@ +package at.hannibal2.skyhanni.features.rift + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.data.ClickType +import at.hannibal2.skyhanni.data.TitleUtils +import at.hannibal2.skyhanni.events.EntityClickEvent +import at.hannibal2.skyhanni.events.LorenzTickEvent +import at.hannibal2.skyhanni.events.withAlpha +import at.hannibal2.skyhanni.features.rift.everywhere.RiftAPI +import at.hannibal2.skyhanni.mixins.hooks.RenderLivingEntityHelper +import at.hannibal2.skyhanni.test.GriffinUtils.drawWaypointFilled +import at.hannibal2.skyhanni.utils.EntityUtils.getAllNameTagsInRadiusWith +import at.hannibal2.skyhanni.utils.EntityUtils.hasSkullTexture +import at.hannibal2.skyhanni.utils.EntityUtils.isNPC +import at.hannibal2.skyhanni.utils.LocationUtils +import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.LorenzUtils.baseMaxHealth +import at.hannibal2.skyhanni.utils.LorenzUtils.toChromaColor +import at.hannibal2.skyhanni.utils.getLorenzVec +import at.hannibal2.skyhanni.utils.toLorenzVec +import net.minecraft.client.Minecraft +import net.minecraft.client.entity.EntityOtherPlayerMP +import net.minecraft.client.renderer.GlStateManager +import net.minecraft.entity.EntityLivingBase +import net.minecraft.entity.item.EntityArmorStand +import net.minecraftforge.client.event.RenderLivingEvent +import net.minecraftforge.client.event.RenderWorldLastEvent +import net.minecraftforge.event.entity.living.LivingDeathEvent +import net.minecraftforge.event.world.WorldEvent +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent + +class VampireSlayerFeatures { + + private val config get() = SkyHanniMod.feature.slayer.vampireSlayerConfig + private val entityList = mutableListOf<EntityLivingBase>() + private val taggedEntityList = mutableListOf<Int>() + private val username get() = LorenzUtils.getPlayerName() + private val bloodIchorTexture = + "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYzAzNDA5MjNhNmRlNDgyNWExNzY4MTNkMTMzNTAzZWZmMTg2ZGIwODk2ZTMyYjY3MDQ5MjhjMmEyYmY2ODQyMiJ9fX0=" + private val killerSpringTexture = + "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNzdmN2E3YmM4YWM4NmYyM2NhN2JmOThhZmViNzY5NjAyMjdlMTgzMmZlMjA5YTMwMjZmNmNlYjhiZGU3NGY1NCJ9fX0=" + + @SubscribeEvent + fun onTick(event: LorenzTickEvent) { + if (!isEnabled()) return + if (!event.isMod(5)) return + val start = LocationUtils.playerLocation() + if (config.ownBoss.highlight || config.othersBoss.highlight || config.coopsBossHighlight.highlight) { + Minecraft.getMinecraft().theWorld.loadedEntityList.filterIsInstance<EntityOtherPlayerMP>().forEach { + val vec = it.position.toLorenzVec() + val distance = start.distance(vec) + if (distance <= 15) + it.process() + } + } + if (config.bloodIchor.highlight || config.killerSpring.highlight) { + Minecraft.getMinecraft().theWorld.loadedEntityList.filterIsInstance<EntityArmorStand>().forEach { stand -> + val vec = stand.position.toLorenzVec() + val distance = start.distance(vec) + val isIchor = stand.hasSkullTexture(bloodIchorTexture) + if (isIchor || stand.hasSkullTexture(killerSpringTexture)) { + val color = (if (isIchor) config.bloodIchor.color else config.killerSpring.color) + .toChromaColor().withAlpha(config.withAlpha) + if (distance <= 15) { + RenderLivingEntityHelper.setEntityColor( + stand, + color + ) { isEnabled() } + if (isIchor) + entityList.add(stand) + } + } + } + } + } + + private fun EntityOtherPlayerMP.process() { + if (name != "Bloodfiend ") return + if (config.ownBoss.twinClawsTitle || config.othersBoss.twinClawsTitle || config.coopsBossHighlight.twinClawsTitle) { + getAllNameTagsInRadiusWith("TWINCLAWS").forEach { stand -> + if (".*(?:§(?:\\d|\\w))+TWINCLAWS (?:§(?:\\w|\\d))+[0-9.,]+s.*".toRegex().matches(stand.name)) { + val coopList = config.coopsBossHighlight.coopMembers.split(",").toList() + val containUser = getAllNameTagsInRadiusWith("Spawned by").any { + it.name.contains(username) + } + val containCoop = getAllNameTagsInRadiusWith("Spawned by").any { + coopList.isNotEmpty() && config.coopsBossHighlight.highlight && coopList.any { it2 -> + var contain = false + if (".*§(?:\\d|\\w)+Spawned by: §(?:\\d|\\w)(\\w*).*".toRegex().matches(it.name)) { + val name = ".*§(?:\\d|\\w)+Spawned by: §(?:\\d|\\w)(\\w*)".toRegex() + .find(it.name)?.groupValues?.get(1) + contain = it2 == name + } + contain + } + } + val shouldSendTitle = + if (containUser && config.ownBoss.twinClawsTitle) true + else if (containCoop && config.coopsBossHighlight.twinClawsTitle) true + else taggedEntityList.contains(this.entityId) && config.othersBoss.twinClawsTitle + + if (shouldSendTitle) { + TitleUtils.sendTitle("§6§lTWINCLAWS", 300, 2.6) + } + } + } + } + getAllNameTagsInRadiusWith("Spawned by").forEach { + val coopList = config.coopsBossHighlight.coopMembers.split(",").toList() + val containUser = it.name.contains(username) + val containCoop = coopList.isNotEmpty() && coopList.any { it2 -> + var contain = false + if (".*§(?:\\d|\\w)+Spawned by: §(?:\\d|\\w)(\\w*).*".toRegex().matches(it.name)) { + val name = + ".*§(?:\\d|\\w)+Spawned by: §(?:\\d|\\w)(\\w*)".toRegex().find(it.name)?.groupValues?.get(1) + contain = it2 == name + } + contain + } + val neededHealth = when (baseMaxHealth) { + 625 -> 125f // t1 + 1100 -> 220f // t2 + 1800 -> 360f // t3 + 2400 -> 480f // t4 + else -> 600f // t5 + } + if (containUser && taggedEntityList.contains(this.entityId)) { + taggedEntityList.remove(this.entityId) + } + val canUseSteak = health <= neededHealth + val ownBoss = config.ownBoss.highlight && containUser && isNPC() + val otherBoss = config.othersBoss.highlight && taggedEntityList.contains(this.entityId) && isNPC() + val coopBoss = config.coopsBossHighlight.highlight && containCoop && isNPC() + val shouldRender = if (ownBoss) true else if (otherBoss) true else coopBoss + + val color = + if (canUseSteak && config.changeColorWhenCanSteak) + config.steakColor.color() + else if (ownBoss) config.ownBoss.highlightColor.color() + else if (otherBoss) config.othersBoss.highlightColor.color() + else if (coopBoss) config.coopsBossHighlight.highlightColor.color() + else 0 + + val shouldSendSteakTitle = + if (canUseSteak && config.ownBoss.steakAlert && containUser) true + else if (canUseSteak && config.othersBoss.steakAlert && taggedEntityList.contains(this.entityId)) true + else canUseSteak && config.coopsBossHighlight.steakAlert && containCoop + + if (shouldSendSteakTitle) + TitleUtils.sendTitle("§c§lSTEAK!", 300, 2.6) + + + if (shouldRender) { + RenderLivingEntityHelper.setEntityColor(this, color) { isEnabled() } + RenderLivingEntityHelper.setNoHurtTime(this) { isEnabled() } + entityList.add(this) + } + } + } + + private fun String.color(): Int { + return toChromaColor().withAlpha(config.withAlpha) + } + + @SubscribeEvent + fun onEntityHit(event: EntityClickEvent) { + if (!isEnabled()) return + if (event.clickType != ClickType.LEFT_CLICK) return + if (event.clickedEntity !is EntityOtherPlayerMP) return + if (!event.clickedEntity.isNPC()) return + val coopList = config.coopsBossHighlight.coopMembers.split(",").toList() + event.clickedEntity.getAllNameTagsInRadiusWith("Spawned by").forEach { + val containCoop = coopList.isNotEmpty() && coopList.any { it2 -> + var contain = false + if (".*§(?:\\d|\\w)+Spawned by: §(?:\\d|\\w)(\\w*).*".toRegex().matches(it.name)) { + val name = + ".*§(?:\\d|\\w)+Spawned by: §(?:\\d|\\w)(\\w*)".toRegex().find(it.name)?.groupValues?.get(1) + contain = it2 == name + } + contain + } + if (it.name.contains(username) || containCoop) return + if (!taggedEntityList.contains(event.clickedEntity.entityId)) { + taggedEntityList.add(event.clickedEntity.entityId) + } + } + } + + @SubscribeEvent + fun onLivingDeath(event: LivingDeathEvent) { + if (!isEnabled()) return + val entity = event.entity + if (entityList.contains(entity)) { + entityList.remove(entity) + } + if (taggedEntityList.contains(entity.entityId)) { + taggedEntityList.remove(entity.entityId) + } + } + + @SubscribeEvent + fun pre(event: RenderLivingEvent.Pre<EntityOtherPlayerMP>) { + if (!isEnabled()) return + if (!config.seeThrough) return + if (entityList.contains(event.entity) && LocationUtils.canSee( + LocationUtils.playerEyeLocation(), + event.entity.getLorenzVec() + ) + ) { + GlStateManager.disableDepth() + } + } + + @SubscribeEvent + fun pre(event: RenderLivingEvent.Post<EntityOtherPlayerMP>) { + if (!isEnabled()) return + if (!config.seeThrough) return + if (entityList.contains(event.entity) && LocationUtils.canSee( + LocationUtils.playerEyeLocation(), + event.entity.getLorenzVec() + ) + ) { + GlStateManager.enableDepth() + } + } + + @SubscribeEvent + fun onWorldRender(event: RenderWorldLastEvent) { + if (!isEnabled()) return + if (config.bloodIchor.renderBeam) + entityList.filterIsInstance<EntityArmorStand>().forEach { + if (it.isEntityAlive) { + event.drawWaypointFilled( + it.position.toLorenzVec().add(0, -2, 0), config.bloodIchor.color.toChromaColor(), + beacon = true + ) + } + } + } + + @SubscribeEvent + fun onWorldChange(event: WorldEvent.Load) { + entityList.clear() + taggedEntityList.clear() + } + + fun isEnabled() = RiftAPI.inRift() +}
\ No newline at end of file diff --git a/src/main/java/at/hannibal2/skyhanni/utils/EntityUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/EntityUtils.kt index 9e095ec1e..6af83a805 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/EntityUtils.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/EntityUtils.kt @@ -3,7 +3,6 @@ package at.hannibal2.skyhanni.utils import at.hannibal2.skyhanni.utils.ItemUtils.getSkullTexture import at.hannibal2.skyhanni.utils.LorenzUtils.baseMaxHealth import net.minecraft.client.multiplayer.WorldClient -import net.minecraft.entity.EntityLiving import net.minecraft.entity.EntityLivingBase import net.minecraft.entity.item.EntityArmorStand import net.minecraft.entity.monster.EntityBlaze @@ -14,7 +13,7 @@ import net.minecraft.util.AxisAlignedBB object EntityUtils { - fun EntityLiving.hasNameTagWith( + fun EntityLivingBase.hasNameTagWith( y: Int, contains: String, debugRightEntity: Boolean = false, @@ -24,7 +23,7 @@ object EntityUtils { return getNameTagWith(y, contains, debugRightEntity, inaccuracy, debugWrongEntity) != null } - fun EntityLiving.getAllNameTagsWith( + fun EntityLivingBase.getAllNameTagsWith( y: Int, contains: String, debugRightEntity: Boolean = false, @@ -51,7 +50,23 @@ object EntityUtils { } } - fun EntityLiving.getNameTagWith( + fun EntityLivingBase.getAllNameTagsInRadiusWith( + contains: String, + radius: Double = 3.0, + ): List<EntityArmorStand> { + val center = getLorenzVec().add(0, 3, 0) + val a = center.add(-radius, -radius - 3, -radius).toBlocPos() + val b = center.add(radius, radius + 3, radius).toBlocPos() + val alignedBB = AxisAlignedBB(a, b) + val clazz = EntityArmorStand::class.java + val found = worldObj.getEntitiesWithinAABB(clazz, alignedBB) + return found.filter { + val result = it.name.contains(contains) + result + } + } + + fun EntityLivingBase.getNameTagWith( y: Int, contains: String, debugRightEntity: Boolean = false, |