Barbarianassault merge (#579)

* widgets: update name to more accurately represent widget

* BarbarianAssault: WIP batools/barbarianassult merge

* widgetinfo: add weapon name widget

* healer codes: semi-fixed

* menu prioritization: walk here here now takes priority over incorrect
eggs and any type of bait if enabled in config

* add cntl healer

* add slider config option for prayer metronome volume, and fix some more
menu options

* add shift overstock and cleanup imports/config

* add death timers and update copyrights and config

* Remove unused class

* add mode class

* add ProjectileSpawn event

* add tagging

* add reset before wave starts

* improve end of wave handling and disabling/enabling plugin mid game

* fix horn of glory pt. 1

* fix horn of glory pt. 2

* fix call timer and finish horn of glory

* fix 🙏 healer codes

* cleanup and move certain methods to client thread

* cleanup
This commit is contained in:
se7enAte9
2019-06-26 20:50:39 -04:00
committed by Kyleeld
parent 9142a08f3f
commit 24a6357baf
31 changed files with 3022 additions and 2416 deletions

View File

@@ -1,5 +1,6 @@
/*
* Copyright (c) 2018, https://runelitepl.us
* Copyright (c) 2019, 7ate9 <https://github.com/se7enAte9>
* Copyright (c) 2019, https://runelitepl.us
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -22,16 +23,19 @@
* (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.batools;
package net.runelite.api.events;
import java.awt.image.BufferedImage;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.ui.overlay.infobox.Counter;
import net.runelite.api.Projectile;
import lombok.Data;
class CycleCounter extends Counter
/**
* An event called whenever a {@link Projectile} has spawned.
*/
@Data
public class ProjectileSpawned
{
CycleCounter(BufferedImage img, Plugin plugin, int tick)
{
super(img, plugin, tick);
}
}
/**
* The spawned projectile.
*/
private Projectile projectile;
}

View File

@@ -57,7 +57,7 @@ public class WidgetID
public static final int PEST_CONTROL_BOAT_GROUP_ID = 407;
public static final int PEST_CONTROL_GROUP_ID = 408;
public static final int PEST_CONTROL_EXCHANGE_WINDOW_GROUP_ID = 243;
public static final int PEST_CONTROL_DIALOG_GROUP_ID = 229;
public static final int DIALOG_MINIGAME_GROUP_ID = 229;
public static final int CLAN_CHAT_GROUP_ID = 7;
public static final int MINIMAP_GROUP_ID = 160;
public static final int LOGIN_CLICK_TO_PLAY_GROUP_ID = 378;
@@ -84,6 +84,7 @@ public class WidgetID
public static final int BA_DEFENDER_GROUP_ID = 487;
public static final int BA_HEALER_GROUP_ID = 488;
public static final int BA_REWARD_GROUP_ID = 497;
public static final int BA_HORN_OF_GLORY = 484;
public static final int LEVEL_UP_GROUP_ID = 233;
public static final int DIALOG_SPRITE_GROUP_ID = 193;
public static final int QUEST_COMPLETED_GROUP_ID = 277;
@@ -197,7 +198,7 @@ public class WidgetID
static final int CONFIRM_BUTTON = 6;
}
static class PestControlDialog
static class MinigameDialog
{
static final int TEXT = 1;
static final int CONTINUE = 2;
@@ -594,7 +595,8 @@ public class WidgetID
{
static class ATK
{
static final int LISTEN = 8;
static final int LISTEN_TOP = 7;
static final int LISTEN_BOTTOM = 8;
static final int TO_CALL_WIDGET = 9;
static final int TO_CALL = 10;
static final int ROLE_SPRITE = 11;
@@ -607,6 +609,13 @@ public class WidgetID
static final int TEAMMATE3 = 26;
static final int TEAMMATE4 = 30;
}
static class HORN_GLORY
{
static final int ATTACKER = 5;
static final int DEFENDER = 6;
static final int COLLECTOR = 7;
static final int HEALER = 8;
}
static class REWARD_VALUES
{
static final int RUNNERS_PASSED = 14;

View File

@@ -85,8 +85,8 @@ public enum WidgetInfo
DIARY_QUEST_WIDGET_TITLE(WidgetID.DIARY_QUEST_GROUP_ID, WidgetID.Diary.DIARY_TITLE),
DIARY_QUEST_WIDGET_TEXT(WidgetID.DIARY_QUEST_GROUP_ID, WidgetID.Diary.DIARY_TEXT),
PEST_CONTROL_DIALOG(WidgetID.PEST_CONTROL_DIALOG_GROUP_ID, 0),
PEST_CONTROL_DIALOG_TEXT(WidgetID.PEST_CONTROL_DIALOG_GROUP_ID, WidgetID.PestControlDialog.TEXT),
MINIGAME_DIALOG(WidgetID.DIALOG_MINIGAME_GROUP_ID, 0),
MINIGAME_DIALOG_TEXT(WidgetID.DIALOG_MINIGAME_GROUP_ID, WidgetID.MinigameDialog.TEXT),
PEST_CONTROL_EXCHANGE_WINDOW(WidgetID.PEST_CONTROL_EXCHANGE_WINDOW_GROUP_ID, 0),
PEST_CONTROL_EXCHANGE_WINDOW_POINTS(WidgetID.PEST_CONTROL_EXCHANGE_WINDOW_GROUP_ID, WidgetID.PestControlExchangeWindow.POINTS),
PEST_CONTROL_BOAT_INFO(WidgetID.PEST_CONTROL_BOAT_GROUP_ID, WidgetID.PestControlBoat.INFO),
@@ -310,6 +310,7 @@ public enum WidgetInfo
QUICK_PRAYER_PRAYERS(WidgetID.QUICK_PRAYERS_GROUP_ID, WidgetID.QuickPrayer.PRAYERS),
COMBAT_LEVEL(WidgetID.COMBAT_GROUP_ID, WidgetID.Combat.LEVEL),
COMBAT_WEAPON(WidgetID.COMBAT_GROUP_ID, WidgetID.Combat.WEAPON_NAME),
COMBAT_STYLE_ONE(WidgetID.COMBAT_GROUP_ID, WidgetID.Combat.STYLE_ONE),
COMBAT_STYLE_TWO(WidgetID.COMBAT_GROUP_ID, WidgetID.Combat.STYLE_TWO),
COMBAT_STYLE_THREE(WidgetID.COMBAT_GROUP_ID, WidgetID.Combat.STYLE_THREE),
@@ -364,6 +365,7 @@ public enum WidgetInfo
BA_HEAL_WAVE_TEXT(WidgetID.BA_HEALER_GROUP_ID, WidgetID.BarbarianAssault.CURRENT_WAVE),
BA_HEAL_CALL_TEXT(WidgetID.BA_HEALER_GROUP_ID, WidgetID.BarbarianAssault.TO_CALL),
BA_HEAL_LISTEN_TEXT(WidgetID.BA_HEALER_GROUP_ID, WidgetID.BarbarianAssault.LISTEN),
BA_HEAL_HORN_LISTEN_TEXT(WidgetID.BA_HORN_OF_GLORY, WidgetID.BarbarianAssault.HORN_GLORY.HEALER),
BA_HEAL_ROLE_TEXT(WidgetID.BA_HEALER_GROUP_ID, WidgetID.BarbarianAssault.ROLE),
BA_HEAL_ROLE_SPRITE(WidgetID.BA_HEALER_GROUP_ID, WidgetID.BarbarianAssault.ROLE_SPRITE),
@@ -375,18 +377,22 @@ public enum WidgetInfo
BA_COLL_WAVE_TEXT(WidgetID.BA_COLLECTOR_GROUP_ID, WidgetID.BarbarianAssault.CURRENT_WAVE),
BA_COLL_CALL_TEXT(WidgetID.BA_COLLECTOR_GROUP_ID, WidgetID.BarbarianAssault.TO_CALL),
BA_COLL_LISTEN_TEXT(WidgetID.BA_COLLECTOR_GROUP_ID, WidgetID.BarbarianAssault.LISTEN),
BA_COLL_HORN_LISTEN_TEXT(WidgetID.BA_HORN_OF_GLORY, WidgetID.BarbarianAssault.HORN_GLORY.COLLECTOR),
BA_COLL_ROLE_TEXT(WidgetID.BA_COLLECTOR_GROUP_ID, WidgetID.BarbarianAssault.ROLE),
BA_COLL_ROLE_SPRITE(WidgetID.BA_COLLECTOR_GROUP_ID, WidgetID.BarbarianAssault.ROLE_SPRITE),
BA_ATK_WAVE_TEXT(WidgetID.BA_ATTACKER_GROUP_ID, WidgetID.BarbarianAssault.CURRENT_WAVE),
BA_ATK_CALL_TEXT(WidgetID.BA_ATTACKER_GROUP_ID, WidgetID.BarbarianAssault.ATK.TO_CALL),
BA_ATK_LISTEN_TEXT(WidgetID.BA_ATTACKER_GROUP_ID, WidgetID.BarbarianAssault.ATK.LISTEN),
BA_ATK_LISTEN_TOP_TEXT(WidgetID.BA_ATTACKER_GROUP_ID, WidgetID.BarbarianAssault.ATK.LISTEN_TOP),
BA_ATK_LISTEN_BOTTOM_TEXT(WidgetID.BA_ATTACKER_GROUP_ID, WidgetID.BarbarianAssault.ATK.LISTEN_BOTTOM),
BA_ATK_HORN_LISTEN_TEXT(WidgetID.BA_HORN_OF_GLORY, WidgetID.BarbarianAssault.HORN_GLORY.ATTACKER),
BA_ATK_ROLE_TEXT(WidgetID.BA_ATTACKER_GROUP_ID, WidgetID.BarbarianAssault.ATK.ROLE),
BA_ATK_ROLE_SPRITE(WidgetID.BA_ATTACKER_GROUP_ID, WidgetID.BarbarianAssault.ATK.ROLE_SPRITE),
BA_DEF_WAVE_TEXT(WidgetID.BA_DEFENDER_GROUP_ID, WidgetID.BarbarianAssault.CURRENT_WAVE),
BA_DEF_CALL_TEXT(WidgetID.BA_DEFENDER_GROUP_ID, WidgetID.BarbarianAssault.TO_CALL),
BA_DEF_LISTEN_TEXT(WidgetID.BA_DEFENDER_GROUP_ID, WidgetID.BarbarianAssault.LISTEN),
BA_DEF_HORN_LISTEN_TEXT(WidgetID.BA_HORN_OF_GLORY, WidgetID.BarbarianAssault.HORN_GLORY.DEFENDER),
BA_DEF_ROLE_TEXT(WidgetID.BA_DEFENDER_GROUP_ID, WidgetID.BarbarianAssault.ROLE),
BA_DEF_ROLE_SPRITE(WidgetID.BA_DEFENDER_GROUP_ID, WidgetID.BarbarianAssault.ROLE_SPRITE),

View File

@@ -0,0 +1,219 @@
/*
* Copyright (c) 2018, Jacob M <https://github.com/jacoblairm>
* Copyright (c) 2019, 7ate9 <https://github.com/se7enAte9>
* Copyright (c) 2019, https://runelitepl.us
* 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.barbarianassault;
import com.google.common.collect.ImmutableMap;
import net.runelite.api.Client;
import net.runelite.api.Perspective;
import net.runelite.api.Point;
import net.runelite.api.coords.LocalPoint;
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.OverlayUtil;
import javax.inject.Inject;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Stroke;
import java.awt.BasicStroke;
import java.util.Map;
class AboveSceneOverlay extends Overlay
{
private static final int HEALTH_BAR_HEIGHT = 20;
private static final int HEALTH_BAR_WIDTH = 115;
private static final int CENTER_OFFSET = Perspective.LOCAL_HALF_TILE_SIZE / 8;
private static final int EGG_DIAMETER = Perspective.LOCAL_HALF_TILE_SIZE / 4;
private static final Color HEALTH_BAR_COLOR = new Color(225, 35, 0, 125);
private static final ImmutableMap<WidgetInfo, Point> TEAMMATES = ImmutableMap.of(
WidgetInfo.BA_HEAL_TEAMMATE1, new Point(28, 2),
WidgetInfo.BA_HEAL_TEAMMATE2, new Point(26, 2),
WidgetInfo.BA_HEAL_TEAMMATE3, new Point(26, 2),
WidgetInfo.BA_HEAL_TEAMMATE4, new Point(25, 2));
private final Client client;
private final BarbarianAssaultPlugin game;
private final BarbarianAssaultConfig config;
@Inject
private AboveSceneOverlay(Client client, BarbarianAssaultPlugin game, BarbarianAssaultConfig config)
{
super(game);
setPosition(OverlayPosition.DYNAMIC);
setLayer(OverlayLayer.ABOVE_SCENE);
this.client = client;
this.game = game;
this.config = config;
}
@Override
public Dimension render(Graphics2D graphics)
{
if (!game.isInGame() || game.getRole() == null || game.isUsingGloryHorn())
{
return null;
}
switch (game.getRole())
{
case HEALER:
if (config.showTeammateHealthbars())
{
renderHealthBars(graphics);
}
if (config.healerCodes())
{
renderHealerCodes(graphics);
}
break;
case COLLECTOR:
if (config.highlightCollectorEggs())
{
renderEggs(graphics);
}
break;
}
return null;
}
//TODO add poison color change or low health color change
private void renderHealthBars(Graphics2D graphics)
{
for (Map.Entry<WidgetInfo, Point> teammate : TEAMMATES.entrySet())
{
Widget widget = client.getWidget(teammate.getKey());
if (widget == null)
{
continue;
}
// This will give us two elements, the first will be current health, and the second will be max health
String[] teammateHealth = widget.getText().split(" / ");
graphics.setColor(HEALTH_BAR_COLOR);
graphics.fillRect((widget.getCanvasLocation().getX() - teammate.getValue().getX()),
(widget.getCanvasLocation().getY() - teammate.getValue().getY()),
getBarWidth(Integer.parseInt(teammateHealth[1]), Integer.parseInt(teammateHealth[0])),
HEALTH_BAR_HEIGHT);
}
}
private int getBarWidth(int base, int current)
{
final double ratio = (double) current / base;
if (ratio >= 1)
{
return HEALTH_BAR_WIDTH;
}
return (int) Math.round(ratio * HEALTH_BAR_WIDTH);
}
private void renderHealerCodes(Graphics2D graphics)
{
for (Healer healer : game.getHealers().values())
{
Color color = Color.GREEN;
int timeLeft = 0;
if (game.getWave() != null)
{
timeLeft = healer.getLastFoodTime() - (int) game.getWave().getWaveTimer().getElapsedTime();
}
timeLeft = timeLeft < 1 ? 0 : timeLeft;
if (timeLeft > 0)
{
color = Color.RED;
}
String text = String.format("%d %d", healer.getFoodRemaining(), timeLeft);
OverlayUtil.renderActorOverlay(graphics, healer.getNpc(), text, color);
}
}
private void renderEggs(Graphics2D graphics)
{
final Color color = graphics.getColor();
final Stroke originalStroke = graphics.getStroke();
String listen = game.getLastListenText();
if (listen != null && !listen.equals("- - -"))
{
graphics.setStroke(new BasicStroke(2));
//TODO Render quantity text as well
//TODO add config options for overlay colors
switch (listen)
{
case "Red eggs":
graphics.setColor(new Color(Color.RED.getRed(), Color.RED.getGreen(), Color.RED.getBlue(), 150));
game.getRedEggs().forEach((point, quantity) -> drawCircle(graphics, LocalPoint.fromWorld(client, point)));
break;
case "Green eggs":
graphics.setColor(new Color(Color.GREEN.getRed(), Color.GREEN.getGreen(), Color.GREEN.getBlue(), 150));
game.getGreenEggs().forEach((point, quantity) -> drawCircle(graphics, LocalPoint.fromWorld(client, point)));
break;
case "Blue eggs":
graphics.setColor(new Color(Color.BLUE.getRed(), Color.BLUE.getGreen(), Color.BLUE.getBlue(), 150));
game.getBlueEggs().forEach((point, quantity) -> drawCircle(graphics, LocalPoint.fromWorld(client, point)));
break;
}
}
graphics.setColor(new Color(Color.YELLOW.getRed(), Color.YELLOW.getGreen(), Color.YELLOW.getBlue(), 150));
game.getYellowEggs().forEach((point, quantity) -> drawCircle(graphics, LocalPoint.fromWorld(client, point)));
graphics.setColor(color);
graphics.setStroke(originalStroke);
}
private void drawCircle(Graphics2D graphics, LocalPoint point)
{
if (point == null)
{
return;
}
Point canvasPoint = Perspective.localToCanvas(client, point, 0);
if (canvasPoint == null)
{
return;
}
//TODO rendering a model would be better / more accurate
graphics.fillOval(canvasPoint.getX() - CENTER_OFFSET, canvasPoint.getY() - CENTER_OFFSET, EGG_DIAMETER, EGG_DIAMETER);
}
}

View File

@@ -0,0 +1,181 @@
/*
* Copyright (c) 2019, 7ate9 <https://github.com/se7enAte9>
* Copyright (c) 2019, https://runelitepl.us
* 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.barbarianassault;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import javax.inject.Inject;
import net.runelite.api.Client;
import net.runelite.api.Point;
import net.runelite.api.widgets.Widget;
import net.runelite.api.widgets.WidgetInfo;
import net.runelite.api.widgets.WidgetItem;
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;
import net.runelite.client.util.ImageUtil;
class AboveWidgetsOverlay extends Overlay
{
private static final int OFFSET_X_TEXT_QUANTITY = 0;
private static final int OFFSET_Y_TEXT_QUANTITY = 10;
private final Client client;
private final BarbarianAssaultPlugin game;
private final BarbarianAssaultConfig config;
@Inject
private AboveWidgetsOverlay(Client client, BarbarianAssaultPlugin game, BarbarianAssaultConfig config)
{
super(game);
setPosition(OverlayPosition.DYNAMIC);
setLayer(OverlayLayer.ABOVE_WIDGETS);
this.client = client;
this.game = game;
this.config = config;
}
@Override
public Dimension render(Graphics2D graphics)
{
if (!game.isInGame() || game.getRole() == null || game.isUsingGloryHorn())
{
return null;
}
Role role = game.getRole();
if (config.showTimer())
{
renderTimer(graphics, role);
}
switch (role)
{
case ATTACKER:
if (config.highlightArrows())
{
renderInventoryHighlights(graphics, game.getRole().getListenItem(game.getLastListenText()), config.highlightArrowColor());
}
break;
case DEFENDER:
if (config.highlightBait())
{
renderInventoryHighlights(graphics, game.getRole().getListenItem(game.getLastListenText()), config.highlightBaitColor());
}
break;
case HEALER:
if (config.highlightPoison())
{
renderInventoryHighlights(graphics, game.getRole().getListenItem(game.getLastListenText()), config.highlightPoisonColor());
}
}
return null;
}
private void renderTimer(Graphics2D graphics, Role role)
{
Widget roleText = client.getWidget(role.getRoleText());
Widget roleSprite = client.getWidget(role.getRoleSprite());
if (roleText == null || roleSprite == null)
{
return;
}
if (role == Role.COLLECTOR && config.showEggCountOverlay() && game.getWave() != null)
{
roleText.setText("(" + game.getWave().getCollectedEggCount() + ") " + formatClock());
}
else if (role == Role.HEALER && config.showHpCountOverlay() && game.getWave() != null)
{
roleText.setText("(" + game.getWave().getHpHealed() + ") " + formatClock());
}
else
{
roleText.setText(formatClock());
}
Rectangle spriteBounds = roleSprite.getBounds();
graphics.drawImage(game.getClockImage(), spriteBounds.x, spriteBounds.y, null);
}
private void renderInventoryHighlights(Graphics2D graphics, int itemID, Color color)
{
Widget inventory = client.getWidget(WidgetInfo.INVENTORY);
if (inventory == null || inventory.isHidden() || itemID == -1)
{
return;
}
Color highlight = new Color(color.getRed(), color.getGreen(), color.getBlue(), 150);
BufferedImage image = ImageUtil.fillImage(client.createItemSprite(itemID, 300, 2, 0, 0, true, 710).toBufferedImage(), highlight);
for (WidgetItem item : inventory.getWidgetItems())
{
if (item.getId() == itemID)
{
OverlayUtil.renderImageLocation(graphics, item.getCanvasLocation(), image);
//The item's text quantity is rendered after the sprite's image is rendered so that the text appears on top
if (item.getQuantity() > 1)
{
OverlayUtil.renderTextLocation(graphics,
new Point(item.getCanvasLocation().getX() + OFFSET_X_TEXT_QUANTITY, item.getCanvasLocation().getY() + OFFSET_Y_TEXT_QUANTITY),
String.valueOf(item.getQuantity()), Color.YELLOW);
}
}
}
}
private String formatClock()
{
if (game.getCallTimer() == null)
{
return "- - -";
}
else
{
long timeLeft = game.getTimeToChange();
if (timeLeft < 0)
{
return "00:00";
}
else
{
return String.format("00:%02d", timeLeft);
}
}
}
}

View File

@@ -1,5 +1,6 @@
/*
* Copyright (c) 2018, https://runelitepl.us
* Copyright (c) 2019, 7ate9 <https://github.com/se7enAte9>
* Copyright (c) 2019, https://runelitepl.us
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -28,26 +29,112 @@ 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.Range;
@ConfigGroup("barbarianAssault")
public interface BarbarianAssaultConfig extends Config
{
@ConfigItem(
keyName = "swapLadder",
name = "Swap quick-start",
description = "Enables swapping of 'Climb-down' and 'Quick-start' in the wave lobby",
position = 0
)
default boolean swapLadder()
{
return true;
}
@ConfigItem(
keyName = "showTimer",
name = "Show call change timer",
description = "Show time to next call change",
position = 0
description = "Shows time to next call change",
position = 1
)
default boolean showTimer()
{
return true;
}
@ConfigItem(
keyName = "removeIncorrectCalls",
name = "Remove incorrect calls",
description = "Removes incorrect 'Tell' menu options from horn",
position = 2
)
default boolean removeIncorrectCalls()
{
return true;
}
@ConfigItem(
keyName = "removeUnusedMenus",
name = "Remove unused menus",
description = "Removes unnecessary menu options" +
"<br>Example: Attack options are removed when not attacker",
position = 3
)
default boolean removeUnusedMenus()
{
return true;
}
@ConfigItem(
keyName = "prayerMetronome",
name = "Enable prayer metronome",
description = "Turns on a metronome sync'd to the game's tick rate when any prayer is active",
position = 4
)
default boolean prayerMetronome()
{
return false;
}
@Range(
min = 1,
max = 50
)
@ConfigItem(
keyName = "prayerMetronomeVolume",
name = "Metronome volume",
description = "Adjusts the metronome's volume",
position = 5,
hidden = true,
unhide = "prayerMetronome"
)
default int prayerMetronomeVolume()
{
return 10;
}
@ConfigItem(
keyName = "showDeathTimes",
name = "Show death times",
description = "Shows the time all penance monsters of a certain type are killed in the chat box, an info box, or both",
position = 6
)
default boolean showDeathTimes()
{
return true;
}
@ConfigItem(
keyName = "showDeathTimesMode",
name = "Mode",
description = "",
position = 7,
hidden = true,
unhide = "showDeathTimes"
)
default DeathTimesMode showDeathTimesMode()
{
return DeathTimesMode.BOTH;
}
@ConfigItem(
keyName = "waveTimes",
name = "Show wave and game duration",
description = "Displays wave and game duration",
position = 1
description = "Displays wave duration after each wave and total game time after wave 10",
position = 8
)
default boolean waveTimes()
{
@@ -55,112 +142,329 @@ public interface BarbarianAssaultConfig extends Config
}
@ConfigItem(
keyName = "showEggCountMessage",
name = "Show count of eggs collected as collector.",
description = "Display egg count as collector after each wave",
position = 2
keyName = "showTotalRewards",
name = "Summarize total reward points",
description = "Gives summary of advanced points breakdown in chat log",
position = 9
)
default boolean showEggCount()
default boolean showTotalRewards()
{
return true;
}
/*///************///*/
/*/// Attacker ///*/
/*///************///*/
@ConfigItem(
keyName = "highlightArrows",
name = "Highlight called arrows",
description = "Highlights arrows called by your teammate",
position = 0,
group = "Attacker"
)
default boolean highlightArrows()
{
return true;
}
@ConfigItem(
keyName = "highlightArrowColor",
name = "Arrow color",
description = "Configures the color to highlight the called arrows",
position = 1,
group = "Attacker",
hidden = true,
unhide = "highlightArrows"
)
default Color highlightArrowColor()
{
return Color.GREEN;
}
@ConfigItem(
keyName = "attackStyles",
name = "Remove incorrect attack styles",
description = "Hide attack styles depending on weapon.",
position = 2,
group = "Attacker"
)
default boolean attackStyles()
{
return false;
}
@ConfigItem(
keyName = "showEggCountOverlay",
name = "Overlay of eggs counted",
description = "Display current egg count as collector",
position = 3
keyName = "tagging",
name = "Enable tagging",
description = "Highlights the menu entry of an attacker/ranger that has not been tagged.",
position = 3,
group = "Attacker"
)
default boolean showEggCountOverlay()
default boolean tagging()
{
return false;
}
/*///************///*/
/*/// Defender ///*/
/*///************///*/
@ConfigItem(
keyName = "showHpCountMessage",
name = "Show count of Hp healed as healer.",
description = "Display healed count as healer after each wave",
position = 4
keyName = "highlightBait",
name = "Highlight called bait",
description = "Highlights bait called by your teammate",
position = 0,
group = "Defender"
)
default boolean showHpCount()
default boolean highlightBait()
{
return false;
return true;
}
@ConfigItem(
keyName = "highlightBaitColor",
name = "Bait color",
description = "Configures the color to highlight the called bait",
position = 1,
group = "Defender",
hidden = true,
unhide = "highlightBait"
)
default Color highlightBaitColor()
{
return Color.GREEN;
}
@ConfigItem(
keyName = "showDefTimer",
name = "Show defender tick timer",
description = "Shows the current cycle tick of runners",
position = 2,
group = "Defender"
)
default boolean showDefTimer()
{
return true;
}
@ConfigItem(
keyName = "deprioritizeBait",
name = "Deprioritize bait",
description = "Moves 'Take' menu option for all bait below 'Walk Here'",
position = 3,
group = "Defender"
)
default boolean deprioritizeBait()
{
return true;
}
@ConfigItem(
keyName = "removePenanceCave",
name = "Remove penance cave",
description = "Removes 'Block' menu option from penance cave",
position = 4,
group = "Defender"
)
default boolean removePenanceCave()
{
return true;
}
/*///**********///*/
/*/// Healer ///*/
/*///**********///*/
@ConfigItem(
keyName = "highlightPoison",
name = "Highlight called poison",
description = "Highlights poison called by your teammate",
position = 0,
group = "Healer"
)
default boolean highlightPoison()
{
return true;
}
@ConfigItem(
keyName = "highlightPoisonColor",
name = "Poison color",
description = "Configures the color to highlight the called poison",
position = 1,
group = "Healer",
hidden = true,
unhide = "highlightPoison"
)
default Color highlightPoisonColor()
{
return Color.GREEN;
}
@ConfigItem(
keyName = "highlightNotification",
name = "Highlight incorrect notification",
description = "Highlights incorrect poison chat notification",
position = 2,
group = "Healer"
)
default boolean highlightNotification()
{
return true;
}
@ConfigItem(
keyName = "highlightNotificationColor",
name = "Notification color",
description = "Configures the color to highlight the notification text",
position = 3,
group = "Healer",
hidden = true,
unhide = "highlightNotification"
)
default Color highlightNotificationColor()
{
return Color.RED;
}
@ConfigItem(
keyName = "showHpCountOverlay",
name = "Overlay of Hp counted",
description = "Display current healed count as healer",
position = 5
name = "Show number of hitpoints healed",
description = "Displays current number of hitpoints healed",
position = 4,
group = "Healer"
)
default boolean showHpCountOverlay()
{
return true;
}
@ConfigItem(
keyName = "showTeammateHealthbars",
name = "Show health bars",
description = "Displays a health bar where a teammate's remaining health is located",
position = 5,
group = "Healer"
)
default boolean showTeammateHealthbars()
{
return true;
}
@ConfigItem(
keyName = "healerCodes",
name = "Show healer codes",
description = "Overlay to show healer codes",
position = 6,
group = "Healer"
)
default boolean healerCodes()
{
return false;
}
@ConfigItem(
keyName = "healerMenuOption",
name = "Show healer menu options",
description = "Shows tick count in healer menu options",
position = 7,
group = "Healer"
)
default boolean healerMenuOption()
{
return false;
}
@ConfigItem(
keyName = "shiftOverstock",
name = "Enable shift overstock",
description = "Enables overstocking by pressing shift",
position = 8,
group = "Healer"
)
default boolean shiftOverstock()
{
return true;
}
@ConfigItem(
keyName = "controlHealer",
name = "Control Healer",
description = "Hold ctrl to put last healer clicked on top",
position = 9,
group = "Healer"
)
default boolean controlHealer()
{
return true;
}
/*///*************///*/
/*/// Collector ///*/
/*///*************///*/
@ConfigItem(
keyName = "swapCollectorBag",
name = "Swap empty",
description = "Enables swapping of 'Look-in' and 'Empty' on the collector's bag",
position = 0,
group = "Collector"
)
default boolean swapCollectorBag()
{
return true;
}
@ConfigItem(
keyName = "swapDestroyEggs",
name = "Swap destroy",
description = "Enables swapping of 'Use' and 'Destroy' on collector eggs; this does not affect yellow/omega eggs",
position = 1,
group = "Collector"
)
default boolean swapDestroyEggs()
{
return true;
}
@ConfigItem(
keyName = "highlightCollectorEggs",
name = "Highlight collector eggs",
description = "Highlight called egg colors",
position = 6
position = 2,
group = "Collector"
)
default boolean highlightCollectorEggs()
{
return false;
return true;
}
@ConfigItem(
keyName = "showTotalRewards",
name = "Summarize total reward points",
description = "Displays total eggs/healed hp and missed attacks/lost runners",
position = 7
keyName = "deprioritizeIncorrectEggs",
name = "Deprioritize incorrect eggs",
description = "Moves 'Take' menu option for incorrect eggs below 'Walk Here'",
position = 3,
group = "Collector"
)
default boolean showTotalRewards()
default boolean deprioritizeIncorrectEggs()
{
return false;
return true;
}
@ConfigItem(
keyName = "showSummaryOfPoints",
name = "Display summary of advanced points",
description = "Gives summary of advanced points breakdown in chat log",
position = 8
keyName = "showEggCountOverlay",
name = "Show number of eggs collected",
description = "Displays current number of eggs collected",
position = 4,
group = "Collector"
)
default boolean showSummaryOfPoints()
default boolean showEggCountOverlay()
{
return false;
}
@ConfigItem(
keyName = "wrongPoisonFoodTextColor",
name = "Change healer wrong poison pack color",
description = "Change healer wrong poison pack color",
position = 9
)
default Color wrongPoisonFoodTextColor()
{
return Color.BLACK;
}
@ConfigItem(
keyName = "highlightItems",
name = "Highlight called poison/bait",
description = "Highlights the poison or bait that was called by your teammate",
position = 10
)
default boolean highlightItems()
{
return false;
}
@ConfigItem(
keyName = "highlightColor",
name = "Highlight color",
description = "Configures the color to highlight the called poison/bait",
position = 11
)
default Color highlightColor()
{
return Color.GREEN;
return true;
}
}

View File

@@ -0,0 +1,227 @@
/*
* Copyright (c) 2019, 7ate9 <https://github.com/se7enAte9>
* Copyright (c) 2019, https://runelitepl.us
* 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.barbarianassault;
import com.google.common.collect.Sets;
import lombok.Getter;
import lombok.Setter;
import net.runelite.client.menus.ComparableEntry;
import net.runelite.client.menus.MenuManager;
import javax.inject.Inject;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
class BarbarianAssaultMenu
{
private final MenuManager menuManager;
private final BarbarianAssaultPlugin game;
private final BarbarianAssaultConfig config;
private final ArrayList<ComparableEntry> tracker = new ArrayList<>();
@Getter @Setter
private boolean hornUpdated = false;
@Getter @Setter
private boolean rebuildForced = false;
@Inject
BarbarianAssaultMenu(MenuManager menuManager, BarbarianAssaultPlugin game, BarbarianAssaultConfig config)
{
this.menuManager = menuManager;
this.game = game;
this.config = config;
}
private boolean isHornOptionHidden(String option)
{
if (game.isInGame() && game.getRole() != null && game.getRole().getTell(game.getLastCallText()).toLowerCase().equals(option))
{
// This will force the menu to be rebuilt after the correct tell is found
// medic will be added to the menu if it wasn't there before
if (!hornUpdated)
{
rebuildForced = true;
}
hornUpdated = true;
return false;
}
return true;
}
void clearHiddenMenus()
{
// Clears menus from MenuManager and tracker
for (Iterator<ComparableEntry> iterator = tracker.iterator(); iterator.hasNext();)
{
menuManager.removeHiddenEntry(iterator.next());
iterator.remove();
}
}
//TODO add omega egg use on?
void validateHiddenMenus(Role role)
{
clearHiddenMenus();
HashSet<Menus> hiddenMenus = Sets.newHashSet(Menus.getMenus());
HashSet<Menus> conditionalMenus = Sets.newHashSet(Menus.getMenus());
// Any option left in this set will not be hidden
// Checking each option for the correct role prevents MenuManager from
// iterating over off role menu entry options that are not possible
conditionalMenus.removeIf(entry ->
{
switch (entry)
{
// Attacker role options
case TELL_BLUE_ATTACKER_HORN:
case TELL_GREEN_ATTACKER_HORN:
case TELL_RED_ATTACKER_HORN:
return ((role == Role.ATTACKER && isHornOptionHidden(entry.getOption())) || role == null) && config.removeIncorrectCalls();
case ATTACK_PENANCE_FIGHTER:
case ATTACK_PENANCE_RANGER:
case GET_SPIKES_PETRIFIED_MUSHROOM:
case TAKE_ATTACKER_ITEM_MACHINE:
return (role != Role.ATTACKER && role != null) && config.removeUnusedMenus();
// Defender role Options
case TELL_MEAT_DEFENDER_HORN:
case TELL_TOFU_DEFENDER_HORN:
case TELL_WORMS_DEFENDER_HORN:
return ((role == Role.DEFENDER && isHornOptionHidden(entry.getOption())) || role == null) && config.removeIncorrectCalls();
case BLOCK_PENANCE_CAVE:
return ((role != Role.DEFENDER && role != null) && config.removeUnusedMenus())
|| (role == Role.DEFENDER && config.removePenanceCave());
case DUNK_LAVA_CRATER:
case FIX:
case STOCK_UP_DEFENDER_ITEM_MACHINE:
case TAKE_DEFENDER_ITEM_MACHINE:
case TAKE_HAMMER:
case TAKE_LOGS:
return (role != Role.DEFENDER && role != null) && config.removeUnusedMenus();
// Collector role options
case TELL_ACCURATE_COLLECTOR_HORN:
case TELL_AGGRESSIVE_COLLECTOR_HORN:
case TELL_CONTROLLED_COLLECTOR_HORN:
case TELL_DEFENSIVE_COLLECTOR_HORN:
return ((role == Role.COLLECTOR && isHornOptionHidden(entry.getOption())) || role == null) && config.removeIncorrectCalls();
case CONVERT_COLLECTOR_CONVERTER:
case LOAD_EGG_HOPPER:
case TAKE_BLUE_EGG:
case TAKE_GREEN_EGG:
case TAKE_RED_EGG:
case TAKE_YELLOW_EGG:
return (role != Role.COLLECTOR && role != null) && config.removeUnusedMenus();
// Healer role options
case TELL_CRACKERS_HEALER_HORN:
case TELL_TOFU_HEALER_HORN:
case TELL_WORMS_HEALER_HORN:
return ((role == Role.HEALER && isHornOptionHidden(entry.getOption())) || role == null) && config.removeIncorrectCalls();
case DUNK_POISON_CRATER:
case STOCK_UP_HEALER_ITEM_MACHINE:
case TAKE_HEALER_ITEM_MACHINE:
case TAKE_FROM_HEALER_SPRING:
case DRINK_FROM_HEALER_SPRING:
return (role != Role.HEALER && role != null) && config.removeUnusedMenus();
case USE_VIAL_GROUND:
case USE_VIAL_ITEM:
case USE_VIAL_NPC:
case USE_VIAL_WIDGET:
return role == Role.HEALER && config.removeUnusedMenus();
// Any role options
case DROP_HORN:
case EXAMINE_HORN:
case USE_HORN:
return config.removeIncorrectCalls();
case MEDIC_HORN:
return config.removeIncorrectCalls() && !hornUpdated;
default:
return config.removeUnusedMenus();
}
});
hiddenMenus.removeAll(conditionalMenus);
for (Menus entry : hiddenMenus)
{
menuManager.addHiddenEntry(entry.getEntry());
tracker.add(entry.getEntry());
}
}
void enableSwaps()
{
if (config.swapLadder())
{
menuManager.addSwap("climb-down", "ladder", "quick-start", "ladder");
}
if (config.swapCollectorBag())
{
menuManager.addSwap("look-in", "collection bag", "empty", "collection bag");
}
if (config.swapDestroyEggs())
{
menuManager.addSwap("use", "blue egg", "destroy", "blue egg");
menuManager.addSwap("use", "green egg", "destroy", "green egg");
menuManager.addSwap("use", "red egg", "destroy", "red egg");
}
}
void disableSwaps(boolean force)
{
if (!config.swapLadder() || force)
{
menuManager.removeSwap("climb-down", "ladder", "quick-start", "ladder");
}
if (!config.swapCollectorBag() || force)
{
menuManager.removeSwap("look-in", "collection bag", "empty", "collection bag");
}
if (!config.swapDestroyEggs() || force)
{
menuManager.removeSwap("use", "blue egg", "destroy", "blue egg");
menuManager.removeSwap("use", "green egg", "destroy", "green egg");
menuManager.removeSwap("use", "red egg", "destroy", "red egg");
}
}
}

View File

@@ -1,247 +0,0 @@
/*
* Copyright (c) 2018, https://runelitepl.us
* 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.barbarianassault;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.Rectangle;
import java.awt.Stroke;
import java.awt.image.BufferedImage;
import java.util.Map;
import javax.inject.Inject;
import lombok.Getter;
import lombok.Setter;
import net.runelite.api.Client;
import net.runelite.api.GameState;
import static net.runelite.api.MenuAction.RUNELITE_OVERLAY_CONFIG;
import net.runelite.api.Perspective;
import net.runelite.api.Player;
import net.runelite.api.Point;
import net.runelite.api.coords.LocalPoint;
import net.runelite.api.coords.WorldPoint;
import net.runelite.api.widgets.Widget;
import net.runelite.api.widgets.WidgetInfo;
import net.runelite.api.widgets.WidgetItem;
import net.runelite.client.game.ItemManager;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayLayer;
import static net.runelite.client.ui.overlay.OverlayManager.OPTION_CONFIGURE;
import net.runelite.client.ui.overlay.OverlayMenuEntry;
import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.OverlayUtil;
import net.runelite.client.util.ImageUtil;
class BarbarianAssaultOverlay extends Overlay
{
private static final int MAX_EGG_DISTANCE = 2500;
private static final int HEALTH_BAR_HEIGHT = 20;
private final Color HEALTH_BAR_COLOR = new Color(225, 35, 0, 125);
private static final Color BACKGROUND = new Color(0, 0, 0, 150);
private static final int OFFSET_Z = 20;
private final Client client;
private final ItemManager itemManager;
private final BarbarianAssaultPlugin plugin;
private final BarbarianAssaultConfig config;
@Getter
@Setter
private Round currentRound;
@Inject
private BarbarianAssaultOverlay(Client client, ItemManager itemManager, BarbarianAssaultPlugin plugin, BarbarianAssaultConfig config)
{
super(plugin);
setPosition(OverlayPosition.DYNAMIC);
setLayer(OverlayLayer.ABOVE_WIDGETS);
this.client = client;
this.itemManager = itemManager;
this.plugin = plugin;
this.config = config;
getMenuEntries().add(new OverlayMenuEntry(RUNELITE_OVERLAY_CONFIG, OPTION_CONFIGURE, "B.A. overlay"));
}
@Override
public Dimension render(Graphics2D graphics)
{
if (client.getGameState() != GameState.LOGGED_IN || currentRound == null)
{
return null;
}
Role role = currentRound.getRoundRole();
if (role == null)
{
return null;
}
Widget roleText = client.getWidget(role.getRoleText());
Widget roleSprite = client.getWidget(role.getRoleSprite());
if (config.showTimer() && roleText != null && roleSprite != null)
{
if (config.showEggCountOverlay() && role.equals(Role.COLLECTOR))
{
roleText.setText(String.format("(%d) 00:%02d", plugin.getCollectedEggCount(), currentRound.getTimeToChange()));
}
else if (config.showHpCountOverlay() && role.equals(Role.HEALER))
{
roleText.setText(String.format("(%d) 00:%02d", plugin.getHpHealed(), currentRound.getTimeToChange()));
}
else
{
roleText.setText(String.format("00:%02d", currentRound.getTimeToChange()));
}
Rectangle spriteBounds = roleSprite.getBounds();
roleSprite.setHidden(true);
graphics.drawImage(plugin.getClockImage(), spriteBounds.x, spriteBounds.y, null);
}
if (role == Role.COLLECTOR && config.highlightCollectorEggs())
{
String heardCall = plugin.getCollectorHeardCall();
Color highlightColor = BarbarianAssaultPlugin.getEggColor(heardCall);
Map<WorldPoint, Integer> calledEggMap = plugin.getCalledEggMap();
Map<WorldPoint, Integer> yellowEggMap = plugin.getYellowEggs();
if (calledEggMap != null)
{
renderEggLocations(graphics, calledEggMap, highlightColor);
}
// Always show yellow eggs
renderEggLocations(graphics, yellowEggMap, Color.YELLOW);
}
Widget inventory = client.getWidget(WidgetInfo.INVENTORY);
if (config.highlightItems() && inventory != null && !inventory.isHidden() && ((role == Role.DEFENDER || role == Role.HEALER)))
{
int listenItemId = plugin.getListenItemId(role.getListen());
if (listenItemId != -1)
{
Color color = config.highlightColor();
BufferedImage highlight = ImageUtil.fillImage(itemManager.getImage(listenItemId), new Color(color.getRed(), color.getGreen(), color.getBlue(), 150));
for (WidgetItem item : inventory.getWidgetItems())
{
if (item.getId() == listenItemId)
{
OverlayUtil.renderImageLocation(graphics, item.getCanvasLocation(), highlight);
}
}
}
}
if (role == Role.HEALER)
{
for (HealerTeam teammate : HealerTeam.values())
{
Widget widget = client.getWidget(teammate.getTeammate());
if (widget == null)
{
continue;
}
String[] teammateHealth = widget.getText().split(" / ");
final int curHealth = Integer.parseInt(teammateHealth[0]);
final int maxHealth = Integer.parseInt(teammateHealth[1]);
int width = teammate.getWidth();
final int filledWidth = getBarWidth(maxHealth, curHealth, width);
int offsetX = teammate.getOffset().getX();
int offsetY = teammate.getOffset().getY();
int x = widget.getCanvasLocation().getX() - offsetX;
int y = widget.getCanvasLocation().getY() - offsetY;
graphics.setColor(HEALTH_BAR_COLOR);
graphics.fillRect(x, y, filledWidth, HEALTH_BAR_HEIGHT);
}
}
return null;
}
private static int getBarWidth(int base, int current, int size)
{
final double ratio = (double) current / base;
if (ratio >= 1)
{
return size;
}
return (int) Math.round(ratio * size);
}
private void renderEggLocations(Graphics2D graphics, Map<WorldPoint, Integer> eggMap, Color color)
{
Player player = client.getLocalPlayer();
if (player == null)
{
return;
}
final Stroke originalStroke = graphics.getStroke();
for (WorldPoint worldPoint : eggMap.keySet())
{
LocalPoint groundPoint = LocalPoint.fromWorld(client, worldPoint);
if (groundPoint == null)
{
continue;
}
if (player.getLocalLocation().distanceTo(groundPoint) > MAX_EGG_DISTANCE)
{
continue;
}
Polygon poly = Perspective.getCanvasTilePoly(client, groundPoint);
if (poly == null)
{
continue;
}
int quantity = eggMap.get(worldPoint);
String quantityText = "x" + quantity;
Point textPoint = Perspective.getCanvasTextLocation(client, graphics, groundPoint, quantityText, OFFSET_Z);
graphics.setColor(color);
graphics.setStroke(new BasicStroke(2));
graphics.drawPolygon(poly);
OverlayUtil.renderTextLocation(graphics, textPoint, quantityText, Color.WHITE);
}
graphics.setStroke(originalStroke);
}
}

View File

@@ -1,83 +0,0 @@
/*
* Copyright (c) 2018, https://runelitepl.us
* 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.barbarianassault;
import java.util.HashMap;
import java.util.Map;
public enum Calls
{ //Attacker Calls
RED_EGG("Red egg", "Tell-red"),
GREEN_EGG("Green egg", "Tell-green"),
BLUE_EGG("Blue egg", "Tell-blue"),
//Collector Calls
CONTROLLED("Controlled/Bullet/Wind", "Tell-controlled"),
ACCURATE("Accurate/Field/Water", "Tell-accurate"),
AGGRESSIVE("Aggressive/Blunt/Earth", "Tell-aggressive"),
DEFENSIVE("Defensive/Barbed/Fire", "Tell-defensive"),
//Healer Calls
TOFU("Tofu", "Tell-tofu"),
CRACKERS("Crackers", "Tell-crackers"),
WORMS("Worms", "Tell-worms"),
//Defender Calls
POIS_WORMS("Pois. Worms", "Tell-worms"),
POIS_TOFU("Pois. Tofu", "Tell-tofu"),
POIS_MEAT("Pois. Meat", "Tell-meat");
private final String call;
private final String option;
private static final Map<String, String> CALL_MENU = new HashMap<>();
static
{
for (Calls s : values())
{
CALL_MENU.put(s.getCall(), s.getOption());
}
}
Calls(String call, String option)
{
this.call = call;
this.option = option;
}
public String getCall()
{
return call;
}
public String getOption()
{
return option;
}
public static String getOption(String call)
{
return CALL_MENU.get(call);
}
}

View File

@@ -1,5 +1,6 @@
/*
* Copyright (c) 2018, whartd <github.com/whartd>
* Copyright (c) 2019, 7ate9 <https://github.com/se7enAte9>
* Copyright (c) 2019, https://runelitepl.us
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -24,21 +25,23 @@
*/
package net.runelite.client.plugins.barbarianassault;
import lombok.AllArgsConstructor;
import lombok.Getter;
import net.runelite.api.Point;
import net.runelite.api.widgets.WidgetInfo;
@Getter
@AllArgsConstructor
enum HealerTeam
public enum DeathTimesMode
{
TEAMMATE1(WidgetInfo.BA_HEAL_TEAMMATE1, new Point(28, 2), 115),
TEAMMATE2(WidgetInfo.BA_HEAL_TEAMMATE2, new Point(26, 2), 115),
TEAMMATE3(WidgetInfo.BA_HEAL_TEAMMATE3, new Point(26, 2), 115),
TEAMMATE4(WidgetInfo.BA_HEAL_TEAMMATE4, new Point(25, 2), 115);
BOTH("Both"),
CHAT_BOX("Chat Box"),
INFO_BOX("Info Box");
private WidgetInfo teammate;
private Point offset;
private int width;
}
private final String name;
DeathTimesMode(String name)
{
this.name = name;
}
@Override
public String toString()
{
return name;
}
}

View File

@@ -0,0 +1,96 @@
/*
* Copyright (c) 2019, 7ate9 <https://github.com/se7enAte9>
* Copyright (c) 2019, https://runelitepl.us
* 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.barbarianassault;
import com.google.common.collect.ImmutableList;
import lombok.AccessLevel;
import lombok.Data;
import lombok.Getter;
import net.runelite.api.NPC;
import java.time.Duration;
import java.time.Instant;
import java.util.List;
@Data
class Healer
{
@Getter(AccessLevel.NONE)
private static final List<List<int[]>> CODES = ImmutableList.of(
// ImmutableList.of(firstCallFood, secondCallFood, lastFoodTime),
ImmutableList.of(new int[]{1, 1}, new int[]{0, 0}, new int[]{0, 0}),
ImmutableList.of(new int[]{1, 1, 2}, new int[]{0, 0, 0}, new int[]{0, 0, 21}),
ImmutableList.of(new int[]{1, 6, 2}, new int[]{0, 0, 0}, new int[]{0, 0, 0}),
ImmutableList.of(new int[]{2, 5, 2, 0}, new int[]{0, 0, 7, 10}, new int[]{0, 0, 0, 0}),
ImmutableList.of(new int[]{2, 5, 2, 3, 0}, new int[]{0, 0, 0, 0, 7}, new int[]{0, 0, 21, 30, 0}),
ImmutableList.of(new int[]{3, 5, 2, 2, 0, 0}, new int[]{0, 0, 0, 2, 9, 10}, new int[]{12, 18, 21, 0, 0, 0}),
ImmutableList.of(new int[]{3, 7, 1, 1, 0, 0, 0}, new int[]{2, 0, 1, 1, 2, 4, 10}, new int[]{0, 21, 0, 0, 30, 45, 0}),
ImmutableList.of(new int[]{1, 9, 1, 1, 0, 0, 0}, new int[]{1, 0, 1, 1, 2, 2, 10}, new int[]{0, 0, 0, 0, 33, 42, 0}),
ImmutableList.of(new int[]{2, 8, 1, 1, 0, 0, 0, 0}, new int[]{1, 0, 1, 1, 2, 1, 1, 10}, new int[]{0, 21, 0, 0, 0, 0, 0, 0, 0}),
ImmutableList.of(new int[]{2, 5, 1, 1, 0, 0, 0}, new int[]{1, 0, 1, 1, 4, 4, 8}, new int[]{21, 33, 0, 33, 30, 45, 0}));
private final NPC npc;
private int wave;
private int spawnNumber;
private int foodRemaining;
private int lastFoodTime;
private int firstCallFood;
private int secondCallFood;
private Instant timeLastPoisoned = null;
Healer(NPC npc, int spawnNumber, int wave)
{
this.npc = npc;
this.wave = wave;
this.spawnNumber = spawnNumber;
List<int[]> code = CODES.get(wave - 1);
this.firstCallFood = code.get(0)[spawnNumber];
this.secondCallFood = code.get(1)[spawnNumber];
this.lastFoodTime = code.get(2)[spawnNumber];
this.foodRemaining = firstCallFood + secondCallFood;
}
int timeToPoison()
{
if (timeLastPoisoned == null)
{
return -1;
}
else
{
long time = Duration.between(timeLastPoisoned, Instant.now()).getSeconds();
return time > 20 ? 0 : (int)(20 - time);
}
}
}

View File

@@ -0,0 +1,130 @@
/*
* Copyright (c) 2019, 7ate9 <https://github.com/se7enAte9>
* Copyright (c) 2019, https://runelitepl.us
* 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.barbarianassault;
import com.google.common.collect.ImmutableSet;
import lombok.AllArgsConstructor;
import lombok.Getter;
import net.runelite.api.MenuAction;
import net.runelite.client.menus.ComparableEntry;
@AllArgsConstructor
public enum Menus
{
ATTACK_PENANCE_FIGHTER(Role.ATTACKER, new ComparableEntry("attack", "penance fighter", -1, -1, true, false)),
ATTACK_PENANCE_RANGER(Role.ATTACKER, new ComparableEntry("attack", "penance ranger", -1, -1, true, false)),
GET_SPIKES_PETRIFIED_MUSHROOM(Role.ATTACKER, new ComparableEntry("get-spikes", "petrified mushroom", -1, -1, true, true)),
TAKE_ATTACKER_ITEM_MACHINE(Role.ATTACKER, new ComparableEntry("take", "attacker item machine", -1, -1, false, true)),
TELL_RED_ATTACKER_HORN(Role.ATTACKER, new ComparableEntry("tell-red", "attacker horn", -1, -1, true, true)),
TELL_GREEN_ATTACKER_HORN(Role.ATTACKER, new ComparableEntry("tell-green", "attacker horn", -1, -1, true, true)),
TELL_BLUE_ATTACKER_HORN(Role.ATTACKER, new ComparableEntry("tell-blue", "attacker horn", -1, -1, true, true)),
BLOCK_PENANCE_CAVE(Role.DEFENDER, new ComparableEntry("block", "penance cave", -1, -1, true, true)),
DUNK_LAVA_CRATER(Role.DEFENDER, new ComparableEntry("dunk", "lava crater", -1, -1, true, true)),
FIX(Role.DEFENDER, new ComparableEntry("fix", "", -1, -1, true, false)),
STOCK_UP_DEFENDER_ITEM_MACHINE(Role.DEFENDER, new ComparableEntry("stock-up", "defender item machine", -1, -1, true, true)),
TAKE_DEFENDER_ITEM_MACHINE(Role.DEFENDER, new ComparableEntry("take", "defender item machine", -1, -1, false, true)),
TAKE_HAMMER(Role.DEFENDER, new ComparableEntry("take", "hammer", -1, -1, true, true)),
TAKE_LOGS(Role.DEFENDER, new ComparableEntry("take", "logs", -1, -1, true, true)),
TELL_WORMS_DEFENDER_HORN(Role.DEFENDER, new ComparableEntry("tell-worms", "defender horn", -1, -1, true, true)),
TELL_TOFU_DEFENDER_HORN(Role.DEFENDER, new ComparableEntry("tell-tofu", "defender horn", -1, -1, true, true)),
TELL_MEAT_DEFENDER_HORN(Role.DEFENDER, new ComparableEntry("tell-meat", "defender horn", -1, -1, true, true)),
DRINK_FROM_HEALER_SPRING(Role.HEALER, new ComparableEntry("drink-from", "healer spring", -1, -1, true, true)),
DUNK_POISON_CRATER(Role.HEALER, new ComparableEntry("dunk", "poison crater", -1, -1, true, true)),
STOCK_UP_HEALER_ITEM_MACHINE(Role.HEALER, new ComparableEntry("stock-up", "healer item machine", -1, -1, true, true)),
TAKE_HEALER_ITEM_MACHINE(Role.HEALER, new ComparableEntry("take", "healer item machine", -1, -1, false, true)),
TAKE_FROM_HEALER_SPRING(Role.HEALER, new ComparableEntry("take-from", "healer spring", -1, -1, true, true)),
TELL_TOFU_HEALER_HORN(Role.HEALER, new ComparableEntry("tell-tofu", "healer horn", -1, -1, true, true)),
TELL_CRACKERS_HEALER_HORN(Role.HEALER, new ComparableEntry("tell-crackers", "healer horn", -1, -1, true, true)),
TELL_WORMS_HEALER_HORN(Role.HEALER, new ComparableEntry("tell-worms", "healer horn", -1, -1, true, true)),
USE_VIAL_GROUND(Role.HEALER, new ComparableEntry("use", "healing vial", -1, MenuAction.ITEM_USE_ON_GROUND_ITEM.getId(), true, false)),
USE_VIAL_ITEM(Role.HEALER, new ComparableEntry("use", "healing vial", -1, MenuAction.ITEM_USE_ON_WIDGET_ITEM.getId(), true, false)),
USE_VIAL_NPC(Role.HEALER, new ComparableEntry("use", "healing vial", -1, MenuAction.ITEM_USE_ON_NPC.getId(), true, false)),
USE_VIAL_WIDGET(Role.HEALER, new ComparableEntry("use", "healing vial", -1, MenuAction.ITEM_USE_ON_WIDGET.getId(), true, false)),
CONVERT_COLLECTOR_CONVERTER(Role.COLLECTOR, new ComparableEntry("convert", "collector converter", -1, -1, true, true)),
LOAD_EGG_HOPPER(Role.COLLECTOR, new ComparableEntry("load", "egg hopper", -1, -1, true, true)),
TAKE_BLUE_EGG(Role.COLLECTOR, new ComparableEntry("take", "blue egg", -1, -1, true, true)),
TAKE_GREEN_EGG(Role.COLLECTOR, new ComparableEntry("take", "green egg", -1, -1, true, true)),
TAKE_RED_EGG(Role.COLLECTOR, new ComparableEntry("take", "red egg", -1, -1, true, true)),
TAKE_YELLOW_EGG(Role.COLLECTOR, new ComparableEntry("take", "yellow egg", -1, -1, true, true)),
TELL_CONTROLLED_COLLECTOR_HORN(Role.COLLECTOR, new ComparableEntry("tell-controlled", "collector horn", -1, -1, true, true)),
TELL_ACCURATE_COLLECTOR_HORN(Role.COLLECTOR, new ComparableEntry("tell-accurate", "collector horn", -1, -1, true, true)),
TELL_AGGRESSIVE_COLLECTOR_HORN(Role.COLLECTOR, new ComparableEntry("tell-aggressive", "collector horn", -1, -1, true, true)),
TELL_DEFENSIVE_COLLECTOR_HORN(Role.COLLECTOR, new ComparableEntry("tell-defensive", "collector horn", -1, -1, true, true)),
ATTACK_PENANCE_QUEEN(null, new ComparableEntry("attack", "penance queen", -1, -1, true, false)),
ATTACK_QUEEN_SPAWN(null, new ComparableEntry("attack", "queen spawn", -1, -1, true, false)),
DROP_HORN(null, new ComparableEntry("drop", "horn", -1, -1, true, false)),
EXAMINE_HORN(null, new ComparableEntry("examine", "horn", -1, -1, true, false)),
LIGHT_LOGS(null, new ComparableEntry("light", "logs", -1, -1, true, true)),
MEDIC_HORN(null, new ComparableEntry("medic", "horn", -1, -1, true, false)),
USE_HORN(null, new ComparableEntry("use", "horn", -1, -1, true, false));
@Getter
private final Role role;
@Getter
private final ComparableEntry entry;
private static final ImmutableSet<Menus> ALL = ImmutableSet.copyOf(Menus.values());
public String getOption()
{
return entry.getOption();
}
public String getTarget()
{
return entry.getTarget();
}
public int getId()
{
return entry.getId();
}
public int getType()
{
return entry.getType();
}
public boolean isStrictOption()
{
return entry.isStrictOption();
}
public boolean isStrictTarget()
{
return entry.isStrictTarget();
}
public static ImmutableSet<Menus> getMenus()
{
return ALL;
}
}

View File

@@ -1,5 +1,7 @@
/*
* Copyright (c) 2018, https://runelitepl.us
* Copyright (c) 2018, Cameron <https://github.com/noremac201>
* Copyright (c) 2019, 7ate9 <https://github.com/se7enAte9>
* Copyright (c) 2019, https://runelitepl.us
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -24,39 +26,211 @@
*/
package net.runelite.client.plugins.barbarianassault;
import com.google.common.collect.ImmutableMap;
import lombok.AllArgsConstructor;
import lombok.Getter;
import net.runelite.api.Client;
import net.runelite.api.ItemID;
import net.runelite.api.widgets.Widget;
import net.runelite.api.widgets.WidgetInfo;
@AllArgsConstructor
enum Role
{
ATTACKER(WidgetInfo.BA_ATK_LISTEN_TEXT, WidgetInfo.BA_ATK_CALL_TEXT, WidgetInfo.BA_ATK_ROLE_TEXT, WidgetInfo.BA_ATK_ROLE_SPRITE),
DEFENDER(WidgetInfo.BA_DEF_LISTEN_TEXT, WidgetInfo.BA_DEF_CALL_TEXT, WidgetInfo.BA_DEF_ROLE_TEXT, WidgetInfo.BA_DEF_ROLE_SPRITE),
COLLECTOR(WidgetInfo.BA_COLL_LISTEN_TEXT, WidgetInfo.BA_COLL_CALL_TEXT, WidgetInfo.BA_COLL_ROLE_TEXT, WidgetInfo.BA_COLL_ROLE_SPRITE),
HEALER(WidgetInfo.BA_HEAL_LISTEN_TEXT, WidgetInfo.BA_HEAL_CALL_TEXT, WidgetInfo.BA_HEAL_ROLE_TEXT, WidgetInfo.BA_HEAL_ROLE_SPRITE);
ATTACKER(WidgetInfo.BA_ATK_WAVE_TEXT, WidgetInfo.BA_ATK_LISTEN_TOP_TEXT, WidgetInfo.BA_ATK_HORN_LISTEN_TEXT,
WidgetInfo.BA_ATK_CALL_TEXT, WidgetInfo.BA_COLL_HORN_LISTEN_TEXT, WidgetInfo.BA_ATK_ROLE_TEXT,
WidgetInfo.BA_ATK_ROLE_SPRITE),
DEFENDER(WidgetInfo.BA_DEF_WAVE_TEXT, WidgetInfo.BA_DEF_LISTEN_TEXT, WidgetInfo.BA_DEF_HORN_LISTEN_TEXT,
WidgetInfo.BA_DEF_CALL_TEXT, WidgetInfo.BA_HEAL_HORN_LISTEN_TEXT, WidgetInfo.BA_DEF_ROLE_TEXT,
WidgetInfo.BA_DEF_ROLE_SPRITE),
COLLECTOR(WidgetInfo.BA_COLL_WAVE_TEXT, WidgetInfo.BA_COLL_LISTEN_TEXT, WidgetInfo.BA_COLL_HORN_LISTEN_TEXT,
WidgetInfo.BA_COLL_CALL_TEXT, WidgetInfo.BA_ATK_HORN_LISTEN_TEXT, WidgetInfo.BA_COLL_ROLE_TEXT,
WidgetInfo.BA_COLL_ROLE_SPRITE),
HEALER(WidgetInfo.BA_HEAL_WAVE_TEXT, WidgetInfo.BA_HEAL_LISTEN_TEXT, WidgetInfo.BA_DEF_HORN_LISTEN_TEXT,
WidgetInfo.BA_HEAL_CALL_TEXT, WidgetInfo.BA_DEF_HORN_LISTEN_TEXT, WidgetInfo.BA_HEAL_ROLE_TEXT,
WidgetInfo.BA_HEAL_ROLE_SPRITE);
@Getter
private final WidgetInfo wave;
@Getter
private final WidgetInfo listen;
@Getter
private final WidgetInfo gloryListen;
@Getter
private final WidgetInfo call;
@Getter
private final WidgetInfo gloryCall;
@Getter
private final WidgetInfo roleText;
@Getter
private final WidgetInfo roleSprite;
Role(WidgetInfo listen, WidgetInfo call, WidgetInfo role, WidgetInfo roleSprite)
// Duplicate* entries are to catch instances where the horn of glory has
// text different than the normal horn
private static final ImmutableMap<String, String> TELLS = ImmutableMap.<String, String>builder()
.put("Red egg", "Tell-red")
.put("Green egg", "Tell-green")
.put("Blue egg", "Tell-blue")
.put("Controlled/Bullet/Wind", "Tell-controlled")
.put("Accurate/Field/Water", "Tell-accurate")
.put("Aggressive/Blunt/Earth", "Tell-aggressive")
.put("Defensive/Barbed/Fire", "Tell-defensive")
.put("Tofu", "Tell-tofu")
.put("Crackers", "Tell-crackers")
.put("Worms", "Tell-worms")
.put("Poison Worms", "Tell-worms")
.put("Pois. Worms", "Tell-worms")
.put("Poison Tofu", "Tell-tofu")
.put("Pois. Tofu", "Tell-tofu")
.put("Poison Meat", "Tell-meat")
.put("Pois. Meat", "Tell-meat")
.build();
private static final ImmutableMap<String, String> GLORY_CALLS = ImmutableMap.<String, String>builder()
.put("Controlled/Bullet/Wind", "Controlled/")
.put("Accurate/Field/Water", "Accurate/")
.put("Aggressive/Blunt/Earth", "Aggressive/")
.put("Defensive/Barbed/Fire", "Defensive/")
.put("Tofu", "Tofu")
.put("Crackers", "Crackers")
.put("Worms", "Worms")
.put("Poison worms", "Pois. Worms")
.put("Poison tofu", "Pois. Tofu")
.put("Poison meat", "Pois. Meat")
.put("Red egg", "Red egg")
.put("Green egg", "Green egg")
.put("Blue egg", "Blue egg")
.build();
private static final ImmutableMap<String, Integer> ITEMS = ImmutableMap.<String, Integer>builder()
.put("Tofu", ItemID.TOFU)
.put("Crackers", ItemID.CRACKERS)
.put("Worms", ItemID.WORMS)
.put("Pois. Worms", ItemID.POISONED_WORMS)
.put("Pois. Tofu", ItemID.POISONED_TOFU)
.put("Pois. Meat", ItemID.POISONED_MEAT)
.put("Defensive/", ItemID.BARBED_ARROW)
.put("Aggressive/", ItemID.BLUNT_ARROW)
.put("Accurate/", ItemID.FIELD_ARROW)
.put("Controlled/", ItemID.BULLET_ARROW)
.build();
private static final ImmutableMap<String, String> SPLIT_LISTENS = ImmutableMap.<String, String>builder()
.put("Controlled/", "Bullet/Wind")
.put("Bullet/Wind", "Controlled/")
.put("Accurate/", "Field/Water")
.put("Field/Water", "Accurate/")
.put("Aggressive/", "Blunt/Earth")
.put("Blunt/Earth", "Aggressive/")
.put("Defensive/", "Barbed/Fire")
.put("Barbed/Fire", "Defensive/")
.build();
int getListenItem(String listen)
{
this.listen = listen;
this.call = call;
this.roleText = role;
this.roleSprite = roleSprite;
return ITEMS.getOrDefault(listen, -1);
}
@Override
public String toString()
String getTell(String call)
{
return name();
return TELLS.getOrDefault(call, "");
}
}
String getCall(Client client)
{
// Do not reverse these if statements to be more efficient
// The normal widgets are no longer null/hidden after you
// click one time in the horn, and the values are incorrect
Widget callWidget = client.getWidget(getGloryCall());
if (callWidget != null)
{
return GLORY_CALLS.get(callWidget.getText());
}
callWidget = client.getWidget(getCall());
if (callWidget != null)
{
return callWidget.getText();
}
return null;
}
String getListen(Client client)
{
// See the comment in getCall(Client client), before editing
Widget listenWidget = client.getWidget(getGloryListen());
if (listenWidget != null)
{
return GLORY_CALLS.get(listenWidget.getText());
}
listenWidget = client.getWidget(getListen());
if (listenWidget != null)
{
return listenWidget.getText();
}
return null;
}
static String getMissingListen(String listen)
{
return SPLIT_LISTENS.getOrDefault(listen, "- - -");
}
// I call it "Switchception" :wutwedoin:
// Should probably switch to using an interface instead of an enum at this point
String getCallFromTell(String listen)
{
switch (this)
{
case COLLECTOR:
switch (listen)
{
case "Tell-controlled":
return "Controlled/";
case "Tell-accurate":
return "Accurate/";
case "Tell-aggressive":
return "Aggressive/";
case "Tell-defensive":
return "Defensive/";
}
break;
case ATTACKER:
switch (listen)
{
case "Tell-red":
return "Red egg";
case "Tell-green":
return "Green egg";
case "Tell-blue":
return "Blue egg";
}
break;
case HEALER:
switch (listen)
{
case "Tell-tofu":
return "Tofu";
case "Tell-crackers":
return "Crackers";
case "Tell-worms":
return "Worms";
}
break;
case DEFENDER:
switch (listen)
{
case "Tell-meat":
return "Pois. Meat";
case "Tell-tofu":
return "Pois. Tofu";
case "Tell-worms":
return "Pois. Worms";
}
break;
}
return null;
}
}

View File

@@ -1,5 +1,6 @@
/*
* Copyright (c) 2018, https://runelitepl.us
* Copyright (c) 2018, Jacob M <https://github.com/jacoblairm>
* Copyright (c) 2019, https://runelitepl.us
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -26,18 +27,21 @@ package net.runelite.client.plugins.barbarianassault;
import java.awt.Color;
import java.util.ArrayList;
import lombok.AccessLevel;
import lombok.Getter;
import net.runelite.api.Client;
import net.runelite.api.events.ChatMessage;
import net.runelite.client.chat.ChatMessageBuilder;
import net.runelite.client.eventbus.Subscribe;
@Getter
public class Game
public class Scorecard
{
private Client client;
private String currentWave;
private ArrayList<Wave> Waves = new ArrayList<>();
private BarbarianAssaultPlugin game;
@Getter(AccessLevel.NONE)
private ArrayList<Wave> waves = new ArrayList<>();
private String[] totalDescriptions = {
"A: ",
"; D: ",
@@ -55,46 +59,46 @@ public class Game
private int[] totalAmounts = new int[6];
private int[] otherRolesPoints = new int[4];
Game(Client client)
Scorecard(BarbarianAssaultPlugin game)
{
this.client = client;
}
Game(Client client, ArrayList<Wave> waves)
{
this.client = client;
this.Waves = waves;
this.game = game;
}
@Subscribe
public void onChatMessage(ChatMessage chatMessage)
{
if (chatMessage.getMessage().startsWith("---- Wave:"))
if (chatMessage.getMessage().startsWith("---- Points:"))
{
String[] tempMessage = chatMessage.getMessage().split(" ");
currentWave = tempMessage[2];
String[] temp = currentWave.split(" ");
}
if (currentWave.equals("1"))
{
Waves = null;
totalPoints = new int[6];
totalAmounts = new int[6];
if (game.getStage() == 1)
{
totalPoints = new int[6];
totalAmounts = new int[6];
}
}
}
void addWave(Wave wave)
{
this.waves.add(wave);
}
int getNumberOfWaves()
{
return waves.size();
}
ChatMessageBuilder getGameSummary()
{
int[] amountsList;
int[] pointsList;
int[] otherRolesPointsList;
ChatMessageBuilder message = new ChatMessageBuilder();
message.append("Round points: ");
for (Wave w : Waves)
message.append("Game points: ");
for (Wave wave : waves)
{
amountsList = w.getWaveAmounts();
pointsList = w.getWavePoints();
otherRolesPointsList = w.getOtherRolesPointsList();
amountsList = wave.getAmounts();
pointsList = wave.getPoints();
otherRolesPointsList = wave.getOtherRolesPointsList();
for (int j = 0; j < totalAmounts.length; j++)
{
totalAmounts[j] += amountsList[j];

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, https://runelitepl.us
* Copyright (c) 2019, https://runelitepl.us
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -24,37 +24,31 @@
*/
package net.runelite.client.plugins.barbarianassault;
import lombok.Getter;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import net.runelite.api.Constants;
class GameTimer
class Timer
{
final private Instant startTime = Instant.now();
private Instant prevWave = startTime;
@Getter
private final Instant startTime;
String getTime(boolean waveTime)
Timer()
{
final Instant now = Instant.now();
final Duration elapsed;
if (waveTime)
{
elapsed = Duration.between(prevWave, now);
}
else
{
elapsed = Duration.between(startTime, now).minusMillis(Constants.GAME_TICK_LENGTH);
}
return formatTime(LocalTime.ofSecondOfDay(elapsed.getSeconds()));
this.startTime = Instant.now();
}
void setWaveStartTime()
long getElapsedTime()
{
prevWave = Instant.now();
return Duration.between(startTime, Instant.now()).getSeconds();
}
String getElapsedTimeFormatted()
{
return formatTime(LocalTime.ofSecondOfDay(getElapsedTime()));
}
private static String formatTime(LocalTime time)

View File

@@ -1,5 +1,6 @@
/*
* Copyright (c) 2018, Cameron <https://github.com/noremac201>
* Copyright (c) 2019, 7ate9 <https://github.com/se7enAte9>
* Copyright (c) 2019, https://runelitepl.us
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -24,50 +25,65 @@
*/
package net.runelite.client.plugins.barbarianassault;
import java.time.Duration;
import java.time.Instant;
import javax.inject.Inject;
import lombok.Getter;
import lombok.Setter;
import net.runelite.api.Constants;
import lombok.Data;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.ui.overlay.infobox.InfoBox;
class Round
import java.awt.Color;
import java.awt.image.BufferedImage;
@Data
public class TimerBox extends InfoBox
{
private final Instant roundStartTime;
private int count;
@Getter
private final Role roundRole;
private boolean inSync = true;
@Getter
@Setter
private boolean runnersKilled;
private boolean tooltipEnabled = false;
@Getter
@Setter
private boolean rangersKilled;
@Getter
@Setter
private boolean healersKilled;
@Getter
@Setter
private boolean fightersKilled;
@Inject
public Round(Role role)
TimerBox(BufferedImage image, Plugin plugin, int count)
{
this.roundRole = role;
this.roundStartTime = Instant.now().plusMillis(2 * Constants.GAME_TICK_LENGTH);
super(image, plugin);
this.count = count;
}
public long getRoundTime()
@Override
public String getText()
{
return Duration.between(roundStartTime, Instant.now()).getSeconds();
if (count == -1)
{
return "";
}
return Integer.toString(getCount());
}
long getTimeToChange()
@Override
public Color getTextColor()
{
return 30 + (Duration.between(Instant.now(), roundStartTime).getSeconds() % 30);
if (inSync)
{
return Color.WHITE;
}
else
{
return Color.RED;
}
}
@Override
public String getTooltip()
{
if (!tooltipEnabled)
{
return "";
}
else if (inSync)
{
return "<col=00FF00>Valid";
}
else
{
return "<col=FF0000>Invalid";
}
}
}

View File

@@ -1,5 +1,7 @@
/*
* Copyright (c) 2018, https://runelitepl.us
* Copyright (c) 2018, Jacob M <https://github.com/jacoblairm>
* Copyright (c) 2019, 7ate9 <https://github.com/se7enAte9>
* Copyright (c) 2019, https://runelitepl.us
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -25,90 +27,105 @@
package net.runelite.client.plugins.barbarianassault;
import com.google.common.collect.ImmutableList;
import java.awt.Color;
import lombok.AccessLevel;
import lombok.Data;
import lombok.Getter;
import net.runelite.api.Client;
import net.runelite.api.widgets.Widget;
import net.runelite.api.widgets.WidgetInfo;
import net.runelite.client.chat.ChatMessageBuilder;
@Getter
class Wave
{
private Client client;
private final ImmutableList<WidgetInfo> WIDGETS = ImmutableList.of(
WidgetInfo.BA_FAILED_ATTACKER_ATTACKS,
WidgetInfo.BA_RUNNERS_PASSED,
WidgetInfo.BA_EGGS_COLLECTED,
WidgetInfo.BA_HITPOINTS_REPLENISHED,
WidgetInfo.BA_WRONG_POISON_PACKS,
WidgetInfo.BA_HONOUR_POINTS_REWARD
);
private final ImmutableList<WidgetInfo> POINTSWIDGETS = ImmutableList.of(
//base
WidgetInfo.BA_BASE_POINTS,
//att
WidgetInfo.BA_FAILED_ATTACKER_ATTACKS_POINTS,
WidgetInfo.BA_RANGERS_KILLED,
WidgetInfo.BA_FIGHTERS_KILLED,
//def
WidgetInfo.BA_RUNNERS_PASSED_POINTS,
WidgetInfo.BA_RUNNERS_KILLED,
//coll
WidgetInfo.BA_EGGS_COLLECTED_POINTS,
//heal
WidgetInfo.BA_HEALERS_KILLED,
WidgetInfo.BA_HITPOINTS_REPLENISHED_POINTS,
WidgetInfo.BA_WRONG_POISON_PACKS_POINTS
);
private int[] waveAmounts = new int[6];
private int[] allPointsList = new int[10];
private int[] wavePoints = new int[6];
private int[] otherRolesPointsList = new int[4];
private String[] descriptions = {
" A: ",
"; D: ",
"; C: ",
"; Vial: ",
"; H packs: ",
"; Total: "};
import java.awt.Color;
private String[] otherPointsDescriptions = {
" A: ",
" D: ",
" C: ",
" H: "
};
@Data
public class Wave
{
@Getter(AccessLevel.NONE)
private static final ImmutableList<WidgetInfo> WIDGETS = ImmutableList.of(
WidgetInfo.BA_FAILED_ATTACKER_ATTACKS,
WidgetInfo.BA_RUNNERS_PASSED,
WidgetInfo.BA_EGGS_COLLECTED,
WidgetInfo.BA_HITPOINTS_REPLENISHED,
WidgetInfo.BA_WRONG_POISON_PACKS,
WidgetInfo.BA_HONOUR_POINTS_REWARD
);
@Getter(AccessLevel.NONE)
private static final ImmutableList<WidgetInfo> POINTSWIDGETS = ImmutableList.of(
//Base
WidgetInfo.BA_BASE_POINTS,
//Attacker
WidgetInfo.BA_FAILED_ATTACKER_ATTACKS_POINTS,
WidgetInfo.BA_RANGERS_KILLED,
WidgetInfo.BA_FIGHTERS_KILLED,
//Defender
WidgetInfo.BA_RUNNERS_PASSED_POINTS,
WidgetInfo.BA_RUNNERS_KILLED,
//Collector
WidgetInfo.BA_EGGS_COLLECTED_POINTS,
//Healer
WidgetInfo.BA_HEALERS_KILLED,
WidgetInfo.BA_HITPOINTS_REPLENISHED_POINTS,
WidgetInfo.BA_WRONG_POISON_PACKS_POINTS
);
@Getter(AccessLevel.NONE)
private final Client client;
private final Timer waveTimer;
private boolean runnersKilled;
private boolean rangersKilled;
private boolean healersKilled;
private boolean fightersKilled;
private int collectedEggCount = 0;
private int positiveEggCount = 0;
private int wrongEggs = 0;
private int hpHealed = 0;
private int totalCollectedEggCount = 0;
private int totalHpHealed = 0;
private int[] amounts = new int[6];
private int[] allPointsList = new int[10];
private int[] points = new int[6];
private int[] otherRolesPointsList = new int[4];
private String[] descriptions = {" A: ", "; D: ", "; C: ", "; Vial: ", "; H packs: ", "; Total: "};
private String[] otherPointsDescriptions = {" A: ", " D: ", " C: ", " H: "};
Wave(Client client)
{
this.client = client;
this.waveTimer = new Timer();
}
void setWaveAmounts(int[] amounts)
{
System.arraycopy(amounts, 0, waveAmounts, 0, amounts.length);
}
void setWavePoints(int[] points, int[] otherRolesPoints)
{
System.arraycopy(points, 0, wavePoints, 0, points.length);
System.arraycopy(otherRolesPoints, 0, otherRolesPointsList, 0, otherRolesPoints.length);
}
void setWaveAmounts()
void setAmounts()
{
for (int i = 0; i < WIDGETS.size(); i++)
{
Widget w = client.getWidget(WIDGETS.get(i));
if (w != null)
{
waveAmounts[i] = Integer.parseInt(w.getText());
amounts[i] = Integer.parseInt(w.getText());
}
}
}
void setWavePoints()
void setPoints()
{
for (int i = 0; i < POINTSWIDGETS.size(); i++)
{
@@ -117,26 +134,26 @@ class Wave
switch (i)
{
case 1:
wavePoints[0] += allPointsList[i];
points[0] += allPointsList[i];
break;
case 4:
wavePoints[1] += allPointsList[i];
points[1] += allPointsList[i];
break;
case 6:
wavePoints[2] += allPointsList[i];
points[2] += allPointsList[i];
break;
case 8:
case 9:
wavePoints[3] += allPointsList[i];
points[3] += allPointsList[i];
break;
default:
break;
}
}
wavePoints[5] = 0;
for (int i = 0; i < wavePoints.length - 1; i++)
points[5] = 0;
for (int i = 0; i < points.length - 1; i++)
{
wavePoints[5] += wavePoints[i];
points[5] += points[i];
}
for (int i = 0; i < POINTSWIDGETS.size(); i++)
{
@@ -166,37 +183,35 @@ class Wave
case 9:
otherRolesPointsList[3] += Integer.parseInt(w.getText());
break;
default:
break;
}
}
}
ChatMessageBuilder getWaveSummary()
ChatMessageBuilder getSummary()
{
ChatMessageBuilder message = new ChatMessageBuilder();
message.append("Wave points:");
for (int i = 0; i < descriptions.length; i++)
{
if (i != 4)
message.append(descriptions[i]);
if (i != 5)
{
message.append(descriptions[i]);
message.append(String.valueOf(waveAmounts[i]));
message.append("(");
if (wavePoints[i] < 0)
{
message.append(Color.RED, String.valueOf(wavePoints[i]));
}
else if (wavePoints[i] > 0)
{
message.append(Color.BLUE, String.valueOf(wavePoints[i]));
}
else
{
message.append(String.valueOf(wavePoints[i]));
}
message.append(")");
message.append(String.valueOf(amounts[i]));
}
message.append("(");
if (points[i] < 0)
{
message.append(Color.RED, String.valueOf(points[i]));
}
else if (points[i] > 0)
{
message.append(Color.BLUE, String.valueOf(points[i]));
}
else
{
message.append(String.valueOf(points[i]));
}
message.append(")");
}
message.append(System.getProperty("line.separator"));
message.append("All roles points this wave: ");

Binary file not shown.

Before

Width:  |  Height:  |  Size: 197 B

View File

@@ -1,214 +0,0 @@
/*
* Copyright (c) 2018, https://runelitepl.us
* 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.batools;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup("BATools")
public interface BAToolsConfig extends Config
{
@ConfigItem(
keyName = "defTimer",
name = "Defender Tick Timer",
description = "Shows the current cycle tick of runners."
)
default boolean defTimer()
{
return false;
}
@ConfigItem(
keyName = "calls",
name = "Remove Incorrect Calls",
description = "Remove incorrect calls."
)
default boolean calls()
{
return false;
}
@ConfigItem(
keyName = "swapLadder",
name = "Swap ladder option",
description = "Swap Climb-down with Quick-start in the wave lobbies"
)
default boolean swapLadder()
{
return true;
}
@ConfigItem(
keyName = "swapCollectorBag",
name = "swaps collector bag in ba to empty left click",
description = "Make empty the left-click option on collector bag"
)
default boolean swapCollectorBag()
{
return false;
}
@ConfigItem(
keyName = "swapDestroyEggs",
name = "Left click destroy eggs in BA",
description = "Make destroy the left-click option for collector eggs"
)
default boolean swapDestroyEggs()
{
return false;
}
@ConfigItem(
keyName = "healerCodes",
name = "Healer Codes",
description = "Overlay to show healer codes"
)
default boolean healerCodes()
{
return false;
}
@ConfigItem(
keyName = "healerMenuOption",
name = "Healer menu options",
description = "Shows time since last food placed on healer"
)
default boolean healerMenuOption()
{
return false;
}
@ConfigItem(
keyName = "eggBoi",
name = "Collector helper",
description = "Hold shift to collect the correct egg"
)
default boolean eggBoi()
{
return false;
}
@ConfigItem(
keyName = "osHelp",
name = "Shift OS",
description = "Hold shift to only pick up correct eggs"
)
default boolean osHelp()
{
return false;
}
@ConfigItem(
keyName = "prayerMetronome",
name = "Prayer Metronome",
description = "Similar to metronome plugin but only activates when a prayer is active"
)
default boolean prayerMetronome()
{
return false;
}
@ConfigItem(
keyName = "prayerMetronomeVolume",
name = "Prayer Metronome Volume",
description = "Volume level"
)
default int prayerMetronomeVolume()
{
return 1;
}
@ConfigItem(
keyName = "attackStyles",
name = "Attack Styles",
description = "Hide attack styles depending on weapon."
)
default boolean attackStyles()
{
return false;
}
@ConfigItem(
keyName = "removeBA",
name = "*Barbarian Assault Helper*",
description = "Remove unnecessary menu options in Barbarian Assault depending on role<br>Examples: Remove attack options when not attacker<br>Remove take options when not collector"
)
default boolean removeBA()
{
return true;
}
@ConfigItem(
keyName = "removeWrongEggs",
name = "Remove wrong eggs - *Barbarian Assault Helper*",
description = "Remove unnecessary menu options in Barbarian Assault depending on role<br>Examples: Remove attack options when not attacker<br>Remove take options when not collector"
)
default boolean removeWrongEggs()
{
return false;
}
@ConfigItem(
keyName = "removeWrongHealFood",
name = "Remove wrong Heal Food - *Barbarian Assault Helper*",
description = "Remove unnecessary menu options in Barbarian Assault depending on role<br>Examples: Remove attack options when not attacker<br>Remove take options when not collector"
)
default boolean removeHealWrongFood()
{
return false;
}
@ConfigItem(
keyName = "tagging",
name = "Attack Tags",
description = "Highlights the menu entry of an attacker/ranger that has not been tagged."
)
default boolean tagging()
{
return false;
}
@ConfigItem(
keyName = "ctrlHealer",
name = "Control Healer",
description = "Hold ctrl to put last healer clicked on top"
)
default boolean ctrlHealer()
{
return false;
}
@ConfigItem(
keyName = "removePenanceCave",
name = "Remove Block Penance Cave",
description = "Removes unnecessary menu option, however Moon wanted it back"
)
default boolean removePenanceCave()
{
return false;
}
}

View File

@@ -1,101 +0,0 @@
/*
* Copyright (c) 2018, https://runelitepl.us
* 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.batools;
import java.awt.Color;
import static java.awt.Color.GREEN;
import static java.awt.Color.RED;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.time.Duration;
import java.time.Instant;
import javax.inject.Inject;
import lombok.extern.slf4j.Slf4j;
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;
@Slf4j
public class BAToolsOverlay extends Overlay
{
private final BAToolsConfig config;
private BAToolsPlugin plugin;
@Inject
public BAToolsOverlay(BAToolsPlugin plugin, BAToolsConfig config)
{
setPosition(OverlayPosition.DYNAMIC);
setLayer(OverlayLayer.ABOVE_SCENE);
this.config = config;
this.plugin = plugin;
}
@Override
public Dimension render(Graphics2D graphics)
{
if (!config.healerCodes())
{
return null;
}
for (Healer healer : plugin.getHealers().values())
{
Color color;
int timeLeft = healer.getLastFoodTime() - (int) Duration.between(plugin.getWave_start(), Instant.now()).getSeconds();
timeLeft = timeLeft < 1 ? 0 : timeLeft;
if (healer.getFoodRemaining() > 1)
{
color = GREEN;
}
else if (healer.getFoodRemaining() == 1)
{
if (timeLeft > 0)
{
color = RED;
}
else
{
color = GREEN;
}
}
else
{
continue;
}
String text = String.format("%d %d",
healer.getFoodRemaining(),
timeLeft);
OverlayUtil.renderActorOverlay(graphics, healer.getNpc(), text, color);
}
return null;
}
}

View File

@@ -1,862 +0,0 @@
/*
* Copyright (c) 2018, https://runelitepl.us
* 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.batools;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Provides;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Actor;
import net.runelite.api.ChatMessageType;
import net.runelite.api.Client;
import net.runelite.api.ItemID;
import net.runelite.api.MenuEntry;
import net.runelite.api.NPC;
import net.runelite.api.NpcID;
import net.runelite.api.Prayer;
import net.runelite.api.SoundEffectID;
import net.runelite.api.Varbits;
import net.runelite.api.coords.WorldPoint;
import net.runelite.api.events.ChatMessage;
import net.runelite.api.events.ConfigChanged;
import net.runelite.api.events.GameTick;
import net.runelite.api.events.HitsplatApplied;
import net.runelite.api.events.InteractingChanged;
import net.runelite.api.events.MenuEntryAdded;
import net.runelite.api.events.MenuOptionClicked;
import net.runelite.api.events.NpcDespawned;
import net.runelite.api.events.NpcSpawned;
import net.runelite.api.events.VarbitChanged;
import net.runelite.api.events.WidgetLoaded;
import net.runelite.api.widgets.Widget;
import net.runelite.api.widgets.WidgetID;
import net.runelite.api.widgets.WidgetInfo;
import static net.runelite.api.widgets.WidgetInfo.BA_ATK_CALL_TEXT;
import static net.runelite.api.widgets.WidgetInfo.BA_ATK_LISTEN_TEXT;
import static net.runelite.api.widgets.WidgetInfo.BA_ATK_ROLE_TEXT;
import static net.runelite.api.widgets.WidgetInfo.BA_COLL_CALL_TEXT;
import static net.runelite.api.widgets.WidgetInfo.BA_COLL_LISTEN_TEXT;
import static net.runelite.api.widgets.WidgetInfo.BA_COLL_ROLE_TEXT;
import static net.runelite.api.widgets.WidgetInfo.BA_DEF_CALL_TEXT;
import static net.runelite.api.widgets.WidgetInfo.BA_DEF_ROLE_TEXT;
import static net.runelite.api.widgets.WidgetInfo.BA_HEAL_CALL_TEXT;
import static net.runelite.api.widgets.WidgetInfo.BA_HEAL_LISTEN_TEXT;
import static net.runelite.api.widgets.WidgetInfo.COMBAT_STYLE_FOUR;
import static net.runelite.api.widgets.WidgetInfo.COMBAT_STYLE_ONE;
import static net.runelite.api.widgets.WidgetInfo.COMBAT_STYLE_THREE;
import static net.runelite.api.widgets.WidgetInfo.COMBAT_STYLE_TWO;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.game.ItemManager;
import net.runelite.client.input.KeyListener;
import net.runelite.client.input.KeyManager;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.plugins.PluginType;
import net.runelite.client.ui.overlay.OverlayManager;
import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
import net.runelite.client.util.Text;
import org.apache.commons.lang3.ArrayUtils;
import net.runelite.client.menus.MenuManager;
@Slf4j
@PluginDescriptor(
name = "BA Tools",
description = "Custom tools for Barbarian Assault",
tags = {"minigame", "overlay", "timer"},
type = PluginType.PVM,
enabledByDefault = false
)
public class BAToolsPlugin extends Plugin implements KeyListener
{
private boolean inGame;
private int tickNum;
private int pastCall = 0;
private int currentWave = 1;
private int lastHealer;
private static final int BA_WAVE_NUM_INDEX = 2;
private static final WorldPoint healerSpawnPoint = new WorldPoint(1898, 1586, 0);
private final List<MenuEntry> entries = new ArrayList<>();
private ImmutableMap<WidgetInfo, Boolean> originalAttackStyles;
private HashMap<Integer, Instant> foodPressed = new HashMap<>();
private CycleCounter counter;
private Actor lastInteracted;
private boolean shiftDown;
private boolean ctrlDown;
@Inject
private Client client;
@Inject
private OverlayManager overlayManager;
@Inject
private BAToolsConfig config;
@Inject
private ItemManager itemManager;
@Inject
private InfoBoxManager infoBoxManager;
@Inject
private BAToolsOverlay overlay;
@Getter
private Map<NPC, Healer> healers;
@Getter
private Instant wave_start;
@Inject
private MenuManager menuManager;
@Inject
private KeyManager keyManager;
@Provides
BAToolsConfig provideConfig(ConfigManager configManager)
{
return configManager.getConfig(BAToolsConfig.class);
}
@Override
protected void startUp() throws Exception
{
overlayManager.add(overlay);
healers = new HashMap<>();
wave_start = Instant.now();
//lastInteracted = null;
foodPressed.clear();
keyManager.registerKeyListener(this);
}
@Override
protected void shutDown() throws Exception
{
removeCounter();
healers.clear();
inGame = false;
lastInteracted = null;
overlayManager.remove(overlay);
keyManager.unregisterKeyListener(this);
shiftDown = false;
}
@Subscribe
public void onWidgetLoaded(WidgetLoaded event)
{
switch (event.getGroupId())
{
case WidgetID.BA_REWARD_GROUP_ID:
{
Widget rewardWidget = client.getWidget(WidgetInfo.BA_REWARD_TEXT);
if (rewardWidget != null && rewardWidget.getText().contains("<br>5"))
{
tickNum = 0;
}
}
}
}
@Subscribe
public void onGameTick(GameTick event)
{
Widget callWidget = getWidget();
if (callWidget != null)
{
if (callWidget.getTextColor() != pastCall && callWidget.getTextColor() == 16316664)
{
tickNum = 0;
}
pastCall = callWidget.getTextColor();
}
if (inGame && config.defTimer())
{
if (tickNum > 9)
{
tickNum = 0;
}
if (counter == null)
{
addCounter();
lastHealer = 0;
}
counter.setCount(tickNum);
tickNum++;
}
Widget weapon = client.getWidget(593, 1);
if (config.attackStyles()
&& weapon != null
&& inGame
&& weapon.getText().contains("Crystal halberd") || weapon.getText().contains("Dragon claws")
&& client.getWidget(BA_ATK_LISTEN_TEXT) != null)
{
if (originalAttackStyles == null)
{
ImmutableMap.Builder<WidgetInfo, Boolean> builder = new ImmutableMap.Builder<>();
builder.put(COMBAT_STYLE_ONE, client.getWidget(COMBAT_STYLE_ONE).isHidden());
builder.put(COMBAT_STYLE_TWO, client.getWidget(COMBAT_STYLE_TWO).isHidden());
builder.put(COMBAT_STYLE_THREE, client.getWidget(COMBAT_STYLE_THREE).isHidden());
builder.put(COMBAT_STYLE_FOUR, client.getWidget(COMBAT_STYLE_FOUR).isHidden());
originalAttackStyles = builder.build();
}
String style = client.getWidget(BA_ATK_LISTEN_TEXT).getText();
if (style.contains("Defensive"))
{
client.getWidget(COMBAT_STYLE_ONE).setHidden(true);
client.getWidget(COMBAT_STYLE_TWO).setHidden(true);
client.getWidget(COMBAT_STYLE_THREE).setHidden(true);
client.getWidget(COMBAT_STYLE_FOUR).setHidden(false);
}
else if (style.contains("Aggressive"))
{
client.getWidget(COMBAT_STYLE_ONE).setHidden(true);
client.getWidget(COMBAT_STYLE_TWO).setHidden(false);
client.getWidget(COMBAT_STYLE_THREE).setHidden(true);
client.getWidget(COMBAT_STYLE_FOUR).setHidden(true);
}
else if (style.contains("Controlled"))
{
if (weapon.getText().contains("Crystal halberd"))
{
client.getWidget(COMBAT_STYLE_ONE).setHidden(false);
client.getWidget(COMBAT_STYLE_THREE).setHidden(true);
}
else
{
client.getWidget(COMBAT_STYLE_ONE).setHidden(true);
client.getWidget(COMBAT_STYLE_THREE).setHidden(false);
}
client.getWidget(COMBAT_STYLE_TWO).setHidden(true);
client.getWidget(COMBAT_STYLE_FOUR).setHidden(true);
}
else if (style.contains("Accurate") && weapon.getText().contains("Dragon claws"))
{
client.getWidget(COMBAT_STYLE_ONE).setHidden(false);
client.getWidget(COMBAT_STYLE_TWO).setHidden(true);
client.getWidget(COMBAT_STYLE_THREE).setHidden(true);
client.getWidget(COMBAT_STYLE_FOUR).setHidden(true);
}
else
{
client.getWidget(COMBAT_STYLE_ONE).setHidden(false);
client.getWidget(COMBAT_STYLE_TWO).setHidden(false);
client.getWidget(COMBAT_STYLE_THREE).setHidden(false);
client.getWidget(COMBAT_STYLE_FOUR).setHidden(false);
}
}
else if (originalAttackStyles != null)
{
originalAttackStyles.forEach((w, b) -> client.getWidget(w).setHidden(b));
}
if (config.prayerMetronome() && isAnyPrayerActive())
{
for (int i = 0; i < config.prayerMetronomeVolume(); i++)
{
client.playSoundEffect(SoundEffectID.GE_INCREMENT_PLOP);
}
}
}
private Widget getWidget()
{
if (client.getWidget(BA_DEF_CALL_TEXT) != null)
{
return client.getWidget(BA_DEF_CALL_TEXT);
}
else if (client.getWidget(BA_ATK_CALL_TEXT) != null)
{
return client.getWidget(BA_ATK_CALL_TEXT);
}
else if (client.getWidget(BA_COLL_CALL_TEXT) != null)
{
return client.getWidget(BA_COLL_CALL_TEXT);
}
else if (client.getWidget(BA_HEAL_CALL_TEXT) != null)
{
return client.getWidget(BA_HEAL_CALL_TEXT);
}
return null;
}
@Subscribe
public void onVarbitChanged(VarbitChanged event)
{
int inGameBit = client.getVar(Varbits.IN_GAME_BA);
if (inGameBit == 1 && !inGame ||
inGameBit == 0 && inGame)
{
inGame = inGameBit == 1;
if (!inGame)
{
pastCall = 0;
removeCounter();
foodPressed.clear();
}
else
{
addCounter();
}
}
}
@Subscribe
public void onChatMessage(ChatMessage event)
{
if (event.getType() == ChatMessageType.GAMEMESSAGE
&& event.getMessage().startsWith("---- Wave:"))
{
String[] message = event.getMessage().split(" ");
currentWave = Integer.parseInt(message[BA_WAVE_NUM_INDEX]);
wave_start = Instant.now();
healers.clear();
}
}
@Subscribe
public void onNpcSpawned(NpcSpawned event)
{
NPC npc = event.getNpc();
if (inGame && isNpcHealer(npc.getId()))
{
if (checkNewSpawn(npc) || Duration.between(wave_start, Instant.now()).getSeconds() < 16)
{
int spawnNumber = healers.size();
healers.put(npc, new Healer(npc, spawnNumber, currentWave));
}
}
}
@Subscribe
public void onHitsplatApplied(HitsplatApplied hitsplatApplied)
{
Actor actor = hitsplatApplied.getActor();
if (healers.isEmpty() && !(actor instanceof NPC) && lastInteracted == null)
{
return;
}
for (Healer healer : healers.values())
{
if (healer.getNpc() == actor && actor == lastInteracted)
{
healer.setFoodRemaining(healer.getFoodRemaining() - 1);
}
}
}
@Subscribe
public void onNpcDespawned(NpcDespawned event)
{
healers.remove(event.getNpc());
}
@Subscribe
public void onInteractingChanged(InteractingChanged event)
{
Actor opponent = event.getTarget();
if (opponent instanceof NPC && isNpcHealer(((NPC) opponent).getId()) && event.getSource() != client.getLocalPlayer())
{
lastInteracted = opponent;
}
}
private static boolean isNpcHealer(int npcId)
{
return npcId == NpcID.PENANCE_HEALER ||
npcId == NpcID.PENANCE_HEALER_5766 ||
npcId == NpcID.PENANCE_HEALER_5767 ||
npcId == NpcID.PENANCE_HEALER_5768 ||
npcId == NpcID.PENANCE_HEALER_5769 ||
npcId == NpcID.PENANCE_HEALER_5770 ||
npcId == NpcID.PENANCE_HEALER_5771 ||
npcId == NpcID.PENANCE_HEALER_5772 ||
npcId == NpcID.PENANCE_HEALER_5773 ||
npcId == NpcID.PENANCE_HEALER_5774;
}
@Subscribe
public void onMenuEntryAdded(MenuEntryAdded event)
{
final int itemId = event.getIdentifier();
String option = Text.removeTags(event.getOption()).toLowerCase();
String target = Text.removeTags(event.getTarget()).toLowerCase();
if (config.swapDestroyEggs() & (target.equals("red egg") || target.equals("green egg") || target.equals("blue egg")))
{
menuManager.addSwap("destroy", option, target);
}
if (config.swapCollectorBag() & target.equals("collection bag"))
{
menuManager.addSwap("empty", option, target);
}
if (config.swapLadder() && option.equals("climb-down") && target.equals("ladder"))
{
menuManager.addSwap("Quick-start", option, target);
}
else if (config.removeBA() && client.getVar(Varbits.IN_GAME_BA) == 1 && !option.contains("tell-"))//if in barbarian assault and menu isnt from a horn
{
if (itemId == ItemID.LOGS && !target.contains("healing vial"))
{
if (client.getWidget(BA_DEF_ROLE_TEXT) == null)
{
remove(new String[]{"take", "light"}, target);
}
else //remove "Light" option (and "Take" option if not defender).
{
remove("light", target);
}
}
else if (option.equals("use"))
{
if (config.removeHealWrongFood())
{
Widget healer = client.getWidget(BA_HEAL_LISTEN_TEXT);
if (healer != null)
{
String item = target.split("-")[0].trim();
List<String> poison = Arrays.asList("poisoned tofu", "poisoned meat", "poisoned worms");
List<String> vials = Arrays.asList("healing vial", "healing vial(1)", "healing vial(2)", "healing vial(3)", "healing vial(4)");//"healing vial(4)"
if (poison.contains(item))
{
//if item is a poison item
int calledPoison = 0;
switch (healer.getText())//choose which poison to hide the use/destroy option for
{
case "Pois. Tofu":
calledPoison = ItemID.POISONED_TOFU;
break;
case "Pois. Meat":
calledPoison = ItemID.POISONED_MEAT;
break;
case "Pois. Worms":
calledPoison = ItemID.POISONED_WORMS;
break;
}
if (target.equals(item))//if targeting the item itself
{
if (calledPoison != 0 && itemId != calledPoison)//if no call or chosen item is not the called one
{
remove(new String[]{"use", "destroy", "examine"}, target);//remove options
}
}
else if (!target.contains("penance healer"))
{
remove(option, target);
}
}
else if (vials.contains(item))//if item is the healer's healing vial
{
if (!target.equals(item))//if target is not the vial itself
{
if (!target.contains("level") || target.contains("penance") || target.contains("queen spawn"))//if someone has "penance" or "queen spawn" in their name, gg...
{
remove(option, target);
}
}
}
}
}
}
else if (option.equals("attack") && client.getWidget(BA_ATK_ROLE_TEXT) == null && !target.equals("queen spawn"))//if not attacker
{
//remove attack option from everything but queen spawns
remove(option, target);
}
else if ((option.equals("fix")) && client.getWidget(WidgetInfo.BA_DEF_ROLE_TEXT) == null)//if not defender
{
remove(option, target);
}
else if ((option.equals("block") && target.equals("penance cave") && config.removePenanceCave()))
{
remove(option, target);
}
else if ((option.equals("load")) && client.getWidget(BA_COLL_ROLE_TEXT) == null)//if not collector, remove hopper options
{
remove(new String[]{option, "look-in"}, target);
}
else if (config.removeWrongEggs() && option.equals("take"))
{
Widget eggToColl = client.getWidget(BA_COLL_LISTEN_TEXT);
if (eggToColl != null)//if we're a collector
{
List<Integer> eggsToHide = new ArrayList<>();
eggsToHide.add(ItemID.HAMMER);
switch (eggToColl.getText())//choose which eggs to hide take option for
{
case "Red eggs":
eggsToHide.add(ItemID.BLUE_EGG);
eggsToHide.add(ItemID.GREEN_EGG);
break;
case "Blue eggs":
eggsToHide.add(ItemID.RED_EGG);
eggsToHide.add(ItemID.GREEN_EGG);
break;
case "Green eggs":
eggsToHide.add(ItemID.RED_EGG);
eggsToHide.add(ItemID.BLUE_EGG);
break;
}
if (eggsToHide.contains(itemId))
{
remove(option, target);//hide wrong eggs
}
}
else
{
List<Integer> defenderItems = Arrays.asList(ItemID.HAMMER, ItemID.TOFU, ItemID.CRACKERS, ItemID.WORMS);//logs are handled separately due to hiding "light" option too.
if (client.getWidget(BA_DEF_ROLE_TEXT) == null || !defenderItems.contains(itemId))//if not defender, or item is not a defenderItem
{
remove(option, target);//hide everything except hammer/logs and bait if Defender
}
}
}
}
if (client.getWidget(WidgetInfo.BA_HEAL_CALL_TEXT) == getWidget() && lastHealer != 0 && inGame && config.ctrlHealer() && ctrlDown)
{
MenuEntry[] menuEntries = client.getMenuEntries();
MenuEntry correctHealer = null;
entries.clear();
for (MenuEntry entry : menuEntries)
{
if (( entry.getIdentifier() == lastHealer && entry.getOption().equals("Use"))
||
(
(entry.getTarget().equals("<col=ff9040>Poisoned meat") || entry.getTarget().equals("<col=ff9040>Poisoned worms") || entry.getTarget().equals("<col=ff9040>Poisoned tofu"))
&&
entry.getOption().equals("Use")
)
)
{
correctHealer = entry;
}
else
{
log.info((entry.getIdentifier() == lastHealer && entry.getOption().equals("Use")) + " " + ((entry.getTarget().equals("<col=ff9040>Poisoned meat") || entry.getTarget().equals("<col=ff9040>Poisoned worms") || entry.getTarget().equals("<col=ff9040>Poisoned tofu")) && entry.getOption().equals("Use")) );
}
}
if (correctHealer != null)
{
entries.add(correctHealer);
}
client.setMenuEntries(entries.toArray(new MenuEntry[entries.size()]));
}
if ((event.getTarget().contains("Penance Healer") || event.getTarget().contains("Penance Fighter") || event.getTarget().contains("Penance Ranger")))
{
MenuEntry[] menuEntries = client.getMenuEntries();
MenuEntry lastEntry = menuEntries[menuEntries.length - 1];
String targett = lastEntry.getTarget();
if (foodPressed.containsKey(lastEntry.getIdentifier()))
{
lastEntry.setTarget(lastEntry.getTarget().split("\\(")[0] + "(" + Duration.between(foodPressed.get(lastEntry.getIdentifier()), Instant.now()).getSeconds() + ")");
if (Duration.between(foodPressed.get(lastEntry.getIdentifier()), Instant.now()).getSeconds() > 20)
{
lastEntry.setTarget(lastEntry.getTarget().replace("<col=ffff00>", "<col=2bff63>"));
}
}
else
{
lastEntry.setTarget(targett.replace("<col=ffff00>", "<col=2bff63>"));
}
client.setMenuEntries(menuEntries);
}
if (client.getWidget(BA_COLL_LISTEN_TEXT) != null && inGame && config.eggBoi() && event.getTarget().endsWith("egg") && shiftDown)
{
String[] currentCall = client.getWidget(BA_COLL_LISTEN_TEXT).getText().split(" ");
MenuEntry[] menuEntries = client.getMenuEntries();
MenuEntry correctEgg = null;
entries.clear();
for (MenuEntry entry : menuEntries)
{
if (entry.getTarget().contains(currentCall[0]) && entry.getOption().equals("Take"))
{
correctEgg = entry;
}
else if (!entry.getOption().startsWith("Take"))
{
entries.add(entry);
}
}
if (correctEgg != null)
{
entries.add(correctEgg);
}
client.setMenuEntries(entries.toArray(new MenuEntry[0]));
}
if (client.getWidget(WidgetInfo.BA_ATK_LISTEN_TEXT) != null && inGame && config.attackStyles() && shiftDown)
{
MenuEntry[] menuEntries = client.getMenuEntries();
MenuEntry correctEgg = null;
entries.clear();
for (MenuEntry entry : menuEntries)
{
if (entry.getOption().contains("Walk here"))
{
entries.add(entry);
}
}
client.setMenuEntries(entries.toArray(new MenuEntry[entries.size()]));
}
if (client.getWidget(BA_HEAL_LISTEN_TEXT) != null && inGame && config.osHelp() && event.getTarget().equals("<col=ffff>Healer item machine") && shiftDown)
{
String[] currentCall = client.getWidget(BA_HEAL_LISTEN_TEXT).getText().split(" ");
if (!currentCall[0].contains("Pois."))
{
return;
}
MenuEntry[] menuEntries = client.getMenuEntries();
MenuEntry correctEgg = null;
entries.clear();
for (MenuEntry entry : menuEntries)
{
if (entry.getOption().equals("Take-" + currentCall[1]))
{
correctEgg = entry;
}
}
if (correctEgg != null)
{
entries.add(correctEgg);
client.setMenuEntries(entries.toArray(new MenuEntry[0]));
}
}
}
@Subscribe
public void onMenuOptionClicked(MenuOptionClicked event)
{
String target = event.getTarget();
if (config.tagging() && (event.getTarget().contains("Penance Ranger") || event.getTarget().contains("Penance Fighter")))
{
if (event.getOption().contains("Attack"))
{
foodPressed.put(event.getIdentifier(), Instant.now());
}
log.info(target);
}
if (config.healerMenuOption() && target.contains("Penance Healer") && target.contains("<col=ff9040>Poisoned") && target.contains("->"))
{
foodPressed.put(event.getIdentifier(), Instant.now());
lastHealer = event.getIdentifier();
log.info("Last healer changed: " + lastHealer);
}
}
public void onConfigChanged(ConfigChanged event)
{
if (counter != null && !config.defTimer())
{
removeCounter();
}
}
private void addCounter()
{
if (!config.defTimer() || counter != null)
{
return;
}
int itemSpriteId = ItemID.FIGHTER_TORSO;
BufferedImage taskImg = itemManager.getImage(itemSpriteId);
counter = new CycleCounter(taskImg, this, tickNum);
infoBoxManager.addInfoBox(counter);
}
private void removeCounter()
{
if (counter == null)
{
return;
}
infoBoxManager.removeInfoBox(counter);
counter = null;
}
private void remove(String option, String target)
{
MenuEntry[] entries = client.getMenuEntries();
int idx = searchIndex(entries, option, target);
if (idx >= 0 && entries[idx] != null)
{
entries = ArrayUtils.removeElement(entries, entries[idx]);
client.setMenuEntries(entries);
}
}
private void remove(String[] options, String target)
{
MenuEntry[] entries = client.getMenuEntries();
for (String option : options)
{
int idx = searchIndex(entries, option, target);
if (idx >= 0 && entries[idx] != null)
{
entries = ArrayUtils.removeElement(entries, entries[idx]);
}
}
client.setMenuEntries(entries);
}
private int searchIndex(MenuEntry[] entries, String option, String target)
{
for (int i = entries.length - 1; i >= 0; i--)
{
MenuEntry entry = entries[i];
String entryOption = Text.removeTags(entry.getOption()).toLowerCase();
String entryTarget = Text.removeTags(entry.getTarget()).toLowerCase();
if (entryOption.equals(option) && entryTarget.equals(target))
{
return i;
}
}
return -1;
}
private boolean checkNewSpawn(NPC npc)
{
for (WorldPoint p : WorldPoint.toLocalInstance(client, healerSpawnPoint))
{
if (p.distanceTo(npc.getWorldLocation()) < 5)
{
return true;
}
}
return false;
}
@Override
public void keyTyped(KeyEvent e)
{
}
@Override
public void keyPressed(KeyEvent e)
{
if (e.getKeyCode() == KeyEvent.VK_SHIFT)
{
shiftDown = true;
}
if (e.getKeyCode() == KeyEvent.VK_CONTROL)
{
ctrlDown = true;
}
}
@Override
public void keyReleased(KeyEvent e)
{
if (e.getKeyCode() == KeyEvent.VK_SHIFT)
{
shiftDown = false;
}
if (e.getKeyCode() == KeyEvent.VK_CONTROL)
{
ctrlDown = false;
}
}
private boolean isAnyPrayerActive()
{
for (Prayer pray : Prayer.values())//Check if any prayers are active
{
if (client.isPrayerActive(pray))
{
return true;
}
}
return false;
}
}

View File

@@ -1,76 +0,0 @@
/*
* Copyright (c) 2018, https://runelitepl.us
* 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.batools;
import java.util.HashMap;
import java.util.Map;
import lombok.Getter;
@Getter
public enum Calls
{
//Attacker Calls
RED_EGG("Red egg", "Tell-red"),
GREEN_EGG("Green egg", "Tell-green"),
BLUE_EGG("Blue egg", "Tell-blue"),
//Collector Calls
CONTROLLED("Controlled/Bullet/Wind", "Tell-controlled"),
ACCURATE("Accurate/Field/Water", "Tell-accurate"),
AGGRESSIVE("Aggressive/Blunt/Earth", "Tell-aggressive"),
DEFENSIVE("Defensive/Barbed/Fire", "Tell-defensive"),
//Healer Calls
TOFU("Tofu", "Tell-tofu"),
CRACKERS("Crackers", "Tell-crackers"),
WORMS("Worms", "Tell-worms"),
//Defender Calls
POIS_WORMS("Pois. Worms", "Tell-worms"),
POIS_TOFU("Pois. Tofu", "Tell-tofu"),
POIS_MEAT("Pois. Meat", "Tell-meat");
private final String call;
private final String option;
private static final Map<String, String> CALL_MENU = new HashMap<>();
static
{
for (Calls s : values())
{
CALL_MENU.put(s.getCall(), s.getOption());
}
}
Calls(String call, String option)
{
this.call = call;
this.option = option;
}
public static String getOption(String call)
{
return CALL_MENU.get(call);
}
}

View File

@@ -1,102 +0,0 @@
/*
* Copyright (c) 2018, https://runelitepl.us
* 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.batools;
import lombok.Getter;
import lombok.Setter;
import net.runelite.api.NPC;
class Healer
{
@Getter
private NPC npc;
@Getter
@Setter
private int wave;
@Getter
@Setter
private int spawnNumber;
@Getter
@Setter
private int foodRemaining;
@Getter
@Setter
private int lastFoodTime;
@Getter
@Setter
private int firstCallFood;
@Getter
@Setter
private int secondCallFood;
Healer(NPC npc, int spawnNumber, int wave)
{
this.npc = npc;
this.wave = wave;
this.spawnNumber = spawnNumber;
this.firstCallFood = getCode(wave).getFirstCallFood()[spawnNumber];
this.secondCallFood = getCode(wave).getSecondCallFood()[spawnNumber];
this.foodRemaining = firstCallFood + secondCallFood;
this.lastFoodTime = getCode(wave).getSpacing()[spawnNumber];
}
private HealerCode getCode(int wave)
{
switch (wave)
{
case 1:
return HealerCode.WAVEONE;
case 2:
return HealerCode.WAVETWO;
case 3:
return HealerCode.WAVETHREE;
case 4:
return HealerCode.WAVEFOUR;
case 5:
return HealerCode.WAVEFIVE;
case 6:
return HealerCode.WAVESIX;
case 7:
return HealerCode.WAVESEVEN;
case 8:
return HealerCode.WAVEEIGHT;
case 9:
return HealerCode.WAVENINE;
case 10:
return HealerCode.WAVETEN;
default:
return null;
}
}
}

View File

@@ -1,58 +0,0 @@
/*
* Copyright (c) 2018, https://runelitepl.us
* 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.batools;
import lombok.Getter;
enum HealerCode
{
WAVEONE(new int[]{1, 1}, new int[]{0, 0}, new int[]{0, 0}),
WAVETWO(new int[]{1, 1, 2}, new int[]{0, 0, 0}, new int[]{0, 0, 21}),
WAVETHREE(new int[]{1, 6, 2}, new int[]{0, 0, 0}, new int[]{0, 0, 0}),
WAVEFOUR(new int[]{2, 5, 2, 0}, new int[]{0, 0, 7, 10}, new int[]{0, 0, 0, 0}),
WAVEFIVE(new int[]{2, 5, 2, 3, 0}, new int[]{0, 0, 0, 0, 7}, new int[]{0, 0, 21, 30, 0}),
WAVESIX(new int[]{3, 5, 2, 2, 0, 0}, new int[]{0, 0, 0, 2, 9, 10}, new int[]{12, 18, 21, 0, 0, 0}),
WAVESEVEN(new int[]{3, 7, 1, 1, 0, 0, 0}, new int[]{2, 0, 1, 1, 2, 4, 10}, new int[]{0, 21, 0, 0, 30, 45, 0}),
WAVEEIGHT(new int[]{1, 9, 1, 1, 0, 0, 0}, new int[]{1, 0, 1, 1, 2, 2, 10}, new int[]{0, 0, 0, 0, 33, 42, 0}),
WAVENINE(new int[]{2, 8, 1, 1, 0, 0, 0, 0}, new int[]{1, 0, 1, 1, 2, 1, 1, 10}, new int[]{0, 21, 0, 0, 0, 0, 0, 0, 0}),
WAVETEN(new int[]{2, 5, 1, 1, 0, 0, 0}, new int[]{1, 0, 1, 1, 4, 4, 8}, new int[]{21, 33, 0, 33, 30, 45, 0});
@Getter
private final int[] firstCallFood;
@Getter
private final int[] secondCallFood;
@Getter
private final int[] spacing;
HealerCode(int[] firstCallFood, int[] secondCallFood, int[] spacing)
{
this.firstCallFood = firstCallFood;
this.secondCallFood = secondCallFood;
this.spacing = spacing;
}
}

View File

@@ -396,7 +396,7 @@ public class PestControlPlugin extends Plugin
}
// Get points from dialog after purchase
Widget pestControlDialog = client.getWidget(WidgetInfo.PEST_CONTROL_DIALOG_TEXT);
Widget pestControlDialog = client.getWidget(WidgetInfo.MINIGAME_DIALOG_TEXT);
if (pestControlDialog != null)
{
String pestControlDialogText = Text.sanitizeMultilineText(pestControlDialog.getText());

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -27,6 +27,7 @@ package net.runelite.mixins;
import net.runelite.api.Actor;
import net.runelite.api.coords.LocalPoint;
import net.runelite.api.events.ProjectileMoved;
import net.runelite.api.events.ProjectileSpawned;
import net.runelite.api.mixins.Inject;
import net.runelite.api.mixins.MethodHook;
import net.runelite.api.mixins.Mixin;
@@ -42,6 +43,14 @@ public abstract class RSProjectileMixin implements RSProjectile
@Shadow("client")
private static RSClient client;
@Inject
RSProjectileMixin()
{
final ProjectileSpawned projectileSpawned = new ProjectileSpawned();
projectileSpawned.setProjectile(this);
client.getCallbacks().post(projectileSpawned);
}
@Inject
@Override
public int getRemainingCycles()