Show opponents hp in menu, your target colored, targeting you *
This commit is contained in:
@@ -64,8 +64,11 @@ public interface Actor extends Entity, Locatable
|
||||
* </ul>
|
||||
*
|
||||
* @return the actor, null if no interaction is occurring
|
||||
*
|
||||
* (getRSInteracting returns the npc/player index, useful for menus)
|
||||
*/
|
||||
Actor getInteracting();
|
||||
int getRSInteracting();
|
||||
|
||||
/**
|
||||
* Gets the health ratio of the actor.
|
||||
|
||||
@@ -341,9 +341,12 @@ public interface Client extends GameShell
|
||||
* Gets the logged in player instance.
|
||||
*
|
||||
* @return the logged in player
|
||||
*
|
||||
* (getLocalPlayerIndex returns the local index, useful for menus/interacting)
|
||||
*/
|
||||
@Nullable
|
||||
Player getLocalPlayer();
|
||||
int getLocalPlayerIndex();
|
||||
|
||||
/**
|
||||
* Gets the item composition corresponding to an items ID.
|
||||
|
||||
@@ -91,6 +91,8 @@ public class MenuManager
|
||||
private MenuEntry leftClickEntry = null;
|
||||
private MenuEntry firstEntry = null;
|
||||
|
||||
private int playerAttackIdx = -1;
|
||||
|
||||
@Inject
|
||||
private MenuManager(Client client, EventBus eventBus)
|
||||
{
|
||||
@@ -500,6 +502,29 @@ public class MenuManager
|
||||
return index;
|
||||
}
|
||||
|
||||
public int getPlayerAttackOpcode()
|
||||
{
|
||||
final String[] playerMenuOptions = client.getPlayerOptions();
|
||||
|
||||
if (playerAttackIdx != -1 && playerMenuOptions[playerAttackIdx].equals("Attack"))
|
||||
{
|
||||
return client.getPlayerMenuTypes()[playerAttackIdx];
|
||||
}
|
||||
|
||||
playerAttackIdx = -1;
|
||||
|
||||
for (int i = IDX_LOWER; i < IDX_UPPER; i++)
|
||||
{
|
||||
if ("Attack".equals(playerMenuOptions[i]))
|
||||
{
|
||||
playerAttackIdx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return playerAttackIdx >= 0 ? client.getPlayerMenuTypes()[playerAttackIdx] : -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds to the set of menu entries which when present, will remove all entries except for this one
|
||||
*/
|
||||
@@ -522,7 +547,7 @@ public class MenuManager
|
||||
|
||||
AbstractComparableEntry entry = newBaseComparableEntry(option, target);
|
||||
|
||||
priorityEntries.removeIf(entry::equals);
|
||||
priorityEntries.remove(entry);
|
||||
}
|
||||
|
||||
|
||||
@@ -562,7 +587,7 @@ public class MenuManager
|
||||
|
||||
public void removePriorityEntry(AbstractComparableEntry entry)
|
||||
{
|
||||
priorityEntries.removeIf(entry::equals);
|
||||
priorityEntries.remove(entry);
|
||||
}
|
||||
|
||||
public void removePriorityEntry(String option)
|
||||
@@ -571,7 +596,7 @@ public class MenuManager
|
||||
|
||||
AbstractComparableEntry entry = newBaseComparableEntry(option, "", false);
|
||||
|
||||
priorityEntries.removeIf(entry::equals);
|
||||
priorityEntries.remove(entry);
|
||||
}
|
||||
|
||||
public void removePriorityEntry(String option, boolean strictOption)
|
||||
@@ -581,7 +606,17 @@ public class MenuManager
|
||||
AbstractComparableEntry entry =
|
||||
newBaseComparableEntry(option, "", -1, -1, false, strictOption);
|
||||
|
||||
priorityEntries.removeIf(entry::equals);
|
||||
priorityEntries.remove(entry);
|
||||
}
|
||||
|
||||
public void addPriorityEntries(Collection<AbstractComparableEntry> entries)
|
||||
{
|
||||
priorityEntries.addAll(entries);
|
||||
}
|
||||
|
||||
public void removePriorityEntries(Collection<AbstractComparableEntry> entries)
|
||||
{
|
||||
priorityEntries.removeAll(entries);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
*/
|
||||
package net.runelite.client.plugins.opponentinfo;
|
||||
|
||||
import java.awt.Color;
|
||||
import net.runelite.client.config.Config;
|
||||
import net.runelite.client.config.ConfigGroup;
|
||||
import net.runelite.client.config.ConfigItem;
|
||||
@@ -65,12 +66,47 @@ public interface OpponentInfoConfig extends Config
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showOpponentsInMenu",
|
||||
name = "Show opponents in menu",
|
||||
description = "Marks opponents names in the menu which you are attacking or are attacking you (NPC only)",
|
||||
position = 3
|
||||
keyName = "showAttackersMenu",
|
||||
name = "Show attackers in menu",
|
||||
description = "Marks attackers' names in menus with a *<br>",
|
||||
position = 3,
|
||||
warning = "NOTE: This'll also mark people who are following you/interacting with you in any other way. Don't blindly trust this in pvp!"
|
||||
)
|
||||
default boolean showOpponentsInMenu()
|
||||
default boolean showAttackersMenu()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showAttackingMenu",
|
||||
name = "Green main target",
|
||||
description = "Display main target's name colored in menus (Players and NPCs)",
|
||||
position = 4,
|
||||
warning = "NOTE: This'll also show green when following/interacting in any other way. Don't blindly trust this in pvp!"
|
||||
)
|
||||
default boolean showAttackingMenu()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "attackingColor",
|
||||
name = "Target color",
|
||||
description = "The color your target will be highlighted with",
|
||||
position = 5
|
||||
)
|
||||
default Color attackingColor()
|
||||
{
|
||||
return Color.GREEN;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showHitpointsMenu",
|
||||
name = "Show NPC hp in menu",
|
||||
description = "Show NPC hp in menu. Useful when barraging",
|
||||
position = 6
|
||||
)
|
||||
default boolean showHitpointsMenu()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -36,11 +36,7 @@ import javax.inject.Singleton;
|
||||
import net.runelite.api.Actor;
|
||||
import net.runelite.api.Client;
|
||||
import static net.runelite.api.MenuOpcode.RUNELITE_OVERLAY_CONFIG;
|
||||
import net.runelite.api.NPC;
|
||||
import net.runelite.api.Player;
|
||||
import net.runelite.api.Varbits;
|
||||
import net.runelite.client.game.HiscoreManager;
|
||||
import net.runelite.client.game.NPCManager;
|
||||
import net.runelite.client.ui.overlay.Overlay;
|
||||
import static net.runelite.client.ui.overlay.OverlayManager.OPTION_CONFIGURE;
|
||||
import net.runelite.client.ui.overlay.OverlayMenuEntry;
|
||||
@@ -51,7 +47,6 @@ import net.runelite.client.ui.overlay.components.PanelComponent;
|
||||
import net.runelite.client.ui.overlay.components.ProgressBarComponent;
|
||||
import net.runelite.client.ui.overlay.components.TitleComponent;
|
||||
import net.runelite.api.util.Text;
|
||||
import net.runelite.http.api.hiscore.HiscoreResult;
|
||||
|
||||
@Singleton
|
||||
class OpponentInfoOverlay extends Overlay
|
||||
@@ -61,8 +56,6 @@ class OpponentInfoOverlay extends Overlay
|
||||
|
||||
private final Client client;
|
||||
private final OpponentInfoPlugin opponentInfoPlugin;
|
||||
private final HiscoreManager hiscoreManager;
|
||||
private final NPCManager npcManager;
|
||||
|
||||
private final PanelComponent panelComponent = new PanelComponent();
|
||||
|
||||
@@ -75,15 +68,11 @@ class OpponentInfoOverlay extends Overlay
|
||||
@Inject
|
||||
private OpponentInfoOverlay(
|
||||
final Client client,
|
||||
final OpponentInfoPlugin opponentInfoPlugin,
|
||||
final HiscoreManager hiscoreManager,
|
||||
final NPCManager npcManager)
|
||||
final OpponentInfoPlugin opponentInfoPlugin)
|
||||
{
|
||||
super(opponentInfoPlugin);
|
||||
this.client = client;
|
||||
this.opponentInfoPlugin = opponentInfoPlugin;
|
||||
this.hiscoreManager = hiscoreManager;
|
||||
this.npcManager = npcManager;
|
||||
|
||||
setPosition(OverlayPosition.TOP_LEFT);
|
||||
setPriority(OverlayPriority.HIGH);
|
||||
@@ -110,23 +99,7 @@ class OpponentInfoOverlay extends Overlay
|
||||
lastHealthScale = opponent.getHealth();
|
||||
opponentName = Text.removeTags(opponent.getName());
|
||||
|
||||
lastMaxHealth = -1;
|
||||
if (opponent instanceof NPC)
|
||||
{
|
||||
lastMaxHealth = npcManager.getHealth(((NPC) opponent).getId());
|
||||
}
|
||||
else if (opponent instanceof Player)
|
||||
{
|
||||
final HiscoreResult hiscoreResult = hiscoreManager.lookupAsync(opponentName, opponentInfoPlugin.getHiscoreEndpoint());
|
||||
if (hiscoreResult != null)
|
||||
{
|
||||
final int hp = hiscoreResult.getHitpoints().getLevel();
|
||||
if (hp > 0)
|
||||
{
|
||||
lastMaxHealth = hp;
|
||||
}
|
||||
}
|
||||
}
|
||||
lastMaxHealth = opponentInfoPlugin.getMaxHp(opponent);
|
||||
|
||||
final Actor opponentsOpponent = opponent.getInteracting();
|
||||
if (opponentsOpponent != null
|
||||
@@ -168,37 +141,7 @@ class OpponentInfoOverlay extends Overlay
|
||||
if ((displayStyle == HitpointsDisplayStyle.HITPOINTS || displayStyle == HitpointsDisplayStyle.BOTH)
|
||||
&& lastMaxHealth != -1)
|
||||
{
|
||||
// This is the reverse of the calculation of healthRatio done by the server
|
||||
// which is: healthRatio = 1 + (healthScale - 1) * health / maxHealth (if health > 0, 0 otherwise)
|
||||
// It's able to recover the exact health if maxHealth <= healthScale.
|
||||
int health = 0;
|
||||
if (lastRatio > 0)
|
||||
{
|
||||
int minHealth = 1;
|
||||
int maxHealth;
|
||||
if (lastHealthScale > 1)
|
||||
{
|
||||
if (lastRatio > 1)
|
||||
{
|
||||
// This doesn't apply if healthRatio = 1, because of the special case in the server calculation that
|
||||
// health = 0 forces healthRatio = 0 instead of the expected healthRatio = 1
|
||||
minHealth = (lastMaxHealth * (lastRatio - 1) + lastHealthScale - 2) / (lastHealthScale - 1);
|
||||
}
|
||||
maxHealth = (lastMaxHealth * lastRatio - 1) / (lastHealthScale - 1);
|
||||
if (maxHealth > lastMaxHealth)
|
||||
{
|
||||
maxHealth = lastMaxHealth;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If healthScale is 1, healthRatio will always be 1 unless health = 0
|
||||
// so we know nothing about the upper limit except that it can't be higher than maxHealth
|
||||
maxHealth = lastMaxHealth;
|
||||
}
|
||||
// Take the average of min and max possible healths
|
||||
health = (minHealth + maxHealth + 1) / 2;
|
||||
}
|
||||
int health = getExactHp(lastRatio, lastHealthScale, lastMaxHealth);
|
||||
|
||||
// Show both the hitpoint and percentage values if enabled in the config
|
||||
final ProgressBarComponent.LabelDisplayMode progressBarDisplayMode = displayStyle == HitpointsDisplayStyle.BOTH ?
|
||||
@@ -229,4 +172,47 @@ class OpponentInfoOverlay extends Overlay
|
||||
|
||||
return panelComponent.render(graphics);
|
||||
}
|
||||
|
||||
static int getExactHp(int ratio, int health, int maxHp)
|
||||
{
|
||||
if (ratio < 0 || health <= 0 || maxHp == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int exactHealth = 0;
|
||||
|
||||
// This is the reverse of the calculation of healthRatio done by the server
|
||||
// which is: healthRatio = 1 + (healthScale - 1) * health / maxHealth (if health > 0, 0 otherwise)
|
||||
// It's able to recover the exact health if maxHealth <= healthScale.
|
||||
if (ratio > 0)
|
||||
{
|
||||
int minHealth = 1;
|
||||
int maxHealth;
|
||||
if (health > 1)
|
||||
{
|
||||
if (ratio > 1)
|
||||
{
|
||||
// This doesn't apply if healthRatio = 1, because of the special case in the server calculation that
|
||||
// health = 0 forces healthRatio = 0 instead of the expected healthRatio = 1
|
||||
minHealth = (maxHp * (ratio - 1) + health - 2) / (health - 1);
|
||||
}
|
||||
maxHealth = (maxHp * ratio - 1) / (health - 1);
|
||||
if (maxHealth > maxHp)
|
||||
{
|
||||
maxHealth = maxHp;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If healthScale is 1, healthRatio will always be 1 unless health = 0
|
||||
// so we know nothing about the upper limit except that it can't be higher than maxHealth
|
||||
maxHealth = maxHp;
|
||||
}
|
||||
// Take the average of min and max possible healths
|
||||
exactHealth = (minHealth + maxHealth + 1) / 2;
|
||||
}
|
||||
|
||||
return exactHealth;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,24 +33,33 @@ import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.Actor;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.MenuEntry;
|
||||
import net.runelite.api.MenuOpcode;
|
||||
import net.runelite.api.NPC;
|
||||
import net.runelite.api.Player;
|
||||
import net.runelite.api.WorldType;
|
||||
import net.runelite.api.events.BeforeRender;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.api.events.GameTick;
|
||||
import net.runelite.api.events.InteractingChanged;
|
||||
import net.runelite.api.events.MenuEntryAdded;
|
||||
import net.runelite.api.events.MenuOpened;
|
||||
import net.runelite.api.util.Text;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.game.HiscoreManager;
|
||||
import net.runelite.client.game.NPCManager;
|
||||
import net.runelite.client.menus.MenuManager;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.ui.overlay.OverlayManager;
|
||||
import net.runelite.client.util.ColorUtil;
|
||||
import net.runelite.http.api.hiscore.HiscoreEndpoint;
|
||||
import net.runelite.http.api.hiscore.HiscoreResult;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "Opponent Information",
|
||||
@@ -58,9 +67,12 @@ import net.runelite.http.api.hiscore.HiscoreEndpoint;
|
||||
tags = {"combat", "health", "hitpoints", "npcs", "overlay"}
|
||||
)
|
||||
@Singleton
|
||||
@Slf4j
|
||||
public class OpponentInfoPlugin extends Plugin
|
||||
{
|
||||
private static final Duration WAIT = Duration.ofSeconds(5);
|
||||
private static final Object MENU = new Object();
|
||||
private static final int COLOR_TAG_LENGTH = 12;
|
||||
|
||||
@Inject
|
||||
private Client client;
|
||||
@@ -80,6 +92,15 @@ public class OpponentInfoPlugin extends Plugin
|
||||
@Inject
|
||||
private EventBus eventBus;
|
||||
|
||||
@Inject
|
||||
private HiscoreManager hiscoreManager;
|
||||
|
||||
@Inject
|
||||
private MenuManager menuManager;
|
||||
|
||||
@Inject
|
||||
private NPCManager npcManager;
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private HiscoreEndpoint hiscoreEndpoint = HiscoreEndpoint.NORMAL;
|
||||
|
||||
@@ -95,6 +116,11 @@ public class OpponentInfoPlugin extends Plugin
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private boolean showOpponentsOpponent;
|
||||
|
||||
private String attackingColTag;
|
||||
private boolean showAttackers;
|
||||
private boolean showAttacking;
|
||||
private boolean showHitpoints;
|
||||
|
||||
@Provides
|
||||
OpponentInfoConfig provideConfig(ConfigManager configManager)
|
||||
{
|
||||
@@ -104,6 +130,11 @@ public class OpponentInfoPlugin extends Plugin
|
||||
@Override
|
||||
protected void startUp() throws Exception
|
||||
{
|
||||
this.attackingColTag = ColorUtil.colorTag(config.attackingColor());
|
||||
this.showAttackers = config.showAttackersMenu();
|
||||
this.showAttacking = config.showAttackingMenu();
|
||||
this.showHitpoints = config.showHitpointsMenu();
|
||||
|
||||
updateConfig();
|
||||
addSubscriptions();
|
||||
|
||||
@@ -115,6 +146,7 @@ public class OpponentInfoPlugin extends Plugin
|
||||
protected void shutDown() throws Exception
|
||||
{
|
||||
eventBus.unregister(this);
|
||||
eventBus.unregister(MENU);
|
||||
|
||||
lastOpponent = null;
|
||||
lastTime = null;
|
||||
@@ -128,7 +160,20 @@ public class OpponentInfoPlugin extends Plugin
|
||||
eventBus.subscribe(GameStateChanged.class, this, this::onGameStateChanged);
|
||||
eventBus.subscribe(InteractingChanged.class, this, this::onInteractingChanged);
|
||||
eventBus.subscribe(GameTick.class, this, this::onGameTick);
|
||||
eventBus.subscribe(MenuEntryAdded.class, this, this::onMenuEntryAdded);
|
||||
updateMenuSubs();
|
||||
}
|
||||
|
||||
private void updateMenuSubs()
|
||||
{
|
||||
if (showAttackers || showAttacking || showHitpoints)
|
||||
{
|
||||
eventBus.subscribe(BeforeRender.class, MENU, this::onBeforeRender);
|
||||
eventBus.subscribe(MenuOpened.class, MENU, this::onMenuOpened);
|
||||
}
|
||||
else
|
||||
{
|
||||
eventBus.unregister(MENU);
|
||||
}
|
||||
}
|
||||
|
||||
private void onGameStateChanged(GameStateChanged gameStateChanged)
|
||||
@@ -194,6 +239,25 @@ public class OpponentInfoPlugin extends Plugin
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event.getKey())
|
||||
{
|
||||
case "showAttackersMenu":
|
||||
this.showAttackers = config.showAttackersMenu();
|
||||
updateMenuSubs();
|
||||
break;
|
||||
case "showAttackingMenu":
|
||||
this.showAttacking = config.showAttackingMenu();
|
||||
updateMenuSubs();
|
||||
break;
|
||||
case "showHitpointsMenu":
|
||||
this.showHitpoints = config.showHitpointsMenu();
|
||||
updateMenuSubs();
|
||||
break;
|
||||
case "attackingColor":
|
||||
attackingColTag = ColorUtil.colorTag(config.attackingColor());
|
||||
break;
|
||||
}
|
||||
|
||||
updateConfig();
|
||||
}
|
||||
|
||||
@@ -204,27 +268,253 @@ public class OpponentInfoPlugin extends Plugin
|
||||
this.showOpponentsOpponent = config.showOpponentsOpponent();
|
||||
}
|
||||
|
||||
private void onMenuEntryAdded(MenuEntryAdded menuEntryAdded)
|
||||
private void onBeforeRender(BeforeRender event)
|
||||
{
|
||||
if (menuEntryAdded.getOpcode() != MenuOpcode.NPC_SECOND_OPTION.getId()
|
||||
|| !menuEntryAdded.getOption().equals("Attack")
|
||||
|| !config.showOpponentsInMenu())
|
||||
if (client.getMenuOptionCount() <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int npcIndex = menuEntryAdded.getIdentifier();
|
||||
NPC npc = client.getCachedNPCs()[npcIndex];
|
||||
if (npc == null)
|
||||
if (client.isMenuOpen())
|
||||
{
|
||||
boolean changed = false;
|
||||
final MenuEntry[] entries = client.getMenuEntries();
|
||||
for (final MenuEntry entry : entries)
|
||||
{
|
||||
changed |= fixup(entry);
|
||||
}
|
||||
|
||||
if (changed)
|
||||
{
|
||||
client.setMenuEntries(entries);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (npc.getInteracting() == client.getLocalPlayer() || lastOpponent == npc)
|
||||
final MenuEntry entry = client.getLeftClickMenuEntry();
|
||||
if (modify(entry))
|
||||
{
|
||||
MenuEntry[] menuEntries = client.getMenuEntries();
|
||||
menuEntries[menuEntries.length - 1].setTarget("*" + menuEntryAdded.getTarget());
|
||||
client.setMenuEntries(menuEntries);
|
||||
client.setLeftClickMenuEntry(entry);
|
||||
}
|
||||
}
|
||||
|
||||
private void onMenuOpened(MenuOpened event)
|
||||
{
|
||||
boolean changed = false;
|
||||
for (MenuEntry entry : event.getMenuEntries())
|
||||
{
|
||||
changed |= modify(entry);
|
||||
}
|
||||
|
||||
if (changed)
|
||||
{
|
||||
event.setModified();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean modify(MenuEntry entry)
|
||||
{
|
||||
if (isNotAttackEntry(entry))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean changed = false;
|
||||
|
||||
int index = entry.getIdentifier();
|
||||
Actor actor = getActorFromIndex(index);
|
||||
|
||||
if (actor == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (actor instanceof Player)
|
||||
{
|
||||
index -= 32768;
|
||||
}
|
||||
|
||||
String target = entry.getTarget();
|
||||
|
||||
if (showAttacking &&
|
||||
client.getLocalPlayer().getRSInteracting() == index)
|
||||
{
|
||||
target = attackingColTag + target.substring(COLOR_TAG_LENGTH);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (showAttackers &&
|
||||
actor.getRSInteracting() - 32768 == client.getLocalPlayerIndex())
|
||||
{
|
||||
target = '*' + target;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (showHitpoints &&
|
||||
actor.getHealth() > 0)
|
||||
{
|
||||
int lvlIndex = target.lastIndexOf("(level-");
|
||||
if (lvlIndex != -1)
|
||||
{
|
||||
String levelReplacement = getHpString(actor, true);
|
||||
|
||||
target = target.substring(0, lvlIndex) + levelReplacement;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (changed)
|
||||
{
|
||||
entry.setTarget(target);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean fixup(MenuEntry entry)
|
||||
{
|
||||
if (isNotAttackEntry(entry))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int index = entry.getIdentifier();
|
||||
|
||||
Actor actor = getActorFromIndex(index);
|
||||
|
||||
if (actor == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (actor instanceof Player)
|
||||
{
|
||||
index -= 32768;
|
||||
}
|
||||
|
||||
String target = entry.getTarget();
|
||||
|
||||
boolean hasAggro = actor.getRSInteracting() - 32768 == client.getLocalPlayerIndex();
|
||||
boolean hadAggro = target.charAt(0) == '*';
|
||||
boolean isTarget = client.getLocalPlayer().getRSInteracting() == index;
|
||||
boolean hasHp = showHitpoints && actor instanceof NPC && actor.getHealth() > 0;
|
||||
|
||||
boolean aggroChanged = showAttackers && hasAggro != hadAggro;
|
||||
boolean targetChanged = showAttacking && isTarget != target.startsWith(attackingColTag, aggroChanged ? 1 : 0);
|
||||
boolean hpChanged = showHitpoints && hasHp == target.contains("(level-");
|
||||
|
||||
if (!aggroChanged &&
|
||||
!targetChanged &&
|
||||
!hasHp &&
|
||||
!hpChanged)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (targetChanged)
|
||||
{
|
||||
boolean player = actor instanceof Player;
|
||||
final int start = hadAggro ? 1 + COLOR_TAG_LENGTH : COLOR_TAG_LENGTH;
|
||||
target =
|
||||
(hasAggro ? '*' : "") +
|
||||
(isTarget ? attackingColTag :
|
||||
player ? ColorUtil.colorStartTag(0xffffff) : ColorUtil.colorStartTag(0xffff00)) +
|
||||
target.substring(start);
|
||||
}
|
||||
else if (aggroChanged)
|
||||
{
|
||||
if (hasAggro)
|
||||
{
|
||||
target = '*' + target;
|
||||
}
|
||||
else
|
||||
{
|
||||
target = target.substring(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (hpChanged || hasHp)
|
||||
{
|
||||
final int braceIdx;
|
||||
|
||||
if (!hasHp)
|
||||
{
|
||||
braceIdx = target.lastIndexOf("<col=ff0000>(");
|
||||
if (braceIdx != -1)
|
||||
{
|
||||
target = target.substring(0, braceIdx - 1) + "(level-" + actor.getCombatLevel() + ")";
|
||||
}
|
||||
}
|
||||
else if ((braceIdx = target.lastIndexOf('(')) != -1)
|
||||
{
|
||||
final String hpString = getHpString(actor, hpChanged);
|
||||
|
||||
target = target.substring(0, braceIdx) + hpString;
|
||||
}
|
||||
}
|
||||
|
||||
entry.setTarget(target);
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean isNotAttackEntry(MenuEntry entry)
|
||||
{
|
||||
return entry.getOpcode() != MenuOpcode.NPC_SECOND_OPTION.getId() &&
|
||||
entry.getOpcode() != menuManager.getPlayerAttackOpcode()
|
||||
|| !entry.getOption().equals("Attack");
|
||||
}
|
||||
|
||||
private String getHpString(Actor actor, boolean withColorTag)
|
||||
{
|
||||
int maxHp = getMaxHp(actor);
|
||||
int health = actor.getHealth();
|
||||
int ratio = actor.getHealthRatio();
|
||||
|
||||
final String result;
|
||||
if (maxHp != -1)
|
||||
{
|
||||
final int exactHealth = OpponentInfoOverlay.getExactHp(ratio, health, maxHp);
|
||||
result = "(" + exactHealth + "/" + maxHp + ")";
|
||||
}
|
||||
else
|
||||
{
|
||||
result = "(" + (100 * ratio) / health + "%)";
|
||||
}
|
||||
|
||||
return withColorTag ? ColorUtil.colorStartTag(0xff0000) + result : result;
|
||||
}
|
||||
|
||||
int getMaxHp(Actor actor)
|
||||
{
|
||||
if (actor instanceof NPC)
|
||||
{
|
||||
return npcManager.getHealth(((NPC) actor).getId());
|
||||
}
|
||||
else
|
||||
{
|
||||
final HiscoreResult hiscoreResult = hiscoreManager.lookupAsync(Text.removeTags(actor.getName()), getHiscoreEndpoint());
|
||||
if (hiscoreResult != null)
|
||||
{
|
||||
final int hp = hiscoreResult.getHitpoints().getLevel();
|
||||
if (hp > 0)
|
||||
{
|
||||
return hp;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
private Actor getActorFromIndex(int index)
|
||||
{
|
||||
if (index < 32768)
|
||||
{
|
||||
return client.getCachedNPCs()[index];
|
||||
}
|
||||
else
|
||||
{
|
||||
return client.getCachedPlayers()[index - 32768];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import net.runelite.mapping.Import;
|
||||
public interface RSActor extends RSEntity, Actor
|
||||
{
|
||||
@Import("targetIndex")
|
||||
@Override
|
||||
int getRSInteracting();
|
||||
|
||||
// Overhead text
|
||||
|
||||
@@ -208,6 +208,10 @@ public interface RSClient extends RSGameShell, Client
|
||||
@Override
|
||||
RSPlayer getLocalPlayer();
|
||||
|
||||
@Import("localPlayerIndex")
|
||||
@Override
|
||||
int getLocalPlayerIndex();
|
||||
|
||||
@Import("npcCount")
|
||||
int getNpcIndexesCount();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user