Merge branch 'master' into loot-tracker-reset

This commit is contained in:
PKLite
2019-06-26 03:10:27 -04:00
301 changed files with 7881 additions and 5168 deletions

View File

@@ -46,11 +46,13 @@ import javax.inject.Singleton;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.ChatMessageType;
import net.runelite.api.Client;
import net.runelite.api.Constants;
import net.runelite.api.GameState;
import net.runelite.client.chat.ChatColorType;
import net.runelite.client.chat.ChatMessageBuilder;
import net.runelite.client.chat.ChatMessageManager;
import net.runelite.client.chat.QueuedMessage;
import net.runelite.client.config.FlashNotification;
import net.runelite.client.config.RuneLiteConfig;
import net.runelite.client.ui.ClientUI;
import net.runelite.client.util.OSType;
@@ -68,7 +70,8 @@ public class Notifier
// Notifier properties
private static final Color FLASH_COLOR = new Color(255, 0, 0, 70);
private static final int FLASH_DURATION = 2000;
private static final int MINIMUM_FLASH_DURATION_MILLIS = 2000;
private static final int MINIMUM_FLASH_DURATION_TICKS = MINIMUM_FLASH_DURATION_MILLIS / Constants.CLIENT_TICK_LENGTH;
private final Client client;
private final String appName;
@@ -79,6 +82,7 @@ public class Notifier
private final Path notifyIconPath;
private final boolean terminalNotifierAvailable;
private Instant flashStart;
private long mouseLastPressedMillis;
@Inject
private Notifier(
@@ -146,9 +150,10 @@ public class Notifier
.build());
}
if (runeLiteConfig.enableFlashNotification())
if (runeLiteConfig.flashNotification() != FlashNotification.DISABLED)
{
flashStart = Instant.now();
mouseLastPressedMillis = client.getMouseLastPressedMillis();
}
log.debug(message);
@@ -156,24 +161,48 @@ public class Notifier
public void processFlash(final Graphics2D graphics)
{
if (flashStart == null || client.getGameCycle() % 40 >= 20)
{
return;
}
else if (client.getGameState() != GameState.LOGGED_IN)
if (flashStart == null || client.getGameState() != GameState.LOGGED_IN)
{
flashStart = null;
return;
}
FlashNotification flashNotification = runeLiteConfig.flashNotification();
if (client.getGameCycle() % 40 >= 20
// For solid colour, fall through every time.
&& (flashNotification == FlashNotification.FLASH_TWO_SECONDS
|| flashNotification == FlashNotification.FLASH_UNTIL_CANCELLED))
{
return;
}
final Color color = graphics.getColor();
graphics.setColor(FLASH_COLOR);
graphics.fill(new Rectangle(client.getCanvas().getSize()));
graphics.setColor(color);
if (Instant.now().minusMillis(FLASH_DURATION).isAfter(flashStart))
if (!Instant.now().minusMillis(MINIMUM_FLASH_DURATION_MILLIS).isAfter(flashStart))
{
flashStart = null;
return;
}
switch (flashNotification)
{
case FLASH_TWO_SECONDS:
case SOLID_TWO_SECONDS:
flashStart = null;
break;
case SOLID_UNTIL_CANCELLED:
case FLASH_UNTIL_CANCELLED:
// Any interaction with the client since the notification started will cancel it after the minimum duration
if (client.getMouseIdleTicks() < MINIMUM_FLASH_DURATION_TICKS
|| client.getKeyboardIdleTicks() < MINIMUM_FLASH_DURATION_TICKS
|| client.getMouseLastPressedMillis() > mouseLastPressedMillis)
{
flashStart = null;
}
break;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, Jordan Atwood <jordan.atwood423@gmail.com>
* Copyright (c) 2019, Twiglet1022 <https://github.com/Twiglet1022>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -22,29 +22,26 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.client.plugins.inferno;
package net.runelite.client.config;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@AllArgsConstructor
enum InfernoWaveMonster
@Getter
@RequiredArgsConstructor
public enum FlashNotification
{
JAL_NIB("Jal-Nib", 32),
JAL_MEJRAH("Jal-MejRah", 85),
JAL_AK("Jal-Ak", 165),
JAL_IMKOT("Jal-ImKot", 240),
JAL_XIL("Jal-XIL", 370),
JAL_ZEK("Jal-Zek", 490),
JALTOK_JAD("JalTok-Jad", 900),
TZKAL_ZUK("TzKal-Zuk", 1400);
DISABLED("Off"),
FLASH_TWO_SECONDS("Flash for 2 seconds"),
SOLID_TWO_SECONDS("Solid for 2 seconds"),
FLASH_UNTIL_CANCELLED("Flash until cancelled"),
SOLID_UNTIL_CANCELLED("Solid until cancelled");
private final String name;
private final int level;
private final String type;
@Override
public String toString()
{
return String.format("%s - Level %s", name, level);
return type;
}
}

View File

@@ -191,9 +191,9 @@ public interface RuneLiteConfig extends Config
description = "Flashes the game frame as a notification",
position = 24
)
default boolean enableFlashNotification()
default FlashNotification flashNotification()
{
return false;
return FlashNotification.DISABLED;
}
@ConfigItem(

View File

@@ -44,8 +44,9 @@ import javax.inject.Singleton;
import lombok.Value;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Client;
import net.runelite.api.Constants;
import static net.runelite.api.Constants.CLIENT_DEFAULT_ZOOM;
import static net.runelite.api.Constants.HIGH_ALCHEMY_CONSTANT;
import static net.runelite.api.Constants.HIGH_ALCHEMY_MULTIPLIER;
import net.runelite.api.GameState;
import net.runelite.api.ItemDefinition;
import net.runelite.api.ItemID;
@@ -423,7 +424,7 @@ public class ItemManager
return 1000;
}
return (int) Math.max(1, composition.getPrice() * HIGH_ALCHEMY_CONSTANT);
return (int) Math.max(1, composition.getPrice() * HIGH_ALCHEMY_MULTIPLIER);
}
public int getAlchValue(int itemID)
@@ -437,7 +438,7 @@ public class ItemManager
return 1000;
}
return (int) Math.max(1, getItemDefinition(itemID).getPrice() * HIGH_ALCHEMY_CONSTANT);
return (int) Math.max(1, getItemDefinition(itemID).getPrice() * HIGH_ALCHEMY_MULTIPLIER);
}
/**
@@ -521,7 +522,7 @@ public class ItemManager
*/
private AsyncBufferedImage loadImage(int itemId, int quantity, boolean stackable)
{
AsyncBufferedImage img = new AsyncBufferedImage(36, 32, BufferedImage.TYPE_INT_ARGB);
AsyncBufferedImage img = new AsyncBufferedImage(Constants.ITEM_SPRITE_WIDTH, Constants.ITEM_SPRITE_HEIGHT, BufferedImage.TYPE_INT_ARGB);
clientThread.invoke(() ->
{
if (client.getGameState().ordinal() < GameState.LOGIN_SCREEN.ordinal())

View File

@@ -144,10 +144,12 @@ public enum ItemMapping
// Bounty hunter
ITEM_GRANITE_MAUL(GRANITE_MAUL, GRANITE_MAUL_12848),
ITEM_MAGIC_SHORTBOW(MAGIC_SHORTBOW, MAGIC_SHORTBOW_I),
ITEM_MAGIC_SHORTBOW_SCROLL(MAGIC_SHORTBOW_SCROLL, MAGIC_SHORTBOW_I),
ITEM_SARADOMINS_BLESSED_SWORD(SARADOMINS_TEAR, SARADOMINS_BLESSED_SWORD),
// Jewellery with charges
ITEM_RING_OF_WEALTH(RING_OF_WEALTH, RING_OF_WEALTH_I, RING_OF_WEALTH_1, RING_OF_WEALTH_I1, RING_OF_WEALTH_2, RING_OF_WEALTH_I2, RING_OF_WEALTH_3, RING_OF_WEALTH_I3, RING_OF_WEALTH_4, RING_OF_WEALTH_I4, RING_OF_WEALTH_I5),
ITEM_RING_OF_WEALTH_SCROLL(RING_OF_WEALTH_SCROLL, RING_OF_WEALTH_I, RING_OF_WEALTH_I1, RING_OF_WEALTH_I2, RING_OF_WEALTH_I3, RING_OF_WEALTH_I4, RING_OF_WEALTH_I5),
ITEM_AMULET_OF_GLORY(AMULET_OF_GLORY, AMULET_OF_GLORY1, AMULET_OF_GLORY2, AMULET_OF_GLORY3, AMULET_OF_GLORY5),
ITEM_AMULET_OF_GLORY_T(AMULET_OF_GLORY_T, AMULET_OF_GLORY_T1, AMULET_OF_GLORY_T2, AMULET_OF_GLORY_T3, AMULET_OF_GLORY_T5),
ITEM_SKILLS_NECKLACE(SKILLS_NECKLACE, SKILLS_NECKLACE1, SKILLS_NECKLACE2, SKILLS_NECKLACE3, SKILLS_NECKLACE5),

View File

@@ -109,7 +109,7 @@ public class LootManager
case NpcID.LIZARD:
case NpcID.ZYGOMITE:
case NpcID.ZYGOMITE_474:
case NpcID.ZYGOMITE_1024:
case NpcID.ANCIENT_ZYGOMITE:
// these monsters die with >0 hp, so we just look for coincident

View File

@@ -42,9 +42,11 @@ import javax.inject.Singleton;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Client;
import net.runelite.api.MenuAction;
import static net.runelite.api.MenuAction.MENU_ACTION_DEPRIORITIZE_OFFSET;
import static net.runelite.api.MenuAction.GAME_OBJECT_FIRST_OPTION;
import static net.runelite.api.MenuAction.WIDGET_DEFAULT;
import net.runelite.api.MenuEntry;
import net.runelite.api.NPCDefinition;
import net.runelite.api.events.ClientTick;
import net.runelite.api.events.MenuEntryAdded;
import net.runelite.api.events.MenuOptionClicked;
import net.runelite.api.events.NpcActionChanged;
@@ -147,14 +149,6 @@ public class MenuManager
Collection<WidgetMenuOption> options = managedMenuOptions.get(widgetId);
MenuEntry[] menuEntries = client.getMenuEntries();
if (menuEntries.length == 1)
{
// Menu entries reset, so priority entries should reset as well
currentPriorityEntries.clear();
originalTypes.clear();
}
for (WidgetMenuOption currentMenu : options)
{
if (!menuContainsCustomMenu(currentMenu))//Don't add if we have already added it to this widget
@@ -173,22 +167,14 @@ public class MenuManager
final MenuEntry newestEntry = menuEntries[menuEntries.length - 1];
boolean isPrio = false;
for (ComparableEntry p : priorityEntries)
{
if (p.matches(newestEntry))
{
isPrio = true;
break;
currentPriorityEntries.add(newestEntry);
}
}
// If the last entry was a priority entry, keep track of it
if (isPrio)
{
currentPriorityEntries.add(newestEntry);
}
// Make a copy of the menu entries, cause you can't remove from Arrays.asList()
List<MenuEntry> copy = Lists.newArrayList(menuEntries);
@@ -197,88 +183,26 @@ public class MenuManager
{
copy.retainAll(currentPriorityEntries);
copy.add(0, CANCEL());
}
// Find the current entry in the swaps map
ComparableEntry swapEntry = null;
for (ComparableEntry e : swaps.keySet())
{
if (e.matches(newestEntry))
// This is because players existing changes walk-here target
// so without this we lose track of em
if (copy.size() != currentPriorityEntries.size())
{
swapEntry = e;
break;
}
}
if (swapEntry != null)
{
ComparableEntry swapTarget = swaps.get(swapEntry);
// Find the target for the swap in current menu entries
MenuEntry foundSwap = null;
for (MenuEntry entry : Lists.reverse(copy))
{
if (swapTarget.matches(entry))
for (MenuEntry e : currentPriorityEntries)
{
foundSwap = entry;
break;
}
}
if (foundSwap != null)
{
// This is the type for the entry we're swapping the newest with
final int foundType = foundSwap.getType();
// This is the type for the newest entry
final int lastType = newestEntry.getType();
// MenuActions with an id of over 1000 get shifted to the back of the menu entry array
// They have different id's in the packet buffer though, so we got to modify them back on click
// I couldn't get this to work with objects, so we're using modified objectcomposition for that
final boolean shouldModifyFoundType = foundType >= 1000;
final boolean shouldModifyLastType = lastType >= 1000;
// Bitwise or so we don't end up making things left click when they shouldn't
if (shouldModifyFoundType ^ shouldModifyLastType)
{
int typeToSet;
switch (MenuAction.of(shouldModifyFoundType ? foundType : lastType))
if (copy.contains(e))
{
case EXAMINE_ITEM_BANK_EQ:
typeToSet = MenuAction.WIDGET_DEFAULT.getId();
break;
case GAME_OBJECT_FIFTH_OPTION:
typeToSet = MenuAction.GAME_OBJECT_FIRST_OPTION.getId();
break;
default:
typeToSet = shouldModifyFoundType ? foundType : lastType;
break;
continue;
}
if (shouldModifyFoundType)
for (MenuEntry e2 : client.getMenuEntries())
{
foundSwap.setType(typeToSet);
originalTypes.put(foundSwap, foundType);
}
else
{
newestEntry.setType(typeToSet);
originalTypes.put(newestEntry, lastType);
// We're probably trying to make something left click, so just slap on
// the menu action deprioritize 2000-inator++
foundSwap.setType(foundType + MENU_ACTION_DEPRIORITIZE_OFFSET);
if (e.getType() == e2.getType())
{
e.setTarget(e2.getTarget());
copy.add(e);
}
}
}
// Swap
int index = copy.indexOf(foundSwap);
int newIndex = copy.indexOf(newestEntry);
copy.set(index, newestEntry);
copy.set(newIndex, foundSwap);
}
}
@@ -300,6 +224,69 @@ public class MenuManager
client.setMenuEntries(copy.toArray(new MenuEntry[0]));
}
@Subscribe
private void onClientTick(ClientTick event)
{
originalTypes.clear();
client.sortMenuEntries();
final MenuEntry[] oldentries = client.getMenuEntries();
MenuEntry[] newEntries;
if (!currentPriorityEntries.isEmpty())
{
newEntries = new MenuEntry[client.getMenuOptionCount() + 1];
newEntries[0] = CANCEL();
System.arraycopy(oldentries, 0, newEntries, 1, oldentries.length);
}
else
{
newEntries = Arrays.copyOf(oldentries, client.getMenuOptionCount());
}
MenuEntry leftClickEntry = newEntries[newEntries.length - 1];
for (ComparableEntry src : swaps.keySet())
{
if (!src.matches(leftClickEntry))
{
continue;
}
ComparableEntry tgt = swaps.get(src);
for (int i = newEntries.length - 2; i > 0; i--)
{
MenuEntry e = newEntries[i];
if (tgt.matches(e))
{
newEntries[newEntries.length - 1] = e;
newEntries[i] = leftClickEntry;
int type = e.getType();
if (type >= 1000)
{
int newType = getLeftClickType(type);
if (newType != -1 && newType != type)
{
e.setType(newType);
originalTypes.put(e, type);
}
}
break;
}
}
}
client.setMenuEntries(newEntries);
currentPriorityEntries.clear();
}
public void addPlayerMenuItem(String menuText)
{
Preconditions.checkNotNull(menuText);
@@ -361,6 +348,24 @@ public class MenuManager
}
}
private int getLeftClickType(int oldType)
{
if (oldType > 2000)
{
oldType -= 2000;
}
switch (MenuAction.of(oldType))
{
case GAME_OBJECT_FIFTH_OPTION:
return GAME_OBJECT_FIRST_OPTION.getId();
case EXAMINE_ITEM_BANK_EQ:
return WIDGET_DEFAULT.getId();
default:
return oldType;
}
}
private void addNpcOption(NPCDefinition composition, String npcOption)
{
String[] actions = composition.getActions();
@@ -404,69 +409,21 @@ public class MenuManager
@Subscribe
public void onMenuOptionClicked(MenuOptionClicked event)
{
// if (originalTypes.get(event.ge
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// This right here. That's the moment I realized once again that
// this event still is one of the worst fucking things that has
// ever happened to this project. MenuOptionClicked right? What
// do you expect the data in the event object to be?
// A FUCKING MENU ENTRY. Honestly I originally forgot why I wrote
// the rant below this, but the hate is coming back to me once again.
// What the fuck do you expect me to do? Make another MenuEntry from
// all the info WHICH WOULD HAVE BEEN INSIDE THE FUCKING MENUENTRY TO
// BEGIN WITH??? I am legit still perplexed over why someone would do
// it like this, and I don't want them to take this lightly cause they
// should really really really feel terrible about this.
if (!event.getMenuTarget().equals("do not edit") &&
!originalTypes.isEmpty() &&
event.getMenuAction() == MenuAction.WIDGET_DEFAULT ||
event.getMenuAction() == MenuAction.GAME_OBJECT_FIRST_OPTION)
if (originalTypes.containsKey(event.getMenuEntry()) &&
!event.getTarget().equals("do not edit"))
{
for (Map.Entry<MenuEntry, Integer> ent : originalTypes.entrySet())
{
// Honestly, I was about to write a huge ass rant about
// how I hate whoever wrote the menuoptionclicked class
// but I decided that that'd be un-nice to them, and they
// probably spent over 24 hours writing it. Not because
// it was that difficult to write, of course, but because
// they must have the fucking iq of a retarded, under developed,
// braindead, basically good-for-nothing, idiotic chimp.
//
// Just kidding, of course, that would be too big of an
// insult towards those poor chimps. It's not their fault
// some dumbass is the way they are, right? Why should they
// feel bad for something they can't do anything about?
//
// Whoever wrote that class though, should actually feel
// 100% terrible. If they aren't depressed, I really wish
// they become depressed very, very soon. What the fuck
// were they even thinking.
event.consume();
MenuEntry e = ent.getKey();
if (event.getMenuAction().getId() != e.getType()
|| event.getId() != e.getIdentifier()
|| !event.getMenuOption().equals(e.getOption()))
{
continue;
}
event.consume();
client.invokeMenuAction(
event.getActionParam(),
event.getWidgetId(),
ent.getValue(),
event.getId(),
event.getMenuOption(),
"do not edit",
client.getMouseCanvasPosition().getX(),
client.getMouseCanvasPosition().getY()
);
break;
}
client.invokeMenuAction(
event.getActionParam0(),
event.getActionParam1(),
originalTypes.get(event.getMenuEntry()),
event.getIdentifier(),
event.getOption(),
"do not edit",
client.getMouseCanvasPosition().getX(),
client.getMouseCanvasPosition().getY()
);
}
if (event.getMenuAction() != MenuAction.RUNELITE)
@@ -474,31 +431,31 @@ public class MenuManager
return; // not a player menu
}
int widgetId = event.getWidgetId();
int widgetId = event.getActionParam1();
Collection<WidgetMenuOption> options = managedMenuOptions.get(widgetId);
for (WidgetMenuOption curMenuOption : options)
{
if (curMenuOption.getMenuTarget().equals(event.getMenuTarget())
&& curMenuOption.getMenuOption().equals(event.getMenuOption()))
if (curMenuOption.getMenuTarget().equals(event.getTarget())
&& curMenuOption.getMenuOption().equals(event.getOption()))
{
WidgetMenuOptionClicked customMenu = new WidgetMenuOptionClicked();
customMenu.setMenuOption(event.getMenuOption());
customMenu.setMenuTarget(event.getMenuTarget());
customMenu.setMenuOption(event.getOption());
customMenu.setMenuTarget(event.getTarget());
customMenu.setWidget(curMenuOption.getWidget());
eventBus.post(customMenu);
return; // don't continue because it's not a player option
}
}
String target = event.getMenuTarget();
String target = event.getTarget();
// removes tags and level from player names for example:
// <col=ffffff>username<col=40ff00> (level-42) or <col=ffffff><img=2>username</col>
String username = Text.removeTags(target).split("[(]")[0].trim();
PlayerMenuOptionClicked playerMenuOptionClicked = new PlayerMenuOptionClicked();
playerMenuOptionClicked.setMenuOption(event.getMenuOption());
playerMenuOptionClicked.setMenuOption(event.getOption());
playerMenuOptionClicked.setMenuTarget(username);
eventBus.post(playerMenuOptionClicked);

View File

@@ -32,15 +32,15 @@ import net.runelite.client.util.ColorUtil;
public final class WidgetMenuOption
{
/**
* The left hand text to be displayed on the menu option. Ex. the menuOption of "Drop Bones" is "Drop"
* The left hand text to be displayed on the menu option. Ex. the option of "Drop Bones" is "Drop"
*/
private String menuOption;
/**
* The right hand text to be displayed on the menu option Ex. the menuTarget of "Drop Bones" is "Bones"
* The right hand text to be displayed on the menu option Ex. the target of "Drop Bones" is "Bones"
*/
private String menuTarget;
/**
* The color that the menuTarget should be. Defaults to the brownish color that most menu options have.
* The color that the target should be. Defaults to the brownish color that most menu options have.
*/
private Color color = JagexColors.MENU_TARGET;

View File

@@ -24,74 +24,119 @@
*/
package net.runelite.client.plugins.alchemicalhydra;
import java.awt.image.BufferedImage;
import javax.inject.Singleton;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import net.runelite.api.NPC;
import net.runelite.api.Prayer;
import net.runelite.api.ProjectileID;
import net.runelite.api.SpriteID;
import net.runelite.client.game.SpriteManager;
import net.runelite.client.util.ImageUtil;
@Getter(AccessLevel.PACKAGE)
@RequiredArgsConstructor
@Singleton
class Hydra
{
@Getter(AccessLevel.PACKAGE)
@RequiredArgsConstructor
enum AttackStyle
{
MAGIC(ProjectileID.HYDRA_MAGIC, Prayer.PROTECT_FROM_MAGIC),
RANGED(ProjectileID.HYDRA_RANGED, Prayer.PROTECT_FROM_MISSILES);
MAGIC(ProjectileID.HYDRA_MAGIC, Prayer.PROTECT_FROM_MAGIC, SpriteID.PRAYER_PROTECT_FROM_MAGIC),
RANGED(ProjectileID.HYDRA_RANGED, Prayer.PROTECT_FROM_MISSILES, SpriteID.PRAYER_PROTECT_FROM_MISSILES);
@Getter
private int projId;
private final int projectileID;
private final Prayer prayer;
private final int spriteID;
@Getter
private Prayer prayer;
@Getter(AccessLevel.NONE)
private BufferedImage image;
AttackStyle(int projId, Prayer prayer)
BufferedImage getImage(SpriteManager spriteManager)
{
this.projId = projId;
this.prayer = prayer;
if (image == null)
{
BufferedImage tmp = spriteManager.getSprite(spriteID, 0);
image = tmp == null ? null : ImageUtil.resizeImage(tmp, HydraOverlay.IMGSIZE, HydraOverlay.IMGSIZE);
}
return image;
}
}
@Getter
private NPC npc;
private final NPC npc;
@Getter
@Setter
private HydraPhase phase;
private HydraPhase phase = HydraPhase.ONE;
@Getter
@Setter
private int attackCount;
private int attackCount = 0;
private int nextSwitch = phase.getAttacksPerSwitch();
@Getter
@Setter
private int nextSwitch;
@Setter(AccessLevel.PACKAGE)
private int nextSpecial = 3;
@Getter
@Setter
private int nextSpecial;
private AttackStyle nextAttack = AttackStyle.MAGIC;
private AttackStyle lastAttack = AttackStyle.MAGIC;
@Getter
@Setter
private AttackStyle nextAttack;
@Setter(AccessLevel.PACKAGE)
private boolean weakened = false;
@Getter
@Setter
private AttackStyle lastAttack;
@Getter
@Setter
private boolean weakened;
Hydra(NPC npc)
void changePhase(HydraPhase newPhase)
{
this.npc = npc;
this.phase = HydraPhase.ONE;
this.nextAttack = AttackStyle.MAGIC;
this.lastAttack = AttackStyle.MAGIC; // important, else we wouldn't switch if the first attack is ranged
this.nextSpecial = 3;
this.nextSwitch = phase.getAttacksPerSwitch();
this.attackCount = 0;
this.weakened = false;
phase = newPhase;
nextSpecial = 3;
attackCount = 0;
weakened = false;
if (newPhase == HydraPhase.FOUR)
{
weakened = true;
switchStyles();
nextSwitch = phase.getAttacksPerSwitch();
}
}
private void switchStyles()
{
nextAttack = lastAttack == Hydra.AttackStyle.MAGIC
? Hydra.AttackStyle.RANGED
: Hydra.AttackStyle.MAGIC;
}
void handleAttack(int id)
{
if (id != nextAttack.getProjectileID())
{
if (id == lastAttack.getProjectileID())
{
// If the current attack isn't what was expected and we accidentally counted 1 too much
return;
}
// If the current attack isn't what was expected and we should have switched prayers
switchStyles();
nextSwitch = phase.getAttacksPerSwitch() - 1;
}
else
{
nextSwitch--;
}
lastAttack = nextAttack;
attackCount++;
if (nextSwitch <= 0)
{
switchStyles();
nextSwitch = phase.getAttacksPerSwitch();
}
}
int getNextSpecialRelative()
{
return nextSpecial - attackCount;
}
}

View File

@@ -26,16 +26,12 @@ package net.runelite.client.plugins.alchemicalhydra;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import javax.inject.Inject;
import javax.inject.Singleton;
import net.runelite.api.Client;
import net.runelite.api.Prayer;
import net.runelite.api.SpriteID;
import net.runelite.client.game.SpriteManager;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayPosition;
@@ -46,13 +42,16 @@ import net.runelite.client.ui.overlay.components.PanelComponent;
@Singleton
class HydraOverlay extends Overlay
{
private static final Color RED_BG_COL = new Color(156, 0, 0, 156);
private static final Color YEL_BG_COL = new Color(200, 156, 0, 156);
private static final Color GRN_BG_COL = new Color(0, 156, 0, 156);
static final int IMGSIZE = 36;
private final HydraPlugin plugin;
private final Client client;
private final SpriteManager spriteManager;
private final PanelComponent panelComponent = new PanelComponent();
private static final Color redBgCol = new Color(156, 0, 0, 156);
private static final Color yelBgCol = new Color(200, 156, 0, 156);
private static final Color grnBgCol = new Color(0, 156, 0, 156);
@Inject
HydraOverlay(HydraPlugin plugin, Client client, SpriteManager spriteManager)
@@ -76,9 +75,8 @@ class HydraOverlay extends Overlay
}
//Add spec overlay first, to keep it above pray
HydraPhase phase = hydra.getPhase();
int attackCount = hydra.getAttackCount();
int nextSpec = hydra.getNextSpecial() - attackCount;
final HydraPhase phase = hydra.getPhase();
final int nextSpec = hydra.getNextSpecialRelative();
if (nextSpec <= 3)
{
@@ -86,37 +84,34 @@ class HydraOverlay extends Overlay
if (nextSpec == 0)
{
specComponent.setBackgroundColor(redBgCol);
specComponent.setBackgroundColor(RED_BG_COL);
}
else if (nextSpec == 1)
{
specComponent.setBackgroundColor(yelBgCol);
specComponent.setBackgroundColor(YEL_BG_COL);
}
Image specImg = scaleImg(spriteManager.getSprite(phase.getSpecImage(), 0));
specComponent.setImage(specImg);
specComponent.setImage(phase.getSpecImage(spriteManager));
specComponent.setText(" " + (nextSpec)); //hacky way to not have to figure out how to move text
specComponent.setPreferredSize(new Dimension(40, 40));
panelComponent.getChildren().add(specComponent);
}
Prayer nextPrayer = hydra.getNextAttack().getPrayer();
Image prayImg = scaleImg(getPrayerImage(hydra.getNextAttack().getPrayer()));
int nextSwitch = hydra.getNextSwitch();
final Prayer nextPrayer = hydra.getNextAttack().getPrayer();
final int nextSwitch = hydra.getNextSwitch();
InfoBoxComponent prayComponent = new InfoBoxComponent();
if (nextSwitch == 1)
{
prayComponent.setBackgroundColor(client.isPrayerActive(nextPrayer) ? yelBgCol : redBgCol);
prayComponent.setBackgroundColor(client.isPrayerActive(nextPrayer) ? YEL_BG_COL : RED_BG_COL);
}
else
{
prayComponent.setBackgroundColor(client.isPrayerActive(nextPrayer) ? grnBgCol : redBgCol);
prayComponent.setBackgroundColor(client.isPrayerActive(nextPrayer) ? GRN_BG_COL : RED_BG_COL);
}
prayComponent.setImage(prayImg);
prayComponent.setImage(hydra.getNextAttack().getImage(spriteManager));
prayComponent.setText(" " + nextSwitch);
prayComponent.setColor(Color.white);
prayComponent.setPreferredSize(new Dimension(40, 40));
@@ -126,32 +121,4 @@ class HydraOverlay extends Overlay
panelComponent.setBorder(new Rectangle(0, 0, 0, 0));
return panelComponent.render(graphics2D);
}
private BufferedImage getPrayerImage(Prayer pray)
{
return pray == Prayer.PROTECT_FROM_MAGIC
? spriteManager.getSprite(SpriteID.PRAYER_PROTECT_FROM_MAGIC, 0)
: spriteManager.getSprite(SpriteID.PRAYER_PROTECT_FROM_MISSILES, 0);
}
private Image scaleImg(final Image img)
{
if (img == null)
{
return null;
}
final double width = img.getWidth(null);
final double height = img.getHeight(null);
final double size = 36; // Limit size to 2 as that is minimum size not causing breakage
final double scalex = size / width;
final double scaley = size / height;
final double scale = Math.min(scalex, scaley);
final int newWidth = (int) (width * scale);
final int newHeight = (int) (height * scale);
final BufferedImage scaledImage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_ARGB);
final Graphics g = scaledImage.createGraphics();
g.drawImage(img, 0, 0, newWidth, newHeight, null);
g.dispose();
return scaledImage;
}
}

View File

@@ -24,48 +24,46 @@
*/
package net.runelite.client.plugins.alchemicalhydra;
import java.awt.image.BufferedImage;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import net.runelite.api.AnimationID;
import net.runelite.api.ProjectileID;
import net.runelite.api.SpriteID;
import net.runelite.api.coords.WorldPoint;
import net.runelite.client.game.SpriteManager;
import net.runelite.client.util.ImageUtil;
@Getter(AccessLevel.PACKAGE)
@RequiredArgsConstructor
enum HydraPhase
{ // Sorry for the autism
{
ONE(3, AnimationID.HYDRA_1_1, AnimationID.HYDRA_1_2, ProjectileID.HYDRA_POISON, 0, SpriteID.BIG_ASS_GUTHIX_SPELL, new WorldPoint(1371, 10263, 0)),
TWO(3, AnimationID.HYDRA_2_1, AnimationID.HYDRA_2_2, 0, AnimationID.HYDRA_LIGHTNING, SpriteID.BIG_SPEC_TRANSFER, new WorldPoint(1371, 10272, 0)),
THREE(3, AnimationID.HYDRA_3_1, AnimationID.HYDRA_3_2, 0, AnimationID.HYDRA_FIRE, SpriteID.BIG_SUPERHEAT, new WorldPoint(1362, 10272, 0)),
FOUR(1, AnimationID.HYDRA_4_1, AnimationID.HYDRA_4_2, ProjectileID.HYDRA_POISON, 0, SpriteID.BIG_ASS_GUTHIX_SPELL, null);
@Getter
private final int attacksPerSwitch;
@Getter
private final int deathAnim1;
@Getter
private final int deathAnim2;
@Getter
private final int specProjectileId;
@Getter
private final int specAnimationId;
@Getter
private final int specImage;
@Getter(AccessLevel.NONE)
private final int specImageID;
private final WorldPoint fountain;
@Getter
private WorldPoint fountain;
private BufferedImage specImage;
HydraPhase(int attacksPerSwitch, int deathAnim1, int deathAnim2, int specProjectileId, int specAnimationId, int specImage, WorldPoint fountain)
BufferedImage getSpecImage(SpriteManager spriteManager)
{
this.attacksPerSwitch = attacksPerSwitch;
this.deathAnim1 = deathAnim1;
this.deathAnim2 = deathAnim2;
this.specProjectileId = specProjectileId;
this.specAnimationId = specAnimationId;
this.specImage = specImage;
this.fountain = fountain;
if (specImage == null)
{
BufferedImage tmp = spriteManager.getSprite(specImageID, 0);
specImage = tmp == null ? null : ImageUtil.resizeImage(tmp, HydraOverlay.IMGSIZE, HydraOverlay.IMGSIZE);
}
return specImage;
}
}

View File

@@ -30,6 +30,7 @@ import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.inject.Inject;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Actor;
@@ -60,10 +61,10 @@ import net.runelite.client.ui.overlay.OverlayManager;
@Slf4j
public class HydraPlugin extends Plugin
{
@Getter
@Getter(AccessLevel.PACKAGE)
private Map<LocalPoint, Projectile> poisonProjectiles = new HashMap<>();
@Getter
@Getter(AccessLevel.PACKAGE)
private Hydra hydra;
private boolean inHydraInstance;
@@ -84,7 +85,7 @@ public class HydraPlugin extends Plugin
private HydraOverlay overlay;
@Inject
private HydraPoisonOverlay poisonOverlay;
private HydraSceneOverlay poisonOverlay;
@Override
protected void startUp()
@@ -124,18 +125,16 @@ public class HydraPlugin extends Plugin
}
return;
}
NPC hydraNpc = null;
for (NPC npc : client.getNpcs())
{
if (npc.getId() == NpcID.ALCHEMICAL_HYDRA)
{
hydraNpc = npc;
hydra = new Hydra(npc);
break;
}
}
hydra = new Hydra(hydraNpc);
addOverlays();
}
@@ -171,13 +170,13 @@ public class HydraPlugin extends Plugin
switch (phase)
{
case ONE:
changePhase(HydraPhase.TWO);
hydra.changePhase(HydraPhase.TWO);
return;
case TWO:
changePhase(HydraPhase.THREE);
hydra.changePhase(HydraPhase.THREE);
return;
case THREE:
changePhase(HydraPhase.FOUR);
hydra.changePhase(HydraPhase.FOUR);
return;
case FOUR:
hydra = null;
@@ -237,9 +236,9 @@ public class HydraPlugin extends Plugin
poisonProjectiles.put(event.getPosition(), projectile);
}
else if (client.getTickCount() != lastAttackTick
&& (id == Hydra.AttackStyle.MAGIC.getProjId() || id == Hydra.AttackStyle.RANGED.getProjId()))
&& (id == Hydra.AttackStyle.MAGIC.getProjectileID() || id == Hydra.AttackStyle.RANGED.getProjectileID()))
{
handleAttack(id);
hydra.handleAttack(id);
lastAttackTick = client.getTickCount();
}
}
@@ -271,53 +270,4 @@ public class HydraPlugin extends Plugin
overlayManager.remove(overlay);
overlayManager.remove(poisonOverlay);
}
private void changePhase(HydraPhase newPhase)
{
hydra.setPhase(newPhase);
hydra.setNextSpecial(3);
hydra.setAttackCount(0);
hydra.setWeakened(false);
if (newPhase == HydraPhase.FOUR)
{
hydra.setWeakened(true);
switchStyles();
hydra.setNextSwitch(newPhase.getAttacksPerSwitch());
}
}
private void switchStyles()
{
hydra.setNextAttack(hydra.getLastAttack() == Hydra.AttackStyle.MAGIC
? Hydra.AttackStyle.RANGED
: Hydra.AttackStyle.MAGIC);
}
private void handleAttack(int id)
{
if (id != hydra.getNextAttack().getProjId() && id != hydra.getLastAttack().getProjId())
{ // If the current attack isn't what was expected and we should have switched prayers
switchStyles();
hydra.setNextSwitch(hydra.getPhase().getAttacksPerSwitch() - 1);
hydra.setLastAttack(hydra.getNextAttack());
}
else if (id != hydra.getNextAttack().getProjId() && id == hydra.getLastAttack().getProjId())
{ // If the current attack isn't what was expected and we accidentally counted 1 too much
return;
}
else
{
hydra.setNextSwitch(hydra.getNextSwitch() - 1);
hydra.setLastAttack(hydra.getNextAttack());
}
hydra.setAttackCount(hydra.getAttackCount() + 1);
if (hydra.getNextSwitch() <= 0)
{
switchStyles();
hydra.setNextSwitch(hydra.getPhase().getAttacksPerSwitch());
}
}
}

View File

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

View File

@@ -321,12 +321,12 @@ public class BankTagsPlugin extends Plugin implements MouseWheelListener, KeyLis
@Subscribe
public void onMenuOptionClicked(MenuOptionClicked event)
{
if (event.getWidgetId() == WidgetInfo.BANK_ITEM_CONTAINER.getId()
if (event.getActionParam1() == WidgetInfo.BANK_ITEM_CONTAINER.getId()
&& event.getMenuAction() == MenuAction.RUNELITE
&& event.getMenuOption().startsWith(EDIT_TAGS_MENU_OPTION))
&& event.getOption().startsWith(EDIT_TAGS_MENU_OPTION))
{
event.consume();
int inventoryIndex = event.getActionParam();
int inventoryIndex = event.getActionParam0();
ItemContainer bankContainer = client.getItemContainer(InventoryID.BANK);
if (bankContainer == null)
{

View File

@@ -50,6 +50,7 @@ import javax.inject.Inject;
import javax.inject.Singleton;
import lombok.Getter;
import net.runelite.api.Client;
import net.runelite.api.Constants;
import net.runelite.api.InventoryID;
import net.runelite.api.Item;
import net.runelite.api.ItemDefinition;
@@ -230,9 +231,9 @@ public class TabInterface
.filter(id -> id != -1)
.collect(Collectors.toList());
if (!Strings.isNullOrEmpty(event.getMenuTarget()))
if (!Strings.isNullOrEmpty(event.getTarget()))
{
if (activeTab != null && Text.removeTags(event.getMenuTarget()).equals(activeTab.getTag()))
if (activeTab != null && Text.removeTags(event.getTarget()).equals(activeTab.getTag()))
{
for (Integer item : items)
{
@@ -564,9 +565,9 @@ public class TabInterface
return;
}
if (event.getWidgetId() == WidgetInfo.BANK_ITEM_CONTAINER.getId()
if (event.getActionParam1() == WidgetInfo.BANK_ITEM_CONTAINER.getId()
&& event.getMenuAction() == MenuAction.EXAMINE_ITEM_BANK_EQ
&& event.getMenuOption().equalsIgnoreCase("withdraw-x"))
&& event.getOption().equalsIgnoreCase("withdraw-x"))
{
waitSearchTick = true;
rememberedSearch = client.getVar(VarClientStr.INPUT_TEXT);
@@ -575,9 +576,9 @@ public class TabInterface
if (iconToSet != null)
{
if (event.getMenuOption().startsWith(CHANGE_ICON + " ("))
if (event.getOption().startsWith(CHANGE_ICON + " ("))
{
ItemDefinition item = getItem(event.getActionParam());
ItemDefinition item = getItem(event.getActionParam0());
int itemId = itemManager.canonicalize(item.getId());
iconToSet.setIconItemId(itemId);
iconToSet.getIcon().setItemId(itemId);
@@ -590,7 +591,7 @@ public class TabInterface
}
if (activeTab != null
&& event.getMenuOption().equals("Search")
&& event.getOption().equals("Search")
&& client.getWidget(WidgetInfo.BANK_SEARCH_BUTTON_BACKGROUND).getSpriteId() != SpriteID.EQUIPMENT_SLOT_SELECTED)
{
activateTab(null);
@@ -600,27 +601,27 @@ public class TabInterface
client.setVar(VarClientInt.INPUT_TYPE, 0);
}
else if (activeTab != null
&& event.getMenuOption().startsWith("View tab"))
&& event.getOption().startsWith("View tab"))
{
activateTab(null);
}
else if (activeTab != null
&& event.getWidgetId() == WidgetInfo.BANK_ITEM_CONTAINER.getId()
&& event.getActionParam1() == WidgetInfo.BANK_ITEM_CONTAINER.getId()
&& event.getMenuAction() == MenuAction.RUNELITE
&& event.getMenuOption().startsWith(REMOVE_TAG))
&& event.getOption().startsWith(REMOVE_TAG))
{
// Add "remove" menu entry to all items in bank while tab is selected
event.consume();
final ItemDefinition item = getItem(event.getActionParam());
final ItemDefinition item = getItem(event.getActionParam0());
final int itemId = item.getId();
tagManager.removeTag(itemId, activeTab.getTag());
bankSearch.search(InputType.SEARCH, TAG_SEARCH + activeTab.getTag(), true);
}
else if (event.getMenuAction() == MenuAction.RUNELITE
&& ((event.getWidgetId() == WidgetInfo.BANK_DEPOSIT_INVENTORY.getId() && event.getMenuOption().equals(TAG_INVENTORY))
|| (event.getWidgetId() == WidgetInfo.BANK_DEPOSIT_EQUIPMENT.getId() && event.getMenuOption().equals(TAG_GEAR))))
&& ((event.getActionParam1() == WidgetInfo.BANK_DEPOSIT_INVENTORY.getId() && event.getOption().equals(TAG_INVENTORY))
|| (event.getActionParam1() == WidgetInfo.BANK_DEPOSIT_EQUIPMENT.getId() && event.getOption().equals(TAG_GEAR))))
{
handleDeposit(event, event.getWidgetId() == WidgetInfo.BANK_DEPOSIT_INVENTORY.getId());
handleDeposit(event, event.getActionParam1() == WidgetInfo.BANK_DEPOSIT_INVENTORY.getId());
}
}
@@ -730,7 +731,13 @@ public class TabInterface
if (tagTab.getIcon() == null)
{
Widget icon = createGraphic(ColorUtil.wrapWithColorTag(tagTab.getTag(), HILIGHT_COLOR), -1, tagTab.getIconItemId(), 36, 32, bounds.x + 3, 1, false);
Widget icon = createGraphic(
ColorUtil.wrapWithColorTag(tagTab.getTag(), HILIGHT_COLOR),
-1,
tagTab.getIconItemId(),
Constants.ITEM_SPRITE_WIDTH, Constants.ITEM_SPRITE_HEIGHT,
bounds.x + 3, 1,
false);
int clickmask = icon.getClickMask();
clickmask |= WidgetConfig.DRAG;
clickmask |= WidgetConfig.DRAG_ON;

View File

@@ -27,12 +27,10 @@
package net.runelite.client.plugins.banlist;
import com.google.inject.Provides;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import javax.inject.Inject;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.ChatMessageType;
import net.runelite.api.ClanMember;
@@ -62,12 +60,12 @@ import okhttp3.Request;
import okhttp3.Response;
@PluginDescriptor(
name = "Ban List",
description = "Displays warning in chat when you join a" +
"clan chat/new member join your clan chat and he is in a WDR/RuneWatch/Manual List",
tags = {"PVM", "WDR", "RuneWatch"},
type = PluginType.UTILITY,
enabledByDefault = false
name = "Ban List",
description = "Displays warning in chat when you join a" +
"clan chat/new member join your clan chat and he is in a WDR/RuneWatch/Manual List",
tags = {"PVM", "WDR", "RuneWatch"},
type = PluginType.UTILITY,
enabledByDefault = false
)
@Slf4j
@@ -137,10 +135,10 @@ public class BanListPlugin extends Plugin
public void onWidgetHiddenChanged(WidgetHiddenChanged widgetHiddenChanged)
{
if (client.getGameState() != GameState.LOGGED_IN
|| client.getWidget(WidgetInfo.LOGIN_CLICK_TO_PLAY_SCREEN) != null
|| client.getViewportWidget() == null
|| client.getWidget(WidgetInfo.CLAN_CHAT) == null
|| !config.highlightInClan())
|| client.getWidget(WidgetInfo.LOGIN_CLICK_TO_PLAY_SCREEN) != null
|| client.getViewportWidget() == null
|| client.getWidget(WidgetInfo.CLAN_CHAT) == null
|| !config.highlightInClan())
{
return;
}
@@ -159,10 +157,21 @@ public class BanListPlugin extends Plugin
public void onClanMemberJoined(ClanMemberJoined event)
{
ClanMember member = event.getMember();
ListType listType = checkBanList(Text.standardize(member.getUsername()));
if (listType != null)
ListType scamList = checkScamList(Text.standardize(member.getUsername()));
ListType toxicList = checkToxicList(Text.standardize(member.getUsername()));
if (scamList != null)
{
sendWarning(Text.standardize(member.getUsername()), listType);
sendWarning(Text.standardize(member.getUsername()), scamList);
if (config.highlightInClan())
{
highlightRedInCC();
}
}
if (toxicList != null)
{
sendWarning(Text.standardize(member.getUsername()), toxicList);
if (config.highlightInClan())
{
highlightRedInCC();
@@ -184,10 +193,14 @@ public class BanListPlugin extends Plugin
{
Widget tradingWith = client.getWidget(335, 31);
String name = tradingWith.getText().replaceAll("Trading With: ", "");
if (checkBanList(name) != null)
if (checkScamList(name) != null)
{
tradingWith.setText(tradingWith.getText().replaceAll(name, "<col=ff0000>" + name + " (Scammer)" + "</col>"));
}
if (checkToxicList(name) != null)
{
tradingWith.setText(tradingWith.getText().replaceAll(name, "<col=ff6400>" + name + " (Toxic)" + "</col>"));
}
});
}
}
@@ -196,7 +209,7 @@ public class BanListPlugin extends Plugin
/**
* Compares player name to everything in the ban lists
*/
private ListType checkBanList(String nameToBeChecked)
private ListType checkScamList(String nameToBeChecked)
{
if (wdrScamArrayList.size() > 0 && config.enableWDR())
{
@@ -206,14 +219,6 @@ public class BanListPlugin extends Plugin
}
}
if (wdrToxicArrayList.size() > 0 && config.enableWDR())
{
if (wdrToxicArrayList.stream().anyMatch(nameToBeChecked::equalsIgnoreCase))
{
return ListType.WEDORAIDSTOXIC_LIST;
}
}
if (runeWatchArrayList.size() > 0 && config.enableRuneWatch())
{
if (runeWatchArrayList.stream().anyMatch(nameToBeChecked::equalsIgnoreCase))
@@ -233,6 +238,20 @@ public class BanListPlugin extends Plugin
return null;
}
private ListType checkToxicList(String nameToBeChecked)
{
if (wdrToxicArrayList.size() > 0 && config.enableWDR())
{
if (wdrToxicArrayList.stream().anyMatch(nameToBeChecked::equalsIgnoreCase))
{
return ListType.WEDORAIDSTOXIC_LIST;
}
}
return null;
}
/**
* Sends a warning to our player, notifying them that a player is on a ban list
*/
@@ -242,53 +261,53 @@ public class BanListPlugin extends Plugin
{
case WEDORAIDSSCAM_LIST:
final String wdr__scam_message = new ChatMessageBuilder()
.append(ChatColorType.HIGHLIGHT)
.append("Warning! " + playerName + " is on WeDoRaids\' scammer list!")
.build();
.append(ChatColorType.HIGHLIGHT)
.append("Warning! " + playerName + " is on WeDoRaids\' scammer list!")
.build();
chatMessageManager.queue(
QueuedMessage.builder()
.type(ChatMessageType.CONSOLE)
.runeLiteFormattedMessage(wdr__scam_message)
.build());
QueuedMessage.builder()
.type(ChatMessageType.CONSOLE)
.runeLiteFormattedMessage(wdr__scam_message)
.build());
break;
case WEDORAIDSTOXIC_LIST:
final String wdr__toxic_message = new ChatMessageBuilder()
.append(ChatColorType.HIGHLIGHT)
.append("Warning! " + playerName + " is on WeDoRaids\' toxic list!")
.build();
.append(ChatColorType.HIGHLIGHT)
.append("Warning! " + playerName + " is on WeDoRaids\' toxic list!")
.build();
chatMessageManager.queue(
QueuedMessage.builder()
.type(ChatMessageType.CONSOLE)
.runeLiteFormattedMessage(wdr__toxic_message)
.build());
QueuedMessage.builder()
.type(ChatMessageType.CONSOLE)
.runeLiteFormattedMessage(wdr__toxic_message)
.build());
break;
case RUNEWATCH_LIST:
final String rw_message = new ChatMessageBuilder()
.append(ChatColorType.HIGHLIGHT)
.append("Warning! " + playerName + " is on the Runewatch\'s scammer list!")
.build();
.append(ChatColorType.HIGHLIGHT)
.append("Warning! " + playerName + " is on the Runewatch\'s scammer list!")
.build();
chatMessageManager.queue(
QueuedMessage.builder()
.type(ChatMessageType.CONSOLE)
.runeLiteFormattedMessage(rw_message)
.build());
QueuedMessage.builder()
.type(ChatMessageType.CONSOLE)
.runeLiteFormattedMessage(rw_message)
.build());
break;
case MANUAL_LIST:
final String manual_message = new ChatMessageBuilder()
.append(ChatColorType.HIGHLIGHT)
.append("Warning! " + playerName + " is on your manual scammer list!")
.build();
.append(ChatColorType.HIGHLIGHT)
.append("Warning! " + playerName + " is on your manual scammer list!")
.build();
chatMessageManager.queue(
QueuedMessage.builder()
.type(ChatMessageType.CONSOLE)
.runeLiteFormattedMessage(manual_message)
.build());
QueuedMessage.builder()
.type(ChatMessageType.CONSOLE)
.runeLiteFormattedMessage(manual_message)
.build());
break;
}
}
@@ -299,8 +318,8 @@ public class BanListPlugin extends Plugin
private void fetchFromWebsites()
{
Request request = new Request.Builder()
.url("https://wdrdev.github.io/index")
.build();
.url("https://wdrdev.github.io/index")
.build();
RuneLiteAPI.CLIENT.newCall(request).enqueue(new Callback()
{
@Override
@@ -327,8 +346,8 @@ public class BanListPlugin extends Plugin
Request secondRequest = new Request.Builder()
.url("https://runewatch.com/incident-index-page/")
.build();
.url("https://runewatch.com/incident-index-page/")
.build();
RuneLiteAPI.CLIENT.newCall(secondRequest).enqueue(new Callback()
{
@Override
@@ -356,8 +375,8 @@ public class BanListPlugin extends Plugin
});
Request thirdRequest = new Request.Builder()
.url("https://wdrdev.github.io/toxic")
.build();
.url("https://wdrdev.github.io/toxic")
.build();
RuneLiteAPI.CLIENT.newCall(thirdRequest).enqueue(new Callback()
{
@Override
@@ -393,13 +412,18 @@ public class BanListPlugin extends Plugin
Widget widget = client.getWidget(WidgetInfo.CLAN_CHAT_LIST);
for (Widget widgetChild : widget.getDynamicChildren())
{
ListType listType = checkBanList(widgetChild.getText());
ListType scamList = checkScamList(widgetChild.getText());
ListType toxicList = checkToxicList(widgetChild.getText());
if (listType != null)
if (scamList != null)
{
widgetChild.setText("<col=ff0000>" + widgetChild.getText() + "</col>");
}
else if (toxicList != null)
{
widgetChild.setText("<col=ff6400>" + widgetChild.getText() + "</col>");
}
}
});
}
}
}

View File

@@ -707,21 +707,21 @@ public class BAToolsPlugin extends Plugin implements KeyListener
@Subscribe
public void onMenuOptionClicked(MenuOptionClicked event)
{
String target = event.getMenuTarget();
String target = event.getTarget();
if (config.tagging() && (event.getMenuTarget().contains("Penance Ranger") || event.getMenuTarget().contains("Penance Fighter")))
if (config.tagging() && (event.getTarget().contains("Penance Ranger") || event.getTarget().contains("Penance Fighter")))
{
if (event.getMenuOption().contains("Attack"))
if (event.getOption().contains("Attack"))
{
foodPressed.put(event.getId(), Instant.now());
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.getId(), Instant.now());
lastHealer = event.getId();
foodPressed.put(event.getIdentifier(), Instant.now());
lastHealer = event.getIdentifier();
log.info("Last healer changed: " + lastHealer);
}
}

View File

@@ -35,7 +35,7 @@ public enum CannonSpots
BLOODVELDS(new WorldPoint(2439, 9821, 0), new WorldPoint(2448, 9821, 0), new WorldPoint(2472, 9833, 0), new WorldPoint(2453, 9817, 0)),
FIRE_GIANTS(new WorldPoint(2393, 9782, 0), new WorldPoint(2412, 9776, 0), new WorldPoint(2401, 9780, 0)),
ABBERANT_SPECTRES(new WorldPoint(2456, 9791, 0)),
ABERRANT_SPECTRES(new WorldPoint(2456, 9791, 0)),
HELLHOUNDS(new WorldPoint(2431, 9776, 0), new WorldPoint(2413, 9786, 0), new WorldPoint(2783, 9686, 0), new WorldPoint(3198, 10071, 0)),
BLACK_DEMONS(new WorldPoint(2859, 9778, 0), new WorldPoint(2841, 9791, 0)),
ELVES(new WorldPoint(2044, 4635, 0)),

View File

@@ -168,7 +168,7 @@ public class ChatHistoryPlugin extends Plugin implements KeyListener
@Subscribe
public void onMenuOptionClicked(MenuOptionClicked event)
{
String menuOption = event.getMenuOption();
String menuOption = event.getOption();
if (menuOption.contains(CLEAR_HISTORY))
{

View File

@@ -129,9 +129,12 @@ public class ChatNotificationsPlugin extends Plugin
{
List<String> items = Text.fromCSV(config.highlightWordsString());
String joined = items.stream()
.map(Text::escapeJagex) // we compare these strings to the raw Jagex ones
.map(Pattern::quote)
.collect(Collectors.joining("|"));
highlightMatcher = Pattern.compile("\\b(" + joined + ")\\b", Pattern.CASE_INSENSITIVE);
// To match <word> \b doesn't work due to <> not being in \w,
// so match \b or \s
highlightMatcher = Pattern.compile("(?:\\b|(?<=\\s))(" + joined + ")(?:\\b|(?=\\s))", Pattern.CASE_INSENSITIVE);
}
}
@@ -139,7 +142,6 @@ public class ChatNotificationsPlugin extends Plugin
public void onChatMessage(ChatMessage chatMessage)
{
MessageNode messageNode = chatMessage.getMessageNode();
String nodeValue = Text.removeTags(messageNode.getValue());
boolean update = false;
switch (chatMessage.getType())
@@ -202,6 +204,7 @@ public class ChatNotificationsPlugin extends Plugin
if (highlightMatcher != null)
{
String nodeValue = messageNode.getValue();
Matcher matcher = highlightMatcher.matcher(nodeValue);
boolean found = false;
StringBuffer stringBuffer = new StringBuffer();

View File

@@ -3,29 +3,22 @@ package net.runelite.client.plugins.clanmanmode;
import com.google.inject.Provides;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.inject.Inject;
import net.runelite.api.Client;
import net.runelite.api.GameState;
import net.runelite.api.MenuEntry;
import net.runelite.api.Player;
import net.runelite.api.Varbits;
import net.runelite.api.coords.WorldPoint;
import net.runelite.api.events.ConfigChanged;
import net.runelite.api.events.GameStateChanged;
import net.runelite.api.events.GameTick;
import net.runelite.api.events.MenuEntryAdded;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.game.ClanManager;
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.util.Text;
import org.apache.commons.lang3.ArrayUtils;
@PluginDescriptor(
name = "Clan Man Mode",
@@ -37,10 +30,6 @@ import org.apache.commons.lang3.ArrayUtils;
public class ClanManModePlugin extends Plugin
{
private static final String WALK_HERE = "WALK HERE";
private static final String CANCEL = "CANCEL";
@Inject
private OverlayManager overlayManager;
@@ -59,18 +48,6 @@ public class ClanManModePlugin extends Plugin
@Inject
private Client client;
@Inject
private ClanManager clanManager;
private static final String CAST = "CAST";
private static final String ATTACK_OPTIONS_ATTACK = "ATTACK";
public static final HashSet<String> ATTACK_OPTIONS_KEYWORDS = new HashSet<>();
static
{
ATTACK_OPTIONS_KEYWORDS.add(CAST);
ATTACK_OPTIONS_KEYWORDS.add(ATTACK_OPTIONS_ATTACK);
}
@Provides
ClanManModeConfig provideConfig(ConfigManager configManager)
{
@@ -90,6 +67,7 @@ public class ClanManModePlugin extends Plugin
overlayManager.add(ClanManModeOverlay);
overlayManager.add(ClanManModeTileOverlay);
overlayManager.add(ClanManModeMinimapOverlay);
client.setHideFriendAttackOptions(config.hideAtkOpt());
}
@Override
@@ -98,6 +76,7 @@ public class ClanManModePlugin extends Plugin
overlayManager.remove(ClanManModeOverlay);
overlayManager.remove(ClanManModeTileOverlay);
overlayManager.remove(ClanManModeMinimapOverlay);
client.setHideFriendAttackOptions(false);
clan.clear();
ticks = 0;
wildernessLevel = 0;
@@ -106,6 +85,17 @@ public class ClanManModePlugin extends Plugin
inwildy = 0;
}
@Subscribe
private void onConfigChanged(ConfigChanged event)
{
if (!"clanmanmode".equals(event.getGroup()))
{
return;
}
client.setHideFriendAttackOptions(config.hideAtkOpt());
}
@Subscribe
public void onGameStateChanged(GameStateChanged gameStateChanged)
{
@@ -135,111 +125,4 @@ public class ClanManModePlugin extends Plugin
clanmax = Collections.max(clan.values());
}
}
@Subscribe
public void onMenuEntryAdded(MenuEntryAdded event)
{
if (client.getGameState() != GameState.LOGGED_IN)
{
return;
}
Player[] players = client.getCachedPlayers();
Player player = null;
int identifier = event.getIdentifier();
if (identifier >= 0 && identifier < players.length)
{
player = players[identifier];
}
if (player == null)
{
return;
}
final String pOptionToReplace = Text.removeTags(event.getOption()).toUpperCase();
//If the option is already to walk there, or cancel we don't need to swap it with anything
if (pOptionToReplace.equals(CANCEL) || pOptionToReplace.equals(WALK_HERE))
{
return;
}
if (config.hideAtkOpt()
&& ATTACK_OPTIONS_KEYWORDS.contains(pOptionToReplace)
&& (player.isFriend() || player.isClanMember()))
{
swap(pOptionToReplace);
}
else if (!config.hideAtkOpt())
{
return;
}
final String option = Text.removeTags(event.getOption()).toLowerCase();
if (option.equals("attack"))
{
final Pattern ppattern = Pattern.compile("<col=ffffff>(.+?)<col=");
final Matcher pmatch = ppattern.matcher(event.getTarget());
if (pmatch.find() && pmatch.matches())
{
if (pmatch.group(1) != null)
{
if (clan.containsKey(pmatch.group(1).replace(" ", " ")))
{
MenuEntry[] entries = client.getMenuEntries();
entries = ArrayUtils.removeElement(entries, entries[entries.length - 1]);
client.setMenuEntries(entries);
}
}
}
}
}
/**
* Swaps menu entries if the entries could be found. This places Walk Here where the top level menu option was.
* @param pOptionToReplace The String containing the Menu Option that needs to be replaced. IE: "Attack", "Chop Down".
*/
private void swap(String pOptionToReplace)
{
MenuEntry[] entries = client.getMenuEntries();
Integer walkHereEntry = searchIndex(entries, WALK_HERE);
Integer entryToReplace = searchIndex(entries, pOptionToReplace);
if (walkHereEntry != null
&& entryToReplace != null)
{
MenuEntry walkHereMenuEntry = entries[walkHereEntry];
entries[walkHereEntry] = entries[entryToReplace];
entries[entryToReplace] = walkHereMenuEntry;
client.setMenuEntries(entries);
}
}
/**
* Finds the index of the menu that contains the verbiage we are looking for.
* @param pMenuEntries The list of {@link MenuEntry}s.
* @param pMenuEntryToSearchFor The Option in the menu to search for.
* @return The index location or null if it was not found.
*/
private Integer searchIndex(MenuEntry[] pMenuEntries, String pMenuEntryToSearchFor)
{
Integer indexLocation = 0;
for (MenuEntry menuEntry : pMenuEntries)
{
String entryOption = Text.removeTags(menuEntry.getOption()).toUpperCase();
if (entryOption.equals(pMenuEntryToSearchFor))
{
return indexLocation;
}
indexLocation++;
}
return null;
}
}

View File

@@ -225,9 +225,9 @@ public class ClueScrollPlugin extends Plugin
@Subscribe
public void onMenuOptionClicked(final MenuOptionClicked event)
{
if (event.getMenuOption() != null && event.getMenuOption().equals("Read"))
if (event.getOption() != null && event.getOption().equals("Read"))
{
final ItemDefinition itemComposition = itemManager.getItemDefinition(event.getId());
final ItemDefinition itemComposition = itemManager.getItemDefinition(event.getIdentifier());
if (itemComposition != null && itemComposition.getName().startsWith("Clue scroll"))
{

View File

@@ -259,7 +259,7 @@ public class CrypticClue extends ClueScroll implements TextClueScroll, NpcClueSc
new CrypticClue("Search the drawers in Catherby's Archery shop.", DRAWERS_350, new WorldPoint(2825, 3442, 0), "Hickton's Archery Emporium in Catherby."),
new CrypticClue("The hand ain't listening.", "The Face", new WorldPoint(3019, 3232, 0), "Talk to The Face located by the manhole just north of the Port Sarim fishing shop."),
new CrypticClue("Search the chest in the left-hand tower of Camelot Castle.", CLOSED_CHEST_25592, new WorldPoint(2748, 3495, 2), "Located on the second floor of the western tower of Camelot."),
new CrypticClue("Kill the spiritual, magic and godly whilst representing their own god", null, "Kill a spiritual mage while wearing a corresponding god item."),
new CrypticClue("Kill the spiritual, magic and godly whilst representing their own god.", null, "Kill a spiritual mage while wearing a corresponding god item."),
new CrypticClue("Anger those who adhere to Saradomin's edicts to prevent travel.", "Monk of Entrana", new WorldPoint(3042, 3236, 0), "Port Sarim Docks, try to charter a ship to Entrana with armour or weapons equipped."),
new CrypticClue("South of a river in a town surrounded by the undead, what lies beneath the furnace?", new WorldPoint(2857, 2966, 0), "Dig in front of the Shilo Village furnace."),
new CrypticClue("Talk to the Squire in the White Knights' castle in Falador.", "Squire", new WorldPoint(2977, 3343, 0), "The squire is located in the courtyard of the White Knights' Castle."),

View File

@@ -87,11 +87,11 @@ public class FaloTheBardClue extends ClueScroll implements TextClueScroll, NpcCl
new FaloTheBardClue("A shiny helmet of flight, to obtain this with melee, struggle you might.", item(ARMADYL_HELMET)),
// The wiki doesn't specify whether the trimmed dragon defender will work so I've assumed that it doesn't
new FaloTheBardClue("A sword held in the other hand, red its colour, Cyclops strength you must withstand.", item(DRAGON_DEFENDER)),
new FaloTheBardClue("A token used to kill mythical beasts, in hope of a blade or just for an xp feast.", item(WARRIOR_GUILD_TOKEN)),
new FaloTheBardClue("A token used to kill mythical beasts, in hopes of a blade or just for an xp feast.", item(WARRIOR_GUILD_TOKEN)),
new FaloTheBardClue("Green is my favorite, mature ale I do love, this takes your herblore above.", item(GREENMANS_ALEM)),
new FaloTheBardClue("It can hold down a boat or crush a goat, this object, you see, is quite heavy.", item(BARRELCHEST_ANCHOR)),
new FaloTheBardClue("It comes from the ground, underneath the snowy plain. Trolls aplenty, with what looks like a mane.", item(BASALT)),
new FaloTheBardClue("No attack to wield, only strength is required, made of obsidian but with no room for a shield.", item(TZHAARKETOM)),
new FaloTheBardClue("No attack to wield, only strength is required, made of obsidian, but with no room for a shield.", item(TZHAARKETOM)),
new FaloTheBardClue("Penance healers runners and more, obtaining this body often gives much deplore.", item(FIGHTER_TORSO)),
new FaloTheBardClue("Strangely found in a chest, many believe these gloves are the best.", item(BARROWS_GLOVES)),
new FaloTheBardClue("These gloves of white won't help you fight, but aid in cooking, they just might.", item(COOKING_GAUNTLETS)),

View File

@@ -38,6 +38,7 @@ import net.runelite.api.SpriteID;
import net.runelite.client.game.SpriteManager;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.OverlayPriority;
import net.runelite.client.ui.overlay.components.ComponentConstants;
import net.runelite.client.ui.overlay.components.InfoBoxComponent;
import net.runelite.client.ui.overlay.components.PanelComponent;
@@ -64,7 +65,8 @@ public class CoxInfoBox extends Overlay
this.client = client;
this.spriteManager = spriteManager;
setPosition(OverlayPosition.BOTTOM_RIGHT);
setPosition(OverlayPosition.DETACHED);
setPriority(OverlayPriority.HIGH);
}
@Override
@@ -103,7 +105,7 @@ public class CoxInfoBox extends Overlay
plugin.setPrayAgainstOlm(null);
}
if (config.vangHealth() && plugin.isRunVanguard())
if (config.vangHealth() && plugin.getVanguards() > 0)
{
panelComponent.getChildren().add(TitleComponent.builder()
.text("Vanguards")

View File

@@ -108,7 +108,7 @@ public class CoxPlugin extends Plugin
@Getter(AccessLevel.PACKAGE)
private boolean runOlm;
@Getter(AccessLevel.PACKAGE)
private boolean runVanguard;
private int vanguards;
@Getter(AccessLevel.PACKAGE)
private boolean tektonActive;
@Getter(AccessLevel.PACKAGE)
@@ -165,13 +165,6 @@ public class CoxPlugin extends Plugin
{
overlayManager.add(coxOverlay);
overlayManager.add(coxInfoBox);
}
@Override
protected void shutDown()
{
overlayManager.remove(coxOverlay);
overlayManager.remove(coxInfoBox);
HandCripple = false;
hand = null;
acidTarget = null;
@@ -183,6 +176,14 @@ public class CoxPlugin extends Plugin
burnTicks = 40;
acidTicks = 25;
teleportTicks = 10;
vanguards = 0;
}
@Override
protected void shutDown()
{
overlayManager.remove(coxOverlay);
overlayManager.remove(coxInfoBox);
}
@Subscribe
@@ -226,22 +227,30 @@ public class CoxPlugin extends Plugin
needOlm = true;
Olm_NextSpec = -1;
break;
case "the great olm's left claw clenches to protect itself temporarily.":
HandCripple = true;
timer = 45;
break;
case "the great olm fires a sphere of aggression your way. your prayers have been sapped.":
prayAgainstOlm = PrayAgainst.MELEE;
lastPrayTime = System.currentTimeMillis();
break;
case "the great olm fires a sphere of aggression your way.":
prayAgainstOlm = PrayAgainst.MELEE;
lastPrayTime = System.currentTimeMillis();
break;
case "the great olm fires a sphere of magical power your way. your prayers have been sapped.":
prayAgainstOlm = PrayAgainst.MAGIC;
lastPrayTime = System.currentTimeMillis();
break;
case "the great olm fires a sphere of magical power your way.":
prayAgainstOlm = PrayAgainst.MAGIC;
lastPrayTime = System.currentTimeMillis();
break;
case "the great olm fires a sphere of accuracy and dexterity your way. your prayers have been sapped.":
prayAgainstOlm = PrayAgainst.RANGED;
lastPrayTime = System.currentTimeMillis();
break;
case "the great olm fires a sphere of accuracy and dexterity your way.":
prayAgainstOlm = PrayAgainst.RANGED;
lastPrayTime = System.currentTimeMillis();
break;
}
}
@@ -316,7 +325,7 @@ public class CoxPlugin extends Plugin
case NpcID.VANGUARD_7527:
case NpcID.VANGUARD_7528:
case NpcID.VANGUARD_7529:
runVanguard = true;
vanguards++;
npcContainer.put(npc, new NPCContainer(npc));
break;
case NpcID.GREAT_OLM_LEFT_CLAW:
@@ -362,7 +371,7 @@ public class CoxPlugin extends Plugin
{
npcContainer.remove(event.getNpc());
}
runVanguard = false;
vanguards--;
break;
case NpcID.GREAT_OLM_RIGHT_CLAW_7553:
case NpcID.GREAT_OLM_RIGHT_CLAW:
@@ -513,16 +522,22 @@ public class CoxPlugin extends Plugin
}
break;
case NpcID.VANGUARD_7529:
npcs.setAttackStyle(NPCContainer.Attackstyle.MAGE);
if (npcs.getAttackStyle() == NPCContainer.Attackstyle.UNKNOWN)
{
npcs.setAttackStyle(NPCContainer.Attackstyle.MAGE);
}
break;
case NpcID.VANGUARD_7528:
npcs.setAttackStyle(NPCContainer.Attackstyle.RANGE);
if (npcs.getAttackStyle() == NPCContainer.Attackstyle.UNKNOWN)
{
npcs.setAttackStyle(NPCContainer.Attackstyle.RANGE);
}
break;
case NpcID.VANGUARD_7527:
npcs.setAttackStyle(NPCContainer.Attackstyle.MELEE);
break;
case NpcID.VANGUARD_7526:
npcs.setAttackStyle(NPCContainer.Attackstyle.UNKNOWN);
if (npcs.getAttackStyle() == NPCContainer.Attackstyle.UNKNOWN)
{
npcs.setAttackStyle(NPCContainer.Attackstyle.MELEE);
}
break;
}
}

View File

@@ -26,6 +26,8 @@ package net.runelite.client.plugins.emojis;
import java.awt.image.BufferedImage;
import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Nullable;
import javax.inject.Inject;
import joptsimple.internal.Strings;
@@ -52,6 +54,8 @@ import net.runelite.client.util.ImageUtil;
@Slf4j
public class EmojiPlugin extends Plugin
{
private static final Pattern TAG_REGEXP = Pattern.compile("<[^>]*>");
@Inject
private Client client;
@@ -128,7 +132,8 @@ public class EmojiPlugin extends Plugin
return;
}
final String message = chatMessage.getMessage();
final MessageNode messageNode = chatMessage.getMessageNode();
final String message = messageNode.getValue();
final String updatedMessage = updateMessage(message);
if (updatedMessage == null)
@@ -136,7 +141,6 @@ public class EmojiPlugin extends Plugin
return;
}
final MessageNode messageNode = chatMessage.getMessageNode();
messageNode.setRuneLiteFormatMessage(updatedMessage);
chatMessageManager.update(messageNode);
client.refreshChat();
@@ -169,7 +173,9 @@ public class EmojiPlugin extends Plugin
boolean editedMessage = false;
for (int i = 0; i < messageWords.length; i++)
{
final Emoji emoji = Emoji.getEmoji(messageWords[i]);
// Remove tags except for <lt> and <gt>
final String trigger = removeTags(messageWords[i]);
final Emoji emoji = Emoji.getEmoji(trigger);
if (emoji == null)
{
@@ -178,7 +184,7 @@ public class EmojiPlugin extends Plugin
final int emojiId = modIconsStart + emoji.ordinal();
messageWords[i] = "<img=" + emojiId + ">";
messageWords[i] = messageWords[i].replace(trigger, "<img=" + emojiId + ">");
editedMessage = true;
}
@@ -190,4 +196,29 @@ public class EmojiPlugin extends Plugin
return Strings.join(messageWords, " ");
}
/**
* Remove tags, except for &lt;lt&gt; and &lt;gt&gt;
*
* @return
*/
private static String removeTags(String str)
{
StringBuffer stringBuffer = new StringBuffer();
Matcher matcher = TAG_REGEXP.matcher(str);
while (matcher.find())
{
matcher.appendReplacement(stringBuffer, "");
String match = matcher.group(0);
switch (match)
{
case "<lt>":
case "<gt>":
stringBuffer.append(match);
break;
}
}
matcher.appendTail(stringBuffer);
return stringBuffer.toString();
}
}

View File

@@ -104,7 +104,7 @@ public class ExaminePlugin extends Plugin
@Subscribe
public void onMenuOptionClicked(MenuOptionClicked event)
{
if (!event.getMenuOption().equals("Examine"))
if (!event.getOption().equals("Examine"))
{
return;
}
@@ -116,20 +116,20 @@ public class ExaminePlugin extends Plugin
case EXAMINE_ITEM:
{
type = ExamineType.ITEM;
id = event.getId();
id = event.getIdentifier();
int widgetId = event.getWidgetId();
int widgetId = event.getActionParam1();
int widgetGroup = TO_GROUP(widgetId);
int widgetChild = TO_CHILD(widgetId);
Widget widget = client.getWidget(widgetGroup, widgetChild);
WidgetItem widgetItem = widget.getWidgetItem(event.getActionParam());
WidgetItem widgetItem = widget.getWidgetItem(event.getActionParam0());
quantity = widgetItem != null && widgetItem.getId() >= 0 ? widgetItem.getQuantity() : 1;
break;
}
case EXAMINE_ITEM_BANK_EQ:
{
type = ExamineType.ITEM_BANK_EQ;
int[] qi = findItemFromWidget(event.getWidgetId(), event.getActionParam());
int[] qi = findItemFromWidget(event.getActionParam1(), event.getActionParam0());
if (qi == null)
{
log.debug("Examine for item with unknown widget: {}", event);
@@ -141,11 +141,11 @@ public class ExaminePlugin extends Plugin
}
case EXAMINE_OBJECT:
type = ExamineType.OBJECT;
id = event.getId();
id = event.getIdentifier();
break;
case EXAMINE_NPC:
type = ExamineType.NPC;
id = event.getId();
id = event.getIdentifier();
break;
default:
return;
@@ -199,26 +199,26 @@ public class ExaminePlugin extends Plugin
log.debug("Got examine for {} {}: {}", pendingExamine.getType(), pendingExamine.getId(), event.getMessage());
// If it is an item, show the price of it
final ItemDefinition itemComposition;
final ItemDefinition Itemdefinition;
if (pendingExamine.getType() == ExamineType.ITEM || pendingExamine.getType() == ExamineType.ITEM_BANK_EQ)
{
final int itemId = pendingExamine.getId();
final int itemQuantity = pendingExamine.getQuantity();
itemComposition = itemManager.getItemDefinition(itemId);
Itemdefinition = itemManager.getItemDefinition(itemId);
if (itemComposition != null)
if (Itemdefinition != null)
{
final int id = itemManager.canonicalize(itemComposition.getId());
executor.submit(() -> getItemPrice(id, itemComposition, itemQuantity));
final int id = itemManager.canonicalize(Itemdefinition.getId());
executor.submit(() -> getItemPrice(id, Itemdefinition, itemQuantity));
}
}
else
{
itemComposition = null;
Itemdefinition = null;
}
// Don't submit examine info for tradeable items, which we already have from the RS item api
if (itemComposition != null && itemComposition.isTradeable())
if (Itemdefinition != null && Itemdefinition.isTradeable())
{
return;
}

View File

@@ -38,6 +38,7 @@ import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.components.PanelComponent;
import net.runelite.client.ui.overlay.components.TitleComponent;
import net.runelite.client.ui.overlay.components.table.TableComponent;
import net.runelite.client.ui.overlay.components.table.TableAlignment;
class WaveOverlay extends Overlay
{
@@ -97,14 +98,19 @@ class WaveOverlay extends Overlay
.color(HEADER_COLOR)
.build());
TableComponent tableComponent = new TableComponent();
tableComponent.setColumnAlignments(TableAlignment.CENTER);
for (String line : buildWaveLines(waveContents))
{
tableComponent.addRow(line);
}
panelComponent.getChildren().add(tableComponent);
if (!tableComponent.isEmpty())
{
panelComponent.getChildren().add(tableComponent);
}
}
private static Collection<String> buildWaveLines(final Map<WaveMonster, Integer> wave)

View File

@@ -45,6 +45,7 @@ public class FpsDrawListener implements Runnable
private static final int SAMPLE_SIZE = 4;
private final FpsConfig config;
private final FpsPlugin plugin;
private long targetDelay = 0;
@@ -58,9 +59,10 @@ public class FpsDrawListener implements Runnable
private long sleepDelay = 0;
@Inject
private FpsDrawListener(FpsConfig config)
private FpsDrawListener(FpsConfig config, FpsPlugin plugin)
{
this.config = config;
this.plugin = plugin;
reloadConfig();
}
@@ -83,8 +85,8 @@ public class FpsDrawListener implements Runnable
private boolean isEnforced()
{
return FpsLimitMode.ALWAYS == config.limitMode()
|| (FpsLimitMode.UNFOCUSED == config.limitMode() && !isFocused);
return FpsLimitMode.ALWAYS == plugin.getLimitMode()
|| (FpsLimitMode.UNFOCUSED == plugin.getLimitMode() && !isFocused);
}
@Override

View File

@@ -50,7 +50,6 @@ import net.runelite.client.ui.overlay.OverlayUtil;
public class FpsOverlay extends Overlay
{
// Local dependencies
private final FpsConfig config;
private final Client client;
private final FpsPlugin plugin;
@@ -58,9 +57,8 @@ public class FpsOverlay extends Overlay
private boolean isFocused = true;
@Inject
private FpsOverlay(FpsPlugin plugin, FpsConfig config, Client client)
private FpsOverlay(FpsPlugin plugin, Client client)
{
this.config = config;
this.client = client;
this.plugin = plugin;
setLayer(OverlayLayer.ABOVE_WIDGETS);
@@ -75,8 +73,8 @@ public class FpsOverlay extends Overlay
private boolean isEnforced()
{
return FpsLimitMode.ALWAYS == config.limitMode()
|| (FpsLimitMode.UNFOCUSED == config.limitMode() && !isFocused);
return FpsLimitMode.ALWAYS == plugin.getLimitMode()
|| (FpsLimitMode.UNFOCUSED == plugin.getLimitMode() && !isFocused);
}
private Color getFpsValueColor()
@@ -110,7 +108,7 @@ public class FpsOverlay extends Overlay
@Override
public Dimension render(Graphics2D graphics)
{
if (!config.drawFps() && !config.drawPing())
if (!plugin.isDrawFps() && !plugin.isDrawPing())
{
return null;
}
@@ -121,7 +119,7 @@ public class FpsOverlay extends Overlay
int baseYOffset = (fontMetrics.getAscent() - fontMetrics.getDescent()) + 1;
if (config.drawFps())
if (plugin.isDrawFps())
{
final String fpsText = String.format("%d FPS", client.getFPS());
final int textWidth = fontMetrics.stringWidth(fpsText);
@@ -132,7 +130,7 @@ public class FpsOverlay extends Overlay
baseYOffset += 11;
}
if (config.drawPing())
if (plugin.isDrawPing())
{
final String pingText = String.format("%dms", plugin.getPing());
final int textWidth = fontMetrics.stringWidth(pingText);

View File

@@ -29,6 +29,7 @@ import com.google.inject.Provides;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import lombok.AccessLevel;
import lombok.Getter;
import net.runelite.api.Client;
import net.runelite.api.GameState;
@@ -90,6 +91,15 @@ public class FpsPlugin extends Plugin
private final ScheduledExecutorService pingExecutorService = new ExecutorServiceExceptionLogger(Executors.newSingleThreadScheduledExecutor());
@Getter(AccessLevel.PACKAGE)
private FpsLimitMode limitMode;
@Getter(AccessLevel.PACKAGE)
private boolean drawFps;
@Getter(AccessLevel.PACKAGE)
private boolean drawPing;
@Provides
FpsConfig provideConfig(ConfigManager configManager)
{
@@ -102,6 +112,10 @@ public class FpsPlugin extends Plugin
if (event.getGroup().equals(CONFIG_GROUP_KEY))
{
drawListener.reloadConfig();
limitMode = fpsConfig.limitMode();
drawFps = fpsConfig.drawFps();
drawPing = fpsConfig.drawPing();
}
}
@@ -115,6 +129,9 @@ public class FpsPlugin extends Plugin
@Override
protected void startUp() throws Exception
{
limitMode = fpsConfig.limitMode();
drawFps = fpsConfig.drawFps();
drawPing = fpsConfig.drawPing();
overlayManager.add(overlay);
drawManager.registerEveryFrameListener(drawListener);
drawListener.reloadConfig();
@@ -131,7 +148,7 @@ public class FpsPlugin extends Plugin
private void getPingToCurrentWorld()
{
if (client.getGameState().equals(GameState.LOGGED_IN) && fpsConfig.drawPing())
if (client.getGameState().equals(GameState.LOGGED_IN) && drawPing)
{
ping = Ping.ping(String.format("oldschool%d.runescape.com", client.getWorld() - 300));
}

View File

@@ -119,6 +119,11 @@ public class FreezeTimersOverlay extends Overlay
String text = processTickCounter(finishedAt);
int test = Integer.parseInt(text);
Point poi = actor.getCanvasTextLocation(g, text, 0);
if (poi == null)
{
return false;
}
int xpoi = poi.getX();
int ypoi = poi.getY();
Point FixedPoint = new Point(xpoi, ypoi);

View File

@@ -190,20 +190,20 @@ public class FriendNotesPlugin extends Plugin
@Subscribe
public void onMenuOptionClicked(MenuOptionClicked event)
{
if (WidgetInfo.TO_GROUP(event.getWidgetId()) == WidgetInfo.FRIENDS_LIST.getGroupId())
if (WidgetInfo.TO_GROUP(event.getActionParam1()) == WidgetInfo.FRIENDS_LIST.getGroupId())
{
if (Strings.isNullOrEmpty(event.getMenuTarget()))
if (Strings.isNullOrEmpty(event.getTarget()))
{
return;
}
// Handle clicks on "Add Note" or "Edit Note"
if (event.getMenuOption().equals(ADD_NOTE) || event.getMenuOption().equals(EDIT_NOTE))
if (event.getOption().equals(ADD_NOTE) || event.getOption().equals(EDIT_NOTE))
{
event.consume();
//Friends have color tags
final String sanitizedTarget = Text.toJagexName(Text.removeTags(event.getMenuTarget()));
final String sanitizedTarget = Text.toJagexName(Text.removeTags(event.getTarget()));
final String note = getFriendNote(sanitizedTarget);
// Open the new chatbox input dialog

View File

@@ -162,16 +162,16 @@ public class FriendTaggingPlugin extends Plugin
@Subscribe
public void onMenuOptionClicked(MenuOptionClicked event)
{
if (WidgetInfo.TO_GROUP(event.getWidgetId()) == WidgetInfo.FRIENDS_LIST.getGroupId())
if (WidgetInfo.TO_GROUP(event.getActionParam1()) == WidgetInfo.FRIENDS_LIST.getGroupId())
{
if (Strings.isNullOrEmpty(event.getMenuTarget()))
if (Strings.isNullOrEmpty(event.getTarget()))
{
return;
}
final String sanitizedTarget = Text.removeTags(event.getMenuTarget());
final String sanitizedTarget = Text.removeTags(event.getTarget());
if (event.getMenuOption().equals(ADD_TAG))
if (event.getOption().equals(ADD_TAG))
{
event.consume();
final ChatboxTextInput build = chatboxPanelManager.openTextInput("Enter the tag").value("")
@@ -185,7 +185,7 @@ public class FriendTaggingPlugin extends Plugin
setTag(sanitizedTarget, content);
}).build();
}
if (event.getMenuOption().equals(DELETE_TAG))
if (event.getOption().equals(DELETE_TAG))
{
event.consume();
client.getLogger().info(sanitizedTarget);

View File

@@ -46,6 +46,7 @@ class GroundItem
private int offset;
private boolean tradeable;
private boolean isMine;
private int ticks;
private int durationMillis;
private boolean isAlwaysPrivate;
private boolean isOwnedByPlayer;

View File

@@ -606,4 +606,16 @@ public interface GroundItemsConfig extends Config
{
return false;
}
@ConfigItem(
keyName = "showTimer",
name = "Show ground item tick countdown timer",
description = "Shows how many ticks left until disappearing.",
position = 48,
parent = "miscStub"
)
default boolean showTimer()
{
return false;
}
}

View File

@@ -277,6 +277,13 @@ public class GroundItemsOverlay extends Overlay
}
}
if (item.getTicks() > 0 && config.showTimer())
{
itemStringBuilder
.append(" - ")
.append(item.getTicks());
}
final String itemString = itemStringBuilder.toString();
itemStringBuilder.setLength(0);

View File

@@ -69,6 +69,7 @@ import net.runelite.api.events.ItemDespawned;
import net.runelite.api.events.ItemQuantityChanged;
import net.runelite.api.events.ItemSpawned;
import net.runelite.api.events.MenuEntryAdded;
import net.runelite.api.events.GameTick;
import net.runelite.client.Notifier;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.Subscribe;
@@ -204,6 +205,16 @@ public class GroundItemsPlugin extends Plugin
collectedGroundItems.clear();
}
@Subscribe
public void onGameTick(GameTick event)
{
for (GroundItem item : collectedGroundItems.values())
{
if (item.getTicks() == -1) continue;
item.setTicks(item.getTicks() - 1);
}
}
@Subscribe
public void onConfigChanged(ConfigChanged event)
{
@@ -461,6 +472,7 @@ public class GroundItemsPlugin extends Plugin
if (groundItem != null)
{
groundItem.setMine(true);
groundItem.setTicks(200);
boolean shouldNotify = config.onlyShowLoot() && config.highlightedColor().equals(getHighlighted(
groundItem.getName(),
@@ -511,6 +523,7 @@ public class GroundItemsPlugin extends Plugin
.durationMillis(durationMillis)
.isAlwaysPrivate(client.isInInstancedRegion() || (!itemComposition.isTradeable() && realItemId != COINS))
.isOwnedByPlayer(tile.getWorldLocation().equals(playerLocation))
.ticks(tile.getWorldLocation().equals(client.getLocalPlayer().getWorldLocation()) ? 200 : 100)
.build();

View File

@@ -315,13 +315,13 @@ public class GroundMarkerPlugin extends Plugin
@Subscribe
public void onMenuOptionClicked(MenuOptionClicked event)
{
if (!event.getMenuOption().contains(MARK) && !event.getMenuOption().contains(UNMARK))
if (!event.getOption().contains(MARK) && !event.getOption().contains(UNMARK))
{
return;
}
int group = 1;
Matcher m = GROUP_MATCHER.matcher(event.getMenuOption());
Matcher m = GROUP_MATCHER.matcher(event.getOption());
if (m.matches())
{
group = Integer.parseInt(m.group(1));

View File

@@ -36,7 +36,9 @@ import javax.inject.Inject;
import net.runelite.api.Client;
import net.runelite.api.GameState;
import net.runelite.api.HashTable;
import net.runelite.api.Skill;
import net.runelite.api.WidgetNode;
import net.runelite.api.WorldType;
import net.runelite.api.events.ConfigChanged;
import net.runelite.api.events.GameStateChanged;
import net.runelite.api.events.WidgetLoaded;
@@ -120,6 +122,7 @@ public class HidePrayersPlugin extends Plugin
{
if (event.getGameState() == GameState.LOGGED_IN)
{
reallyHidePrayers();
hidePrayers();
}
}
@@ -506,9 +509,19 @@ public class HidePrayersPlugin extends Plugin
prayerWidgets.get(9).setHidden(false); // Rapid Heal
}
if (WorldType.isHighRiskWorld(client.getWorldType()) || client.getRealSkillLevel(Skill.PRAYER) <= 24)
{
prayerWidgets.get(10).setHidden(true); // Protect Item
}
else
{
prayerWidgets.get(10).setHidden(false); // Protect Item
}
switch (config.pvpprayers())
{
case DISABLED:
reallyHidePrayers();
break;
case PRAY1:
prayerWidgets.get(0).setHidden(false); // Thick Skin
@@ -521,30 +534,21 @@ public class HidePrayersPlugin extends Plugin
prayerWidgets.get(6).setHidden(false); // Super Human Strength
break;
case PRAY16:
prayerWidgets.get(3).setHidden(false); // Sharp Eye
prayerWidgets.get(4).setHidden(false); // Mystic Will
prayerWidgets.get(5).setHidden(false); // Rock Skin
prayerWidgets.get(6).setHidden(false); // Super Human Strength
prayerWidgets.get(7).setHidden(false); // Improved Reflexed
break;
case PRAY25:
prayerWidgets.get(3).setHidden(false); // Sharp Eye
prayerWidgets.get(4).setHidden(false); // Mystic Will
prayerWidgets.get(5).setHidden(false); // Rock Skin
prayerWidgets.get(6).setHidden(false); // Super Human Strength
prayerWidgets.get(7).setHidden(false); // Improved Reflexed
prayerWidgets.get(10).setHidden(false); // Protect Item
break;
case PRAY31:
prayerWidgets.get(7).setHidden(false); // Improved Reflexed
prayerWidgets.get(10).setHidden(false); // Protect Item
prayerWidgets.get(11).setHidden(false); // Hawk Eye
prayerWidgets.get(12).setHidden(false); // Mystic Lore
prayerWidgets.get(13).setHidden(false); // Steel Skin
prayerWidgets.get(14).setHidden(false); // Ultimate Strength
break;
case PRAY43:
prayerWidgets.get(10).setHidden(false); // Protect Item
prayerWidgets.get(11).setHidden(false); // Hawk Eye
prayerWidgets.get(12).setHidden(false); // Mystic Lore
prayerWidgets.get(13).setHidden(false); // Steel Skin
@@ -555,7 +559,6 @@ public class HidePrayersPlugin extends Plugin
prayerWidgets.get(18).setHidden(false); // Protect from Melee
break;
case PRAY44:
prayerWidgets.get(10).setHidden(false); // Protect Item
prayerWidgets.get(12).setHidden(false); // Mystic Lore
prayerWidgets.get(13).setHidden(false); // Steel Skin
prayerWidgets.get(14).setHidden(false); // Ultimate Strength
@@ -566,7 +569,6 @@ public class HidePrayersPlugin extends Plugin
prayerWidgets.get(19).setHidden(false); // Eagle Eye
break;
case PRAY45:
prayerWidgets.get(10).setHidden(false); // Protect Item
prayerWidgets.get(13).setHidden(false); // Steel Skin
prayerWidgets.get(14).setHidden(false); // Ultimate Strength
prayerWidgets.get(15).setHidden(false); // Incredible Reflexes
@@ -577,7 +579,6 @@ public class HidePrayersPlugin extends Plugin
prayerWidgets.get(20).setHidden(false); // Mystic Might
break;
case PRAY52:
prayerWidgets.get(10).setHidden(false); // Protect Item
prayerWidgets.get(13).setHidden(false); // Steel Skin
prayerWidgets.get(14).setHidden(false); // Ultimate Strength
prayerWidgets.get(15).setHidden(false); // Incredible Reflexes
@@ -590,7 +591,6 @@ public class HidePrayersPlugin extends Plugin
prayerWidgets.get(23).setHidden(false); // Smite
break;
case PRAY55:
prayerWidgets.get(10).setHidden(false); // Protect Item
prayerWidgets.get(13).setHidden(false); // Steel Skin
prayerWidgets.get(14).setHidden(false); // Ultimate Strength
prayerWidgets.get(15).setHidden(false); // Incredible Reflexes
@@ -604,7 +604,6 @@ public class HidePrayersPlugin extends Plugin
prayerWidgets.get(24).setHidden(false); // Preserve
break;
case PRAY60:
prayerWidgets.get(10).setHidden(false); // Protect Item
prayerWidgets.get(16).setHidden(false); // Protect from Magic
prayerWidgets.get(17).setHidden(false); // Protect from Range
prayerWidgets.get(18).setHidden(false); // Protect from Melee
@@ -616,7 +615,6 @@ public class HidePrayersPlugin extends Plugin
prayerWidgets.get(25).setHidden(false); // Chivalry
break;
case PRAY70:
prayerWidgets.get(10).setHidden(false); // Protect Item
prayerWidgets.get(16).setHidden(false); // Protect from Magic
prayerWidgets.get(17).setHidden(false); // Protect from Range
prayerWidgets.get(18).setHidden(false); // Protect from Melee
@@ -628,7 +626,6 @@ public class HidePrayersPlugin extends Plugin
prayerWidgets.get(26).setHidden(false); // Piety
break;
case PRAY74:
prayerWidgets.get(10).setHidden(false); // Protect Item
prayerWidgets.get(16).setHidden(false); // Protect from Magic
prayerWidgets.get(17).setHidden(false); // Protect from Range
prayerWidgets.get(18).setHidden(false); // Protect from Melee
@@ -640,7 +637,6 @@ public class HidePrayersPlugin extends Plugin
prayerWidgets.get(27).setHidden(false); // Rigour
break;
case PRAY77:
prayerWidgets.get(10).setHidden(false); // Protect Item
prayerWidgets.get(16).setHidden(false); // Protect from Magic
prayerWidgets.get(17).setHidden(false); // Protect from Range
prayerWidgets.get(18).setHidden(false); // Protect from Melee

View File

@@ -27,40 +27,63 @@ package net.runelite.client.plugins.inferno;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
import java.awt.Color;
@ConfigGroup("inferno")
public interface InfernoConfig extends Config
{
{
@ConfigItem(
position = 0,
keyName = "Nibbler Overlay",
name = "Nibbler Overlay",
description = "Shows if there are any Nibblers left"
position = 0,
keyName = "Nibbler Overlay",
name = "Nibbler Overlay",
description = "Shows if there are any Nibblers left"
)
default boolean displayNibblerOverlay()
{
return false;
}
{
return false;
}
@ConfigItem(
position = 1,
keyName = "Prayer Helper",
name = "Prayer Helper",
description = "Tells you what to flick in how many ticks"
position = 1,
keyName = "Prayer Helper",
name = "Prayer Helper",
description = "Tells you what to flick in how many ticks"
)
default boolean showPrayerHelp()
{
return false;
}
{
return false;
}
@ConfigItem(
position = 2,
keyName = "Wave Display",
name = "Wave display",
description = "Shows monsters that will spawn on the selected wave(s)."
position = 2,
keyName = "waveDisplay",
name = "Wave display",
description = "Shows monsters that will spawn on the selected wave(s)."
)
default InfernoWaveDisplayMode waveDisplay()
{
return InfernoWaveDisplayMode.BOTH;
}
}
{
return InfernoWaveDisplayMode.BOTH;
}
@ConfigItem(
position = 3,
keyName = "getWaveOverlayHeaderColor",
name = "Wave Header",
description = "Color for Wave Header"
)
default Color getWaveOverlayHeaderColor()
{
return Color.ORANGE;
}
@ConfigItem(
position = 4,
keyName = "getWaveTextColor",
name = "Wave Text Color",
description = "Color for Wave Texts"
)
default Color getWaveTextColor()
{
return Color.WHITE;
}
}

View File

@@ -1,427 +1,477 @@
/*
* Copyright (c) 2019, Jacky <liangj97@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.client.plugins.inferno;
import com.google.inject.Provides;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Nullable;
import javax.inject.Inject;
import lombok.AccessLevel;
import lombok.Getter;
import net.runelite.api.ChatMessageType;
import net.runelite.api.Client;
import net.runelite.api.GameState;
import net.runelite.api.HeadIcon;
import net.runelite.api.NPC;
import net.runelite.api.NpcID;
import net.runelite.api.events.AnimationChanged;
import net.runelite.api.events.ChatMessage;
import net.runelite.api.events.GameStateChanged;
import net.runelite.api.events.GameTick;
import net.runelite.api.events.NpcDespawned;
import net.runelite.api.events.NpcSpawned;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.Subscribe;
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 org.apache.commons.lang3.ArrayUtils;
@PluginDescriptor(
name = "Inferno",
description = "Inferno helper",
tags = {"combat", "overlay", "pve", "pvm"},
type = PluginType.PVM
)
public class InfernoPlugin extends Plugin
{
private static final Pattern WAVE_PATTERN = Pattern.compile(".*Wave: (\\d+).*");
private static final int MAX_MONSTERS_OF_TYPE_PER_WAVE = 6;
private static final int INFERNO_REGION = 9043;
static final int MAX_WAVE = 69;
@Inject
private Client client;
@Inject
private OverlayManager overlayManager;
@Inject
private InfernoOverlay infernoOverlay;
@Inject
private InfernoWaveOverlay waveOverlay;
@Inject
private InfernoJadOverlay jadOverlay;
@Inject
private InfernoInfobox infernoInfobox;
@Inject
private InfernoNibblerOverlay nibblerOverlay;
@Inject
private InfernoConfig config;
@Getter
static final List<EnumMap<InfernoWaveMonster, Integer>> WAVES = new ArrayList<>();
@Getter
private int currentWave = -1;
@Getter
private Map<NPC, InfernoNPC> monsters;
@Getter
private Map<Integer, ArrayList<InfernoNPC>> monsterCurrentAttackMap;
@Getter
private List<NPC> nibblers;
@Getter
private InfernoNPC[] priorityNPC;
@Getter(AccessLevel.PACKAGE)
@Nullable
private InfernoJadAttack attack;
private NPC jad;
static
{
final InfernoWaveMonster[] waveMonsters = InfernoWaveMonster.values();
// Add wave 1, future waves are derived from its contents
final EnumMap<InfernoWaveMonster, Integer> waveOne = new EnumMap<>(InfernoWaveMonster.class);
waveOne.put(waveMonsters[0], 1);
WAVES.add(waveOne);
for (int wave = 1; wave < MAX_WAVE; wave++)
{
final EnumMap<InfernoWaveMonster, Integer> prevWave = WAVES.get(wave - 1).clone();
int maxMonsterOrdinal = -1;
for (int i = 0; i < waveMonsters.length; i++)
{
final int ordinalMonsterQuantity = prevWave.getOrDefault(waveMonsters[i], 0);
if (ordinalMonsterQuantity == MAX_MONSTERS_OF_TYPE_PER_WAVE)
{
maxMonsterOrdinal = i;
break;
}
}
if (maxMonsterOrdinal >= 0)
{
prevWave.remove(waveMonsters[maxMonsterOrdinal]);
}
final int addedMonsterOrdinal = maxMonsterOrdinal >= 0 ? maxMonsterOrdinal + 1 : 0;
final InfernoWaveMonster addedMonster = waveMonsters[addedMonsterOrdinal];
final int addedMonsterQuantity = prevWave.getOrDefault(addedMonster, 0);
prevWave.put(addedMonster, addedMonsterQuantity + 1);
WAVES.add(prevWave);
}
}
@Provides
InfernoConfig provideConfig(ConfigManager configManager)
{
return configManager.getConfig(InfernoConfig.class);
}
@Override
protected void startUp() throws Exception
{
overlayManager.add(infernoOverlay);
overlayManager.add(infernoInfobox);
overlayManager.add(nibblerOverlay);
overlayManager.add(waveOverlay);
overlayManager.add(jadOverlay);
monsters = new HashMap<>();
monsterCurrentAttackMap = new HashMap<>(6);
for (int i = 1; i <= 6; i++)
{
monsterCurrentAttackMap.put(i, new ArrayList<>());
}
nibblers = new ArrayList<>();
priorityNPC = new InfernoNPC[4];
}
@Override
protected void shutDown() throws Exception
{
overlayManager.remove(infernoInfobox);
overlayManager.remove(infernoOverlay);
overlayManager.remove(nibblerOverlay);
overlayManager.remove(waveOverlay);
overlayManager.remove(jadOverlay);
jad = null;
attack = null;
}
@Subscribe
public void onNpcSpawned(NpcSpawned event)
{
if (client.getMapRegions()[0] != 9043) return;
NPC npc = event.getNpc();
if (isValidInfernoMob(npc))
{
monsters.put(npc, new InfernoNPC(npc));
System.out.println(monsters.size());
}
if (npc.getId() == NpcID.JALNIB)
{
nibblers.add(npc);
}
final int id = event.getNpc().getId();
if (id == NpcID.JALTOKJAD || id == NpcID.JALTOKJAD_7704)
{
jad = event.getNpc();
}
}
@Subscribe
public void onNpcDespawned(NpcDespawned event)
{
if (client.getMapRegions()[0] != 9043) return;
NPC npc = event.getNpc();
if (monsters.containsKey(npc))
{
monsters.remove(npc);
System.out.println(monsters.size());
}
if (npc.getId() == NpcID.JALNIB)
{
nibblers.remove(npc);
}
if (jad == event.getNpc())
{
jad = null;
attack = null;
}
}
@Subscribe
public void onGameStateChanged(GameStateChanged event)
{
if (event.getGameState() != GameState.LOGGED_IN)
{
return;
}
if (!inInferno())
{
currentWave = -1;
}
}
@Subscribe
public void onChatMessage(ChatMessage event)
{
final Matcher waveMatcher = WAVE_PATTERN.matcher(event.getMessage());
if (event.getType() != ChatMessageType.GAMEMESSAGE
|| !inInferno()
|| !waveMatcher.matches())
{
return;
}
currentWave = Integer.parseInt(waveMatcher.group(1));
}
@Subscribe
public void onGameTick(GameTick event)
{
if (client.getMapRegions()[0] != 9043) return;
clearMapAndPriority();
for (InfernoNPC monster : monsters.values())
{
calculateDistanceToPlayer(monster);
NPC npc = monster.getNpc();
// if they are not attacking but are still attacking
if (monster.isAttacking())
{
monster.setTicksTillAttack(monster.getTicksTillAttack() - 1);
// sets the blobs attack style
if (monster.getName().equals("blob") && monster.getTicksTillAttack() == 3 && monster.getDistanceToPlayer() <= 15)
{
if (client.getLocalPlayer().getOverheadIcon() == null)
{
monster.setAttackstyle(InfernoNPC.Attackstyle.RANDOM);
}
else if (client.getLocalPlayer().getOverheadIcon().equals(HeadIcon.MAGIC))
{
monster.setAttackstyle(InfernoNPC.Attackstyle.RANGE);
}
else if (client.getLocalPlayer().getOverheadIcon().equals(HeadIcon.RANGED))
{
monster.setAttackstyle(InfernoNPC.Attackstyle.MAGE);
}
}
// we know the monster is not attacking because it should have attacked and is idling
if (monster.getTicksTillAttack() == 0)
{
if (npc.getAnimation() == -1)
{
monster.setAttacking(false);
}
else
{
// want to reset the monsters attack back to attacking
monster.attacked();
}
}
}
else
{
// they've just attacked
if (npc.getAnimation() == monster.getAttackAnimation() || npc.getAnimation() == 7581) // special case for blob
{
monster.attacked();
}
}
if (monster.getTicksTillAttack() >= 1)
{
monsterCurrentAttackMap.get(monster.getTicksTillAttack()).add(monster);
}
}
calculatePriorityNPC();
}
@Subscribe
public void onAnimationChanged(final AnimationChanged event)
{
if (event.getActor() != jad)
{
return;
}
if (jad.getAnimation() == InfernoJadAttack.MAGIC.getAnimation())
{
attack = InfernoJadAttack.MAGIC;
}
else if (jad.getAnimation() == InfernoJadAttack.RANGE.getAnimation())
{
attack = InfernoJadAttack.RANGE;
}
}
private void calculatePriorityNPC()
{
for (int i = 0; i < priorityNPC.length; i++)
{
ArrayList<InfernoNPC> monsters = monsterCurrentAttackMap.get(i + 1);
if ( monsters.size() == 0) continue;
int priority = monsters.get(0).getPriority();
InfernoNPC infernoNPC = monsters.get(0);
for (InfernoNPC npc : monsters)
{
if (npc.getPriority() < priority)
{
priority = npc.getPriority();
infernoNPC = npc;
}
}
priorityNPC[i] = infernoNPC;
System.out.println("i: " + i + " " + infernoNPC.getName());
}
}
// TODO: blob calculator
private void calculateDistanceToPlayer(InfernoNPC monster)
{
monster.setDistanceToPlayer(client.getLocalPlayer().getWorldLocation().distanceTo(monster.getNpc().getWorldArea()));
}
private void clearMapAndPriority()
{
for (List<InfernoNPC> l : monsterCurrentAttackMap.values())
{
l.clear();
}
for (int i = 0; i < priorityNPC.length; i++)
{
priorityNPC[i] = null;
}
}
public boolean isValidInfernoMob(NPC npc)
{
// we only want the bat, blob, melee, ranger and mager
if (npc.getId() == NpcID.JALMEJRAH ||
npc.getId() == NpcID.JALAK ||
npc.getId() == NpcID.JALIMKOT ||
npc.getId() == NpcID.JALXIL ||
npc.getId() == NpcID.JALZEK) return true;
return false;
}
boolean inInferno()
{
return ArrayUtils.contains(client.getMapRegions(), INFERNO_REGION);
}
static String formatMonsterQuantity(final InfernoWaveMonster monster, final int quantity)
{
return String.format("%dx %s", quantity, monster);
}
}
/*
* Copyright (c) 2019, Jacky <liangj97@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.client.plugins.inferno;
import com.google.inject.Provides;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;
import javax.inject.Inject;
import lombok.AccessLevel;
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.GameState;
import net.runelite.api.HeadIcon;
import net.runelite.api.NPC;
import net.runelite.api.NpcID;
import net.runelite.api.events.AnimationChanged;
import net.runelite.api.events.ChatMessage;
import net.runelite.api.events.ConfigChanged;
import net.runelite.api.events.GameStateChanged;
import net.runelite.api.events.GameTick;
import net.runelite.api.events.NpcDespawned;
import net.runelite.api.events.NpcSpawned;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.Subscribe;
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 org.apache.commons.lang3.ArrayUtils;
@PluginDescriptor(
name = "Inferno",
description = "Inferno helper",
tags = {"combat", "overlay", "pve", "pvm"},
type = PluginType.PVM
)
@Slf4j
public class InfernoPlugin extends Plugin
{
private static final int INFERNO_REGION = 9043;
@Inject
private Client client;
@Inject
private OverlayManager overlayManager;
@Inject
private InfernoOverlay infernoOverlay;
@Inject
private InfernoWaveOverlay waveOverlay;
@Inject
private InfernoJadOverlay jadOverlay;
@Inject
private InfernoInfobox infernoInfobox;
@Inject
private InfernoNibblerOverlay nibblerOverlay;
@Inject
private InfernoConfig config;
@Getter
private int currentWave = -1;
@Getter
private Map<NPC, InfernoNPC> monsters;
@Getter
private Map<Integer, ArrayList<InfernoNPC>> monsterCurrentAttackMap;
@Getter
private List<NPC> nibblers;
@Getter
private InfernoNPC[] priorityNPC;
@Getter(AccessLevel.PACKAGE)
@Nullable
private InfernoJadAttack attack;
private NPC jad;
@Getter(AccessLevel.PACKAGE)
private int currentWaveNumber;
private List<Actor> waveMonsters;
public InfernoPlugin()
{
waveMonsters = new ArrayList<>();
}
@Provides
InfernoConfig provideConfig(ConfigManager configManager)
{
return configManager.getConfig(InfernoConfig.class);
}
@Override
protected void startUp() throws Exception
{
waveOverlay.setDisplayMode(config.waveDisplay());
if (isInInferno())
{
overlayManager.add(infernoOverlay);
overlayManager.add(infernoInfobox);
overlayManager.add(nibblerOverlay);
if (config.waveDisplay() != InfernoWaveDisplayMode.NONE)
{
overlayManager.add(waveOverlay);
}
overlayManager.add(jadOverlay);
}
waveOverlay.setWaveHeaderColor(config.getWaveOverlayHeaderColor());
waveOverlay.setWaveTextColor(config.getWaveTextColor());
monsters = new HashMap<>();
monsterCurrentAttackMap = new HashMap<>(6);
for (int i = 1; i <= 6; i++)
{
monsterCurrentAttackMap.put(i, new ArrayList<>());
}
nibblers = new ArrayList<>();
priorityNPC = new InfernoNPC[4];
}
@Override
protected void shutDown() throws Exception
{
overlayManager.remove(infernoInfobox);
overlayManager.remove(infernoOverlay);
overlayManager.remove(nibblerOverlay);
overlayManager.remove(waveOverlay);
overlayManager.remove(jadOverlay);
jad = null;
attack = null;
monsters = null;
currentWaveNumber = -1;
}
@Subscribe
private void onConfigChanged(ConfigChanged event)
{
if (!"inferno".equals(event.getGroup()))
{
return;
}
if (event.getKey().endsWith("color"))
{
waveOverlay.setWaveHeaderColor(config.getWaveOverlayHeaderColor());
waveOverlay.setWaveTextColor(config.getWaveTextColor());
}
else if ("waveDisplay".equals(event.getKey()))
{
overlayManager.remove(waveOverlay);
waveOverlay.setDisplayMode(config.waveDisplay());
if (isInInferno() && config.waveDisplay() != InfernoWaveDisplayMode.NONE)
{
overlayManager.add(waveOverlay);
}
}
}
@Subscribe
public void onNpcSpawned(NpcSpawned event)
{
if (client.getMapRegions()[0] != 9043) return;
NPC npc = event.getNpc();
if (isValidInfernoMob(npc))
{
monsters.put(npc, new InfernoNPC(npc));
log.debug(String.valueOf(monsters.size()));
}
if (npc.getId() == NpcID.JALNIB)
{
nibblers.add(npc);
}
final int id = event.getNpc().getId();
if (id == NpcID.JALTOKJAD || id == NpcID.JALTOKJAD_7704)
{
jad = event.getNpc();
}
final Actor actor = event.getActor();
if (actor != null)
{
waveMonsters.add(actor);
}
}
@Subscribe
public void onNpcDespawned(NpcDespawned event)
{
if (client.getMapRegions()[0] != 9043) return;
NPC npc = event.getNpc();
if (monsters.containsKey(npc))
{
monsters.remove(npc);
log.debug(String.valueOf(monsters.size()));
}
if (npc.getId() == NpcID.JALNIB)
{
nibblers.remove(npc);
}
if (jad == event.getNpc())
{
jad = null;
attack = null;
}
final Actor actor = event.getActor();
if (actor != null)
{
waveMonsters.remove(actor);
}
}
@Subscribe
public void onGameStateChanged(GameStateChanged event)
{
if (event.getGameState() != GameState.LOGGED_IN)
{
return;
}
if (!isInInferno())
{
currentWaveNumber = -1;
overlayManager.remove(infernoInfobox);
overlayManager.remove(infernoOverlay);
overlayManager.remove(nibblerOverlay);
overlayManager.remove(waveOverlay);
overlayManager.remove(jadOverlay);
}
else if (currentWaveNumber == -1)
{
currentWaveNumber = 1;
overlayManager.add(infernoOverlay);
overlayManager.add(infernoInfobox);
overlayManager.add(nibblerOverlay);
if (config.waveDisplay() != InfernoWaveDisplayMode.NONE)
{
overlayManager.add(waveOverlay);
}
overlayManager.add(jadOverlay);
}
}
@Subscribe
public void onChatMessage(ChatMessage event)
{
if (!isInInferno() || event.getType() != ChatMessageType.GAMEMESSAGE)
{
return;
}
String message = event.getMessage();
if (event.getMessage().contains("Wave:"))
{
message = message.substring(message.indexOf(": ") + 2);
currentWaveNumber = Integer.parseInt(message.substring(0, message.indexOf("<")));
}
}
@Subscribe
public void onGameTick(GameTick event)
{
if (client.getMapRegions()[0] != 9043) return;
clearMapAndPriority();
for (InfernoNPC monster : monsters.values())
{
calculateDistanceToPlayer(monster);
NPC npc = monster.getNpc();
// if they are not attacking but are still attacking
if (monster.isAttacking())
{
monster.setTicksTillAttack(monster.getTicksTillAttack() - 1);
// sets the blobs attack style
if (monster.getName().equals("blob") && monster.getTicksTillAttack() == 3 && monster.getDistanceToPlayer() <= 15)
{
if (client.getLocalPlayer().getOverheadIcon() == null)
{
monster.setAttackstyle(InfernoNPC.Attackstyle.RANDOM);
}
else if (client.getLocalPlayer().getOverheadIcon().equals(HeadIcon.MAGIC))
{
monster.setAttackstyle(InfernoNPC.Attackstyle.RANGE);
}
else if (client.getLocalPlayer().getOverheadIcon().equals(HeadIcon.RANGED))
{
monster.setAttackstyle(InfernoNPC.Attackstyle.MAGE);
}
}
// we know the monster is not attacking because it should have attacked and is idling
if (monster.getTicksTillAttack() == 0)
{
if (npc.getAnimation() == -1)
{
monster.setAttacking(false);
}
else
{
// want to reset the monsters attack back to attacking
monster.attacked();
}
}
}
else
{
// they've just attacked
if (npc.getAnimation() == monster.getAttackAnimation() || npc.getAnimation() == 7581) // special case for blob
{
monster.attacked();
}
}
if (monster.getTicksTillAttack() >= 1)
{
monsterCurrentAttackMap.get(monster.getTicksTillAttack()).add(monster);
}
}
calculatePriorityNPC();
}
@Subscribe
public void onAnimationChanged(final AnimationChanged event)
{
if (event.getActor() != jad)
{
return;
}
if (jad.getAnimation() == InfernoJadAttack.MAGIC.getAnimation())
{
attack = InfernoJadAttack.MAGIC;
}
else if (jad.getAnimation() == InfernoJadAttack.RANGE.getAnimation())
{
attack = InfernoJadAttack.RANGE;
}
}
private void calculatePriorityNPC()
{
for (int i = 0; i < priorityNPC.length; i++)
{
ArrayList<InfernoNPC> monsters = monsterCurrentAttackMap.get(i + 1);
if (monsters.size() == 0) continue;
int priority = monsters.get(0).getPriority();
InfernoNPC infernoNPC = monsters.get(0);
for (InfernoNPC npc : monsters)
{
if (npc.getPriority() < priority)
{
priority = npc.getPriority();
infernoNPC = npc;
}
}
priorityNPC[i] = infernoNPC;
log.debug("i: " + i + " " + infernoNPC.getName());
}
}
// TODO: blob calculator
private void calculateDistanceToPlayer(InfernoNPC monster)
{
monster.setDistanceToPlayer(client.getLocalPlayer().getWorldLocation().distanceTo(monster.getNpc().getWorldArea()));
}
private void clearMapAndPriority()
{
for (List<InfernoNPC> l : monsterCurrentAttackMap.values())
{
l.clear();
}
for (int i = 0; i < priorityNPC.length; i++)
{
priorityNPC[i] = null;
}
}
private boolean isValidInfernoMob(NPC npc)
{
// we only want the bat, blob, melee, ranger and mager
return npc.getId() == NpcID.JALMEJRAH ||
npc.getId() == NpcID.JALAK ||
npc.getId() == NpcID.JALIMKOT ||
npc.getId() == NpcID.JALXIL ||
npc.getId() == NpcID.JALZEK;
}
private boolean isInInferno()
{
return ArrayUtils.contains(client.getMapRegions(), INFERNO_REGION);
}
boolean isNotFinalWave()
{
return currentWaveNumber <= 68;
}
List<Actor> getWaveMonsters()
{
return waveMonsters;
}
int getNextWaveNumber()
{
return currentWaveNumber == -1 || currentWaveNumber == 69 ? -1 : currentWaveNumber + 1;
}
}

View File

@@ -31,7 +31,8 @@ public enum InfernoWaveDisplayMode
{
CURRENT("Current wave"),
NEXT("Next wave"),
BOTH("Both");
BOTH("Both"),
NONE("None");
private final String name;

View File

@@ -0,0 +1,168 @@
/*
* Copyright (c) 2019, Kyleeld <https://github.com/kyleeld>
* Copyright (c) 2019, RuneLitePlus <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.inferno;
import com.google.common.collect.ImmutableMap;
import java.awt.Color;
import lombok.Getter;
import net.runelite.client.ui.overlay.components.PanelComponent;
import net.runelite.client.ui.overlay.components.TitleComponent;
class InfernoWaveMappings
{
@Getter
private static final ImmutableMap<Integer, int[]> waveMapping;
@Getter
private static final ImmutableMap<Integer, String> npcNameMapping;
static
{
ImmutableMap.Builder<Integer, int[]> waveMapBuilder = new ImmutableMap.Builder<>();
waveMapBuilder.put(1, new int[]{32, 32, 32, 85});
waveMapBuilder.put(2, new int[]{32, 32, 32, 85, 85});
waveMapBuilder.put(3, new int[]{32, 32, 32, 32, 32, 32});
waveMapBuilder.put(4, new int[]{32, 32, 32, 165});
waveMapBuilder.put(5, new int[]{32, 32, 32, 85, 165});
waveMapBuilder.put(6, new int[]{32, 32, 32, 85, 85, 165});
waveMapBuilder.put(7, new int[]{32, 32, 32, 165, 165});
waveMapBuilder.put(8, new int[]{32, 32, 32, 32, 32, 32});
waveMapBuilder.put(9, new int[]{32, 32, 32, 240});
waveMapBuilder.put(10, new int[]{32, 32, 32, 85, 240});
waveMapBuilder.put(11, new int[]{32, 32, 32, 85, 85, 240});
waveMapBuilder.put(12, new int[]{32, 32, 32, 165, 240});
waveMapBuilder.put(13, new int[]{32, 32, 32, 85, 165, 240});
waveMapBuilder.put(14, new int[]{32, 32, 32, 85, 85, 165, 240});
waveMapBuilder.put(15, new int[]{32, 32, 32, 165, 165, 240});
waveMapBuilder.put(16, new int[]{32, 32, 32, 240, 240});
waveMapBuilder.put(17, new int[]{32, 32, 32, 32, 32, 32});
waveMapBuilder.put(18, new int[]{32, 32, 32, 370});
waveMapBuilder.put(19, new int[]{32, 32, 32, 85, 370});
waveMapBuilder.put(20, new int[]{32, 32, 32, 85, 85, 370});
waveMapBuilder.put(21, new int[]{32, 32, 32, 165, 370});
waveMapBuilder.put(22, new int[]{32, 32, 32, 85, 165, 370});
waveMapBuilder.put(23, new int[]{32, 32, 32, 85, 85, 165, 370});
waveMapBuilder.put(24, new int[]{32, 32, 32, 165, 165, 370});
waveMapBuilder.put(25, new int[]{32, 32, 32, 240, 370});
waveMapBuilder.put(26, new int[]{32, 32, 32, 85, 240, 370});
waveMapBuilder.put(27, new int[]{32, 32, 32, 85, 85, 240, 370});
waveMapBuilder.put(28, new int[]{32, 32, 32, 165, 240, 370});
waveMapBuilder.put(29, new int[]{32, 32, 32, 85, 165, 240, 370});
waveMapBuilder.put(30, new int[]{32, 32, 32, 85, 85, 165, 240, 370});
waveMapBuilder.put(31, new int[]{32, 32, 32, 165, 165, 240, 370});
waveMapBuilder.put(32, new int[]{32, 32, 32, 240, 240, 370});
waveMapBuilder.put(33, new int[]{32, 32, 32, 370, 370});
waveMapBuilder.put(34, new int[]{32, 32, 32, 32, 32, 32});
waveMapBuilder.put(35, new int[]{32, 32, 32, 490});
waveMapBuilder.put(36, new int[]{32, 32, 32, 85, 490});
waveMapBuilder.put(37, new int[]{32, 32, 32, 85, 85, 490});
waveMapBuilder.put(38, new int[]{32, 32, 32, 165, 490});
waveMapBuilder.put(39, new int[]{32, 32, 32, 85, 165, 490});
waveMapBuilder.put(40, new int[]{32, 32, 32, 85, 85, 165, 490});
waveMapBuilder.put(41, new int[]{32, 32, 32, 165, 165, 490});
waveMapBuilder.put(42, new int[]{32, 32, 32, 240, 490});
waveMapBuilder.put(43, new int[]{32, 32, 32, 85, 240, 490});
waveMapBuilder.put(44, new int[]{32, 32, 32, 85, 85, 240, 490});
waveMapBuilder.put(45, new int[]{32, 32, 32, 165, 240, 490 });
waveMapBuilder.put(46, new int[]{32, 32, 32, 85, 165, 240, 490});
waveMapBuilder.put(47, new int[]{32, 32, 32, 85, 85, 165, 240, 490});
waveMapBuilder.put(48, new int[]{32, 32, 32, 165, 165, 240, 490});
waveMapBuilder.put(49, new int[]{32, 32, 32, 240, 240, 490});
waveMapBuilder.put(50, new int[]{32, 32, 32, 370, 490});
waveMapBuilder.put(51, new int[]{32, 32, 32, 85, 370, 490});
waveMapBuilder.put(52, new int[]{32, 32, 32, 85, 85, 370, 490});
waveMapBuilder.put(53, new int[]{32, 32, 32, 165, 370, 490});
waveMapBuilder.put(54, new int[]{32, 32, 32, 85, 165, 370, 490});
waveMapBuilder.put(55, new int[]{32, 32, 32, 85, 85, 165, 370, 490});
waveMapBuilder.put(56, new int[]{32, 32, 32, 165, 165, 370, 490});
waveMapBuilder.put(57, new int[]{32, 32, 32, 240, 370, 490});
waveMapBuilder.put(58, new int[]{32, 32, 32, 85, 240, 370, 490});
waveMapBuilder.put(59, new int[]{32, 32, 32, 85, 85, 240, 370, 490});
waveMapBuilder.put(60, new int[]{32, 32, 32, 165, 240, 370, 490});
waveMapBuilder.put(61, new int[]{32, 32, 32, 85, 165, 240, 370, 490});
waveMapBuilder.put(62, new int[]{32, 32, 32, 85, 85, 165, 240, 370, 490});
waveMapBuilder.put(63, new int[]{32, 32, 32, 165, 165, 240, 370, 490});
waveMapBuilder.put(64, new int[]{32, 32, 32, 85, 240, 240, 370, 490});
waveMapBuilder.put(65, new int[]{32, 32, 32, 85, 370, 370, 490});
waveMapBuilder.put(66, new int[]{32, 32, 32, 85, 490, 490});
waveMapBuilder.put(67, new int[]{900});
waveMapBuilder.put(68, new int[]{900, 900, 900});
waveMapBuilder.put(69, new int[]{1400});
waveMapping = waveMapBuilder.build();
ImmutableMap.Builder<Integer, String> nameMapBuilder = new ImmutableMap.Builder<>();
nameMapBuilder.put(32, "Jal-Nib - Level 32");
nameMapBuilder.put(85, "Jal-MejRah - Level 85");
nameMapBuilder.put(165, "Jal-Ak - Level 165");
nameMapBuilder.put(240, "Jal-ImKot - Level 240");
nameMapBuilder.put(370, "Jal-Xil - Level 370");
nameMapBuilder.put(490, "Jal-Zek - Level 490");
nameMapBuilder.put(900, "JalTok-Jad - Level 900");
nameMapBuilder.put(1400, "TzKal-Zuk - Level 1400");
npcNameMapping = nameMapBuilder.build();
}
static void addWaveComponent(PanelComponent panelComponent, String header, int wave, Color titleColor, Color color)
{
int[] monsters = waveMapping.get(wave);
if (monsters == null)
{
return;
}
panelComponent.getChildren()
.add(TitleComponent.builder()
.text(header)
.color(titleColor)
.build()
);
for (int i = 0; i < monsters.length; i++)
{
int monsterType = monsters[i];
int count = 1;
for (; i < monsters.length - 1 && monsters[i + 1] == monsterType; i++)
{
count++;
}
TitleComponent.TitleComponentBuilder builder = TitleComponent.builder();
builder.text(count + "x " + npcNameMapping.get(monsterType));
builder.color(color);
panelComponent.getChildren().add(builder.build());
}
}
}

View File

@@ -1,127 +1,69 @@
/*
* Copyright (c) 2018, Jordan Atwood <jordan.atwood423@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.client.plugins.inferno;
import java.awt.Color;
import java.awt.Dimension;
import com.google.inject.Inject;
import lombok.Setter;
import static net.runelite.client.plugins.inferno.InfernoWaveMappings.addWaveComponent;
import java.awt.Graphics2D;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import net.runelite.client.ui.ColorScheme;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayPriority;
import net.runelite.client.ui.overlay.OverlayPosition;
import java.awt.Dimension;
import net.runelite.client.ui.overlay.components.PanelComponent;
import net.runelite.client.ui.overlay.components.TitleComponent;
import net.runelite.client.ui.overlay.components.table.TableComponent;
import net.runelite.client.ui.overlay.Overlay;
class InfernoWaveOverlay extends Overlay
{
private static final Color HEADER_COLOR = ColorScheme.BRAND_ORANGE;
private final InfernoConfig config;
public class InfernoWaveOverlay extends Overlay
{
private final InfernoPlugin plugin;
private final PanelComponent panelComponent;
private final PanelComponent panelComponent = new PanelComponent();
@Setter
private Color waveHeaderColor;
@Setter
private Color waveTextColor;
@Setter
private InfernoWaveDisplayMode displayMode;
@Inject
private InfernoWaveOverlay(InfernoConfig config, InfernoPlugin plugin)
InfernoWaveOverlay(final InfernoPlugin plugin)
{
setPosition(OverlayPosition.TOP_RIGHT);
this.config = config;
this.panelComponent = new PanelComponent();
this.setPosition(OverlayPosition.TOP_RIGHT);
this.setPriority(OverlayPriority.HIGH);
this.plugin = plugin;
panelComponent.setPreferredSize(new Dimension(160, 0));
}
@Override
public Dimension render(Graphics2D graphics)
public Dimension render(final Graphics2D graphics)
{
if (!plugin.inInferno()
|| plugin.getCurrentWave() < 0)
{
return null;
}
panelComponent.getChildren().clear();
final int currentWave = plugin.getCurrentWave();
final int waveIndex = currentWave - 1;
if (config.waveDisplay() == InfernoWaveDisplayMode.CURRENT
|| config.waveDisplay() == InfernoWaveDisplayMode.BOTH)
if (displayMode == InfernoWaveDisplayMode.CURRENT ||
displayMode == InfernoWaveDisplayMode.BOTH)
{
final Map<InfernoWaveMonster, Integer> waveContents = InfernoPlugin.getWAVES().get(waveIndex);
addWaveInfo("Wave " + plugin.getCurrentWave(), waveContents);
addWaveComponent(
panelComponent,
"Current Wave (Wave " + plugin.getCurrentWaveNumber() + ")",
plugin.getCurrentWaveNumber(),
waveHeaderColor,
waveTextColor
);
}
if ((config.waveDisplay() == InfernoWaveDisplayMode.NEXT
|| config.waveDisplay() == InfernoWaveDisplayMode.BOTH)
&& currentWave != InfernoPlugin.MAX_WAVE)
if (displayMode == InfernoWaveDisplayMode.NEXT ||
displayMode == InfernoWaveDisplayMode.BOTH)
{
final Map<InfernoWaveMonster, Integer> waveContents = InfernoPlugin.getWAVES().get(waveIndex + 1);
addWaveInfo("Next wave", waveContents);
addWaveComponent(
panelComponent,
"Next Wave (Wave " + plugin.getNextWaveNumber() + ")",
plugin.getNextWaveNumber(),
waveHeaderColor,
waveTextColor
);
}
return panelComponent.render(graphics);
}
private void addWaveInfo(final String headerText, final Map<InfernoWaveMonster, Integer> waveContents)
{
panelComponent.getChildren().add(TitleComponent.builder()
.text(headerText)
.color(HEADER_COLOR)
.build());
TableComponent tableComponent = new TableComponent();
for (String line : buildWaveLines(waveContents))
{
tableComponent.addRow(line);
}
panelComponent.getChildren().add(tableComponent);
}
private static Collection<String> buildWaveLines(final Map<InfernoWaveMonster, Integer> wave)
{
final List<Map.Entry<InfernoWaveMonster, Integer>> monsters = new ArrayList<>(wave.entrySet());
monsters.sort(Map.Entry.comparingByKey());
final List<String> outputLines = new ArrayList<>();
for (Map.Entry<InfernoWaveMonster, Integer> monsterEntry : monsters)
{
final InfernoWaveMonster monster = monsterEntry.getKey();
final int quantity = monsterEntry.getValue();
final String line = InfernoPlugin.formatMonsterQuantity(monster, quantity);
outputLines.add(line);
}
return outputLines;
}
}

View File

@@ -0,0 +1,87 @@
/*
* Copyright (c) 2019 Hydrox6 <ikada@protonmail.ch>
* 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.interfacestyles;
import com.google.common.collect.ImmutableMap;
import java.util.Map;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import static net.runelite.api.SpriteID.*;
import net.runelite.client.game.SpriteOverride;
@RequiredArgsConstructor
enum HealthbarOverride implements SpriteOverride
{
BACK_30PX(HEALTHBAR_DEFAULT_BACK_30PX, "back_30px.png"),
BACK_50PX(HEALTHBAR_DEFAULT_BACK_50PX, "back_30px.png"),
BACK_60PX(HEALTHBAR_DEFAULT_BACK_60PX, "back_30px.png"),
BACK_80PX(HEALTHBAR_DEFAULT_BACK_80PX, "back_90px.png"),
BACK_100PX(HEALTHBAR_DEFAULT_BACK_100PX, "back_90px.png"),
BACK_120PX(HEALTHBAR_DEFAULT_BACK_120PX, "back_90px.png"),
BACK_140PX(HEALTHBAR_DEFAULT_BACK_140PX, "back_90px.png"),
BACK_160PX(HEALTHBAR_DEFAULT_BACK_160PX, "back_90px.png"),
FRONT_30PX(HEALTHBAR_DEFAULT_FRONT_30PX, "front_30px.png"),
FRONT_50PX(HEALTHBAR_DEFAULT_FRONT_50PX, "front_30px.png"),
FRONT_60PX(HEALTHBAR_DEFAULT_FRONT_60PX, "front_30px.png"),
FRONT_80PX(HEALTHBAR_DEFAULT_FRONT_80PX, "front_90px.png"),
FRONT_100PX(HEALTHBAR_DEFAULT_FRONT_100PX, "front_90px.png"),
FRONT_120PX(HEALTHBAR_DEFAULT_FRONT_120PX, "front_90px.png"),
FRONT_140PX(HEALTHBAR_DEFAULT_FRONT_140PX, "front_90px.png"),
FRONT_160PX(HEALTHBAR_DEFAULT_FRONT_160PX, "front_90px.png");
@Getter
private final int spriteId;
private final String fileName;
@Getter
private int padding = 1;
private static final Map<Integer, HealthbarOverride> MAP;
static
{
ImmutableMap.Builder<Integer, HealthbarOverride> builder = new ImmutableMap.Builder<>();
for (HealthbarOverride override : values())
{
builder.put(override.spriteId, override);
}
MAP = builder.build();
}
static HealthbarOverride get(int spriteID)
{
return MAP.get(spriteID);
}
@Override
public String getFileName()
{
return Skin.AROUND_2010.toString() + "/healthbar/" + this.fileName;
}
}

View File

@@ -32,8 +32,6 @@ import javax.inject.Inject;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Client;
import net.runelite.api.HealthBar;
import net.runelite.api.HealthBarOverride;
import net.runelite.api.NodeCache;
import net.runelite.api.SpriteID;
import net.runelite.api.Sprite;
import net.runelite.api.events.BeforeMenuRender;
@@ -71,8 +69,6 @@ public class InterfaceStylesPlugin extends Plugin
@Inject
private SpriteManager spriteManager;
private HealthBarOverride healthBarOverride;
@Provides
InterfaceStylesConfig provideConfig(ConfigManager configManager)
{
@@ -92,10 +88,7 @@ public class InterfaceStylesPlugin extends Plugin
{
restoreWidgetDimensions();
removeGameframe();
healthBarOverride = null;
client.setHealthBarOverride(null);
NodeCache heathBarCache = client.getHealthBarCache();
heathBarCache.reset(); // invalidate healthbar cache so padding resets
restoreHealthBars();
});
}
@@ -117,19 +110,19 @@ public class InterfaceStylesPlugin extends Plugin
@Subscribe
public void onPostHealthBar(PostHealthBar postHealthBar)
{
if (healthBarOverride == null || !config.hdHealthBars())
if (!config.hdHealthBars())
{
return;
}
HealthBar healthBar = postHealthBar.getHealthBar();
Sprite frontSprite = healthBar.getHealthBarFrontSprite();
HealthbarOverride override = HealthbarOverride.get(healthBar.getHealthBarFrontSpriteId());
// Check if this is the health bar we are replacing
if (frontSprite == healthBarOverride.getFrontSprite() || frontSprite == healthBarOverride.getFrontSpriteLarge())
if (override != null)
{
// Increase padding to show some more green at very low hp percentages
healthBar.setPadding(1);
healthBar.setPadding(override.getPadding());
}
}
@@ -162,7 +155,7 @@ public class InterfaceStylesPlugin extends Plugin
if (skin == config.skin())
{
String file = config.skin().toString() + "/" + spriteOverride.getSpriteID() + ".png";
Sprite spritePixels = getFileSprite(file);
Sprite spritePixels = getFileSpritePixels(file);
if (spriteOverride.getSpriteID() == SpriteID.COMPASS_TEXTURE)
{
@@ -194,7 +187,7 @@ public class InterfaceStylesPlugin extends Plugin
if (widgetOverride.getSkin() == config.skin())
{
String file = config.skin().toString() + "/widget/" + widgetOverride.getName() + ".png";
Sprite spritePixels = getFileSprite(file);
Sprite spritePixels = getFileSpritePixels(file);
if (spritePixels != null)
{
@@ -218,7 +211,7 @@ public class InterfaceStylesPlugin extends Plugin
}
}
private Sprite getFileSprite(String file)
private Sprite getFileSpritePixels(String file)
{
try
{
@@ -272,31 +265,24 @@ public class InterfaceStylesPlugin extends Plugin
private void overrideHealthBars()
{
// Reset health bar cache to reset applied padding
NodeCache healthBarCache = client.getHealthBarCache();
healthBarCache.reset();
if (config.hdHealthBars())
{
String fileBase = Skin.AROUND_2010.toString() + "/healthbar/";
Sprite frontSprite = getFileSprite(fileBase + "front.png");
Sprite backSprite = getFileSprite(fileBase + "back.png");
Sprite frontSpriteLarge = getFileSprite(fileBase + "front_large.png");
Sprite backSpriteLarge = getFileSprite(fileBase + "back_large.png");
HealthBarOverride override = new HealthBarOverride(frontSprite, backSprite, frontSpriteLarge, backSpriteLarge);
healthBarOverride = override;
client.setHealthBarOverride(override);
spriteManager.addSpriteOverrides(HealthbarOverride.values());
// Reset health bar caches to apply the override
clientThread.invokeLater(client::resetHealthBarCaches);
}
else
{
healthBarOverride = null;
client.setHealthBarOverride(null);
restoreHealthBars();
}
}
private void restoreHealthBars()
{
spriteManager.removeSpriteOverrides(HealthbarOverride.values());
clientThread.invokeLater(client::resetHealthBarCaches);
}
private void restoreWidgetDimensions()
{
for (WidgetOffset widgetOffset : WidgetOffset.values())

View File

@@ -27,6 +27,7 @@ package net.runelite.client.plugins.inventorygrid;
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("inventorygrid")
public interface InventoryGridConfig extends Config
@@ -60,4 +61,15 @@ public interface InventoryGridConfig extends Config
{
return true;
}
@ConfigItem(
keyName = "dragDelay",
name = "Drag Delay",
description = "Time in ms to wait after item press before showing grid"
)
@Range(min = 100)
default int dragDelay()
{
return 100;
}
}

View File

@@ -34,6 +34,7 @@ import java.awt.Point;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import net.runelite.api.Client;
import net.runelite.api.Constants;
import net.runelite.api.widgets.Widget;
import net.runelite.api.widgets.WidgetInfo;
import net.runelite.api.widgets.WidgetItem;
@@ -45,7 +46,6 @@ import net.runelite.client.ui.overlay.OverlayPosition;
class InventoryGridOverlay extends Overlay
{
private static final int INVENTORY_SIZE = 28;
private static final int DRAG_DELAY = 5;
private static final Color HIGHLIGHT = new Color(0, 255, 0, 45);
private static final Color GRID = new Color(255, 255, 255, 45);
@@ -72,7 +72,7 @@ class InventoryGridOverlay extends Overlay
final Widget inventoryWidget = client.getWidget(WidgetInfo.INVENTORY);
if (if1DraggingWidget == null || if1DraggingWidget != inventoryWidget
|| client.getItemPressedDuration() < DRAG_DELAY)
|| client.getItemPressedDuration() < config.dragDelay() / Constants.CLIENT_TICK_LENGTH)
{
return null;
}

View File

@@ -32,6 +32,7 @@ import java.awt.image.BufferedImage;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import javax.inject.Inject;
import javax.swing.JOptionPane;
@@ -102,7 +103,7 @@ public class InventorySetupPlugin extends Plugin
private InventorySetupPluginPanel panel;
private HashMap<String, InventorySetup> inventorySetups;
private Map<String, InventorySetup> inventorySetups = new HashMap<>();
private NavigationButton navButton;
@@ -270,7 +271,7 @@ public class InventorySetupPlugin extends Plugin
final String json = configManager.getConfiguration(CONFIG_GROUP, CONFIG_KEY);
if (json == null || json.isEmpty())
{
inventorySetups = new HashMap<>();
inventorySetups.clear();
}
else
{
@@ -280,7 +281,8 @@ public class InventorySetupPlugin extends Plugin
{
}.getType();
inventorySetups = gson.fromJson(json, type);
inventorySetups.clear();
inventorySetups.putAll(gson.fromJson(json, type));
}
for (final String key : inventorySetups.keySet())

View File

@@ -165,15 +165,15 @@ public class InventoryTagsPlugin extends Plugin
return;
}
final String selectedMenu = Text.removeTags(event.getMenuTarget());
final String selectedMenu = Text.removeTags(event.getTarget());
if (event.getMenuOption().equals(MENU_SET))
if (event.getOption().equals(MENU_SET))
{
setTag(event.getId(), selectedMenu);
setTag(event.getIdentifier(), selectedMenu);
}
else if (event.getMenuOption().equals(MENU_REMOVE))
else if (event.getOption().equals(MENU_REMOVE))
{
unsetTag(event.getId());
unsetTag(event.getIdentifier());
}
}

View File

@@ -34,12 +34,14 @@ import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import javax.inject.Inject;
import net.runelite.api.Client;
import net.runelite.api.Constants;
import net.runelite.api.InventoryID;
import net.runelite.api.Item;
import net.runelite.api.ItemDefinition;
import net.runelite.api.ItemContainer;
import net.runelite.api.VarClientInt;
import net.runelite.client.game.ItemManager;
import static net.runelite.client.plugins.lootingbagviewer.LootingBagViewerOverlay.PLACEHOLDER_WIDTH;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.components.ComponentConstants;
@@ -51,9 +53,8 @@ import net.runelite.client.ui.overlay.components.TitleComponent;
class InventoryViewerOverlay extends Overlay
{
private static final int INVENTORY_SIZE = 28;
private static final int PLACEHOLDER_WIDTH = 36;
private static final int PLACEHOLDER_HEIGHT = 32;
private static final ImageComponent PLACEHOLDER_IMAGE = new ImageComponent(new BufferedImage(PLACEHOLDER_WIDTH, PLACEHOLDER_HEIGHT, BufferedImage.TYPE_4BYTE_ABGR));
private static final ImageComponent PLACEHOLDER_IMAGE = new ImageComponent(
new BufferedImage(Constants.ITEM_SPRITE_WIDTH, Constants.ITEM_SPRITE_HEIGHT, BufferedImage.TYPE_4BYTE_ABGR));
private final Client client;
private final ItemManager itemManager;

View File

@@ -29,6 +29,7 @@ import java.awt.Dimension;
import java.awt.Graphics2D;
import javax.inject.Inject;
import net.runelite.api.Client;
import net.runelite.api.Constants;
import net.runelite.api.InventoryID;
import net.runelite.api.Item;
import net.runelite.api.ItemDefinition;
@@ -93,6 +94,8 @@ class ItemPricesOverlay extends Overlay
// Tooltip action type handling
switch (action)
{
case ITEM_USE_ON_WIDGET:
if (!menuEntry.getTarget().contains("High Level Alchemy") || !config.showAlchProfit()) return null;
case WIDGET_DEFAULT:
case ITEM_USE:
case ITEM_FIRST_OPTION:
@@ -194,6 +197,7 @@ class ItemPricesOverlay extends Overlay
int gePrice = 0;
int haPrice = 0;
int haProfit = 0;
final int itemHaPrice = Math.round(itemDef.getPrice() * Constants.HIGH_ALCHEMY_MULTIPLIER);
if (config.showGEPrice())
{
@@ -203,9 +207,9 @@ class ItemPricesOverlay extends Overlay
{
haPrice = itemManager.getAlchValue(id);
}
if (gePrice > 0 && haPrice > 0 && config.showAlchProfit())
if (gePrice > 0 && itemHaPrice > 0 && config.showAlchProfit())
{
haProfit = calculateHAProfit(haPrice, gePrice);
haProfit = calculateHAProfit(itemHaPrice, gePrice);
}
if (gePrice > 0 || haPrice > 0)

View File

@@ -0,0 +1,65 @@
/*
* Copyright (c) 2018, TheStonedTurtle <https://github.com/TheStonedTurtle>
* 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.itemskeptondeath;
import com.google.common.collect.ImmutableMap;
import lombok.AllArgsConstructor;
import lombok.Getter;
import net.runelite.api.ItemID;
/**
* Certain Items receive a white outline by Jagex as they are always lost on death. This is sometimes incorrectly
* added to Items by Jagex as the item is actually kept in non-pvp areas of the game, such as the Rune Pouch.
*
* The white outline will be added to these items when they are lost on death.
*/
@AllArgsConstructor
@Getter
enum AlwaysLostItem
{
RUNE_POUCH(ItemID.RUNE_POUCH, true),
LOOTING_BAG(ItemID.LOOTING_BAG, false),
CLUE_BOX(ItemID.CLUE_BOX, false);
private final int itemID;
private final boolean keptOutsideOfWilderness;
private static final ImmutableMap<Integer, AlwaysLostItem> ID_MAP;
static
{
final ImmutableMap.Builder<Integer, AlwaysLostItem> map = ImmutableMap.builder();
for (final AlwaysLostItem p : values())
{
map.put(p.itemID, p);
}
ID_MAP = map.build();
}
static AlwaysLostItem getByItemID(final int itemID)
{
return ID_MAP.get(itemID);
}
}

View File

@@ -0,0 +1,111 @@
/*
* Copyright (c) 2018, TheStonedTurtle <https://github.com/TheStonedTurtle>
* 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.itemskeptondeath;
import com.google.common.collect.ImmutableSet;
import lombok.AllArgsConstructor;
import net.runelite.api.ItemID;
/**
* Some non tradeable items are kept on death inside low level wilderness (1-20) but are turned into a broken variant.
*
* The non-broken variant will be shown inside the interface.
*/
@AllArgsConstructor
enum BrokenOnDeathItem
{
// Capes
FIRE_CAPE(ItemID.FIRE_CAPE),
FIRE_MAX_CAPE(ItemID.FIRE_MAX_CAPE),
INFERNAL_CAPE(ItemID.INFERNAL_CAPE),
INFERNAL_MAX_CAPE(ItemID.INFERNAL_MAX_CAPE),
AVAS_ASSEMBLER(ItemID.AVAS_ASSEMBLER),
ASSEMBLER_MAX_CAPE(ItemID.ASSEMBLER_MAX_CAPE),
// Defenders
BRONZE_DEFENDER(ItemID.BRONZE_DEFENDER),
IRON_DEFENDER(ItemID.IRON_DEFENDER),
STEEL_DEFENDER(ItemID.STEEL_DEFENDER),
BLACK_DEFENDER(ItemID.BLACK_DEFENDER),
MITHRIL_DEFENDER(ItemID.MITHRIL_DEFENDER),
ADAMANT_DEFENDER(ItemID.ADAMANT_DEFENDER),
RUNE_DEFENDER(ItemID.RUNE_DEFENDER),
DRAGON_DEFENDER(ItemID.DRAGON_DEFENDER),
AVERNIC_DEFENDER(ItemID.AVERNIC_DEFENDER),
// Void
VOID_MAGE_HELM(ItemID.VOID_MAGE_HELM),
VOID_RANGER_HELM(ItemID.VOID_RANGER_HELM),
VOID_MELEE_HELM(ItemID.VOID_MELEE_HELM),
VOID_KNIGHT_TOP(ItemID.VOID_KNIGHT_TOP),
VOID_KNIGHT_ROBE(ItemID.VOID_KNIGHT_ROBE),
VOID_KNIGHT_GLOVES(ItemID.VOID_KNIGHT_GLOVES),
VOID_KNIGHT_MACE(ItemID.VOID_KNIGHT_MACE),
ELITE_VOID_TOP(ItemID.ELITE_VOID_TOP),
ELITE_VOID_ROBE(ItemID.ELITE_VOID_ROBE),
// Barb Assault
FIGHTER_HAT(ItemID.FIGHTER_HAT),
RANGER_HAT(ItemID.RANGER_HAT),
HEALER_HAT(ItemID.HEALER_HAT),
FIGHTER_TORSO(ItemID.FIGHTER_TORSO),
PENANCE_SKIRT(ItemID.PENANCE_SKIRT),
// Castle Wars
SARADOMIN_HALO(ItemID.SARADOMIN_HALO),
ZAMORAK_HALO(ItemID.ZAMORAK_HALO),
GUTHIX_HALO(ItemID.GUTHIX_HALO),
DECORATIVE_MAGIC_HAT(ItemID.DECORATIVE_ARMOUR_11898),
DECORATIVE_MAGIC_ROBE_TOP(ItemID.DECORATIVE_ARMOUR_11896),
DECORATIVE_MAGIC_ROBE_LEGS(ItemID.DECORATIVE_ARMOUR_11897),
DECORATIVE_RANGE_TOP(ItemID.DECORATIVE_ARMOUR_11899),
DECORATIVE_RANGE_BOTTOM(ItemID.DECORATIVE_ARMOUR_11900),
DECORATIVE_RANGE_QUIVER(ItemID.DECORATIVE_ARMOUR_11901),
GOLD_DECORATIVE_HELM(ItemID.DECORATIVE_HELM_4511),
GOLD_DECORATIVE_BODY(ItemID.DECORATIVE_ARMOUR_4509),
GOLD_DECORATIVE_LEGS(ItemID.DECORATIVE_ARMOUR_4510),
GOLD_DECORATIVE_SKIRT(ItemID.DECORATIVE_ARMOUR_11895),
GOLD_DECORATIVE_SHIELD(ItemID.DECORATIVE_SHIELD_4512),
GOLD_DECORATIVE_SWORD(ItemID.DECORATIVE_SWORD_4508);
private final int itemID;
private static final ImmutableSet<Integer> ID_SET;
static
{
final ImmutableSet.Builder<Integer> set = new ImmutableSet.Builder<>();
for (final BrokenOnDeathItem p : values())
{
set.add(p.itemID);
}
ID_SET = set.build();
}
static boolean isBrokenOnDeath(final int itemID)
{
return ID_SET.contains(itemID);
}
}

View File

@@ -0,0 +1,91 @@
/*
* Copyright (c) 2019, Adam <Adam@sigterm.info>
* Copyright (c) 2019, TheStonedTurtle <https://github.com/TheStonedTurtle>
* 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.itemskeptondeath;
import com.google.common.collect.ImmutableMap;
import java.util.Map;
import javax.annotation.Nullable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import net.runelite.api.ItemID;
/**
* Some items have a fixed price that is added to its default value when calculating death prices.
* These are typically imbued items, such as Berserker ring (i), to help it protect over the non-imbued variants.
*/
@AllArgsConstructor
@Getter
enum FixedPriceItem
{
IMBUED_BLACK_MASK_I(ItemID.BLACK_MASK_I, 5000),
IMBUED_BLACK_MASK_1_I(ItemID.BLACK_MASK_1_I, 5000),
IMBUED_BLACK_MASK_2_I(ItemID.BLACK_MASK_2_I, 5000),
IMBUED_BLACK_MASK_3_I(ItemID.BLACK_MASK_3_I, 5000),
IMBUED_BLACK_MASK_4_I(ItemID.BLACK_MASK_4_I, 5000),
IMBUED_BLACK_MASK_5_I(ItemID.BLACK_MASK_5_I, 5000),
IMBUED_BLACK_MASK_6_I(ItemID.BLACK_MASK_6_I, 5000),
IMBUED_BLACK_MASK_7_I(ItemID.BLACK_MASK_7_I, 5000),
IMBUED_BLACK_MASK_8_I(ItemID.BLACK_MASK_8_I, 5000),
IMBUED_BLACK_MASK_9_I(ItemID.BLACK_MASK_9_I, 5000),
IMBUED_BLACK_MASK_10_I(ItemID.BLACK_MASK_10_I, 5000),
IMBUED_SLAYER_HELMET_I(ItemID.SLAYER_HELMET_I, 1000),
IMBUED_BLACK_SLAYER_HELMET_I(ItemID.BLACK_SLAYER_HELMET_I, 1000),
IMBUED_PURPLE_SLAYER_HELMET_I(ItemID.PURPLE_SLAYER_HELMET_I, 1000),
IMBUED_RED_SLAYER_HELMET_I(ItemID.RED_SLAYER_HELMET_I, 1000),
IMBUED_GREEN_SLAYER_HELMET_I(ItemID.GREEN_SLAYER_HELMET_I, 1000),
IMBUED_TURQUOISE_SLAYER_HELMET_I(ItemID.TURQUOISE_SLAYER_HELMET_I, 1000),
IMBUED_HYDRA_SLAYER_HELMET_I(ItemID.HYDRA_SLAYER_HELMET_I, 1000),
IMBUED_ARCHERS_RING_I(ItemID.ARCHERS_RING_I, 2000),
IMBUED_BERSERKER_RING_I(ItemID.BERSERKER_RING_I, 2000),
IMBUED_SEERS_RING_I(ItemID.SEERS_RING_I, 2000),
IMBUED_RING_OF_THE_GODS_I(ItemID.RING_OF_THE_GODS_I, 2000),
IMBUED_TREASONOUS_RING_I(ItemID.TREASONOUS_RING_I, 2000),
IMBUED_TYRANNICAL_RING_I(ItemID.TYRANNICAL_RING_I, 2000);
private final int itemId;
private final int offset;
private static final Map<Integer, FixedPriceItem> FIXED_ITEMS;
static
{
final ImmutableMap.Builder<Integer, FixedPriceItem> map = ImmutableMap.builder();
for (final FixedPriceItem p : values())
{
map.put(p.itemId, p);
}
FIXED_ITEMS = map.build();
}
@Nullable
static FixedPriceItem find(int itemId)
{
return FIXED_ITEMS.get(itemId);
}
}

View File

@@ -0,0 +1,610 @@
/*
* Copyright (c) 2018, TheStonedTurtle <https://github.com/TheStonedTurtle>
* Copyright (c) 2019, Adam <Adam@sigterm.info>
* 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.itemskeptondeath;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.EnumSet;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.inject.Inject;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Client;
import net.runelite.api.Constants;
import net.runelite.api.FontID;
import net.runelite.api.InventoryID;
import net.runelite.api.Item;
import net.runelite.api.ItemDefinition;
import net.runelite.api.ItemContainer;
import net.runelite.api.ItemID;
import net.runelite.api.ScriptID;
import net.runelite.api.SkullIcon;
import net.runelite.api.SpriteID;
import net.runelite.api.Varbits;
import net.runelite.api.WorldType;
import net.runelite.api.events.ScriptCallbackEvent;
import net.runelite.api.vars.AccountType;
import net.runelite.api.widgets.Widget;
import net.runelite.api.widgets.WidgetInfo;
import net.runelite.api.widgets.WidgetType;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.game.ItemManager;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.util.StackFormatter;
@PluginDescriptor(
name = "Items Kept on Death",
description = "Updates the Items Kept on Death interface to be more accurate",
enabledByDefault = false
)
@Slf4j
public class ItemsKeptOnDeathPlugin extends Plugin
{
private static final int DEEP_WILDY = 20;
private static final Pattern WILDERNESS_LEVEL_PATTERN = Pattern.compile("^Level: (\\d+).*");
// Item Container helpers
private static final int MAX_ROW_ITEMS = 8;
private static final int ITEM_X_OFFSET = 5;
private static final int ITEM_Y_OFFSET = 25;
private static final int ITEM_X_STRIDE = 38;
private static final int ITEM_Y_STRIDE = 38;
private static final int ORIGINAL_LOST_HEIGHT = 209;
private static final int ORIGINAL_LOST_Y = 107;
// Information panel text helpers
private static final String LINE_BREAK = "<br>";
private static final int INFORMATION_CONTAINER_HEIGHT = 183;
private static final int FONT_COLOR = 0xFF981F;
// Button Images
private static final int PROTECT_ITEM_SPRITE_ID = SpriteID.PRAYER_PROTECT_ITEM;
private static final int SKULL_SPRITE_ID = SpriteID.PLAYER_KILLER_SKULL_523;
private static final int SWORD_SPRITE_ID = SpriteID.MULTI_COMBAT_ZONE_CROSSED_SWORDS;
private static final int SKULL_2_SPRITE_ID = SpriteID.FIGHT_PITS_WINNER_SKULL_RED;
@Inject
private Client client;
@Inject
private ItemManager itemManager;
private WidgetButton deepWildyButton;
private WidgetButton lowWildyButton;
private boolean isSkulled;
private boolean protectingItem;
private int wildyLevel;
@Subscribe
public void onScriptCallbackEvent(ScriptCallbackEvent event)
{
if (event.getEventName().equals("itemsKeptOnDeath"))
{
// The script in charge of building the Items Kept on Death interface has finished running.
// Make all necessary changes now.
// Players inside Safe Areas (POH/Clan Wars) or playing DMM see the default interface
if (isInSafeArea() || client.getWorldType().contains(WorldType.DEADMAN))
{
return;
}
syncSettings();
createWidgetButtons();
rebuildItemsKeptOnDeathInterface();
final Widget keptText = client.getWidget(WidgetInfo.ITEMS_KEPT_ON_DEATH_TEXT);
keptText.setText("Items you will keep on death:");
final Widget lostText = client.getWidget(WidgetInfo.ITEMS_LOST_ON_DEATH_TEXT);
lostText.setText("Items you will lose on death:");
}
}
// Sync user settings
private void syncSettings()
{
final SkullIcon s = client.getLocalPlayer().getSkullIcon();
// Ultimate iron men deaths are treated like they are always skulled
isSkulled = s == SkullIcon.SKULL || isUltimateIronman();
protectingItem = client.getVar(Varbits.PRAYER_PROTECT_ITEM) == 1;
syncWildernessLevel();
}
private void syncWildernessLevel()
{
if (client.getVar(Varbits.IN_WILDERNESS) != 1)
{
// if they are in a PvP world and not in a safe zone act like in lvl 1 wildy
if (isInPvpWorld() && !isInPvPSafeZone())
{
wildyLevel = 1;
return;
}
wildyLevel = -1;
return;
}
final Widget wildernessLevelWidget = client.getWidget(WidgetInfo.PVP_WILDERNESS_LEVEL);
if (wildernessLevelWidget == null)
{
wildyLevel = -1;
return;
}
final String wildernessLevelText = wildernessLevelWidget.getText();
final Matcher m = WILDERNESS_LEVEL_PATTERN.matcher(wildernessLevelText);
if (!m.matches())
{
wildyLevel = -1;
return;
}
wildyLevel = Integer.parseInt(m.group(1));
}
private boolean isInPvpWorld()
{
final EnumSet<WorldType> world = client.getWorldType();
return world.contains(WorldType.PVP);
}
private boolean isProtectItemAllowed()
{
return !client.getWorldType().contains(WorldType.HIGH_RISK)
&& !isUltimateIronman();
}
private boolean isInPvPSafeZone()
{
final Widget w = client.getWidget(WidgetInfo.PVP_WORLD_SAFE_ZONE);
return w != null && !w.isHidden();
}
private boolean isInSafeArea()
{
final Widget w = client.getWidget(WidgetInfo.ITEMS_KEPT_SAFE_ZONE_CONTAINER);
return w != null && !w.isHidden();
}
private boolean isUltimateIronman()
{
return client.getAccountType() == AccountType.ULTIMATE_IRONMAN;
}
private int getDefaultItemsKept()
{
final int count = isSkulled ? 0 : 3;
return count + (protectingItem ? 1 : 0);
}
private void rebuildItemsKeptOnDeathInterface()
{
final Widget lost = client.getWidget(WidgetInfo.ITEMS_LOST_ON_DEATH_CONTAINER);
final Widget kept = client.getWidget(WidgetInfo.ITEMS_KEPT_ON_DEATH_CONTAINER);
if (lost == null || kept == null)
{
return;
}
lost.deleteAllChildren();
kept.deleteAllChildren();
// Grab all items on player
final ItemContainer inventory = client.getItemContainer(InventoryID.INVENTORY);
final Item[] inv = inventory == null ? new Item[0] : inventory.getItems();
final ItemContainer equipment = client.getItemContainer(InventoryID.EQUIPMENT);
final Item[] equip = equipment == null ? new Item[0] : equipment.getItems();
final List<Item> items = new ArrayList<>();
Collections.addAll(items, inv);
Collections.addAll(items, equip);
// Sort by item price
items.sort(Comparator.comparing(this::getDeathPrice).reversed());
boolean hasAlwaysLost = false;
int keepCount = getDefaultItemsKept();
final List<Widget> keptItems = new ArrayList<>();
final List<Widget> lostItems = new ArrayList<>();
for (final Item i : items)
{
final int id = i.getId();
int itemQuantity = i.getQuantity();
if (id == -1)
{
continue;
}
final ItemDefinition c = itemManager.getItemDefinition(i.getId());
// Bonds are always kept and do not count towards the limit.
if (id == ItemID.OLD_SCHOOL_BOND || id == ItemID.OLD_SCHOOL_BOND_UNTRADEABLE)
{
final Widget itemWidget = createItemWidget(kept, itemQuantity, c);
itemWidget.setOnOpListener(ScriptID.DEATH_KEEP_ITEM_EXAMINE, 1, itemQuantity, c.getName());
keptItems.add(itemWidget);
continue;
}
// Certain items are always lost on death and have a white outline which we need to add
final AlwaysLostItem alwaysLostItem = AlwaysLostItem.getByItemID(i.getId());
if (alwaysLostItem != null)
{
// Some of these items are kept on death (outside wildy), like the Rune pouch. Ignore them
if (!alwaysLostItem.isKeptOutsideOfWilderness() || wildyLevel > 0)
{
final Widget itemWidget = createItemWidget(lost, itemQuantity, c);
itemWidget.setOnOpListener(ScriptID.DEATH_KEEP_ITEM_EXAMINE, 0, itemQuantity, c.getName());
itemWidget.setBorderType(2); // white outline
lostItems.add(itemWidget);
hasAlwaysLost = true;
continue;
}
// the rune pouch is "always lost" but its kept outside of pvp, and does not count towards your keep count
}
else if (keepCount > 0)
{
// Keep most valuable items regardless of trade-ability.
if (i.getQuantity() > keepCount)
{
final Widget itemWidget = createItemWidget(kept, keepCount, c);
itemWidget.setOnOpListener(ScriptID.DEATH_KEEP_ITEM_EXAMINE, 1, keepCount, c.getName());
keptItems.add(itemWidget);
itemQuantity -= keepCount;
keepCount = 0;
// Fall through to below to drop the rest of the stack
}
else
{
final Widget itemWidget = createItemWidget(kept, itemQuantity, c);
itemWidget.setOnOpListener(ScriptID.DEATH_KEEP_ITEM_EXAMINE, 1, itemQuantity, c.getName());
keptItems.add(itemWidget);
keepCount -= i.getQuantity();
continue;
}
}
// Items are kept if:
// 1) is not tradeable
// 2) is under the deep wilderness line
// 3) is outside of the wilderness, or item has a broken form
if (!Pets.isPet(id)
&& !isTradeable(c) && wildyLevel <= DEEP_WILDY
&& (wildyLevel <= 0 || BrokenOnDeathItem.isBrokenOnDeath(i.getId())))
{
final Widget itemWidget = createItemWidget(kept, itemQuantity, c);
itemWidget.setOnOpListener(ScriptID.DEATH_KEEP_ITEM_EXAMINE, 1, itemQuantity, c.getName());
keptItems.add(itemWidget);
}
else
{
// Otherwise, the item is lost
final Widget itemWidget = createItemWidget(lost, itemQuantity, c);
itemWidget.setOnOpListener(ScriptID.DEATH_KEEP_ITEM_EXAMINE, 0, itemQuantity, c.getName());
lostItems.add(itemWidget);
}
}
int rows = (keptItems.size() + MAX_ROW_ITEMS - 1) / MAX_ROW_ITEMS;
// Show an empty row if there isn't anything
if (rows > 0)
{
// ORIGINAL_LOST_Y/HEIGHT includes a row already
rows--;
}
// Adjust items lost container position if new rows were added to kept items container
lost.setOriginalY(ORIGINAL_LOST_Y + (rows * ITEM_Y_STRIDE));
lost.setOriginalHeight(ORIGINAL_LOST_HEIGHT - (rows * ITEM_Y_STRIDE));
positionWidgetItems(kept, keptItems);
positionWidgetItems(lost, lostItems);
updateKeptWidgetInfoText(hasAlwaysLost, keptItems, lostItems);
}
/**
* Get the price of an item
* @param item
* @return
*/
private int getDeathPrice(Item item)
{
int itemId = item.getId();
// Unnote/unplaceholder item
int canonicalizedItemId = itemManager.canonicalize(itemId);
int exchangePrice = itemManager.getItemPrice(canonicalizedItemId);
if (exchangePrice == 0)
{
final ItemDefinition c1 = itemManager.getItemDefinition(canonicalizedItemId);
exchangePrice = c1.getPrice();
}
else
{
// Some items have artifically applied death prices - such as ring imbues
// which are +2k over the non imbues. Check if the item has a fixed price.
FixedPriceItem fixedPrice = FixedPriceItem.find(canonicalizedItemId);
if (fixedPrice != null)
{
// Apply fixed price offset
exchangePrice += fixedPrice.getOffset();
}
}
return exchangePrice;
}
/**
* Position a list of widget items in the parent container
*/
private static void positionWidgetItems(final Widget parent, final List<Widget> widgets)
{
int startingIndex = 0;
for (final Widget w : widgets)
{
final int originalX = ITEM_X_OFFSET + ((startingIndex % MAX_ROW_ITEMS) * ITEM_X_STRIDE);
final int originalY = ITEM_Y_OFFSET + ((startingIndex / MAX_ROW_ITEMS) * ITEM_Y_STRIDE);
w.setOriginalX(originalX);
w.setOriginalY(originalY);
w.revalidate();
++startingIndex;
}
parent.revalidate();
}
/**
* Creates the text to be displayed in the right side of the interface based on current selections
*/
private String getInfoText(final boolean hasAlwaysLost)
{
final StringBuilder sb = new StringBuilder();
if (isUltimateIronman())
{
sb.append("You are an <col=FFFFFF>UIM<col=FF981F> which means <col=FFFFFF>0<col=FF981F> items are protected by default");
}
else
{
sb.append("<col=FFFFFF>3<col=FF981F> items protected by default");
if (isSkulled)
{
sb.append(LINE_BREAK)
.append("<col=ff3333>PK skull<col=ff981f> -3");
}
if (protectingItem)
{
sb.append(LINE_BREAK)
.append("<col=ff3333>Protect Item prayer<col=ff981f> +1");
}
sb.append(LINE_BREAK)
.append(String.format("Actually protecting <col=FFFFFF>%s<col=FF981F> items", getDefaultItemsKept()));
}
if (wildyLevel < 1)
{
sb.append(LINE_BREAK)
.append(LINE_BREAK)
.append("You will have 1 hour to retrieve your lost items.");
}
if (hasAlwaysLost)
{
sb.append(LINE_BREAK)
.append(LINE_BREAK)
.append("Items with a <col=ffffff>white outline<col=ff981f> will always be lost.");
}
sb.append(LINE_BREAK)
.append(LINE_BREAK)
.append("Untradeable items are kept on death in non-pvp scenarios.");
return sb.toString();
}
/**
* Updates the information panel based on the item containers
*/
private void updateKeptWidgetInfoText(final boolean hasAlwaysLost, final List<Widget> keptItems, final List<Widget> lostItems)
{
// Add Information text widget
final Widget textWidget = findOrCreateInfoText();
textWidget.setText(getInfoText(hasAlwaysLost));
textWidget.revalidate();
// Update Items lost total value
long total = 0;
for (final Widget w : lostItems)
{
int cid = itemManager.canonicalize(w.getItemId());
int price = itemManager.getItemPrice(cid);
if (price == 0)
{
// Default to alch price
price = (int) (itemManager.getItemDefinition(cid).getPrice() * Constants.HIGH_ALCHEMY_MULTIPLIER);
}
total += (long) price * w.getItemQuantity();
}
final Widget lostValue = client.getWidget(WidgetInfo.ITEMS_LOST_VALUE);
lostValue.setText(StackFormatter.quantityToStackSize(total) + " gp");
// Update Max items kept
final Widget max = client.getWidget(WidgetInfo.ITEMS_KEPT_MAX);
final int keptQty = keptItems.stream().mapToInt(Widget::getItemQuantity).sum();
max.setText(String.format("<col=ffcc33>Max items kept on death:<br><br><col=ffcc33>~ %d ~", keptQty));
}
/**
* Check if an item is tradeable to another player
*
* @param c The item
* @return
*/
private static boolean isTradeable(final ItemDefinition c)
{
// ItemDefinition:: isTradeable checks if they are traded on the grand exchange, some items are trade-able but not via GE
if (c.getNote() != -1
|| c.getLinkedNoteId() != -1
|| c.isTradeable())
{
return true;
}
final int id = c.getId();
switch (id)
{
case ItemID.COINS_995:
case ItemID.PLATINUM_TOKEN:
return true;
default:
return false;
}
}
private Widget findOrCreateInfoText()
{
// The text was on the ITEMS_KEPT_INFORMATION_CONTAINER widget - but now that it is a layer,
// we need to create a child widget to hold the text
final Widget parent = client.getWidget(WidgetInfo.ITEMS_KEPT_INFORMATION_CONTAINER);
// Use the text TEXT widget if it already exists. It should be the last child of the parent
final Widget[] children = parent.getChildren();
if (children != null && children.length > 0)
{
final Widget w = parent.getChild(children.length - 1);
if (w != null && w.getType() == WidgetType.TEXT)
{
log.debug("Reusing old text widget");
return w;
}
}
log.debug("Creating new text widget");
final Widget w = parent.createChild(-1, WidgetType.TEXT);
// Position under buttons taking remaining space
w.setOriginalWidth(parent.getOriginalWidth());
w.setOriginalHeight(INFORMATION_CONTAINER_HEIGHT - parent.getOriginalHeight());
w.setOriginalY(parent.getOriginalHeight());
w.setFontId(FontID.PLAIN_11);
w.setTextShadowed(true);
w.setTextColor(FONT_COLOR);
// Need to adjust parent height so text is visible
parent.setOriginalHeight(INFORMATION_CONTAINER_HEIGHT);
parent.revalidate();
return w;
}
private void createWidgetButtons()
{
final Widget parent = client.getWidget(WidgetInfo.ITEMS_KEPT_INFORMATION_CONTAINER);
// Change the information container from a text widget to a layer
parent.setType(WidgetType.LAYER);
parent.deleteAllChildren();
// Ultimate Iron men are always skulled and can't use the protect item prayer
WidgetButton protectItemButton = isProtectItemAllowed()
? new WidgetButton(parent, "Protect Item Prayer", PROTECT_ITEM_SPRITE_ID, protectingItem, selected ->
{
protectingItem = selected;
rebuildItemsKeptOnDeathInterface();
}) : null;
WidgetButton skulledButton = !isUltimateIronman()
? new WidgetButton(parent, "Skulled", SKULL_SPRITE_ID, isSkulled, selected ->
{
isSkulled = selected;
rebuildItemsKeptOnDeathInterface();
}) : null;
lowWildyButton = new WidgetButton(parent, "Low Wildy (1-20)", SWORD_SPRITE_ID, wildyLevel > 0 && wildyLevel <= DEEP_WILDY, selected ->
{
if (!selected)
{
syncWildernessLevel();
}
else
{
wildyLevel = 1;
deepWildyButton.setSelected(false);
}
rebuildItemsKeptOnDeathInterface();
});
deepWildyButton = new WidgetButton(parent, "Deep Wildy (21+)", SKULL_2_SPRITE_ID, wildyLevel > DEEP_WILDY, selected ->
{
if (!selected)
{
syncWildernessLevel();
}
else
{
wildyLevel = DEEP_WILDY + 1;
lowWildyButton.setSelected(false);
}
rebuildItemsKeptOnDeathInterface();
});
parent.revalidate();
WidgetButton.layoutButtonsToContainer(parent, protectItemButton, skulledButton, lowWildyButton, deepWildyButton);
}
/**
* Creates an Item Widget for use inside the Kept on Death Interface
*
* @param qty Amount of item
* @param c Items Composition
* @return
*/
private static Widget createItemWidget(final Widget parent, final int qty, final ItemDefinition c)
{
final Widget itemWidget = parent.createChild(-1, WidgetType.GRAPHIC);
itemWidget.setItemId(c.getId());
itemWidget.setItemQuantity(qty);
itemWidget.setHasListener(true);
itemWidget.setOriginalWidth(Constants.ITEM_SPRITE_WIDTH);
itemWidget.setOriginalHeight(Constants.ITEM_SPRITE_HEIGHT);
itemWidget.setBorderType(1);
itemWidget.setAction(1, String.format("Item: <col=ff981f>%s", c.getName()));
return itemWidget;
}
}

View File

@@ -0,0 +1,99 @@
/*
* Copyright (c) 2018 Abex
* 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.itemskeptondeath;
import com.google.common.collect.ImmutableSet;
import java.util.Set;
import static net.runelite.api.ItemID.*;
final class Pets
{
private Pets()
{
}
private static final Set<Integer> PETS = ImmutableSet.of(
BABY_MOLE,
PRINCE_BLACK_DRAGON,
PET_CORPOREAL_CRITTER, PET_DARK_CORE,
JALNIBREK, TZREKZUK,
KALPHITE_PRINCESS, KALPHITE_PRINCESS_12654,
LIL_ZIK,
SKOTOS,
PET_SNAKELING, PET_SNAKELING_12939, PET_SNAKELING_12940,
TZREKJAD,
VORKI,
OLMLET, PUPPADILE, TEKTINY, VANGUARD, VASA_MINIRIO, VESPINA,
PET_DAGANNOTH_PRIME, PET_DAGANNOTH_REX, PET_DAGANNOTH_SUPREME,
PET_GENERAL_GRAARDOR, PET_KRIL_TSUTSAROTH, PET_KREEARRA, PET_ZILYANA,
ABYSSAL_ORPHAN,
HELLPUPPY,
PET_KRAKEN,
MIDNIGHT, NOON,
PET_SMOKE_DEVIL, PET_SMOKE_DEVIL_22663,
IKKLE_HYDRA, IKKLE_HYDRA_22748, IKKLE_HYDRA_22750, IKKLE_HYDRA_22752,
CALLISTO_CUB,
PET_CHAOS_ELEMENTAL,
SCORPIAS_OFFSPRING,
VENENATIS_SPIDERLING,
VETION_JR, VETION_JR_13180,
BABY_CHINCHOMPA, BABY_CHINCHOMPA_13324, BABY_CHINCHOMPA_13325, BABY_CHINCHOMPA_13326,
BEAVER,
GIANT_SQUIRREL,
HERON,
RIFT_GUARDIAN, RIFT_GUARDIAN_20667, RIFT_GUARDIAN_20669, RIFT_GUARDIAN_20671, RIFT_GUARDIAN_20673, RIFT_GUARDIAN_20675,
RIFT_GUARDIAN_20677, RIFT_GUARDIAN_20679, RIFT_GUARDIAN_20681, RIFT_GUARDIAN_20683, RIFT_GUARDIAN_20685, RIFT_GUARDIAN_20687,
RIFT_GUARDIAN_20689, RIFT_GUARDIAN_20691, RIFT_GUARDIAN_21990,
ROCK_GOLEM, ROCK_GOLEM_21187, ROCK_GOLEM_21188, ROCK_GOLEM_21189, ROCK_GOLEM_21190, ROCK_GOLEM_21191, ROCK_GOLEM_21192,
ROCK_GOLEM_21193, ROCK_GOLEM_21194, ROCK_GOLEM_21195, ROCK_GOLEM_21196, ROCK_GOLEM_21197, ROCK_GOLEM_21340, ROCK_GOLEM_21358,
ROCK_GOLEM_21359, ROCK_GOLEM_21360,
ROCKY,
TANGLEROOT,
PET_KITTEN, PET_KITTEN_1556, PET_KITTEN_1557, PET_KITTEN_1558, PET_KITTEN_1559, PET_KITTEN_1560,
PET_CAT, PET_CAT_1562, PET_CAT_1563, PET_CAT_1564, PET_CAT_1565, PET_CAT_1566, PET_CAT_1567, PET_CAT_1568, PET_CAT_1569,
PET_CAT_1570, PET_CAT_1571, PET_CAT_1572,
LAZY_CAT, LAZY_CAT_6550, LAZY_CAT_6551, LAZY_CAT_6552, LAZY_CAT_6553, LAZY_CAT_6554,
WILY_CAT, WILY_CAT_6556, WILY_CAT_6557, WILY_CAT_6558, WILY_CAT_6559, WILY_CAT_6560,
OVERGROWN_HELLCAT, HELL_CAT, HELLKITTEN, LAZY_HELL_CAT, WILY_HELLCAT,
BLOODHOUND,
CHOMPY_CHICK,
HERBI,
PET_PENANCE_QUEEN,
PHOENIX
);
public static boolean isPet(int id)
{
return PETS.contains(id);
}
}

View File

@@ -0,0 +1,163 @@
/*
* Copyright (c) 2018, TheStonedTurtle <https://github.com/TheStonedTurtle>
* 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.itemskeptondeath;
import net.runelite.api.ScriptEvent;
import net.runelite.api.SpriteID;
import net.runelite.api.widgets.JavaScriptCallback;
import net.runelite.api.widgets.Widget;
import net.runelite.api.widgets.WidgetType;
class WidgetButton
{
private static final int ICON_HEIGHT = 26;
private static final int ICON_WIDTH = 26;
private static final int BACKGROUND_HEIGHT = 32;
private static final int BACKGROUND_WIDTH = 32;
private static final int PADDING = 5;
private static final int ICON_PADDING = (BACKGROUND_HEIGHT - ICON_HEIGHT) / 2;
private static final int BACKGROUND_SPRITE_ID = SpriteID.EQUIPMENT_SLOT_TILE;
private static final int SELECTED_BACKGROUND_SPRITE_ID = SpriteID.EQUIPMENT_SLOT_SELECTED;
@FunctionalInterface
public interface WidgetButtonCallback
{
void run(boolean newState);
}
private final Widget parent;
private final String name;
private final int spriteID;
private boolean selected;
private final WidgetButtonCallback callback;
private Widget icon;
private Widget background;
WidgetButton(
final Widget parent,
final String name,
final int spriteID,
final boolean selectedStartState,
final WidgetButtonCallback callback)
{
this.parent = parent;
this.name = name;
this.spriteID = spriteID;
this.selected = selectedStartState;
this.callback = callback;
createBackgroundWidget();
createIconWidget();
}
private void createBackgroundWidget()
{
background = createWidget();
background.setOriginalWidth(BACKGROUND_WIDTH);
background.setOriginalHeight(BACKGROUND_HEIGHT);
syncBackgroundSprite();
}
private void createIconWidget()
{
icon = createWidget();
icon.setAction(1, "Toggle:");
icon.setOnOpListener((JavaScriptCallback) this::onButtonClicked);
icon.setOnMouseRepeatListener((JavaScriptCallback) e -> e.getSource().setOpacity(120));
icon.setOnMouseLeaveListener((JavaScriptCallback) e -> e.getSource().setOpacity(0));
icon.setHasListener(true);
icon.setSpriteId(spriteID);
}
private Widget createWidget()
{
final Widget w = parent.createChild(-1, WidgetType.GRAPHIC);
w.setOriginalWidth(ICON_WIDTH);
w.setOriginalHeight(ICON_HEIGHT);
w.setName("<col=ff981f>" + this.name);
return w;
}
public void setSelected(boolean selected)
{
this.selected = selected;
syncBackgroundSprite();
}
private void syncBackgroundSprite()
{
background.setSpriteId(selected ? SELECTED_BACKGROUND_SPRITE_ID : BACKGROUND_SPRITE_ID);
}
/**
* Adds the collection of WidgetButtons to the container overriding any existing children.
*
* @param container Widget to add buttons too
* @param buttons buttons to add
*/
static void layoutButtonsToContainer(final Widget container, final WidgetButton... buttons)
{
// Each button has two widgets, Icon and Background
final int xIncrement = BACKGROUND_WIDTH + PADDING;
final int yIncrement = BACKGROUND_HEIGHT + PADDING;
int maxRowItems = container.getWidth() / xIncrement;
// Ensure at least 1 button per row
maxRowItems = maxRowItems < 1 ? 1 : maxRowItems;
int index = 0;
for (final WidgetButton w : buttons)
{
if (w == null)
{
continue;
}
final int originalX = ((index % maxRowItems) * xIncrement);
final int originalY = ((index / maxRowItems) * yIncrement);
w.background.setOriginalX(originalX);
w.background.setOriginalY(originalY);
w.background.revalidate();
// Icon must be padded to center inside image
w.icon.setOriginalX(originalX + ICON_PADDING);
w.icon.setOriginalY(originalY + ICON_PADDING);
w.icon.revalidate();
index++;
}
final int numButtons = index;
final int rows = 1 + (numButtons > maxRowItems ? numButtons / maxRowItems : 0);
container.setOriginalHeight(yIncrement * rows);
container.revalidate();
}
private void onButtonClicked(ScriptEvent scriptEvent)
{
setSelected(!selected);
callback.run(selected);
}
}

View File

@@ -92,6 +92,16 @@ public interface ItemStatConfig extends Config
return false;
}
@ConfigItem(
keyName = "showWeight",
name = "Show Weight",
description = "Show weight in tooltip"
)
default boolean showWeight()
{
return true;
}
@ConfigItem(
keyName = "colorBetterUncapped",
name = "Better (Uncapped)",

View File

@@ -189,7 +189,10 @@ public class ItemStatOverlay extends Overlay
private String buildStatBonusString(ItemStats s)
{
final StringBuilder b = new StringBuilder();
b.append(getChangeString("Weight", s.getWeight(), true, false));
if (config.showWeight())
{
b.append(getChangeString("Weight", s.getWeight(), true, false));
}
ItemStats other = null;
final ItemEquipmentStats currentEquipment = s.getEquipment();

View File

@@ -35,6 +35,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import net.runelite.api.Client;
import net.runelite.api.Constants;
import net.runelite.api.FontID;
import net.runelite.api.InventoryID;
import net.runelite.api.Item;
@@ -232,8 +233,8 @@ public class ItemStatPlugin extends Plugin
Widget icon = invContainer.createChild(-1, WidgetType.GRAPHIC);
icon.setOriginalX(8);
icon.setOriginalY(yPos);
icon.setOriginalWidth(36);
icon.setOriginalHeight(32);
icon.setOriginalWidth(Constants.ITEM_SPRITE_WIDTH);
icon.setOriginalHeight(Constants.ITEM_SPRITE_HEIGHT);
icon.setItemId(id);
icon.setItemQuantityMode(0);
icon.setBorderType(1);

View File

@@ -179,9 +179,9 @@ public class KourendLibraryPlugin extends Plugin
@Subscribe
public void onMenuOptionClicked(MenuOptionClicked menuOpt)
{
if (MenuAction.GAME_OBJECT_FIRST_OPTION == menuOpt.getMenuAction() && menuOpt.getMenuTarget().contains("Bookshelf"))
if (MenuAction.GAME_OBJECT_FIRST_OPTION == menuOpt.getMenuAction() && menuOpt.getTarget().contains("Bookshelf"))
{
lastBookcaseClick = WorldPoint.fromScene(client, menuOpt.getActionParam(), menuOpt.getWidgetId(), client.getPlane());
lastBookcaseClick = WorldPoint.fromScene(client, menuOpt.getActionParam0(), menuOpt.getActionParam1(), client.getPlane());
overlay.setHidden(false);
}
}

View File

@@ -41,10 +41,10 @@ import net.runelite.client.ui.overlay.components.ComponentOrientation;
import net.runelite.client.ui.overlay.components.ImageComponent;
import net.runelite.client.ui.overlay.components.PanelComponent;
class LootingBagViewerOverlay extends Overlay
public class LootingBagViewerOverlay extends Overlay
{
private static final int INVENTORY_SIZE = 28;
private static final int PLACEHOLDER_WIDTH = 36;
public static final int PLACEHOLDER_WIDTH = 36;
private static final int PLACEHOLDER_HEIGHT = 32;
private static final ImageComponent PLACEHOLDER_IMAGE = new ImageComponent(new BufferedImage(PLACEHOLDER_WIDTH, PLACEHOLDER_HEIGHT, BufferedImage.TYPE_4BYTE_ABGR));

View File

@@ -35,7 +35,9 @@ public interface LootTrackerConfig extends Config
@ConfigItem(
keyName = "ignoredItems",
name = "Ignored items",
description = "Configures which items should be ignored when calculating loot prices."
description = "Configures which items should be ignored when calculating loot prices.",
position = 0,
group = "Filters"
)
default String getIgnoredItems()
{
@@ -91,6 +93,7 @@ public interface LootTrackerConfig extends Config
{
return true;
}
@ConfigItem(
keyName = "sortType",
name = "Sorting",
@@ -101,4 +104,59 @@ public interface LootTrackerConfig extends Config
return LootRecordSortType.TIMESTAMP;
}
@ConfigItem(
keyName = "whitelistEnabled",
name = "NPC Whitelist",
description = "Only track drops from specific NPCs",
position = 1,
group = "Filters",
disabledBy = "blacklistEnabled"
)
default boolean whitelistEnabled()
{
return false;
}
@ConfigItem(
keyName = "getWhitelist",
name = "Whitelist",
description = "Comma-separated list of NPCs to track drops from",
position = 2,
group = "Filters",
hidden = true,
unhide = "whitelistEnabled"
)
default String getWhitelist()
{
return "";
}
@ConfigItem(
keyName = "blacklistEnabled",
name = "NPC Blacklist",
description = "Track drops from all NPCs except for specified ones",
position = 3,
group = "Filters",
disabledBy = "whitelistEnabled"
)
default boolean blacklistEnabled()
{
return false;
}
@ConfigItem(
keyName = "getBlacklist",
name = "Blacklist",
description = "Comma-separated list of NPCs to not track drops from",
position = 4,
group = "Filters",
hidden = true,
unhide = "blacklistEnabled"
)
default String getBlacklist()
{
return "";
}
}

View File

@@ -323,13 +323,14 @@ public class LootTrackerPlugin extends Plugin
log.debug("Loaded {} remote data entries", lootRecords.size());
}
if (config.localPersistence() )
if (config.localPersistence())
{
try
{
lootRecords.addAll(RuneLiteAPI.GSON.fromJson(new FileReader(LOOT_RECORDS_FILE),
new TypeToken<ArrayList<LootRecord>>()
{ }.getType()));
{
}.getType()));
}
catch (IOException | NullPointerException e)
{
@@ -370,8 +371,28 @@ public class LootTrackerPlugin extends Plugin
final int combat = npc.getCombatLevel();
final LootTrackerItem[] entries = buildEntries(stack(items));
String localUsername = client.getLocalPlayer().getName();
if (config.whitelistEnabled())
{
final String configNpcs = config.getWhitelist().toLowerCase();
List<String> whitelist = Text.fromCSV(configNpcs);
if (!whitelist.contains(name.toLowerCase()))
{
return;
}
}
else if (config.blacklistEnabled())
{
final String configNpcs = config.getBlacklist().toLowerCase();
List<String> blacklist = Text.fromCSV(configNpcs);
if (blacklist.contains(name.toLowerCase()))
{
return;
}
}
SwingUtilities.invokeLater(() -> panel.add(name, localUsername, combat, entries));
LootRecord lootRecord = new LootRecord( name, localUsername, LootRecordType.NPC,
LootRecord lootRecord = new LootRecord(name, localUsername, LootRecordType.NPC,
toGameItems(items), Instant.now());
if (lootTrackerClient != null && config.saveLoot())
@@ -404,7 +425,7 @@ public class LootTrackerPlugin extends Plugin
final LootTrackerItem[] entries = buildEntries(stack(items));
String localUsername = client.getLocalPlayer().getName();
SwingUtilities.invokeLater(() -> panel.add(name, localUsername, combat, entries));
LootRecord lootRecord = new LootRecord( name, localUsername, LootRecordType.PLAYER,
LootRecord lootRecord = new LootRecord(name, localUsername, LootRecordType.PLAYER,
toGameItems(items), Instant.now());
if (lootTrackerClient != null && config.saveLoot())
{
@@ -599,7 +620,7 @@ public class LootTrackerPlugin extends Plugin
SwingUtilities.invokeLater(() -> panel.add(name, client.getLocalPlayer().getName(),
client.getLocalPlayer().getCombatLevel(), entries));
LootRecord lootRecord = new LootRecord(name, client.getLocalPlayer().getName(), LootRecordType.DEATH,
toGameItems(itemsLost), Instant.now());
toGameItems(itemsLost), Instant.now());
if (lootTrackerClient != null && config.saveLoot())
{
lootTrackerClient.submit(lootRecord);
@@ -685,10 +706,10 @@ public class LootTrackerPlugin extends Plugin
.forEach(item -> inventorySnapshot.add(item.getId(), item.getQuantity()));
}
if (equipment != null)
{
Arrays.stream(equipment.getItems())
.forEach(item -> inventorySnapshot.add(item.getId(), item.getQuantity()));
if (equipment != null)
{
Arrays.stream(equipment.getItems())
.forEach(item -> inventorySnapshot.add(item.getId(), item.getQuantity()));
}
}

View File

@@ -474,20 +474,20 @@ public class MenuEntrySwapperPlugin extends Plugin
@Subscribe
public void onMenuOptionClicked(MenuOptionClicked event)
{
if (event.getMenuAction() != MenuAction.RUNELITE || event.getWidgetId() != WidgetInfo.INVENTORY.getId())
if (event.getMenuAction() != MenuAction.RUNELITE || event.getActionParam1() != WidgetInfo.INVENTORY.getId())
{
return;
}
int itemId = event.getId();
int itemId = event.getIdentifier();
if (itemId == -1)
{
return;
}
String option = event.getMenuOption();
String target = event.getMenuTarget();
String option = event.getOption();
String target = event.getTarget();
ItemDefinition itemComposition = client.getItemDefinition(itemId);
if (option.equals(RESET) && target.equals(MENU_TARGET))
@@ -862,7 +862,7 @@ public class MenuEntrySwapperPlugin extends Plugin
}
}
}
else if (target.equals("magpie impling jar") || (target.equals("nature impling jar")))
else if (target.equals("magpie impling jar") || (target.equals("nature impling jar")) || (target.equals("ninja impling jar")))
{
if (client.getItemContainer(InventoryID.INVENTORY) != null)
{
@@ -1309,7 +1309,17 @@ public class MenuEntrySwapperPlugin extends Plugin
if (!Strings.isNullOrEmpty(config))
{
Map<String, String> split = NEWLINE_SPLITTER.withKeyValueSeparator(':').split(config);
StringBuilder sb = new StringBuilder();
for (String str : config.split("\n"))
{
if (!str.startsWith("//"))
{
sb.append(str + "\n");
}
}
Map<String, String> split = NEWLINE_SPLITTER.withKeyValueSeparator(':').split(sb);
for (Map.Entry<String, String> entry : split.entrySet())
{

View File

@@ -32,12 +32,22 @@ public class Parse
{
try
{
StringBuilder sb = new StringBuilder();
for (String str : value.split("\n"))
{
if (!str.startsWith("//"))
{
sb.append(str + "\n");
}
}
Splitter NEWLINE_SPLITTER = Splitter
.on("\n")
.omitEmptyStrings()
.trimResults();
NEWLINE_SPLITTER.withKeyValueSeparator(':').split(value);
NEWLINE_SPLITTER.withKeyValueSeparator(':').split(sb);
return true;
}
catch (IllegalArgumentException ex)

View File

@@ -47,7 +47,7 @@ class MiningOverlay extends Overlay
{
// Range of Motherlode vein respawn time not 100% confirmed but based on observation
@Getter(AccessLevel.PACKAGE)
private static final int ORE_VEIN_MAX_RESPAWN_TIME = 123;
public static final int ORE_VEIN_MAX_RESPAWN_TIME = 123;
private static final int ORE_VEIN_MIN_RESPAWN_TIME = 90;
private static final float ORE_VEIN_RANDOM_PERCENT_THRESHOLD = (float) ORE_VEIN_MIN_RESPAWN_TIME / ORE_VEIN_MAX_RESPAWN_TIME;
private static final Color DARK_GREEN = new Color(0, 100, 0);

View File

@@ -168,6 +168,7 @@ public class MiningPlugin extends Plugin
case ORE_VEIN_26663: // Motherlode vein
case ORE_VEIN_26664: // Motherlode vein
{
// If the vein respawns before the timer is up, remove it
final WorldPoint point = object.getWorldLocation();
respawns.removeIf(rockRespawn -> rockRespawn.getWorldPoint().equals(point));
break;

View File

@@ -49,6 +49,7 @@ import static net.runelite.api.ObjectID.ROCKS_11376;
import static net.runelite.api.ObjectID.ROCKS_11377;
import static net.runelite.api.ObjectID.ROCKS_11386;
import static net.runelite.api.ObjectID.ROCKS_11387;
import static net.runelite.api.ObjectID.ASH_PILE;
enum Rock
{
@@ -98,8 +99,9 @@ enum Rock
return inMiningGuild ? Duration.ofMinutes(6) : super.respawnTime;
}
},
ORE_VEIN(Duration.ofSeconds(MiningOverlay.getORE_VEIN_MAX_RESPAWN_TIME()), 150),
AMETHYST(Duration.ofSeconds(75), 120);
ORE_VEIN(Duration.ofSeconds(MiningOverlay.ORE_VEIN_MAX_RESPAWN_TIME), 150),
AMETHYST(Duration.ofSeconds(75), 120),
ASH_VEIN(Duration.ofSeconds(30), 0, ASH_PILE);
private static final Map<Integer, Rock> ROCKS;

View File

@@ -328,11 +328,11 @@ public class MotherlodePlugin extends Plugin
return;
}
if (MINE_SPOTS.contains(menu.getId()) && menu.getMenuAction() == MenuAction.GAME_OBJECT_FIRST_OPTION)
if (MINE_SPOTS.contains(menu.getIdentifier()) && menu.getMenuAction() == MenuAction.GAME_OBJECT_FIRST_OPTION)
{
resetIdleChecks();
int veinX = menu.getActionParam();
int veinY = menu.getWidgetId();
int veinX = menu.getActionParam0();
int veinY = menu.getActionParam1();
targetVeinLocation = WorldPoint.fromScene(client, veinX, veinY, client.getPlane());
}
}

View File

@@ -1,5 +1,6 @@
/*
* Copyright (c) 2018, Woox <https://github.com/wooxsolo>
* Copyright (c) 2019, Enza-Denino <https://github.com/Enza-Denino>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -34,11 +35,12 @@ import net.runelite.api.Constants;
public class MapLocations
{
private static final List<Shape>[] MULTICOMBAT = new List[Constants.MAX_Z];
private static final List<Shape>[] NOT_MULTICOMBAT = new List[Constants.MAX_Z];
private static final List<Shape>[] ROUGH_WILDERNESS = new List[Constants.MAX_Z];
private static final List<Shape>[] DEADMAN_SAFE_ZONES = new List[Constants.MAX_Z];
private static final List<Shape>[] PVP_WORLD_SAFE_ZONES = new List[Constants.MAX_Z];
private static final List<Shape>[] MULTICOMBAT = new List[Constants.MAX_Z];
private static final List<Shape>[] NOT_MULTICOMBAT = new List[Constants.MAX_Z];
private static final List<Shape>[] ROUGH_WILDERNESS = new List[Constants.MAX_Z];
private static final List<Shape>[] WILDERNESS_LEVEL_LINES = new List[Constants.MAX_Z];
private static final List<Shape>[] DEADMAN_SAFE_ZONES = new List[Constants.MAX_Z];
private static final List<Shape>[] PVP_WORLD_SAFE_ZONES = new List[Constants.MAX_Z];
private static Area getArea(List<Shape> shapes)
{
@@ -87,6 +89,16 @@ public class MapLocations
return getArea(ROUGH_WILDERNESS[plane], view);
}
public static Area getWildernessLevelLines(int plane)
{
return getArea(WILDERNESS_LEVEL_LINES[plane]);
}
public static Area getWildernessLevelLines(Rectangle view, int plane)
{
return getArea(WILDERNESS_LEVEL_LINES[plane], view);
}
public static Area getDeadmanSafeZones(int plane)
{
return getArea(DEADMAN_SAFE_ZONES[plane]);
@@ -107,33 +119,28 @@ public class MapLocations
return getArea(PVP_WORLD_SAFE_ZONES[plane], view);
}
private static void initializeWithEmptyLists(List<Shape>[] array)
{
for (int i = 0; i < array.length; i++)
{
array[i] = new ArrayList<>();
}
}
static
{
for (int i = 0; i < MULTICOMBAT.length; i++)
{
MULTICOMBAT[i] = new ArrayList<>();
}
for (int i = 0; i < NOT_MULTICOMBAT.length; i++)
{
NOT_MULTICOMBAT[i] = new ArrayList<>();
}
for (int i = 0; i < ROUGH_WILDERNESS.length; i++)
{
ROUGH_WILDERNESS[i] = new ArrayList<>();
}
for (int i = 0; i < DEADMAN_SAFE_ZONES.length; i++)
{
DEADMAN_SAFE_ZONES[i] = new ArrayList<>();
}
for (int i = 0; i < PVP_WORLD_SAFE_ZONES.length; i++)
{
PVP_WORLD_SAFE_ZONES[i] = new ArrayList<>();
}
initializeWithEmptyLists(MULTICOMBAT);
initializeWithEmptyLists(NOT_MULTICOMBAT);
initializeWithEmptyLists(ROUGH_WILDERNESS);
initializeWithEmptyLists(WILDERNESS_LEVEL_LINES);
initializeWithEmptyLists(DEADMAN_SAFE_ZONES);
initializeWithEmptyLists(PVP_WORLD_SAFE_ZONES);
defineMulticombatAreas();
defineDeadmanSafeZones();
definePvpSafeZones();
defineWilderness();
defineWildernessLevelLines();
}
private static void defineMulticombatAreas()
@@ -3441,6 +3448,33 @@ public class MapLocations
3264, 9918);
}
private static void defineWildernessLevelLines()
{
int wildyLeftX = 2944;
int wildyRightX = 3392;
int wildyBottomY = 3525;
int wildyTopY = 3971;
// define wilderness level lines at ground level
int accumulatedY = 0;
for (int level = 1; level <= 56; level++)
{
int levelTiles = level == 1 ? 3 : 8;
// only draw every 2 levels, otherwise lines on two adjacent levels will collide
// and it will not show up
if (level % 2 != 0)
{
addPolygonTo(WILDERNESS_LEVEL_LINES,
wildyLeftX, wildyBottomY + accumulatedY,
wildyRightX, wildyBottomY + accumulatedY,
wildyRightX, wildyBottomY + accumulatedY + levelTiles,
wildyLeftX, wildyBottomY + accumulatedY + levelTiles);
}
accumulatedY += levelTiles;
}
}
private static void addPolygonTo(List<Shape>[] shapes, int... coords)
{
Polygon poly = new Polygon();
@@ -3476,4 +3510,4 @@ public class MapLocations
shapes[i].add(poly);
}
}
}
}

View File

@@ -1,5 +1,6 @@
/*
* Copyright (c) 2018, Woox <https://github.com/wooxsolo>
* Copyright (c) 2019, Enza-Denino <https://github.com/Enza-Denino>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -66,14 +67,14 @@ public interface MultiIndicatorsConfig extends Config
}
@ConfigItem(
keyName = "collisionDetection",
name = "Collision detection",
description = "Only show lines where they can be walked through",
keyName = "wildernessLevelLines",
name = "Wilderness level lines",
description = "Show wilderness level lines",
position = 4
)
default boolean collisionDetection()
default boolean showWildernessLevelLines()
{
return false;
return true;
}
@ConfigItem(
@@ -108,4 +109,16 @@ public interface MultiIndicatorsConfig extends Config
{
return Color.GREEN;
}
@ConfigItem(
keyName = "wildernessLevelLinesColor",
name = "Wilderness level lines color",
description = "Choose color to use for marking wilderness level lines",
position = 8
)
default Color wildernessLevelLinesColor()
{
return Color.WHITE;
}
}

View File

@@ -1,5 +1,6 @@
/*
* Copyright (c) 2018, Woox <https://github.com/wooxsolo>
* Copyright (c) 2019, Enza-Denino <https://github.com/Enza-Denino>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -102,6 +103,7 @@ public class MultiIndicatorsMinimapOverlay extends Overlay
GeneralPath multicombatPath = plugin.getMulticombatPathToDisplay()[client.getPlane()];
GeneralPath pvpPath = plugin.getPvpPathToDisplay()[client.getPlane()];
GeneralPath wildernessLevelLinesPath = plugin.getWildernessLevelLinesPathToDisplay()[client.getPlane()];
if (config.multicombatZoneVisibility() != ZoneVisibility.HIDE && multicombatPath != null)
{
@@ -111,6 +113,10 @@ public class MultiIndicatorsMinimapOverlay extends Overlay
{
renderPath(graphics, pvpPath, getTransparentColorVersion(config.safeZoneColor()));
}
if (config.showWildernessLevelLines() && wildernessLevelLinesPath != null)
{
renderPath(graphics, wildernessLevelLinesPath, getTransparentColorVersion(config.wildernessLevelLinesColor()));
}
return null;
}

View File

@@ -1,5 +1,6 @@
/*
* Copyright (c) 2018, Woox <https://github.com/wooxsolo>
* Copyright (c) 2019, Enza-Denino <https://github.com/Enza-Denino>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -98,6 +99,7 @@ public class MultiIndicatorsOverlay extends Overlay
{
GeneralPath multicombatPath = plugin.getMulticombatPathToDisplay()[client.getPlane()];
GeneralPath pvpPath = plugin.getPvpPathToDisplay()[client.getPlane()];
GeneralPath wildernessLevelLinesPath = plugin.getWildernessLevelLinesPathToDisplay()[client.getPlane()];
if (config.multicombatZoneVisibility() != ZoneVisibility.HIDE && multicombatPath != null)
{
@@ -107,6 +109,10 @@ public class MultiIndicatorsOverlay extends Overlay
{
renderPath(graphics, pvpPath, getTransparentColorVersion(config.safeZoneColor()));
}
if (config.showWildernessLevelLines() && wildernessLevelLinesPath != null)
{
renderPath(graphics, wildernessLevelLinesPath, getTransparentColorVersion(config.wildernessLevelLinesColor()));
}
return null;
}

View File

@@ -1,5 +1,6 @@
/*
* Copyright (c) 2018, Woox <https://github.com/wooxsolo>
* Copyright (c) 2019, Enza-Denino <https://github.com/Enza-Denino>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,6 +28,7 @@ package net.runelite.client.plugins.multiindicators;
import com.google.inject.Provides;
import java.awt.Rectangle;
import java.awt.geom.GeneralPath;
import java.time.temporal.ChronoUnit;
import java.util.Arrays;
import javax.inject.Inject;
import lombok.Getter;
@@ -50,6 +52,7 @@ import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.plugins.PluginType;
import net.runelite.client.task.Schedule;
import net.runelite.client.ui.overlay.OverlayManager;
@PluginDescriptor(
@@ -86,6 +89,9 @@ public class MultiIndicatorsPlugin extends Plugin
@Getter
private GeneralPath[] pvpPathToDisplay;
@Getter
private GeneralPath[] wildernessLevelLinesPathToDisplay;
@Getter
private boolean inPvp;
@@ -106,8 +112,7 @@ public class MultiIndicatorsPlugin extends Plugin
overlayManager.add(overlay);
overlayManager.add(minimapOverlay);
multicombatPathToDisplay = new GeneralPath[Constants.MAX_Z];
pvpPathToDisplay = new GeneralPath[Constants.MAX_Z];
initializePaths();
clientThread.invokeLater(() ->
{
@@ -124,8 +129,37 @@ public class MultiIndicatorsPlugin extends Plugin
overlayManager.remove(overlay);
overlayManager.remove(minimapOverlay);
uninitializePaths();
}
private void initializePaths()
{
multicombatPathToDisplay = new GeneralPath[Constants.MAX_Z];
pvpPathToDisplay = new GeneralPath[Constants.MAX_Z];
wildernessLevelLinesPathToDisplay = new GeneralPath[Constants.MAX_Z];
}
private void uninitializePaths()
{
multicombatPathToDisplay = null;
pvpPathToDisplay = null;
wildernessLevelLinesPathToDisplay = null;
}
// sometimes the lines get offset (seems to happen when there is a delay
// due to map reloading when walking/running "Loading - please wait")
// resetting the lines generation logic fixes this
@Schedule(
period = 1800,
unit = ChronoUnit.MILLIS
)
public void update()
{
if (client.getGameState() == GameState.LOGGED_IN)
{
findLinesInScene();
}
}
private void transformWorldToLocal(float[] coords)
@@ -134,7 +168,6 @@ public class MultiIndicatorsPlugin extends Plugin
coords[0] = lp.getX() - Perspective.LOCAL_TILE_SIZE / 2;
coords[1] = lp.getY() - Perspective.LOCAL_TILE_SIZE / 2;
}
private boolean isOpenableAt(WorldPoint wp)
{
int sceneX = wp.getX() - client.getBaseX();
@@ -153,6 +186,7 @@ public class MultiIndicatorsPlugin extends Plugin
}
ObjectDefinition objectComposition = client.getObjectDefinition(wallObject.getId());
if (objectComposition == null)
{
return false;
@@ -240,7 +274,7 @@ public class MultiIndicatorsPlugin extends Plugin
lines = Geometry.clipPath(lines, MapLocations.getRoughWilderness(i));
}
lines = Geometry.splitIntoSegments(lines, 1);
if (config.collisionDetection())
if (useCollisionLogic())
{
lines = Geometry.filterPath(lines, this::collisionFilter);
}
@@ -267,7 +301,7 @@ public class MultiIndicatorsPlugin extends Plugin
{
safeZonePath = Geometry.clipPath(safeZonePath, sceneRect);
safeZonePath = Geometry.splitIntoSegments(safeZonePath, 1);
if (config.collisionDetection())
if (useCollisionLogic())
{
safeZonePath = Geometry.filterPath(safeZonePath, this::collisionFilter);
}
@@ -275,6 +309,35 @@ public class MultiIndicatorsPlugin extends Plugin
}
pvpPathToDisplay[i] = safeZonePath;
}
// Generate wilderness level lines
for (int i = 0; i < wildernessLevelLinesPathToDisplay.length; i++)
{
currentPlane = i;
GeneralPath wildernessLevelLinesPath = null;
if (config.showWildernessLevelLines())
{
wildernessLevelLinesPath = new GeneralPath(MapLocations.getWildernessLevelLines(sceneRect, i));
}
if (wildernessLevelLinesPath != null)
{
wildernessLevelLinesPath = Geometry.clipPath(wildernessLevelLinesPath, sceneRect);
wildernessLevelLinesPath = Geometry.splitIntoSegments(wildernessLevelLinesPath, 1);
if (useCollisionLogic())
{
wildernessLevelLinesPath = Geometry.filterPath(wildernessLevelLinesPath, this::collisionFilter);
}
wildernessLevelLinesPath = Geometry.transformPath(wildernessLevelLinesPath, this::transformWorldToLocal);
}
wildernessLevelLinesPathToDisplay[i] = wildernessLevelLinesPath;
}
}
private boolean useCollisionLogic()
{
// currently prevents overlay lines from showing up if this is ever enabled right now
return false;
}
@Subscribe
@@ -283,7 +346,8 @@ public class MultiIndicatorsPlugin extends Plugin
if (event.getKey().equals("collisionDetection") ||
event.getKey().equals("multicombatZoneVisibility") ||
event.getKey().equals("deadmanSafeZones") ||
event.getKey().equals("pvpSafeZones"))
event.getKey().equals("pvpSafeZones") ||
event.getKey().equals("wildernessLevelLines"))
{
findLinesInScene();
}

View File

@@ -40,4 +40,4 @@ public enum ZoneVisibility
{
return visibility;
}
}
}

View File

@@ -286,13 +286,13 @@ public class NpcIndicatorsPlugin extends Plugin
public void onMenuOptionClicked(MenuOptionClicked click)
{
if (click.getMenuAction() != MenuAction.RUNELITE
|| (!click.getMenuOption().equals(TAG)
&& !click.getMenuOption().equals(UNTAG)))
|| (!click.getOption().equals(TAG)
&& !click.getOption().equals(UNTAG)))
{
return;
}
final int id = click.getId();
final int id = click.getIdentifier();
final boolean removed = npcTags.remove(id);
final NPC[] cachedNPCs = client.getCachedNPCs();
final NPC npc = cachedNPCs[id];

View File

@@ -272,20 +272,20 @@ public class ObjectIndicatorsPlugin extends Plugin implements KeyListener
public void onMenuOptionClicked(MenuOptionClicked event)
{
if (event.getMenuAction() != MenuAction.RUNELITE
|| (!event.getMenuOption().equals(MARK)
&& !event.getMenuOption().equals(UNMARK)))
|| (!event.getOption().equals(MARK)
&& !event.getOption().equals(UNMARK)))
{
return;
}
Scene scene = client.getScene();
Tile[][][] tiles = scene.getTiles();
final int x = event.getActionParam();
final int y = event.getWidgetId();
final int x = event.getActionParam0();
final int y = event.getActionParam1();
final int z = client.getPlane();
final Tile tile = tiles[z][x][y];
TileObject object = findTileObject(tile, event.getId());
TileObject object = findTileObject(tile, event.getIdentifier());
if (object == null)
{
return;

View File

@@ -73,6 +73,8 @@ import net.runelite.client.util.Text;
)
public class PestControlPlugin extends Plugin
{
private static final int VOID_KNIGHTS_OUTPOST = 10537;
private final int NOVICE_GANGPLANK = 14315; // Combat 40+ (3 points)
private final int INTERMEDIATE_GANGPLANK = 25631; // Combat 70+ (4 points)
private final int VETERAN_GANGPLANK = 25632; // Combat 100+ (5 points)
@@ -662,6 +664,10 @@ public class PestControlPlugin extends Plugin
boolean isOnPestControlMainIsland()
{
return client.getLocalPlayer().getWorldLocation().getRegionID() == 10537;
if (client.getLocalPlayer() != null)
{
return client.getLocalPlayer().getWorldLocation().getRegionID() == VOID_KNIGHTS_OUTPOST;
}
return false;
}
}

View File

@@ -35,10 +35,10 @@ import net.runelite.client.config.Stub;
public interface PileIndicatorsConfig extends Config
{
@ConfigItem(
keyName = "playerPilesStub",
name = "Player Piles",
description = "",
position = 0
keyName = "playerPilesStub",
name = "Player Piles",
description = "",
position = 0
)
default Stub playerPilesStub()
{
@@ -46,11 +46,11 @@ public interface PileIndicatorsConfig extends Config
}
@ConfigItem(
position = 1,
keyName = "enablePlayers",
name = "Enable Player Piling",
description = "Enable the option to highlight players when they pile.",
parent = "playerPilesStub"
position = 1,
keyName = "enablePlayers",
name = "Enable Player Piling",
description = "Enable the option to highlight players when they pile.",
parent = "playerPilesStub"
)
default boolean enablePlayers()
{
@@ -58,11 +58,11 @@ public interface PileIndicatorsConfig extends Config
}
@ConfigItem(
position = 2,
keyName = "wildyOnlyPlayer",
name = "Wilderness Only",
description = "Show player piling only when in the Wilderness.",
parent = "playerPilesStub"
position = 2,
keyName = "wildyOnlyPlayer",
name = "Wilderness Only",
description = "Show player piling only when in the Wilderness.",
parent = "playerPilesStub"
)
default boolean wildyOnlyPlayer()
{
@@ -70,22 +70,22 @@ public interface PileIndicatorsConfig extends Config
}
@ConfigItem(
position = 3,
keyName = "playerPileColor",
name = "Player Pile Color",
description = "Color used for player piles.",
parent = "playerPilesStub"
position = 3,
keyName = "playerPileColor",
name = "Player Pile Color",
description = "Color used for player piles.",
parent = "playerPilesStub"
)
default Color playerPileColor()
{
return Color.RED;
}
@ConfigItem(
keyName = "npcPilesStub",
name = "NPC Piles",
description = "",
position = 4
keyName = "npcPilesStub",
name = "NPC Piles",
description = "",
position = 4
)
default Stub npcPilesStub()
{
@@ -93,11 +93,11 @@ public interface PileIndicatorsConfig extends Config
}
@ConfigItem(
position = 5,
keyName = "enableNPCS",
name = "Enable NPC Piling",
description = "Enable the option to highlight NPCs when they pile.",
parent = "npcPilesStub"
position = 5,
keyName = "enableNPCS",
name = "Enable NPC Piling",
description = "Enable the option to highlight NPCs when they pile.",
parent = "npcPilesStub"
)
default boolean enableNPCS()
{
@@ -105,11 +105,11 @@ public interface PileIndicatorsConfig extends Config
}
@ConfigItem(
position = 6,
keyName = "npcPileColor",
name = "NPC Pile Color",
description = "Color used for NPC piles.",
parent = "npcPilesStub"
position = 6,
keyName = "npcPileColor",
name = "NPC Pile Color",
description = "Color used for NPC piles.",
parent = "npcPilesStub"
)
default Color npcPileColor()
{
@@ -117,10 +117,10 @@ public interface PileIndicatorsConfig extends Config
}
@ConfigItem(
keyName = "mixedPilesStub",
name = "Mixed Piles",
description = "",
position = 7
keyName = "mixedPilesStub",
name = "Mixed Piles",
description = "",
position = 7
)
default Stub mixedPilesStub()
{
@@ -128,11 +128,11 @@ public interface PileIndicatorsConfig extends Config
}
@ConfigItem(
position = 8,
keyName = "mixedPileColor",
name = "Mixed Pile Color",
description = "Color used for mixed piles.",
parent = "mixedPilesStub"
position = 8,
keyName = "mixedPileColor",
name = "Mixed Pile Color",
description = "Color used for mixed piles.",
parent = "mixedPilesStub"
)
default Color mixedPileColor()
{
@@ -140,10 +140,10 @@ public interface PileIndicatorsConfig extends Config
}
@ConfigItem(
keyName = "pilesSizeStub",
name = "Pile size",
description = "",
position = 9
keyName = "pilesSizeStub",
name = "Pile size",
description = "",
position = 9
)
default Stub pilesSizeStub()
{
@@ -151,14 +151,14 @@ public interface PileIndicatorsConfig extends Config
}
@Range(
min = 2
min = 2
)
@ConfigItem(
position = 10,
keyName = "minimumPileSize",
name = "Minimum Pile Size",
description = "Any pile under this size will not show up. (Minimum: 2)",
parent = "pilesSizeStub"
position = 10,
keyName = "minimumPileSize",
name = "Minimum Pile Size",
description = "Any pile under this size will not show up. (Minimum: 2)",
parent = "pilesSizeStub"
)
default int minimumPileSize()
{
@@ -166,10 +166,10 @@ public interface PileIndicatorsConfig extends Config
}
@ConfigItem(
keyName = "miscellaneousStub",
name = "Miscellaneous",
description = "",
position = 11
keyName = "miscellaneousStub",
name = "Miscellaneous",
description = "",
position = 11
)
default Stub miscellaneousStub()
{
@@ -177,14 +177,39 @@ public interface PileIndicatorsConfig extends Config
}
@ConfigItem(
position = 12,
keyName = "numberOnly",
name = "Display Number Only",
description = "Shorten \"PILE SIZE: 1\" to \"1\"",
parent = "miscellaneousStub"
position = 12,
keyName = "numberOnly",
name = "Display Number Only",
description = "Shorten \"PILE SIZE: 1\" to \"1\"",
parent = "miscellaneousStub"
)
default boolean numberOnly()
{
return false;
}
@ConfigItem(
position = 13,
keyName = "drawPileTile",
name = "Draw Pile Tile",
description = "Draws the tile of the pile for best visibility.",
parent = "miscellaneousStub"
)
default boolean drawPileTile()
{
return true;
}
@ConfigItem(
position = 14,
keyName = "drawPileHull",
name = "Draw Pile Convex Hull",
description = "Draws the hull of the pile for best visibility.",
parent = "miscellaneousStub"
)
default boolean drawPileHull()
{
return false;
}
}

View File

@@ -26,11 +26,15 @@ package net.runelite.client.plugins.pileindicators;
import net.runelite.api.Actor;
import net.runelite.api.Client;
import net.runelite.client.ui.overlay.*;
import javax.inject.Inject;
import java.awt.*;
import java.util.ArrayList;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayLayer;
import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.OverlayPriority;
import net.runelite.client.ui.overlay.OverlayUtil;
public class PileIndicatorsOverlay extends Overlay
{
@@ -65,22 +69,21 @@ public class PileIndicatorsOverlay extends Overlay
PileType pileType = plugin.getPileType(actorArrayList);
Color pileColor = plugin.getColorByPileType(pileType);
try
try
{
Actor actorToRender = actorArrayList.get(0); //guaranteed to have at least two players
final String text;
if (config.numberOnly())
final String pileTypeStr = pileType == PileType.PLAYER_PILE ? "PLAYER" : pileType == PileType.NPC_PILE ? "NPC" : pileType == PileType.MIXED_PILE ? "MIXED" : "";
final String text = config.numberOnly() ? "" + actorArrayList.size() : (pileTypeStr + " PILE SIZE: " + actorArrayList.size());
if (config.drawPileTile())
{
text = "" + actorArrayList.size();
OverlayUtil.renderPolygon(graphics, actorToRender.getCanvasTilePoly(), pileColor);
}
else
if (config.drawPileHull())
{
text = "PILE SIZE: " + actorArrayList.size();
OverlayUtil.renderPolygon(graphics, actorToRender.getConvexHull(), pileColor);
}
OverlayUtil.renderPolygon(graphics, actorToRender.getCanvasTilePoly(), pileColor);
OverlayUtil.renderTextLocation(graphics, actorToRender.getCanvasTextLocation(graphics, text, 40), text, pileColor);
}
}
catch (Exception ignored)
{
}
@@ -89,4 +92,5 @@ public class PileIndicatorsOverlay extends Overlay
return null;
}
}

View File

@@ -27,7 +27,11 @@ package net.runelite.client.plugins.pileindicators;
import com.google.inject.Binder;
import com.google.inject.Provides;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.*;
import net.runelite.api.Actor;
import net.runelite.api.Client;
import net.runelite.api.NPC;
import net.runelite.api.Player;
import net.runelite.api.Varbits;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
@@ -40,11 +44,11 @@ import java.awt.*;
import java.util.ArrayList;
@PluginDescriptor(
name = "Pile Indicators",
description = "Highlight and count how many npcs/players are stacked on each other.",
tags = {"overlay", "pile", "stack", "pvp", "pvm", "pve"},
type = PluginType.UTILITY,
enabledByDefault = false
name = "Pile Indicators",
description = "Highlight and count how many npcs/players are stacked on each other.",
tags = {"overlay", "pile", "stack", "pvp", "pvm", "pve"},
type = PluginType.UTILITY,
enabledByDefault = false
)
@Singleton

View File

@@ -29,7 +29,6 @@ import net.runelite.api.ClanMemberRank;
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("playerindicators")
public interface PlayerIndicatorsConfig extends Config
@@ -365,46 +364,6 @@ public interface PlayerIndicatorsConfig extends Config
return Color.WHITE;
}
@ConfigItem(
position = 27,
keyName = "highlightPile",
name = "Highlight Pile",
description = "Highlights Pile Onscreen",
group = "Callers"
)
default boolean highlightPile()
{
return false;
}
@ConfigItem(
position = 29,
keyName = "drawPileHull",
name = "Draws the hull of the pile.",
description = "Draws the hull of the pile for best visibility.",
group = "Callers"
)
default boolean drawPileHull()
{
return false;
}
@Range(
min = 1,
max = 10
)
@ConfigItem(
position = 30,
keyName = "pileColor",
name = "Pile Color",
description = "Color of Indicated Pile",
group = "Callers"
)
default Color pileColor()
{
return Color.WHITE;
}
@ConfigItem(
position = 27,
keyName = "unchargedGlory",

View File

@@ -172,10 +172,6 @@ public class PlayerIndicatorsOverlay extends Overlay
{
name = "[C] " + name;
}
if (config.highlightPile() && playerIndicatorsPlugin.isPile(actor))
{
name = "[P] " + name;
}
if (config.showCombatLevel())
{

View File

@@ -29,9 +29,7 @@ import java.awt.Color;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import javax.inject.Inject;
import net.runelite.api.Actor;
import net.runelite.api.ClanMember;
import net.runelite.api.ClanMemberRank;
import static net.runelite.api.ClanMemberRank.UNRANKED;
@@ -54,7 +52,6 @@ import net.runelite.api.Player;
import net.runelite.api.events.ClanMemberJoined;
import net.runelite.api.events.ClanMemberLeft;
import net.runelite.api.events.ConfigChanged;
import net.runelite.api.events.GameTick;
import net.runelite.api.events.MenuEntryAdded;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.Subscribe;
@@ -128,35 +125,6 @@ public class PlayerIndicatorsPlugin extends Plugin
}
}
@Subscribe
public void onGameTick(GameTick gameTick)
{
if (config.highlightPile() && callers != null)
{
for (Player p : client.getPlayers())
{
for (String name : callers)
{
Actor pile;
String finalName = name.toLowerCase().replace("_", " ");
if (p.getName().toLowerCase().replace("_", " ").equals(finalName))
{
pile = p.getInteracting();
if (pile != null)
{
pileList.set(callers.indexOf(name), pile.getName());
//pileList.add(pile.getName());
}
else
{
pileList.set(callers.indexOf(name), "");
}
}
}
}
}
}
@Subscribe
public void onClanMemberJoined(ClanMemberJoined event)
{
@@ -213,14 +181,6 @@ public class PlayerIndicatorsPlugin extends Plugin
return false;
}
boolean isPile(Player player)
{
if (Objects.nonNull(pileList) && pileList.size() > 0)
{
return pileList.contains(player.getName());
}
return false;
}
@Subscribe
public void onMenuEntryAdded(MenuEntryAdded menuEntryAdded)
@@ -328,10 +288,6 @@ public class PlayerIndicatorsPlugin extends Plugin
{
color = config.callerColor();
}
if (config.colorPlayerMenu() && config.highlightPile() && this.isPile(player))
{
color = config.pileColor();
}
if (image != -1 || color != null)
{
MenuEntry[] menuEntries = client.getMenuEntries();

View File

@@ -50,8 +50,7 @@ public class PlayerIndicatorsService
public void forEachPlayer(final BiConsumer<Player, Color> consumer)
{
if (!config.highlightOwnPlayer() && !config.drawClanMemberNames()
&& !config.highlightFriends() && !config.highlightNonClanMembers() && !config.highlightTargets()
&& !config.highlightPile() && !config.highlightCallers() && !config.highlightTeamMembers())
&& !config.highlightFriends() && !config.highlightNonClanMembers() && !config.highlightTargets() && !config.highlightCallers() && !config.highlightTeamMembers())
{
return;
}
@@ -107,11 +106,6 @@ public class PlayerIndicatorsService
{
consumer.accept(player, config.callerColor());
}
if (config.highlightPile() && playerIndicatorsPlugin.isPile(player)
&& !player.isClanMember())
{
consumer.accept(player, config.pileColor());
}
}
}
}

View File

@@ -25,8 +25,6 @@
package net.runelite.client.plugins.playerindicators;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Polygon;
@@ -58,18 +56,6 @@ public class PlayerIndicatorsTileOverlay extends Overlay
@Override
public Dimension render(Graphics2D graphics)
{
if (config.drawPileHull())
{
playerIndicatorsService.forEachPlayer((player, color) ->
{
if (playerIndicatorsPlugin.isPile(player))
{
Polygon objectClickbox = player.getConvexHull();
renderPoly(graphics, config.pileColor(), objectClickbox);
}
});
}
if (!config.drawTiles() /*&& !config.drawPlayerHull()*/)
{
return null;
@@ -89,15 +75,4 @@ public class PlayerIndicatorsTileOverlay extends Overlay
return null;
}
private void renderPoly(Graphics2D graphics, Color color, Polygon polygon)
{
if (polygon != null)
{
graphics.setColor(color);
graphics.setStroke(new BasicStroke(2));
graphics.draw(polygon);
graphics.setColor(new Color(color.getRed(), color.getGreen(), color.getBlue(), 20));
graphics.fill(polygon);
}
}
}

View File

@@ -138,7 +138,7 @@ public class PuzzleSolverPlugin extends Plugin
@Subscribe
public void onMenuOptionClicked(MenuOptionClicked menuOptionClicked)
{
int widgetId = menuOptionClicked.getWidgetId();
int widgetId = menuOptionClicked.getActionParam1();
if (TO_GROUP(widgetId) != WidgetID.LIGHT_BOX_GROUP_ID)
{
return;

View File

@@ -16,6 +16,9 @@ import java.awt.Dimension;
import java.awt.Graphics2D;
import java.util.Arrays;
import javax.inject.Inject;
import net.runelite.api.Client;
import net.runelite.api.Varbits;
import net.runelite.api.WorldType;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayLayer;
import net.runelite.client.ui.overlay.OverlayPosition;
@@ -23,18 +26,23 @@ import net.runelite.client.ui.overlay.OverlayPriority;
import net.runelite.client.ui.overlay.components.table.TableComponent;
import net.runelite.client.ui.overlay.components.table.TableElement;
import net.runelite.client.ui.overlay.components.table.TableRow;
import org.apache.commons.lang3.ArrayUtils;
public class PlayerCountOverlay extends Overlay
{
private static int[] CLAN_WARS_REGIONS = {9520, 13135, 13134, 13133, 13131, 13130, 13387, 13386};
private final PvpToolsPlugin pvpToolsPlugin;
private final PvpToolsConfig config;
private final Client client;
@Inject
public PlayerCountOverlay(PvpToolsPlugin pvpToolsPlugin, PvpToolsConfig pvpToolsConfig)
public PlayerCountOverlay(PvpToolsPlugin pvpToolsPlugin, PvpToolsConfig pvpToolsConfig, Client client)
{
this.pvpToolsPlugin = pvpToolsPlugin;
this.config = pvpToolsConfig;
this.client = client;
setLayer(OverlayLayer.ABOVE_WIDGETS);
setPriority(OverlayPriority.HIGHEST);
setPosition(OverlayPosition.TOP_LEFT);
@@ -46,17 +54,23 @@ public class PlayerCountOverlay extends Overlay
{
if (config.countPlayers())
{
TableComponent tableComponent = new TableComponent();
TableElement[] firstRowElements = {
if ((client.getVar(Varbits.IN_WILDERNESS) == 1) || WorldType.isPvpWorld(client.getWorldType())
|| ArrayUtils.contains(CLAN_WARS_REGIONS, client.getMapRegions()[0]) ||
WorldType.isDeadmanWorld(client.getWorldType()))
{
// Make this stop showing up when its not relevant
TableComponent tableComponent = new TableComponent();
TableElement[] firstRowElements = {
TableElement.builder().content("Friendly").color(Color.GREEN).build(),
TableElement.builder().content(String.valueOf(pvpToolsPlugin.getFriendlyPlayerCount())).build()};
TableRow firstRow = TableRow.builder().elements(Arrays.asList(firstRowElements)).build();
TableElement[] secondRowElements = {
TableElement.builder().content("Enemy").color(Color.RED).build(),
TableElement.builder().content(String.valueOf(pvpToolsPlugin.getEnemyPlayerCount())).build()};
TableRow secondRow = TableRow.builder().elements(Arrays.asList(secondRowElements)).build();
tableComponent.addRows(firstRow, secondRow);
return tableComponent.render(graphics);
TableElement.builder().content(String.valueOf(pvpToolsPlugin.getFriendlyPlayerCount())).build()};
TableRow firstRow = TableRow.builder().elements(Arrays.asList(firstRowElements)).build();
TableElement[] secondRowElements = {
TableElement.builder().content("Enemy").color(Color.RED).build(),
TableElement.builder().content(String.valueOf(pvpToolsPlugin.getEnemyPlayerCount())).build()};
TableRow secondRow = TableRow.builder().elements(Arrays.asList(secondRowElements)).build();
tableComponent.addRows(firstRow, secondRow);
return tableComponent.render(graphics);
}
}
return null;
}

View File

@@ -178,10 +178,10 @@ public class PvpToolsPlugin extends Plugin
};
private final HotkeyListener renderselfHotkeyListener = new HotkeyListener(() -> config.renderSelf())
{ //TODO FIX
{
public void hotkeyPressed()
{
//client.toggleRenderSelf();
client.setRenderSelf(!client.getRenderSelf());
}
};

View File

@@ -59,6 +59,18 @@ public interface RaidsConfig extends Config
return true;
}
@ConfigItem(
position = 2,
parent = "scouterConfig",
keyName = "hideBackground",
name = "Hide Scouter Background",
description = "Removes the scouter background, and makes it transparent."
)
default boolean hideBackground()
{
return true;
}
@ConfigItem(
position = 2,
parent = "scouterConfig",

View File

@@ -52,6 +52,7 @@ 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.OverlayPriority;
import net.runelite.client.ui.overlay.components.ComponentConstants;
import net.runelite.client.ui.overlay.components.ComponentOrientation;
import net.runelite.client.ui.overlay.components.ImageComponent;
import net.runelite.client.ui.overlay.components.PanelComponent;
@@ -154,6 +155,15 @@ public class RaidsOverlay extends Overlay
scouterActive = false;
panelComponent.getChildren().clear();
if (config.hideBackground())
{
panelComponent.setBackgroundColor(null);
}
else
{
panelComponent.setBackgroundColor(ComponentConstants.STANDARD_BACKGROUND_COLOR);
}
if (plugin.getRaid() == null || plugin.getRaid().getLayout() == null)
{
panelComponent.getChildren().add(TitleComponent.builder()
@@ -279,14 +289,13 @@ public class RaidsOverlay extends Overlay
scavsBeforeIceRooms.add(prev);
}
int lastScavs = scavRooms.get(scavRooms.size() - 1);
if (!recordRaid())
{
panelComponent.getChildren().add(TitleComponent.builder()
.text(displayLayout)
.color(color)
.build());
}
else
panelComponent.getChildren().add(TitleComponent.builder()
.text(displayLayout)
.color(color)
.build());
if (recordRaid())
{
panelComponent.getChildren().add(TitleComponent.builder()
.text("Record Raid")
@@ -294,6 +303,17 @@ public class RaidsOverlay extends Overlay
.build());
panelComponent.setBackgroundColor(new Color(0, 255, 0, 10));
}
else
{
if (config.hideBackground())
{
panelComponent.setBackgroundColor(null);
}
else
{
panelComponent.setBackgroundColor(ComponentConstants.STANDARD_BACKGROUND_COLOR);
}
}
TableComponent tableComponent = new TableComponent();
tableComponent.setColumnAlignments(TableAlignment.LEFT, TableAlignment.RIGHT);
@@ -304,7 +324,7 @@ public class RaidsOverlay extends Overlay
String clanOwner = Text.removeTags(client.getWidget(WidgetInfo.CLAN_CHAT_OWNER).getText());
if (clanOwner.equals("None"))
{
clanOwner = "Open CC tab...";
clanOwner = "Open CC Tab";
color = Color.RED;
}

View File

@@ -27,7 +27,6 @@ package net.runelite.client.plugins.raids;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.lang.reflect.Method;
import javax.inject.Inject;
import javax.swing.BorderFactory;
import javax.swing.JButton;
@@ -78,22 +77,9 @@ class RaidsPanel extends PluginPanel
JPanel scoutFrame = new JPanel();
reloadButton.addActionListener((ActionEvent e) ->
{
if ((client.getGameState() == GameState.LOGGED_IN))
{
try
{
//look for client.gameStateChanged(-1); in src files to find
Method m = client.getClass().getClassLoader().loadClass("ba").getDeclaredMethod("ec", int.class, byte.class);
m.setAccessible(true);
m.invoke(null, 40, (byte) 3);
}
catch (ReflectiveOperationException f)
{
throw new RuntimeException(f);
}
client.setGameState(40);
}
});
reloadScouter.addActionListener((ActionEvent e) ->

View File

@@ -28,16 +28,29 @@ import java.awt.Color;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
import net.runelite.client.config.Stub;
@ConfigGroup("runedoku")
public interface RunedokuConfig extends Config
{
@ConfigItem(
position = 0,
keyName = "mindRuneColor",
name = "Mind Rune Color",
description = "Color used to highlight Mind runes."
position = 0,
keyName = "colorStub",
name = "Colors",
description = "" //stubs don't show descriptions when hovered over
)
default Stub colorStub()
{
return new Stub();
}
@ConfigItem(
position = 1,
keyName = "mindRuneColor",
name = "Mind Rune Color",
description = "Color used to highlight Mind runes.",
parent = "colorStub"
)
default Color mindRuneColor()
{
@@ -45,10 +58,11 @@ public interface RunedokuConfig extends Config
}
@ConfigItem(
position = 1,
keyName = "fireRuneColor",
name = "Fire Rune Color",
description = "Color used to highlight Fire runes."
position = 2,
keyName = "fireRuneColor",
name = "Fire Rune Color",
description = "Color used to highlight Fire runes.",
parent = "colorStub"
)
default Color fireRuneColor()
{
@@ -56,10 +70,11 @@ public interface RunedokuConfig extends Config
}
@ConfigItem(
position = 2,
keyName = "bodyRuneColor",
name = "Body Rune Color",
description = "Color used to highlight Body runes."
position = 3,
keyName = "bodyRuneColor",
name = "Body Rune Color",
description = "Color used to highlight Body runes.",
parent = "colorStub"
)
default Color bodyRuneColor()
{
@@ -67,10 +82,11 @@ public interface RunedokuConfig extends Config
}
@ConfigItem(
position = 3,
keyName = "airRuneColor",
name = "Air Rune Color",
description = "Color used to highlight Air runes."
position = 4,
keyName = "airRuneColor",
name = "Air Rune Color",
description = "Color used to highlight Air runes.",
parent = "colorStub"
)
default Color airRuneColor()
{
@@ -78,10 +94,11 @@ public interface RunedokuConfig extends Config
}
@ConfigItem(
position = 4,
keyName = "deathRuneColor",
name = "Death Rune Color",
description = "Color used to highlight Death runes."
position = 5,
keyName = "deathRuneColor",
name = "Death Rune Color",
description = "Color used to highlight Death runes.",
parent = "colorStub"
)
default Color deathRuneColor()
{
@@ -89,10 +106,11 @@ public interface RunedokuConfig extends Config
}
@ConfigItem(
position = 5,
keyName = "waterRuneColor",
name = "Water Rune Color",
description = "Color used to highlight Water runes."
position = 6,
keyName = "waterRuneColor",
name = "Water Rune Color",
description = "Color used to highlight Water runes.",
parent = "colorStub"
)
default Color waterRuneColor()
{
@@ -100,10 +118,11 @@ public interface RunedokuConfig extends Config
}
@ConfigItem(
position = 6,
keyName = "chaosRuneColor",
name = "Chaos Rune Color",
description = "Color used to highlight Chaos runes."
position = 7,
keyName = "chaosRuneColor",
name = "Chaos Rune Color",
description = "Color used to highlight Chaos runes.",
parent = "colorStub"
)
default Color chaosRuneColor()
{
@@ -111,10 +130,11 @@ public interface RunedokuConfig extends Config
}
@ConfigItem(
position = 7,
keyName = "earthRuneColor",
name = "Earth Rune Color",
description = "Color used to highlight Earth runes."
position = 8,
keyName = "earthRuneColor",
name = "Earth Rune Color",
description = "Color used to highlight Earth runes.",
parent = "colorStub"
)
default Color earthRuneColor()
{
@@ -122,14 +142,37 @@ public interface RunedokuConfig extends Config
}
@ConfigItem(
position = 8,
keyName = "lawRuneColor",
name = "Law Rune Color",
description = "Color used to highlight Law runes."
position = 9,
keyName = "lawRuneColor",
name = "Law Rune Color",
description = "Color used to highlight Law runes.",
parent = "colorStub"
)
default Color lawRuneColor()
{
return Color.CYAN;
}
@ConfigItem(
position = 10,
keyName = "miscFeature",
name = "Miscellaneous Features",
description = ""
)
default Stub miscFeature()
{
return new Stub();
}
@ConfigItem(
position = 11,
keyName = "onlyHighlightSelectedPiece",
name = "Only Highlight Selected Piece",
description = "Instead of showing all, this option only show what rune you have selected."
)
default boolean onlyHighlightSelectedPiece()
{
return false;
}
}

View File

@@ -47,15 +47,17 @@ class RunedokuOverlay extends Overlay
private final RunedokuPlugin plugin;
private final Client client;
private final RunedokuUtil util;
private final RunedokuConfig config;
@Inject
private RunedokuOverlay(final RunedokuPlugin plugin, final Client client, final RunedokuUtil util)
private RunedokuOverlay(final RunedokuPlugin plugin, final Client client, final RunedokuUtil util, final RunedokuConfig config)
{
super(plugin);
this.plugin = plugin;
this.client = client;
this.util = util;
this.config = config;
setPosition(OverlayPosition.DETACHED);
setLayer(OverlayLayer.ALWAYS_ON_TOP);
@@ -138,7 +140,10 @@ class RunedokuOverlay extends Overlay
}
else
{
OverlayUtil.renderPolygon(graphics, RunedokuUtil.rectangleToPolygon(squareToHighlight.getBounds()), util.sudokuPieceToColor(simpleArr.get(iteration)));
if (!config.onlyHighlightSelectedPiece() ^ (config.onlyHighlightSelectedPiece() && util.getSelectedPiece(client) == simpleArr.get(iteration)))
{
OverlayUtil.renderPolygon(graphics, RunedokuUtil.rectangleToPolygon(squareToHighlight.getBounds()), util.sudokuPieceToColor(simpleArr.get(iteration)));
}
}
iteration++;
}

View File

@@ -180,4 +180,41 @@ class RunedokuUtil
return myArr;
}
/**
* @param client
* @return
*/
int getSelectedPiece(Client client)
{
for (int i = 91; i < 100; i++)
{
Widget selectedPieceWidget = client.getWidget(288, i);
if (!selectedPieceWidget.isHidden())
{
switch (i)
{
case 91:
return 8;
case 92:
return 6;
case 93:
return 4;
case 94:
return 2;
case 95:
return 1;
case 96:
return 3;
case 97:
return 5;
case 98:
return 7;
case 99:
return 9;
}
}
}
return -1;
}
}

View File

@@ -784,7 +784,7 @@ public class SlayerPlugin extends Plugin
private boolean doubleTroubleExtraKill()
{
return WorldPoint.fromLocalInstance(client, client.getLocalPlayer().getLocalLocation()).getRegionID() == GROTESQUE_GUARDIANS_REGION &&
SlayerUnlock.GROTESQUE_GARDIAN_DOUBLE_COUNT.isEnabled(client);
SlayerUnlock.GROTESQUE_GUARDIAN_DOUBLE_COUNT.isEnabled(client);
}
// checks if any contiguous subsequence of seq0 exactly matches the String toMatch

Some files were not shown because too many files have changed in this diff Show More