Add hunter plugin
This commit is contained in:
@@ -43,6 +43,12 @@ public final class AnimationID
|
||||
public static final int COOKING_FIRE = 897;
|
||||
public static final int COOKING_RANGE = 896;
|
||||
public static final int FLETCHING_BOW_CUTTING = 1248;
|
||||
public static final int HUNTER_LAY_BOXTRAP_BIRDSNARE = 5208; //same for laying bird snares and box traps
|
||||
public static final int HUNTER_LAY_DEADFALLTRAP = 5212; //setting up deadfall trap
|
||||
public static final int HUNTER_LAY_NETTRAP = 5215; //setting up net trap
|
||||
public static final int HUNTER_CHECK_BIRD_SNARE = 5207;
|
||||
public static final int HUNTER_CHECK_BOX_TRAP = 5212;
|
||||
public static final int HERBLORE_MAKE_TAR = 5249;
|
||||
public static final int FLETCHING_STRING_NORMAL_SHORTBOW = 6678;
|
||||
public static final int FLETCHING_STRING_NORMAL_LONGBOW = 6684;
|
||||
public static final int FLETCHING_STRING_OAK_SHORTBOW = 6679;
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Robin Weymans <Robin.weymans@gmail.com>
|
||||
* 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.hunter;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Point;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import javax.inject.Inject;
|
||||
import net.runelite.client.ui.overlay.Overlay;
|
||||
import net.runelite.client.ui.overlay.OverlayPosition;
|
||||
import net.runelite.client.ui.overlay.components.PanelComponent;
|
||||
|
||||
/**
|
||||
* Represents the overlay that shows the catch rate (percentage).
|
||||
*/
|
||||
public class CatchrateOverlay extends Overlay
|
||||
{
|
||||
/**
|
||||
* The time after which the catch rate panel disappears, if the player
|
||||
* stops hunting.
|
||||
*/
|
||||
private final Duration catchRatePanelTimeOut = Duration.ofSeconds(30);
|
||||
private final PanelComponent catchRatePanel = new PanelComponent();
|
||||
|
||||
private final HunterPlugin plugin;
|
||||
private final HunterConfig config;
|
||||
|
||||
@Inject
|
||||
CatchrateOverlay(HunterPlugin plugin, HunterConfig config)
|
||||
{
|
||||
setPosition(OverlayPosition.BOTTOM_RIGHT);
|
||||
this.plugin = plugin;
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics, Point parent)
|
||||
{
|
||||
if (config.enabled())
|
||||
{
|
||||
if (Duration.between(plugin.getLastActionTime(), Instant.now()).compareTo(catchRatePanelTimeOut) < 0)
|
||||
{
|
||||
final String attackStyleString = String.format("%.2f", plugin.getCatchRate() * 100) + " %";
|
||||
catchRatePanel.setTitle(attackStyleString);
|
||||
catchRatePanel.setWidth(80);
|
||||
return catchRatePanel.render(graphics, parent);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Robin Weymans <Robin.weymans@gmail.com>
|
||||
* 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.hunter;
|
||||
|
||||
import java.awt.Color;
|
||||
import net.runelite.client.config.Config;
|
||||
import net.runelite.client.config.ConfigGroup;
|
||||
import net.runelite.client.config.ConfigItem;
|
||||
|
||||
@ConfigGroup(
|
||||
keyName = "hunterplugin",
|
||||
name = "Hunter plugin",
|
||||
description = "Configuration for the hunter plugin"
|
||||
)
|
||||
public interface HunterConfig extends Config
|
||||
{
|
||||
@ConfigItem(
|
||||
position = 0,
|
||||
keyName = "enabled",
|
||||
name = "Enabled",
|
||||
description = "Configures whether or not the hunter plugin is enabled"
|
||||
)
|
||||
default boolean enabled()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 1,
|
||||
keyName = "hexColorOpenTrap",
|
||||
name = "Open trap",
|
||||
description = "Color of open trap timer"
|
||||
)
|
||||
default Color getOpenTrapColor()
|
||||
{
|
||||
return Color.YELLOW;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 2,
|
||||
keyName = "hexColorFullTrap",
|
||||
name = "Full trap",
|
||||
description = "Color of full trap timer"
|
||||
)
|
||||
default Color getFullTrapColor()
|
||||
{
|
||||
return Color.GREEN;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 3,
|
||||
keyName = "hexColorEmptyTrap",
|
||||
name = "Empty trap",
|
||||
description = "Color of empty trap timer"
|
||||
)
|
||||
default Color getEmptyTrapColor()
|
||||
{
|
||||
return Color.RED;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 4,
|
||||
keyName = "hexColorTransTrap",
|
||||
name = "Transitioning trap",
|
||||
description = "Color of transitioning trap timer"
|
||||
)
|
||||
default Color getTransTrapColor()
|
||||
{
|
||||
return Color.ORANGE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,348 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Robin Weymans <Robin.weymans@gmail.com>
|
||||
* 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.hunter;
|
||||
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
import com.google.inject.Binder;
|
||||
import com.google.inject.Provides;
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import javax.inject.Inject;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.AnimationID;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GameObject;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.ObjectID;
|
||||
import net.runelite.api.Player;
|
||||
import net.runelite.api.Point;
|
||||
import net.runelite.api.queries.GameObjectQuery;
|
||||
import net.runelite.api.queries.PlayerQuery;
|
||||
import net.runelite.client.RuneLite;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.client.events.GameObjectsChanged;
|
||||
import net.runelite.client.events.GameStateChanged;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.task.Schedule;
|
||||
import net.runelite.client.ui.overlay.Overlay;
|
||||
|
||||
@Slf4j
|
||||
@PluginDescriptor(
|
||||
name = "Hunter plugin"
|
||||
)
|
||||
public class HunterPlugin extends Plugin
|
||||
{
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private RuneLite runelite;
|
||||
|
||||
@Inject
|
||||
private HunterConfig config;
|
||||
|
||||
@Inject
|
||||
private TrapOverlay trapOverlay;
|
||||
|
||||
@Inject
|
||||
private CatchrateOverlay catchrateOverlay;
|
||||
|
||||
@Getter
|
||||
private final Set<HunterTrap> traps = new HashSet<>();
|
||||
|
||||
private double catchAtempts = 0;
|
||||
private double catchSuccess = 0;
|
||||
|
||||
@Getter
|
||||
private Instant lastActionTime = Instant.ofEpochMilli(0);
|
||||
|
||||
@Override
|
||||
public void configure(Binder binder)
|
||||
{
|
||||
binder.bind(TrapOverlay.class);
|
||||
binder.bind(CatchrateOverlay.class);
|
||||
}
|
||||
|
||||
@Provides
|
||||
HunterConfig provideConfig(ConfigManager configManager)
|
||||
{
|
||||
return configManager.getConfig(HunterConfig.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Overlay> getOverlays()
|
||||
{
|
||||
return Arrays.asList(trapOverlay, catchrateOverlay);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGameObjectsChanged(GameObjectsChanged event)
|
||||
{
|
||||
if (!config.enabled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
GameObject gameObject = event.getGameObject();
|
||||
|
||||
HunterTrap myTrap = getTrapFromCollection(gameObject);
|
||||
|
||||
Player localPlayer = client.getLocalPlayer();
|
||||
|
||||
switch (gameObject.getId())
|
||||
{
|
||||
case ObjectID.DEADFALL: //Deadfall trap placed
|
||||
if (localPlayer.getWorldLocation().distanceTo(gameObject.getWorldLocation()) <= 2
|
||||
&& localPlayer.getAnimation() == AnimationID.HUNTER_LAY_DEADFALLTRAP)
|
||||
{
|
||||
log.debug("Deadfall trap placed by \"{}\" on {}", localPlayer.getName(), gameObject.getWorldLocation());
|
||||
traps.add(new HunterTrap(gameObject));
|
||||
lastActionTime = Instant.now();
|
||||
}
|
||||
break;
|
||||
case ObjectID.BOX_TRAP_9380: //Box trap placed
|
||||
case ObjectID.BIRD_SNARE_9345: //Bird snare placed
|
||||
case ObjectID.NET_TRAP_9343: //Net trap placed at green sallys
|
||||
case ObjectID.NET_TRAP: //Net trap placed at orange sallys
|
||||
case ObjectID.NET_TRAP_8992: //Net trap placed at red sallys
|
||||
case ObjectID.NET_TRAP_9002: //Net trap placed at black sallys
|
||||
//Look for players that are on the same tile
|
||||
PlayerQuery playerQuery = new PlayerQuery().atLocalLocation(gameObject.getLocalLocation());
|
||||
List<Player> possiblePlayers = Arrays.asList(runelite.runQuery(playerQuery));
|
||||
|
||||
/* If the player is on that tile, and it has the correct animation, assume he is the one that placed the trap
|
||||
* Special case: if you herb+tar, then move and place the trap, it does not detect laying the trap. It does work
|
||||
* if you herb+tar en then place the trap.
|
||||
*/
|
||||
if (possiblePlayers.contains(localPlayer))
|
||||
{
|
||||
switch (localPlayer.getAnimation())
|
||||
{
|
||||
case AnimationID.HUNTER_LAY_BOXTRAP_BIRDSNARE:
|
||||
case AnimationID.HUNTER_LAY_NETTRAP:
|
||||
case AnimationID.HERBLORE_MAKE_TAR: // When 3 ticking
|
||||
log.debug("Trap placed by \"{}\" on {}", localPlayer.getName(), localPlayer.getWorldLocation());
|
||||
traps.add(new HunterTrap(gameObject));
|
||||
|
||||
lastActionTime = Instant.now();
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
case ObjectID.SHAKING_BOX: //Black chinchompa caught
|
||||
case ObjectID.SHAKING_BOX_9382: // Grey chinchompa caught
|
||||
case ObjectID.SHAKING_BOX_9383: //Red chinchompa caught
|
||||
case ObjectID.BOULDER_20648: //Prickly kebbit caught
|
||||
case ObjectID.BOULDER_20649: //Sabre-tooth kebbit caught
|
||||
case ObjectID.BOULDER_20650: //Barb-tailed kebbit caught
|
||||
case ObjectID.BOULDER_20651: //Wild kebbit caught
|
||||
case ObjectID.BIRD_SNARE_9373: //Crimson swift caught
|
||||
case ObjectID.BIRD_SNARE_9375: //Cerulean twitch caught
|
||||
case ObjectID.BIRD_SNARE_9377: //Golden warbler caught
|
||||
case ObjectID.BIRD_SNARE_9379: //Copper longtail caught
|
||||
case ObjectID.BIRD_SNARE_9348: //Tropical wagtail caught
|
||||
case ObjectID.NET_TRAP_9004: //Green sally caught
|
||||
case ObjectID.NET_TRAP_8986: //Red sally caught
|
||||
case ObjectID.NET_TRAP_8734: //Orange sally caught
|
||||
case ObjectID.NET_TRAP_8996: //Black sally caught
|
||||
if (myTrap != null)
|
||||
{
|
||||
log.debug("Yay, you caught something");
|
||||
myTrap.setState(HunterTrap.State.FULL);
|
||||
catchAtempts++;
|
||||
catchSuccess++;
|
||||
|
||||
lastActionTime = Instant.now();
|
||||
}
|
||||
break;
|
||||
case ObjectID.BOX_TRAP_9385: //Empty box trap
|
||||
case ObjectID.BIRD_SNARE: //Empty box trap
|
||||
if (myTrap != null)
|
||||
{
|
||||
log.debug("Your trap didn't catch anything");
|
||||
myTrap.setState(HunterTrap.State.EMPTY);
|
||||
myTrap.resetTimer();
|
||||
catchAtempts++;
|
||||
|
||||
lastActionTime = Instant.now();
|
||||
}
|
||||
break;
|
||||
//Black chin shaking box
|
||||
case ObjectID.BOX_TRAP:
|
||||
case ObjectID.BOX_TRAP_2026:
|
||||
case ObjectID.BOX_TRAP_2028:
|
||||
case ObjectID.BOX_TRAP_2029:
|
||||
|
||||
//Red chin shaking box
|
||||
case ObjectID.BOX_TRAP_9381:
|
||||
case ObjectID.BOX_TRAP_9390:
|
||||
case ObjectID.BOX_TRAP_9391:
|
||||
case ObjectID.BOX_TRAP_9392:
|
||||
case ObjectID.BOX_TRAP_9393:
|
||||
|
||||
//Grey chin shaking box
|
||||
case ObjectID.BOX_TRAP_9386:
|
||||
case ObjectID.BOX_TRAP_9387:
|
||||
case ObjectID.BOX_TRAP_9388:
|
||||
|
||||
//Bird traps
|
||||
case ObjectID.BIRD_SNARE_9346:
|
||||
case ObjectID.BIRD_SNARE_9347:
|
||||
case ObjectID.BIRD_SNARE_9349:
|
||||
case ObjectID.BIRD_SNARE_9374:
|
||||
case ObjectID.BIRD_SNARE_9376:
|
||||
case ObjectID.BIRD_SNARE_9378:
|
||||
|
||||
//Deadfall trap
|
||||
case ObjectID.DEADFALL_19218:
|
||||
case ObjectID.DEADFALL_19851:
|
||||
case ObjectID.DEADFALL_20128:
|
||||
case ObjectID.DEADFALL_20129:
|
||||
case ObjectID.DEADFALL_20130:
|
||||
case ObjectID.DEADFALL_20131:
|
||||
|
||||
//Net trap
|
||||
case ObjectID.NET_TRAP_9003:
|
||||
case ObjectID.NET_TRAP_9005:
|
||||
case ObjectID.NET_TRAP_8972:
|
||||
case ObjectID.NET_TRAP_8974:
|
||||
case ObjectID.NET_TRAP_8985:
|
||||
case ObjectID.NET_TRAP_8987:
|
||||
case ObjectID.NET_TRAP_8993:
|
||||
case ObjectID.NET_TRAP_8997:
|
||||
if (myTrap != null)
|
||||
{
|
||||
myTrap.setState(HunterTrap.State.TRANSITION);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGameStateChange(GameStateChanged event)
|
||||
{
|
||||
if (event.getGameState().equals(GameState.LOGIN_SCREEN))
|
||||
{
|
||||
trapOverlay.updateConfig();
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onConfigChanged(ConfigChanged event)
|
||||
{
|
||||
if (event.getGroup().equals("hunterplugin"))
|
||||
{
|
||||
trapOverlay.updateConfig();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates over all the traps that were placed by the local player and
|
||||
* checks if the trap is still there. If the trap is gone, it removes
|
||||
* the trap from the local players trap collection.
|
||||
*/
|
||||
@Schedule(
|
||||
period = 500,
|
||||
unit = ChronoUnit.MILLIS
|
||||
)
|
||||
public void updateTraps()
|
||||
{
|
||||
if (!config.enabled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//Check if all traps are still there, and remove the ones that are not.
|
||||
Iterator<HunterTrap> it = traps.iterator();
|
||||
while (it.hasNext())
|
||||
{
|
||||
HunterTrap trap = it.next();
|
||||
|
||||
//Look for gameobjects that are on the same location as the trap
|
||||
GameObjectQuery goQuery = new GameObjectQuery()
|
||||
.atWorldLocation(trap.getGameObject().getWorldLocation());
|
||||
//This is for placeable traps like box traps. There are no gameobjects on that location if the trap collapsed
|
||||
if (runelite.runQuery(goQuery).length == 0)
|
||||
{
|
||||
it.remove();
|
||||
log.debug("Trap removed from personal trap collection, {} left", traps.size());
|
||||
}
|
||||
else //For traps like deadfalls. This is different because when the trap is gone, there is still a GameObject (boulder)
|
||||
{
|
||||
goQuery = goQuery
|
||||
.idEquals(ObjectID.BOULDER_19215); //Deadfalls are the only ones (that i can test) that have this behaviour. I think maniacal monkeys have this too.
|
||||
if (runelite.runQuery(goQuery).length != 0)
|
||||
{
|
||||
it.remove();
|
||||
log.debug("Special trap removed from personal trap collection, {} left", traps.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks for a trap in the local players trap collection, on the same
|
||||
* place as the given GameObject.
|
||||
*
|
||||
* @param gameObject
|
||||
* @return A HunterTrap object if the player has a trap on the same
|
||||
* location as the GameObject. Otherwise it returns null.
|
||||
*/
|
||||
private HunterTrap getTrapFromCollection(GameObject gameObject)
|
||||
{
|
||||
Point gameObjectLocation = gameObject.getWorldLocation();
|
||||
for (HunterTrap trap : traps)
|
||||
{
|
||||
if (gameObjectLocation.equals(trap.getGameObject().getWorldLocation()))
|
||||
{
|
||||
return trap;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the catch rate, i.e. the attempts to catch something
|
||||
* compared to the times you succeed.
|
||||
*
|
||||
* @return Value between 0 (none) and 1 (all).
|
||||
*/
|
||||
public double getCatchRate()
|
||||
{
|
||||
return catchAtempts != 0 ? catchSuccess / catchAtempts : 0;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Robin Weymans <Robin.weymans@gmail.com>
|
||||
* 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.hunter;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.Objects;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import net.runelite.api.GameObject;
|
||||
|
||||
/**
|
||||
* Wrapper class for a GameObject that represents a hunter trap.
|
||||
*/
|
||||
class HunterTrap
|
||||
{
|
||||
/**
|
||||
* A hunter trap stays up 1 minute before collapsing.
|
||||
*/
|
||||
private static final Duration TRAP_TIME = Duration.ofMinutes(1);
|
||||
|
||||
/**
|
||||
* The time in milliseconds when the trap was placed.
|
||||
*/
|
||||
@Getter
|
||||
private Instant placedOn;
|
||||
|
||||
/**
|
||||
* The state of the trap.
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
private State state;
|
||||
|
||||
/**
|
||||
* The gameobject thats corresponds with this trap.
|
||||
*/
|
||||
@Getter
|
||||
private final GameObject gameObject;
|
||||
|
||||
/**
|
||||
* The states a trap can be in.
|
||||
*/
|
||||
enum State
|
||||
{
|
||||
/**
|
||||
* A laid out trap.
|
||||
*/
|
||||
OPEN,
|
||||
/**
|
||||
* A trap that is empty.
|
||||
*/
|
||||
EMPTY,
|
||||
/**
|
||||
* A trap that caught something.
|
||||
*/
|
||||
FULL,
|
||||
/**
|
||||
* A trap that is closing.
|
||||
*/
|
||||
TRANSITION
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for a HunterTrap object
|
||||
*
|
||||
* @param gameObject The gameobject thats corresponds with this trap.
|
||||
*/
|
||||
HunterTrap(GameObject gameObject)
|
||||
{
|
||||
this.state = State.OPEN;
|
||||
this.gameObject = gameObject;
|
||||
this.placedOn = Instant.now();
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates how much time is left before the trap is collapsing.
|
||||
*
|
||||
* @return Value between 0 and 1. 0 means the trap was laid moments ago.
|
||||
* 1 is a trap that's about to collapse.
|
||||
*/
|
||||
public double getTrapTimeRelative()
|
||||
{
|
||||
Duration duration = Duration.between(placedOn, Instant.now());
|
||||
return duration.compareTo(TRAP_TIME) < 0 ? (double) duration.toMillis() / TRAP_TIME.toMillis() : 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the time value when the trap was placed.
|
||||
*/
|
||||
public void resetTimer()
|
||||
{
|
||||
placedOn = Instant.now();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (o == this)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof HunterTrap))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
HunterTrap t = (HunterTrap) o;
|
||||
return gameObject.getWorldLocation().equals(t.getGameObject().getWorldLocation());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
int hash = 7;
|
||||
hash = 97 * hash + Objects.hashCode(this.gameObject);
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Robin Weymans <Robin.weymans@gmail.com>
|
||||
* 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.hunter;
|
||||
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Point;
|
||||
import java.awt.geom.Arc2D;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.client.ui.overlay.Overlay;
|
||||
import net.runelite.client.ui.overlay.OverlayPosition;
|
||||
|
||||
/**
|
||||
* Represents the overlay that shows timers on traps that are placed by the
|
||||
* player.
|
||||
*/
|
||||
public class TrapOverlay extends Overlay
|
||||
{
|
||||
/**
|
||||
* Size of the trap timer.
|
||||
*/
|
||||
private static final int TIMER_SIZE = 25;
|
||||
|
||||
/**
|
||||
* Width of the border around the trap timer.
|
||||
*/
|
||||
private static final int TIMER_BORDER_WIDTH = 1;
|
||||
|
||||
/**
|
||||
* The timer is low when only 25% is left.
|
||||
*/
|
||||
private static final double TIMER_LOW = 0.25; // When the timer is under a quarter left, if turns red.
|
||||
|
||||
private final Client client;
|
||||
private final HunterPlugin plugin;
|
||||
private final HunterConfig config;
|
||||
|
||||
private Color colorOpen, colorOpenBorder;
|
||||
private Color colorEmpty, colorEmptyBorder;
|
||||
private Color colorFull, colorFullBorder;
|
||||
private Color colorTrans, colorTransBorder;
|
||||
|
||||
@Inject
|
||||
TrapOverlay(@Nullable Client client, HunterPlugin plugin, HunterConfig config)
|
||||
{
|
||||
setPosition(OverlayPosition.DYNAMIC);
|
||||
this.plugin = plugin;
|
||||
this.config = config;
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics, Point parent)
|
||||
{
|
||||
if (config.enabled())
|
||||
{
|
||||
drawTraps(graphics);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the timer colors.
|
||||
*/
|
||||
public void updateConfig()
|
||||
{
|
||||
colorEmptyBorder = config.getEmptyTrapColor();
|
||||
colorEmpty = new Color(colorEmptyBorder.getRed(), colorEmptyBorder.getGreen(), colorEmptyBorder.getBlue(), 100);
|
||||
colorFullBorder = config.getFullTrapColor();
|
||||
colorFull = new Color(colorFullBorder.getRed(), colorFullBorder.getGreen(), colorFullBorder.getBlue(), 100);
|
||||
colorOpenBorder = config.getOpenTrapColor();
|
||||
colorOpen = new Color(colorOpenBorder.getRed(), colorOpenBorder.getGreen(), colorOpenBorder.getBlue(), 100);
|
||||
colorTransBorder = config.getTransTrapColor();
|
||||
colorTrans = new Color(colorTransBorder.getRed(), colorTransBorder.getGreen(), colorTransBorder.getBlue(), 100);
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates over all the traps that were placed by the local player, and
|
||||
* draws a circle or a timer on the trap, depending on the trap state.
|
||||
*
|
||||
* @param graphics
|
||||
*/
|
||||
private void drawTraps(Graphics2D graphics)
|
||||
{
|
||||
Widget viewport = client.getViewportWidget();
|
||||
for (HunterTrap trap : plugin.getTraps())
|
||||
{
|
||||
if (viewport != null && viewport.contains(trap.getGameObject().getCanvasLocation()))
|
||||
{
|
||||
switch (trap.getState())
|
||||
{
|
||||
case OPEN:
|
||||
drawTimerOnTrap(graphics, trap, colorOpen, colorOpenBorder, colorEmpty, colorOpenBorder);
|
||||
break;
|
||||
case EMPTY:
|
||||
drawTimerOnTrap(graphics, trap, colorEmpty, colorEmptyBorder, colorEmpty, colorEmptyBorder);
|
||||
break;
|
||||
case FULL:
|
||||
drawCircleOnTrap(graphics, trap, colorFull, colorFullBorder);
|
||||
break;
|
||||
case TRANSITION:
|
||||
drawCircleOnTrap(graphics, trap, colorTrans, colorTransBorder);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a timer on a given trap.
|
||||
*
|
||||
* @param graphics
|
||||
* @param trap The trap on which the timer needs to be drawn
|
||||
* @param fill The fill color of the timer
|
||||
* @param border The border color of the timer
|
||||
* @param fillTimeLow The fill color of the timer when it is low
|
||||
* @param borderTimeLow The border color of the timer when it is low
|
||||
*/
|
||||
private void drawTimerOnTrap(Graphics2D graphics, HunterTrap trap, Color fill, Color border, Color fillTimeLow, Color borderTimeLow)
|
||||
{
|
||||
net.runelite.api.Point loc = trap.getGameObject().getCanvasLocation();
|
||||
|
||||
//Construct the arc
|
||||
Arc2D.Float arc = new Arc2D.Float(Arc2D.PIE);
|
||||
arc.setAngleStart(90);
|
||||
double timeLeft = 1 - trap.getTrapTimeRelative();
|
||||
arc.setAngleExtent(timeLeft * 360);
|
||||
arc.setFrame(loc.getX() - TIMER_SIZE / 2, loc.getY() - TIMER_SIZE / 2, TIMER_SIZE, TIMER_SIZE);
|
||||
|
||||
//Draw the inside of the arc
|
||||
graphics.setColor(timeLeft > TIMER_LOW ? fill : fillTimeLow);
|
||||
graphics.fill(arc);
|
||||
|
||||
//Draw the outlines of the arc
|
||||
graphics.setStroke(new BasicStroke(TIMER_BORDER_WIDTH));
|
||||
graphics.setColor(timeLeft > TIMER_LOW ? border : borderTimeLow);
|
||||
graphics.drawOval(loc.getX() - TIMER_SIZE / 2, loc.getY() - TIMER_SIZE / 2, TIMER_SIZE, TIMER_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a timer on a given trap.
|
||||
*
|
||||
* @param graphics
|
||||
* @param trap The trap on which the timer needs to be drawn
|
||||
* @param fill The fill color of the timer
|
||||
* @param border The border color of the timer
|
||||
*/
|
||||
private void drawCircleOnTrap(Graphics2D graphics, HunterTrap trap, Color fill, Color border)
|
||||
{
|
||||
net.runelite.api.Point loc = trap.getGameObject().getCanvasLocation();
|
||||
|
||||
//Draw the inside of the arc
|
||||
graphics.setColor(fill);
|
||||
graphics.fillOval(loc.getX() - TIMER_SIZE / 2, loc.getY() - TIMER_SIZE / 2, TIMER_SIZE, TIMER_SIZE);
|
||||
|
||||
//Draw the border of the cirlce
|
||||
graphics.setColor(border);
|
||||
graphics.setStroke(new BasicStroke(TIMER_BORDER_WIDTH));
|
||||
graphics.drawOval(loc.getX() - TIMER_SIZE / 2, loc.getY() - TIMER_SIZE / 2, TIMER_SIZE, TIMER_SIZE);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user