inferno: add multiple jad support, prayer indicator, healer indicator (#1392)

* inferno: add multiple jads support, add healer indicators, add new prayer indicators

* inferno: add config entries

* inferno: reformatting

* inferno: refactoring

* inferno: refactoring
This commit is contained in:
Alexander
2019-08-20 01:57:07 +02:00
committed by Ganom
parent aa4b505fe2
commit 3946471568
7 changed files with 375 additions and 145 deletions

View File

@@ -28,12 +28,79 @@ import java.awt.Color;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
import net.runelite.client.config.Stub;
@ConfigGroup("inferno")
public interface InfernoConfig extends Config
{
@ConfigItem(
position = 0,
keyName = "prayer",
name = "Prayer",
description = ""
)
default Stub prayer()
{
return new Stub();
}
@ConfigItem(
position = 1,
keyName = "Prayer Helper",
name = "Prayer Helper",
description = "Indicates the correct prayer"
)
default boolean showPrayerHelp()
{
return true;
}
@ConfigItem(
position = 2,
keyName = "prayerHelperMode",
name = "Prayer Helper Mode",
description = "Display prayer indicator in the prayer tab or in the bottom right corner of the screen"
)
default InfernoPrayerOverlayMode prayerOverlayMode()
{
return InfernoPrayerOverlayMode.PRAYER_TAB;
}
@ConfigItem(
position = 3,
keyName = "descendingBoxes",
name = "Descending Boxes",
description = "Draws timing boxes above the prayer icons, as if you were playing Piano Tiles"
)
default boolean descendingBoxes()
{
return true;
}
@ConfigItem(
position = 4,
keyName = "indicateWhenPrayingCorrectly",
name = "Indicate When Praying Correctly",
description = "Indicate the correct prayer, even if you are already praying that prayer"
)
default boolean indicateWhenPrayingCorrectly()
{
return false;
}
@ConfigItem(
position = 5,
keyName = "monsters",
name = "Monsters",
description = ""
)
default Stub monsters()
{
return new Stub();
}
@ConfigItem(
position = 6,
keyName = "Nibbler Overlay",
name = "Nibbler Overlay",
description = "Shows if there are any Nibblers left"
@@ -44,18 +111,29 @@ public interface InfernoConfig extends Config
}
@ConfigItem(
position = 1,
keyName = "Prayer Helper",
name = "Prayer Helper",
description = "Tells you what to flick in how many ticks"
position = 7,
keyName = "indicateActiveHealers",
name = "Indicate Active Healers",
description = "Indicate healers that are still healing Jad"
)
default boolean showPrayerHelp()
default boolean indicateActiveHealers()
{
return false;
return true;
}
@ConfigItem(
position = 2,
position = 8,
keyName = "waves",
name = "Waves",
description = ""
)
default Stub waves()
{
return new Stub();
}
@ConfigItem(
position = 9,
keyName = "waveDisplay",
name = "Wave display",
description = "Shows monsters that will spawn on the selected wave(s)."
@@ -66,7 +144,7 @@ public interface InfernoConfig extends Config
}
@ConfigItem(
position = 3,
position = 10,
keyName = "getWaveOverlayHeaderColor",
name = "Wave Header",
description = "Color for Wave Header"
@@ -77,7 +155,7 @@ public interface InfernoConfig extends Config
}
@ConfigItem(
position = 4,
position = 11,
keyName = "getWaveTextColor",
name = "Wave Text Color",
description = "Color for Wave Texts"

View File

@@ -1,81 +0,0 @@
/*
* Copyright (c) 2019, Jacky <liangj97@gmail.com>
* 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.inferno;
import java.awt.Dimension;
import java.awt.Graphics2D;
import javax.inject.Inject;
import javax.inject.Singleton;
import net.runelite.api.Client;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.components.PanelComponent;
import net.runelite.client.ui.overlay.components.table.TableAlignment;
import net.runelite.client.ui.overlay.components.table.TableComponent;
@Singleton
public class InfernoInfobox extends Overlay
{
private final Client client;
private final InfernoPlugin plugin;
private final PanelComponent panelComponent = new PanelComponent();
@Inject
public InfernoInfobox(final Client client, final InfernoPlugin plugin)
{
this.client = client;
this.plugin = plugin;
setPosition(OverlayPosition.TOP_LEFT);
}
@Override
public Dimension render(Graphics2D graphics)
{
if (!plugin.isShowPrayerHelp() || client.getMapRegions()[0] != 9043)
{
return null;
}
panelComponent.getChildren().clear();
TableComponent tableComponent = new TableComponent();
tableComponent.setColumnAlignments(TableAlignment.LEFT, TableAlignment.RIGHT);
for (int i = plugin.getPriorityNPC().length; i > 0; i--)
{
if (plugin.getPriorityNPC()[i - 1] == null)
{
tableComponent.addRow(Integer.toString(i), "-");
}
else
{
tableComponent.addRow(plugin.getPriorityNPC()[i - 1].getName(), plugin.getPriorityNPC()[i - 1].getAttackstyle().getName());
}
}
panelComponent.getChildren().add(tableComponent);
return panelComponent.render(graphics);
}
}

View File

@@ -24,30 +24,63 @@
*/
package net.runelite.client.plugins.inferno;
import lombok.AccessLevel;
import lombok.Getter;
import net.runelite.api.AnimationID;
import net.runelite.api.NPC;
import net.runelite.api.Prayer;
public enum InfernoJadAttack
@Getter(AccessLevel.PACKAGE)
public class InfernoJad
{
MAGIC(AnimationID.JALTOK_JAD_MAGE_ATTACK, Prayer.PROTECT_FROM_MAGIC),
RANGE(AnimationID.JALTOK_JAD_RANGE_ATTACK, Prayer.PROTECT_FROM_MISSILES);
private static final int TICKS_AFTER_ANIMATION = 4;
private final int animation;
private final Prayer prayer;
private NPC npc;
private Attack nextAttack;
private int ticksTillNextAttack;
InfernoJadAttack(final int animation, final Prayer prayer)
InfernoJad(NPC npc)
{
this.animation = animation;
this.prayer = prayer;
this.npc = npc;
nextAttack = null;
ticksTillNextAttack = -1;
}
public int getAnimation()
void updateNextAttack(Attack nextAttack)
{
return animation;
this.nextAttack = nextAttack;
this.ticksTillNextAttack = TICKS_AFTER_ANIMATION;
}
public Prayer getPrayer()
void gameTick()
{
return prayer;
if (ticksTillNextAttack < 0)
{
return;
}
this.ticksTillNextAttack--;
if (ticksTillNextAttack < 0)
{
nextAttack = null;
}
}
@Getter(AccessLevel.PACKAGE)
enum Attack
{
MAGIC(AnimationID.JALTOK_JAD_MAGE_ATTACK, Prayer.PROTECT_FROM_MAGIC),
RANGE(AnimationID.JALTOK_JAD_RANGE_ATTACK, Prayer.PROTECT_FROM_MISSILES);
private final int animation;
private final Prayer prayer;
Attack(final int animation, final Prayer prayer)
{
this.animation = animation;
this.prayer = prayer;
}
}
}

View File

@@ -62,7 +62,28 @@ public class InfernoJadOverlay extends Overlay
@Override
public Dimension render(Graphics2D graphics)
{
final InfernoJadAttack attack = plugin.getAttack();
if (!plugin.isShowPrayerHelp() || (plugin.getPrayerOverlayMode() != InfernoPrayerOverlayMode.BOTTOM_RIGHT
&& plugin.getPrayerOverlayMode() != InfernoPrayerOverlayMode.BOTH))
{
return null;
}
InfernoJad.Attack attack = null;
int leastTicks = 999;
for (InfernoJad jad : plugin.getJads())
{
if (jad.getNextAttack() == null || jad.getTicksTillNextAttack() < 1)
{
continue;
}
if (jad.getTicksTillNextAttack() < leastTicks)
{
leastTicks = jad.getTicksTillNextAttack();
attack = jad.getNextAttack();
}
}
if (attack == null)
{
@@ -80,9 +101,9 @@ public class InfernoJadOverlay extends Overlay
return imagePanelComponent.render(graphics);
}
private BufferedImage getPrayerImage(InfernoJadAttack attack)
private BufferedImage getPrayerImage(InfernoJad.Attack attack)
{
final int prayerSpriteID = attack == InfernoJadAttack.MAGIC ? SpriteID.PRAYER_PROTECT_FROM_MAGIC : SpriteID.PRAYER_PROTECT_FROM_MISSILES;
final int prayerSpriteID = attack == InfernoJad.Attack.MAGIC ? SpriteID.PRAYER_PROTECT_FROM_MAGIC : SpriteID.PRAYER_PROTECT_FROM_MISSILES;
return spriteManager.getSprite(prayerSpriteID, 0);
}
}

View File

@@ -29,8 +29,8 @@ import java.awt.Color;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import javax.annotation.Nullable;
import javax.inject.Inject;
import javax.inject.Singleton;
import lombok.AccessLevel;
@@ -86,7 +86,7 @@ public class InfernoPlugin extends Plugin
private InfernoJadOverlay jadOverlay;
@Inject
private InfernoInfobox infernoInfobox;
private InfernoPrayerOverlay prayerOverlay;
@Inject
private InfernoNibblerOverlay nibblerOverlay;
@@ -101,40 +101,46 @@ public class InfernoPlugin extends Plugin
private int currentWave = -1;
@Getter(AccessLevel.PACKAGE)
private Map<NPC, InfernoNPC> monsters;
private final Map<NPC, InfernoNPC> monsters = new HashMap<>();
@Getter(AccessLevel.PACKAGE)
private Map<Integer, ArrayList<InfernoNPC>> monsterCurrentAttackMap;
private final Map<Integer, ArrayList<InfernoNPC>> monsterCurrentAttackMap = new HashMap<>(6);
@Getter(AccessLevel.PACKAGE)
private List<NPC> nibblers;
private final List<NPC> nibblers = new ArrayList<>();
@Getter(AccessLevel.PACKAGE)
private InfernoNPC[] priorityNPC;
private final InfernoNPC[] priorityNPC = new InfernoNPC[4];
@Getter(AccessLevel.PACKAGE)
@Nullable
private InfernoJadAttack attack;
private final List<InfernoJad> jads = new ArrayList<>();
private NPC jad;
@Getter(AccessLevel.PACKAGE)
private final List<NPC> activeHealers = new ArrayList<>();
@Getter
private long lastTick;
@Getter(AccessLevel.PACKAGE)
private int currentWaveNumber;
private final List<Actor> waveMonsters;
public InfernoPlugin()
{
waveMonsters = new ArrayList<>();
}
private final List<Actor> waveMonsters = new ArrayList<>();
@Getter(AccessLevel.PACKAGE)
private boolean displayNibblerOverlay;
@Getter(AccessLevel.PACKAGE)
private boolean showPrayerHelp;
@Getter(AccessLevel.PACKAGE)
private InfernoPrayerOverlayMode prayerOverlayMode;
private InfernoWaveDisplayMode waveDisplay;
private Color getWaveOverlayHeaderColor;
private Color getWaveTextColor;
@Getter(AccessLevel.PACKAGE)
private boolean descendingBoxes;
@Getter(AccessLevel.PACKAGE)
private boolean indicateWhenPrayingCorrectly;
@Getter(AccessLevel.PACKAGE)
private boolean indicateActiveHealers;
@Provides
InfernoConfig provideConfig(ConfigManager configManager)
@@ -153,7 +159,6 @@ public class InfernoPlugin extends Plugin
if (isInInferno())
{
overlayManager.add(infernoOverlay);
overlayManager.add(infernoInfobox);
overlayManager.add(nibblerOverlay);
if (this.waveDisplay != InfernoWaveDisplayMode.NONE)
@@ -162,21 +167,16 @@ public class InfernoPlugin extends Plugin
}
overlayManager.add(jadOverlay);
overlayManager.add(prayerOverlay);
}
waveOverlay.setWaveHeaderColor(this.getWaveOverlayHeaderColor);
waveOverlay.setWaveTextColor(this.getWaveTextColor);
monsters = new HashMap<>();
monsterCurrentAttackMap = new HashMap<>(6);
for (int i = 1; i <= 6; i++)
{
monsterCurrentAttackMap.put(i, new ArrayList<>());
}
nibblers = new ArrayList<>();
priorityNPC = new InfernoNPC[4];
}
@Override
@@ -184,14 +184,11 @@ public class InfernoPlugin extends Plugin
{
eventBus.unregister(this);
overlayManager.remove(infernoInfobox);
overlayManager.remove(infernoOverlay);
overlayManager.remove(nibblerOverlay);
overlayManager.remove(waveOverlay);
overlayManager.remove(jadOverlay);
jad = null;
attack = null;
monsters = null;
overlayManager.remove(prayerOverlay);
currentWaveNumber = -1;
}
@@ -256,7 +253,7 @@ public class InfernoPlugin extends Plugin
if (id == NpcID.JALTOKJAD || id == NpcID.JALTOKJAD_7704)
{
jad = event.getNpc();
jads.add(new InfernoJad(npc));
}
final Actor actor = event.getActor();
@@ -286,11 +283,17 @@ public class InfernoPlugin extends Plugin
nibblers.remove(npc);
}
if (jad == event.getNpc())
final ListIterator<InfernoJad> iter = jads.listIterator();
while (iter.hasNext())
{
jad = null;
attack = null;
final InfernoJad possibleJad = iter.next();
if (possibleJad.getNpc() == npc)
{
iter.remove();
}
}
final Actor actor = event.getActor();
if (actor != null)
{
@@ -308,17 +311,16 @@ public class InfernoPlugin extends Plugin
if (!isInInferno())
{
currentWaveNumber = -1;
overlayManager.remove(infernoInfobox);
overlayManager.remove(infernoOverlay);
overlayManager.remove(nibblerOverlay);
overlayManager.remove(waveOverlay);
overlayManager.remove(jadOverlay);
overlayManager.remove(prayerOverlay);
}
else if (currentWaveNumber == -1)
{
currentWaveNumber = 1;
overlayManager.add(infernoOverlay);
overlayManager.add(infernoInfobox);
overlayManager.add(nibblerOverlay);
if (this.waveDisplay != InfernoWaveDisplayMode.NONE)
@@ -327,6 +329,7 @@ public class InfernoPlugin extends Plugin
}
overlayManager.add(jadOverlay);
overlayManager.add(prayerOverlay);
}
}
@@ -355,6 +358,24 @@ public class InfernoPlugin extends Plugin
clearMapAndPriority();
lastTick = System.currentTimeMillis();
for (InfernoJad jad : jads)
{
jad.gameTick();
}
activeHealers.clear();
for (NPC npc : client.getNpcs())
{
if (npc.getId() != NpcID.YTHURKOT_7701 || npc.getInteracting() == client.getLocalPlayer())
{
continue;
}
activeHealers.add(npc);
}
for (InfernoNPC monster : monsters.values())
{
calculateDistanceToPlayer(monster);
@@ -417,18 +438,26 @@ public class InfernoPlugin extends Plugin
private void onAnimationChanged(final AnimationChanged event)
{
if (event.getActor() != jad)
InfernoJad jad = null;
for (InfernoJad possibleJad : jads)
{
return;
if (possibleJad.getNpc() == event.getActor())
{
jad = possibleJad;
}
}
if (jad.getAnimation() == InfernoJadAttack.MAGIC.getAnimation())
if (jad != null)
{
attack = InfernoJadAttack.MAGIC;
}
else if (jad.getAnimation() == InfernoJadAttack.RANGE.getAnimation())
{
attack = InfernoJadAttack.RANGE;
if (event.getActor().getAnimation() == InfernoJad.Attack.MAGIC.getAnimation())
{
jad.updateNextAttack(InfernoJad.Attack.MAGIC);
}
else if (event.getActor().getAnimation() == InfernoJad.Attack.RANGE.getAnimation())
{
jad.updateNextAttack(InfernoJad.Attack.RANGE);
}
}
}
@@ -515,8 +544,12 @@ public class InfernoPlugin extends Plugin
{
this.displayNibblerOverlay = config.displayNibblerOverlay();
this.showPrayerHelp = config.showPrayerHelp();
this.prayerOverlayMode = config.prayerOverlayMode();
this.waveDisplay = config.waveDisplay();
this.getWaveOverlayHeaderColor = config.getWaveOverlayHeaderColor();
this.getWaveTextColor = config.getWaveTextColor();
this.descendingBoxes = config.descendingBoxes();
this.indicateWhenPrayingCorrectly = config.indicateWhenPrayingCorrectly();
this.indicateActiveHealers = config.indicateActiveHealers();
}
}

View File

@@ -0,0 +1,138 @@
package net.runelite.client.plugins.inferno;
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.NPC;
import net.runelite.api.Prayer;
import net.runelite.api.widgets.Widget;
import net.runelite.api.widgets.WidgetInfo;
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.OverlayPriority;
import net.runelite.client.ui.overlay.OverlayUtil;
public class InfernoPrayerOverlay extends Overlay
{
private static final int TICK_PIXEL_SIZE = 60;
private static final int BLOB_WIDTH = 10;
private static final int BLOB_HEIGHT = 5;
private final InfernoPlugin plugin;
private final Client client;
@Inject
private InfernoPrayerOverlay(final Client client, final InfernoPlugin plugin)
{
setPosition(OverlayPosition.DYNAMIC);
setLayer(OverlayLayer.ABOVE_WIDGETS);
setPriority(OverlayPriority.HIGHEST);
this.client = client;
this.plugin = plugin;
}
@Override
public Dimension render(Graphics2D graphics)
{
if (client.getWidget(WidgetInfo.PRAYER_PROTECT_FROM_MAGIC).isHidden()
|| client.getWidget(WidgetInfo.PRAYER_PROTECT_FROM_MISSILES).isHidden())
{
return null;
}
InfernoJad.Attack prayerForAttack = null;
if (client.isPrayerActive(Prayer.PROTECT_FROM_MAGIC))
{
prayerForAttack = InfernoJad.Attack.MAGIC;
}
else if (client.isPrayerActive(Prayer.PROTECT_FROM_MISSILES))
{
prayerForAttack = InfernoJad.Attack.RANGE;
}
InfernoJad.Attack closestAttack = null;
int leastTicks = 999;
for (InfernoJad jad : plugin.getJads())
{
if (jad.getNextAttack() == null || jad.getTicksTillNextAttack() < 1)
{
continue;
}
if (jad.getTicksTillNextAttack() < leastTicks)
{
leastTicks = jad.getTicksTillNextAttack();
closestAttack = jad.getNextAttack();
}
if (!plugin.isDescendingBoxes() || !plugin.isShowPrayerHelp()
|| (plugin.getPrayerOverlayMode() != InfernoPrayerOverlayMode.PRAYER_TAB
&& plugin.getPrayerOverlayMode() != InfernoPrayerOverlayMode.BOTH))
{
continue;
}
final Widget prayerWidget = jad.getNextAttack() == InfernoJad.Attack.MAGIC
? client.getWidget(WidgetInfo.PRAYER_PROTECT_FROM_MAGIC) : client.getWidget(WidgetInfo.PRAYER_PROTECT_FROM_MISSILES);
int baseX = (int) prayerWidget.getBounds().getX();
baseX += prayerWidget.getBounds().getWidth() / 2;
baseX -= BLOB_WIDTH / 2;
int baseY = (int) prayerWidget.getBounds().getY() - jad.getTicksTillNextAttack() * TICK_PIXEL_SIZE - BLOB_HEIGHT;
baseY += TICK_PIXEL_SIZE - ((plugin.getLastTick() + 600 - System.currentTimeMillis()) / 600.0 * TICK_PIXEL_SIZE);
final Polygon blob = new Polygon(new int[]{0, BLOB_WIDTH, BLOB_WIDTH, 0}, new int[]{0, 0, BLOB_HEIGHT, BLOB_HEIGHT}, 4);
blob.translate(baseX, baseY);
OverlayUtil.renderPolygon(graphics, blob, Color.ORANGE);
}
if (plugin.isShowPrayerHelp() && closestAttack != null
&& (closestAttack != prayerForAttack || plugin.isIndicateWhenPrayingCorrectly())
&& (plugin.getPrayerOverlayMode() == InfernoPrayerOverlayMode.PRAYER_TAB
|| plugin.getPrayerOverlayMode() == InfernoPrayerOverlayMode.BOTH))
{
final Widget prayerWidget = closestAttack == InfernoJad.Attack.MAGIC
? client.getWidget(WidgetInfo.PRAYER_PROTECT_FROM_MAGIC) : client.getWidget(WidgetInfo.PRAYER_PROTECT_FROM_MISSILES);
final Polygon prayer = new Polygon(
new int[]{0, (int) prayerWidget.getBounds().getWidth(), (int) prayerWidget.getBounds().getWidth(), 0},
new int[]{0, 0, (int) prayerWidget.getBounds().getHeight(), (int) prayerWidget.getBounds().getHeight()},
4);
prayer.translate((int) prayerWidget.getBounds().getX(), (int) prayerWidget.getBounds().getY());
Color prayerColor;
if (closestAttack == prayerForAttack)
{
prayerColor = Color.GREEN;
}
else
{
prayerColor = Color.RED;
}
OverlayUtil.renderPolygon(graphics, prayer, prayerColor);
}
if (plugin.isIndicateActiveHealers())
{
for (NPC healer : plugin.getActiveHealers())
{
if (healer.getConvexHull() == null)
{
continue;
}
OverlayUtil.renderPolygon(graphics, healer.getConvexHull(), Color.CYAN);
}
}
return null;
}
}

View File

@@ -0,0 +1,8 @@
package net.runelite.client.plugins.inferno;
enum InfernoPrayerOverlayMode
{
PRAYER_TAB,
BOTTOM_RIGHT,
BOTH
}