Alch hydra: Improve poison overlay, add defence overlay, bugfixes (#129)
* Alch hydra: Improve poison overlay, add defence overlay, bugfixes * Hydra: use WorldArea instead of npc poly tile or whatever it was
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, https://runelitepl.us
|
||||
* Copyright (c) 2019, Lucas <https://github.com/lucwousin>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -27,6 +27,7 @@ package net.runelite.client.plugins.alchemicalhydra;
|
||||
import javax.inject.Singleton;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import net.runelite.api.NPC;
|
||||
import net.runelite.api.Prayer;
|
||||
import net.runelite.api.ProjectileID;
|
||||
|
||||
@@ -51,6 +52,9 @@ class Hydra
|
||||
}
|
||||
}
|
||||
|
||||
@Getter
|
||||
private NPC npc;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private HydraPhase phase;
|
||||
@@ -75,12 +79,19 @@ class Hydra
|
||||
@Setter
|
||||
private AttackStyle lastAttack;
|
||||
|
||||
Hydra()
|
||||
@Getter
|
||||
@Setter
|
||||
private boolean weakened;
|
||||
|
||||
Hydra(NPC npc)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, https://runelitepl.us
|
||||
* Copyright (c) 2019, Lucas <https://github.com/lucwousin>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, https://runelitepl.us
|
||||
* Copyright (c) 2019, Lucas <https://github.com/lucwousin>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -28,33 +28,37 @@ import lombok.Getter;
|
||||
import net.runelite.api.AnimationID;
|
||||
import net.runelite.api.ProjectileID;
|
||||
import net.runelite.api.SpriteID;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
|
||||
enum HydraPhase
|
||||
{
|
||||
ONE(3, AnimationID.HYDRA_1_1, AnimationID.HYDRA_1_2, ProjectileID.HYDRA_POISON, 0, SpriteID.BIG_ASS_GUTHIX_SPELL),
|
||||
TWO(3, AnimationID.HYDRA_2_1, AnimationID.HYDRA_2_2, 0, AnimationID.HYDRA_LIGHTNING, SpriteID.BIG_SPEC_TRANSFER),
|
||||
THREE(3, AnimationID.HYDRA_3_1, AnimationID.HYDRA_3_2, 0, AnimationID.HYDRA_FIRE, SpriteID.BIG_SUPERHEAT),
|
||||
FOUR(1, AnimationID.HYDRA_4_1, AnimationID.HYDRA_4_2, ProjectileID.HYDRA_POISON, 0, SpriteID.BIG_ASS_GUTHIX_SPELL);
|
||||
{ // 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 int attacksPerSwitch;
|
||||
private final int attacksPerSwitch;
|
||||
|
||||
@Getter
|
||||
private int deathAnim1;
|
||||
private final int deathAnim1;
|
||||
|
||||
@Getter
|
||||
private int deathAnim2;
|
||||
private final int deathAnim2;
|
||||
|
||||
@Getter
|
||||
private int specProjectileId;
|
||||
private final int specProjectileId;
|
||||
|
||||
@Getter
|
||||
private int specAnimationId;
|
||||
private final int specAnimationId;
|
||||
|
||||
@Getter
|
||||
private int specImage;
|
||||
private final int specImage;
|
||||
|
||||
HydraPhase(int attacksPerSwitch, int deathAnim1, int deathAnim2, int specProjectileId, int specAnimationId, int specImage)
|
||||
@Getter
|
||||
private WorldPoint fountain;
|
||||
|
||||
HydraPhase(int attacksPerSwitch, int deathAnim1, int deathAnim2, int specProjectileId, int specAnimationId, int specImage, WorldPoint fountain)
|
||||
{
|
||||
this.attacksPerSwitch = attacksPerSwitch;
|
||||
this.deathAnim1 = deathAnim1;
|
||||
@@ -62,5 +66,6 @@ enum HydraPhase
|
||||
this.specProjectileId = specProjectileId;
|
||||
this.specAnimationId = specAnimationId;
|
||||
this.specImage = specImage;
|
||||
this.fountain = fountain;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, https://runelitepl.us
|
||||
* Copyright (c) 2019, Lucas <https://github.com/lucwousin>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -25,17 +25,22 @@
|
||||
package net.runelite.client.plugins.alchemicalhydra;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.inject.Inject;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.Actor;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.NPC;
|
||||
import net.runelite.api.NpcID;
|
||||
import net.runelite.api.Projectile;
|
||||
import net.runelite.api.coords.LocalPoint;
|
||||
import net.runelite.api.events.AnimationChanged;
|
||||
import net.runelite.api.events.ChatMessage;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.api.events.NpcSpawned;
|
||||
import net.runelite.api.events.ProjectileMoved;
|
||||
@@ -55,14 +60,13 @@ import net.runelite.client.ui.overlay.OverlayManager;
|
||||
public class HydraPlugin extends Plugin
|
||||
{
|
||||
@Getter
|
||||
private HashSet<LocalPoint> poisonPoints = new HashSet<>();
|
||||
private Map<LocalPoint, Projectile> poisonProjectiles = new HashMap<>();
|
||||
|
||||
@Getter
|
||||
private Hydra hydra;
|
||||
|
||||
private boolean inHydraInstance;
|
||||
private int lastAttackTick;
|
||||
private int lastPoisonTick;
|
||||
|
||||
private static final int[] HYDRA_REGIONS = {
|
||||
5279, 5280,
|
||||
@@ -86,7 +90,7 @@ public class HydraPlugin extends Plugin
|
||||
{
|
||||
inHydraInstance = checkArea();
|
||||
lastAttackTick = -1;
|
||||
poisonPoints.clear();
|
||||
poisonProjectiles.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -94,7 +98,7 @@ public class HydraPlugin extends Plugin
|
||||
{
|
||||
inHydraInstance = false;
|
||||
hydra = null;
|
||||
poisonPoints.clear();
|
||||
poisonProjectiles.clear();
|
||||
removeOverlays();
|
||||
lastAttackTick = -1;
|
||||
}
|
||||
@@ -109,18 +113,29 @@ public class HydraPlugin extends Plugin
|
||||
|
||||
inHydraInstance = checkArea();
|
||||
|
||||
if (inHydraInstance)
|
||||
if (!inHydraInstance)
|
||||
{
|
||||
hydra = new Hydra();
|
||||
log.debug("Entered hydra instance");
|
||||
addOverlays();
|
||||
}
|
||||
else if (hydra != null)
|
||||
|
||||
if (hydra != null)
|
||||
{
|
||||
removeOverlays();
|
||||
hydra = null;
|
||||
log.debug("Left hydra instance");
|
||||
}
|
||||
return;
|
||||
}
|
||||
NPC hydraNpc = null;
|
||||
|
||||
for (NPC npc : client.getNpcs())
|
||||
{
|
||||
if (npc.getId() == NpcID.ALCHEMICAL_HYDRA)
|
||||
{
|
||||
hydraNpc = npc;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
hydra = new Hydra(hydraNpc);
|
||||
addOverlays();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
@@ -131,8 +146,7 @@ public class HydraPlugin extends Plugin
|
||||
return;
|
||||
}
|
||||
|
||||
hydra = new Hydra();
|
||||
log.debug("Hydra spawned");
|
||||
hydra = new Hydra(event.getNpc());
|
||||
addOverlays();
|
||||
}
|
||||
|
||||
@@ -148,47 +162,56 @@ public class HydraPlugin extends Plugin
|
||||
|
||||
HydraPhase phase = hydra.getPhase();
|
||||
|
||||
// Using the first animation sometimes fucks shit up, so just use 2
|
||||
if ( /* actor.getAnimation() == phase.getDeathAnim1() || */ actor.getAnimation() == phase.getDeathAnim2())
|
||||
if (actor.getAnimation() == phase.getDeathAnim2() &&
|
||||
phase != HydraPhase.THREE // Else log's gonna say "Tried some weird shit"
|
||||
|| actor.getAnimation() == phase.getDeathAnim1() &&
|
||||
phase == HydraPhase.THREE) // We want the pray to switch ye ok ty
|
||||
{
|
||||
switch (phase)
|
||||
{
|
||||
case ONE:
|
||||
changePhase(HydraPhase.TWO);
|
||||
log.debug("Hydra phase 2");
|
||||
hydra.setWeakened(false);
|
||||
return;
|
||||
case TWO:
|
||||
changePhase(HydraPhase.THREE);
|
||||
log.debug("Hydra phase 3");
|
||||
hydra.setWeakened(false);
|
||||
return;
|
||||
case THREE:
|
||||
changePhase(HydraPhase.FOUR);
|
||||
log.debug("Hydra phase 4");
|
||||
return;
|
||||
case FOUR:
|
||||
hydra = null;
|
||||
poisonPoints.clear();
|
||||
log.debug("Hydra dead");
|
||||
poisonProjectiles.clear();
|
||||
removeOverlays();
|
||||
return;
|
||||
default:
|
||||
log.debug("Tried some weird shit");
|
||||
break;
|
||||
}
|
||||
|
||||
if (actor.getAnimation() == phase.getDeathAnim1() && phase == HydraPhase.THREE)
|
||||
{
|
||||
changePhase(HydraPhase.FOUR);
|
||||
}
|
||||
}
|
||||
|
||||
else if (actor.getAnimation() == phase.getSpecAnimationId() && phase.getSpecAnimationId() != 0)
|
||||
{
|
||||
hydra.setNextSpecial(hydra.getNextSpecial() + 9);
|
||||
}
|
||||
|
||||
if (!poisonPoints.isEmpty() && lastPoisonTick + 10 < client.getTickCount())
|
||||
if (poisonProjectiles.isEmpty())
|
||||
{
|
||||
poisonPoints.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
Set<LocalPoint> exPoisonProjectiles = new HashSet<>();
|
||||
for (Map.Entry<LocalPoint, Projectile> entry : poisonProjectiles.entrySet())
|
||||
{
|
||||
if (entry.getValue().getEndCycle() < client.getGameCycle())
|
||||
{
|
||||
exPoisonProjectiles.add(entry.getKey());
|
||||
}
|
||||
}
|
||||
for (LocalPoint toRemove : exPoisonProjectiles)
|
||||
{
|
||||
poisonProjectiles.remove(toRemove);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,11 +226,11 @@ public class HydraPlugin extends Plugin
|
||||
|
||||
Projectile projectile = event.getProjectile();
|
||||
int id = projectile.getId();
|
||||
|
||||
if (hydra.getPhase().getSpecProjectileId() != 0 && hydra.getPhase().getSpecProjectileId() == id)
|
||||
{
|
||||
poisonPoints.add(event.getPosition());
|
||||
poisonProjectiles.put(event.getPosition(), projectile);
|
||||
hydra.setNextSpecial(hydra.getNextSpecial() + 9);
|
||||
lastPoisonTick = client.getTickCount();
|
||||
}
|
||||
else if (client.getTickCount() != lastAttackTick
|
||||
&& (id == Hydra.AttackStyle.MAGIC.getProjId() || id == Hydra.AttackStyle.RANGED.getProjId()))
|
||||
@@ -217,6 +240,17 @@ public class HydraPlugin extends Plugin
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onChatMessage(ChatMessage event)
|
||||
{
|
||||
if (!event.getMessage().equals("The chemicals neutralise the Alchemical Hydra's defences!"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
hydra.setWeakened(true);
|
||||
}
|
||||
|
||||
private boolean checkArea()
|
||||
{
|
||||
return Arrays.equals(client.getMapRegions(), HYDRA_REGIONS) && client.isInInstancedRegion();
|
||||
@@ -255,15 +289,25 @@ public class HydraPlugin extends Plugin
|
||||
|
||||
private void handleAttack(int id)
|
||||
{
|
||||
hydra.setNextSwitch(hydra.getNextSwitch() - 1);
|
||||
hydra.setAttackCount(hydra.getAttackCount() + 1);
|
||||
hydra.setLastAttack(hydra.getNextAttack());
|
||||
|
||||
if (id != hydra.getNextAttack().getProjId())
|
||||
{
|
||||
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 (hydra.getNextSwitch() <= 0)
|
||||
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());
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, https://runelitepl.us
|
||||
* Copyright (c) 2019, Lucas <https://github.com/lucwousin>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -29,12 +29,16 @@ import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Polygon;
|
||||
import java.awt.geom.Area;
|
||||
import java.util.HashSet;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import net.runelite.api.Client;
|
||||
import static net.runelite.api.Perspective.getCanvasTileAreaPoly;
|
||||
import net.runelite.api.Projectile;
|
||||
import net.runelite.api.coords.LocalPoint;
|
||||
import net.runelite.api.coords.WorldArea;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import net.runelite.client.ui.overlay.Overlay;
|
||||
import net.runelite.client.ui.overlay.OverlayLayer;
|
||||
import net.runelite.client.ui.overlay.OverlayPosition;
|
||||
@@ -57,29 +61,85 @@ class HydraPoisonOverlay extends Overlay
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
final HashSet<LocalPoint> initialPoints = plugin.getPoisonPoints();
|
||||
Area poisonTiles = new Area();
|
||||
for (LocalPoint point : initialPoints)
|
||||
{
|
||||
Polygon poly = getCanvasTileAreaPoly(client, point, 3);
|
||||
if (poly == null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
Hydra hydra = plugin.getHydra();
|
||||
final Map<LocalPoint, Projectile> poisonProjectiles = plugin.getPoisonProjectiles();
|
||||
|
||||
poisonTiles.add(new Area(poly));
|
||||
if (!poisonProjectiles.isEmpty())
|
||||
{
|
||||
drawPoisonArea(graphics, poisonProjectiles);
|
||||
}
|
||||
|
||||
if (poisonTiles.isEmpty())
|
||||
if (hydra.getPhase().getFountain() != null)
|
||||
{
|
||||
return null;
|
||||
drawFountain(graphics, hydra);
|
||||
}
|
||||
graphics.setPaintMode();
|
||||
graphics.setColor(new Color(255, 0, 0, 75));
|
||||
graphics.draw(poisonTiles);
|
||||
graphics.setColor(new Color(255, 0, 0, 30));
|
||||
graphics.fill(poisonTiles);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void drawPoisonArea(Graphics2D graphics, Map<LocalPoint, Projectile> poisonProjectiles)
|
||||
{
|
||||
Area poisonTiles = new Area();
|
||||
|
||||
for (Map.Entry<LocalPoint, Projectile> entry : poisonProjectiles.entrySet())
|
||||
{
|
||||
if (entry.getValue().getEndCycle() < client.getGameCycle())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
LocalPoint point = entry.getKey();
|
||||
Polygon poly = getCanvasTileAreaPoly(client, point, 3);
|
||||
|
||||
if (poly != null)
|
||||
{
|
||||
poisonTiles.add(new Area(poly));
|
||||
}
|
||||
}
|
||||
|
||||
graphics.setPaintMode();
|
||||
graphics.setColor(new Color(255, 0, 0, 100));
|
||||
graphics.draw(poisonTiles);
|
||||
graphics.setColor(new Color(255, 0, 0, 50));
|
||||
graphics.fill(poisonTiles);
|
||||
}
|
||||
|
||||
private void drawFountain(Graphics2D graphics, Hydra hydra)
|
||||
{
|
||||
Collection<WorldPoint> fountainWorldPoint = WorldPoint.toLocalInstance(client, hydra.getPhase().getFountain()); // thanks
|
||||
if (fountainWorldPoint.size() > 1) // for
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
WorldPoint wp = null;
|
||||
for (WorldPoint p : fountainWorldPoint) // this
|
||||
{
|
||||
wp = p;
|
||||
}
|
||||
|
||||
LocalPoint fountainPoint = wp == null ? null : LocalPoint.fromWorld(client, wp); // trash
|
||||
|
||||
if (fountainPoint == null || hydra.isWeakened()) // I
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
final Polygon poly = getCanvasTileAreaPoly(client, fountainPoint, 3); // don't
|
||||
|
||||
if (poly == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Color color = new Color(255, 0, 0, 100); // like
|
||||
|
||||
if (hydra.getNpc().getWorldArea().intersectsWith(new WorldArea(wp.getX() - 1, wp.getY() - 1, 3, 3, wp.getPlane()))) // coords
|
||||
{ // WHICH FUCKING RETARD DID X, Y, dX, dY, Z???? IT'S XYZdXdY REEEEEEEEEE
|
||||
color = new Color(0, 255, 0, 100);
|
||||
}
|
||||
|
||||
graphics.setColor(color);
|
||||
graphics.draw(poly);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user