From f5d8c268137247c83d8d944f8c9b0156cb95ca35 Mon Sep 17 00:00:00 2001 From: Ron Young Date: Fri, 5 Oct 2018 05:09:29 -0500 Subject: [PATCH] More accurate NPC hp overlay when max hp is known (#5528) Closes #58 Closes #2509 Co-authored-by: henke96 --- .../opponentinfo/OpponentInfoOverlay.java | 47 ++++++++++++++++--- 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfoOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfoOverlay.java index 1c637facaf..9a2729e809 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfoOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfoOverlay.java @@ -61,7 +61,8 @@ class OpponentInfoOverlay extends Overlay private final PanelComponent panelComponent = new PanelComponent(); private Integer lastMaxHealth; - private float lastRatio = 0; + private int lastRatio = 0; + private int lastHealthScale = 0; private String opponentName; private String opponentsOpponentName; @@ -94,7 +95,8 @@ class OpponentInfoOverlay extends Overlay if (opponent.getName() != null && opponent.getHealth() > 0) { - lastRatio = (float) opponent.getHealthRatio() / (float) opponent.getHealth(); + lastRatio = opponent.getHealthRatio(); + lastHealthScale = opponent.getHealth(); opponentName = Text.removeTags(opponent.getName()); lastMaxHealth = null; @@ -117,7 +119,7 @@ class OpponentInfoOverlay extends Overlay final Actor opponentsOpponent = opponent.getInteracting(); if (opponentsOpponent != null - && (opponentsOpponent != client.getLocalPlayer() || client.getVar(Varbits.MULTICOMBAT_AREA) == 1)) + && (opponentsOpponent != client.getLocalPlayer() || client.getVar(Varbits.MULTICOMBAT_AREA) == 1)) { opponentsOpponentName = Text.removeTags(opponentsOpponent.getName()); } @@ -144,7 +146,7 @@ class OpponentInfoOverlay extends Overlay .build()); // Health bar - if (lastRatio >= 0) + if (lastRatio >= 0 && lastHealthScale > 0) { final ProgressBarComponent progressBarComponent = new ProgressBarComponent(); progressBarComponent.setBackgroundColor(HP_RED); @@ -152,13 +154,46 @@ class OpponentInfoOverlay extends Overlay if (lastMaxHealth != null && !opponentInfoConfig.showPercent()) { + // 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 healts + health = (minHealth + maxHealth + 1) / 2; + } + progressBarComponent.setLabelDisplayMode(ProgressBarComponent.LabelDisplayMode.FULL); progressBarComponent.setMaximum(lastMaxHealth); - progressBarComponent.setValue(lastRatio * lastMaxHealth); + progressBarComponent.setValue(health); } else { - progressBarComponent.setValue(lastRatio * 100d); + float floatRatio = (float) lastRatio / (float) lastHealthScale; + progressBarComponent.setValue(floatRatio * 100d); } panelComponent.getChildren().add(progressBarComponent);