diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/alchemicalhydra/Hydra.java b/runelite-client/src/main/java/net/runelite/client/plugins/alchemicalhydra/Hydra.java index ff979672a2..3b332f3589 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/alchemicalhydra/Hydra.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/alchemicalhydra/Hydra.java @@ -24,74 +24,119 @@ */ package net.runelite.client.plugins.alchemicalhydra; +import java.awt.image.BufferedImage; import javax.inject.Singleton; +import lombok.AccessLevel; import lombok.Getter; +import lombok.RequiredArgsConstructor; import lombok.Setter; import net.runelite.api.NPC; import net.runelite.api.Prayer; import net.runelite.api.ProjectileID; +import net.runelite.api.SpriteID; +import net.runelite.client.game.SpriteManager; +import net.runelite.client.util.ImageUtil; +@Getter(AccessLevel.PACKAGE) +@RequiredArgsConstructor @Singleton class Hydra { + @Getter(AccessLevel.PACKAGE) + @RequiredArgsConstructor enum AttackStyle { - MAGIC(ProjectileID.HYDRA_MAGIC, Prayer.PROTECT_FROM_MAGIC), - RANGED(ProjectileID.HYDRA_RANGED, Prayer.PROTECT_FROM_MISSILES); + MAGIC(ProjectileID.HYDRA_MAGIC, Prayer.PROTECT_FROM_MAGIC, SpriteID.PRAYER_PROTECT_FROM_MAGIC), + RANGED(ProjectileID.HYDRA_RANGED, Prayer.PROTECT_FROM_MISSILES, SpriteID.PRAYER_PROTECT_FROM_MISSILES); - @Getter - private int projId; + private final int projectileID; + private final Prayer prayer; + private final int spriteID; - @Getter - private Prayer prayer; + @Getter(AccessLevel.NONE) + private BufferedImage image; - AttackStyle(int projId, Prayer prayer) + BufferedImage getImage(SpriteManager spriteManager) { - this.projId = projId; - this.prayer = prayer; + if (image == null) + { + BufferedImage tmp = spriteManager.getSprite(spriteID, 0); + image = tmp == null ? null : ImageUtil.resizeImage(tmp, HydraOverlay.IMGSIZE, HydraOverlay.IMGSIZE); + } + + return image; } } - @Getter - private NPC npc; + private final NPC npc; - @Getter - @Setter - private HydraPhase phase; + private HydraPhase phase = HydraPhase.ONE; - @Getter - @Setter - private int attackCount; + private int attackCount = 0; + private int nextSwitch = phase.getAttacksPerSwitch(); - @Getter - @Setter - private int nextSwitch; + @Setter(AccessLevel.PACKAGE) + private int nextSpecial = 3; - @Getter - @Setter - private int nextSpecial; + private AttackStyle nextAttack = AttackStyle.MAGIC; + private AttackStyle lastAttack = AttackStyle.MAGIC; - @Getter - @Setter - private AttackStyle nextAttack; + @Setter(AccessLevel.PACKAGE) + private boolean weakened = false; - @Getter - @Setter - private AttackStyle lastAttack; - - @Getter - @Setter - private boolean weakened; - - Hydra(NPC npc) + void changePhase(HydraPhase newPhase) { - this.npc = npc; - this.phase = HydraPhase.ONE; - this.nextAttack = AttackStyle.MAGIC; - this.lastAttack = AttackStyle.MAGIC; // important, else we wouldn't switch if the first attack is ranged - this.nextSpecial = 3; - this.nextSwitch = phase.getAttacksPerSwitch(); - this.attackCount = 0; - this.weakened = false; + phase = newPhase; + nextSpecial = 3; + attackCount = 0; + weakened = false; + + if (newPhase == HydraPhase.FOUR) + { + weakened = true; + switchStyles(); + nextSwitch = phase.getAttacksPerSwitch(); + } + } + + private void switchStyles() + { + nextAttack = lastAttack == Hydra.AttackStyle.MAGIC + ? Hydra.AttackStyle.RANGED + : Hydra.AttackStyle.MAGIC; + } + + void handleAttack(int id) + { + if (id != nextAttack.getProjectileID()) + { + if (id == lastAttack.getProjectileID()) + { + // If the current attack isn't what was expected and we accidentally counted 1 too much + return; + } + + // If the current attack isn't what was expected and we should have switched prayers + switchStyles(); + nextSwitch = phase.getAttacksPerSwitch() - 1; + } + else + { + nextSwitch--; + } + + lastAttack = nextAttack; + attackCount++; + + if (nextSwitch <= 0) + { + switchStyles(); + nextSwitch = phase.getAttacksPerSwitch(); + } + } + + int getNextSpecialRelative() + { + return nextSpecial - attackCount; } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/alchemicalhydra/HydraOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/alchemicalhydra/HydraOverlay.java index 50d683c78d..e5860abcd0 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/alchemicalhydra/HydraOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/alchemicalhydra/HydraOverlay.java @@ -26,16 +26,12 @@ package net.runelite.client.plugins.alchemicalhydra; import java.awt.Color; import java.awt.Dimension; -import java.awt.Graphics; import java.awt.Graphics2D; -import java.awt.Image; import java.awt.Rectangle; -import java.awt.image.BufferedImage; import javax.inject.Inject; import javax.inject.Singleton; import net.runelite.api.Client; import net.runelite.api.Prayer; -import net.runelite.api.SpriteID; import net.runelite.client.game.SpriteManager; import net.runelite.client.ui.overlay.Overlay; import net.runelite.client.ui.overlay.OverlayPosition; @@ -46,13 +42,16 @@ import net.runelite.client.ui.overlay.components.PanelComponent; @Singleton class HydraOverlay extends Overlay { + + private static final Color RED_BG_COL = new Color(156, 0, 0, 156); + private static final Color YEL_BG_COL = new Color(200, 156, 0, 156); + private static final Color GRN_BG_COL = new Color(0, 156, 0, 156); + static final int IMGSIZE = 36; + private final HydraPlugin plugin; private final Client client; private final SpriteManager spriteManager; private final PanelComponent panelComponent = new PanelComponent(); - private static final Color redBgCol = new Color(156, 0, 0, 156); - private static final Color yelBgCol = new Color(200, 156, 0, 156); - private static final Color grnBgCol = new Color(0, 156, 0, 156); @Inject HydraOverlay(HydraPlugin plugin, Client client, SpriteManager spriteManager) @@ -76,9 +75,8 @@ class HydraOverlay extends Overlay } //Add spec overlay first, to keep it above pray - HydraPhase phase = hydra.getPhase(); - int attackCount = hydra.getAttackCount(); - int nextSpec = hydra.getNextSpecial() - attackCount; + final HydraPhase phase = hydra.getPhase(); + final int nextSpec = hydra.getNextSpecialRelative(); if (nextSpec <= 3) { @@ -86,37 +84,34 @@ class HydraOverlay extends Overlay if (nextSpec == 0) { - specComponent.setBackgroundColor(redBgCol); + specComponent.setBackgroundColor(RED_BG_COL); } else if (nextSpec == 1) { - specComponent.setBackgroundColor(yelBgCol); + specComponent.setBackgroundColor(YEL_BG_COL); } - Image specImg = scaleImg(spriteManager.getSprite(phase.getSpecImage(), 0)); - specComponent.setImage(specImg); + specComponent.setImage(phase.getSpecImage(spriteManager)); specComponent.setText(" " + (nextSpec)); //hacky way to not have to figure out how to move text specComponent.setPreferredSize(new Dimension(40, 40)); panelComponent.getChildren().add(specComponent); } - - Prayer nextPrayer = hydra.getNextAttack().getPrayer(); - Image prayImg = scaleImg(getPrayerImage(hydra.getNextAttack().getPrayer())); - int nextSwitch = hydra.getNextSwitch(); + final Prayer nextPrayer = hydra.getNextAttack().getPrayer(); + final int nextSwitch = hydra.getNextSwitch(); InfoBoxComponent prayComponent = new InfoBoxComponent(); if (nextSwitch == 1) { - prayComponent.setBackgroundColor(client.isPrayerActive(nextPrayer) ? yelBgCol : redBgCol); + prayComponent.setBackgroundColor(client.isPrayerActive(nextPrayer) ? YEL_BG_COL : RED_BG_COL); } else { - prayComponent.setBackgroundColor(client.isPrayerActive(nextPrayer) ? grnBgCol : redBgCol); + prayComponent.setBackgroundColor(client.isPrayerActive(nextPrayer) ? GRN_BG_COL : RED_BG_COL); } - prayComponent.setImage(prayImg); + prayComponent.setImage(hydra.getNextAttack().getImage(spriteManager)); prayComponent.setText(" " + nextSwitch); prayComponent.setColor(Color.white); prayComponent.setPreferredSize(new Dimension(40, 40)); @@ -126,32 +121,4 @@ class HydraOverlay extends Overlay panelComponent.setBorder(new Rectangle(0, 0, 0, 0)); return panelComponent.render(graphics2D); } - - private BufferedImage getPrayerImage(Prayer pray) - { - return pray == Prayer.PROTECT_FROM_MAGIC - ? spriteManager.getSprite(SpriteID.PRAYER_PROTECT_FROM_MAGIC, 0) - : spriteManager.getSprite(SpriteID.PRAYER_PROTECT_FROM_MISSILES, 0); - } - - private Image scaleImg(final Image img) - { - if (img == null) - { - return null; - } - final double width = img.getWidth(null); - final double height = img.getHeight(null); - final double size = 36; // Limit size to 2 as that is minimum size not causing breakage - final double scalex = size / width; - final double scaley = size / height; - final double scale = Math.min(scalex, scaley); - final int newWidth = (int) (width * scale); - final int newHeight = (int) (height * scale); - final BufferedImage scaledImage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_ARGB); - final Graphics g = scaledImage.createGraphics(); - g.drawImage(img, 0, 0, newWidth, newHeight, null); - g.dispose(); - return scaledImage; - } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/alchemicalhydra/HydraPhase.java b/runelite-client/src/main/java/net/runelite/client/plugins/alchemicalhydra/HydraPhase.java index 7f2db35e5b..4fa739e6d8 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/alchemicalhydra/HydraPhase.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/alchemicalhydra/HydraPhase.java @@ -24,48 +24,46 @@ */ package net.runelite.client.plugins.alchemicalhydra; +import java.awt.image.BufferedImage; +import lombok.AccessLevel; import lombok.Getter; +import lombok.RequiredArgsConstructor; import net.runelite.api.AnimationID; import net.runelite.api.ProjectileID; import net.runelite.api.SpriteID; import net.runelite.api.coords.WorldPoint; +import net.runelite.client.game.SpriteManager; +import net.runelite.client.util.ImageUtil; +@Getter(AccessLevel.PACKAGE) +@RequiredArgsConstructor enum HydraPhase -{ // Sorry for the autism +{ ONE(3, AnimationID.HYDRA_1_1, AnimationID.HYDRA_1_2, ProjectileID.HYDRA_POISON, 0, SpriteID.BIG_ASS_GUTHIX_SPELL, new WorldPoint(1371, 10263, 0)), TWO(3, AnimationID.HYDRA_2_1, AnimationID.HYDRA_2_2, 0, AnimationID.HYDRA_LIGHTNING, SpriteID.BIG_SPEC_TRANSFER, new WorldPoint(1371, 10272, 0)), THREE(3, AnimationID.HYDRA_3_1, AnimationID.HYDRA_3_2, 0, AnimationID.HYDRA_FIRE, SpriteID.BIG_SUPERHEAT, new WorldPoint(1362, 10272, 0)), FOUR(1, AnimationID.HYDRA_4_1, AnimationID.HYDRA_4_2, ProjectileID.HYDRA_POISON, 0, SpriteID.BIG_ASS_GUTHIX_SPELL, null); - @Getter private final int attacksPerSwitch; - - @Getter private final int deathAnim1; - - @Getter private final int deathAnim2; - - @Getter private final int specProjectileId; - - @Getter private final int specAnimationId; - @Getter - private final int specImage; + @Getter(AccessLevel.NONE) + private final int specImageID; + private final WorldPoint fountain; - @Getter - private WorldPoint fountain; + private BufferedImage specImage; - HydraPhase(int attacksPerSwitch, int deathAnim1, int deathAnim2, int specProjectileId, int specAnimationId, int specImage, WorldPoint fountain) + BufferedImage getSpecImage(SpriteManager spriteManager) { - this.attacksPerSwitch = attacksPerSwitch; - this.deathAnim1 = deathAnim1; - this.deathAnim2 = deathAnim2; - this.specProjectileId = specProjectileId; - this.specAnimationId = specAnimationId; - this.specImage = specImage; - this.fountain = fountain; + if (specImage == null) + { + BufferedImage tmp = spriteManager.getSprite(specImageID, 0); + specImage = tmp == null ? null : ImageUtil.resizeImage(tmp, HydraOverlay.IMGSIZE, HydraOverlay.IMGSIZE); + } + + return specImage; } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/alchemicalhydra/HydraPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/alchemicalhydra/HydraPlugin.java index f15e02b25d..b92b6f3875 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/alchemicalhydra/HydraPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/alchemicalhydra/HydraPlugin.java @@ -30,6 +30,7 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; import javax.inject.Inject; +import lombok.AccessLevel; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import net.runelite.api.Actor; @@ -60,10 +61,10 @@ import net.runelite.client.ui.overlay.OverlayManager; @Slf4j public class HydraPlugin extends Plugin { - @Getter + @Getter(AccessLevel.PACKAGE) private Map poisonProjectiles = new HashMap<>(); - @Getter + @Getter(AccessLevel.PACKAGE) private Hydra hydra; private boolean inHydraInstance; @@ -84,7 +85,7 @@ public class HydraPlugin extends Plugin private HydraOverlay overlay; @Inject - private HydraPoisonOverlay poisonOverlay; + private HydraSceneOverlay poisonOverlay; @Override protected void startUp() @@ -124,18 +125,16 @@ public class HydraPlugin extends Plugin } return; } - NPC hydraNpc = null; for (NPC npc : client.getNpcs()) { if (npc.getId() == NpcID.ALCHEMICAL_HYDRA) { - hydraNpc = npc; + hydra = new Hydra(npc); break; } } - hydra = new Hydra(hydraNpc); addOverlays(); } @@ -171,13 +170,13 @@ public class HydraPlugin extends Plugin switch (phase) { case ONE: - changePhase(HydraPhase.TWO); + hydra.changePhase(HydraPhase.TWO); return; case TWO: - changePhase(HydraPhase.THREE); + hydra.changePhase(HydraPhase.THREE); return; case THREE: - changePhase(HydraPhase.FOUR); + hydra.changePhase(HydraPhase.FOUR); return; case FOUR: hydra = null; @@ -237,9 +236,9 @@ public class HydraPlugin extends Plugin poisonProjectiles.put(event.getPosition(), projectile); } else if (client.getTickCount() != lastAttackTick - && (id == Hydra.AttackStyle.MAGIC.getProjId() || id == Hydra.AttackStyle.RANGED.getProjId())) + && (id == Hydra.AttackStyle.MAGIC.getProjectileID() || id == Hydra.AttackStyle.RANGED.getProjectileID())) { - handleAttack(id); + hydra.handleAttack(id); lastAttackTick = client.getTickCount(); } } @@ -271,53 +270,4 @@ public class HydraPlugin extends Plugin overlayManager.remove(overlay); overlayManager.remove(poisonOverlay); } - - private void changePhase(HydraPhase newPhase) - { - hydra.setPhase(newPhase); - hydra.setNextSpecial(3); - hydra.setAttackCount(0); - hydra.setWeakened(false); - - if (newPhase == HydraPhase.FOUR) - { - hydra.setWeakened(true); - switchStyles(); - hydra.setNextSwitch(newPhase.getAttacksPerSwitch()); - } - } - - private void switchStyles() - { - hydra.setNextAttack(hydra.getLastAttack() == Hydra.AttackStyle.MAGIC - ? Hydra.AttackStyle.RANGED - : Hydra.AttackStyle.MAGIC); - } - - private void handleAttack(int id) - { - if (id != hydra.getNextAttack().getProjId() && id != hydra.getLastAttack().getProjId()) - { // If the current attack isn't what was expected and we should have switched prayers - switchStyles(); - hydra.setNextSwitch(hydra.getPhase().getAttacksPerSwitch() - 1); - hydra.setLastAttack(hydra.getNextAttack()); - } - else if (id != hydra.getNextAttack().getProjId() && id == hydra.getLastAttack().getProjId()) - { // If the current attack isn't what was expected and we accidentally counted 1 too much - return; - } - else - { - hydra.setNextSwitch(hydra.getNextSwitch() - 1); - hydra.setLastAttack(hydra.getNextAttack()); - } - - hydra.setAttackCount(hydra.getAttackCount() + 1); - - if (hydra.getNextSwitch() <= 0) - { - switchStyles(); - hydra.setNextSwitch(hydra.getPhase().getAttacksPerSwitch()); - } - } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/alchemicalhydra/HydraPoisonOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/alchemicalhydra/HydraSceneOverlay.java similarity index 91% rename from runelite-client/src/main/java/net/runelite/client/plugins/alchemicalhydra/HydraPoisonOverlay.java rename to runelite-client/src/main/java/net/runelite/client/plugins/alchemicalhydra/HydraSceneOverlay.java index 0e72d3e399..52e02fadca 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/alchemicalhydra/HydraPoisonOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/alchemicalhydra/HydraSceneOverlay.java @@ -45,13 +45,17 @@ import net.runelite.client.ui.overlay.OverlayLayer; import net.runelite.client.ui.overlay.OverlayPosition; @Singleton -class HydraPoisonOverlay extends Overlay +class HydraSceneOverlay extends Overlay { + private static final Color GREEN = new Color(0, 255, 0, 100); + private static final Color RED = new Color(255, 0, 0, 100); + private static final Color REDFILL = new Color(255, 0, 0, 50); + private final HydraPlugin plugin; private final Client client; @Inject - public HydraPoisonOverlay(Client client, HydraPlugin plugin) + public HydraSceneOverlay(Client client, HydraPlugin plugin) { setPosition(OverlayPosition.DYNAMIC); setLayer(OverlayLayer.UNDER_WIDGETS); @@ -99,9 +103,9 @@ class HydraPoisonOverlay extends Overlay } graphics.setPaintMode(); - graphics.setColor(new Color(255, 0, 0, 100)); + graphics.setColor(RED); graphics.draw(poisonTiles); - graphics.setColor(new Color(255, 0, 0, 50)); + graphics.setColor(REDFILL); graphics.fill(poisonTiles); } @@ -133,11 +137,15 @@ class HydraPoisonOverlay extends Overlay return; } - Color color = new Color(255, 0, 0, 100); // like + Color color; // like if (hydra.getNpc().getWorldArea().intersectsWith(new WorldArea(wp, 1, 1))) // coords { // WHICH FUCKING RETARD DID X, Y, dX, dY, Z???? IT'S XYZdXdY REEEEEEEEEE - color = new Color(0, 255, 0, 100); + color = GREEN; + } + else + { + color = RED; } graphics.setColor(color);