Merge remote-tracking branch 'runelite/master'
This commit is contained in:
@@ -50,4 +50,13 @@ public final class ParamID
|
||||
public static final int SETTING_SLIDER_IS_DRAGGABLE = 1108;
|
||||
public static final int SETTING_SLIDER_DEADZONE = 1109;
|
||||
public static final int SETTING_SLIDER_DEADTIME = 1110;
|
||||
|
||||
public static final int OC_ITEM_OP1 = 451;
|
||||
public static final int OC_ITEM_OP2 = 452;
|
||||
public static final int OC_ITEM_OP3 = 453;
|
||||
public static final int OC_ITEM_OP4 = 454;
|
||||
public static final int OC_ITEM_OP5 = 455;
|
||||
public static final int OC_ITEM_OP6 = 456;
|
||||
public static final int OC_ITEM_OP7 = 457;
|
||||
public static final int OC_ITEM_OP8 = 458;
|
||||
}
|
||||
|
||||
@@ -105,15 +105,12 @@ class NpcOverlay extends Overlay
|
||||
|
||||
if (highlightedNpc.isSwTile())
|
||||
{
|
||||
int size = npcComposition.getSize();
|
||||
LocalPoint lp = actor.getLocalLocation();
|
||||
|
||||
int x = lp.getX() - ((size - 1) * Perspective.LOCAL_TILE_SIZE / 2);
|
||||
int y = lp.getY() - ((size - 1) * Perspective.LOCAL_TILE_SIZE / 2);
|
||||
|
||||
Polygon southWestTilePoly = Perspective.getCanvasTilePoly(client, new LocalPoint(x, y));
|
||||
|
||||
renderPoly(graphics, borderColor, borderWidth, fillColor, southWestTilePoly);
|
||||
LocalPoint lp = LocalPoint.fromWorld(client, actor.getWorldLocation());
|
||||
if (lp != null)
|
||||
{
|
||||
Polygon tilePoly = Perspective.getCanvasTilePoly(client, lp);
|
||||
renderPoly(graphics, borderColor, borderWidth, fillColor, tilePoly);
|
||||
}
|
||||
}
|
||||
|
||||
if (highlightedNpc.isOutline())
|
||||
|
||||
@@ -33,6 +33,17 @@ public interface CorpConfig extends Config
|
||||
{
|
||||
String GROUP = "corp";
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "leftClickCore",
|
||||
name = "Left click walk on core",
|
||||
description = "Prioritizes Walk here over Attack on the Dark energy core",
|
||||
position = 1
|
||||
)
|
||||
default boolean leftClickCore()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showDamage",
|
||||
name = "Show damage overlay",
|
||||
|
||||
@@ -37,12 +37,15 @@ import net.runelite.api.Actor;
|
||||
import net.runelite.api.ChatMessageType;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.MenuAction;
|
||||
import net.runelite.api.MenuEntry;
|
||||
import net.runelite.api.NPC;
|
||||
import net.runelite.api.NpcID;
|
||||
import net.runelite.api.Varbits;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.api.events.HitsplatApplied;
|
||||
import net.runelite.api.events.InteractingChanged;
|
||||
import net.runelite.api.events.MenuEntryAdded;
|
||||
import net.runelite.api.events.NpcDespawned;
|
||||
import net.runelite.api.events.NpcSpawned;
|
||||
import net.runelite.api.events.VarbitChanged;
|
||||
@@ -66,6 +69,9 @@ import net.runelite.client.ui.overlay.OverlayManager;
|
||||
@Slf4j
|
||||
public class CorpPlugin extends Plugin
|
||||
{
|
||||
private static final String ATTACK = "Attack";
|
||||
private static final String DARK_ENERGY_CORE = "Dark energy core";
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private NPC corp;
|
||||
|
||||
@@ -243,4 +249,24 @@ public class CorpPlugin extends Plugin
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onMenuEntryAdded(MenuEntryAdded menuEntryAdded)
|
||||
{
|
||||
final MenuEntry menuEntry = menuEntryAdded.getMenuEntry();
|
||||
final NPC npc = menuEntry.getNpc();
|
||||
if (npc == null || !DARK_ENERGY_CORE.equals(npc.getName()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (menuEntry.getType() != MenuAction.NPC_SECOND_OPTION
|
||||
|| !menuEntry.getOption().equals(ATTACK)
|
||||
|| !config.leftClickCore())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
menuEntry.setDeprioritized(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,4 +176,15 @@ public interface EntityHiderConfig extends Config
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 14,
|
||||
keyName = "hideDeadNpcs",
|
||||
name = "Hide Dead NPCs",
|
||||
description = "Hides NPCs when their health reaches 0"
|
||||
)
|
||||
default boolean hideDeadNpcs()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,6 +68,7 @@ public class EntityHiderPlugin extends Plugin
|
||||
private boolean hideLocalPlayer2D;
|
||||
private boolean hideNPCs;
|
||||
private boolean hideNPCs2D;
|
||||
private boolean hideDeadNpcs;
|
||||
private boolean hidePets;
|
||||
private boolean hideAttackers;
|
||||
private boolean hideProjectiles;
|
||||
@@ -118,6 +119,7 @@ public class EntityHiderPlugin extends Plugin
|
||||
|
||||
hideNPCs = config.hideNPCs();
|
||||
hideNPCs2D = config.hideNPCs2D();
|
||||
hideDeadNpcs = config.hideDeadNpcs();
|
||||
|
||||
hidePets = config.hidePets();
|
||||
|
||||
@@ -187,6 +189,12 @@ public class EntityHiderPlugin extends Plugin
|
||||
return !hidePets;
|
||||
}
|
||||
|
||||
// dead npcs can also be interacting so prioritize it over the interacting check
|
||||
if (npc.isDead() && hideDeadNpcs)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (npc.getInteracting() == client.getLocalPlayer())
|
||||
{
|
||||
boolean b = hideAttackers;
|
||||
|
||||
@@ -211,7 +211,7 @@ class LootTrackerPanel extends PluginPanel
|
||||
SwingUtil.removeButtonDecorations(collapseBtn);
|
||||
collapseBtn.setIcon(EXPAND_ICON);
|
||||
collapseBtn.setSelectedIcon(COLLAPSE_ICON);
|
||||
SwingUtil.addModalTooltip(collapseBtn, "Collapse All", "Un-Collapse All");
|
||||
SwingUtil.addModalTooltip(collapseBtn, "Expand All", "Collapse All");
|
||||
collapseBtn.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||
collapseBtn.setUI(new BasicButtonUI()); // substance breaks the layout
|
||||
collapseBtn.addActionListener(ev -> changeCollapse());
|
||||
|
||||
@@ -878,4 +878,15 @@ public interface MenuEntrySwapperConfig extends Config
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "removeDeadNpcMenus",
|
||||
name = "Remove dead npc menus",
|
||||
description = "Remove menu options such as Attack and Talk-to from dead npcs",
|
||||
section = npcSection
|
||||
)
|
||||
default boolean removeDeadNpcMenus()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
import javax.inject.Inject;
|
||||
@@ -55,10 +56,13 @@ import net.runelite.api.MenuAction;
|
||||
import net.runelite.api.MenuEntry;
|
||||
import net.runelite.api.NPC;
|
||||
import net.runelite.api.NPCComposition;
|
||||
import net.runelite.api.NpcID;
|
||||
import net.runelite.api.ObjectComposition;
|
||||
import net.runelite.api.ParamID;
|
||||
import net.runelite.api.events.ClientTick;
|
||||
import net.runelite.api.events.MenuOpened;
|
||||
import net.runelite.api.events.PostItemComposition;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetID;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.client.callback.ClientThread;
|
||||
@@ -100,6 +104,9 @@ public class MenuEntrySwapperPlugin extends Plugin
|
||||
private static final String ITEM_KEY_PREFIX = "item_";
|
||||
private static final String OBJECT_KEY_PREFIX = "object_";
|
||||
private static final String NPC_KEY_PREFIX = "npc_";
|
||||
private static final String NPC_SHIFT_KEY_PREFIX = "npc_shift_";
|
||||
private static final String WORN_ITEM_KEY_PREFIX = "wornitem_";
|
||||
private static final String WORN_ITEM_SHIFT_KEY_PREFIX = "wornitem_shift_";
|
||||
|
||||
// Shift click
|
||||
private static final WidgetMenuOption FIXED_INVENTORY_TAB_CONFIGURE_SC = new WidgetMenuOption(CONFIGURE,
|
||||
@@ -522,6 +529,33 @@ public class MenuEntrySwapperPlugin extends Plugin
|
||||
configManager.unsetConfiguration(shift ? SHIFTCLICK_CONFIG_GROUP : MenuEntrySwapperConfig.GROUP, ITEM_KEY_PREFIX + itemId);
|
||||
}
|
||||
|
||||
private Integer getWornItemSwapConfig(boolean shift, int itemId)
|
||||
{
|
||||
itemId = ItemVariationMapping.map(itemId);
|
||||
String config = configManager.getConfiguration(MenuEntrySwapperConfig.GROUP,
|
||||
(shift ? WORN_ITEM_SHIFT_KEY_PREFIX : WORN_ITEM_KEY_PREFIX) + itemId);
|
||||
if (config == null || config.isEmpty())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return Integer.parseInt(config);
|
||||
}
|
||||
|
||||
private void setWornItemSwapConfig(boolean shift, int itemId, int index)
|
||||
{
|
||||
itemId = ItemVariationMapping.map(itemId);
|
||||
configManager.setConfiguration(MenuEntrySwapperConfig.GROUP,
|
||||
(shift ? WORN_ITEM_SHIFT_KEY_PREFIX : WORN_ITEM_KEY_PREFIX) + itemId, index);
|
||||
}
|
||||
|
||||
private void unsetWornItemSwapConfig(boolean shift, int itemId)
|
||||
{
|
||||
itemId = ItemVariationMapping.map(itemId);
|
||||
configManager.unsetConfiguration(MenuEntrySwapperConfig.GROUP,
|
||||
(shift ? WORN_ITEM_SHIFT_KEY_PREFIX : WORN_ITEM_KEY_PREFIX) + itemId);
|
||||
}
|
||||
|
||||
private void enableCustomization()
|
||||
{
|
||||
rebuildCustomizationMenus();
|
||||
@@ -544,6 +578,7 @@ public class MenuEntrySwapperPlugin extends Plugin
|
||||
{
|
||||
configureObjectClick(event);
|
||||
configureNpcClick(event);
|
||||
configureWornItems(event);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -711,6 +746,26 @@ public class MenuEntrySwapperPlugin extends Plugin
|
||||
}
|
||||
}
|
||||
|
||||
private Consumer<MenuEntry> walkHereConsumer(boolean shift, NPCComposition composition)
|
||||
{
|
||||
return e ->
|
||||
{
|
||||
final String message = new ChatMessageBuilder()
|
||||
.append("The default ").append(shift ? "shift" : "left").append(" click option for '").append(Text.removeTags(composition.getName())).append("' ")
|
||||
.append("has been set to Walk here.")
|
||||
.build();
|
||||
|
||||
chatMessageManager.queue(QueuedMessage.builder()
|
||||
.type(ChatMessageType.CONSOLE)
|
||||
.runeLiteFormattedMessage(message)
|
||||
.build());
|
||||
|
||||
log.debug("Set npc {} click swap for {} to Walk here", shift ? "shift" : "left", composition.getId());
|
||||
|
||||
setNpcSwapConfig(shift, composition.getId(), -1);
|
||||
};
|
||||
}
|
||||
|
||||
private void configureNpcClick(MenuOpened event)
|
||||
{
|
||||
if (!shiftModifier() || !config.npcLeftClickCustomization())
|
||||
@@ -729,18 +784,20 @@ public class MenuEntrySwapperPlugin extends Plugin
|
||||
final NPC npc = entry.getNpc();
|
||||
assert npc != null;
|
||||
final NPCComposition composition = npc.getTransformedComposition();
|
||||
assert composition != null;
|
||||
final String[] actions = composition.getActions();
|
||||
|
||||
final Integer swapConfig = getNpcSwapConfig(composition.getId());
|
||||
final Integer swapConfig = getNpcSwapConfig(false, composition.getId());
|
||||
final boolean hasAttack = Arrays.stream(composition.getActions()).anyMatch("Attack"::equalsIgnoreCase);
|
||||
final MenuAction currentAction = swapConfig != null ? NPC_MENU_TYPES.get(swapConfig) :
|
||||
final MenuAction currentAction = swapConfig == null ?
|
||||
// Attackable NPCs always have Attack as the first, last (deprioritized), or when hidden, no, option.
|
||||
// Due to this the default action would be either Attack or the first non-Attack option, based on
|
||||
// the game settings. Since it may be valid to swap an option up to override Attack, even when Attack
|
||||
// is left-click, we cannot assume any default currentAction on attackable NPCs.
|
||||
// Non-attackable NPCS have a predictable default action which we can prevent a swap to if no swap
|
||||
// config is set, which just avoids showing a Swap option on a 1-op NPC, which looks odd.
|
||||
(hasAttack ? null : defaultAction(composition));
|
||||
(hasAttack ? null : defaultAction(composition)) :
|
||||
(swapConfig == -1 ? MenuAction.WALK : NPC_MENU_TYPES.get(swapConfig));
|
||||
|
||||
for (int actionIdx = 0; actionIdx < NPC_MENU_TYPES.size(); ++actionIdx)
|
||||
{
|
||||
@@ -759,8 +816,7 @@ public class MenuEntrySwapperPlugin extends Plugin
|
||||
continue;
|
||||
}
|
||||
|
||||
if ("Pickpocket".equals(actions[actionIdx])
|
||||
|| "Knock-Out".equals(actions[actionIdx])
|
||||
if ("Knock-Out".equals(actions[actionIdx])
|
||||
|| "Lure".equals(actions[actionIdx]))
|
||||
{
|
||||
// https://secure.runescape.com/m=news/another-message-about-unofficial-clients?oldschool=1
|
||||
@@ -785,11 +841,24 @@ public class MenuEntrySwapperPlugin extends Plugin
|
||||
|
||||
log.debug("Set npc swap for {} to {}", composition.getId(), menuAction);
|
||||
|
||||
setNpcSwapConfig(composition.getId(), menuIdx);
|
||||
setNpcSwapConfig(false, composition.getId(), menuIdx);
|
||||
});
|
||||
}
|
||||
|
||||
if (getNpcSwapConfig(composition.getId()) != null)
|
||||
// Walk here swap
|
||||
client.createMenuEntry(idx)
|
||||
.setOption("Swap left click Walk here")
|
||||
.setTarget(entry.getTarget())
|
||||
.setType(MenuAction.RUNELITE)
|
||||
.onClick(walkHereConsumer(false, composition));
|
||||
|
||||
client.createMenuEntry(idx)
|
||||
.setOption("Swap shift click Walk here")
|
||||
.setTarget(entry.getTarget())
|
||||
.setType(MenuAction.RUNELITE)
|
||||
.onClick(walkHereConsumer(true, composition));
|
||||
|
||||
if (getNpcSwapConfig(true, composition.getId()) != null || getNpcSwapConfig(false, composition.getId()) != null) // NOPMD: BrokenNullCheck
|
||||
{
|
||||
// Reset
|
||||
client.createMenuEntry(idx)
|
||||
@@ -799,8 +868,8 @@ public class MenuEntrySwapperPlugin extends Plugin
|
||||
.onClick(e ->
|
||||
{
|
||||
final String message = new ChatMessageBuilder()
|
||||
.append("The default left click option for '").append(Text.removeTags(composition.getName())).append("' ")
|
||||
.append("has been reset.")
|
||||
.append("The default left and shift click options for '").append(Text.removeTags(composition.getName())).append("' ")
|
||||
.append("have been reset.")
|
||||
.build();
|
||||
|
||||
chatMessageManager.queue(QueuedMessage.builder()
|
||||
@@ -809,13 +878,129 @@ public class MenuEntrySwapperPlugin extends Plugin
|
||||
.build());
|
||||
|
||||
log.debug("Unset npc swap for {}", composition.getId());
|
||||
unsetNpcSwapConfig(composition.getId());
|
||||
unsetNpcSwapConfig(true, composition.getId());
|
||||
unsetNpcSwapConfig(false, composition.getId());
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void configureWornItems(MenuOpened event)
|
||||
{
|
||||
if (!shiftModifier())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
final MenuEntry[] entries = event.getMenuEntries();
|
||||
for (int idx = entries.length - 1; idx >= 0; --idx)
|
||||
{
|
||||
final MenuEntry entry = entries[idx];
|
||||
Widget w = entry.getWidget();
|
||||
|
||||
if (w != null && WidgetInfo.TO_GROUP(w.getId()) == WidgetID.EQUIPMENT_GROUP_ID
|
||||
&& "Examine".equals(entry.getOption()) && entry.getIdentifier() == 10)
|
||||
{
|
||||
w = w.getChild(1);
|
||||
if (w != null && w.getItemId() > -1)
|
||||
{
|
||||
final ItemComposition itemComposition = itemManager.getItemComposition(w.getItemId());
|
||||
final Integer leftClickOp = getWornItemSwapConfig(false, itemComposition.getId());
|
||||
final Integer shiftClickOp = getWornItemSwapConfig(true, itemComposition.getId());
|
||||
|
||||
for (int paramId = ParamID.OC_ITEM_OP1, opId = 2; paramId <= ParamID.OC_ITEM_OP8; ++paramId, ++opId)
|
||||
{
|
||||
final String opName = itemComposition.getStringValue(paramId);
|
||||
if (!Strings.isNullOrEmpty(opName))
|
||||
{
|
||||
if (leftClickOp == null || leftClickOp != opId)
|
||||
{
|
||||
client.createMenuEntry(idx)
|
||||
.setOption("Swap left click " + opName)
|
||||
.setTarget(entry.getTarget())
|
||||
.setType(MenuAction.RUNELITE)
|
||||
.onClick(wornItemConsumer(itemComposition, opName, opId, false));
|
||||
}
|
||||
if (shiftClickOp == null || shiftClickOp != opId)
|
||||
{
|
||||
client.createMenuEntry(idx)
|
||||
.setOption("Swap shift click " + opName)
|
||||
.setTarget(entry.getTarget())
|
||||
.setType(MenuAction.RUNELITE)
|
||||
.onClick(wornItemConsumer(itemComposition, opName, opId, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (leftClickOp != null)
|
||||
{
|
||||
client.createMenuEntry(idx)
|
||||
.setOption("Reset swap left click")
|
||||
.setTarget(entry.getTarget())
|
||||
.setType(MenuAction.RUNELITE)
|
||||
.onClick(e ->
|
||||
{
|
||||
final String message = new ChatMessageBuilder()
|
||||
.append("The default worn left click option for '").append(itemComposition.getName()).append("' ")
|
||||
.append("has been reset.")
|
||||
.build();
|
||||
|
||||
chatMessageManager.queue(QueuedMessage.builder()
|
||||
.type(ChatMessageType.CONSOLE)
|
||||
.runeLiteFormattedMessage(message)
|
||||
.build());
|
||||
|
||||
log.debug("Unset worn item left swap for {}", itemComposition.getName());
|
||||
unsetWornItemSwapConfig(false, itemComposition.getId());
|
||||
});
|
||||
}
|
||||
if (shiftClickOp != null)
|
||||
{
|
||||
client.createMenuEntry(idx)
|
||||
.setOption("Reset swap shift click")
|
||||
.setTarget(entry.getTarget())
|
||||
.setType(MenuAction.RUNELITE)
|
||||
.onClick(e ->
|
||||
{
|
||||
final String message = new ChatMessageBuilder()
|
||||
.append("The default worn shift click option for '").append(itemComposition.getName()).append("' ")
|
||||
.append("has been reset.")
|
||||
.build();
|
||||
|
||||
chatMessageManager.queue(QueuedMessage.builder()
|
||||
.type(ChatMessageType.CONSOLE)
|
||||
.runeLiteFormattedMessage(message)
|
||||
.build());
|
||||
|
||||
log.debug("Unset worn item shift swap for {}", itemComposition.getName());
|
||||
unsetWornItemSwapConfig(true, itemComposition.getId());
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Consumer<MenuEntry> wornItemConsumer(ItemComposition itemComposition, String opName, int opIdx, boolean shift)
|
||||
{
|
||||
return e ->
|
||||
{
|
||||
final String message = new ChatMessageBuilder()
|
||||
.append("The default worn ").append(shift ? "shift" : "left").append(" click option for '").append(Text.removeTags(itemComposition.getName())).append("' ")
|
||||
.append("has been set to '").append(opName).append("'.")
|
||||
.build();
|
||||
|
||||
chatMessageManager.queue(QueuedMessage.builder()
|
||||
.type(ChatMessageType.CONSOLE)
|
||||
.runeLiteFormattedMessage(message)
|
||||
.build());
|
||||
|
||||
log.debug("Set worn item {} swap for {} to {}", shift ? "shift" : "left", itemComposition.getName(), opIdx);
|
||||
setWornItemSwapConfig(shift, itemComposition.getId(), opIdx);
|
||||
};
|
||||
}
|
||||
|
||||
private boolean swapBank(MenuEntry menuEntry, MenuAction type)
|
||||
{
|
||||
if (type != MenuAction.CC_OP && type != MenuAction.CC_OP_LOW_PRIORITY)
|
||||
@@ -952,6 +1137,25 @@ public class MenuEntrySwapperPlugin extends Plugin
|
||||
}
|
||||
}
|
||||
|
||||
// Worn items swap
|
||||
Widget w = menuEntry.getWidget();
|
||||
if (w != null && WidgetInfo.TO_GROUP(w.getId()) == WidgetID.EQUIPMENT_GROUP_ID)
|
||||
{
|
||||
w = w.getChild(1);
|
||||
if (w != null && w.getItemId() > -1)
|
||||
{
|
||||
final Integer wornItemSwapConfig = getWornItemSwapConfig(shiftModifier(), w.getItemId());
|
||||
if (wornItemSwapConfig != null)
|
||||
{
|
||||
if (wornItemSwapConfig == menuEntry.getIdentifier())
|
||||
{
|
||||
swap(optionIndexes, menuEntries, index, menuEntries.length - 1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (OBJECT_MENU_TYPES.contains(menuAction))
|
||||
{
|
||||
// Get multiloc id
|
||||
@@ -981,24 +1185,33 @@ public class MenuEntrySwapperPlugin extends Plugin
|
||||
assert npc != null;
|
||||
final NPCComposition composition = npc.getTransformedComposition();
|
||||
|
||||
Integer customOption = getNpcSwapConfig(composition.getId());
|
||||
Integer customOption = getNpcSwapConfig(shiftModifier(), composition.getId());
|
||||
if (customOption != null)
|
||||
{
|
||||
MenuAction swapAction = NPC_MENU_TYPES.get(customOption);
|
||||
if (swapAction == menuAction)
|
||||
// Walk here swap
|
||||
if (customOption == -1)
|
||||
{
|
||||
// Advance to the top-most op for this NPC. Normally menuEntries.length - 1 is examine, and swapping
|
||||
// with that works due to it being sorted later, but if other plugins like NPC indicators add additional
|
||||
// menus before examine that are also >1000, like RUNELITE menus, that would result in the >1000 menus being
|
||||
// reordered relative to each other.
|
||||
int i = index;
|
||||
while (i < menuEntries.length - 1 && NPC_MENU_TYPES.contains(menuEntries[i + 1].getType()))
|
||||
// we can achieve this by just deprioritizing the normal npc menus
|
||||
menuEntry.setDeprioritized(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
MenuAction swapAction = NPC_MENU_TYPES.get(customOption);
|
||||
if (swapAction == menuAction)
|
||||
{
|
||||
++i;
|
||||
}
|
||||
// Advance to the top-most op for this NPC. Normally menuEntries.length - 1 is examine, and swapping
|
||||
// with that works due to it being sorted later, but if other plugins like NPC indicators add additional
|
||||
// menus before examine that are also >1000, like RUNELITE menus, that would result in the >1000 menus being
|
||||
// reordered relative to each other.
|
||||
int i = index;
|
||||
while (i < menuEntries.length - 1 && NPC_MENU_TYPES.contains(menuEntries[i + 1].getType()))
|
||||
{
|
||||
++i;
|
||||
}
|
||||
|
||||
swap(optionIndexes, menuEntries, index, i);
|
||||
return;
|
||||
swap(optionIndexes, menuEntries, index, i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1049,6 +1262,53 @@ public class MenuEntrySwapperPlugin extends Plugin
|
||||
{
|
||||
swapMenuEntry(menuEntries, idx++, entry);
|
||||
}
|
||||
|
||||
if (config.removeDeadNpcMenus())
|
||||
{
|
||||
removeDeadNpcs();
|
||||
}
|
||||
}
|
||||
|
||||
private void removeDeadNpcs()
|
||||
{
|
||||
MenuEntry[] oldEntries = client.getMenuEntries();
|
||||
MenuEntry[] newEntries = Arrays.stream(oldEntries)
|
||||
.filter(e ->
|
||||
{
|
||||
final NPC npc = e.getNpc();
|
||||
if (npc == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
final int id = npc.getId();
|
||||
switch (id)
|
||||
{
|
||||
// These NPCs hit 0hp but don't actually die
|
||||
case NpcID.GARGOYLE:
|
||||
case NpcID.GARGOYLE_413:
|
||||
case NpcID.GARGOYLE_1543:
|
||||
case NpcID.ZYGOMITE:
|
||||
case NpcID.ZYGOMITE_1024:
|
||||
case NpcID.ANCIENT_ZYGOMITE:
|
||||
case NpcID.ROCKSLUG:
|
||||
case NpcID.ROCKSLUG_422:
|
||||
case NpcID.DESERT_LIZARD:
|
||||
case NpcID.DESERT_LIZARD_460:
|
||||
case NpcID.DESERT_LIZARD_461:
|
||||
case NpcID.ICE_DEMON:
|
||||
case NpcID.ICE_DEMON_7585:
|
||||
return true;
|
||||
default:
|
||||
return !npc.isDead();
|
||||
|
||||
}
|
||||
})
|
||||
.toArray(MenuEntry[]::new);
|
||||
if (oldEntries.length != newEntries.length)
|
||||
{
|
||||
client.setMenuEntries(newEntries);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
@@ -1278,9 +1538,10 @@ public class MenuEntrySwapperPlugin extends Plugin
|
||||
return null;
|
||||
}
|
||||
|
||||
private Integer getNpcSwapConfig(int npcId)
|
||||
private Integer getNpcSwapConfig(boolean shift, int npcId)
|
||||
{
|
||||
String config = configManager.getConfiguration(MenuEntrySwapperConfig.GROUP, NPC_KEY_PREFIX + npcId);
|
||||
String config = configManager.getConfiguration(MenuEntrySwapperConfig.GROUP,
|
||||
(shift ? NPC_SHIFT_KEY_PREFIX : NPC_KEY_PREFIX) + npcId);
|
||||
if (config == null || config.isEmpty())
|
||||
{
|
||||
return null;
|
||||
@@ -1289,14 +1550,14 @@ public class MenuEntrySwapperPlugin extends Plugin
|
||||
return Integer.parseInt(config);
|
||||
}
|
||||
|
||||
private void setNpcSwapConfig(int npcId, int index)
|
||||
private void setNpcSwapConfig(boolean shift, int npcId, int index)
|
||||
{
|
||||
configManager.setConfiguration(MenuEntrySwapperConfig.GROUP, NPC_KEY_PREFIX + npcId, index);
|
||||
configManager.setConfiguration(MenuEntrySwapperConfig.GROUP, (shift ? NPC_SHIFT_KEY_PREFIX : NPC_KEY_PREFIX) + npcId, index);
|
||||
}
|
||||
|
||||
private void unsetNpcSwapConfig(int npcId)
|
||||
private void unsetNpcSwapConfig(boolean shift, int npcId)
|
||||
{
|
||||
configManager.unsetConfiguration(MenuEntrySwapperConfig.GROUP, NPC_KEY_PREFIX + npcId);
|
||||
configManager.unsetConfiguration(MenuEntrySwapperConfig.GROUP, (shift ? NPC_SHIFT_KEY_PREFIX : NPC_KEY_PREFIX) + npcId);
|
||||
}
|
||||
|
||||
private static MenuAction defaultAction(NPCComposition composition)
|
||||
|
||||
@@ -78,11 +78,22 @@ public interface XpGlobesConfig extends Config
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showTimeTilGoal",
|
||||
name = "Show time til goal",
|
||||
description = "Shows the amount of time until goal level in the globe tooltip box",
|
||||
position = 4
|
||||
)
|
||||
default boolean showTimeTilGoal()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "hideMaxed",
|
||||
name = "Hide maxed skills",
|
||||
description = "Stop globes from showing up for level 99 skills",
|
||||
position = 4
|
||||
position = 14
|
||||
)
|
||||
default boolean hideMaxed()
|
||||
{
|
||||
@@ -93,7 +104,7 @@ public interface XpGlobesConfig extends Config
|
||||
keyName = "showVirtualLevel",
|
||||
name = "Show virtual level",
|
||||
description = "Shows virtual level if over 99 in a skill and Hide maxed skill is not checked",
|
||||
position = 5
|
||||
position = 15
|
||||
)
|
||||
default boolean showVirtualLevel()
|
||||
{
|
||||
@@ -104,7 +115,7 @@ public interface XpGlobesConfig extends Config
|
||||
keyName = "enableCustomArcColor",
|
||||
name = "Enable custom arc color",
|
||||
description = "Enables the custom coloring of the globe's arc instead of using the skill's default color.",
|
||||
position = 6
|
||||
position = 16
|
||||
)
|
||||
default boolean enableCustomArcColor()
|
||||
{
|
||||
@@ -116,7 +127,7 @@ public interface XpGlobesConfig extends Config
|
||||
keyName = "Progress arc color",
|
||||
name = "Progress arc color",
|
||||
description = "Change the color of the progress arc in the xp orb",
|
||||
position = 7
|
||||
position = 17
|
||||
)
|
||||
default Color progressArcColor()
|
||||
{
|
||||
@@ -128,7 +139,7 @@ public interface XpGlobesConfig extends Config
|
||||
keyName = "Progress orb outline color",
|
||||
name = "Progress orb outline color",
|
||||
description = "Change the color of the progress orb outline",
|
||||
position = 8
|
||||
position = 18
|
||||
)
|
||||
default Color progressOrbOutLineColor()
|
||||
{
|
||||
@@ -140,7 +151,7 @@ public interface XpGlobesConfig extends Config
|
||||
keyName = "Progress orb background color",
|
||||
name = "Progress orb background color",
|
||||
description = "Change the color of the progress orb background",
|
||||
position = 9
|
||||
position = 19
|
||||
)
|
||||
default Color progressOrbBackgroundColor()
|
||||
{
|
||||
@@ -151,7 +162,7 @@ public interface XpGlobesConfig extends Config
|
||||
keyName = "Progress arc width",
|
||||
name = "Progress arc width",
|
||||
description = "Change the stroke width of the progress arc",
|
||||
position = 10
|
||||
position = 20
|
||||
)
|
||||
@Units(Units.PIXELS)
|
||||
default int progressArcStrokeWidth()
|
||||
@@ -163,7 +174,7 @@ public interface XpGlobesConfig extends Config
|
||||
keyName = "Orb size",
|
||||
name = "Size of orbs",
|
||||
description = "Change the size of the xp orbs",
|
||||
position = 11
|
||||
position = 21
|
||||
)
|
||||
@Units(Units.PIXELS)
|
||||
default int xpOrbSize()
|
||||
@@ -175,7 +186,7 @@ public interface XpGlobesConfig extends Config
|
||||
keyName = "Orb duration",
|
||||
name = "Duration of orbs",
|
||||
description = "Change the duration the xp orbs are visible",
|
||||
position = 12
|
||||
position = 22
|
||||
)
|
||||
@Units(Units.SECONDS)
|
||||
default int xpOrbDuration()
|
||||
|
||||
@@ -352,6 +352,16 @@ public class XpGlobesOverlay extends Overlay
|
||||
.build());
|
||||
}
|
||||
}
|
||||
|
||||
if (config.showTimeTilGoal())
|
||||
{
|
||||
String timeLeft = xpTrackerService.getTimeTilGoal(mouseOverSkill.getSkill());
|
||||
xpTooltip.getChildren().add(LineComponent.builder()
|
||||
.left("Time left:")
|
||||
.leftColor(Color.ORANGE)
|
||||
.right(timeLeft)
|
||||
.build());
|
||||
}
|
||||
}
|
||||
|
||||
tooltipManager.add(this.xpTooltip);
|
||||
|
||||
@@ -204,7 +204,7 @@ class XpStateSingle
|
||||
// return time remaining in hh:mm:ss or mm:ss format where hh can be > 24
|
||||
if (durationHoursTotal > 0)
|
||||
{
|
||||
return String.format("%02d:%02d:%02d", durationHoursTotal, durationMinutes, durationSeconds);
|
||||
return String.format("%d:%02d:%02d", durationHoursTotal, durationMinutes, durationSeconds);
|
||||
}
|
||||
|
||||
// Minutes and seconds will always be present
|
||||
|
||||
@@ -62,4 +62,9 @@ public interface XpTrackerService
|
||||
* Get the amount of XP left until goal level
|
||||
*/
|
||||
int getEndGoalXp(Skill skill);
|
||||
|
||||
/**
|
||||
* Get the amount of time left until goal level
|
||||
*/
|
||||
String getTimeTilGoal(Skill skill);
|
||||
}
|
||||
|
||||
@@ -80,4 +80,10 @@ class XpTrackerServiceImpl implements XpTrackerService
|
||||
{
|
||||
return plugin.getSkillSnapshot(skill).getEndGoalXp();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTimeTilGoal(Skill skill)
|
||||
{
|
||||
return plugin.getSkillSnapshot(skill).getTimeTillGoalShort();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user