fishing plugin: add minnows overlay

This shows a progress pie on how much time is left before the minnow
moves

Co-authored-by: Jacky <liangj97@gmail.com>
This commit is contained in:
Adam
2018-07-27 22:57:27 -04:00
parent 5fe8033dc1
commit d9ca9f5060
4 changed files with 139 additions and 5 deletions

View File

@@ -200,4 +200,14 @@ public interface FishingConfig extends Config
{
return true;
}
@ConfigItem(
keyName = "showMinnowOverlay",
name = "Show Minnow Movement overlay",
description = "Configures whether to display the minnow progress pie overlay"
)
default boolean showMinnowOverlay()
{
return true;
}
}

View File

@@ -28,14 +28,18 @@ package net.runelite.client.plugins.fishing;
import com.google.common.eventbus.Subscribe;
import com.google.common.primitives.Ints;
import com.google.inject.Provides;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Singleton;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.ChatMessageType;
import net.runelite.api.Client;
import net.runelite.api.NPC;
@@ -43,6 +47,7 @@ import net.runelite.api.coords.LocalPoint;
import net.runelite.api.events.ChatMessage;
import net.runelite.api.events.ConfigChanged;
import net.runelite.api.events.GameTick;
import net.runelite.api.events.NpcDespawned;
import net.runelite.api.queries.NPCQuery;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.plugins.Plugin;
@@ -59,10 +64,14 @@ import net.runelite.client.util.QueryRunner;
)
@PluginDependency(XpTrackerPlugin.class)
@Singleton
@Slf4j
public class FishingPlugin extends Plugin
{
private final List<Integer> spotIds = new ArrayList<>();
@Getter(AccessLevel.PACKAGE)
private Map<Integer, MinnowSpot> minnowSpots = new HashMap<>();
@Getter(AccessLevel.PACKAGE)
private NPC[] fishingSpots;
@@ -110,6 +119,7 @@ public class FishingPlugin extends Plugin
overlayManager.remove(overlay);
overlayManager.remove(spotOverlay);
overlayManager.remove(fishingSpotMinimapOverlay);
minnowSpots.clear();
}
public FishingSession getSession()
@@ -199,7 +209,7 @@ public class FishingPlugin extends Plugin
}
@Subscribe
public void checkSpots(GameTick event)
public void onGameTick(GameTick event)
{
final LocalPoint cameraPoint = new LocalPoint(client.getCameraX(), client.getCameraY());
@@ -209,5 +219,43 @@ public class FishingPlugin extends Plugin
// -1 to make closer things draw last (on top of farther things)
Arrays.sort(spots, Comparator.comparing(npc -> -1 * npc.getLocalLocation().distanceTo(cameraPoint)));
fishingSpots = spots;
// process minnows
for (NPC npc : spots)
{
FishingSpot spot = FishingSpot.getSpot(npc.getId());
if (spot == null)
{
continue;
}
if (spot == FishingSpot.MINNOW && config.showMinnowOverlay())
{
int id = npc.getIndex();
MinnowSpot minnowSpot = minnowSpots.get(id);
// create the minnow spot if it doesn't already exist
if (minnowSpot == null)
{
minnowSpots.put(id, new MinnowSpot(npc.getWorldLocation(), Instant.now()));
}
// if moved, reset
else if (!minnowSpot.getLoc().equals(npc.getWorldLocation()))
{
minnowSpots.put(id, new MinnowSpot(npc.getWorldLocation(), Instant.now()));
}
}
}
}
@Subscribe
public void onNpcDespawned(NpcDespawned npcDespawned)
{
NPC npc = npcDespawned.getNpc();
MinnowSpot minnowSpot = minnowSpots.remove(npc.getIndex());
if (minnowSpot != null)
{
log.debug("Minnow spot {} despawned", npc);
}
}
}

View File

@@ -28,30 +28,41 @@ import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.time.Duration;
import java.time.Instant;
import javax.inject.Inject;
import net.runelite.api.Client;
import net.runelite.api.GraphicID;
import net.runelite.api.NPC;
import net.runelite.api.Perspective;
import net.runelite.api.Point;
import net.runelite.api.coords.LocalPoint;
import net.runelite.client.game.ItemManager;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayLayer;
import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.OverlayUtil;
import net.runelite.client.ui.overlay.components.ProgressPieComponent;
class FishingSpotOverlay extends Overlay
{
private static final Duration MINNOW_MOVE = Duration.ofSeconds(15);
private static final Duration MINNOW_WARN = Duration.ofSeconds(3);
private final FishingPlugin plugin;
private final FishingConfig config;
private final Client client;
private final ItemManager itemManager;
@Inject
ItemManager itemManager;
@Inject
public FishingSpotOverlay(FishingPlugin plugin, FishingConfig config)
private FishingSpotOverlay(FishingPlugin plugin, FishingConfig config, Client client, ItemManager itemManager)
{
setPosition(OverlayPosition.DYNAMIC);
setLayer(OverlayLayer.ABOVE_SCENE);
this.plugin = plugin;
this.config = config;
this.client = client;
this.itemManager = itemManager;
}
@Override
@@ -73,6 +84,33 @@ class FishingSpotOverlay extends Overlay
}
Color color = npc.getGraphic() == GraphicID.FLYING_FISH ? Color.RED : Color.CYAN;
if (spot == FishingSpot.MINNOW && config.showMinnowOverlay())
{
MinnowSpot minnowSpot = plugin.getMinnowSpots().get(npc.getIndex());
if (minnowSpot != null)
{
long millisLeft = MINNOW_MOVE.toMillis() - Duration.between(minnowSpot.getTime(), Instant.now()).toMillis();
if (millisLeft < MINNOW_WARN.toMillis())
{
color = Color.ORANGE;
}
LocalPoint localPoint = npc.getLocalLocation();
Point location = Perspective.worldToCanvas(client, localPoint.getX(), localPoint.getY(), client.getPlane());
if (location != null)
{
ProgressPieComponent pie = new ProgressPieComponent();
pie.setFill(color);
pie.setBorderColor(color);
pie.setPosition(location);
pie.setProgress((float) millisLeft / MINNOW_MOVE.toMillis());
pie.render(graphics);
}
}
}
if (config.showIcons())
{
BufferedImage fishImage = getFishImage(spot);

View File

@@ -0,0 +1,38 @@
/*
* Copyright (c) 2018, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.client.plugins.fishing;
import java.time.Instant;
import lombok.AllArgsConstructor;
import lombok.Value;
import net.runelite.api.coords.WorldPoint;
@AllArgsConstructor
@Value
class MinnowSpot
{
private final WorldPoint loc;
private final Instant time;
}