From 48ea01dd28fbd6e132faacc0f9d5587fb0d7db2d Mon Sep 17 00:00:00 2001 From: chaticon Date: Tue, 9 Feb 2021 22:33:33 -0800 Subject: [PATCH] opponentinfo: Show health bar of actors attacking the player --- .../opponentinfo/OpponentInfoPlugin.java | 46 ++-- .../opponentinfo/OpponentInfoPluginTest.java | 197 +++++++++++++++++- 2 files changed, 219 insertions(+), 24 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfoPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfoPlugin.java index 65fcf0af05..b3f0b145ed 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfoPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfoPlugin.java @@ -1,6 +1,7 @@ /* * Copyright (c) 2016-2018, Adam * Copyright (c) 2018, Jordan Atwood + * Copyright (c) 2021, Andre Araya * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -137,33 +138,50 @@ public class OpponentInfoPlugin extends Plugin @Subscribe public void onInteractingChanged(InteractingChanged event) { - if (event.getSource() != client.getLocalPlayer()) + final Actor player = client.getLocalPlayer(); + if (player == null) { return; } + final Actor opponent = player.getInteracting(); + final Actor source = event.getSource(); + final Actor target = event.getTarget(); - Actor opponent = event.getTarget(); - - if (opponent == null) + if (source == player) + { + // You have attacked an enemy + if (target != null) + { + lastOpponent = target; + lastTime = null; + } + // You have stopped attacking an enemy which is not attacking you + else if (lastOpponent != null && lastOpponent.getInteracting() != player) + { + lastTime = Instant.now(); + } + } + // You are attacked while not attacking anything + else if (target == player && opponent == null) + { + lastOpponent = source; + lastTime = null; + } + // An enemy which was previously attacking you (which you were not attacking back) has changed its target + else if (source == lastOpponent && opponent != lastOpponent) { lastTime = Instant.now(); - return; } - - lastOpponent = opponent; } @Subscribe public void onGameTick(GameTick gameTick) { - if (lastOpponent != null - && lastTime != null - && client.getLocalPlayer().getInteracting() == null) + if (lastTime != null + && Duration.between(lastTime, Instant.now()).compareTo(WAIT) > 0) { - if (Duration.between(lastTime, Instant.now()).compareTo(WAIT) > 0) - { - lastOpponent = null; - } + lastOpponent = null; + lastTime = null; } } diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/opponentinfo/OpponentInfoPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/opponentinfo/OpponentInfoPluginTest.java index 4b213bde95..e288170d83 100644 --- a/runelite-client/src/test/java/net/runelite/client/plugins/opponentinfo/OpponentInfoPluginTest.java +++ b/runelite-client/src/test/java/net/runelite/client/plugins/opponentinfo/OpponentInfoPluginTest.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2021, Jordan Atwood + * Copyright (c) 2021, Andre Araya * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -88,13 +89,14 @@ public class OpponentInfoPluginTest interactingChanged(npc, localPlayer); - assertNull(plugin.getLastOpponent()); + assertSame(npc, plugin.getLastOpponent()); assertNull(plugin.getLastTime()); interactingChanged(npc, null); - assertNull(plugin.getLastOpponent()); - assertNull(plugin.getLastTime()); + // last opponent is remembered for 5 seconds + assertSame(npc, plugin.getLastOpponent()); + assertNotNull(plugin.getLastTime()); interactingChanged(localPlayer, npc); @@ -108,9 +110,9 @@ public class OpponentInfoPluginTest interactingChanged(localPlayer, null); - // last opponent is remembered for 5 seconds + // last opponent is remembered as it is still attacking the player assertSame(npc, plugin.getLastOpponent()); - assertNotNull(plugin.getLastTime()); + assertNull(plugin.getLastTime()); } @Test @@ -120,13 +122,14 @@ public class OpponentInfoPluginTest interactingChanged(otherPlayer, localPlayer); - assertNull(plugin.getLastOpponent()); + assertSame(otherPlayer, plugin.getLastOpponent()); assertNull(plugin.getLastTime()); interactingChanged(otherPlayer, null); - assertNull(plugin.getLastOpponent()); - assertNull(plugin.getLastTime()); + // last opponent is remembered for 5 seconds + assertSame(otherPlayer, plugin.getLastOpponent()); + assertNotNull(plugin.getLastTime()); interactingChanged(localPlayer, otherPlayer); @@ -140,9 +143,9 @@ public class OpponentInfoPluginTest interactingChanged(localPlayer, null); - // last opponent is remembered for 5 seconds + // last opponent is remembered as it is still attacking the player assertSame(otherPlayer, plugin.getLastOpponent()); - assertNotNull(plugin.getLastTime()); + assertNull(plugin.getLastTime()); } @Test @@ -172,6 +175,180 @@ public class OpponentInfoPluginTest assertNull(plugin.getLastTime()); } + /* + * Verify that the current opponent in multi is always the npc that the player is attacking + */ + @Test + public void testAttackingEnemyInMulti() + { + final Player otherPlayer = mock(Player.class); + final NPC aggro = mock(NPC.class), attacked = mock(NPC.class); + + interactingChanged(localPlayer, null); + + // verify that there is currently no opponent + assertNull(plugin.getLastOpponent()); + + // some npc attacks the player + interactingChanged(aggro, localPlayer); + + // verify that the current opponent is the aggressive npc + assertSame(aggro, plugin.getLastOpponent()); + + // the player attacks a different npc + interactingChanged(localPlayer, attacked); + + // verify the attacked npc is now considered the current opponent + assertSame(attacked, plugin.getLastOpponent()); + + // the npc attacks them back + interactingChanged(attacked, localPlayer); + + // verify that the current opponent is still the attacked npc + assertSame(attacked, plugin.getLastOpponent()); + + // the player is attacked by an aggressive npc while attacking a different npc + interactingChanged(aggro, localPlayer); + + // verify that the current opponent is still the npc the player is attacking + assertSame(attacked, plugin.getLastOpponent()); + + // the npc attacking the player that is not the current opponent attacks a different player + interactingChanged(aggro, otherPlayer); + + // verify that the current opponent is still the npc the player is attacking + assertSame(attacked, plugin.getLastOpponent()); + + // the npc the player is attacking, the current opponent, attacks a different player + interactingChanged(attacked, otherPlayer); + + // verify that the current opponent is still the npc the player is attacking + assertSame(attacked, plugin.getLastOpponent()); + } + + /* + * Verify that the current opponent is the expected npc while the player is not attacking anything + */ + @Test + public void testIdleInMulti() + { + final Player otherPlayer = mock(Player.class); + final NPC aggroFirst = mock(NPC.class), aggroRecent = mock(NPC.class); + + interactingChanged(localPlayer, null); + + // verify that there is currently no opponent + assertNull(plugin.getLastOpponent()); + + // some npc attacks the player + interactingChanged(aggroFirst, localPlayer); + + // verify that the current opponent is the aggressive npc + assertSame(aggroFirst, plugin.getLastOpponent()); + + // the player is attacked by a different npc + interactingChanged(aggroRecent, localPlayer); + + // verify that the current opponent is the most recent aggressor + assertSame(aggroRecent, plugin.getLastOpponent()); + + // an npc that is not the current opponent targets another player + interactingChanged(aggroFirst, otherPlayer); + + // verify that the current opponent is still the most recent aggressor + assertSame(aggroRecent, plugin.getLastOpponent()); + + // the current opponent switches targets to another player + interactingChanged(aggroRecent, otherPlayer); + + // verify that there is no longer an opponent + // (if lastTime is not null, then the lastOpponent will become null after OpponentInfoPlugin.WAIT time) + assertNotNull(plugin.getLastTime()); + } + + /* + * Verify that the current opponent is the expected npc in singles + */ + @Test + public void testSingles() + { + final Player otherPlayer = mock(Player.class); + final NPC npc = mock(NPC.class); + + interactingChanged(localPlayer, null); + + // verify that there is currently no opponent + assertNull(plugin.getLastOpponent()); + + // some npc attacks the player + interactingChanged(npc, localPlayer); + + // verify that the attacking npc is the current opponent + assertSame(npc, plugin.getLastOpponent()); + + // the npc stops attacking the player + interactingChanged(npc, null); + + // verify that there is no longer an opponent + // (if lastTime is not null, then the lastOpponent will become null after OpponentInfoPlugin.WAIT time) + assertNotNull(plugin.getLastTime()); + + // the player attacks the npc + interactingChanged(localPlayer, npc); + + // verify that the attacked npc is the current opponent + assertSame(npc, plugin.getLastOpponent()); + // verify that the hp bar will no longer be hidden + assertNull(plugin.getLastTime()); + + // the npc attacks them back + interactingChanged(npc, localPlayer); + + // verify that the attacked npc is still the current opponent + assertSame(npc, plugin.getLastOpponent()); + + // the player stops attacking the npc + interactingChanged(localPlayer, null); + + // verify that the npc attacking the player is still the current opponent + assertSame(npc, plugin.getLastOpponent()); + // verify that the hp bar will not be hidden (because the npc is still attacking the player) + assertNull(plugin.getLastTime()); + + // the player attacks the npc again + interactingChanged(localPlayer, npc); + + // verify the npc is still the opponent + assertSame(npc, plugin.getLastOpponent()); + + // the npc stops attacking the player + interactingChanged(npc, null); + + // verify that the attacked npc is still the current opponent + assertSame(npc, plugin.getLastOpponent()); + + // the player stops attacking the npc while the npc is not attacking the player + interactingChanged(localPlayer, null); + + // verify that there is no longer an opponent + // (if lastTime is not null, then the lastOpponent will become null after OpponentInfoPlugin.WAIT time) + assertNotNull(plugin.getLastTime()); + + // the npc attacks a different player + interactingChanged(npc, otherPlayer); + + // verify there is still no opponent + // (if lastTime is not null, then the lastOpponent will become null after OpponentInfoPlugin.WAIT time) + assertNotNull(plugin.getLastTime()); + + // the npc stops attacking the other player + interactingChanged(npc, null); + + // verify there is still no opponent + // (if lastTime is not null, then the lastOpponent will become null after OpponentInfoPlugin.WAIT time) + assertNotNull(plugin.getLastTime()); + } + private void interactingChanged(final Actor source, final Actor target) { when(source.getInteracting()).thenReturn(target);