From 71e4b5d9ad43ccf968380f5cf6845a0d20849865 Mon Sep 17 00:00:00 2001 From: dekvall Date: Thu, 26 Dec 2019 05:34:04 +0100 Subject: [PATCH] herbiboar: use guaranteed tracks when highlighting path There's a set of guaranteed tracks that can be used when calculating the path when tracking herbiboars. The tracks are listed on the osrs wiki. Co-authored-by: Jordan Atwood --- .../main/java/net/runelite/api/Varbits.java | 9 +- .../herbiboars/HerbiboarMinimapOverlay.java | 43 +-- .../plugins/herbiboars/HerbiboarOverlay.java | 99 +++---- .../plugins/herbiboars/HerbiboarPlugin.java | 271 +++++++++++------- .../plugins/herbiboars/HerbiboarRule.java | 110 +++++++ .../herbiboars/HerbiboarSearchSpot.java | 180 ++++++++++++ .../plugins/herbiboars/HerbiboarStart.java | 55 ++++ .../plugins/herbiboars/HerbiboarTrail.java | 109 ------- .../plugins/herbiboars/TrailToSpot.java | 60 ++++ 9 files changed, 641 insertions(+), 295 deletions(-) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/herbiboars/HerbiboarRule.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/herbiboars/HerbiboarSearchSpot.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/herbiboars/HerbiboarStart.java delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/herbiboars/HerbiboarTrail.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/herbiboars/TrailToSpot.java diff --git a/runelite-api/src/main/java/net/runelite/api/Varbits.java b/runelite-api/src/main/java/net/runelite/api/Varbits.java index bea1e9b830..b9b8a7a4ed 100644 --- a/runelite-api/src/main/java/net/runelite/api/Varbits.java +++ b/runelite-api/src/main/java/net/runelite/api/Varbits.java @@ -219,7 +219,14 @@ public enum Varbits HB_TRAIL_31372(5750), HB_FINISH(5766), - HB_STARTED(5767), //not working + + /** + * Started hunting Herbiboar. + *
+ * NOTE: This value remains at 0 even after starting a Herbiboar trail up until searching the first object along the + * hunting path. + */ + HB_STARTED(5767), /** * Barbarian Assault diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/herbiboars/HerbiboarMinimapOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/herbiboars/HerbiboarMinimapOverlay.java index fff22cbc39..acbdbdfb89 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/herbiboars/HerbiboarMinimapOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/herbiboars/HerbiboarMinimapOverlay.java @@ -35,7 +35,7 @@ import net.runelite.client.ui.overlay.OverlayLayer; import net.runelite.client.ui.overlay.OverlayPosition; import net.runelite.client.ui.overlay.OverlayUtil; -public class HerbiboarMinimapOverlay extends Overlay +class HerbiboarMinimapOverlay extends Overlay { private final HerbiboarPlugin plugin; private final HerbiboarConfig config; @@ -52,29 +52,30 @@ public class HerbiboarMinimapOverlay extends Overlay @Override public Dimension render(Graphics2D graphics) { - if (config.isTrailShown() && plugin.isInHerbiboarArea()) + if (!config.isTrailShown() || !plugin.isInHerbiboarArea()) { - HerbiboarTrail currentTrail = plugin.getCurrentTrail(); - int finishId = plugin.getFinishId(); - Set shownTrailIds = plugin.getShownTrails(); - - for (TileObject tileObject : plugin.getTrails().values()) - { - int id = tileObject.getId(); - Point minimapLocation = tileObject.getMinimapLocation(); - - if (minimapLocation == null) - { - continue; - } - - if (shownTrailIds.contains(id) && (finishId > 0 || (currentTrail != null && currentTrail.getTrailId() != id && currentTrail.getTrailId() + 1 != id))) - { - OverlayUtil.renderMinimapLocation(graphics, minimapLocation, config.getTrailColor()); - } - } + return null; } + TrailToSpot nextTrail = plugin.getNextTrail(); + int finishId = plugin.getFinishId(); + Set shownTrailIds = plugin.getShownTrails(); + + for (TileObject tileObject : plugin.getTrails().values()) + { + int id = tileObject.getId(); + Point minimapLocation = tileObject.getMinimapLocation(); + + if (minimapLocation == null) + { + continue; + } + + if (shownTrailIds.contains(id) && (finishId > 0 || nextTrail != null && !nextTrail.getFootprintIds().contains(id))) + { + OverlayUtil.renderMinimapLocation(graphics, minimapLocation, config.getTrailColor()); + } + } return null; } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/herbiboars/HerbiboarOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/herbiboars/HerbiboarOverlay.java index a97f5d9d49..5389cd6fd0 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/herbiboars/HerbiboarOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/herbiboars/HerbiboarOverlay.java @@ -24,6 +24,7 @@ */ package net.runelite.client.plugins.herbiboars; +import com.google.common.collect.Iterables; import com.google.inject.Inject; import java.awt.Color; import java.awt.Dimension; @@ -59,17 +60,14 @@ class HerbiboarOverlay extends Overlay return null; } - HerbiboarTrail currentTrail = plugin.getCurrentTrail(); - + HerbiboarSearchSpot.Group currentGroup = plugin.getCurrentGroup(); + TrailToSpot nextTrail = plugin.getNextTrail(); int finishId = plugin.getFinishId(); // Draw start objects - if (config.isStartShown() && (currentTrail == null && finishId == 0)) + if (config.isStartShown() && (currentGroup == null && finishId == 0)) { - plugin.getStarts().values().forEach((obj) -> - { - OverlayUtil.renderTileOverlay(graphics, obj, "", config.getStartColor()); - }); + plugin.getStarts().values().forEach((obj) -> OverlayUtil.renderTileOverlay(graphics, obj, "", config.getStartColor())); } // Draw trails @@ -79,7 +77,7 @@ class HerbiboarOverlay extends Overlay plugin.getTrails().values().forEach((x) -> { int id = x.getId(); - if (shownTrailIds.contains(id) && (finishId > 0 || (currentTrail != null && currentTrail.getTrailId() != id && currentTrail.getTrailId() + 1 != id))) + if (shownTrailIds.contains(id) && (finishId > 0 || nextTrail != null && !nextTrail.getFootprintIds().contains(id))) { OverlayUtil.renderTileOverlay(graphics, x, "", config.getTrailColor()); } @@ -87,35 +85,20 @@ class HerbiboarOverlay extends Overlay } // Draw trail objects (mushrooms, mud, etc) - if (config.isObjectShown() && currentTrail != null) + if (config.isObjectShown() && !(finishId > 0 || currentGroup == null)) { - int currentPath = plugin.getCurrentPath(); - WorldPoint[] trailLocs = currentTrail.getObjectLocs(currentPath); - for (WorldPoint trailLoc : trailLocs) + if (plugin.isRuleApplicable()) { - if (trailLoc == null) + WorldPoint correct = Iterables.getLast(plugin.getCurrentPath()).getLocation(); + TileObject object = plugin.getTrailObjects().get(correct); + drawObjectLocation(graphics, object, config.getObjectColor()); + } + else + { + for (WorldPoint trailLoc : HerbiboarSearchSpot.getGroupLocations(plugin.getCurrentGroup())) { - continue; - } - - TileObject object = plugin.getTrailObjects().get(trailLoc); - if (object != null) - { - if (config.showClickBoxes()) - { - Shape clickbox = object.getClickbox(); - if (clickbox != null) - { - graphics.setColor(config.getObjectColor()); - graphics.draw(clickbox); - graphics.setColor(new Color(255, 0, 255, 20)); - graphics.fill(clickbox); - } - } - else - { - OverlayUtil.renderTileOverlay(graphics, object, "", config.getObjectColor()); - } + TileObject object = plugin.getTrailObjects().get(trailLoc); + drawObjectLocation(graphics, object, config.getObjectColor()); } } } @@ -125,27 +108,35 @@ class HerbiboarOverlay extends Overlay { WorldPoint finishLoc = plugin.getEndLocations().get(finishId - 1); TileObject object = plugin.getTunnels().get(finishLoc); - if (object != null) - { - if (config.showClickBoxes()) - { - Shape clickbox = object.getClickbox(); - if (clickbox != null) - { - Color col = config.getObjectColor(); - graphics.setColor(col); - graphics.draw(clickbox); - graphics.setColor(new Color(col.getRed(), col.getGreen(), col.getBlue(), 20)); - graphics.fill(clickbox); - } - } - else - { - OverlayUtil.renderTileOverlay(graphics, object, "", config.getTunnelColor()); - } - } + drawObjectLocation(graphics, object, config.getTunnelColor()); } return null; } -} \ No newline at end of file + + private void drawObjectLocation(Graphics2D graphics, TileObject object, Color color) + { + if (object == null) + { + return; + } + + if (config.showClickBoxes()) + { + Shape clickbox = object.getClickbox(); + if (clickbox != null) + { + Color clickBoxColor = new Color(color.getRed(), color.getGreen(), color.getBlue(), 20); + + graphics.setColor(color); + graphics.draw(clickbox); + graphics.setColor(clickBoxColor); + graphics.fill(clickbox); + } + } + else + { + OverlayUtil.renderTileOverlay(graphics, object, "", color); + } + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/herbiboars/HerbiboarPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/herbiboars/HerbiboarPlugin.java index 83e59c19a4..02288075c5 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/herbiboars/HerbiboarPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/herbiboars/HerbiboarPlugin.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2017, Tyler + * Copyright (c) 2020, dekvall * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,8 +25,10 @@ */ package net.runelite.client.plugins.herbiboars; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Lists; import com.google.inject.Provides; -import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -33,14 +36,15 @@ import java.util.Map; import java.util.Set; import javax.inject.Inject; import lombok.Getter; -import lombok.Setter; +import lombok.extern.slf4j.Slf4j; import net.runelite.api.Client; +import net.runelite.api.GameState; +import net.runelite.api.MenuAction; import static net.runelite.api.ObjectID.DRIFTWOOD_30523; import static net.runelite.api.ObjectID.MUSHROOM_30520; import static net.runelite.api.ObjectID.ROCK_30519; import static net.runelite.api.ObjectID.ROCK_30521; import static net.runelite.api.ObjectID.ROCK_30522; -import net.runelite.api.Tile; import net.runelite.api.TileObject; import net.runelite.api.Varbits; import net.runelite.api.coords.WorldPoint; @@ -51,21 +55,27 @@ import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.GroundObjectChanged; import net.runelite.api.events.GroundObjectDespawned; import net.runelite.api.events.GroundObjectSpawned; +import net.runelite.api.events.MenuOptionClicked; import net.runelite.api.events.VarbitChanged; +import net.runelite.client.callback.ClientThread; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.ui.overlay.OverlayManager; +import net.runelite.client.util.Text; +import org.apache.commons.lang3.ArrayUtils; @PluginDescriptor( name = "Herbiboar", description = "Highlight starting rocks, trails, and the objects to search at the end of each trail", tags = {"herblore", "hunter", "skilling", "overlay"} ) +@Slf4j +@Getter public class HerbiboarPlugin extends Plugin { - private static final List END_LOCATIONS = Arrays.asList( + private static final List END_LOCATIONS = ImmutableList.of( new WorldPoint(3693, 3798, 0), new WorldPoint(3702, 3808, 0), new WorldPoint(3703, 3826, 0), @@ -77,7 +87,7 @@ public class HerbiboarPlugin extends Plugin new WorldPoint(3681, 3863, 0) ); - private static final List START_OBJECT_IDS = Arrays.asList( + private static final Set START_OBJECT_IDS = ImmutableSet.of( ROCK_30519, MUSHROOM_30520, ROCK_30521, @@ -85,16 +95,19 @@ public class HerbiboarPlugin extends Plugin DRIFTWOOD_30523 ); - private static final int[] HERBIBOAR_REGIONS = { + private static final List HERBIBOAR_REGIONS = ImmutableList.of( 14652, 14651, 14908, 14907 - }; + ); @Inject private Client client; + @Inject + private ClientThread clientThread; + @Inject private OverlayManager overlayManager; @@ -104,39 +117,43 @@ public class HerbiboarPlugin extends Plugin @Inject private HerbiboarMinimapOverlay minimapOverlay; - @Getter + /** + * Objects which appear at the beginning of Herbiboar hunting trails + */ + private final Map starts = new HashMap<>(); + /** + * Herbiboar hunting "footstep" trail objects + */ + private final Map trails = new HashMap<>(); + /** + * Objects which trigger next trail (mushrooms, mud, seaweed, etc) + */ + private final Map trailObjects = new HashMap<>(); + /** + * Tunnel where the Herbiboar is hiding at the end of a trail + */ + private final Map tunnels = new HashMap<>(); + /** + * Trail object IDs which should be highlighted + */ + private final Set shownTrails = new HashSet<>(); + /** + * Sequence of herbiboar spots searched along the current trail + */ + private final List currentPath = Lists.newArrayList(); + private boolean inHerbiboarArea; - - @Getter - private Map trails = new HashMap<>(); - - @Getter - private Map tunnels = new HashMap<>(); - - @Getter - private Map starts = new HashMap<>(); - - @Getter - private Map trailObjects = new HashMap<>(); - - @Getter - @Setter - private Set shownTrails = new HashSet<>(); - - @Getter - @Setter - private HerbiboarTrail currentTrail; - - @Getter - @Setter - private int currentPath; - - @Getter - @Setter + private TrailToSpot nextTrail; + private HerbiboarSearchSpot.Group currentGroup; private int finishId; + private boolean started; + private WorldPoint startPoint; + private HerbiboarStart startSpot; + private boolean ruleApplicable; + @Provides - HerbiboarConfig getConfig(ConfigManager configManager) + HerbiboarConfig provideConfig(ConfigManager configManager) { return configManager.getConfig(HerbiboarConfig.class); } @@ -146,7 +163,15 @@ public class HerbiboarPlugin extends Plugin { overlayManager.add(overlay); overlayManager.add(minimapOverlay); - inHerbiboarArea = checkArea(); + + if (client.getGameState() == GameState.LOGGED_IN) + { + clientThread.invokeLater(() -> + { + inHerbiboarArea = checkArea(); + updateTrailData(); + }); + } } @Override @@ -154,61 +179,105 @@ public class HerbiboarPlugin extends Plugin { overlayManager.remove(overlay); overlayManager.remove(minimapOverlay); + resetTrailData(); + clearCache(); + inHerbiboarArea = false; } private void updateTrailData() { - currentTrail = null; - currentPath = -1; + if (!isInHerbiboarArea()) + { + return; + } + + boolean pathActive = false; + boolean wasStarted = started; // Get trail data - for (HerbiboarTrail trail : HerbiboarTrail.values()) + for (HerbiboarSearchSpot spot : HerbiboarSearchSpot.values()) { - int trailId = trail.getTrailId(); - int value = client.getVar(trail.getVarbit()); + for (TrailToSpot trail : spot.getTrails()) + { + int value = client.getVar(trail.getVarbit()); - if (value > 0) - { - shownTrails.add(trailId); - shownTrails.add(trailId + 1); - } - if (value == 1 || value == 2) - { - currentTrail = trail; - currentPath = value; + if (value == trail.getValue()) + { + // The trail after you have searched the spot + currentGroup = spot.getGroup(); + nextTrail = trail; + + // You never visit the same spot twice + if (!currentPath.contains(spot)) + { + currentPath.add(spot); + } + } + else if (value > 0) + { + // The current trail + shownTrails.addAll(trail.getFootprintIds()); + pathActive = true; + } } } - // Get finish data finishId = client.getVar(Varbits.HB_FINISH); - if (finishId > 0 && currentTrail != null) + + // The started varbit doesn't get set until the first spot of the rotation has been searched + // so we need to use the current group as an indicator of the rotation being started + started = client.getVar(Varbits.HB_STARTED) > 0 || currentGroup != null; + boolean finished = !pathActive && started; + + if (!wasStarted && started) { - shownTrails.add(currentTrail.getTrailId()); - shownTrails.add(currentTrail.getTrailId() + 1); - currentTrail = null; - currentPath = -1; + startSpot = HerbiboarStart.from(startPoint); } - int started = client.getVar(Varbits.HB_STARTED); - if (currentPath == -1 && finishId == 0 && started == 0) + ruleApplicable = HerbiboarRule.canApplyRule(startSpot, currentPath); + + if (finished) { resetTrailData(); } } + @Subscribe + public void onMenuOptionClicked(MenuOptionClicked menuOpt) + { + if (!inHerbiboarArea || started || MenuAction.GAME_OBJECT_FIRST_OPTION != menuOpt.getMenuAction()) + { + return; + } + + switch (Text.removeTags(menuOpt.getMenuTarget())) + { + case "Rock": + case "Mushroom": + case "Driftwood": + startPoint = WorldPoint.fromScene(client, menuOpt.getActionParam(), menuOpt.getWidgetId(), client.getPlane()); + } + } + private void resetTrailData() { - currentPath = 0; - currentTrail = null; - finishId = 0; + log.debug("Reset trail data"); shownTrails.clear(); + currentPath.clear(); + nextTrail = null; + currentGroup = null; + finishId = 0; + started = false; + startPoint = null; + startSpot = null; + ruleApplicable = false; } private void clearCache() { starts.clear(); - trailObjects.clear(); trails.clear(); + trailObjects.clear(); tunnels.clear(); } @@ -233,57 +302,55 @@ public class HerbiboarPlugin extends Plugin @Subscribe public void onVarbitChanged(VarbitChanged event) { - if (isInHerbiboarArea()) - { - updateTrailData(); - } + updateTrailData(); } @Subscribe public void onGameObjectSpawned(GameObjectSpawned event) { - onGameObject(event.getTile(), null, event.getGameObject()); + onTileObject(null, event.getGameObject()); } @Subscribe public void onGameObjectChanged(GameObjectChanged event) { - onGameObject(event.getTile(), event.getPrevious(), event.getGameObject()); + onTileObject(event.getPrevious(), event.getGameObject()); } @Subscribe public void onGameObjectDespawned(GameObjectDespawned event) { - onGameObject(event.getTile(), event.getGameObject(), null); + onTileObject(event.getGameObject(), null); } @Subscribe public void onGroundObjectSpawned(GroundObjectSpawned event) { - onGroundObject(event.getTile(), null, event.getGroundObject()); + onTileObject(null, event.getGroundObject()); } @Subscribe public void onGroundObjectChanged(GroundObjectChanged event) { - onGroundObject(event.getTile(), event.getPrevious(), event.getGroundObject()); + onTileObject(event.getPrevious(), event.getGroundObject()); } @Subscribe public void onGroundObjectDespawned(GroundObjectDespawned event) { - onGroundObject(event.getTile(), event.getGroundObject(), null); + onTileObject(event.getGroundObject(), null); } - // Store relevant GameObjects (starts, objects used to trigger next trails, and some tunnels) - private void onGameObject(Tile tile, TileObject oldObject, TileObject newObject) + // Store relevant GameObjects (starts, tracks on trails, objects used to trigger next trails, and tunnels) + private void onTileObject(TileObject oldObject, TileObject newObject) { if (oldObject != null) { WorldPoint oldLocation = oldObject.getWorldLocation(); + starts.remove(oldLocation); + trails.remove(oldLocation); trailObjects.remove(oldLocation); tunnels.remove(oldLocation); - starts.remove(oldLocation); } if (newObject == null) @@ -298,8 +365,15 @@ public class HerbiboarPlugin extends Plugin return; } + // Trails + if (HerbiboarSearchSpot.isTrail(newObject.getId())) + { + trails.put(newObject.getWorldLocation(), newObject); + return; + } + // GameObject to trigger next trail (mushrooms, mud, seaweed, etc) - if (HerbiboarTrail.getAllObjectLocs().contains(newObject.getWorldLocation())) + if (HerbiboarSearchSpot.isSearchSpot(newObject.getWorldLocation())) { trailObjects.put(newObject.getWorldLocation(), newObject); return; @@ -312,43 +386,20 @@ public class HerbiboarPlugin extends Plugin } } - // Store relevant GroundObjects (tracks on trails, and some tunnels) - private void onGroundObject(Tile tile, TileObject oldObject, TileObject newObject) - { - if (oldObject != null) - { - WorldPoint oldLocation = oldObject.getWorldLocation(); - trails.remove(oldLocation); - tunnels.remove(oldLocation); - } - - if (newObject == null) - { - return; - } - - //Trails - if (HerbiboarTrail.getTrailIds().contains(newObject.getId())) - { - trails.put(newObject.getWorldLocation(), newObject); - return; - } - - //Herbiboar tunnel - if (END_LOCATIONS.contains(newObject.getWorldLocation())) - { - tunnels.put(newObject.getWorldLocation(), newObject); - } - } - private boolean checkArea() { - return client.getMapRegions() != null && Arrays.stream(client.getMapRegions()) - .filter(x -> Arrays.stream(HERBIBOAR_REGIONS).anyMatch(y -> y == x)) - .toArray().length > 0; + final int[] mapRegions = client.getMapRegions(); + for (int region : HERBIBOAR_REGIONS) + { + if (ArrayUtils.contains(mapRegions, region)) + { + return true; + } + } + return false; } - public List getEndLocations() + List getEndLocations() { return END_LOCATIONS; } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/herbiboars/HerbiboarRule.java b/runelite-client/src/main/java/net/runelite/client/plugins/herbiboars/HerbiboarRule.java new file mode 100644 index 0000000000..b904e05d3a --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/herbiboars/HerbiboarRule.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2020, dekvall + * Copyright (c) 2020, Jordan + * 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.herbiboars; + +import java.util.List; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +enum HerbiboarRule +{ + A_SOUTH(HerbiboarSearchSpot.Group.A, HerbiboarStart.MIDDLE), + C_WEST(HerbiboarSearchSpot.Group.C, HerbiboarStart.MIDDLE), + D_WEST_1(HerbiboarSearchSpot.Group.D, HerbiboarStart.MIDDLE), + D_WEST_2(HerbiboarSearchSpot.Group.D, HerbiboarSearchSpot.Group.C), + E_NORTH(HerbiboarSearchSpot.Group.E, HerbiboarSearchSpot.Group.A), + F_EAST(HerbiboarSearchSpot.Group.F, HerbiboarSearchSpot.Group.G), + G_NORTH(HerbiboarSearchSpot.Group.G, HerbiboarSearchSpot.Group.F), + H_NORTH(HerbiboarSearchSpot.Group.H, HerbiboarSearchSpot.Group.D), + H_EAST(HerbiboarSearchSpot.Group.H, HerbiboarStart.DRIFTWOOD), + I_EAST(HerbiboarSearchSpot.Group.I, HerbiboarStart.LEPRECHAUN), + I_SOUTH_1(HerbiboarSearchSpot.Group.I, HerbiboarStart.GHOST_MUSHROOM), + I_SOUTH_2(HerbiboarSearchSpot.Group.I, HerbiboarStart.CAMP_ENTRANCE), + I_WEST(HerbiboarSearchSpot.Group.I, HerbiboarSearchSpot.Group.E), + ; + + private final HerbiboarSearchSpot.Group to; + private final HerbiboarStart fromStart; + private final HerbiboarSearchSpot.Group fromGroup; + + HerbiboarRule(HerbiboarSearchSpot.Group to, HerbiboarSearchSpot.Group from) + { + this(to, null, from); + } + + HerbiboarRule(HerbiboarSearchSpot.Group to, HerbiboarStart fromStart) + { + this(to, fromStart, null); + } + + /** + * Returns whether the next {@link HerbiboarSearchSpot} can be deterministically selected based on the starting + * location and the path taken so far, based on the rules defined on the OSRS wiki. + * + * {@see https://oldschool.runescape.wiki/w/Herbiboar#Guaranteed_tracks} + * + * @param start Herbiboar's starting spot where the tracking path begins + * @param currentPath A list of {@link HerbiboarSearchSpot}s which have been searched thus far, and the next one to search + * @return {@code true} if a rule can be applied, {@code false} otherwise + */ + static boolean canApplyRule(HerbiboarStart start, List currentPath) + { + if (start == null || currentPath.isEmpty()) + { + return false; + } + + int lastIndex = currentPath.size() - 1; + HerbiboarSearchSpot.Group goingTo = currentPath.get(lastIndex).getGroup(); + + for (HerbiboarRule rule : values()) + { + if (lastIndex > 0 && rule.matches(currentPath.get(lastIndex - 1).getGroup(), goingTo) + || lastIndex == 0 && rule.matches(start, goingTo)) + { + return true; + } + } + + return false; + } + + boolean matches(HerbiboarStart from, HerbiboarSearchSpot.Group to) + { + return this.matches(from, null, to); + } + + boolean matches(HerbiboarSearchSpot.Group from, HerbiboarSearchSpot.Group to) + { + return this.matches(null, from, to); + } + + boolean matches(HerbiboarStart fromStart, HerbiboarSearchSpot.Group fromGroup, HerbiboarSearchSpot.Group to) + { + return this.to == to + && (fromStart != null && this.fromStart == fromStart || fromGroup != null && this.fromGroup == fromGroup); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/herbiboars/HerbiboarSearchSpot.java b/runelite-client/src/main/java/net/runelite/client/plugins/herbiboars/HerbiboarSearchSpot.java new file mode 100644 index 0000000000..9e324f5a2b --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/herbiboars/HerbiboarSearchSpot.java @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2020, dekvall + * Copyright (c) 2020, Jordan + * 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.herbiboars; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.ImmutableSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; +import lombok.Getter; +import static net.runelite.api.NullObjectID.*; +import net.runelite.api.Varbits; +import net.runelite.api.coords.WorldPoint; + +@Getter +enum HerbiboarSearchSpot +{ + // Wiki A location + A_MUSHROOM(Group.A, new WorldPoint(3670, 3889, 0), + new TrailToSpot(Varbits.HB_TRAIL_31318, 1, NULL_31318), + new TrailToSpot(Varbits.HB_TRAIL_31321, 1, NULL_31321)), + A_PATCH(Group.A, new WorldPoint(3672, 3890, 0), + new TrailToSpot(Varbits.HB_TRAIL_31306, 2, NULL_31306)), + + // Wiki B location + B_SEAWEED(Group.B, new WorldPoint(3728, 3893, 0), + new TrailToSpot(Varbits.HB_TRAIL_31315, 2, NULL_31315), + new TrailToSpot(Varbits.HB_TRAIL_31318, 2, NULL_31318), + new TrailToSpot(Varbits.HB_TRAIL_31336, 1, NULL_31336), + new TrailToSpot(Varbits.HB_TRAIL_31339, 1, NULL_31339)), + + // Wiki C location + C_MUSHROOM(Group.C, new WorldPoint(3697, 3875, 0), + new TrailToSpot(Varbits.HB_TRAIL_31303, 2, NULL_31303)), + C_PATCH(Group.C, new WorldPoint(3699, 3875, 0), + new TrailToSpot(Varbits.HB_TRAIL_31312, 1, NULL_31312), + new TrailToSpot(Varbits.HB_TRAIL_31315, 1, NULL_31315)), + + // Wiki D location + D_PATCH(Group.D, new WorldPoint(3708, 3876, 0), + new TrailToSpot(Varbits.HB_TRAIL_31330, 1, NULL_31330), + new TrailToSpot(Varbits.HB_TRAIL_31333, 1, NULL_31333)), + D_SEAWEED(Group.D, new WorldPoint(3710, 3877, 0), + new TrailToSpot(Varbits.HB_TRAIL_31312, 2, NULL_31312), + new TrailToSpot(Varbits.HB_TRAIL_31339, 2, NULL_31339)), + + // Wiki E location + E_MUSHROOM(Group.E, new WorldPoint(3668, 3865, 0), + new TrailToSpot(Varbits.HB_TRAIL_31342, 1, NULL_31342), + new TrailToSpot(Varbits.HB_TRAIL_31345, 1, NULL_31345)), + E_PATCH(Group.E, new WorldPoint(3667, 3862, 0), + new TrailToSpot(Varbits.HB_TRAIL_31321, 2, NULL_31321)), + + // Wiki F location + F_MUSHROOM(Group.F, new WorldPoint(3681, 3860, 0), + new TrailToSpot(Varbits.HB_TRAIL_31324, 1, NULL_31324), + new TrailToSpot(Varbits.HB_TRAIL_31327, 1, NULL_31327), + new TrailToSpot(Varbits.HB_TRAIL_31342, 2, NULL_31342)), + F_PATCH(Group.F, new WorldPoint(3681, 3859, 0), + new TrailToSpot(Varbits.HB_TRAIL_31309, 2, NULL_31309)), + + // Wiki G location + G_MUSHROOM(Group.G, new WorldPoint(3694, 3847, 0), + new TrailToSpot(Varbits.HB_TRAIL_31333, 2, NULL_31333), + new TrailToSpot(Varbits.HB_TRAIL_31354, 1, NULL_31354)), + G_PATCH(Group.G, new WorldPoint(3698, 3847, 0), + new TrailToSpot(Varbits.HB_TRAIL_31327, 2, NULL_31327)), + + // Wiki H location + H_SEAWEED_EAST(Group.H, new WorldPoint(3715, 3851, 0), + new TrailToSpot(Varbits.HB_TRAIL_31357, 1, NULL_31357), + new TrailToSpot(Varbits.HB_TRAIL_31360, 1, NULL_31360)), + H_SEAWEED_WEST(Group.H, new WorldPoint(3713, 3850, 0), + new TrailToSpot(Varbits.HB_TRAIL_31330, 2, NULL_31330), + new TrailToSpot(Varbits.HB_TRAIL_31363, 1, NULL_31363)), + + // Wiki I location + I_MUSHROOM(Group.I, new WorldPoint(3680, 3838, 0), + new TrailToSpot(Varbits.HB_TRAIL_31348, 1, NULL_31348), + new TrailToSpot(Varbits.HB_TRAIL_31351, 1, NULL_31351)), + I_PATCH(Group.I, new WorldPoint(3680, 3836, 0), + new TrailToSpot(Varbits.HB_TRAIL_31324, 2, NULL_31324), + new TrailToSpot(Varbits.HB_TRAIL_31345, 2, NULL_31345)), + + // Wiki J location + J_PATCH(Group.J, new WorldPoint(3713, 3840, 0), + new TrailToSpot(Varbits.HB_TRAIL_31357, 2, NULL_31357), + new TrailToSpot(Varbits.HB_TRAIL_31372, 1, NULL_31372)), + + // Wiki K location + K_PATCH(Group.K, new WorldPoint(3706, 3811, 0), + new TrailToSpot(Varbits.HB_TRAIL_31348, 2, NULL_31348), + new TrailToSpot(Varbits.HB_TRAIL_31366, 1, NULL_31366), + new TrailToSpot(Varbits.HB_TRAIL_31369, 1, NULL_31369)), + ; + + private static final ImmutableMultimap GROUPS; + private static final Set SPOTS; + private static final Set TRAILS; + + static + { + ImmutableMultimap.Builder groupBuilder = new ImmutableMultimap.Builder<>(); + ImmutableSet.Builder spotBuilder = new ImmutableSet.Builder<>(); + ImmutableSet.Builder trailBuilder = new ImmutableSet.Builder<>(); + + for (HerbiboarSearchSpot spot : values()) + { + groupBuilder.put(spot.getGroup(), spot); + spotBuilder.add(spot.getLocation()); + + for (TrailToSpot trail : spot.getTrails()) + { + trailBuilder.addAll(trail.getFootprintIds()); + } + } + + GROUPS = groupBuilder.build(); + SPOTS = spotBuilder.build(); + TRAILS = trailBuilder.build(); + } + + private final Group group; + private final WorldPoint location; + private final List trails; + + HerbiboarSearchSpot(Group group, WorldPoint location, TrailToSpot... trails) + { + this.group = group; + this.location = location; + this.trails = ImmutableList.copyOf(trails); + } + + /** + * Spots are placed in groups of two + */ + enum Group + { + A, B, C, D, E, F, G, H, I, J, K + } + + static boolean isTrail(int id) + { + return TRAILS.contains(id); + } + + static boolean isSearchSpot(WorldPoint location) + { + return SPOTS.contains(location); + } + + static List getGroupLocations(Group group) + { + return GROUPS.get(group).stream().map(HerbiboarSearchSpot::getLocation).collect(Collectors.toList()); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/herbiboars/HerbiboarStart.java b/runelite-client/src/main/java/net/runelite/client/plugins/herbiboars/HerbiboarStart.java new file mode 100644 index 0000000000..3aa6485450 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/herbiboars/HerbiboarStart.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2020, dekvall + * 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.herbiboars; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import net.runelite.api.coords.WorldPoint; + +@Getter +@RequiredArgsConstructor +enum HerbiboarStart +{ + MIDDLE(new WorldPoint(3686, 3870, 0)), + LEPRECHAUN(new WorldPoint(3705, 3830, 0)), + CAMP_ENTRANCE(new WorldPoint(3704, 3810, 0)), + GHOST_MUSHROOM(new WorldPoint(3695, 3800, 0)), + DRIFTWOOD(new WorldPoint(3751, 3850, 0)), + ; + + private final WorldPoint location; + + static HerbiboarStart from(WorldPoint location) + { + for (final HerbiboarStart start : values()) + { + if (start.getLocation().equals(location)) + { + return start; + } + } + return null; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/herbiboars/HerbiboarTrail.java b/runelite-client/src/main/java/net/runelite/client/plugins/herbiboars/HerbiboarTrail.java deleted file mode 100644 index 6f1dba41fb..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/herbiboars/HerbiboarTrail.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) 2017, Tyler - * 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.herbiboars; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; -import lombok.AllArgsConstructor; -import lombok.Getter; -import net.runelite.api.Varbits; -import net.runelite.api.coords.WorldPoint; - -//Location of GameObjects which show TRAIL_xxxxx when used -@AllArgsConstructor -public enum HerbiboarTrail -{ - TRAIL_31303(31303, Varbits.HB_TRAIL_31303, null, new WorldPoint(3697, 3875, 0), null, new WorldPoint(3699, 3875, 0)), - TRAIL_31306(31306, Varbits.HB_TRAIL_31306, null, new WorldPoint(3672, 3890, 0), null, new WorldPoint(3670, 3889, 0)), - TRAIL_31309(31309, Varbits.HB_TRAIL_31309, null, new WorldPoint(3681, 3859, 0), null, new WorldPoint(3681, 3860, 0)), - TRAIL_31312(31312, Varbits.HB_TRAIL_31312, new WorldPoint(3699, 3875, 0), new WorldPoint(3710, 3877, 0), new WorldPoint(3697, 3875, 0), new WorldPoint(3708, 3876, 0)), - TRAIL_31315(31315, Varbits.HB_TRAIL_31315, new WorldPoint(3699, 3875, 0), new WorldPoint(3728, 3893, 0), new WorldPoint(3697, 3875, 0), null), - TRAIL_31318(31318, Varbits.HB_TRAIL_31318, new WorldPoint(3670, 3889, 0), new WorldPoint(3728, 3893, 0), new WorldPoint(3672, 3890, 0), null), - TRAIL_31321(31321, Varbits.HB_TRAIL_31321, new WorldPoint(3670, 3889, 0), new WorldPoint(3667, 3862, 0), new WorldPoint(3672, 3890, 0), new WorldPoint(3668, 3865, 0)), - TRAIL_31324(31324, Varbits.HB_TRAIL_31324, new WorldPoint(3681, 3860, 0), new WorldPoint(3680, 3836, 0), new WorldPoint(3681, 3859, 0), new WorldPoint(3680, 3838, 0)), - TRAIL_31327(31327, Varbits.HB_TRAIL_31327, new WorldPoint(3681, 3860, 0), new WorldPoint(3698, 3847, 0), new WorldPoint(3681, 3859, 0), new WorldPoint(3694, 3847, 0)), - TRAIL_31330(31330, Varbits.HB_TRAIL_31330, new WorldPoint(3708, 3876, 0), new WorldPoint(3713, 3850, 0), new WorldPoint(3710, 3877, 0), new WorldPoint(3715, 3851, 0)), - TRAIL_31333(31333, Varbits.HB_TRAIL_31333, new WorldPoint(3708, 3876, 0), new WorldPoint(3694, 3847, 0), new WorldPoint(3710, 3877, 0), new WorldPoint(3698, 3847, 0)), - TRAIL_31336(31336, Varbits.HB_TRAIL_31336, new WorldPoint(3728, 3893, 0), null, null, null), - TRAIL_31339(31339, Varbits.HB_TRAIL_31339, new WorldPoint(3728, 3893, 0), new WorldPoint(3710, 3877, 0), null, new WorldPoint(3708, 3876, 0)), - TRAIL_31342(31342, Varbits.HB_TRAIL_31342, new WorldPoint(3668, 3865, 0), new WorldPoint(3681, 3860, 0), new WorldPoint(3667, 3862, 0), new WorldPoint(3681, 3859, 0)), - TRAIL_31345(31345, Varbits.HB_TRAIL_31345, new WorldPoint(3668, 3865, 0), new WorldPoint(3680, 3836, 0), new WorldPoint(3667, 3862, 0), new WorldPoint(3680, 3838, 0)), - TRAIL_31348(31348, Varbits.HB_TRAIL_31348, new WorldPoint(3680, 3838, 0), new WorldPoint(3706, 3811, 0), new WorldPoint(3680, 3836, 0), null), - TRAIL_31351(31351, Varbits.HB_TRAIL_31351, new WorldPoint(3680, 3838, 0), null, new WorldPoint(3680, 3836, 0), null), - TRAIL_31354(31354, Varbits.HB_TRAIL_31354, new WorldPoint(3694, 3847, 0), null, new WorldPoint(3698, 3847, 0), null), - TRAIL_31357(31357, Varbits.HB_TRAIL_31357, new WorldPoint(3715, 3851, 0), new WorldPoint(3713, 3840, 0), new WorldPoint(3713, 3850, 0), null), - TRAIL_31360(31360, Varbits.HB_TRAIL_31360, new WorldPoint(3715, 3851, 0), null, new WorldPoint(3713, 3850, 0), null), - TRAIL_31363(31363, Varbits.HB_TRAIL_31363, new WorldPoint(3713, 3850, 0), null, new WorldPoint(3715, 3851, 0), null), - TRAIL_31366(31366, Varbits.HB_TRAIL_31366, null, null, null, null), - TRAIL_31369(31369, Varbits.HB_TRAIL_31369, new WorldPoint(3706, 3811, 0), null, null, null), - TRAIL_31372(31372, Varbits.HB_TRAIL_31372, new WorldPoint(3713, 3840, 0), null, null, null); - - @Getter - private final int trailId; - @Getter - private final Varbits varbit; - private final WorldPoint objectLoc1; - private final WorldPoint objectLoc2; - private final WorldPoint objectLoc3; - private final WorldPoint objectLoc4; - - @Getter - private static Set trailIds = new HashSet<>(); - @Getter - private static Set allObjectLocs = new HashSet<>(); - - static - { - for (HerbiboarTrail trail : values()) - { - trailIds.add(trail.trailId); - trailIds.add(trail.trailId + 1); - - allObjectLocs.addAll(Arrays.asList(trail.getObjectLocs(1))); - allObjectLocs.addAll(Arrays.asList(trail.getObjectLocs(2))); - } - } - - public WorldPoint[] getObjectLocs(int varbitValue) - { - switch (varbitValue) - { - case 1: - return new WorldPoint[]{objectLoc1, objectLoc3}; - case 2: - return new WorldPoint[]{objectLoc2, objectLoc4}; - case 0: - default: - return new WorldPoint[]{}; - } - } - - @Override - public String toString() - { - return String.format("trailId=%s obj1=%s obj2=%s obj3=%s obj4=%s", trailId, objectLoc1, objectLoc2, objectLoc3, objectLoc4); - } -} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/herbiboars/TrailToSpot.java b/runelite-client/src/main/java/net/runelite/client/plugins/herbiboars/TrailToSpot.java new file mode 100644 index 0000000000..17c0b923cb --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/herbiboars/TrailToSpot.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2020, dekvall + * Copyright (c) 2020, Jordan + * 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.herbiboars; + +import com.google.common.collect.ImmutableSet; +import java.util.Set; +import lombok.Value; +import net.runelite.api.Varbits; + +/** + * A representation of a trail of footsteps which appears when hunting for the Herbiboar. + */ +@Value +class TrailToSpot +{ + /** + * The Varbit associated with the trail. When inactive, this Varbit's value should be less than + * {@link TrailToSpot#getValue()}. When this trail appears after searching a spot, this Varbit's value should be + * equal to that of {@link TrailToSpot#getValue()}. Once the next object along the trail has been searched, this + * Varbit's value will be greater than that of {@link TrailToSpot#getValue()}. + */ + private final Varbits varbit; + /** + * The cutoff reference value to compare against the value of {@link TrailToSpot#getVarbit()} to determine its state + * along the current trail. + */ + private final int value; + /** + * The object ID of the footprints which appear when the trail is made visible. + */ + private final int footprint; + + Set getFootprintIds() + { + return ImmutableSet.of(footprint, footprint + 1); + } +}