Add slayer plugin

This commit is contained in:
Tyler Hardy
2017-11-03 19:02:05 -04:00
committed by Adam
parent 4b6a4e42bb
commit 000d3ffdb2
8 changed files with 998 additions and 1 deletions

View File

@@ -43,6 +43,21 @@ class WidgetID
static final int SHOP_GROUP_ID = 300;
static final int SHOP_INVENTORY_GROUP_ID = 301;
static final int COMBAT_GROUP_ID = 593;
static final int DIALOG_NPC_GROUP_ID = 231;
static final int SLAYER_REWARDS_GROUP_ID = 426;
static class SlayerRewards
{
static final int TOP_BAR = 12;
}
static class DialogNPC
{
static final int HEAD_MODEL = 0;
static final int NAME = 1;
static final int CONTINUE = 2;
static final int TEXT = 3;
}
static class PestControl
{

View File

@@ -81,7 +81,14 @@ public enum WidgetInfo
PRAYER_PROTECT_FROM_MAGIC(WidgetID.PRAYER_GROUP_ID, WidgetID.Prayer.PROTECT_FROM_MAGIC),
PRAYER_PROTECT_FROM_MISSILES(WidgetID.PRAYER_GROUP_ID, WidgetID.Prayer.PROTECT_FROM_MISSILES),
COMBAT_LEVEL(WidgetID.COMBAT_GROUP_ID, WidgetID.Combat.LEVEL);
COMBAT_LEVEL(WidgetID.COMBAT_GROUP_ID, WidgetID.Combat.LEVEL),
DIALOG_NPC_NAME(WidgetID.DIALOG_NPC_GROUP_ID, WidgetID.DialogNPC.NAME),
DIALOG_NPC_TEXT(WidgetID.DIALOG_NPC_GROUP_ID, WidgetID.DialogNPC.TEXT),
DIALOG_NPC_HEAD_MODEL(WidgetID.DIALOG_NPC_GROUP_ID, WidgetID.DialogNPC.HEAD_MODEL),
DIALOG_NPC_CONTINUE(WidgetID.DIALOG_NPC_GROUP_ID, WidgetID.DialogNPC.CONTINUE),
SLAYER_REWARDS_TOPBAR(WidgetID.SLAYER_REWARDS_GROUP_ID, WidgetID.SlayerRewards.TOP_BAR);
private final int groupId;

View File

@@ -0,0 +1,339 @@
/*
* Copyright (c) 2017, Tyler <https://github.com/tylerthardy>
* 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.slayer;
import com.google.common.eventbus.Subscribe;
import java.awt.image.BufferedImage;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import net.runelite.api.ChatMessageType;
import net.runelite.api.Client;
import net.runelite.api.ItemID;
import static net.runelite.api.Skill.SLAYER;
import net.runelite.api.widgets.Widget;
import net.runelite.api.widgets.WidgetInfo;
import net.runelite.client.RuneLite;
import net.runelite.client.events.ChatMessage;
import net.runelite.client.events.ExperienceChanged;
import net.runelite.client.events.GameStateChanged;
import net.runelite.client.game.ItemManager;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.task.Schedule;
import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@PluginDescriptor(
name = "Slayer plugin"
)
public class Slayer extends Plugin
{
private static final Logger logger = LoggerFactory.getLogger(Slayer.class);
//Chat messages
private static final Pattern CHAT_GEM_PROGRESS_MESSAGE = Pattern.compile("You're assigned to kill (.*); only (\\d*) more to go\\.");
private static final String CHAT_GEM_COMPLETE_MESSAGE = "You need something new to hunt.";
private static final Pattern CHAT_COMPLETE_MESSAGE = Pattern.compile("[\\d]+(?:,[\\d]+)?");
private static final String CHAT_CANCEL_MESSAGE = "Your task has been cancelled.";
//NPC messages
private static final Pattern NPC_ASSIGN_MESSAGE = Pattern.compile(".*Your new task is to kill (\\d*) (.*)\\.");
private static final Pattern NPC_CURRENT_MESSAGE = Pattern.compile("You're still hunting (.*), you have (\\d*) to go\\..*");
//Reward UI
private static final Pattern REWARD_POINTS = Pattern.compile("Reward points: (\\d*)");
private final InfoBoxManager infoBoxManager = RuneLite.getRunelite().getInfoBoxManager();
private final SlayerConfig config = RuneLite.getRunelite().getConfigManager().getConfig(SlayerConfig.class);
private final SlayerOverlay overlay = new SlayerOverlay(this);
private final Client client = RuneLite.getClient();
private String taskName;
private int amount;
private TaskCounter counter;
private int streak;
private int points;
private int cachedXp;
@Override
protected void startUp() throws Exception
{
}
@Override
protected void shutDown() throws Exception
{
}
@Subscribe
public void onGameStateChange(GameStateChanged event)
{
if (!config.enabled())
{
return;
}
switch (event.getGameState())
{
case HOPPING:
case LOGGING_IN:
cachedXp = 0;
taskName = "";
amount = 0;
break;
case LOGGED_IN:
if (config.amount() != -1 && !config.taskName().isEmpty())
{
setTask(config.taskName(), config.amount());
}
break;
}
}
private void save()
{
config.amount(amount);
config.taskName(taskName);
config.points(points);
config.streak(streak);
}
@Schedule(
period = 600,
unit = ChronoUnit.MILLIS
)
public void scheduledChecks()
{
if (!config.enabled() || client == null)
{
return;
}
Widget NPCDialog = client.getWidget(WidgetInfo.DIALOG_NPC_TEXT);
if (NPCDialog != null)
{
String NPCText = NPCDialog.getText().replaceAll("<[^>]*>", " "); //remove color and linebreaks
Matcher mAssign = NPC_ASSIGN_MESSAGE.matcher(NPCText); //number, name
Matcher mCurrent = NPC_CURRENT_MESSAGE.matcher(NPCText); //name, number
boolean found1 = mAssign.find();
boolean found2 = mCurrent.find();
if (!found1 && !found2)
{
return;
}
String taskName = found1 ? mAssign.group(2) : mCurrent.group(1);
int amount = Integer.parseInt(found1 ? mAssign.group(1) : mCurrent.group(2));
setTask(taskName, amount);
}
Widget rewardsBarWidget = client.getWidget(WidgetInfo.SLAYER_REWARDS_TOPBAR);
if (rewardsBarWidget != null)
{
for (Widget w : rewardsBarWidget.getDynamicChildren())
{
Matcher mPoints = REWARD_POINTS.matcher(w.getText());
if (mPoints.find())
{
points = Integer.parseInt(mPoints.group(1));
break;
}
}
}
}
@Subscribe
public void onChatMessage(ChatMessage event)
{
if (!config.enabled() || event.getType() != ChatMessageType.SERVER)
{
return;
}
String chatMsg = event.getMessage().replaceAll("<[^>]*>", ""); //remove color and linebreaks
if (chatMsg.endsWith("; return to a Slayer master."))
{
Matcher mComplete = CHAT_COMPLETE_MESSAGE.matcher(chatMsg);
List<String> matches = new ArrayList<>();
while (mComplete.find())
{
matches.add(mComplete.group(0));
}
switch (matches.size())
{
case 0:
streak = 1;
break;
case 1:
streak = Integer.parseInt(matches.get(0));
break;
case 3:
streak = Integer.parseInt(matches.get(0));
points = Integer.parseInt(matches.get(2).replaceAll(",", ""));
break;
default:
logger.warn("Unreachable default case for message ending in '; return to Slayer master'");
}
setTask("", 0);
return;
}
if (chatMsg.equals(CHAT_GEM_COMPLETE_MESSAGE) || chatMsg.equals(CHAT_CANCEL_MESSAGE))
{
setTask("", 0);
return;
}
Matcher mProgress = CHAT_GEM_PROGRESS_MESSAGE.matcher(chatMsg);
if (!mProgress.find())
{
return;
}
String taskName = mProgress.group(1);
int amount = Integer.parseInt(mProgress.group(2));
setTask(taskName, amount);
}
@Subscribe
public void onExperienceChanged(ExperienceChanged event)
{
if (!config.enabled() || event.getSkill() != SLAYER)
{
return;
}
if (cachedXp == 0)
{
// this is the initial xp sent on login
cachedXp = client.getSkillExperience(SLAYER);
return;
}
killedOne();
}
private void killedOne()
{
amount--;
save();
if (!config.showInfobox())
{
return;
}
counter.setText(String.valueOf(amount));
}
private void setTask(String name, int amt)
{
taskName = name.toLowerCase();
amount = amt;
save();
infoBoxManager.removeIf(t -> t instanceof TaskCounter);
if (taskName.isEmpty() || !config.showInfobox())
{
return;
}
Task task = Task.getTask(taskName);
if (task == null)
{
logger.warn("No slayer task for {} in the Task database", taskName);
}
BufferedImage taskImg = task != null ? task.getImage() : ItemManager.getImage(ItemID.ENCHANTED_GEM);
counter = new TaskCounter(taskImg, amount);
counter.setTooltip(capsString(taskName));
infoBoxManager.addInfoBox(counter);
}
//Getters
public SlayerConfig getConfig()
{
return config;
}
@Override
public SlayerOverlay getOverlay()
{
return overlay;
}
public String getTaskName()
{
return taskName;
}
void setTaskName(String taskName)
{
this.taskName = taskName;
}
public int getAmount()
{
return amount;
}
void setAmount(int amount)
{
this.amount = amount;
}
public int getStreak()
{
return streak;
}
void setStreak(int streak)
{
this.streak = streak;
}
public int getPoints()
{
return points;
}
void setPoints(int points)
{
this.points = points;
}
//Utils
private String capsString(String str)
{
return str.substring(0, 1).toUpperCase() + str.substring(1);
}
}

View File

@@ -0,0 +1,139 @@
/*
* Copyright (c) 2017, Seth <Sethtroll3@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.slayer;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup(
keyName = "slayer",
name = "Slayer",
description = "Configuration for the slayer plugin"
)
public interface SlayerConfig
{
@ConfigItem(
keyName = "enabled",
name = "Enable",
description = "Configures whether slayer plugin is enabled"
)
default boolean enabled()
{
return true;
}
@ConfigItem(
keyName = "infobox",
name = "Task InfoBox",
description = "Display task information in an InfoBox"
)
default boolean showInfobox()
{
return true;
}
@ConfigItem(
keyName = "itemoverlay",
name = "Count on Items",
description = "Display task count remaining on slayer items"
)
default boolean showItemOverlay()
{
return true;
}
// Stored data
@ConfigItem(
keyName = "taskName",
name = "",
description = "",
hidden = true
)
default String taskName()
{
return "";
}
@ConfigItem(
keyName = "taskName",
name = "",
description = ""
)
void taskName(String key);
@ConfigItem(
keyName = "amount",
name = "",
description = "",
hidden = true
)
default int amount()
{
return -1;
}
@ConfigItem(
keyName = "amount",
name = "",
description = ""
)
void amount(int amt);
@ConfigItem(
keyName = "streak",
name = "",
description = "",
hidden = true
)
default int streak()
{
return -1;
}
@ConfigItem(
keyName = "streak",
name = "",
description = ""
)
void streak(int streak);
@ConfigItem(
keyName = "points",
name = "",
description = "",
hidden = true
)
default int points()
{
return -1;
}
@ConfigItem(
keyName = "points",
name = "",
description = ""
)
void points(int points);
}

View File

@@ -0,0 +1,157 @@
/*
* Copyright (c) 2017, Seth <Sethtroll3@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.slayer;
import com.google.common.collect.ImmutableList;
import static com.google.common.collect.ObjectArrays.concat;
import com.google.common.collect.Sets;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.util.Collection;
import java.util.Set;
import net.runelite.api.Client;
import net.runelite.api.GameState;
import net.runelite.api.ItemID;
import net.runelite.api.Query;
import net.runelite.api.queries.EquipmentItemQuery;
import net.runelite.api.queries.InventoryItemQuery;
import net.runelite.api.widgets.WidgetInfo;
import net.runelite.api.widgets.WidgetItem;
import net.runelite.client.RuneLite;
import net.runelite.client.ui.FontManager;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayPosition;
class SlayerOverlay extends Overlay
{
private final RuneLite runelite = RuneLite.getRunelite();
private final Client client = RuneLite.getClient();
private final SlayerConfig config;
private final Slayer plugin;
private final Font font = FontManager.getRunescapeSmallFont().deriveFont(Font.PLAIN, 16);
private final Set<Integer> slayerJewelry = Sets.newHashSet(
ItemID.SLAYER_RING_1,
ItemID.SLAYER_RING_2,
ItemID.SLAYER_RING_3,
ItemID.SLAYER_RING_4,
ItemID.SLAYER_RING_5,
ItemID.SLAYER_RING_6,
ItemID.SLAYER_RING_7,
ItemID.SLAYER_RING_8
);
private final Set<Integer> slayerEquipment = Sets.newHashSet(
ItemID.SLAYER_HELMET,
ItemID.SLAYER_HELMET_I,
ItemID.BLACK_SLAYER_HELMET,
ItemID.BLACK_SLAYER_HELMET_I,
ItemID.GREEN_SLAYER_HELMET,
ItemID.GREEN_SLAYER_HELMET_I,
ItemID.PURPLE_SLAYER_HELMET,
ItemID.PURPLE_SLAYER_HELMET_I,
ItemID.RED_SLAYER_HELMET,
ItemID.RED_SLAYER_HELMET_I,
ItemID.SLAYER_RING_ETERNAL,
ItemID.ENCHANTED_GEM,
ItemID.ETERNAL_GEM
);
SlayerOverlay(Slayer plugin)
{
super(OverlayPosition.DYNAMIC);
this.plugin = plugin;
this.config = plugin.getConfig();
}
@Override
public Dimension render(Graphics2D graphics)
{
if (client.getGameState() != GameState.LOGGED_IN
|| !config.enabled()
|| client.getWidget(WidgetInfo.LOGIN_CLICK_TO_PLAY_SCREEN) != null)
{
return null;
}
if (!config.showItemOverlay())
{
return null;
}
int amount = plugin.getAmount();
if (amount <= 0)
{
return null;
}
graphics.setFont(font);
for (WidgetItem item : getSlayerWidgetItems())
{
int itemId = item.getId();
if (!slayerEquipment.contains(itemId) && !slayerJewelry.contains(itemId))
{
continue;
}
renderWidgetText(graphics, itemId, item.getCanvasBounds(), amount, Color.white);
}
return null;
}
private Collection<WidgetItem> getSlayerWidgetItems()
{
Query inventoryQuery = new InventoryItemQuery();
WidgetItem[] inventoryWidgetItems = runelite.runQuery(inventoryQuery);
Query equipmentQuery = new EquipmentItemQuery().slotEquals(WidgetInfo.EQUIPMENT_HELMET, WidgetInfo.EQUIPMENT_RING);
WidgetItem[] equipmentWidgetItems = runelite.runQuery(equipmentQuery);
WidgetItem[] items = concat(inventoryWidgetItems, equipmentWidgetItems, WidgetItem.class);
return ImmutableList.copyOf(items);
}
private void renderWidgetText(Graphics2D graphics, int itemId, Rectangle bounds, int amount, Color color)
{
FontMetrics fm = graphics.getFontMetrics();
int textX = (int) bounds.getX();
int textY = (int) bounds.getY() + (slayerJewelry.contains(itemId) ? (int) bounds.getHeight() : fm.getHeight());
//text shadow
graphics.setColor(Color.BLACK);
graphics.drawString(String.valueOf(amount), textX + 1, textY + 1);
graphics.setColor(color);
graphics.drawString(String.valueOf(amount), textX, textY);
}
}

View File

@@ -0,0 +1,176 @@
/*
* Copyright (c) 2017, Tyler <https://github.com/tylerthardy>
* 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.slayer;
import net.runelite.api.ItemID;
import net.runelite.client.game.ItemManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.awt.image.BufferedImage;
import java.util.HashMap;
import java.util.Map;
enum Task
{
//<editor-fold desc="Enums">
ABERRANT_SPECTRES("aberrant spectres", ItemID.ABERRANT_SPECTRE),
ABYSSAL_DEMONS("abyssal demons", ItemID.ABYSSAL_DEMON),
ANKOU("ankou", ItemID.ANKOU_MASK),
AVIANSIES("aviansies", ItemID.ENSOULED_AVIANSIE_HEAD),
BANSHEES("banshees", ItemID.BANSHEE),
BASILISKS("basilisks", ItemID.BASILISK),
BATS("bats", ItemID.GIRAL_BAT_2),
BEARS("bears", ItemID.ENSOULED_BEAR_HEAD),
BIRDS("birds", ItemID.FEATHER),
BLACK_DEMONS("black demons", ItemID.BLACK_DEMON_MASK),
BLACK_DRAGONS("black dragons", ItemID.BLACK_DRAGON_MASK),
BLOODVELD("bloodveld", ItemID.BLOODVELD),
BLUE_DRAGONS("blue dragons", ItemID.BLUE_DRAGON_MASK),
BOSSES("bosses", -1),
BRINE_RATS("brine rats", ItemID.BRINE_RAT),
BRONZE_DRAGONS("bronze dragons", ItemID.BRONZE_DRAGON_MASK),
CATABLEPON("catablepon", ItemID.LEFT_SKULL_HALF),
CAVE_BUGS("cave bugs", ItemID.SWAMP_CAVE_BUG),
CAVE_CRAWLERS("cave crawlers", ItemID.CAVE_CRAWLER),
CAVE_HORRORS("cave horrors", ItemID.CAVE_HORROR),
CAVE_KRAKEN("cave kraken", ItemID.CAVE_KRAKEN),
CAVE_SLIMES("cave slimes", ItemID.SWAMP_CAVE_SLIME),
COCKATRICE("cockatrice", ItemID.COCKATRICE),
COWS("cows", ItemID.COW_MASK),
CRAWLING_HANDS("crawling hands", ItemID.CRAWLING_HAND),
CROCODILES("crocodiles", ItemID.SWAMP_LIZARD),
DAGANNOTH("dagannoth", ItemID.DAGANNOTH),
DARK_BEASTS("dark beasts", ItemID.DARK_BEAST),
DESERT_LIZARDS("desert lizards", ItemID.DESERT_LIZARD),
DOGS("dogs", ItemID.GUARD_DOG),
DUST_DEVILS("dust devils", ItemID.DUST_DEVIL),
DWARVES("dwarves", ItemID.DWARVEN_HELMET),
EARTH_WARRIORS("earth warriors", ItemID.BRONZE_FULL_HELM_T),
ELVES("elves", ItemID.ELF),
FEVER_SPIDERS("fever spiders", ItemID.FEVER_SPIDER),
FIRE_GIANTS("fire giants", -1),
FLESHCRAWLERS("fleshcrawlers", -1),
GARGOYLES("gargoyles", ItemID.GARGOYLE),
GHOSTS("ghosts", -1),
GHOULS("ghouls", -1),
GOBLINS("goblins", ItemID.ENSOULED_GOBLIN_HEAD),
GREATER_DEMONS("greater demons", ItemID.GREATER_DEMON_MASK),
GREEN_DRAGONS("green dragons", ItemID.GREEN_DRAGON_MASK),
HARPIE_BUG_SWARMS("harpie bug swarms", ItemID.SWARM),
HELLHOUNDS("hellhounds", ItemID.HELLHOUND),
HILL_GIANTS("hill giants", ItemID.ENSOULED_GIANT_HEAD),
HOBGOBLINS("hobgoblins", ItemID.HOBGOBLIN_GUARD),
ICE_GIANTS("ice giants", -1),
ICE_WARRIORS("ice warriors", ItemID.MITHRIL_FULL_HELM_T),
ICEFIENDS("icefiends", -1),
INFERNAL_MAGES("infernal mages", ItemID.INFERNAL_MAGE),
IRON_DRAGONS("iron dragons", ItemID.IRON_DRAGON_MASK),
JELLIES("jellies", ItemID.JELLY),
JUNGLE_HORRORS("jungle horrors", -1),
KALPHITE("kalphite", ItemID.KALPHITE_SOLDIER),
KILLERWATTS("killerwatts", ItemID.KILLERWATT),
KURASK("kurask", ItemID.KURASK),
LESSER_DEMONS("lesser demons", ItemID.LESSER_DEMON_MASK),
LIZARDMEN("lizardmen", ItemID.LIZARDMAN_FANG),
MINIONS_OF_SCABARAS("minions of scabaras", ItemID.GOLDEN_SCARAB),
MINOTAURS("minotaurs", ItemID.ENSOULED_MINOTAUR_HEAD),
MITHRIL_DRAGONS("mithril dragons", ItemID.MITHRIL_DRAGON_MASK),
MOGRES("mogres", ItemID.MOGRE),
MOLANISKS("molanisks", ItemID.MOLANISK),
MONKEYS("monkeys", ItemID.ENSOULED_MONKEY_HEAD),
MOSS_GIANTS("moss giants", -1),
MUTATED_ZYGOMITES("mutated zygomites", ItemID.MUTATED_ZYGOMITE),
NECHRYAEL("nechryael", ItemID.NECHRYAEL),
OGRES("ogres", ItemID.ENSOULED_OGRE_HEAD),
OTHERWORLDLY_BEING("otherworldly being", ItemID.GHOSTLY_HOOD),
PYREFIENDS("pyrefiends", ItemID.PYREFIEND),
RATS("rats", ItemID.RATS_TAIL),
RED_DRAGONS("red dragons", ItemID.BABY_RED_DRAGON),
ROCKSLUGS("rockslugs", ItemID.ROCKSLUG),
SCORPIONS("scorpions", -1),
SEA_SNAKES("sea snakes", ItemID.SNAKE_CORPSE),
SHADES("shades", ItemID.SHADE_ROBE_TOP),
SHADOW_WARRIORS("shadow warriors", -1),
SKELETAL_WYVERNS("skeletal wyverns", ItemID.SKELETAL_WYVERN),
SKELETONS("skeletons", ItemID.SKELETON_GUARD),
SMOKE_DEVILS("smoke devils", ItemID.SMOKE_DEVIL),
SPIDERS("spiders", ItemID.HUGE_SPIDER),
SPIRITUAL_CREATURES("spiritual creatures", -1),
STEEL_DRAGONS("steel dragons", ItemID.STEEL_DRAGON),
SUQAHS("suqahs", ItemID.SUQAH_TOOTH),
TERROR_DOGS("terror dogs", ItemID.TERROR_DOG),
TROLLS("trolls", ItemID.TROLL_GUARD),
TUROTH("turoth", ItemID.TUROTH),
TZHAAR("tzhaar", ItemID.ENSOULED_TZHAAR_HEAD),
VAMPIRES("vampires", ItemID.STAKE),
WALL_BEASTS("wall beasts", ItemID.SWAMP_WALLBEAST),
WATERFIENDS("waterfiends", -1),
WEREWOLVES("werewolves", ItemID.WOLFBANE),
WOLVES("wolves", ItemID.GREY_WOLF_FUR),
ZOMBIES("zombies", ItemID.ZOMBIE_HEAD);
//</editor-fold>
private static final Logger logger = LoggerFactory.getLogger(Task.class);
private static final Map<String, Task> tasks = new HashMap<>();
private final String name;
private final int itemSpriteId;
static
{
for (Task task : values())
{
tasks.put(task.getName(), task);
}
}
Task(String name, int itemSpriteId)
{
this.name = name;
this.itemSpriteId = itemSpriteId;
}
public static Task getTask(String taskName)
{
return tasks.get(taskName);
}
public String getName()
{
return this.name;
}
public BufferedImage getImage()
{
if (itemSpriteId == -1)
{
return ItemManager.getImage(ItemID.ENCHANTED_GEM);
}
return ItemManager.getImage(itemSpriteId);
}
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright (c) 2017, Tyler <https://github.com/tylerthardy>
* 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.slayer;
import net.runelite.client.ui.overlay.infobox.Counter;
import java.awt.image.BufferedImage;
public class TaskCounter extends Counter
{
public TaskCounter(BufferedImage img, int amount)
{
super(img, String.valueOf(amount));
}
}

View File

@@ -0,0 +1,127 @@
/*
* Copyright (c) 2017, 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.slayer;
import static net.runelite.api.ChatMessageType.SERVER;
import net.runelite.client.RuneLite;
import net.runelite.client.events.ChatMessage;
import static org.junit.Assert.assertEquals;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.mockito.Answers.RETURNS_DEEP_STUBS;
import org.mockito.Matchers;
import org.mockito.Mock;
import static org.mockito.Mockito.when;
import org.mockito.runners.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class SlayerTest
{
private static final String TASK_ONE = "You've completed one task; return to a Slayer master.";
private static final String TASK_COMPLETE_NO_POINTS = "<col=ef1020>You've completed 3 tasks; return to a Slayer master.</col>";
private static final String TASK_POINTS = "You've completed 9 tasks and received 0 points, giving you a total of 18,000; return to a Slayer master.";
private static final String TASK_COMPLETE = "You need something new to hunt.";
private static final String TASK_CANCELED = "Your task has been cancelled.";
@Mock(answer = RETURNS_DEEP_STUBS)
private RuneLite runeLite;
@Mock
private SlayerConfig slayerConfig;
private Slayer slayerPlugin;
@Before
public void before()
{
RuneLite.setRunelite(runeLite);
when(runeLite.getConfigManager().getConfig(Matchers.any(Class.class))).thenReturn(slayerConfig);
when(slayerConfig.enabled()).thenReturn(true);
slayerPlugin = new Slayer();
}
@Test
public void testOneTask()
{
ChatMessage chatMessageEvent = new ChatMessage(SERVER, "Perterter", TASK_ONE, null);
slayerPlugin.onChatMessage(chatMessageEvent);
assertEquals(1, slayerPlugin.getStreak());
assertEquals("", slayerPlugin.getTaskName());
assertEquals(0, slayerPlugin.getAmount());
}
@Test
public void testNoPoints()
{
ChatMessage chatMessageEvent = new ChatMessage(SERVER, "Perterter", TASK_COMPLETE_NO_POINTS, null);
slayerPlugin.onChatMessage(chatMessageEvent);
assertEquals(3, slayerPlugin.getStreak());
assertEquals("", slayerPlugin.getTaskName());
assertEquals(0, slayerPlugin.getAmount());
}
@Test
public void testPoints()
{
ChatMessage chatMessageEvent = new ChatMessage(SERVER, "Perterter", TASK_POINTS, null);
slayerPlugin.onChatMessage(chatMessageEvent);
assertEquals(9, slayerPlugin.getStreak());
assertEquals("", slayerPlugin.getTaskName());
assertEquals(0, slayerPlugin.getAmount());
assertEquals(18_000, slayerPlugin.getPoints());
}
@Test
public void testComplete()
{
slayerPlugin.setTaskName("cows");
slayerPlugin.setAmount(42);
ChatMessage chatMessageEvent = new ChatMessage(SERVER, "Perterter", TASK_COMPLETE, null);
slayerPlugin.onChatMessage(chatMessageEvent);
assertEquals("", slayerPlugin.getTaskName());
assertEquals(0, slayerPlugin.getAmount());
}
@Test
public void testCancelled()
{
slayerPlugin.setTaskName("cows");
slayerPlugin.setAmount(42);
ChatMessage chatMessageEvent = new ChatMessage(SERVER, "Perterter", TASK_CANCELED, null);
slayerPlugin.onChatMessage(chatMessageEvent);
assertEquals("", slayerPlugin.getTaskName());
assertEquals(0, slayerPlugin.getAmount());
}
}