cluescroll plugin: Clear stale location clue hint arrows

Location clue scrolls added a hint arrow when the player was nearby one
of the clue's locations. It did not, however clear that arrow if the
locations were changed and the previously-set hint arrow location was no
longer marked. This commit updates this behavior to clear the active
hint arrow each game tick before re-adding any location hint arrows.
(and if no NPC hint arrows are set)

Fixes runelite/runelite#10370
This commit is contained in:
Jordan Atwood
2020-01-26 22:18:23 -08:00
committed by Adam
parent 86d8bd9d1a
commit 9e560d91e3
2 changed files with 110 additions and 5 deletions

View File

@@ -396,14 +396,17 @@ public class ClueScrollPlugin extends Plugin
if (clue instanceof LocationClueScroll)
{
final WorldPoint[] locations = ((LocationClueScroll) clue).getLocations();
final boolean npcHintArrowMarked = client.getHintArrowNpc() != null && npcsToMark.contains(client.getHintArrowNpc());
if (!npcHintArrowMarked)
{
client.clearHintArrow();
}
for (WorldPoint location : locations)
{
// Only set the location hint arrow if we do not already have more accurate location
if (location.isInScene(client)
&& config.displayHintArrows()
&& (client.getHintArrowNpc() == null
|| !npcsToMark.contains(client.getHintArrowNpc())))
if (location.isInScene(client) && config.displayHintArrows() && !npcHintArrowMarked)
{
client.setHintArrow(location);
}

View File

@@ -25,13 +25,68 @@
*/
package net.runelite.client.plugins.cluescrolls;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.name.Named;
import com.google.inject.testing.fieldbinder.Bind;
import com.google.inject.testing.fieldbinder.BoundFieldModule;
import net.runelite.api.ChatMessageType;
import net.runelite.api.Client;
import net.runelite.api.NPC;
import net.runelite.api.Player;
import net.runelite.api.coords.WorldPoint;
import net.runelite.api.events.ChatMessage;
import net.runelite.api.events.GameTick;
import net.runelite.api.widgets.Widget;
import net.runelite.api.widgets.WidgetInfo;
import net.runelite.client.game.ItemManager;
import net.runelite.client.plugins.cluescrolls.clues.hotcold.HotColdLocation;
import net.runelite.client.ui.overlay.OverlayManager;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.mockito.ArgumentMatchers.any;
import org.mockito.Mock;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class ClueScrollPluginTest
{
@Mock
@Bind
Client client;
@Inject
ClueScrollPlugin plugin;
@Bind
@Named("developerMode")
boolean developerMode;
@Mock
@Bind
ClueScrollConfig config;
@Mock
@Bind
OverlayManager overlayManager;
@Mock
@Bind
ItemManager itemManager;
@Before
public void before()
{
Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this);
}
@Test
public void getGetMirrorPoint()
{
@@ -61,4 +116,51 @@ public class ClueScrollPluginTest
converted = ClueScrollPlugin.getMirrorPoint(point, false);
assertEquals(point, converted);
}
}
@Test
public void testLocationHintArrowCleared()
{
final Widget clueWidget = mock(Widget.class);
when(clueWidget.getText()).thenReturn("Buried beneath the ground, who knows where it's found. Lucky for you, A man called Reldo may have a clue.");
final ChatMessage hotColdMessage = new ChatMessage();
hotColdMessage.setType(ChatMessageType.GAMEMESSAGE);
final Player localPlayer = mock(Player.class);
when(client.getWidget(WidgetInfo.CLUE_SCROLL_TEXT)).thenReturn(clueWidget);
when(client.getLocalPlayer()).thenReturn(localPlayer);
when(client.getPlane()).thenReturn(0);
when(client.getCachedNPCs()).thenReturn(new NPC[] {});
when(config.displayHintArrows()).thenReturn(true);
// The hint arrow should be reset each game tick from when the clue is read onward
// This is to verify the arrow is cleared the correct number of times during the clue updating process.
int clueSetupHintArrowClears = 0;
// Initialize a beginner hot-cold clue (which will have an end point of LUMBRIDGE_COW_FIELD)
plugin.onGameTick(new GameTick());
verify(client, times(++clueSetupHintArrowClears)).clearHintArrow();
// Perform the first hot-cold check in Lumbridge near sheep pen (get 2 possible points: LUMBRIDGE_COW_FIELD and DRAYNOR_WHEAT_FIELD)
when(localPlayer.getWorldLocation()).thenReturn(new WorldPoint(3208, 3254, 0));
hotColdMessage.setMessage("The device is hot.");
plugin.onChatMessage(hotColdMessage);
// Move to SW of DRAYNOR_WHEAT_FIELD (hint arrow should be visible here)
when(localPlayer.getWorldLocation()).thenReturn(new WorldPoint(3105, 3265, 0));
when(client.getBaseX()).thenReturn(3056);
when(client.getBaseY()).thenReturn(3216);
plugin.onGameTick(new GameTick());
verify(client, times(++clueSetupHintArrowClears)).clearHintArrow();
verify(client).setHintArrow(HotColdLocation.DRAYNOR_WHEAT_FIELD.getWorldPoint());
// Test in that location (get 1 possible location: LUMBRIDGE_COW_FIELD)
hotColdMessage.setMessage("The device is hot, and warmer than last time.");
plugin.onChatMessage(hotColdMessage);
plugin.onGameTick(new GameTick());
// Hint arrow should be cleared and not re-set now as the only remaining location is outside of the current
// scene
verify(client, times(++clueSetupHintArrowClears)).clearHintArrow();
verify(client, times(1)).setHintArrow(any(WorldPoint.class));
}
}