vorkathhelper: add wooxwalk tile indicator, wooxwalk tick indicator, path through acid and config (#997)
* vorkathhelper: add wooxwalk tile indicator, wooxwalk tick indicator, path through acid indicator and config * vorkathhelper: fix code formatting * vorkathhelper: import formatting * vorkathhelper: fix import formatting * vorkathhelper: add config caching, fix issue where render overlays would not be removed on teleport or death * Various refactoring work.
This commit is contained in:
@@ -24,7 +24,6 @@
|
|||||||
*/
|
*/
|
||||||
package net.runelite.client.plugins.demonicgorilla;
|
package net.runelite.client.plugins.demonicgorilla;
|
||||||
|
|
||||||
import java.awt.BasicStroke;
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
@@ -43,6 +42,7 @@ import net.runelite.client.game.SkillIconManager;
|
|||||||
import net.runelite.client.ui.overlay.Overlay;
|
import net.runelite.client.ui.overlay.Overlay;
|
||||||
import net.runelite.client.ui.overlay.OverlayLayer;
|
import net.runelite.client.ui.overlay.OverlayLayer;
|
||||||
import net.runelite.client.ui.overlay.OverlayPosition;
|
import net.runelite.client.ui.overlay.OverlayPosition;
|
||||||
|
import net.runelite.client.ui.overlay.OverlayUtil;
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
public class DemonicGorillaOverlay extends Overlay
|
public class DemonicGorillaOverlay extends Overlay
|
||||||
@@ -118,31 +118,11 @@ public class DemonicGorillaOverlay extends Overlay
|
|||||||
int currentPosX = 0;
|
int currentPosX = 0;
|
||||||
for (BufferedImage icon : icons)
|
for (BufferedImage icon : icons)
|
||||||
{
|
{
|
||||||
graphics.setStroke(new BasicStroke(2));
|
OverlayUtil.setProgressIcon(graphics, point, icon, totalWidth, bgPadding, currentPosX,
|
||||||
graphics.setColor(COLOR_ICON_BACKGROUND);
|
COLOR_ICON_BACKGROUND, OVERLAY_ICON_DISTANCE, COLOR_ICON_BORDER, COLOR_ICON_BORDER_FILL);
|
||||||
graphics.fillOval(
|
|
||||||
point.getX() - totalWidth / 2 + currentPosX - bgPadding,
|
|
||||||
point.getY() - icon.getHeight() / 2 - OVERLAY_ICON_DISTANCE - bgPadding,
|
|
||||||
icon.getWidth() + bgPadding * 2,
|
|
||||||
icon.getHeight() + bgPadding * 2);
|
|
||||||
|
|
||||||
graphics.setColor(COLOR_ICON_BORDER);
|
|
||||||
graphics.drawOval(
|
|
||||||
point.getX() - totalWidth / 2 + currentPosX - bgPadding,
|
|
||||||
point.getY() - icon.getHeight() / 2 - OVERLAY_ICON_DISTANCE - bgPadding,
|
|
||||||
icon.getWidth() + bgPadding * 2,
|
|
||||||
icon.getHeight() + bgPadding * 2);
|
|
||||||
|
|
||||||
graphics.drawImage(
|
|
||||||
icon,
|
|
||||||
point.getX() - totalWidth / 2 + currentPosX,
|
|
||||||
point.getY() - icon.getHeight() / 2 - OVERLAY_ICON_DISTANCE,
|
|
||||||
null);
|
|
||||||
|
|
||||||
graphics.setColor(COLOR_ICON_BORDER_FILL);
|
|
||||||
Arc2D.Double arc = new Arc2D.Double(
|
Arc2D.Double arc = new Arc2D.Double(
|
||||||
point.getX() - totalWidth / 2 + currentPosX - bgPadding,
|
point.getX() - totalWidth / 2 + currentPosX - bgPadding,
|
||||||
point.getY() - icon.getHeight() / 2 - OVERLAY_ICON_DISTANCE - bgPadding,
|
point.getY() - (float) (icon.getHeight() / 2) - OVERLAY_ICON_DISTANCE - bgPadding,
|
||||||
icon.getWidth() + bgPadding * 2,
|
icon.getWidth() + bgPadding * 2,
|
||||||
icon.getHeight() + bgPadding * 2,
|
icon.getHeight() + bgPadding * 2,
|
||||||
90.0,
|
90.0,
|
||||||
|
|||||||
@@ -0,0 +1,173 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, https://runelitepl.us
|
||||||
|
* Copyright (c) 2019, Infinitay <https://github.com/Infinitay>
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package net.runelite.client.plugins.vorkath;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.Polygon;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import net.runelite.api.Client;
|
||||||
|
import net.runelite.api.Perspective;
|
||||||
|
import net.runelite.api.coords.LocalPoint;
|
||||||
|
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;
|
||||||
|
import net.runelite.client.ui.overlay.OverlayUtil;
|
||||||
|
|
||||||
|
public class AcidPathOverlay extends Overlay
|
||||||
|
{
|
||||||
|
private static final Color ACID_SPOTS_COLOR = Color.GREEN;
|
||||||
|
private static final Color ACID_FREE_PATH_COLOR = Color.PINK;
|
||||||
|
private static final Color WOOXWALK_ATTACK_SPOT_COLOR = Color.YELLOW;
|
||||||
|
private static final Color WOOXWALK_OUT_OF_REACH_SPOT_COLOR = Color.RED;
|
||||||
|
private static final int BAR_INDICATOR_SPACER = 5;
|
||||||
|
|
||||||
|
private final Client client;
|
||||||
|
private final VorkathPlugin plugin;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public AcidPathOverlay(final Client client, final VorkathPlugin plugin)
|
||||||
|
{
|
||||||
|
setPosition(OverlayPosition.DYNAMIC);
|
||||||
|
setLayer(OverlayLayer.ABOVE_SCENE);
|
||||||
|
|
||||||
|
this.client = client;
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Dimension render(Graphics2D graphics)
|
||||||
|
{
|
||||||
|
if (plugin.getVorkath() == null || plugin.getVorkath().getVorkath().getLocalLocation() == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (plugin.isIndicateAcidPools() && plugin.getAcidSpots() != null
|
||||||
|
&& !plugin.getAcidSpots().isEmpty())
|
||||||
|
{
|
||||||
|
for (WorldPoint acidWorldPoint : plugin.getAcidSpots())
|
||||||
|
{
|
||||||
|
LocalPoint acidLocalPoint = LocalPoint.fromWorld(client, acidWorldPoint);
|
||||||
|
if (acidLocalPoint == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
OverlayUtil.renderPolygon(graphics, Perspective.getCanvasTilePoly(client,
|
||||||
|
acidLocalPoint), ACID_SPOTS_COLOR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (plugin.isIndicateAcidFreePath() && plugin.getAcidFreePath() != null
|
||||||
|
&& !plugin.getAcidFreePath().isEmpty())
|
||||||
|
{
|
||||||
|
for (WorldPoint acidFreeWorldPoint : plugin.getAcidFreePath())
|
||||||
|
{
|
||||||
|
LocalPoint acidFreeLocalPoint = LocalPoint.fromWorld(client, acidFreeWorldPoint);
|
||||||
|
if (acidFreeLocalPoint == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
OverlayUtil.renderPolygon(graphics, Perspective.getCanvasTilePoly(client,
|
||||||
|
acidFreeLocalPoint), ACID_FREE_PATH_COLOR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (plugin.isIndicateWooxWalkPath() && plugin.getWooxWalkPath()[0] != null
|
||||||
|
&& plugin.getWooxWalkPath()[1] != null)
|
||||||
|
{
|
||||||
|
LocalPoint attackLocalPoint = LocalPoint.fromWorld(client, plugin.getWooxWalkPath()[0]);
|
||||||
|
LocalPoint outOfReachLocalPoint = LocalPoint.fromWorld(client, plugin.getWooxWalkPath()[1]);
|
||||||
|
|
||||||
|
if (attackLocalPoint != null && outOfReachLocalPoint != null)
|
||||||
|
{
|
||||||
|
OverlayUtil.renderPolygon(graphics, Perspective.getCanvasTilePoly(client,
|
||||||
|
attackLocalPoint), Color.YELLOW);
|
||||||
|
OverlayUtil.renderPolygon(graphics, Perspective.getCanvasTilePoly(client,
|
||||||
|
outOfReachLocalPoint), Color.RED);
|
||||||
|
|
||||||
|
if (plugin.isIndicateWooxWalkTick() && plugin.getWooxWalkBar() != null
|
||||||
|
&& plugin.getWooxWalkTimer() != -1)
|
||||||
|
{
|
||||||
|
int[] xpointsAttack = {
|
||||||
|
(int) (plugin.getWooxWalkBar().getX() + plugin.getWooxWalkBar().getWidth() / 2.0 + 1),
|
||||||
|
(int) (plugin.getWooxWalkBar().getX() + plugin.getWooxWalkBar().getWidth()),
|
||||||
|
(int) (plugin.getWooxWalkBar().getX() + plugin.getWooxWalkBar().getWidth()),
|
||||||
|
(int) (plugin.getWooxWalkBar().getX() + plugin.getWooxWalkBar().getWidth() / 2 + 1)
|
||||||
|
};
|
||||||
|
int[] xpointsOutOfReach = {
|
||||||
|
(int) plugin.getWooxWalkBar().getX(),
|
||||||
|
(int) (plugin.getWooxWalkBar().getX() + plugin.getWooxWalkBar().getWidth() / 2.0),
|
||||||
|
(int) (plugin.getWooxWalkBar().getX() + plugin.getWooxWalkBar().getWidth() / 2.0),
|
||||||
|
(int) plugin.getWooxWalkBar().getX()
|
||||||
|
};
|
||||||
|
int[] ypointsBoth = {
|
||||||
|
(int) plugin.getWooxWalkBar().getY(),
|
||||||
|
(int) plugin.getWooxWalkBar().getY(),
|
||||||
|
(int) (plugin.getWooxWalkBar().getY() + plugin.getWooxWalkBar().getHeight()),
|
||||||
|
(int) (plugin.getWooxWalkBar().getY() + plugin.getWooxWalkBar().getHeight())
|
||||||
|
};
|
||||||
|
Polygon wooxWalkAttack = new Polygon(xpointsAttack, ypointsBoth, 4);
|
||||||
|
Polygon wooxWalkOutOfReach = new Polygon(xpointsOutOfReach, ypointsBoth, 4);
|
||||||
|
OverlayUtil.renderPolygon(graphics, wooxWalkAttack, WOOXWALK_ATTACK_SPOT_COLOR);
|
||||||
|
OverlayUtil.renderPolygon(graphics, wooxWalkOutOfReach, WOOXWALK_OUT_OF_REACH_SPOT_COLOR);
|
||||||
|
|
||||||
|
long timeLeft = (System.currentTimeMillis() - plugin.getWooxWalkTimer()) % 1200;
|
||||||
|
double timeScale;
|
||||||
|
if (timeLeft <= 600)
|
||||||
|
{
|
||||||
|
timeScale = 1 - timeLeft / 600.0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
timeLeft -= 600;
|
||||||
|
timeScale = timeLeft / 600.0;
|
||||||
|
}
|
||||||
|
int progress = (int) Math.round(plugin.getWooxWalkBar().getWidth() * timeScale);
|
||||||
|
|
||||||
|
int[] xpointsIndicator = {
|
||||||
|
(int) (plugin.getWooxWalkBar().getX() - plugin.getWooxWalkBar().getHeight() / 2 + progress),
|
||||||
|
(int) (plugin.getWooxWalkBar().getX() + plugin.getWooxWalkBar().getHeight() / 2 + progress),
|
||||||
|
(int) plugin.getWooxWalkBar().getX() + progress
|
||||||
|
};
|
||||||
|
int[] ypointsIndicator = {
|
||||||
|
(int) (plugin.getWooxWalkBar().getY() - plugin.getWooxWalkBar().getHeight() - BAR_INDICATOR_SPACER),
|
||||||
|
(int) (plugin.getWooxWalkBar().getY() - plugin.getWooxWalkBar().getHeight() - BAR_INDICATOR_SPACER),
|
||||||
|
(int) (plugin.getWooxWalkBar().getY() - BAR_INDICATOR_SPACER)
|
||||||
|
};
|
||||||
|
Polygon indicator = new Polygon(xpointsIndicator, ypointsIndicator, 3);
|
||||||
|
OverlayUtil.renderPolygon(graphics, indicator, Color.WHITE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -38,23 +38,12 @@ public class Vorkath
|
|||||||
static final int FIRE_BALL_ATTACKS = 25;
|
static final int FIRE_BALL_ATTACKS = 25;
|
||||||
|
|
||||||
private NPC vorkath;
|
private NPC vorkath;
|
||||||
|
|
||||||
private VorkathAttack lastAttack;
|
private VorkathAttack lastAttack;
|
||||||
|
|
||||||
private Phase currentPhase;
|
private Phase currentPhase;
|
||||||
private Phase nextPhase;
|
private Phase nextPhase;
|
||||||
private Phase lastPhase;
|
private Phase lastPhase;
|
||||||
|
|
||||||
private int attacksLeft;
|
private int attacksLeft;
|
||||||
|
|
||||||
enum Phase
|
|
||||||
{
|
|
||||||
UNKNOWN,
|
|
||||||
ACID,
|
|
||||||
FIRE_BALL,
|
|
||||||
SPAWN
|
|
||||||
}
|
|
||||||
|
|
||||||
public Vorkath(NPC vorkath)
|
public Vorkath(NPC vorkath)
|
||||||
{
|
{
|
||||||
this.vorkath = vorkath;
|
this.vorkath = vorkath;
|
||||||
@@ -107,4 +96,12 @@ public class Vorkath
|
|||||||
log.debug("[Vorkath] Update! Last Phase: {}->{}, Current Phase: {}->{}, Next Phase: {}->{}, Attacks: {}->{}",
|
log.debug("[Vorkath] Update! Last Phase: {}->{}, Current Phase: {}->{}, Next Phase: {}->{}, Attacks: {}->{}",
|
||||||
oldLastPhase, this.lastPhase, oldCurrentPhase, this.currentPhase, oldNextPhase, this.nextPhase, oldAttacksLeft, this.attacksLeft);
|
oldLastPhase, this.lastPhase, oldCurrentPhase, this.currentPhase, oldNextPhase, this.nextPhase, oldAttacksLeft, this.attacksLeft);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum Phase
|
||||||
|
{
|
||||||
|
UNKNOWN,
|
||||||
|
ACID,
|
||||||
|
FIRE_BALL,
|
||||||
|
SPAWN
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -82,9 +82,6 @@ public enum VorkathAttack
|
|||||||
*/
|
*/
|
||||||
ZOMBIFIED_SPAWN(AnimationID.VORKATH_FIRE_BOMB_OR_SPAWN_ATTACK, ProjectileID.VORKATH_SPAWN_AOE);
|
ZOMBIFIED_SPAWN(AnimationID.VORKATH_FIRE_BOMB_OR_SPAWN_ATTACK, ProjectileID.VORKATH_SPAWN_AOE);
|
||||||
|
|
||||||
private final int vorkathAnimationID;
|
|
||||||
private final int projectileID;
|
|
||||||
|
|
||||||
private static final Map<Integer, VorkathAttack> VORKATH_ATTACKS;
|
private static final Map<Integer, VorkathAttack> VORKATH_ATTACKS;
|
||||||
private static final Map<Integer, VorkathAttack> VORKATH_BASIC_ATTACKS;
|
private static final Map<Integer, VorkathAttack> VORKATH_BASIC_ATTACKS;
|
||||||
|
|
||||||
@@ -113,6 +110,9 @@ public enum VorkathAttack
|
|||||||
VORKATH_BASIC_ATTACKS = builder.build();
|
VORKATH_BASIC_ATTACKS = builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final int vorkathAnimationID;
|
||||||
|
private final int projectileID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param projectileID id of projectile
|
* @param projectileID id of projectile
|
||||||
* @return {@link VorkathAttack} associated with the specified projectile
|
* @return {@link VorkathAttack} associated with the specified projectile
|
||||||
@@ -123,7 +123,7 @@ public enum VorkathAttack
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param projectileID
|
* @param projectileID id of projectile
|
||||||
* @return true if the projectile id matches a {@link VorkathAttack#getProjectileID()} within {@link VorkathAttack#VORKATH_BASIC_ATTACKS},
|
* @return true if the projectile id matches a {@link VorkathAttack#getProjectileID()} within {@link VorkathAttack#VORKATH_BASIC_ATTACKS},
|
||||||
* false otherwise
|
* false otherwise
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018, https://runelitepl.us
|
* Copyright (c) 2018, Jordan Atwood <jordan.atwood423@gmail.com>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -24,37 +24,67 @@
|
|||||||
*/
|
*/
|
||||||
package net.runelite.client.plugins.vorkath;
|
package net.runelite.client.plugins.vorkath;
|
||||||
|
|
||||||
import java.awt.Color;
|
import net.runelite.client.config.Config;
|
||||||
import java.awt.Dimension;
|
import net.runelite.client.config.ConfigGroup;
|
||||||
import java.awt.Graphics2D;
|
import net.runelite.client.config.ConfigItem;
|
||||||
import javax.inject.Inject;
|
|
||||||
import javax.inject.Singleton;
|
|
||||||
import net.runelite.client.ui.overlay.Overlay;
|
|
||||||
import net.runelite.client.ui.overlay.OverlayLayer;
|
|
||||||
import net.runelite.client.ui.overlay.OverlayPosition;
|
|
||||||
import net.runelite.client.ui.overlay.OverlayUtil;
|
|
||||||
|
|
||||||
@Singleton
|
@ConfigGroup("vorkath")
|
||||||
public class ZombifiedSpawnOverlay extends Overlay
|
public interface VorkathConfig extends Config
|
||||||
{
|
{
|
||||||
private final VorkathPlugin plugin;
|
@ConfigItem(
|
||||||
|
keyName = "indicateAcidPools",
|
||||||
@Inject
|
name = "Acid Pools",
|
||||||
public ZombifiedSpawnOverlay(final VorkathPlugin plugin)
|
description = "Indicate the acid pools",
|
||||||
|
position = 0
|
||||||
|
)
|
||||||
|
default boolean indicateAcidPools()
|
||||||
{
|
{
|
||||||
setPosition(OverlayPosition.DYNAMIC);
|
return false;
|
||||||
setLayer(OverlayLayer.ABOVE_SCENE);
|
|
||||||
this.plugin = plugin;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@ConfigItem(
|
||||||
public Dimension render(Graphics2D graphics)
|
keyName = "indicateAcidFreePath",
|
||||||
|
name = "Acid Free Path",
|
||||||
|
description = "Indicate the most efficient acid free path",
|
||||||
|
position = 1
|
||||||
|
)
|
||||||
|
default boolean indicateAcidFreePath()
|
||||||
{
|
{
|
||||||
if (plugin.getZombifiedSpawn() != null)
|
return true;
|
||||||
{
|
}
|
||||||
OverlayUtil.renderActorOverlayImage(graphics, plugin.getZombifiedSpawn(), VorkathPlugin.SPAWN, Color.green, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
@ConfigItem(
|
||||||
|
keyName = "acidFreePathMinLength",
|
||||||
|
name = "Minimum Length Acid Free Path",
|
||||||
|
description = "The minimum length of an acid free path",
|
||||||
|
position = 2,
|
||||||
|
hidden = true,
|
||||||
|
unhide = "indicateAcidFreePath"
|
||||||
|
)
|
||||||
|
default int acidFreePathLength()
|
||||||
|
{
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ConfigItem(
|
||||||
|
keyName = "indicateWooxWalkPath",
|
||||||
|
name = "WooxWalk Path",
|
||||||
|
description = "Indicate the closest WooxWalk path",
|
||||||
|
position = 3
|
||||||
|
)
|
||||||
|
default boolean indicateWooxWalkPath()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ConfigItem(
|
||||||
|
keyName = "indicateWooxWalkTick",
|
||||||
|
name = "WooxWalk Tick",
|
||||||
|
description = "Indicate on which tile to click during each game tick",
|
||||||
|
position = 4
|
||||||
|
)
|
||||||
|
default boolean indicateWooxWalkTick()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -26,7 +26,6 @@
|
|||||||
*/
|
*/
|
||||||
package net.runelite.client.plugins.vorkath;
|
package net.runelite.client.plugins.vorkath;
|
||||||
|
|
||||||
import java.awt.BasicStroke;
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
@@ -41,6 +40,8 @@ import net.runelite.api.coords.LocalPoint;
|
|||||||
import net.runelite.client.ui.overlay.Overlay;
|
import net.runelite.client.ui.overlay.Overlay;
|
||||||
import net.runelite.client.ui.overlay.OverlayLayer;
|
import net.runelite.client.ui.overlay.OverlayLayer;
|
||||||
import net.runelite.client.ui.overlay.OverlayPosition;
|
import net.runelite.client.ui.overlay.OverlayPosition;
|
||||||
|
import net.runelite.client.ui.overlay.OverlayUtil;
|
||||||
|
import net.runelite.client.util.ImageUtil;
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
public class VorkathOverlay extends Overlay
|
public class VorkathOverlay extends Overlay
|
||||||
@@ -50,6 +51,18 @@ public class VorkathOverlay extends Overlay
|
|||||||
private static final Color COLOR_ICON_BORDER_FILL = new Color(219, 175, 0, 255);
|
private static final Color COLOR_ICON_BORDER_FILL = new Color(219, 175, 0, 255);
|
||||||
private static final int OVERLAY_ICON_DISTANCE = 30;
|
private static final int OVERLAY_ICON_DISTANCE = 30;
|
||||||
private static final int OVERLAY_ICON_MARGIN = 1;
|
private static final int OVERLAY_ICON_MARGIN = 1;
|
||||||
|
private static final BufferedImage UNKNOWN;
|
||||||
|
private static final BufferedImage ACID;
|
||||||
|
private static final BufferedImage FIRE_BALL;
|
||||||
|
private static final BufferedImage SPAWN;
|
||||||
|
|
||||||
|
static
|
||||||
|
{
|
||||||
|
UNKNOWN = ImageUtil.getResourceStreamFromClass(VorkathPlugin.class, "magerange.png");
|
||||||
|
ACID = ImageUtil.getResourceStreamFromClass(VorkathPlugin.class, "acid.png");
|
||||||
|
FIRE_BALL = ImageUtil.getResourceStreamFromClass(VorkathPlugin.class, "fire_strike.png");
|
||||||
|
SPAWN = ImageUtil.getResourceStreamFromClass(VorkathPlugin.class, "ice.png");
|
||||||
|
}
|
||||||
|
|
||||||
private final Client client;
|
private final Client client;
|
||||||
private final VorkathPlugin plugin;
|
private final VorkathPlugin plugin;
|
||||||
@@ -68,9 +81,9 @@ public class VorkathOverlay extends Overlay
|
|||||||
{
|
{
|
||||||
if (plugin.getVorkath() != null)
|
if (plugin.getVorkath() != null)
|
||||||
{
|
{
|
||||||
Vorkath vorkath = plugin.getVorkath();
|
final Vorkath vorkath = plugin.getVorkath();
|
||||||
|
|
||||||
LocalPoint localLocation = vorkath.getVorkath().getLocalLocation();
|
final LocalPoint localLocation = vorkath.getVorkath().getLocalLocation();
|
||||||
if (localLocation != null)
|
if (localLocation != null)
|
||||||
{
|
{
|
||||||
Point point = Perspective.localToCanvas(client, localLocation, client.getPlane(), vorkath.getVorkath().getLogicalHeight() + 16);
|
Point point = Perspective.localToCanvas(client, localLocation, client.getPlane(), vorkath.getVorkath().getLogicalHeight() + 16);
|
||||||
@@ -78,7 +91,7 @@ public class VorkathOverlay extends Overlay
|
|||||||
{
|
{
|
||||||
point = new Point(point.getX(), point.getY());
|
point = new Point(point.getX(), point.getY());
|
||||||
|
|
||||||
BufferedImage currentPhaseIcon = getIcon(vorkath);
|
final BufferedImage currentPhaseIcon = getIcon(vorkath);
|
||||||
|
|
||||||
int totalWidth = 0;
|
int totalWidth = 0;
|
||||||
if (currentPhaseIcon != null)
|
if (currentPhaseIcon != null)
|
||||||
@@ -88,41 +101,33 @@ public class VorkathOverlay extends Overlay
|
|||||||
int bgPadding = 8;
|
int bgPadding = 8;
|
||||||
int currentPosX = 0;
|
int currentPosX = 0;
|
||||||
|
|
||||||
graphics.setStroke(new BasicStroke(2));
|
if (currentPhaseIcon == null)
|
||||||
graphics.setColor(COLOR_ICON_BACKGROUND);
|
{
|
||||||
graphics.fillOval(
|
return null;
|
||||||
point.getX() - totalWidth / 2 + currentPosX - bgPadding,
|
}
|
||||||
point.getY() - currentPhaseIcon.getHeight() / 2 - OVERLAY_ICON_DISTANCE - bgPadding,
|
|
||||||
currentPhaseIcon.getWidth() + bgPadding * 2,
|
|
||||||
currentPhaseIcon.getHeight() + bgPadding * 2);
|
|
||||||
|
|
||||||
graphics.setColor(COLOR_ICON_BORDER);
|
OverlayUtil.setProgressIcon(graphics, point, currentPhaseIcon, totalWidth, bgPadding, currentPosX,
|
||||||
graphics.drawOval(
|
COLOR_ICON_BACKGROUND, OVERLAY_ICON_DISTANCE, COLOR_ICON_BORDER, COLOR_ICON_BORDER_FILL);
|
||||||
point.getX() - totalWidth / 2 + currentPosX - bgPadding,
|
|
||||||
point.getY() - currentPhaseIcon.getHeight() / 2 - OVERLAY_ICON_DISTANCE - bgPadding,
|
|
||||||
currentPhaseIcon.getWidth() + bgPadding * 2,
|
|
||||||
currentPhaseIcon.getHeight() + bgPadding * 2);
|
|
||||||
|
|
||||||
graphics.drawImage(
|
final Arc2D.Double arc = new Arc2D.Double(
|
||||||
currentPhaseIcon,
|
|
||||||
point.getX() - totalWidth / 2 + currentPosX,
|
|
||||||
point.getY() - currentPhaseIcon.getHeight() / 2 - OVERLAY_ICON_DISTANCE,
|
|
||||||
null);
|
|
||||||
|
|
||||||
graphics.setColor(COLOR_ICON_BORDER_FILL);
|
|
||||||
Arc2D.Double arc = new Arc2D.Double(
|
|
||||||
point.getX() - totalWidth / 2 + currentPosX - bgPadding,
|
point.getX() - totalWidth / 2 + currentPosX - bgPadding,
|
||||||
point.getY() - currentPhaseIcon.getHeight() / 2 - OVERLAY_ICON_DISTANCE - bgPadding,
|
point.getY() - (float) (currentPhaseIcon.getHeight() / 2) - OVERLAY_ICON_DISTANCE - bgPadding,
|
||||||
currentPhaseIcon.getWidth() + bgPadding * 2,
|
currentPhaseIcon.getWidth() + bgPadding * 2,
|
||||||
currentPhaseIcon.getHeight() + bgPadding * 2,
|
currentPhaseIcon.getHeight() + bgPadding * 2,
|
||||||
90.0,
|
90.0,
|
||||||
-360.0 * getAttacksLeftProgress(),
|
-360.0 * getAttacksLeftProgress(),
|
||||||
Arc2D.OPEN);
|
Arc2D.OPEN
|
||||||
|
);
|
||||||
graphics.draw(arc);
|
graphics.draw(arc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (plugin.getZombifiedSpawn() != null)
|
||||||
|
{
|
||||||
|
OverlayUtil.renderActorOverlayImage(graphics, plugin.getZombifiedSpawn(), SPAWN, Color.green, 10);
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,13 +140,13 @@ public class VorkathOverlay extends Overlay
|
|||||||
switch (vorkath.getCurrentPhase())
|
switch (vorkath.getCurrentPhase())
|
||||||
{
|
{
|
||||||
case UNKNOWN:
|
case UNKNOWN:
|
||||||
return VorkathPlugin.UNKNOWN;
|
return UNKNOWN;
|
||||||
case ACID:
|
case ACID:
|
||||||
return VorkathPlugin.ACID;
|
return ACID;
|
||||||
case FIRE_BALL:
|
case FIRE_BALL:
|
||||||
return VorkathPlugin.FIRE_BALL;
|
return FIRE_BALL;
|
||||||
case SPAWN:
|
case SPAWN:
|
||||||
return VorkathPlugin.SPAWN;
|
return SPAWN;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,28 +27,47 @@
|
|||||||
package net.runelite.client.plugins.vorkath;
|
package net.runelite.client.plugins.vorkath;
|
||||||
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.Provides;
|
||||||
import com.google.inject.Singleton;
|
import com.google.inject.Singleton;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.Rectangle;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
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.Client;
|
import net.runelite.api.Client;
|
||||||
|
import net.runelite.api.GameObject;
|
||||||
import net.runelite.api.NPC;
|
import net.runelite.api.NPC;
|
||||||
import net.runelite.api.NpcID;
|
import net.runelite.api.ObjectID;
|
||||||
|
import net.runelite.api.Projectile;
|
||||||
|
import net.runelite.api.ProjectileID;
|
||||||
|
import net.runelite.api.coords.LocalPoint;
|
||||||
|
import net.runelite.api.coords.WorldPoint;
|
||||||
import net.runelite.api.events.AnimationChanged;
|
import net.runelite.api.events.AnimationChanged;
|
||||||
|
import net.runelite.api.events.ClientTick;
|
||||||
|
import net.runelite.api.events.ConfigChanged;
|
||||||
|
import net.runelite.api.events.GameObjectDespawned;
|
||||||
|
import net.runelite.api.events.GameObjectSpawned;
|
||||||
|
import net.runelite.api.events.GameTick;
|
||||||
import net.runelite.api.events.NpcDespawned;
|
import net.runelite.api.events.NpcDespawned;
|
||||||
import net.runelite.api.events.NpcSpawned;
|
import net.runelite.api.events.NpcSpawned;
|
||||||
import net.runelite.api.events.ProjectileMoved;
|
import net.runelite.api.events.ProjectileMoved;
|
||||||
|
import net.runelite.api.events.ProjectileSpawned;
|
||||||
|
import net.runelite.api.widgets.Widget;
|
||||||
|
import net.runelite.api.widgets.WidgetInfo;
|
||||||
|
import net.runelite.client.config.ConfigManager;
|
||||||
import net.runelite.client.eventbus.Subscribe;
|
import net.runelite.client.eventbus.Subscribe;
|
||||||
import net.runelite.client.plugins.Plugin;
|
import net.runelite.client.plugins.Plugin;
|
||||||
import net.runelite.client.plugins.PluginDescriptor;
|
import net.runelite.client.plugins.PluginDescriptor;
|
||||||
import net.runelite.client.plugins.PluginType;
|
import net.runelite.client.plugins.PluginType;
|
||||||
import net.runelite.client.ui.overlay.OverlayManager;
|
import net.runelite.client.ui.overlay.OverlayManager;
|
||||||
import net.runelite.client.util.ImageUtil;
|
|
||||||
import org.apache.commons.lang3.ArrayUtils;
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
|
|
||||||
@PluginDescriptor(
|
@PluginDescriptor(
|
||||||
name = "Vorkath Helper",
|
name = "Vorkath Helper",
|
||||||
description = "Count vorkath attacks, and which phase is coming next",
|
description = "Count vorkath attacks, indicate next phase, wooxwalk timer, indicate path through acid",
|
||||||
tags = {"combat", "overlay", "pve", "pvm"},
|
tags = {"combat", "overlay", "pve", "pvm"},
|
||||||
type = PluginType.PVM,
|
type = PluginType.PVM,
|
||||||
enabledByDefault = false
|
enabledByDefault = false
|
||||||
@@ -61,93 +80,133 @@ public class VorkathPlugin extends Plugin
|
|||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private Client client;
|
private Client client;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private OverlayManager overlayManager;
|
private OverlayManager overlayManager;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private VorkathOverlay overlay;
|
private VorkathOverlay overlay;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private ZombifiedSpawnOverlay SpawnOverlay;
|
private AcidPathOverlay acidPathOverlay;
|
||||||
|
@Inject
|
||||||
@Getter
|
private VorkathConfig config;
|
||||||
|
@Getter(AccessLevel.PACKAGE)
|
||||||
private Vorkath vorkath;
|
private Vorkath vorkath;
|
||||||
|
@Getter(AccessLevel.PACKAGE)
|
||||||
@Getter
|
|
||||||
private NPC zombifiedSpawn;
|
private NPC zombifiedSpawn;
|
||||||
|
@Getter(AccessLevel.PACKAGE)
|
||||||
|
private List<WorldPoint> acidSpots = new ArrayList<>();
|
||||||
|
@Getter(AccessLevel.PACKAGE)
|
||||||
|
private List<WorldPoint> acidFreePath = new ArrayList<>();
|
||||||
|
@Getter(AccessLevel.PACKAGE)
|
||||||
|
private WorldPoint[] wooxWalkPath = new WorldPoint[2];
|
||||||
|
@Getter(AccessLevel.PACKAGE)
|
||||||
|
private long wooxWalkTimer = -1;
|
||||||
|
@Getter(AccessLevel.PACKAGE)
|
||||||
|
private Rectangle wooxWalkBar;
|
||||||
|
private int lastAcidSpotsSize = 0;
|
||||||
|
// Config values
|
||||||
|
@Getter(AccessLevel.PACKAGE)
|
||||||
|
private boolean indicateAcidPools;
|
||||||
|
@Getter(AccessLevel.PACKAGE)
|
||||||
|
private boolean indicateAcidFreePath;
|
||||||
|
@Getter(AccessLevel.PACKAGE)
|
||||||
|
private boolean indicateWooxWalkPath;
|
||||||
|
@Getter(AccessLevel.PACKAGE)
|
||||||
|
private boolean indicateWooxWalkTick;
|
||||||
|
private int acidFreePathLength;
|
||||||
|
|
||||||
/**
|
@Provides
|
||||||
* The last projectile's starting movement cycle
|
VorkathConfig provideConfig(ConfigManager configManager)
|
||||||
*/
|
|
||||||
private int lastProjectileCycle;
|
|
||||||
|
|
||||||
static final BufferedImage UNKNOWN;
|
|
||||||
static final BufferedImage ACID;
|
|
||||||
static final BufferedImage FIRE_BALL;
|
|
||||||
static final BufferedImage SPAWN;
|
|
||||||
|
|
||||||
static
|
|
||||||
{
|
{
|
||||||
UNKNOWN = ImageUtil.getResourceStreamFromClass(VorkathPlugin.class, "magerange.png");
|
return configManager.getConfig(VorkathConfig.class);
|
||||||
ACID = ImageUtil.getResourceStreamFromClass(VorkathPlugin.class, "acid.png");
|
}
|
||||||
FIRE_BALL = ImageUtil.getResourceStreamFromClass(VorkathPlugin.class, "fire_strike.png");
|
|
||||||
SPAWN = ImageUtil.getResourceStreamFromClass(VorkathPlugin.class, "ice.png");
|
@Override
|
||||||
|
protected void startUp()
|
||||||
|
{
|
||||||
|
updateConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void shutDown()
|
||||||
|
{
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onConfigChanged(ConfigChanged event)
|
||||||
|
{
|
||||||
|
if (!event.getGroup().equals("vorkath"))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void onNpcSpawned(NpcSpawned event)
|
public void onNpcSpawned(NpcSpawned event)
|
||||||
{
|
{
|
||||||
if (isAtVorkath())
|
if (!isAtVorkath())
|
||||||
{
|
{
|
||||||
if (isVorkath(event.getNpc().getId()))
|
return;
|
||||||
{
|
}
|
||||||
vorkath = new Vorkath(event.getNpc());
|
|
||||||
lastProjectileCycle = -1;
|
final NPC npc = event.getNpc();
|
||||||
overlayManager.add(overlay);
|
|
||||||
}
|
if (npc.getName() == null)
|
||||||
else if (isZombifiedSpawn(event.getNpc().getId()))
|
{
|
||||||
{
|
return;
|
||||||
zombifiedSpawn = event.getNpc();
|
}
|
||||||
overlayManager.add(SpawnOverlay);
|
|
||||||
}
|
if (npc.getName().equals("Vorkath"))
|
||||||
|
{
|
||||||
|
vorkath = new Vorkath(npc);
|
||||||
|
overlayManager.add(overlay);
|
||||||
|
}
|
||||||
|
else if (npc.getName().equals("Zombified Spawn"))
|
||||||
|
{
|
||||||
|
zombifiedSpawn = npc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void onNpcDespawned(NpcDespawned event)
|
public void onNpcDespawned(NpcDespawned event)
|
||||||
{
|
{
|
||||||
if (isAtVorkath())
|
if (!isAtVorkath())
|
||||||
{
|
|
||||||
if (isVorkath(event.getNpc().getId()))
|
|
||||||
{
|
|
||||||
vorkath = null;
|
|
||||||
lastProjectileCycle = -1;
|
|
||||||
overlayManager.remove(overlay);
|
|
||||||
}
|
|
||||||
else if (isZombifiedSpawn(event.getNpc().getId()))
|
|
||||||
{
|
|
||||||
zombifiedSpawn = null;
|
|
||||||
overlayManager.remove(SpawnOverlay);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Subscribe
|
|
||||||
public void onProjectileMoved(ProjectileMoved event)
|
|
||||||
{
|
|
||||||
// Only capture initial projectile
|
|
||||||
if (!isAtVorkath() || event.getProjectile().getStartMovementCycle() == lastProjectileCycle)
|
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
VorkathAttack vorkathAttack = VorkathAttack.getVorkathAttack(event.getProjectile().getId());
|
final NPC npc = event.getNpc();
|
||||||
|
|
||||||
|
if (npc.getName() == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (npc.getName().equals("Vorkath"))
|
||||||
|
{
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
else if (npc.getName().equals("Zombified Spawn"))
|
||||||
|
{
|
||||||
|
zombifiedSpawn = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onProjectileSpawned(ProjectileSpawned event)
|
||||||
|
{
|
||||||
|
if (!isAtVorkath())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Projectile proj = event.getProjectile();
|
||||||
|
final VorkathAttack vorkathAttack = VorkathAttack.getVorkathAttack(proj.getId());
|
||||||
|
|
||||||
if (vorkathAttack != null)
|
if (vorkathAttack != null)
|
||||||
{
|
{
|
||||||
/*log.debug("[Projectile ({})] Game Tick: {}, Game Cycle: {}, Starting Cyle: {} Last Cycle: {}, Initial Projectile?: {}",
|
|
||||||
vorkathAttack, client.getTickCount(), client.getGameCycle(), event.getProjectile().getStartMovementCycle(),
|
|
||||||
lastProjectileCycle, event.getProjectile().getStartMovementCycle() == client.getGameCycle());*/
|
|
||||||
if (VorkathAttack.isBasicAttack(vorkathAttack.getProjectileID()) && vorkath.getAttacksLeft() > 0)
|
if (VorkathAttack.isBasicAttack(vorkathAttack.getProjectileID()) && vorkath.getAttacksLeft() > 0)
|
||||||
{
|
{
|
||||||
vorkath.setAttacksLeft(vorkath.getAttacksLeft() - 1);
|
vorkath.setAttacksLeft(vorkath.getAttacksLeft() - 1);
|
||||||
@@ -155,47 +214,94 @@ public class VorkathPlugin extends Plugin
|
|||||||
else if (vorkathAttack == VorkathAttack.ACID)
|
else if (vorkathAttack == VorkathAttack.ACID)
|
||||||
{
|
{
|
||||||
vorkath.updatePhase(Vorkath.Phase.ACID);
|
vorkath.updatePhase(Vorkath.Phase.ACID);
|
||||||
// Sets the phase's progress indicator to done
|
|
||||||
vorkath.setAttacksLeft(0);
|
vorkath.setAttacksLeft(0);
|
||||||
}
|
}
|
||||||
else if (vorkathAttack == VorkathAttack.FIRE_BALL)
|
else if (vorkathAttack == VorkathAttack.FIRE_BALL)
|
||||||
{
|
{
|
||||||
vorkath.updatePhase(Vorkath.Phase.FIRE_BALL);
|
vorkath.updatePhase(Vorkath.Phase.FIRE_BALL);
|
||||||
// Decrement to account for this fire ball
|
|
||||||
vorkath.setAttacksLeft(vorkath.getAttacksLeft() - 1);
|
vorkath.setAttacksLeft(vorkath.getAttacksLeft() - 1);
|
||||||
}
|
}
|
||||||
else if (vorkathAttack == VorkathAttack.FREEZE_BREATH && vorkath.getLastAttack() != VorkathAttack.ZOMBIFIED_SPAWN)
|
else if (vorkathAttack == VorkathAttack.FREEZE_BREATH && vorkath.getLastAttack() != VorkathAttack.ZOMBIFIED_SPAWN)
|
||||||
{
|
{
|
||||||
// Filters out second invisible freeze attack that is immediately after the Zombified Spawn
|
|
||||||
vorkath.updatePhase(Vorkath.Phase.SPAWN);
|
vorkath.updatePhase(Vorkath.Phase.SPAWN);
|
||||||
// Sets progress of the phase to half
|
|
||||||
vorkath.setAttacksLeft(vorkath.getAttacksLeft() - (vorkath.getAttacksLeft() / 2));
|
vorkath.setAttacksLeft(vorkath.getAttacksLeft() - (vorkath.getAttacksLeft() / 2));
|
||||||
}
|
}
|
||||||
else if (vorkathAttack == VorkathAttack.ZOMBIFIED_SPAWN || (vorkath.getLastAttack() == VorkathAttack.ZOMBIFIED_SPAWN))
|
else if (vorkathAttack == VorkathAttack.ZOMBIFIED_SPAWN || (vorkath.getLastAttack() == VorkathAttack.ZOMBIFIED_SPAWN))
|
||||||
{
|
{
|
||||||
// Also consumes the second invisible freeze attack that is immediately after the Zombified Spawn
|
|
||||||
// Sets progress of the phase to done as there are no more attacks within this phase
|
|
||||||
vorkath.setAttacksLeft(0);
|
vorkath.setAttacksLeft(0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Vorkath fired a basic attack AND there are no more attacks left, typically after phases are over
|
|
||||||
vorkath.updatePhase(vorkath.getNextPhase());
|
vorkath.updatePhase(vorkath.getNextPhase());
|
||||||
// Decrement to account for this basic attack
|
|
||||||
vorkath.setAttacksLeft(vorkath.getAttacksLeft() - 1);
|
vorkath.setAttacksLeft(vorkath.getAttacksLeft() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
log.debug("[Vorkath ({})] {}", vorkathAttack, vorkath);
|
log.debug("[Vorkath ({})] {}", vorkathAttack, vorkath);
|
||||||
vorkath.setLastAttack(vorkathAttack);
|
vorkath.setLastAttack(vorkathAttack);
|
||||||
lastProjectileCycle = event.getProjectile().getStartMovementCycle();
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onProjectileMoved(ProjectileMoved event)
|
||||||
|
{
|
||||||
|
if (!isAtVorkath())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Projectile proj = event.getProjectile();
|
||||||
|
final LocalPoint loc = event.getPosition();
|
||||||
|
|
||||||
|
if (proj.getId() == ProjectileID.VORKATH_POISON_POOL_AOE)
|
||||||
|
{
|
||||||
|
addAcidSpot(WorldPoint.fromLocal(client, loc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onGameObjectSpawned(GameObjectSpawned event)
|
||||||
|
{
|
||||||
|
if (!isAtVorkath())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final GameObject obj = event.getGameObject();
|
||||||
|
|
||||||
|
if (obj.getId() == ObjectID.ACID_POOL || obj.getId() == ObjectID.ACID_POOL_32000)
|
||||||
|
{
|
||||||
|
addAcidSpot(obj.getWorldLocation());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onGameObjectDespawned(GameObjectDespawned event)
|
||||||
|
{
|
||||||
|
if (!isAtVorkath())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final GameObject obj = event.getGameObject();
|
||||||
|
|
||||||
|
if (obj.getId() == ObjectID.ACID_POOL || obj.getId() == ObjectID.ACID_POOL_32000)
|
||||||
|
{
|
||||||
|
acidSpots.remove(obj.getWorldLocation());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void onAnimationChanged(AnimationChanged event)
|
public void onAnimationChanged(AnimationChanged event)
|
||||||
{
|
{
|
||||||
if (isAtVorkath() && vorkath != null && event.getActor().equals(vorkath.getVorkath())
|
if (!isAtVorkath())
|
||||||
&& event.getActor().getAnimation() == VorkathAttack.SLASH_ATTACK.getVorkathAnimationID())
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Actor actor = event.getActor();
|
||||||
|
|
||||||
|
if (isAtVorkath() && vorkath != null && actor.equals(vorkath.getVorkath())
|
||||||
|
&& actor.getAnimation() == VorkathAttack.SLASH_ATTACK.getVorkathAnimationID())
|
||||||
{
|
{
|
||||||
if (vorkath.getAttacksLeft() > 0)
|
if (vorkath.getAttacksLeft() > 0)
|
||||||
{
|
{
|
||||||
@@ -203,15 +309,85 @@ public class VorkathPlugin extends Plugin
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// No more attacks left, typically after phases are over
|
|
||||||
vorkath.updatePhase(vorkath.getNextPhase());
|
vorkath.updatePhase(vorkath.getNextPhase());
|
||||||
// Decrement to account for this basic attack
|
|
||||||
vorkath.setAttacksLeft(vorkath.getAttacksLeft() - 1);
|
vorkath.setAttacksLeft(vorkath.getAttacksLeft() - 1);
|
||||||
}
|
}
|
||||||
log.debug("[Vorkath (SLASH_ATTACK)] {}", vorkath);
|
log.debug("[Vorkath (SLASH_ATTACK)] {}", vorkath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onGameTick(GameTick event)
|
||||||
|
{
|
||||||
|
if (!isAtVorkath())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the acid free path every tick to account for player movement
|
||||||
|
if (this.indicateAcidFreePath && !acidSpots.isEmpty())
|
||||||
|
{
|
||||||
|
calculateAcidFreePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start the timer when the player walks into the WooxWalk zone
|
||||||
|
if (this.indicateWooxWalkPath && this.indicateWooxWalkTick && wooxWalkPath[0] != null && wooxWalkPath[1] != null)
|
||||||
|
{
|
||||||
|
final WorldPoint playerLoc = client.getLocalPlayer().getWorldLocation();
|
||||||
|
|
||||||
|
if (playerLoc.getX() == wooxWalkPath[0].getX() && playerLoc.getY() == wooxWalkPath[0].getY()
|
||||||
|
&& playerLoc.getPlane() == wooxWalkPath[0].getPlane())
|
||||||
|
{
|
||||||
|
if (wooxWalkTimer == -1)
|
||||||
|
{
|
||||||
|
wooxWalkTimer = System.currentTimeMillis() - 400;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (playerLoc.getX() == wooxWalkPath[1].getX() && playerLoc.getY() == wooxWalkPath[1].getY()
|
||||||
|
&& playerLoc.getPlane() == wooxWalkPath[1].getPlane())
|
||||||
|
{
|
||||||
|
if (wooxWalkTimer == -1)
|
||||||
|
{
|
||||||
|
wooxWalkTimer = System.currentTimeMillis() - 1000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (wooxWalkTimer != -1)
|
||||||
|
{
|
||||||
|
wooxWalkTimer = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
private void onClientTick(ClientTick event)
|
||||||
|
{
|
||||||
|
if (acidSpots.size() != lastAcidSpotsSize)
|
||||||
|
{
|
||||||
|
if (acidSpots.size() == 0)
|
||||||
|
{
|
||||||
|
overlayManager.remove(acidPathOverlay);
|
||||||
|
acidFreePath.clear();
|
||||||
|
Arrays.fill(wooxWalkPath, null);
|
||||||
|
wooxWalkTimer = -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (this.indicateAcidFreePath)
|
||||||
|
{
|
||||||
|
calculateAcidFreePath();
|
||||||
|
}
|
||||||
|
if (this.indicateWooxWalkPath)
|
||||||
|
{
|
||||||
|
calculateWooxWalkPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
overlayManager.add(acidPathOverlay);
|
||||||
|
}
|
||||||
|
|
||||||
|
lastAcidSpotsSize = acidSpots.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true if the player is in the Vorkath region, false otherwise
|
* @return true if the player is in the Vorkath region, false otherwise
|
||||||
*/
|
*/
|
||||||
@@ -220,28 +396,209 @@ public class VorkathPlugin extends Plugin
|
|||||||
return ArrayUtils.contains(client.getMapRegions(), VORKATH_REGION);
|
return ArrayUtils.contains(client.getMapRegions(), VORKATH_REGION);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private void addAcidSpot(WorldPoint acidSpotLocation)
|
||||||
* @param npcID
|
|
||||||
* @return true if the npc is Vorkath, false otherwise
|
|
||||||
*/
|
|
||||||
private boolean isVorkath(int npcID)
|
|
||||||
{
|
{
|
||||||
// Could be done with a a simple name check instead...
|
if (!acidSpots.contains(acidSpotLocation))
|
||||||
return npcID == NpcID.VORKATH ||
|
{
|
||||||
npcID == NpcID.VORKATH_8058 ||
|
acidSpots.add(acidSpotLocation);
|
||||||
npcID == NpcID.VORKATH_8059 ||
|
}
|
||||||
npcID == NpcID.VORKATH_8060 ||
|
|
||||||
npcID == NpcID.VORKATH_8061;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private void calculateAcidFreePath()
|
||||||
* @param npcID
|
|
||||||
* @return true if the npc is a Zombified Spawn, otherwise false
|
|
||||||
*/
|
|
||||||
private boolean isZombifiedSpawn(int npcID)
|
|
||||||
{
|
{
|
||||||
// Could be done with a a simple name check instead...
|
acidFreePath.clear();
|
||||||
return npcID == NpcID.ZOMBIFIED_SPAWN ||
|
|
||||||
npcID == NpcID.ZOMBIFIED_SPAWN_8063;
|
final int[][][] directions = {
|
||||||
|
{
|
||||||
|
{0, 1}, {0, -1} // Positive and negative Y
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{1, 0}, {-1, 0} // Positive and negative X
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
List<WorldPoint> bestPath = new ArrayList<>();
|
||||||
|
double bestClicksRequired = 99;
|
||||||
|
|
||||||
|
final WorldPoint playerLoc = client.getLocalPlayer().getWorldLocation();
|
||||||
|
final WorldPoint vorkLoc = vorkath.getVorkath().getWorldLocation();
|
||||||
|
final int maxX = vorkLoc.getX() + 14;
|
||||||
|
final int minX = vorkLoc.getX() - 8;
|
||||||
|
final int maxY = vorkLoc.getY() - 1;
|
||||||
|
final int minY = vorkLoc.getY() - 8;
|
||||||
|
|
||||||
|
// Attempt to search an acid free path, beginning at a location
|
||||||
|
// adjacent to the player's location (including diagonals)
|
||||||
|
for (int x = -1; x < 2; x++)
|
||||||
|
{
|
||||||
|
for (int y = -1; y < 2; y++)
|
||||||
|
{
|
||||||
|
final WorldPoint baseLocation = new WorldPoint(playerLoc.getX() + x,
|
||||||
|
playerLoc.getY() + y, playerLoc.getPlane());
|
||||||
|
|
||||||
|
if (acidSpots.contains(baseLocation) || baseLocation.getY() < minY || baseLocation.getY() > maxY)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search in X and Y direction
|
||||||
|
for (int d = 0; d < directions.length; d++)
|
||||||
|
{
|
||||||
|
// Calculate the clicks required to start walking on the path
|
||||||
|
double currentClicksRequired = Math.abs(x) + Math.abs(y);
|
||||||
|
if (currentClicksRequired < 2)
|
||||||
|
{
|
||||||
|
currentClicksRequired += Math.abs(y * directions[d][0][0]) + Math.abs(x * directions[d][0][1]);
|
||||||
|
}
|
||||||
|
if (d == 0)
|
||||||
|
{
|
||||||
|
// Prioritize a path in the X direction (sideways)
|
||||||
|
currentClicksRequired += 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<WorldPoint> currentPath = new ArrayList<>();
|
||||||
|
currentPath.add(baseLocation);
|
||||||
|
|
||||||
|
// Positive X (first iteration) or positive Y (second iteration)
|
||||||
|
for (int i = 1; i < 25; i++)
|
||||||
|
{
|
||||||
|
final WorldPoint testingLocation = new WorldPoint(baseLocation.getX() + i * directions[d][0][0],
|
||||||
|
baseLocation.getY() + i * directions[d][0][1], baseLocation.getPlane());
|
||||||
|
|
||||||
|
if (acidSpots.contains(testingLocation) || testingLocation.getY() < minY || testingLocation.getY() > maxY
|
||||||
|
|| testingLocation.getX() < minX || testingLocation.getX() > maxX)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentPath.add(testingLocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Negative X (first iteration) or positive Y (second iteration)
|
||||||
|
for (int i = 1; i < 25; i++)
|
||||||
|
{
|
||||||
|
final WorldPoint testingLocation = new WorldPoint(baseLocation.getX() + i * directions[d][1][0],
|
||||||
|
baseLocation.getY() + i * directions[d][1][1], baseLocation.getPlane());
|
||||||
|
|
||||||
|
if (acidSpots.contains(testingLocation) || testingLocation.getY() < minY || testingLocation.getY() > maxY
|
||||||
|
|| testingLocation.getX() < minX || testingLocation.getX() > maxX)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentPath.add(testingLocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentPath.size() >= this.acidFreePathLength && currentClicksRequired < bestClicksRequired
|
||||||
|
|| (currentClicksRequired == bestClicksRequired && currentPath.size() > bestPath.size()))
|
||||||
|
{
|
||||||
|
bestPath = currentPath;
|
||||||
|
bestClicksRequired = currentClicksRequired;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bestClicksRequired != 99)
|
||||||
|
{
|
||||||
|
acidFreePath = bestPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void calculateWooxWalkPath()
|
||||||
|
{
|
||||||
|
wooxWalkTimer = -1;
|
||||||
|
|
||||||
|
updateWooxWalkBar();
|
||||||
|
|
||||||
|
final WorldPoint playerLoc = client.getLocalPlayer().getWorldLocation();
|
||||||
|
final WorldPoint vorkLoc = vorkath.getVorkath().getWorldLocation();
|
||||||
|
final int maxX = vorkLoc.getX() + 14;
|
||||||
|
final int minX = vorkLoc.getX() - 8;
|
||||||
|
final int baseX = playerLoc.getX();
|
||||||
|
final int baseY = vorkLoc.getY() - 5;
|
||||||
|
final int middleX = vorkLoc.getX() + 3;
|
||||||
|
|
||||||
|
// Loop through the arena tiles in the x-direction and
|
||||||
|
// alternate between positive and negative x direction
|
||||||
|
for (int i = 0; i < 50; i++)
|
||||||
|
{
|
||||||
|
// Make sure we always choose the spot closest to
|
||||||
|
// the middle of the arena
|
||||||
|
int directionRemainder = 0;
|
||||||
|
if (playerLoc.getX() < middleX)
|
||||||
|
{
|
||||||
|
directionRemainder = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int deviation = (int) Math.floor(i / 2.0);
|
||||||
|
if (i % 2 == directionRemainder)
|
||||||
|
{
|
||||||
|
deviation = -deviation;
|
||||||
|
}
|
||||||
|
|
||||||
|
final WorldPoint attackLocation = new WorldPoint(baseX + deviation, baseY, playerLoc.getPlane());
|
||||||
|
final WorldPoint outOfRangeLocation = new WorldPoint(baseX + deviation, baseY - 1, playerLoc.getPlane());
|
||||||
|
|
||||||
|
if (acidSpots.contains(attackLocation) || acidSpots.contains(outOfRangeLocation)
|
||||||
|
|| attackLocation.getX() < minX || attackLocation.getX() > maxX)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
wooxWalkPath[0] = attackLocation;
|
||||||
|
wooxWalkPath[1] = outOfRangeLocation;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateWooxWalkBar()
|
||||||
|
{
|
||||||
|
// Update the WooxWalk tick indicator's dimensions
|
||||||
|
// based on the canvas dimensions
|
||||||
|
final Widget exp = client.getWidget(WidgetInfo.EXPERIENCE_TRACKER);
|
||||||
|
|
||||||
|
if (exp == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Rectangle screen = exp.getBounds();
|
||||||
|
|
||||||
|
int width = (int) Math.floor(screen.getWidth() / 2.0);
|
||||||
|
if (width % 2 == 1)
|
||||||
|
{
|
||||||
|
width++;
|
||||||
|
}
|
||||||
|
int height = (int) Math.floor(width / 20.0);
|
||||||
|
if (height % 2 == 1)
|
||||||
|
{
|
||||||
|
height++;
|
||||||
|
}
|
||||||
|
final int x = (int) Math.floor(screen.getX() + width / 2.0);
|
||||||
|
final int y = (int) Math.floor(screen.getY() + screen.getHeight() - 2 * height);
|
||||||
|
wooxWalkBar = new Rectangle(x, y, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateConfig()
|
||||||
|
{
|
||||||
|
this.indicateAcidPools = config.indicateAcidPools();
|
||||||
|
this.indicateAcidFreePath = config.indicateAcidFreePath();
|
||||||
|
this.indicateWooxWalkPath = config.indicateWooxWalkPath();
|
||||||
|
this.indicateWooxWalkTick = config.indicateWooxWalkTick();
|
||||||
|
this.acidFreePathLength = config.acidFreePathLength();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void reset()
|
||||||
|
{
|
||||||
|
overlayManager.remove(overlay);
|
||||||
|
overlayManager.remove(acidPathOverlay);
|
||||||
|
vorkath = null;
|
||||||
|
acidSpots.clear();
|
||||||
|
acidFreePath.clear();
|
||||||
|
Arrays.fill(wooxWalkPath, null);
|
||||||
|
wooxWalkTimer = -1;
|
||||||
|
zombifiedSpawn = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -393,4 +393,30 @@ public class OverlayUtil
|
|||||||
OverlayUtil.drawStrokeAndFillPoly(graphics, color, outlineWidth, outlineAlpha, fillAlpha, tilePoly);
|
OverlayUtil.drawStrokeAndFillPoly(graphics, color, outlineWidth, outlineAlpha, fillAlpha, tilePoly);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void setProgressIcon(Graphics2D graphics, Point point, BufferedImage currentPhaseIcon, int totalWidth, int bgPadding, int currentPosX, Color colorIconBackground, int overlayIconDistance, Color colorIconBorder, Color colorIconBorderFill)
|
||||||
|
{
|
||||||
|
graphics.setStroke(new BasicStroke(2));
|
||||||
|
graphics.setColor(colorIconBackground);
|
||||||
|
graphics.fillOval(
|
||||||
|
point.getX() - totalWidth / 2 + currentPosX - bgPadding,
|
||||||
|
point.getY() - currentPhaseIcon.getHeight() / 2 - overlayIconDistance - bgPadding,
|
||||||
|
currentPhaseIcon.getWidth() + bgPadding * 2,
|
||||||
|
currentPhaseIcon.getHeight() + bgPadding * 2);
|
||||||
|
|
||||||
|
graphics.setColor(colorIconBorder);
|
||||||
|
graphics.drawOval(
|
||||||
|
point.getX() - totalWidth / 2 + currentPosX - bgPadding,
|
||||||
|
point.getY() - currentPhaseIcon.getHeight() / 2 - overlayIconDistance - bgPadding,
|
||||||
|
currentPhaseIcon.getWidth() + bgPadding * 2,
|
||||||
|
currentPhaseIcon.getHeight() + bgPadding * 2);
|
||||||
|
|
||||||
|
graphics.drawImage(
|
||||||
|
currentPhaseIcon,
|
||||||
|
point.getX() - totalWidth / 2 + currentPosX,
|
||||||
|
point.getY() - currentPhaseIcon.getHeight() / 2 - overlayIconDistance,
|
||||||
|
null);
|
||||||
|
|
||||||
|
graphics.setColor(colorIconBorderFill);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user