Show opponents hp in menu, your target colored, targeting you *

This commit is contained in:
Lucwousin
2019-10-24 12:01:46 +02:00
parent e5d259d56e
commit e2f8f0af32
8 changed files with 441 additions and 83 deletions

View File

@@ -64,8 +64,11 @@ public interface Actor extends Entity, Locatable
* </ul> * </ul>
* *
* @return the actor, null if no interaction is occurring * @return the actor, null if no interaction is occurring
*
* (getRSInteracting returns the npc/player index, useful for menus)
*/ */
Actor getInteracting(); Actor getInteracting();
int getRSInteracting();
/** /**
* Gets the health ratio of the actor. * Gets the health ratio of the actor.

View File

@@ -341,9 +341,12 @@ public interface Client extends GameShell
* Gets the logged in player instance. * Gets the logged in player instance.
* *
* @return the logged in player * @return the logged in player
*
* (getLocalPlayerIndex returns the local index, useful for menus/interacting)
*/ */
@Nullable @Nullable
Player getLocalPlayer(); Player getLocalPlayer();
int getLocalPlayerIndex();
/** /**
* Gets the item composition corresponding to an items ID. * Gets the item composition corresponding to an items ID.

View File

@@ -91,6 +91,8 @@ public class MenuManager
private MenuEntry leftClickEntry = null; private MenuEntry leftClickEntry = null;
private MenuEntry firstEntry = null; private MenuEntry firstEntry = null;
private int playerAttackIdx = -1;
@Inject @Inject
private MenuManager(Client client, EventBus eventBus) private MenuManager(Client client, EventBus eventBus)
{ {
@@ -500,6 +502,29 @@ public class MenuManager
return index; 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 * 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); AbstractComparableEntry entry = newBaseComparableEntry(option, target);
priorityEntries.removeIf(entry::equals); priorityEntries.remove(entry);
} }
@@ -562,7 +587,7 @@ public class MenuManager
public void removePriorityEntry(AbstractComparableEntry entry) public void removePriorityEntry(AbstractComparableEntry entry)
{ {
priorityEntries.removeIf(entry::equals); priorityEntries.remove(entry);
} }
public void removePriorityEntry(String option) public void removePriorityEntry(String option)
@@ -571,7 +596,7 @@ public class MenuManager
AbstractComparableEntry entry = newBaseComparableEntry(option, "", false); AbstractComparableEntry entry = newBaseComparableEntry(option, "", false);
priorityEntries.removeIf(entry::equals); priorityEntries.remove(entry);
} }
public void removePriorityEntry(String option, boolean strictOption) public void removePriorityEntry(String option, boolean strictOption)
@@ -581,7 +606,17 @@ public class MenuManager
AbstractComparableEntry entry = AbstractComparableEntry entry =
newBaseComparableEntry(option, "", -1, -1, false, strictOption); 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);
} }
/** /**

View File

@@ -24,6 +24,7 @@
*/ */
package net.runelite.client.plugins.opponentinfo; package net.runelite.client.plugins.opponentinfo;
import java.awt.Color;
import net.runelite.client.config.Config; import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem; import net.runelite.client.config.ConfigItem;
@@ -65,12 +66,47 @@ public interface OpponentInfoConfig extends Config
} }
@ConfigItem( @ConfigItem(
keyName = "showOpponentsInMenu", keyName = "showAttackersMenu",
name = "Show opponents in menu", name = "Show attackers in menu",
description = "Marks opponents names in the menu which you are attacking or are attacking you (NPC only)", description = "Marks attackers' names in menus with a *<br>",
position = 3 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; return false;
} }

View File

@@ -36,11 +36,7 @@ import javax.inject.Singleton;
import net.runelite.api.Actor; import net.runelite.api.Actor;
import net.runelite.api.Client; import net.runelite.api.Client;
import static net.runelite.api.MenuOpcode.RUNELITE_OVERLAY_CONFIG; 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.api.Varbits;
import net.runelite.client.game.HiscoreManager;
import net.runelite.client.game.NPCManager;
import net.runelite.client.ui.overlay.Overlay; import net.runelite.client.ui.overlay.Overlay;
import static net.runelite.client.ui.overlay.OverlayManager.OPTION_CONFIGURE; import static net.runelite.client.ui.overlay.OverlayManager.OPTION_CONFIGURE;
import net.runelite.client.ui.overlay.OverlayMenuEntry; 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.ProgressBarComponent;
import net.runelite.client.ui.overlay.components.TitleComponent; import net.runelite.client.ui.overlay.components.TitleComponent;
import net.runelite.api.util.Text; import net.runelite.api.util.Text;
import net.runelite.http.api.hiscore.HiscoreResult;
@Singleton @Singleton
class OpponentInfoOverlay extends Overlay class OpponentInfoOverlay extends Overlay
@@ -61,8 +56,6 @@ class OpponentInfoOverlay extends Overlay
private final Client client; private final Client client;
private final OpponentInfoPlugin opponentInfoPlugin; private final OpponentInfoPlugin opponentInfoPlugin;
private final HiscoreManager hiscoreManager;
private final NPCManager npcManager;
private final PanelComponent panelComponent = new PanelComponent(); private final PanelComponent panelComponent = new PanelComponent();
@@ -75,15 +68,11 @@ class OpponentInfoOverlay extends Overlay
@Inject @Inject
private OpponentInfoOverlay( private OpponentInfoOverlay(
final Client client, final Client client,
final OpponentInfoPlugin opponentInfoPlugin, final OpponentInfoPlugin opponentInfoPlugin)
final HiscoreManager hiscoreManager,
final NPCManager npcManager)
{ {
super(opponentInfoPlugin); super(opponentInfoPlugin);
this.client = client; this.client = client;
this.opponentInfoPlugin = opponentInfoPlugin; this.opponentInfoPlugin = opponentInfoPlugin;
this.hiscoreManager = hiscoreManager;
this.npcManager = npcManager;
setPosition(OverlayPosition.TOP_LEFT); setPosition(OverlayPosition.TOP_LEFT);
setPriority(OverlayPriority.HIGH); setPriority(OverlayPriority.HIGH);
@@ -110,23 +99,7 @@ class OpponentInfoOverlay extends Overlay
lastHealthScale = opponent.getHealth(); lastHealthScale = opponent.getHealth();
opponentName = Text.removeTags(opponent.getName()); opponentName = Text.removeTags(opponent.getName());
lastMaxHealth = -1; lastMaxHealth = opponentInfoPlugin.getMaxHp(opponent);
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;
}
}
}
final Actor opponentsOpponent = opponent.getInteracting(); final Actor opponentsOpponent = opponent.getInteracting();
if (opponentsOpponent != null if (opponentsOpponent != null
@@ -168,37 +141,7 @@ class OpponentInfoOverlay extends Overlay
if ((displayStyle == HitpointsDisplayStyle.HITPOINTS || displayStyle == HitpointsDisplayStyle.BOTH) if ((displayStyle == HitpointsDisplayStyle.HITPOINTS || displayStyle == HitpointsDisplayStyle.BOTH)
&& lastMaxHealth != -1) && lastMaxHealth != -1)
{ {
// This is the reverse of the calculation of healthRatio done by the server int health = getExactHp(lastRatio, lastHealthScale, lastMaxHealth);
// 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;
}
// Show both the hitpoint and percentage values if enabled in the config // Show both the hitpoint and percentage values if enabled in the config
final ProgressBarComponent.LabelDisplayMode progressBarDisplayMode = displayStyle == HitpointsDisplayStyle.BOTH ? final ProgressBarComponent.LabelDisplayMode progressBarDisplayMode = displayStyle == HitpointsDisplayStyle.BOTH ?
@@ -229,4 +172,47 @@ class OpponentInfoOverlay extends Overlay
return panelComponent.render(graphics); 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;
}
} }

View File

@@ -33,24 +33,33 @@ import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import lombok.AccessLevel; import lombok.AccessLevel;
import lombok.Getter; import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Actor; import net.runelite.api.Actor;
import net.runelite.api.Client; import net.runelite.api.Client;
import net.runelite.api.GameState; import net.runelite.api.GameState;
import net.runelite.api.MenuEntry; import net.runelite.api.MenuEntry;
import net.runelite.api.MenuOpcode; import net.runelite.api.MenuOpcode;
import net.runelite.api.NPC; import net.runelite.api.NPC;
import net.runelite.api.Player;
import net.runelite.api.WorldType; import net.runelite.api.WorldType;
import net.runelite.api.events.BeforeRender;
import net.runelite.api.events.ConfigChanged; import net.runelite.api.events.ConfigChanged;
import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.GameStateChanged;
import net.runelite.api.events.GameTick; import net.runelite.api.events.GameTick;
import net.runelite.api.events.InteractingChanged; 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.config.ConfigManager;
import net.runelite.client.eventbus.EventBus; 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.Plugin;
import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.ui.overlay.OverlayManager; 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.HiscoreEndpoint;
import net.runelite.http.api.hiscore.HiscoreResult;
@PluginDescriptor( @PluginDescriptor(
name = "Opponent Information", name = "Opponent Information",
@@ -58,9 +67,12 @@ import net.runelite.http.api.hiscore.HiscoreEndpoint;
tags = {"combat", "health", "hitpoints", "npcs", "overlay"} tags = {"combat", "health", "hitpoints", "npcs", "overlay"}
) )
@Singleton @Singleton
@Slf4j
public class OpponentInfoPlugin extends Plugin public class OpponentInfoPlugin extends Plugin
{ {
private static final Duration WAIT = Duration.ofSeconds(5); private static final Duration WAIT = Duration.ofSeconds(5);
private static final Object MENU = new Object();
private static final int COLOR_TAG_LENGTH = 12;
@Inject @Inject
private Client client; private Client client;
@@ -80,6 +92,15 @@ public class OpponentInfoPlugin extends Plugin
@Inject @Inject
private EventBus eventBus; private EventBus eventBus;
@Inject
private HiscoreManager hiscoreManager;
@Inject
private MenuManager menuManager;
@Inject
private NPCManager npcManager;
@Getter(AccessLevel.PACKAGE) @Getter(AccessLevel.PACKAGE)
private HiscoreEndpoint hiscoreEndpoint = HiscoreEndpoint.NORMAL; private HiscoreEndpoint hiscoreEndpoint = HiscoreEndpoint.NORMAL;
@@ -95,6 +116,11 @@ public class OpponentInfoPlugin extends Plugin
@Getter(AccessLevel.PACKAGE) @Getter(AccessLevel.PACKAGE)
private boolean showOpponentsOpponent; private boolean showOpponentsOpponent;
private String attackingColTag;
private boolean showAttackers;
private boolean showAttacking;
private boolean showHitpoints;
@Provides @Provides
OpponentInfoConfig provideConfig(ConfigManager configManager) OpponentInfoConfig provideConfig(ConfigManager configManager)
{ {
@@ -104,6 +130,11 @@ public class OpponentInfoPlugin extends Plugin
@Override @Override
protected void startUp() throws Exception protected void startUp() throws Exception
{ {
this.attackingColTag = ColorUtil.colorTag(config.attackingColor());
this.showAttackers = config.showAttackersMenu();
this.showAttacking = config.showAttackingMenu();
this.showHitpoints = config.showHitpointsMenu();
updateConfig(); updateConfig();
addSubscriptions(); addSubscriptions();
@@ -115,6 +146,7 @@ public class OpponentInfoPlugin extends Plugin
protected void shutDown() throws Exception protected void shutDown() throws Exception
{ {
eventBus.unregister(this); eventBus.unregister(this);
eventBus.unregister(MENU);
lastOpponent = null; lastOpponent = null;
lastTime = null; lastTime = null;
@@ -128,7 +160,20 @@ public class OpponentInfoPlugin extends Plugin
eventBus.subscribe(GameStateChanged.class, this, this::onGameStateChanged); eventBus.subscribe(GameStateChanged.class, this, this::onGameStateChanged);
eventBus.subscribe(InteractingChanged.class, this, this::onInteractingChanged); eventBus.subscribe(InteractingChanged.class, this, this::onInteractingChanged);
eventBus.subscribe(GameTick.class, this, this::onGameTick); 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) private void onGameStateChanged(GameStateChanged gameStateChanged)
@@ -194,6 +239,25 @@ public class OpponentInfoPlugin extends Plugin
return; 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(); updateConfig();
} }
@@ -204,27 +268,253 @@ public class OpponentInfoPlugin extends Plugin
this.showOpponentsOpponent = config.showOpponentsOpponent(); this.showOpponentsOpponent = config.showOpponentsOpponent();
} }
private void onMenuEntryAdded(MenuEntryAdded menuEntryAdded) private void onBeforeRender(BeforeRender event)
{ {
if (menuEntryAdded.getOpcode() != MenuOpcode.NPC_SECOND_OPTION.getId() if (client.getMenuOptionCount() <= 0)
|| !menuEntryAdded.getOption().equals("Attack")
|| !config.showOpponentsInMenu())
{ {
return; return;
} }
if (client.isMenuOpen())
int npcIndex = menuEntryAdded.getIdentifier();
NPC npc = client.getCachedNPCs()[npcIndex];
if (npc == null)
{ {
boolean changed = false;
final MenuEntry[] entries = client.getMenuEntries();
for (final MenuEntry entry : entries)
{
changed |= fixup(entry);
}
if (changed)
{
client.setMenuEntries(entries);
}
return; return;
} }
if (npc.getInteracting() == client.getLocalPlayer() || lastOpponent == npc) final MenuEntry entry = client.getLeftClickMenuEntry();
if (modify(entry))
{ {
MenuEntry[] menuEntries = client.getMenuEntries(); client.setLeftClickMenuEntry(entry);
menuEntries[menuEntries.length - 1].setTarget("*" + menuEntryAdded.getTarget()); }
client.setMenuEntries(menuEntries); }
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];
} }
} }
} }

View File

@@ -30,6 +30,7 @@ import net.runelite.mapping.Import;
public interface RSActor extends RSEntity, Actor public interface RSActor extends RSEntity, Actor
{ {
@Import("targetIndex") @Import("targetIndex")
@Override
int getRSInteracting(); int getRSInteracting();
// Overhead text // Overhead text

View File

@@ -208,6 +208,10 @@ public interface RSClient extends RSGameShell, Client
@Override @Override
RSPlayer getLocalPlayer(); RSPlayer getLocalPlayer();
@Import("localPlayerIndex")
@Override
int getLocalPlayerIndex();
@Import("npcCount") @Import("npcCount")
int getNpcIndexesCount(); int getNpcIndexesCount();