Merge pull request #706 from Lucwousin/a

Refactor hydra plugin
This commit is contained in:
Ganom
2019-06-23 16:06:54 -04:00
committed by GitHub
5 changed files with 148 additions and 180 deletions

View File

@@ -24,74 +24,119 @@
*/ */
package net.runelite.client.plugins.alchemicalhydra; package net.runelite.client.plugins.alchemicalhydra;
import java.awt.image.BufferedImage;
import javax.inject.Singleton; import javax.inject.Singleton;
import lombok.AccessLevel;
import lombok.Getter; import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter; import lombok.Setter;
import net.runelite.api.NPC; import net.runelite.api.NPC;
import net.runelite.api.Prayer; import net.runelite.api.Prayer;
import net.runelite.api.ProjectileID; 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 @Singleton
class Hydra class Hydra
{ {
@Getter(AccessLevel.PACKAGE)
@RequiredArgsConstructor
enum AttackStyle enum AttackStyle
{ {
MAGIC(ProjectileID.HYDRA_MAGIC, Prayer.PROTECT_FROM_MAGIC), MAGIC(ProjectileID.HYDRA_MAGIC, Prayer.PROTECT_FROM_MAGIC, SpriteID.PRAYER_PROTECT_FROM_MAGIC),
RANGED(ProjectileID.HYDRA_RANGED, Prayer.PROTECT_FROM_MISSILES); RANGED(ProjectileID.HYDRA_RANGED, Prayer.PROTECT_FROM_MISSILES, SpriteID.PRAYER_PROTECT_FROM_MISSILES);
@Getter private final int projectileID;
private int projId; private final Prayer prayer;
private final int spriteID;
@Getter @Getter(AccessLevel.NONE)
private Prayer prayer; private BufferedImage image;
AttackStyle(int projId, Prayer prayer) BufferedImage getImage(SpriteManager spriteManager)
{ {
this.projId = projId; if (image == null)
this.prayer = prayer; {
BufferedImage tmp = spriteManager.getSprite(spriteID, 0);
image = tmp == null ? null : ImageUtil.resizeImage(tmp, HydraOverlay.IMGSIZE, HydraOverlay.IMGSIZE);
}
return image;
} }
} }
@Getter private final NPC npc;
private NPC npc;
@Getter private HydraPhase phase = HydraPhase.ONE;
@Setter
private HydraPhase phase;
@Getter private int attackCount = 0;
@Setter private int nextSwitch = phase.getAttacksPerSwitch();
private int attackCount;
@Getter @Setter(AccessLevel.PACKAGE)
@Setter private int nextSpecial = 3;
private int nextSwitch;
@Getter private AttackStyle nextAttack = AttackStyle.MAGIC;
@Setter private AttackStyle lastAttack = AttackStyle.MAGIC;
private int nextSpecial;
@Getter @Setter(AccessLevel.PACKAGE)
@Setter private boolean weakened = false;
private AttackStyle nextAttack;
@Getter void changePhase(HydraPhase newPhase)
@Setter
private AttackStyle lastAttack;
@Getter
@Setter
private boolean weakened;
Hydra(NPC npc)
{ {
this.npc = npc; phase = newPhase;
this.phase = HydraPhase.ONE; nextSpecial = 3;
this.nextAttack = AttackStyle.MAGIC; attackCount = 0;
this.lastAttack = AttackStyle.MAGIC; // important, else we wouldn't switch if the first attack is ranged weakened = false;
this.nextSpecial = 3;
this.nextSwitch = phase.getAttacksPerSwitch(); if (newPhase == HydraPhase.FOUR)
this.attackCount = 0; {
this.weakened = false; 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;
} }
} }

View File

@@ -26,16 +26,12 @@ package net.runelite.client.plugins.alchemicalhydra;
import java.awt.Color; import java.awt.Color;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle; import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import net.runelite.api.Client; import net.runelite.api.Client;
import net.runelite.api.Prayer; import net.runelite.api.Prayer;
import net.runelite.api.SpriteID;
import net.runelite.client.game.SpriteManager; import net.runelite.client.game.SpriteManager;
import net.runelite.client.ui.overlay.Overlay; import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayPosition; import net.runelite.client.ui.overlay.OverlayPosition;
@@ -46,13 +42,16 @@ import net.runelite.client.ui.overlay.components.PanelComponent;
@Singleton @Singleton
class HydraOverlay extends Overlay 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 HydraPlugin plugin;
private final Client client; private final Client client;
private final SpriteManager spriteManager; private final SpriteManager spriteManager;
private final PanelComponent panelComponent = new PanelComponent(); 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 @Inject
HydraOverlay(HydraPlugin plugin, Client client, SpriteManager spriteManager) HydraOverlay(HydraPlugin plugin, Client client, SpriteManager spriteManager)
@@ -76,9 +75,8 @@ class HydraOverlay extends Overlay
} }
//Add spec overlay first, to keep it above pray //Add spec overlay first, to keep it above pray
HydraPhase phase = hydra.getPhase(); final HydraPhase phase = hydra.getPhase();
int attackCount = hydra.getAttackCount(); final int nextSpec = hydra.getNextSpecialRelative();
int nextSpec = hydra.getNextSpecial() - attackCount;
if (nextSpec <= 3) if (nextSpec <= 3)
{ {
@@ -86,37 +84,34 @@ class HydraOverlay extends Overlay
if (nextSpec == 0) if (nextSpec == 0)
{ {
specComponent.setBackgroundColor(redBgCol); specComponent.setBackgroundColor(RED_BG_COL);
} }
else if (nextSpec == 1) 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.setText(" " + (nextSpec)); //hacky way to not have to figure out how to move text
specComponent.setPreferredSize(new Dimension(40, 40)); specComponent.setPreferredSize(new Dimension(40, 40));
panelComponent.getChildren().add(specComponent); panelComponent.getChildren().add(specComponent);
} }
final Prayer nextPrayer = hydra.getNextAttack().getPrayer();
Prayer nextPrayer = hydra.getNextAttack().getPrayer(); final int nextSwitch = hydra.getNextSwitch();
Image prayImg = scaleImg(getPrayerImage(hydra.getNextAttack().getPrayer()));
int nextSwitch = hydra.getNextSwitch();
InfoBoxComponent prayComponent = new InfoBoxComponent(); InfoBoxComponent prayComponent = new InfoBoxComponent();
if (nextSwitch == 1) if (nextSwitch == 1)
{ {
prayComponent.setBackgroundColor(client.isPrayerActive(nextPrayer) ? yelBgCol : redBgCol); prayComponent.setBackgroundColor(client.isPrayerActive(nextPrayer) ? YEL_BG_COL : RED_BG_COL);
} }
else 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.setText(" " + nextSwitch);
prayComponent.setColor(Color.white); prayComponent.setColor(Color.white);
prayComponent.setPreferredSize(new Dimension(40, 40)); prayComponent.setPreferredSize(new Dimension(40, 40));
@@ -126,32 +121,4 @@ class HydraOverlay extends Overlay
panelComponent.setBorder(new Rectangle(0, 0, 0, 0)); panelComponent.setBorder(new Rectangle(0, 0, 0, 0));
return panelComponent.render(graphics2D); 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;
}
} }

View File

@@ -24,48 +24,46 @@
*/ */
package net.runelite.client.plugins.alchemicalhydra; package net.runelite.client.plugins.alchemicalhydra;
import java.awt.image.BufferedImage;
import lombok.AccessLevel;
import lombok.Getter; import lombok.Getter;
import lombok.RequiredArgsConstructor;
import net.runelite.api.AnimationID; import net.runelite.api.AnimationID;
import net.runelite.api.ProjectileID; import net.runelite.api.ProjectileID;
import net.runelite.api.SpriteID; import net.runelite.api.SpriteID;
import net.runelite.api.coords.WorldPoint; import net.runelite.api.coords.WorldPoint;
import net.runelite.client.game.SpriteManager;
import net.runelite.client.util.ImageUtil;
@Getter(AccessLevel.PACKAGE)
@RequiredArgsConstructor
enum HydraPhase 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)), 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)), 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)), 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); 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; private final int attacksPerSwitch;
@Getter
private final int deathAnim1; private final int deathAnim1;
@Getter
private final int deathAnim2; private final int deathAnim2;
@Getter
private final int specProjectileId; private final int specProjectileId;
@Getter
private final int specAnimationId; private final int specAnimationId;
@Getter @Getter(AccessLevel.NONE)
private final int specImage; private final int specImageID;
private final WorldPoint fountain;
@Getter private BufferedImage specImage;
private WorldPoint fountain;
HydraPhase(int attacksPerSwitch, int deathAnim1, int deathAnim2, int specProjectileId, int specAnimationId, int specImage, WorldPoint fountain) BufferedImage getSpecImage(SpriteManager spriteManager)
{ {
this.attacksPerSwitch = attacksPerSwitch; if (specImage == null)
this.deathAnim1 = deathAnim1; {
this.deathAnim2 = deathAnim2; BufferedImage tmp = spriteManager.getSprite(specImageID, 0);
this.specProjectileId = specProjectileId; specImage = tmp == null ? null : ImageUtil.resizeImage(tmp, HydraOverlay.IMGSIZE, HydraOverlay.IMGSIZE);
this.specAnimationId = specAnimationId; }
this.specImage = specImage;
this.fountain = fountain; return specImage;
} }
} }

View File

@@ -30,6 +30,7 @@ import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import javax.inject.Inject; import javax.inject.Inject;
import lombok.AccessLevel;
import lombok.Getter; import lombok.Getter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Actor; import net.runelite.api.Actor;
@@ -60,10 +61,10 @@ import net.runelite.client.ui.overlay.OverlayManager;
@Slf4j @Slf4j
public class HydraPlugin extends Plugin public class HydraPlugin extends Plugin
{ {
@Getter @Getter(AccessLevel.PACKAGE)
private Map<LocalPoint, Projectile> poisonProjectiles = new HashMap<>(); private Map<LocalPoint, Projectile> poisonProjectiles = new HashMap<>();
@Getter @Getter(AccessLevel.PACKAGE)
private Hydra hydra; private Hydra hydra;
private boolean inHydraInstance; private boolean inHydraInstance;
@@ -84,7 +85,7 @@ public class HydraPlugin extends Plugin
private HydraOverlay overlay; private HydraOverlay overlay;
@Inject @Inject
private HydraPoisonOverlay poisonOverlay; private HydraSceneOverlay poisonOverlay;
@Override @Override
protected void startUp() protected void startUp()
@@ -124,18 +125,16 @@ public class HydraPlugin extends Plugin
} }
return; return;
} }
NPC hydraNpc = null;
for (NPC npc : client.getNpcs()) for (NPC npc : client.getNpcs())
{ {
if (npc.getId() == NpcID.ALCHEMICAL_HYDRA) if (npc.getId() == NpcID.ALCHEMICAL_HYDRA)
{ {
hydraNpc = npc; hydra = new Hydra(npc);
break; break;
} }
} }
hydra = new Hydra(hydraNpc);
addOverlays(); addOverlays();
} }
@@ -171,13 +170,13 @@ public class HydraPlugin extends Plugin
switch (phase) switch (phase)
{ {
case ONE: case ONE:
changePhase(HydraPhase.TWO); hydra.changePhase(HydraPhase.TWO);
return; return;
case TWO: case TWO:
changePhase(HydraPhase.THREE); hydra.changePhase(HydraPhase.THREE);
return; return;
case THREE: case THREE:
changePhase(HydraPhase.FOUR); hydra.changePhase(HydraPhase.FOUR);
return; return;
case FOUR: case FOUR:
hydra = null; hydra = null;
@@ -237,9 +236,9 @@ public class HydraPlugin extends Plugin
poisonProjectiles.put(event.getPosition(), projectile); poisonProjectiles.put(event.getPosition(), projectile);
} }
else if (client.getTickCount() != lastAttackTick 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(); lastAttackTick = client.getTickCount();
} }
} }
@@ -271,53 +270,4 @@ public class HydraPlugin extends Plugin
overlayManager.remove(overlay); overlayManager.remove(overlay);
overlayManager.remove(poisonOverlay); 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());
}
}
} }

View File

@@ -45,13 +45,17 @@ import net.runelite.client.ui.overlay.OverlayLayer;
import net.runelite.client.ui.overlay.OverlayPosition; import net.runelite.client.ui.overlay.OverlayPosition;
@Singleton @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 HydraPlugin plugin;
private final Client client; private final Client client;
@Inject @Inject
public HydraPoisonOverlay(Client client, HydraPlugin plugin) public HydraSceneOverlay(Client client, HydraPlugin plugin)
{ {
setPosition(OverlayPosition.DYNAMIC); setPosition(OverlayPosition.DYNAMIC);
setLayer(OverlayLayer.UNDER_WIDGETS); setLayer(OverlayLayer.UNDER_WIDGETS);
@@ -99,9 +103,9 @@ class HydraPoisonOverlay extends Overlay
} }
graphics.setPaintMode(); graphics.setPaintMode();
graphics.setColor(new Color(255, 0, 0, 100)); graphics.setColor(RED);
graphics.draw(poisonTiles); graphics.draw(poisonTiles);
graphics.setColor(new Color(255, 0, 0, 50)); graphics.setColor(REDFILL);
graphics.fill(poisonTiles); graphics.fill(poisonTiles);
} }
@@ -133,11 +137,15 @@ class HydraPoisonOverlay extends Overlay
return; return;
} }
Color color = new Color(255, 0, 0, 100); // like Color color; // like
if (hydra.getNpc().getWorldArea().intersectsWith(new WorldArea(wp, 1, 1))) // coords if (hydra.getNpc().getWorldArea().intersectsWith(new WorldArea(wp, 1, 1))) // coords
{ // WHICH FUCKING RETARD DID X, Y, dX, dY, Z???? IT'S XYZdXdY REEEEEEEEEE { // 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); graphics.setColor(color);